#Translating template fragments

44 messages · Page 1 of 1 (latest)

main raptor
#

The question has risen recently of the absence in Angular (even among known third-party modules) of a way to substitute, for translation purposes, a piece of DOM in a templace with another - with a potentially slightly different structure.

Use case :

// original (english)
<p>I do <b class="angry">not</b> want that.</p>

// translation (french)
<p>Je <b class="angry">ne</b> veux <b class="angry">pas</b> ça.</p>
// notice how there are two <b> now

In my experience (translating dialogue-heavy video games), it is necessary to have flexibility when it comes to structure, when translating, whether you're considering a document-style script like HTML, or a sequential imperative script like in video games.

#

A solution I could envision would be:

  • for each node to translate, someTranslationAttr="node_id" is added (the node being the enclosing <p> in the exampld above, or a <ng-container> for instance). The id would need to be unique across the angular project.
  • In some place or other, html files are created, containing sections like the following:
<translate-block node_id="thenodeid" language="zz_ZZ">
    Hmmm, the translation !
</>
  • at build time, an Angular component (or some lightweight equivalent) is created from each translate-block node, with the node's content as its template.
  • the selector of the proto-component is something like [someTranslationAttr=thenodeid]
  • the component has an input for each variable used in interpolation in the template
  • the selection of the language happens at routing/resolver time at the very latest. Only the "translation proto-components" of that language are loaded.
  • when building the template to a DOM, the translation proto-components trigger, and replace the contents of the nodes with directives and for which a translation is matched.
  • by derogation to normal component behavior, the style of the actual element applies to the template of the proto-element
  • hot-switching without a reload or at the very least a router pass is not supported

Ignoring, for now, the question of who would implement all that, would this design sound semi-sane ? Are there technical impossibilities that come to mind ?

#

@lapis mountain @rose forge if you're interested in following this train of thought

acoustic igloo
#

I don't see any problems with existing libs. We use transloco for translating formatted text. innerHTML + sanitize

lapis mountain
#

I think while your solution could work I think it is way more trouble than its worth. "Compiler magic" is a lot of work.
I would go with what Yehor said or, if you really don't want HTML, some other markup-like structure in Transloco strings (e.g. [b]this is bold[/b]).

Pragmatism is sometimes the answer 😄

main raptor
main raptor
#

I don't think it's that magic, I mean the only special things are 1) the style thing near the end, 2) the creation of the components from a non-traditional syntax, especially the input creation. Otherwise the syntax in the host component is standard.

lapis mountain
#

And why not go with what Isofruit suggested and do a @switch?

main raptor
#

I forgot that one

#

well, it would bloat the template file if you have too many languages

#

but for few, it's probably workable

#

and standard practice as far as I know is not letting your translators work on your base files, though "everybody does that" is not the most compelling reason

lapis mountain
#

I must say that I have just never seen this kind of feature in any translation tool

main raptor
#

Well, you should look at Ren'Py

lapis mountain
#

Can you link me the docs?

main raptor
#

and I can believe that other web framework make do with string translations, but other web frameworks don't have templates

lapis mountain
#

but other web frameworks don't have templates
Sorry, what? 😂

lapis mountain
#

Where exactly there does it show changing the equivalent of what would be the HTML structure?

main raptor
lapis mountain
main raptor
lapis mountain
#

Okay, so the equivalent would be using innerHTML. You can do arbitrary HTML with no constraint 🙂

main raptor
main raptor
lapis mountain
#

Looking at the first result for "react i18n", they do support something like this, but it is really just fancy syntax for innerHTML

lapis mountain
#

And I don't know of anything where it does exist.

#

At least on the web.

main raptor
lapis mountain
main raptor
# lapis mountain And I don't know of anything where it does exist.

I understand, what I'm saying is that I think it's the direction things should be heading, after having used it elsewhere. Especially in a framework that parses and checks HTML fragments before converting them to DOM - notwithstanding the fact that other framework which do the same could benefit from it as well.

main raptor
#

though there seem to be strong constraints on what you can put in the HTML fragment

#

not as strong as in angular's i18n still

acoustic igloo
# main raptor you don't see any problem with storing HTML in JSON files ? with having your ori...

Let me explain my point. I do SPA, I don't care about SEO, so I'm good with missing original text in templates and runtime translation. If I need text on my page at load time, I would use i18n to build copies of my app for each language.
And ng templates are skeletons for your dynamic content. In this case, translations are dynamic content. So I'm good with storing dynamic content in translation files (plain text or HTML fragments)

main raptor
acoustic igloo
#

"Also, can you use interpolation in your translation fragments ?"
Yes

main raptor
#

how do you handle having both html markup and interpolation in your translated bits ?

acoustic igloo
#

Once again, markup is just a string Hello <b>{{ name}}</b>
I just pass transloco results to innerHTML with sanitize

#

If you are concerned about translators' markup errors, probably you should think about some tool for translators to validate json files (in case of transloco). I don't know such tools. I didn't have such problem.

main raptor
#

So, it took me ages to actually implement it, but I finally made a system work with that, more specifically a directive that replaces innerHTML depending on the translation key it is passed.
I didn't use transloco because its syntax seemed overkill for my simple test, and given the issue I ran into, I don't see how it would change anything.

The issue is that when I innerHTML-translate a div containing a <p>, some <i>, and some inline <img>, it just crushes the style that's supposed to apply to all of those, since the _ngcontent-ng-c0000000000 attributes on which angular styling relies, are all missing.
So, that's a dead end for me.