diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b8babbb..4356b2d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -62,7 +62,8 @@ jobs:
           release/latest.yml
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    - name: test launch
-      run: npm test
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    # - name: test launch
+    #   run: npm test
+    #   env:
+    #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    ## spectron does not support Electron 15 yet
diff --git a/build.js b/build.js
index b6e0a50..9d909eb 100644
--- a/build.js
+++ b/build.js
@@ -24,9 +24,7 @@ async function copyFiles() {
 
 async function patchFiles() {
   await fs.copy('patch/underscore-package.json', path.join(__dirname, "node_modules/nomnom/node_modules/underscore/package.json"));
-  // issue#49 https://github.com/sakazuki/node-red-desktop/issues/49
-  // await fs.copy('patch/i18n.js', path.join(__dirname, "node_modules/@node-red/util/lib/i18n.js"));
-  return ['nomnom/*/underscore/package.json', '@node-red/util/lib/i18.js'];
+  return ['nomnom/*/underscore/package.json'];
 }
 
 async function build() {
diff --git a/patch/i18n.js b/patch/i18n.js
deleted file mode 100644
index ef472c6..0000000
--- a/patch/i18n.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @ignore
- **/
-
-/**
- * Internationalization utilities
- * @mixin @node-red/util_i18n
- */
-
-var i18n = require("i18next");
-
-var path = require("path");
-var fs = require("fs");
-
-var defaultLang = "en-US";
-
-var resourceMap = {};
-var resourceCache = {};
-var initPromise;
-
-/**
- * Register multiple message catalogs with i18n.
- * @memberof @node-red/util_i18n
- */
-function registerMessageCatalogs(catalogs) {
-    var promises = catalogs.map(function(catalog) {
-        return registerMessageCatalog(catalog.namespace,catalog.dir,catalog.file).catch(err => {});
-    });
-    return Promise.all(promises);
-}
-
-/**
- * Register a message catalog with i18n.
- * @memberof @node-red/util_i18n
- */
-async function registerMessageCatalog(namespace,dir,file) {
-    return initPromise.then(function() {
-        return new Promise((resolve,reject) => {
-            resourceMap[namespace] = { basedir:dir, file:file, lngs: []};
-            fs.readdir(dir,function(err, files) {
-                if (err) {
-                    resolve();
-                } else {
-                    files.forEach(function(f) {
-                        if (fs.existsSync(path.join(dir,f,file))) {
-                            resourceMap[namespace].lngs.push(f);
-                        }
-                    });
-                    i18n.loadNamespaces(namespace,function() {
-                        resolve();
-                    });
-                }
-            })
-        });
-    });
-}
-
-function mergeCatalog(fallback,catalog) {
-    for (var k in fallback) {
-        if (fallback.hasOwnProperty(k)) {
-            if (!catalog[k]) {
-                catalog[k] = fallback[k];
-            } else if (typeof fallback[k] === 'object') {
-                mergeCatalog(fallback[k],catalog[k]);
-            }
-        }
-    }
-}
-
-
-async function readFile(lng, ns) {
-    if (/[^a-z\-]/i.test(lng)) {
-        throw new Error("Invalid language: "+lng)
-    }
-    if (resourceCache[ns] && resourceCache[ns][lng]) {
-        return resourceCache[ns][lng];
-    } else if (resourceMap[ns]) {
-        const file = path.join(resourceMap[ns].basedir, lng, resourceMap[ns].file);
-        const content = await fs.promises.readFile(file, "utf8");
-        resourceCache[ns] = resourceCache[ns] || {};
-        resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, ''));
-        var baseLng = lng.split('-')[0];
-        if (baseLng !== lng && resourceCache[ns][baseLng]) {
-            mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]);
-        }
-        if (lng !== defaultLang) {
-            mergeCatalog(resourceCache[ns][defaultLang], resourceCache[ns][lng]);
-        }
-        return resourceCache[ns][lng];
-    } else {
-        throw new Error("Unrecognised namespace");
-    }
-}
-
-var MessageFileLoader = {
-    type: "backend",
-    init: function (services, backendOptions, i18nextOptions) { },
-    read: function (lng, ns, callback) {
-        readFile(lng, ns)
-            .then(data => callback(null, data))
-            .catch(err => {
-                if (/-/.test(lng)) {
-                    // if reading language file fails -> try reading base language (e. g. 'fr' instead of 'fr-FR' or 'de' for 'de-DE')
-                    var baseLng = lng.split('-')[0];
-                    readFile(baseLng, ns).then(baseData => callback(null, baseData)).catch(err => callback(err));
-                } else {
-                    callback(err);
-                }
-            });
-    }
-}
-
-function getCurrentLocale() {
-    var env = process.env;
-    for (var name of ['LC_ALL', 'LC_MESSAGES', 'LANG']) {
-        if (name in env) {
-            var val = env[name];
-            return val.substring(0, 2);
-        }
-    }
-    return undefined;
-}
-
-function init(settings) {
-    if (!initPromise) {
-        // Keep this as a 'when' promise as top-level red.js uses 'otherwise'
-        // and embedded users of NR may have copied that.
-        initPromise = new Promise((resolve,reject) => {
-            i18n.use(MessageFileLoader);
-            var opt = {
-                // debug: true,
-                defaultNS: "runtime",
-                ns: [],
-                fallbackLng: defaultLang,
-                interpolation: {
-                    unescapeSuffix: 'HTML',
-                    escapeValue: false,
-                    prefix: '__',
-                    suffix: '__'
-                }
-            };
-            var lang = settings.lang || getCurrentLocale();
-            if (lang) {
-                opt.lng = lang;
-            }
-            i18n.init(opt ,function() {
-                resolve();
-            });
-        });
-    }
-}
-
-
-/**
- * Gets a message catalog.
- * @name catalog
- * @function
- * @memberof @node-red/util_i18n
- */
-function getCatalog(namespace,lang) {
-    var result = null;
-    lang = lang || defaultLang;
-    if (/[^a-z\-]/i.test(lang)) {
-        throw new Error("Invalid language: "+lng)
-    }
-
-    if (resourceCache.hasOwnProperty(namespace)) {
-        result = resourceCache[namespace][lang];
-        if (!result) {
-            var langParts = lang.split("-");
-            if (langParts.length == 2) {
-                result = resourceCache[namespace][langParts[0]];
-            }
-        }
-    }
-    return result;
-}
-
-/**
- * Gets a list of languages a given catalog is available in.
- * @name availableLanguages
- * @function
- * @memberof @node-red/util_i18n
- */
-function availableLanguages(namespace) {
-    if (resourceMap.hasOwnProperty(namespace)) {
-        return resourceMap[namespace].lngs
-    }
-}
-
-var obj = module.exports = {
-    init: init,
-    registerMessageCatalog: registerMessageCatalog,
-    registerMessageCatalogs: registerMessageCatalogs,
-    catalog: getCatalog,
-    availableLanguages: availableLanguages,
-    /**
-     * The underlying i18n library for when direct access is really needed
-     */
-    i: i18n,
-    /**
-     * The default language of the runtime
-     */
-    defaultLang: defaultLang
-}
-
-/**
- * Perform a message catalog lookup.
- * @name _
- * @function
- * @memberof @node-red/util_i18n
- */
-obj['_'] = function() {
-    //var opts = {};
-    //if (def) {
-    //    opts.defaultValue = def;
-    //}
-    //console.log(arguments);
-    var res = i18n.t.apply(i18n,arguments);
-    return res;
-}