Issue #2674Opened March 20, 2020by teawithfruit1 reactions

[QUESTIONS] i18n content integration

Question

Hello,

I'm working on an integration of my localization system (i18n) with grapes.js. The idea is to have a data field, which will hold the i18n string.

<div class="content" data-i18n="common:localize.string"></div>

If the data attribute is set, grapes.js will take the string and make it visible in a settings field. If the settings field is altered, the data attribute is also altered and also the content inside the canvas. If the settings field is cleared, the data attribute will be deleted.

If the file is saved, the attributes will be included. When using the file in production, a little script is searching for the data-i18n attribute to set the text inside the element in the right language.

Now I got some problems with the implementation.

  1. If I edit the settings field, the content in the canvas is set right but in the "View code" and the saved file not. It seems that the text is appended and not replaced. Is component.components('Insert text here...') the right way to replace content inside a component? (jsfiddle line 29) You can emulate a valid i18n string by using i18nString in the settings field.
  2. I would like to integrate the script in the component. Now I got a problem while using async functions. Is it possible to use async functions inside a component script? (jsfiddle line 57)
  3. What is the best way to update the canvas content? I'm pending between line 27 and line 61. Both in the jsfiddle.
  4. If I alter the settings field, the typographic settings are reseted. Is it possible to prevent that?
  5. I've read the documentation and the api docs. But I'm not sure if the way I created the component is the best way. Can you give me a feedback about that?

You can check my points by adding the "Content" Block to the canvas and altering the i18n field in settings. Here is the jsfiddle link. https://jsfiddle.net/bool/gfbdyLup/6/

Thank you for this great library and your help!

Answers (3)

artfApril 1, 20201 reactions

@teawithfruit if you expect something in your saved HTML page (outside of the GrapesJS editor) the only thing I see it can do is:

script: function() {
	console.log('script done!')
}

So it does nothing, probably you're another victim of thinking that scripts inside GrapesJS editor will work in the exported code (but the final HTML has nothing to do with the editor). A bit more detailed explanation here

pouyamiralayiMarch 21, 20200 reactions

Hi @teawithfruit there are a couple of issues with your code:

  1. you don't have access to this as the model inside component script: Component & Js docs
  2. if your use case is to control an attribute, you don't have to provide a custom trait for that; just define a regular trait, and add listeners for the changes upon that attribute:
model: {
            init() {
                this.on('change:attributes:data-i18n', this.handleTypeChange);
            },

            handleTypeChange() {
                console.log('Input changed to: ', this.getAttributes()['data-i18n']);
            },
            defaults: {
                attributes:{
                  'data-i18n':''
                },
                traits: [
                    {
                        name: 'data-i18n',
                        label:'i18n!'
                    }
                ],
            //....

Cheers!

teawithfruitMarch 23, 20200 reactions

Thank you for the very helpful the answer! This is my updated Block/Component. Right now I've got just one more problem.

The script function I've added to the component is not called in the saved html page. If I add the block to the canvas in the editor, the function is called, but not if I save the page and open it outside grapes.js. If I look into the elements inspector, the script tag is visible but not being called.

Is there something I'm doing wrong?

editor.DomComponents.addType('content', {
  isComponent: el => el.classList && el.classList.contains('content'),
  extend: 'text',
  model: {
    async init() {
      const key = this.getAttributes()['data-i18n']

      if(key && await Localize.exists(key) == true) {
        this.set('content', await Localize.get(key))
      }
      
      this.on('change:attributes:data-i18n', this.handleTypeChange)
    },
    async handleTypeChange() {
      const key = this.getAttributes()['data-i18n']
      
      if(key && await Localize.exists(key) == true) {
        this.set('content', await Localize.get(key))
      } else {
        let attributes = this.getAttributes()

        if(attributes['data-i18n'] != undefined) {
          delete attributes['data-i18n']
          this.setAttributes(attributes)
        }
      }
    },
    defaults: {
      traits: [
        {
          name: 'data-i18n',
          label: 'i18n'
        }
      ],
      script: function() {
        console.log('script done!')
      }
    }
  }
})

editor.BlockManager.add('add-content', {
  label: 'Content',
  category: 'Elements',
  type: 'content',
  content: `<div class="content">Insert text here...</div>`
})

Thank's again for your help!

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.