node-blockly icon indicating copy to clipboard operation
node-blockly copied to clipboard

Blocks do not always translate

Open NAllred91 opened this issue 7 years ago • 5 comments

You can reproduce this in your live demo, http://mo4islona.github.io/blockly/

First, load the page and change the language to french. Open the the Loops flyout to see that the while block has been translated to french. Then close the flyout and translate back to english. Check the Loops flyout again and still see french in the While block.

It seems like these blocks are getting stuck on whatever language they are set to when you first look at them.

NAllred91 avatar Oct 17 '17 20:10 NAllred91

I've got a hacky way I think I can fix this in my own fork of node-blockly. I'm not sure how what the correct way to fix this is yet.

NAllred91 avatar Oct 17 '17 21:10 NAllred91

I know about this problem and think the problem is inside Blockly. Some blocks translates back correctly some not. For example Test translates correctly in english after french.

They fixed some blocks – in earlier versions of Blockly no one blocks translated back.

mo4islona avatar Oct 18 '17 10:10 mo4islona

Ah yea... At first I thought it was only drop downs but now I see its all pretty random. I'll take a look at blockly at some point and see if I can do a PR there.

For the time being I'm working around this in my application by creating a blocklyStore.js:

module.exports = {
    Blockly: require('node-blockly/browser'),
    reset: function() {
        delete require.cache[require.resolve('node-blockly/browser')]
        delete require.cache[require.resolve('node-blockly/lib/blockly_compressed_browser')]
        delete require.cache[require.resolve('node-blockly/lib/blocks_compressed_browser')]
        this.Blockly = require('node-blockly/browser')
    },
}

Then to use Blockly I do:

var BS = require('blocklyStore')

BS.Blockly.inject(...

Then whenever I change languages I call BS.reset().

This seems to work fine as a work around for now.

NAllred91 avatar Oct 18 '17 11:10 NAllred91

Turns out my work around wasn't quite enough...

This line causes problems.. https://github.com/mo4islona/node-blockly/blob/master/browser.js#L12

Since setLocale is always called initially with english, so even when you clear the require cache it still gets called with english from the start and that messes up some blocks.

I'm not sure if my current solution is good enough for a PR, but I changed browser.js to this

var getBlockly = function(languageCode) {
  delete require.cache[require.resolve('node-blockly/lib/blockly_compressed_browser')]
  delete require.cache[require.resolve('node-blockly/lib/blocks_compressed_browser')]
  var Blockly = require('./lib/blockly_compressed_browser');

  Blockly._setLocale = function(locale) {
    Blockly.Msg = Object.assign(locale, Blockly.Msg);
    Blockly.Msg = Blockly.Msg();
  }

  Blockly.utils.getMessageArray_ = function () {
    return Blockly.Msg
  }

  Blockly._setLocale(require('./lib/i18n/' + languageCode))

  Blockly.Blocks = Object.assign(Blockly.Blocks, require('./lib/blocks_compressed_browser')(Blockly));

  Blockly.JavaScript = require('./lib/javascript_compressed')(Blockly);
  Blockly.Lua = require('./lib/lua_compressed')(Blockly);
  Blockly.Dart = require('./lib/dart_compressed')(Blockly);
  Blockly.PHP = require('./lib/php_compressed')(Blockly);
  Blockly.Python = require('./lib/python_compressed')(Blockly);

  return Blockly
}

class Blockly {
  constructor() {
      Object.assign(this, getBlockly('en'))
  }

  setLanguage = (languageCode) => {
      Object.assign(this, getBlockly(languageCode))
  }
}

module.exports =  new Blockly()

Then, to change the language I do this

import Blockly from 'node-blockly/browser'

var changeLanguage = (languageCode) => {
    Blockly.setLanguage(languageCode)
    var currentXML = this._getWorkspaceXML()
    this._workspace.dispose()
    this._workspace = Blockly.inject(config.blocklyElementId, {
                toolbox: getToolbox(this._appManager),
                grid: config.blocklyGridOptions,
            })
    this._setWorkspaceXML(currentXML)
}

With this solution, Blockly._setLocale only ever gets called on a given instance of Blockly once.

NAllred91 avatar Dec 22 '17 23:12 NAllred91

But this solution is nice because I can change the language without doing the weird cache invalidation in my own code.

If I made a PR using this pattern and cleaned it up some keeping Blockly.setLocale as the public method, I don't think it would break existing code that uses setLocale? Let me know if you're interested in a PR with this pattern.

NAllred91 avatar Dec 22 '17 23:12 NAllred91