GetmeUK / ContentTools

A JS library for building WYSIWYG editors for HTML content.
http://getcontenttools.com
MIT License
3.94k stars 393 forks source link

Dynamic change of language #546

Closed Jakuboslav closed 4 years ago

Jakuboslav commented 4 years ago

Hello, I am able to change language as mentioned in you guide. My app comunicate with editor with messages. When I sent message with data to change language, ContentEdit.LANGUAGE is changed as intended, but language stays the same. Am I missing something? Can you advice me, how to change language dynamicaly?

Thanks in advance.

anthonyjb commented 4 years ago

Hi @Jakuboslav can you post the relevant code from your project please and I'll take a look and see if I can help :)

Jakuboslav commented 4 years ago

I have something like this, issue is with setting ContentEdit.LANGUAGE in listening to message.

import cs from "../../../translations/cs.json“;

  ...

  message.listen("set-language", data => {
    console.info(ContentEdit.LANGUAGE); // prints "cs“, lang is cs, its correct
    ContentEdit.LANGUAGE = data.lang; // data.lang is "en"
    console.info(ContentEdit.LANGUAGE); // prints „en“, lang is still cs, its incorrect
  });

  ContentEdit.addTranslations("cs", cs);
  ContentEdit.LANGUAGE = "cs“; // Sets language to cs, it is correct

  ...

Thanks

anthonyjb commented 4 years ago

OK I think the the issue is that changing the ContentEdit.LANGUAGE setting wont automatically update the already rendered UI components so you'd need to force the UI to be re-rendered. You should be able to do this by calling unmount and then mount against the editor, alternatively you can destroy and init the editor.

Let me know how you get on.

Jakuboslav commented 4 years ago

Thanks for advice, I didn’t realise, it is not reactive.

Unfortunatelly, when I call unmount() and mount() against editor, it ends up with error Uncaught TypeError: Cannot read property 'tools' of null. Which leads me here:

  FIXTURE_TOOLS = [["undo", "redo", "remove"]];
  IMAGE_FIXTURE_TOOLS = [["undo", "redo", "image"]];
  LINK_FIXTURE_TOOLS = [["undo", "redo", "link", "bold", "italic"]];
  ContentEdit.Root.get().bind("focus", function(element) {
    var tools;
    if (element.isFixed()) {
      if (element.type() === "ImageFixture") {
        tools = IMAGE_FIXTURE_TOOLS;
      } else if (element.tagName() === "a") {
        tools = LINK_FIXTURE_TOOLS;
      } else {
        tools = FIXTURE_TOOLS;
      }
    } else {
      tools = ContentTools.DEFAULT_TOOLS;
    }
    if (editor.toolbox().tools() !== tools) { // Here it seems like toolbox() is null for some reason I dont understand
      return editor.toolbox().tools(tools);
    }
  });

destoy() and init() doesn’t seem to trigger this method at all because there is no error nor toolbox.

anthonyjb commented 4 years ago

OK so if you need to do this reactively it's likely you'd need to determine what's active on the screen currently (toolbox, dialog, etc) and basically use unmount/mount for each (including applying the active widget class to each).

Since most of the time the only relevant UI component is the toolbox (as it's the only one with translated content that's mounted from the moment the editor is initialized) the following code works for me in the sandbox demo.

message.listen('set-language', data => {
  ContentEdit.LANGUAGE = 'en'
  const editor = ContentTools.EditorApp.get()

  if (editor.isEditing()) {
    const toolbox = editor.toolbox()

    if (toolbox) {
      toolbox.unmount()
      toolbox.mount()
      toolbox.addCSSClass('ct-widget--active')
    }
  }
})

Hopefully this helps you for now or at least points you in the right direction - let me know if you have further issues.

Jakuboslav commented 4 years ago

Oh, perfect, it works out of box!

Thanks a lot for your help, you saved my day.