From 9dc4e99aca7a5efb185da5527c169492a160c9b1 Mon Sep 17 00:00:00 2001 From: Ahmad Date: Fri, 23 Oct 2020 13:30:20 +0200 Subject: [PATCH 1/2] translation - the traslation feature without the changes from other branches --- package-lock.json | 670 +++++++++--------- package.json | 8 +- web/app/admin/admin.component.html | 16 +- web/app/admin/bridges/bridges.component.html | 17 +- web/app/admin/bridges/bridges.component.ts | 6 +- .../bridges/gitter/gitter.component.html | 17 +- .../admin/bridges/gitter/gitter.component.ts | 17 +- .../manage-selfhosted.component.html | 17 +- .../manage-selfhosted.component.ts | 13 +- .../add-selfhosted.component.html | 14 +- .../add-selfhosted.component.ts | 9 +- web/app/admin/bridges/irc/irc.component.html | 19 +- web/app/admin/bridges/irc/irc.component.ts | 15 +- .../irc/networks/networks.component.html | 8 +- .../irc/networks/networks.component.ts | 9 +- .../manage-selfhosted.component.html | 15 +- .../manage-selfhosted.component.ts | 13 +- .../admin/bridges/slack/slack.component.html | 17 +- .../admin/bridges/slack/slack.component.ts | 17 +- .../manage-selfhosted.component.html | 26 +- .../manage-selfhosted.component.ts | 13 +- .../bridges/telegram/telegram.component.html | 21 +- .../bridges/telegram/telegram.component.ts | 11 +- .../manage-selfhosted.component.html | 18 +- .../manage-selfhosted.component.ts | 13 +- .../bridges/webhooks/webhooks.component.html | 14 +- .../bridges/webhooks/webhooks.component.ts | 11 +- .../admin/custom-bots/add/add.component.html | 22 +- .../admin/custom-bots/add/add.component.ts | 19 +- .../custom-bots/custom-bots.component.html | 18 +- .../custom-bots/custom-bots.component.ts | 15 +- web/app/admin/home/home.component.html | 27 +- web/app/admin/home/home.component.ts | 9 +- .../logout-confirmation.component.html | 12 +- .../add-selfhosted.component.html | 17 +- .../add-selfhosted.component.ts | 10 +- .../appservice-config.component.html | 12 +- .../appservice-config.component.ts | 13 +- .../neb/config/giphy/giphy.component.html | 18 +- .../admin/neb/config/giphy/giphy.component.ts | 11 +- .../neb/config/google/google.component.html | 14 +- .../neb/config/google/google.component.ts | 11 +- .../neb/config/guggy/guggy.component.html | 12 +- .../admin/neb/config/guggy/guggy.component.ts | 11 +- .../neb/config/imgur/imgur.component.html | 16 +- .../admin/neb/config/imgur/imgur.component.ts | 11 +- web/app/admin/neb/edit/edit.component.html | 9 +- web/app/admin/neb/edit/edit.component.ts | 13 +- web/app/admin/neb/neb.component.html | 19 +- web/app/admin/neb/neb.component.ts | 13 +- .../preview/preview.component.html | 4 +- .../sticker-packs.component.html | 24 +- .../sticker-packs/sticker-packs.component.ts | 15 +- .../terms/new-edit/new-edit.component.html | 16 +- .../terms/new-edit/new-edit.component.ts | 27 +- .../new-edit/publish/publish.component.html | 12 +- .../new-edit/publish/publish.component.ts | 5 +- web/app/admin/terms/terms.component.html | 19 +- web/app/admin/terms/terms.component.ts | 7 +- .../widgets/etherpad/etherpad.component.html | 12 +- .../widgets/etherpad/etherpad.component.ts | 11 +- .../admin/widgets/jitsi/jitsi.component.html | 20 +- .../admin/widgets/jitsi/jitsi.component.ts | 8 +- web/app/admin/widgets/widgets.component.html | 13 +- web/app/admin/widgets/widgets.component.ts | 12 +- web/app/app.component.ts | 12 +- web/app/app.module.ts | 16 +- web/app/app.routing.ts | 2 +- web/app/configs/bridge/bridge.component.ts | 13 +- .../gitter/gitter.bridge.component.html | 10 +- .../bridge/gitter/gitter.bridge.component.ts | 18 +- .../bridge/irc/irc.bridge.component.html | 32 +- .../bridge/irc/irc.bridge.component.ts | 22 +- .../bridge/slack/slack.bridge.component.html | 18 +- .../bridge/slack/slack.bridge.component.ts | 24 +- .../ask-unbridge/ask-unbridge.component.html | 11 +- .../cannot-unbridge.component.html | 9 +- .../telegram/telegram.bridge.component.html | 12 +- .../telegram/telegram.bridge.component.ts | 35 +- .../webhooks/webhooks.bridge.component.html | 18 +- .../webhooks/webhooks.bridge.component.ts | 17 +- .../complex-bot/complex-bot.component.ts | 11 +- .../rss/rss.complex-bot.component.html | 14 +- .../rss/rss.complex-bot.component.ts | 10 +- .../travisci.complex-bot.component.html | 55 +- .../travisci.complex-bot.component.ts | 10 +- .../simple-bot/simple-bot.component.html | 4 +- .../simple-bot/simple-bot.component.ts | 19 +- .../stickerpicker.component.html | 14 +- .../stickerpicker/stickerpicker.component.ts | 16 +- .../config-screen.widget.component.html | 12 +- .../custom/custom.widget.component.html | 8 +- .../widget/custom/custom.widget.component.ts | 7 +- .../etherpad/etherpad.widget.component.html | 6 +- .../etherpad/etherpad.widget.component.ts | 7 +- .../gcal.widget.component.html | 4 +- .../google-calendar/gcal.widget.component.ts | 7 +- .../google-docs/gdoc.widget.component.html | 4 +- .../google-docs/gdoc.widget.component.ts | 7 +- .../grafana/grafana.widget.component.html | 8 +- .../grafana/grafana.widget.component.ts | 7 +- .../widget/jitsi/jitsi.widget.component.html | 4 +- .../widget/jitsi/jitsi.widget.component.ts | 7 +- .../spotify/spotify.widget.component.html | 6 +- .../spotify/spotify.widget.component.ts | 7 +- .../tradingview.widget.component.html | 6 +- .../tradingview.widget.component.ts | 7 +- .../twitch/twitch.widget.component.html | 4 +- .../widget/twitch/twitch.widget.component.ts | 7 +- web/app/configs/widget/widget.component.ts | 17 +- .../youtube/youtube.widget.component.html | 4 +- .../youtube/youtube.widget.component.ts | 12 +- web/app/home/home.component.html | 106 ++- .../integration-bag.component.html | 6 +- .../page-header/page-header.component.html | 4 +- web/app/page-header/page-header.component.ts | 5 +- web/app/riot/riot-home/home.component.html | 22 +- web/app/riot/riot-home/home.component.ts | 58 +- .../screenshot-capable.directive.ts | 8 +- web/app/shared/models/integration.ts | 2 +- .../generic/generic.component.html | 4 +- .../jitsi/jitsi.component.html | 4 +- .../manager-test/manager-test.component.html | 12 +- .../manager-test/manager-test.component.ts | 30 +- .../reauth-example.component.html | 10 +- .../reauth-example.component.ts | 12 +- .../sticker-picker.component.html | 9 +- .../widget-wrappers/terms/terms.component.ts | 7 +- web/public/assets/i18n/basisNewLang.json | 586 +++++++++++++++ web/public/assets/i18n/de.json | 588 +++++++++++++++ web/public/assets/i18n/en.json | 587 +++++++++++++++ web/public/img/avatars/whiteboard.png | Bin 0 -> 12472 bytes 132 files changed, 3077 insertions(+), 1144 deletions(-) create mode 100644 web/public/assets/i18n/basisNewLang.json create mode 100644 web/public/assets/i18n/de.json create mode 100644 web/public/assets/i18n/en.json create mode 100644 web/public/img/avatars/whiteboard.png diff --git a/package-lock.json b/package-lock.json index d7bfab5..03abbdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -978,6 +978,26 @@ "tslib": "^1.9.0" } }, + "@ngx-translate/core": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-12.1.2.tgz", + "integrity": "sha512-ZudJsqIxTKlLmPoqK8gJY3UpMGujR0Xm7HfXL6AR79yGRS23QqpjAhMfx4v5qUCcHMmQ9/78bW8QJLfp31c7vQ==" + }, + "@ngx-translate/http-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-6.0.0.tgz", + "integrity": "sha512-LCekn6qCbeXWlhESCxU1rAbZz33WzDG0lI7Ig0pYC1o5YxJWrkU9y3Y4tNi+jakQ7R6YhTR2D3ox6APxDtA0wA==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, "@types/bluebird": { "version": "3.5.27", "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.27.tgz", @@ -1489,9 +1509,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1832,8 +1852,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "basic-auth": { "version": "2.0.1", @@ -1869,44 +1888,29 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" } } }, @@ -2118,25 +2122,6 @@ "isarray": "^1.0.0" } }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -2435,14 +2420,59 @@ } }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } } }, "clone": { @@ -3331,11 +3361,11 @@ "dev": true }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^2.0.0" } }, "deep-equal": { @@ -4228,11 +4258,6 @@ "schema-utils": "^1.0.0" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -4471,11 +4496,6 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, - "fs-copy-file-sync": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", - "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==" - }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -4487,11 +4507,11 @@ } }, "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs-write-stream-atomic": { @@ -5284,9 +5304,9 @@ } }, "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", "dev": true, "requires": { "glob": "~7.1.1", @@ -5446,9 +5466,9 @@ } }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "hpack.js": { @@ -5702,8 +5722,7 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "iferr": { "version": "0.1.5", @@ -5718,9 +5737,9 @@ "dev": true }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "requires": { "minimatch": "^3.0.4" } @@ -5770,9 +5789,9 @@ "dev": true }, "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", "dev": true }, "indent-string": { @@ -5838,12 +5857,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -5995,13 +6008,10 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -6197,9 +6207,9 @@ "dev": true }, "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", "dev": true }, "js-levenshtein": { @@ -6305,15 +6315,6 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -6789,9 +6790,9 @@ "dev": true }, "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "mini-css-extract-plugin": { "version": "0.7.0", @@ -6849,20 +6850,20 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mississippi": { @@ -6949,6 +6950,11 @@ } } }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "module-parent": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/module-parent/-/module-parent-0.0.2.tgz", @@ -7054,14 +7060,14 @@ } }, "napi-build-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz", - "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, "needle": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", - "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -7136,20 +7142,25 @@ } }, "node-abi": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.9.0.tgz", - "integrity": "sha512-jmEOvv0eanWjhX8dX1pmjb7oJl1U1oR4FOh0b2GnvALwSYoOdU7sj+kLDSAyjo4pfC9aj/IxkloxdLJQhSSQBA==", + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", + "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", "requires": { "semver": "^5.4.1" }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, + "node-addon-api": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", + "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -7301,9 +7312,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -7325,9 +7336,9 @@ } }, "node-sass": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz", - "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -7337,14 +7348,14 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "in-publish": "^2.0.0", - "lodash": "^4.17.11", + "lodash": "^4.17.15", "meow": "^3.7.0", "mkdirp": "^0.5.1", "nan": "^2.13.2", "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", - "sass-graph": "^2.2.4", + "sass-graph": "2.2.5", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" }, @@ -7368,6 +7379,12 @@ "supports-color": "^2.0.0" } }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -7390,9 +7407,9 @@ "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" }, "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "requires": { "abbrev": "1", "osenv": "^0.1.4" @@ -7411,9 +7428,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -7437,17 +7454,26 @@ "dev": true }, "npm-bundled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" }, "npm-packlist": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.3.tgz", - "integrity": "sha512-YABl09v5EoSw3uea9/gUfmqPUSbhhv7Qht8f7VKQWzTEEeUr5q+9w3jOvjIZ31v8qmR4UrkwpPvIk43MDevvsg==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npm-run-path": { @@ -7651,15 +7677,6 @@ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -9474,34 +9491,47 @@ } }, "prebuild-install": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.0.tgz", - "integrity": "sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", "github-from-package": "0.0.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^2.7.0", "noop-logger": "^0.1.1", "npmlog": "^4.0.1", - "os-homedir": "^1.0.1", - "pump": "^2.0.1", + "pump": "^3.0.0", "rc": "^1.2.7", - "simple-get": "^2.7.0", - "tar-fs": "^1.13.0", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0", "which-pm-runs": "^1.0.0" }, "dependencies": { - "simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "requires": { - "decompress-response": "^3.3.0", + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } @@ -9596,6 +9626,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -10354,15 +10385,15 @@ } }, "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", "dev": true, "requires": { "glob": "^7.0.0", "lodash": "^4.0.0", "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" + "yargs": "^13.3.2" } }, "sass-loader": { @@ -10685,27 +10716,25 @@ } }, "sharp": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.21.3.tgz", - "integrity": "sha512-5qZk8r+YgfyztLEKkNez20Wynq/Uh1oNyP5T/3gTYwt2lBYGs9iDs5m0yVsZEPm8eVBbAJhS08J1wp/g+Ai1Qw==", + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.2.tgz", + "integrity": "sha512-bGBPCxRAvdK9bX5HokqEYma4j/Q5+w8Nrmb2/sfgQCLEUx/HblcpmOfp59obL3+knIKnOhyKmDb4tEOhvFlp6Q==", "requires": { - "bindings": "^1.3.1", - "color": "^3.1.0", + "color": "^3.1.2", "detect-libc": "^1.0.3", - "fs-copy-file-sync": "^1.1.1", - "nan": "^2.12.1", + "node-addon-api": "^3.0.2", "npmlog": "^4.1.2", - "prebuild-install": "^5.2.2", - "semver": "^5.6.0", - "simple-get": "^3.0.3", - "tar": "^4.4.8", + "prebuild-install": "^5.3.5", + "semver": "^7.3.2", + "simple-get": "^4.0.0", + "tar-fs": "^2.1.0", "tunnel-agent": "^0.6.0" }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" } } }, @@ -10746,18 +10775,33 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.0.3.tgz", - "integrity": "sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", + "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", "requires": { - "decompress-response": "^3.3.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "simple-swizzle": { @@ -10987,9 +11031,9 @@ "dev": true }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10997,15 +11041,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -11013,9 +11057,9 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, "spdy": { @@ -11110,13 +11154,12 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sqlite3": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.9.tgz", - "integrity": "sha512-IkvzjmsWQl9BuBiM4xKpl5X8WCR4w0AeJHRdobCdXZ8dT/lNc1XS6WqvY35N6+YzIIgzSBeY5prdFObID9F9tA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "requires": { "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0", - "request": "^2.87.0" + "node-pre-gyp": "^0.11.0" } }, "srcset": { @@ -11200,9 +11243,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -11479,13 +11522,13 @@ "dev": true }, "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", + "minipass": "^2.8.6", "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", @@ -11493,20 +11536,20 @@ } }, "tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", "requires": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" }, "dependencies": { "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -11515,41 +11558,15 @@ } }, "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" } }, "telegraf": { @@ -11682,11 +11699,6 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -12757,9 +12769,9 @@ } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "which-pm-runs": { @@ -12846,55 +12858,77 @@ } }, "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" }, "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } } } }, "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, "zone.js": { diff --git a/package.json b/package.json index cc4785f..f3c4f1b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ }, "author": "Travis Ralston", "dependencies": { + "@ngx-translate/core": "^12.1.2", + "@ngx-translate/http-loader": "^6.0.0", "@types/bluebird": "^3.5.27", "@types/body-parser": "^1.17.0", "@types/node": "^12.0.10", @@ -46,10 +48,10 @@ "semver": "^6.0.0", "sequelize": "^5.18.4", "sequelize-typescript": "^1.0.0", - "sharp": "^0.21.1", + "sharp": "^0.26.0", "split-host": "^0.1.1", "spotify-uri": "^1.0.0", - "sqlite3": "^4.0.9", + "sqlite3": "^4.2.0", "telegraf": "^3.30.1", "typescript": "^3.5.2", "typescript-ioc": "^1.2.5", @@ -100,7 +102,7 @@ "mini-css-extract-plugin": "^0.7.0", "ng2-breadcrumbs": "^0.1.281", "ngx-modialog": "^5.0.1", - "node-sass": "^4.12.0", + "node-sass": "^4.14.1", "postcss-cssnext": "^3.1.0", "postcss-import": "^12.0.1", "postcss-loader": "^3.0.0", diff --git a/web/app/admin/admin.component.html b/web/app/admin/admin.component.html index 9bcd246..a996527 100644 --- a/web/app/admin/admin.component.html +++ b/web/app/admin/admin.component.html @@ -1,14 +1,14 @@ {{ version }}
-
\ No newline at end of file + diff --git a/web/app/admin/bridges/bridges.component.html b/web/app/admin/bridges/bridges.component.html index 8faac99..4fc4bf7 100644 --- a/web/app/admin/bridges/bridges.component.html +++ b/web/app/admin/bridges/bridges.component.html @@ -5,25 +5,24 @@

- Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For - example, an IRC bridge can allow IRC and matrix users to communicate with each other. + {{'Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.' | translate}}

- - - + + + - + - - + +
NameDescriptionActions{{'Name' | translate}}{{'Description' | translate}}{{'Actions' | translate}}
No bridges.{{'No bridges.' | translate}}
{{ bridge.displayName }}{{ bridge.description }}{{ bridge.displayName | translate }}{{ bridge.description | translate }} @@ -34,4 +33,4 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/bridges.component.ts b/web/app/admin/bridges/bridges.component.ts index 216eebc..00bd2e3 100644 --- a/web/app/admin/bridges/bridges.component.ts +++ b/web/app/admin/bridges/bridges.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ToasterService } from "angular2-toaster"; import { FE_Bridge } from "../../shared/models/integration"; import { AdminIntegrationsApiService } from "../../shared/services/admin/admin-integrations-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./bridges.component.html", @@ -13,7 +14,8 @@ export class AdminBridgesComponent implements OnInit { public bridges: FE_Bridge[]; constructor(private adminIntegrations: AdminIntegrationsApiService, - private toaster: ToasterService) { + private toaster: ToasterService, public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -22,7 +24,7 @@ export class AdminBridgesComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load bridges"); + this.translate.get('Failed to load bridges').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/gitter/gitter.component.html b/web/app/admin/bridges/gitter/gitter.component.html index 6b045fb..c504284 100644 --- a/web/app/admin/bridges/gitter/gitter.component.html +++ b/web/app/admin/bridges/gitter/gitter.component.html @@ -5,21 +5,20 @@

- matrix-appservice-gitter - is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a - single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room. + {{'matrix-appservice-gitter' | translate}} + {{'is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.' | translate}}

- - + + - +
NameActions{{'Name' | translate}}{{'Actions' | translate}}
No bridge configurations.{{'No bridge configurations.' | translate}}
@@ -37,12 +36,12 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/gitter/gitter.component.ts b/web/app/admin/bridges/gitter/gitter.component.ts index e5f60eb..0d77140 100644 --- a/web/app/admin/bridges/gitter/gitter.component.ts +++ b/web/app/admin/bridges/gitter/gitter.component.ts @@ -9,6 +9,7 @@ import { AdminGitterApiService } from "../../../shared/services/admin/admin-gitt import { FE_GitterBridge } from "../../../shared/models/gitter"; import { FE_Upstream } from "../../../shared/models/admin-responses"; import { AdminUpstreamApiService } from "../../../shared/services/admin/admin-upstream-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./gitter.component.html", @@ -25,7 +26,9 @@ export class AdminGitterBridgeComponent implements OnInit { constructor(private gitterApi: AdminGitterApiService, private upstreamApi: AdminUpstreamApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -38,7 +41,7 @@ export class AdminGitterBridgeComponent implements OnInit { this.configurations = await this.gitterApi.getBridges(); } catch (err) { console.error(err); - this.toaster.pop("error", "Error loading bridges"); + this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); } ); } } @@ -48,12 +51,12 @@ export class AdminGitterBridgeComponent implements OnInit { const createBridge = (upstream: FE_Upstream) => { return this.gitterApi.newFromUpstream(upstream).then(bridge => { this.configurations.push(bridge); - this.toaster.pop("success", "matrix.org's Gitter bridge added"); + this.translate.get('matrix.org\'s Gitter bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.isUpdating = false; }).catch(err => { console.error(err); this.isUpdating = false; - this.toaster.pop("error", "Error adding matrix.org's Gitter Bridge"); + this.translate.get('Error adding matrix.org\'s Gitter Bridge').subscribe((res: string) => {this.toaster.pop("error", res); } ); }); }; @@ -66,7 +69,7 @@ export class AdminGitterBridgeComponent implements OnInit { createBridge(upstream); }).catch(err => { console.error(err); - this.toaster.pop("error", "Error creating matrix.org's Gitter Bridge"); + this.translate.get('Error creating matrix.org\'s Gitter Bridge').subscribe((res: string) => {this.toaster.pop("error", res); } ); }); } else createBridge(vectorUpstreams[0]); } @@ -80,7 +83,7 @@ export class AdminGitterBridgeComponent implements OnInit { }, ManageSelfhostedGitterBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Gitter bridge list"); + this.translate.get('Failed to get an update Gitter bridge list').subscribe((res: string) => {this.toaster.pop("error", res); } ); }); }); } @@ -95,7 +98,7 @@ export class AdminGitterBridgeComponent implements OnInit { }, ManageSelfhostedGitterBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Gitter bridge list"); + this.translate.get('Failed to get an update Gitter bridge list').subscribe((res: string) => {this.toaster.pop("error", res); } ); }); }); } diff --git a/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.html b/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.html index f30ff44..813275a 100644 --- a/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.html +++ b/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.html @@ -1,16 +1,17 @@
-

{{ isAdding ? "Add a new" : "Edit" }} self-hosted Gitter bridge

+

{{'self-hosted Gitter bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})

- Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public - internet. + {{'Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.ts b/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.ts index 511d889..5dbd481 100644 --- a/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.ts +++ b/web/app/admin/bridges/gitter/manage-selfhosted/manage-selfhosted.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminGitterApiService } from "../../../../shared/services/admin/admin-gitter-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class ManageSelfhostedGitterBridgeDialogContext extends BSModalContext { public provisionUrl: string; @@ -22,7 +23,9 @@ export class AdminGitterBridgeManageSelfhostedComponent implements ModalComponen constructor(public dialog: DialogRef, private gitterApi: AdminGitterApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.provisionUrl = dialog.context.provisionUrl; this.bridgeId = dialog.context.bridgeId; this.isAdding = !this.bridgeId; @@ -32,21 +35,21 @@ export class AdminGitterBridgeManageSelfhostedComponent implements ModalComponen this.isSaving = true; if (this.isAdding) { this.gitterApi.newSelfhosted(this.provisionUrl).then(() => { - this.toaster.pop("success", "Gitter bridge added"); + this.translate.get('Gitter bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to create Gitter bridge"); + this.translate.get('Failed to create Gitter bridge').subscribe((res: string) => { this.toaster.pop("error", res); }); }); } else { this.gitterApi.updateSelfhosted(this.bridgeId, this.provisionUrl).then(() => { - this.toaster.pop("success", "Gitter bridge updated"); + this.translate.get('Gitter bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to update Gitter bridge"); + this.translate.get('Failed to update Gitter bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.html b/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.html index b9d0d3c..690f61d 100644 --- a/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.html +++ b/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.html @@ -1,13 +1,13 @@
-

Add a new self-hosted IRC Bridge

+

{{'Add a new self-hosted IRC Bridge' | translate}}

-

Self-hosted IRC bridges must have provisioning enabled in the configuration.

+

{{'Self-hosted IRC bridges must have' | translate}}{{'provisioning' | translate}} {{'enabled in the configuration.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.ts b/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.ts index c26e7af..7e3c09f 100644 --- a/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.ts +++ b/web/app/admin/bridges/irc/add-selfhosted/add-selfhosted.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminIrcApiService } from "../../../../shared/services/admin/admin-irc-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class AddSelfhostedIrcBridgeDialogContext extends BSModalContext { } @@ -18,18 +19,20 @@ export class AdminIrcBridgeAddSelfhostedComponent implements ModalComponent, private ircApi: AdminIrcApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; } public add() { this.isSaving = true; this.ircApi.newSelfhosted(this.provisionUrl).then(() => { - this.toaster.pop("success", "IRC Bridge added"); + this.translate.get('IRC Bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to create IRC bridge"); + this.translate.get('Failed to create IRC bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/irc/irc.component.html b/web/app/admin/bridges/irc/irc.component.html index b019b1c..a82e217 100644 --- a/web/app/admin/bridges/irc/irc.component.html +++ b/web/app/admin/bridges/irc/irc.component.html @@ -5,22 +5,21 @@

- matrix-appservice-irc - is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC - bridges to better distribute the load across multiple networks in large deployments. + {{'matrix-appservice-irc' | translate}} + {{'is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.' | translate}}

- - + + - +
NameEnabled NetworksActions{{'Enabled Networks' | translate}}{{'Actions' | translate}}
No bridge configurations.{{'No bridge configurations.' | translate}}
@@ -33,7 +32,7 @@ - This bridge is offline or unavailable. + {{'This bridge is offline or unavailable.' | translate}} @@ -45,11 +44,11 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/irc/irc.component.ts b/web/app/admin/bridges/irc/irc.component.ts index ab46c26..7dbf699 100644 --- a/web/app/admin/bridges/irc/irc.component.ts +++ b/web/app/admin/bridges/irc/irc.component.ts @@ -10,6 +10,7 @@ import { AddSelfhostedIrcBridgeDialogContext, AdminIrcBridgeAddSelfhostedComponent } from "./add-selfhosted/add-selfhosted.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./irc.component.html", @@ -27,7 +28,9 @@ export class AdminIrcBridgeComponent implements OnInit { constructor(private upstreamApi: AdminUpstreamApiService, private ircApi: AdminIrcApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -48,7 +51,7 @@ export class AdminIrcBridgeComponent implements OnInit { } } catch (err) { console.error(err); - this.toaster.pop("error", "Error loading bridges"); + this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); }); } } @@ -67,13 +70,13 @@ export class AdminIrcBridgeComponent implements OnInit { const createBridge = (upstream: FE_Upstream) => { return this.ircApi.newFromUpstream(upstream).then(bridge => { this.configurations.push(bridge); - this.toaster.pop("success", "matrix.org's IRC bridge added", "Click the pencil icon to enable networks."); + this.translate.get(['Click the pencil icon to enable networks.', 'matrix.org\'s IRC bridge added']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); }); this.isUpdating = false; this.hasModularBridge = true; }).catch(err => { console.error(err); this.isUpdating = false; - this.toaster.pop("error", "Error adding matrix.org's IRC Bridge"); + this.translate.get('Error adding matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }; const vectorUpstreams = this.upstreams.filter(u => u.type === "vector"); @@ -85,7 +88,7 @@ export class AdminIrcBridgeComponent implements OnInit { createBridge(upstream); }).catch(err => { console.error(err); - this.toaster.pop("error", "Error creating matrix.org's IRC Bridge"); + this.translate.get('Error creating matrix.org\'s IRC Bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else createBridge(vectorUpstreams[0]); } @@ -97,7 +100,7 @@ export class AdminIrcBridgeComponent implements OnInit { }, AddSelfhostedIrcBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update IRC bridge list"); + this.translate.get('Failed to get an update IRC bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } diff --git a/web/app/admin/bridges/irc/networks/networks.component.html b/web/app/admin/bridges/irc/networks/networks.component.html index b93d7e0..ffa9068 100644 --- a/web/app/admin/bridges/irc/networks/networks.component.html +++ b/web/app/admin/bridges/irc/networks/networks.component.html @@ -6,8 +6,8 @@ - - + + @@ -23,7 +23,7 @@ - \ No newline at end of file + diff --git a/web/app/admin/bridges/irc/networks/networks.component.ts b/web/app/admin/bridges/irc/networks/networks.component.ts index d65b821..6e06cde 100644 --- a/web/app/admin/bridges/irc/networks/networks.component.ts +++ b/web/app/admin/bridges/irc/networks/networks.component.ts @@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { FE_IrcBridge } from "../../../../shared/models/irc"; import { AdminIrcApiService } from "../../../../shared/services/admin/admin-irc-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class IrcNetworksDialogContext extends BSModalContext { public bridge: FE_IrcBridge; @@ -29,7 +30,9 @@ export class AdminIrcBridgeNetworksComponent implements ModalComponent, private ircApi: AdminIrcApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.bridge = dialog.context.bridge; const networkIds = Object.keys(this.bridge.availableNetworks); @@ -51,13 +54,13 @@ export class AdminIrcBridgeNetworksComponent implements ModalComponent { this.isUpdating = false; - this.toaster.pop("success", "Network " + (network.isEnabled ? "enabled" : "disabled")); + this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Network " + (network.isEnabled ? res[0] : res[1])); }); }).catch(err => { console.error(err); this.isUpdating = false; network.isEnabled = !network.isEnabled; this.bridge.availableNetworks[network.id].isEnabled = network.isEnabled; - this.toaster.pop("error", "Failed to update network"); + this.translate.get('Failed to update network').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.html b/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.html index 8e09010..a545584 100644 --- a/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.html +++ b/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.html @@ -1,16 +1,15 @@
-

{{ isAdding ? "Add a new" : "Edit" }} self-hosted Slack bridge

+

{{'self-hosted Slack bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})

- Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public - internet. + {{'Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.ts b/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.ts index 24bb6d9..296d7d3 100644 --- a/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.ts +++ b/web/app/admin/bridges/slack/manage-selfhosted/manage-selfhosted.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminSlackApiService } from "../../../../shared/services/admin/admin-slack-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class ManageSelfhostedSlackBridgeDialogContext extends BSModalContext { public provisionUrl: string; @@ -22,7 +23,9 @@ export class AdminSlackBridgeManageSelfhostedComponent implements ModalComponent constructor(public dialog: DialogRef, private slackApi: AdminSlackApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.provisionUrl = dialog.context.provisionUrl; this.bridgeId = dialog.context.bridgeId; this.isAdding = !this.bridgeId; @@ -32,21 +35,21 @@ export class AdminSlackBridgeManageSelfhostedComponent implements ModalComponent this.isSaving = true; if (this.isAdding) { this.slackApi.newSelfhosted(this.provisionUrl).then(() => { - this.toaster.pop("success", "Slack bridge added"); + this.translate.get('Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to create Slack bridge"); + this.translate.get('Failed to create Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else { this.slackApi.updateSelfhosted(this.bridgeId, this.provisionUrl).then(() => { - this.toaster.pop("success", "Slack bridge updated"); + this.translate.get('Slack bridge updated').subscribe((res: string) => {this.toaster.pop("success", res);}); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to update Slack bridge"); + this.translate.get('Failed to update Slack bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/slack/slack.component.html b/web/app/admin/bridges/slack/slack.component.html index 7eadfe9..32a9c1b 100644 --- a/web/app/admin/bridges/slack/slack.component.html +++ b/web/app/admin/bridges/slack/slack.component.html @@ -6,21 +6,20 @@

matrix-appservice-slack - is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access - their Slack workspaces and from there they can pick the channels they'd like to bridge. + target="_blank">{{'matrix-appservice-slack' | translate}} + {{'is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they\'d like to bridge.' | translate}}

NetworkEnabled{{'Network' | translate}}{{'Enabled' | translate}}
- - + + - +
NameActions{{'Name' | translate}}{{'Actions' | translate}}
No bridge configurations.{{'No bridge configurations.' | translate}}
@@ -38,12 +37,12 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/slack/slack.component.ts b/web/app/admin/bridges/slack/slack.component.ts index 1654b7d..34eb109 100644 --- a/web/app/admin/bridges/slack/slack.component.ts +++ b/web/app/admin/bridges/slack/slack.component.ts @@ -9,6 +9,7 @@ import { } from "./manage-selfhosted/manage-selfhosted.component"; import { FE_SlackBridge } from "../../../shared/models/slack"; import { AdminSlackApiService } from "../../../shared/services/admin/admin-slack-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./slack.component.html", @@ -25,7 +26,9 @@ export class AdminSlackBridgeComponent implements OnInit { constructor(private slackApi: AdminSlackApiService, private upstreamApi: AdminUpstreamApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -38,7 +41,7 @@ export class AdminSlackBridgeComponent implements OnInit { this.configurations = await this.slackApi.getBridges(); } catch (err) { console.error(err); - this.toaster.pop("error", "Error loading bridges"); + this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); }); } } @@ -48,12 +51,12 @@ export class AdminSlackBridgeComponent implements OnInit { const createBridge = (upstream: FE_Upstream) => { return this.slackApi.newFromUpstream(upstream).then(bridge => { this.configurations.push(bridge); - this.toaster.pop("success", "matrix.org's Slack bridge added"); + this.translate.get('matrix.org\'s Slack bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.isUpdating = false; }).catch(err => { console.error(err); this.isUpdating = false; - this.toaster.pop("error", "Error adding matrix.org's Slack Bridge"); + this.translate.get('Error adding matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }; @@ -66,7 +69,7 @@ export class AdminSlackBridgeComponent implements OnInit { createBridge(upstream); }).catch(err => { console.error(err); - this.toaster.pop("error", "Error creating matrix.org's Slack Bridge"); + this.translate.get('Error creating matrix.org\'s Slack Bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else createBridge(vectorUpstreams[0]); } @@ -80,7 +83,7 @@ export class AdminSlackBridgeComponent implements OnInit { }, ManageSelfhostedSlackBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Slack bridge list"); + this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } @@ -95,7 +98,7 @@ export class AdminSlackBridgeComponent implements OnInit { }, ManageSelfhostedSlackBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Slack bridge list"); + this.translate.get('Failed to get an update Slack bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } diff --git a/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.html b/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.html index 37bf426..b1a2248 100644 --- a/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.html +++ b/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.html @@ -1,46 +1,46 @@
-

{{ isAdding ? "Add a new" : "Edit" }} self-hosted Telegram bridge

+

{{'self-hosted Telegram bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})

-

Self-hosted Telegram bridges must have provisioning enabled in the configuration.

+

{{'Self-hosted Telegram bridges must have' | translate}} {{'provisioning' | translate}} {{'enabled in the configuration.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.ts b/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.ts index 74d54db..a2b268d 100644 --- a/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.ts +++ b/web/app/admin/bridges/telegram/manage-selfhosted/manage-selfhosted.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminTelegramApiService } from "../../../../shared/services/admin/admin-telegram-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class ManageSelfhostedTelegramBridgeDialogContext extends BSModalContext { public provisionUrl: string; @@ -28,7 +29,9 @@ export class AdminTelegramBridgeManageSelfhostedComponent implements ModalCompon constructor(public dialog: DialogRef, private telegramApi: AdminTelegramApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.provisionUrl = dialog.context.provisionUrl; this.sharedSecret = dialog.context.sharedSecret; this.allowTgPuppets = dialog.context.allowTgPuppets; @@ -45,21 +48,21 @@ export class AdminTelegramBridgeManageSelfhostedComponent implements ModalCompon }; if (this.isAdding) { this.telegramApi.newSelfhosted(this.provisionUrl, this.sharedSecret, options).then(() => { - this.toaster.pop("success", "Telegram bridge added"); + this.translate.get('Telegram bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to create Telegram bridge"); + this.translate.get('Failed to create Telegram bridge').subscribe((res: string) => { this.toaster.pop("error", res); }); }); } else { this.telegramApi.updateSelfhosted(this.bridgeId, this.provisionUrl, this.sharedSecret, options).then(() => { - this.toaster.pop("success", "Telegram bridge updated"); + this.translate.get('Telegram bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to update Telegram bridge"); + this.translate.get('Failed to update Telegram bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/telegram/telegram.component.html b/web/app/admin/bridges/telegram/telegram.component.html index 27d818e..f250e1c 100644 --- a/web/app/admin/bridges/telegram/telegram.component.html +++ b/web/app/admin/bridges/telegram/telegram.component.html @@ -5,24 +5,19 @@

- mautrix-telegram - is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be - done through a "relay bot" (all Matrix users are represented through a single bot in Telegram) - or by making use of a user's real Telegram account (known as "puppeting"). Currently - only one Telegram bridge can be configured at a time. -

- + {{'mautrix-telegram' | translate}} + {{'is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a \'relay bot\' (all Matrix users are represented through a single bot in Telegram) or by making use of a user\'s real Telegram account (known as \'puppeting\'). Currently only one Telegram bridge can be configured at a time.' | translate}} - - - + + + - +
NameEnabled FeaturesActions{{'Name' | translate}}{{'Enabled Features' | translate}}{{'Actions' | translate}}
No bridge configurations.{{'No bridge configurations.' | translate}}
@@ -43,8 +38,8 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/telegram/telegram.component.ts b/web/app/admin/bridges/telegram/telegram.component.ts index 7ce6002..1e29c07 100644 --- a/web/app/admin/bridges/telegram/telegram.component.ts +++ b/web/app/admin/bridges/telegram/telegram.component.ts @@ -7,6 +7,7 @@ import { } from "./manage-selfhosted/manage-selfhosted.component"; import { FE_TelegramBridge } from "../../../shared/models/telegram"; import { AdminTelegramApiService } from "../../../shared/services/admin/admin-telegram-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./telegram.component.html", @@ -20,7 +21,9 @@ export class AdminTelegramBridgeComponent implements OnInit { constructor(private telegramApi: AdminTelegramApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -32,7 +35,7 @@ export class AdminTelegramBridgeComponent implements OnInit { this.configurations = await this.telegramApi.getBridges(); } catch (err) { console.error(err); - this.toaster.pop("error", "Error loading bridges"); + this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); }); } } @@ -47,7 +50,7 @@ export class AdminTelegramBridgeComponent implements OnInit { }, ManageSelfhostedTelegramBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Telegram bridge list"); + this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } @@ -72,7 +75,7 @@ export class AdminTelegramBridgeComponent implements OnInit { }, ManageSelfhostedTelegramBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Telegram bridge list"); + this.translate.get('Failed to get an update Telegram bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } diff --git a/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.html b/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.html index ee4472a..2a80119 100644 --- a/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.html +++ b/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.html @@ -1,21 +1,21 @@
-

{{ isAdding ? "Add a new" : "Edit" }} self-hosted webhook bridge

+

{{'self-hosted webhook bridge' | translate}} ({{ isAdding ? "Add a new" : "Edit" }})

-

Self-hosted webhook bridges must have provisioning enabled in the configuration.

+

{{'Self-hosted webhook bridges must have' | translate}} {{'provisioning' | translate}} {{'enabled in the configuration.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.ts b/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.ts index 454b876..80798a7 100644 --- a/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.ts +++ b/web/app/admin/bridges/webhooks/manage-selfhosted/manage-selfhosted.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminWebhooksApiService } from "../../../../shared/services/admin/admin-webhooks-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class ManageSelfhostedWebhooksBridgeDialogContext extends BSModalContext { public provisionUrl: string; @@ -26,7 +27,9 @@ export class AdminWebhooksBridgeManageSelfhostedComponent implements ModalCompon constructor(public dialog: DialogRef, private webhooksApi: AdminWebhooksApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.provisionUrl = dialog.context.provisionUrl; this.sharedSecret = dialog.context.sharedSecret; this.bridgeId = dialog.context.bridgeId; @@ -37,21 +40,21 @@ export class AdminWebhooksBridgeManageSelfhostedComponent implements ModalCompon this.isSaving = true; if (this.isAdding) { this.webhooksApi.newSelfhosted(this.provisionUrl, this.sharedSecret).then(() => { - this.toaster.pop("success", "Webhook bridge added"); + this.translate.get('Webhook bridge added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to create Webhook bridge"); + this.translate.get('Failed to create Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else { this.webhooksApi.updateSelfhosted(this.bridgeId, this.provisionUrl, this.sharedSecret).then(() => { - this.toaster.pop("success", "Webhook bridge updated"); + this.translate.get('Webhook bridge updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Failed to update Webhook bridge"); + this.translate.get('Failed to update Webhook bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/bridges/webhooks/webhooks.component.html b/web/app/admin/bridges/webhooks/webhooks.component.html index 78e620f..7c8297a 100644 --- a/web/app/admin/bridges/webhooks/webhooks.component.html +++ b/web/app/admin/bridges/webhooks/webhooks.component.html @@ -5,20 +5,20 @@

- matrix-appservice-webhooks - provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room. + {{'matrix-appservice-webhooks' | translate}} + {{'provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.' | translate}}

- - + + - +
NameActions{{'Name' | translate}}{{'Actions' | translate}}
No bridge configurations.{{'No bridge configurations.' | translate}}
@@ -36,8 +36,8 @@
- \ No newline at end of file + diff --git a/web/app/admin/bridges/webhooks/webhooks.component.ts b/web/app/admin/bridges/webhooks/webhooks.component.ts index d41e3a3..1d53c94 100644 --- a/web/app/admin/bridges/webhooks/webhooks.component.ts +++ b/web/app/admin/bridges/webhooks/webhooks.component.ts @@ -7,6 +7,7 @@ import { } from "./manage-selfhosted/manage-selfhosted.component"; import { FE_WebhooksBridge } from "../../../shared/models/webhooks"; import { AdminWebhooksApiService } from "../../../shared/services/admin/admin-webhooks-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./webhooks.component.html", @@ -20,7 +21,9 @@ export class AdminWebhooksBridgeComponent implements OnInit { constructor(private webhooksApi: AdminWebhooksApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -32,7 +35,7 @@ export class AdminWebhooksBridgeComponent implements OnInit { this.configurations = await this.webhooksApi.getBridges(); } catch (err) { console.error(err); - this.toaster.pop("error", "Error loading bridges"); + this.translate.get('Error loading bridges').subscribe((res: string) => {this.toaster.pop("error", res); }); } } @@ -47,7 +50,7 @@ export class AdminWebhooksBridgeComponent implements OnInit { }, ManageSelfhostedWebhooksBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Webhooks bridge list"); + this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } @@ -63,7 +66,7 @@ export class AdminWebhooksBridgeComponent implements OnInit { }, ManageSelfhostedWebhooksBridgeDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an update Webhooks bridge list"); + this.translate.get('Failed to get an update Webhooks bridge list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } diff --git a/web/app/admin/custom-bots/add/add.component.html b/web/app/admin/custom-bots/add/add.component.html index dcbf97e..fdf8447 100644 --- a/web/app/admin/custom-bots/add/add.component.html +++ b/web/app/admin/custom-bots/add/add.component.html @@ -1,11 +1,11 @@
-

{{ isAdding ? "Add a new" : "Edit" }} custom bot

+

{{ isAdding ? "Add a new" : "Edit" }} {{ 'custom bot' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/custom-bots/add/add.component.ts b/web/app/admin/custom-bots/add/add.component.ts index d0aa47c..c67eee4 100644 --- a/web/app/admin/custom-bots/add/add.component.ts +++ b/web/app/admin/custom-bots/add/add.component.ts @@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { FE_CustomSimpleBot, FE_UserProfile } from "../../../shared/models/admin-responses"; import { AdminCustomSimpleBotsApiService } from "../../../shared/services/admin/admin-custom-simple-bots-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class AddCustomBotDialogContext extends BSModalContext { bot: FE_CustomSimpleBot; @@ -23,7 +24,9 @@ export class AdminAddCustomBotComponent implements ModalComponent, private botApi: AdminCustomSimpleBotsApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.bot = this.dialog.context.bot || {}; this.isAdding = !this.dialog.context.bot; } @@ -45,23 +48,23 @@ export class AdminAddCustomBotComponent implements ModalComponent {this.toaster.pop("warning", res); }); return; } if (!this.bot.avatarUrl) { - this.toaster.pop("warning", "Please enter an avatar URL for the bot"); + this.translate.get('Please enter an avatar URL for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } if (!this.bot.userId) { - this.toaster.pop("warning", "Please enter a user ID for the bot"); + this.translate.get('Please enter a user ID for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } if (!this.bot.description) { - this.toaster.pop("warning", "Please enter a description for the bot"); + this.translate.get('Please enter a description for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } if (!this.bot.accessToken) { - this.toaster.pop("warning", "Please enter an access token for the bot"); + this.translate.get('Please enter an access token for the bot').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } @@ -85,12 +88,12 @@ export class AdminAddCustomBotComponent implements ModalComponent { - this.toaster.pop("success", "Bot updated"); + this.translate.get('Bot updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(error => { this.isSaving = false; console.error(error); - this.toaster.pop("error", "Error updating bot"); + this.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/custom-bots/custom-bots.component.html b/web/app/admin/custom-bots/custom-bots.component.html index f278587..209e6b0 100644 --- a/web/app/admin/custom-bots/custom-bots.component.html +++ b/web/app/admin/custom-bots/custom-bots.component.html @@ -2,25 +2,21 @@
- +
-

- Custom bots give you the ability to add your own bots to Dimension for users to add - to their rooms. These bots can't have any configuration to them and must be able to - accept room invites on their own. All Dimension will do when a user wants to add the - bot is invite it to the room. +

{{'Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can\'t have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.' | translate}}

- - + + - +
NameActions{{'Name' | translate}}{{'Actions' | translate}}
No custom bots.{{'No custom bots.' | translate}}
@@ -38,8 +34,8 @@
-
\ No newline at end of file + diff --git a/web/app/admin/custom-bots/custom-bots.component.ts b/web/app/admin/custom-bots/custom-bots.component.ts index 50f45e0..52fcbc2 100644 --- a/web/app/admin/custom-bots/custom-bots.component.ts +++ b/web/app/admin/custom-bots/custom-bots.component.ts @@ -4,6 +4,7 @@ import { FE_CustomSimpleBot } from "../../shared/models/admin-responses"; import { AdminCustomSimpleBotsApiService } from "../../shared/services/admin/admin-custom-simple-bots-api.service"; import { Modal, overlayConfigFactory } from "ngx-modialog"; import { AddCustomBotDialogContext, AdminAddCustomBotComponent } from "./add/add.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./custom-bots.component.html", @@ -17,11 +18,13 @@ export class AdminCustomBotsComponent { constructor(private botApi: AdminCustomSimpleBotsApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; this.reload().then(() => this.isLoading = false).catch(error => { console.error(error); - this.toaster.pop("error", "Error loading go-neb configuration"); + this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -39,7 +42,7 @@ export class AdminCustomBotsComponent { }, AddCustomBotDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an updated bot list"); + this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } @@ -53,7 +56,7 @@ export class AdminCustomBotsComponent { }, AddCustomBotDialogContext)).result.then(() => { this.reload().catch(err => { console.error(err); - this.toaster.pop("error", "Failed to get an updated bot list"); + this.translate.get('Failed to get an updated bot list').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } @@ -63,11 +66,11 @@ export class AdminCustomBotsComponent { bot.isEnabled = !bot.isEnabled; this.botApi.updateBot(bot.id, bot).then(() => { this.isUpdating = false; - this.toaster.pop("success", "Bot " + (bot.isEnabled ? "enabled" : "disabled")); + this.translate.get(['Enabled', 'disabled']).subscribe((res: string) => {this.toaster.pop("success", "Bot " + (bot.isEnabled ? res[0] : res[1])); }); }).catch(error => { console.error(error); bot.isEnabled = !bot.isEnabled; - this.toaster.pop("error", "Error updating bot"); + this.translate.get('Error updating bot').subscribe((res: string) => {this.toaster.pop("error", res); }); }) } } diff --git a/web/app/admin/home/home.component.html b/web/app/admin/home/home.component.html index bbce040..3499de1 100644 --- a/web/app/admin/home/home.component.html +++ b/web/app/admin/home/home.component.html @@ -2,45 +2,44 @@
- +

- Parts of your configuration are displayed below. To change these values, edit your configuration and - restart Dimension. + {{'Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.' | translate}}

- Administrators + {{'Administrators' | translate}}
  • {{ user }}
- Widget Blacklist + {{'Widget Blacklist' | translate}}
  • {{ ip }}
- Homeserver
+ {{'Homeserver' | translate}}
Name: {{ config.homeserver.name }}
- Federation URL: {{ config.homeserver.federationUrl }}
- Federation Hostname: {{ config.homeserver.federationHostname }}
- Client/Server URL: {{ config.homeserver.clientServerUrl }}
- Utility User ID: {{ config.homeserver.userId }} + {{'Federation URL' | translate}}: {{ config.homeserver.federationUrl }}
+ {{'Federation Hostname' | translate}}: {{ config.homeserver.federationHostname }}
+ {{'Client/Server URL'| translate}}: {{ config.homeserver.clientServerUrl }}
+ {{'Utility User ID' | translate}}: {{ config.homeserver.userId }}
- Sessions
- Tokens registered: {{ config.sessionInfo.numTokens }}
+ {{'Sessions' | translate}}
+ {{'Tokens registered' | translate}}: {{ config.sessionInfo.numTokens }}
-
\ No newline at end of file + diff --git a/web/app/admin/home/home.component.ts b/web/app/admin/home/home.component.ts index e47bb15..57457dc 100644 --- a/web/app/admin/home/home.component.ts +++ b/web/app/admin/home/home.component.ts @@ -7,6 +7,7 @@ import { AdminLogoutConfirmationDialogComponent, LogoutConfirmationDialogContext } from "./logout-confirmation/logout-confirmation.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./home.component.html", @@ -19,7 +20,9 @@ export class AdminHomeComponent { constructor(private adminApi: AdminApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; adminApi.getConfig().then(config => { this.config = config; this.isLoading = false; @@ -31,11 +34,11 @@ export class AdminHomeComponent { isBlocking: true, }, LogoutConfirmationDialogContext)).result.then(() => { this.adminApi.logoutAll().then(() => { - this.toaster.pop("success", "Everyone has been logged out"); + this.translate.get('Everyone has been logged out').subscribe((res: string) => {this.toaster.pop("success", res); }); this.config.sessionInfo.numTokens = 0; }).catch(err => { console.error(err); - this.toaster.pop("error", "Error logging everyone out"); + this.translate.get('Error logging everyone out').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }); } diff --git a/web/app/admin/home/logout-confirmation/logout-confirmation.component.html b/web/app/admin/home/logout-confirmation/logout-confirmation.component.html index 024b0c8..956b74e 100644 --- a/web/app/admin/home/logout-confirmation/logout-confirmation.component.html +++ b/web/app/admin/home/logout-confirmation/logout-confirmation.component.html @@ -1,20 +1,18 @@
-

Logout confirmation

+

{{'Logout confirmation' | translate}}

- Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. - Most clients will automatically re-register for a login token behind the scenes, similar to how a login - token was first acquired. + {{'Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/neb/add-selfhosted/add-selfhosted.component.html b/web/app/admin/neb/add-selfhosted/add-selfhosted.component.html index 455b21e..a049afb 100644 --- a/web/app/admin/neb/add-selfhosted/add-selfhosted.component.html +++ b/web/app/admin/neb/add-selfhosted/add-selfhosted.component.html @@ -1,27 +1,26 @@ - +

- Self-hosted go-neb instances are powered by application services installed on your homeserver. The - application service is responsible for creating the bots dynamically. + {{'Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.' | translate}}

-
\ No newline at end of file +
diff --git a/web/app/admin/neb/add-selfhosted/add-selfhosted.component.ts b/web/app/admin/neb/add-selfhosted/add-selfhosted.component.ts index d2a7dbc..5f35d91 100644 --- a/web/app/admin/neb/add-selfhosted/add-selfhosted.component.ts +++ b/web/app/admin/neb/add-selfhosted/add-selfhosted.component.ts @@ -8,6 +8,7 @@ import { AdminNebAppserviceConfigComponent, AppserviceConfigDialogContext } from "../appservice-config/appservice-config.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ @@ -25,7 +26,9 @@ export class AdminAddSelfhostedNebComponent { private toaster: ToasterService, private router: Router, private activatedRoute: ActivatedRoute, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public save(): void { @@ -33,8 +36,7 @@ export class AdminAddSelfhostedNebComponent { this.asApi.createAppservice(this.userPrefix).then(appservice => { return this.nebApi.newAppserviceConfiguration(this.adminUrl, appservice); }).then(neb => { - this.toaster.pop("success", "New go-neb created"); - + this.translate.get('New go-neb created').subscribe((res: string) => {this.toaster.pop("success", res); }); this.modal.open(AdminNebAppserviceConfigComponent, overlayConfigFactory({ neb: neb, @@ -44,7 +46,7 @@ export class AdminAddSelfhostedNebComponent { }).catch(err => { console.error(err); this.isSaving = false; - this.toaster.pop("error", "Error creating appservice"); + this.translate.get('Error creating appservice').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/appservice-config/appservice-config.component.html b/web/app/admin/neb/appservice-config/appservice-config.component.html index 97b9433..833e80f 100644 --- a/web/app/admin/neb/appservice-config/appservice-config.component.html +++ b/web/app/admin/neb/appservice-config/appservice-config.component.html @@ -1,22 +1,22 @@
-

go-neb appservice configuration

+

{{'go-neb appservice configuration' | translate}}

- Copy and paste this configuration to appservice-{{appservice.id}}.yaml on your homeserver and - register it as an application service. + {{'Copy and paste this configuration to' | translate}} appservice-{{appservice.id}}.yaml + {{'on your homeserver and register it as an application service.' | translate}}
{{appserviceConfig}}
-
\ No newline at end of file + diff --git a/web/app/admin/neb/appservice-config/appservice-config.component.ts b/web/app/admin/neb/appservice-config/appservice-config.component.ts index a9693f7..9532d13 100644 --- a/web/app/admin/neb/appservice-config/appservice-config.component.ts +++ b/web/app/admin/neb/appservice-config/appservice-config.component.ts @@ -4,6 +4,7 @@ import { DialogRef, ModalComponent } from "ngx-modialog"; import { FE_Appservice, FE_NebConfiguration } from "../../../shared/models/admin-responses"; import { AdminAppserviceApiService } from "../../../shared/services/admin/admin-appservice-api.service"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; +import { TranslateService } from "@ngx-translate/core"; export class AppserviceConfigDialogContext extends BSModalContext { public neb: FE_NebConfiguration; @@ -19,7 +20,11 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent, private adminAppserviceApi: AdminAppserviceApiService, private toaster: ToasterService) { + constructor(public dialog: DialogRef, + private adminAppserviceApi: AdminAppserviceApiService, + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.neb = dialog.context.neb; this.adminAppserviceApi.getAppservice(this.neb.appserviceId).then(appservice => { @@ -27,7 +32,7 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent { console.error(err); - this.toaster.pop("error", "Could not load appservice configuration"); + this.translate.get('Could not load appservice configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -48,10 +53,10 @@ export class AdminNebAppserviceConfigComponent implements ModalComponent { - this.toaster.pop("success", "The appservice appears to be correctly set up"); + this.translate.get('The appservice appears to be correctly set up').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); - this.toaster.pop("error", "The appservice is not correctly set up"); + this.translate.get('The appservice is not correctly set up').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/config/giphy/giphy.component.html b/web/app/admin/neb/config/giphy/giphy.component.html index eec64e8..47412fb 100644 --- a/web/app/admin/neb/config/giphy/giphy.component.html +++ b/web/app/admin/neb/config/giphy/giphy.component.html @@ -1,33 +1,33 @@
-

Giphy Configuration

+

{{'Giphy Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/neb/config/giphy/giphy.component.ts b/web/app/admin/neb/config/giphy/giphy.component.ts index eaee6ce..b814908 100644 --- a/web/app/admin/neb/config/giphy/giphy.component.ts +++ b/web/app/admin/neb/config/giphy/giphy.component.ts @@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context"; import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service"; import { FE_NebConfiguration } from "../../../../shared/models/admin-responses"; import { FE_Integration } from "../../../../shared/models/integration"; +import { TranslateService } from "@ngx-translate/core"; interface GiphyConfig { api_key: string; @@ -25,7 +26,9 @@ export class AdminNebGiphyConfigComponent implements ModalComponent, private adminNebApi: AdminNebApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.neb = dialog.context.neb; this.integration = dialog.context.integration; } @@ -36,19 +39,19 @@ export class AdminNebGiphyConfigComponent implements ModalComponent { console.error(err); - this.toaster.pop("error", "Error loading configuration"); + this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save() { this.isUpdating = true; this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating integration"); + this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/config/google/google.component.html b/web/app/admin/neb/config/google/google.component.html index 1ce043f..1f9fd4b 100644 --- a/web/app/admin/neb/config/google/google.component.html +++ b/web/app/admin/neb/config/google/google.component.html @@ -1,21 +1,21 @@
-

Google Configuration

+

{{'Google Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/neb/config/google/google.component.ts b/web/app/admin/neb/config/google/google.component.ts index 6126c69..aa6e71e 100644 --- a/web/app/admin/neb/config/google/google.component.ts +++ b/web/app/admin/neb/config/google/google.component.ts @@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context"; import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service"; import { FE_NebConfiguration } from "../../../../shared/models/admin-responses"; import { FE_Integration } from "../../../../shared/models/integration"; +import { TranslateService } from "@ngx-translate/core"; interface GoogleConfig { api_key: string; @@ -25,7 +26,9 @@ export class AdminNebGoogleConfigComponent implements ModalComponent, private adminNebApi: AdminNebApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.neb = dialog.context.neb; this.integration = dialog.context.integration; } @@ -36,19 +39,19 @@ export class AdminNebGoogleConfigComponent implements ModalComponent { console.error(err); - this.toaster.pop("error", "Error loading configuration"); + this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save() { this.isUpdating = true; this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating integration"); + this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/config/guggy/guggy.component.html b/web/app/admin/neb/config/guggy/guggy.component.html index a868714..cb39e55 100644 --- a/web/app/admin/neb/config/guggy/guggy.component.html +++ b/web/app/admin/neb/config/guggy/guggy.component.html @@ -1,14 +1,14 @@
-

Guggy Configuration

+

{{'Guggy Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/neb/config/guggy/guggy.component.ts b/web/app/admin/neb/config/guggy/guggy.component.ts index 9517de2..0d827c3 100644 --- a/web/app/admin/neb/config/guggy/guggy.component.ts +++ b/web/app/admin/neb/config/guggy/guggy.component.ts @@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context"; import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service"; import { FE_NebConfiguration } from "../../../../shared/models/admin-responses"; import { FE_Integration } from "../../../../shared/models/integration"; +import { TranslateService } from "@ngx-translate/core"; interface GuggyConfig { api_key: string; @@ -24,7 +25,9 @@ export class AdminNebGuggyConfigComponent implements ModalComponent, private adminNebApi: AdminNebApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.neb = dialog.context.neb; this.integration = dialog.context.integration; } @@ -35,19 +38,19 @@ export class AdminNebGuggyConfigComponent implements ModalComponent { console.error(err); - this.toaster.pop("error", "Error loading configuration"); + this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save() { this.isUpdating = true; this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating integration"); + this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/config/imgur/imgur.component.html b/web/app/admin/neb/config/imgur/imgur.component.html index ed4e138..0b3d700 100644 --- a/web/app/admin/neb/config/imgur/imgur.component.html +++ b/web/app/admin/neb/config/imgur/imgur.component.html @@ -1,21 +1,21 @@
-

Imgur Configuration

+

{{'Imgur Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/neb/config/imgur/imgur.component.ts b/web/app/admin/neb/config/imgur/imgur.component.ts index ac7c404..39d0ed0 100644 --- a/web/app/admin/neb/config/imgur/imgur.component.ts +++ b/web/app/admin/neb/config/imgur/imgur.component.ts @@ -5,6 +5,7 @@ import { NebBotConfigurationDialogContext } from "../config-context"; import { AdminNebApiService } from "../../../../shared/services/admin/admin-neb-api.service"; import { FE_NebConfiguration } from "../../../../shared/models/admin-responses"; import { FE_Integration } from "../../../../shared/models/integration"; +import { TranslateService } from "@ngx-translate/core"; interface ImgurConfig { client_id: string; @@ -25,7 +26,9 @@ export class AdminNebImgurConfigComponent implements ModalComponent, private adminNebApi: AdminNebApiService, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.neb = dialog.context.neb; this.integration = dialog.context.integration; } @@ -36,19 +39,19 @@ export class AdminNebImgurConfigComponent implements ModalComponent { console.error(err); - this.toaster.pop("error", "Error loading configuration"); + this.translate.get('Error loading configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save() { this.isUpdating = true; this.adminNebApi.setIntegrationConfiguration(this.neb.id, this.integration.type, this.config).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get('Configuration updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating integration"); + this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/neb/edit/edit.component.html b/web/app/admin/neb/edit/edit.component.html index 50eb5fd..4e541b2 100644 --- a/web/app/admin/neb/edit/edit.component.html +++ b/web/app/admin/neb/edit/edit.component.html @@ -4,15 +4,14 @@
-

go-neb supports many different types of bots, each of which is listed below. Here you can configure which - bots this go-neb instance should use.

+

{{'go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.' | translate}}

- - + + @@ -34,4 +33,4 @@
NameDescriptionActions{{'Description' | translate}}{{'Actions' | translate}}
-
\ No newline at end of file + diff --git a/web/app/admin/neb/edit/edit.component.ts b/web/app/admin/neb/edit/edit.component.ts index 72dfb94..4bd46bb 100644 --- a/web/app/admin/neb/edit/edit.component.ts +++ b/web/app/admin/neb/edit/edit.component.ts @@ -11,6 +11,7 @@ import { NebBotConfigurationDialogContext } from "../config/config-context"; import { AdminNebGuggyConfigComponent } from "../config/guggy/guggy.component"; import { AdminNebGoogleConfigComponent } from "../config/google/google.component"; import { AdminNebImgurConfigComponent } from "../config/imgur/imgur.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ @@ -30,7 +31,9 @@ export class AdminEditNebComponent implements OnInit, OnDestroy { constructor(private nebApi: AdminNebApiService, private route: ActivatedRoute, private modal: Modal, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -58,12 +61,12 @@ export class AdminEditNebComponent implements OnInit, OnDestroy { try { await this.nebApi.toggleIntegration(this.nebConfig.id, bot.type, bot.isEnabled); this.isUpdating = false; - this.toaster.pop("success", "Integration updated"); + this.translate.get('Integration updated').subscribe((res: string) => {this.toaster.pop("success", res); }); } catch (err) { console.error(err); bot.isEnabled = !bot.isEnabled; // revert change this.isUpdating = false; - this.toaster.pop("error", "Error updating integration"); + this.translate.get('Error updating integration').subscribe((res: string) => {this.toaster.pop("error", res); }); return; } @@ -76,7 +79,7 @@ export class AdminEditNebComponent implements OnInit, OnDestroy { await this.nebApi.setIntegrationConfiguration(this.nebConfig.id, bot.type, {}); } catch (err) { console.error(err); - this.toaster.pop("warning", "Failed to configure the integration", "Manual troubleshooting may be requred"); + this.translate.get(['Failed to configure the integration', 'Manual troubleshooting may be requred' ]).subscribe((res: string) => {this.toaster.pop("warning", res[0], res[1]); }); return; } } @@ -120,7 +123,7 @@ export class AdminEditNebComponent implements OnInit, OnDestroy { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop('error', "Could not get go-neb configuration"); + this.translate.get('Could not get go-neb configuration').subscribe((res: string) => {this.toaster.pop('error', res); }); }); } } diff --git a/web/app/admin/neb/neb.component.html b/web/app/admin/neb/neb.component.html index 638af76..9034ef6 100644 --- a/web/app/admin/neb/neb.component.html +++ b/web/app/admin/neb/neb.component.html @@ -2,24 +2,21 @@
- +
-

go-neb is a multi-purpose bot that can - provide various services, such as reaction GIFs and Github notifications. There are two options for - go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have - multiple services associated with it (ie: one go-neb here can do everything).

+

go-neb {{'is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org\'s or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).' | translate}}

- - + + - +
NameEnabled BotsActions{{'Enabled Bots' | translate}}{{'Actions' | translate}}
No go-neb configurations.{{'No go-neb configurations.' | translate}}
@@ -43,11 +40,11 @@
-
\ No newline at end of file + diff --git a/web/app/admin/neb/neb.component.ts b/web/app/admin/neb/neb.component.ts index d2fa73d..86ad0f2 100644 --- a/web/app/admin/neb/neb.component.ts +++ b/web/app/admin/neb/neb.component.ts @@ -10,6 +10,7 @@ import { AppserviceConfigDialogContext } from "./appservice-config/appservice-config.component"; import { Modal, overlayConfigFactory } from "ngx-modialog"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./neb.component.html", @@ -30,11 +31,13 @@ export class AdminNebComponent { private toaster: ToasterService, private router: Router, private activatedRoute: ActivatedRoute, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; this.reload().then(() => this.isLoading = false).catch(error => { console.error(error); - this.toaster.pop("error", "Error loading go-neb configuration"); + this.translate.get('Error loading go-neb configuration').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -97,13 +100,13 @@ export class AdminNebComponent { const createNeb = (upstream: FE_Upstream) => { return this.nebApi.newUpstreamConfiguration(upstream).then(neb => { this.configurations.push(neb); - this.toaster.pop("success", "matrix.org's go-neb added", "Click the pencil icon to enable the bots."); + this.translate.get(['matrix.org\'s go-neb added', 'Click the pencil icon to enable the bots.']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); }); this.isAddingModularNeb = false; this.hasModularNeb = true; }).catch(error => { console.error(error); this.isAddingModularNeb = false; - this.toaster.pop("error", "Error adding matrix.org's go-neb"); + this.translate.get('Error adding matrix.org\'s go-neb').subscribe((res: string) => {this.toaster.pop("error", res); }); }); }; @@ -116,7 +119,7 @@ export class AdminNebComponent { createNeb(upstream); }).catch(err => { console.error(err); - this.toaster.pop("error", "Error creating matrix.org go-neb"); + this.translate.get('Error creating matrix.org go-neb').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else createNeb(vectorUpstreams[0]); } diff --git a/web/app/admin/sticker-packs/preview/preview.component.html b/web/app/admin/sticker-packs/preview/preview.component.html index 67e867c..0a5e04f 100644 --- a/web/app/admin/sticker-packs/preview/preview.component.html +++ b/web/app/admin/sticker-packs/preview/preview.component.html @@ -13,7 +13,7 @@ - \ No newline at end of file + diff --git a/web/app/admin/sticker-packs/sticker-packs.component.html b/web/app/admin/sticker-packs/sticker-packs.component.html index f6c9ca7..aab0c95 100644 --- a/web/app/admin/sticker-packs/sticker-packs.component.html +++ b/web/app/admin/sticker-packs/sticker-packs.component.html @@ -5,9 +5,7 @@

- Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able - to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled - then the 'sticker picker' widget will be disabled. + {{'Sticker packs provide a way to convey memes or feelings to others in a room. From here you\'re able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the \'sticker picker\' widget will be disabled.' | translate}}

@@ -17,7 +15,7 @@
@@ -26,24 +24,24 @@ Name - Description - Author - License - Actions + {{'Description' | translate}} + {{'Author' | translate}} + {{'License' | translate}} + {{'Actions' | translate}} - No sticker packs installed. + {{'No sticker packs installed.' | translate}} - {{ pack.displayName }} - {{ pack.description }} + {{ pack.displayName | translate}} + {{ pack.description | translate }} {{ pack.author.name }} - Dimension + {{'Dimension' | translate}} {{ pack.license.name }} @@ -58,4 +56,4 @@
- \ No newline at end of file + diff --git a/web/app/admin/sticker-packs/sticker-packs.component.ts b/web/app/admin/sticker-packs/sticker-packs.component.ts index 8078833..090f7fd 100644 --- a/web/app/admin/sticker-packs/sticker-packs.component.ts +++ b/web/app/admin/sticker-packs/sticker-packs.component.ts @@ -4,6 +4,7 @@ import { FE_StickerPack } from "../../shared/models/integration"; import { AdminStickersApiService } from "../../shared/services/admin/admin-stickers-api-service"; import { Modal, overlayConfigFactory } from "ngx-modialog"; import { AdminStickerPackPreviewComponent, StickerPackPreviewDialogContext } from "./preview/preview.component"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./sticker-packs.component.html", @@ -19,7 +20,9 @@ export class AdminStickerPacksComponent implements OnInit { constructor(private adminStickers: AdminStickersApiService, private toaster: ToasterService, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -28,7 +31,7 @@ export class AdminStickerPacksComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load sticker packs"); + this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -37,12 +40,12 @@ export class AdminStickerPacksComponent implements OnInit { this.isUpdating = true; this.adminStickers.togglePack(pack.id, pack.isEnabled).then(() => { this.isUpdating = false; - this.toaster.pop("success", "Sticker pack updated"); + this.translate.get('Sticker pack updated').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); pack.isEnabled = !pack.isEnabled; // revert change this.isUpdating = false; - this.toaster.pop("error", "Error updating sticker pack"); + this.translate.get('Error updating sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -61,11 +64,11 @@ export class AdminStickerPacksComponent implements OnInit { this.isImporting = false; this.tgUrl = ""; this.packs.push(pack); - this.toaster.pop("success", "Telegram sticker pack imported"); + this.translate.get('Telegram sticker pack imported').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); this.isImporting = false; - this.toaster.pop("error", "Error importing sticker pack"); + this.translate.get('Error importing sticker pack').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/terms/new-edit/new-edit.component.html b/web/app/admin/terms/new-edit/new-edit.component.html index 6d3f723..1b558a1 100644 --- a/web/app/admin/terms/new-edit/new-edit.component.html +++ b/web/app/admin/terms/new-edit/new-edit.component.html @@ -4,18 +4,18 @@
-
{{languages[code].langName}} version
+
{{languages[code].langName}} {{'version' | translate}}
@@ -33,14 +33,14 @@
-
\ No newline at end of file + diff --git a/web/app/admin/terms/new-edit/new-edit.component.ts b/web/app/admin/terms/new-edit/new-edit.component.ts index 07a9a98..ce682ae 100644 --- a/web/app/admin/terms/new-edit/new-edit.component.ts +++ b/web/app/admin/terms/new-edit/new-edit.component.ts @@ -9,6 +9,7 @@ import { AdminTermsNewEditPublishDialogComponent, AdminTermsNewEditPublishDialogContext } from "./publish/publish.component"; +import { TranslateService } from "@ngx-translate/core"; interface ILanguage { name: string, @@ -66,7 +67,9 @@ export class AdminNewEditTermsComponent implements OnInit { private toaster: ToasterService, private router: Router, private activatedRoute: ActivatedRoute, - private modal: Modal) { + private modal: Modal, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -94,7 +97,7 @@ export class AdminNewEditTermsComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load policy"); + this.translate.get('Failed to load policy').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } else { this.adminTerms.getAllPolicies().then(policies => { @@ -102,7 +105,7 @@ export class AdminNewEditTermsComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load policies"); + this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } @@ -133,11 +136,11 @@ export class AdminNewEditTermsComponent implements OnInit { }); await this.adminTerms.publishDraft(this.shortcode, val); - this.toaster.pop("success", "Policy published"); + this.translate.get('Policy published').subscribe((res: string) => {this.toaster.pop("success", res); }); this.router.navigate(["../.."], {relativeTo: this.activatedRoute}); } catch (e) { console.error(e); - this.toaster.pop("error", "Error publishing policy"); + this.translate.get('Error publishing policy').subscribe((res: string) => {this.toaster.pop("error", res); }); this.isUpdating = false; } }); @@ -146,11 +149,11 @@ export class AdminNewEditTermsComponent implements OnInit { public async create() { for (const languageCode in this.languages) { if (this.languages[languageCode].name.trim().length <= 0) { - this.toaster.pop("warning", "Please enter a name for all policies"); + this.translate.get('Please enter a name for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } if (this.languages[languageCode].text.trim().length <= 0) { - this.toaster.pop("warning", "Please enter text for all policies"); + this.translate.get('Please enter text for all policies').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } } @@ -164,12 +167,11 @@ export class AdminNewEditTermsComponent implements OnInit { text: this.languages['en'].text, url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/draft`, }); - - this.toaster.pop("success", "Draft saved"); + this.translate.get('Draft saved').subscribe((res: string) => {this.toaster.pop("success", res); }); this.router.navigate(["../.."], {relativeTo: this.activatedRoute}); } catch (e) { console.error(e); - this.toaster.pop("error", "Error saving policy"); + this.translate.get('Error saving policy').subscribe((res: string) => {this.toaster.pop("error", res); }); this.isUpdating = false; } return; @@ -188,12 +190,11 @@ export class AdminNewEditTermsComponent implements OnInit { text: this.languages['en'].text, url: `${window.location.origin}/widgets/terms/${shortcode}/en/draft`, }); - - this.toaster.pop("success", "Draft created"); + this.translate.get('Draft created').subscribe((res: string) => {this.toaster.pop("success", res); }); this.router.navigate([".."], {relativeTo: this.activatedRoute}); } catch (e) { console.error(e); - this.toaster.pop("error", "Error creating document"); + this.translate.get('Error creating document').subscribe((res: string) => {this.toaster.pop("error", res); }); this.isUpdating = false; } } diff --git a/web/app/admin/terms/new-edit/publish/publish.component.html b/web/app/admin/terms/new-edit/publish/publish.component.html index 2128780..5dc07f4 100644 --- a/web/app/admin/terms/new-edit/publish/publish.component.html +++ b/web/app/admin/terms/new-edit/publish/publish.component.html @@ -1,20 +1,20 @@
-

Publish policy

+

{{'Publish policy' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/terms/new-edit/publish/publish.component.ts b/web/app/admin/terms/new-edit/publish/publish.component.ts index 993f7b7..b3c1bbb 100644 --- a/web/app/admin/terms/new-edit/publish/publish.component.ts +++ b/web/app/admin/terms/new-edit/publish/publish.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { ToasterService } from "angular2-toaster"; +import { TranslateService } from "@ngx-translate/core"; export class AdminTermsNewEditPublishDialogContext extends BSModalContext { } @@ -14,12 +15,12 @@ export class AdminTermsNewEditPublishDialogComponent implements ModalComponent, private toaster: ToasterService) { + constructor(public dialog: DialogRef, private toaster: ToasterService, public translate: TranslateService) { } public publish() { if (!this.version || !this.version.trim()) { - this.toaster.pop("warning", "Please enter a version number"); + this.translate.get('Please enter a version number').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } this.dialog.close(this.version); diff --git a/web/app/admin/terms/terms.component.html b/web/app/admin/terms/terms.component.html index dcc94fb..74f01f5 100644 --- a/web/app/admin/terms/terms.component.html +++ b/web/app/admin/terms/terms.component.html @@ -2,26 +2,23 @@
- +

- Before users can use Dimension they must agree to the terms of service for using your - instance. If you're using any matrix.org bridges, users will be required to accept - the terms of service for your upstream integration managers (scalar.vector.im usually) - in addition to the terms you add here. + {{'Before users can use Dimension they must agree to the terms of service for using your instance. If you\'re using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.' | translate}}

- - - + + + - + @@ -37,8 +34,8 @@
Policy NameVersionActions{{'Policy Name' | translate}}{{'Version' | translate}}{{'Actions' | translate}}
No policies written.{{'No policies written.' | translate}}
{{ policy.languages['en'].name }}
-
\ No newline at end of file + diff --git a/web/app/admin/terms/terms.component.ts b/web/app/admin/terms/terms.component.ts index 40b20ff..d39d3b1 100644 --- a/web/app/admin/terms/terms.component.ts +++ b/web/app/admin/terms/terms.component.ts @@ -3,6 +3,7 @@ import { ToasterService } from "angular2-toaster"; import { FE_TermsEditable } from "../../shared/models/terms"; import { AdminTermsApiService } from "../../shared/services/admin/admin-terms-api.service"; import { ActivatedRoute, Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./terms.component.html", @@ -19,7 +20,9 @@ export class AdminTermsComponent implements OnInit { constructor(private adminTerms: AdminTermsApiService, private toaster: ToasterService, private router: Router, - private activatedRoute: ActivatedRoute) { + private activatedRoute: ActivatedRoute, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit() { @@ -31,7 +34,7 @@ export class AdminTermsComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load policies"); + this.translate.get('Failed to load policies').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } diff --git a/web/app/admin/widgets/etherpad/etherpad.component.html b/web/app/admin/widgets/etherpad/etherpad.component.html index 0a5c468..30763dd 100644 --- a/web/app/admin/widgets/etherpad/etherpad.component.html +++ b/web/app/admin/widgets/etherpad/etherpad.component.html @@ -1,11 +1,11 @@
-

Etherpad Widget Configuration

+

{{'Etherpad Widget Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/widgets/etherpad/etherpad.component.ts b/web/app/admin/widgets/etherpad/etherpad.component.ts index 87f63dc..25b97c4 100644 --- a/web/app/admin/widgets/etherpad/etherpad.component.ts +++ b/web/app/admin/widgets/etherpad/etherpad.component.ts @@ -4,6 +4,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { WidgetConfigDialogContext } from "../widgets.component"; import { AdminIntegrationsApiService } from "../../../shared/services/admin/admin-integrations-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./etherpad.component.html", @@ -15,7 +16,11 @@ export class AdminWidgetEtherpadConfigComponent implements ModalComponent, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService) { + constructor(public dialog: DialogRef, + private adminIntegrationsApi: AdminIntegrationsApiService, + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; this.originalWidget = dialog.context.widget; this.widget = JSON.parse(JSON.stringify(this.originalWidget)); } @@ -24,12 +29,12 @@ export class AdminWidgetEtherpadConfigComponent implements ModalComponent { this.originalWidget.options = this.widget.options; - this.toaster.pop("success", "Widget updated"); + this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating widget"); + this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/app/admin/widgets/jitsi/jitsi.component.html b/web/app/admin/widgets/jitsi/jitsi.component.html index f756647..df74150 100644 --- a/web/app/admin/widgets/jitsi/jitsi.component.html +++ b/web/app/admin/widgets/jitsi/jitsi.component.html @@ -1,24 +1,24 @@
-

Jitsi Widget Configuration

+

{{'Jitsi Widget Configuration' | translate}}

-
\ No newline at end of file + diff --git a/web/app/admin/widgets/jitsi/jitsi.component.ts b/web/app/admin/widgets/jitsi/jitsi.component.ts index ca5daf8..309581d 100644 --- a/web/app/admin/widgets/jitsi/jitsi.component.ts +++ b/web/app/admin/widgets/jitsi/jitsi.component.ts @@ -4,6 +4,7 @@ import { ToasterService } from "angular2-toaster"; import { DialogRef, ModalComponent } from "ngx-modialog"; import { WidgetConfigDialogContext } from "../widgets.component"; import { AdminIntegrationsApiService } from "../../../shared/services/admin/admin-integrations-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "./jitsi.component.html", @@ -15,7 +16,8 @@ export class AdminWidgetJitsiConfigComponent implements ModalComponent, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService) { + constructor(public dialog: DialogRef, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, public translate: TranslateService) { + this.translate = translate; this.originalWidget = dialog.context.widget; this.widget = JSON.parse(JSON.stringify(this.originalWidget)); @@ -27,12 +29,12 @@ export class AdminWidgetJitsiConfigComponent implements ModalComponent { this.originalWidget.options = this.widget.options; - this.toaster.pop("success", "Widget updated"); + this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); }); this.dialog.close(); }).catch(err => { this.isUpdating = false; console.error(err); - this.toaster.pop("error", "Error updating widget"); + this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } diff --git a/web/app/admin/widgets/widgets.component.html b/web/app/admin/widgets/widgets.component.html index 9dc0d74..f212ce5 100644 --- a/web/app/admin/widgets/widgets.component.html +++ b/web/app/admin/widgets/widgets.component.html @@ -4,21 +4,20 @@
-

Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets - Dimension will offer to users.

+

{{'Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.' | translate}}

- - + + - - + +
NameDescriptionActions{{'Description' | translate}}{{'Actions' | translate}}
{{ widget.displayName }}{{ widget.description }}{{ widget.displayName | translate }}{{ widget.description | translate }} @@ -32,4 +31,4 @@
-
\ No newline at end of file + diff --git a/web/app/admin/widgets/widgets.component.ts b/web/app/admin/widgets/widgets.component.ts index 5debd8e..f64e0c1 100644 --- a/web/app/admin/widgets/widgets.component.ts +++ b/web/app/admin/widgets/widgets.component.ts @@ -6,6 +6,7 @@ import { Modal, overlayConfigFactory } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminWidgetJitsiConfigComponent } from "./jitsi/jitsi.component"; import { AdminIntegrationsApiService } from "../../shared/services/admin/admin-integrations-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class WidgetConfigDialogContext extends BSModalContext { public widget: FE_Widget; @@ -21,13 +22,14 @@ export class AdminWidgetsComponent { public isUpdating = false; public widgets: FE_Widget[]; - constructor(private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, private modal: Modal) { + constructor(private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService, private modal: Modal, public translate: TranslateService) { + this.translate = translate; this.adminIntegrationsApi.getAllWidgets().then(widgets => { this.isLoading = false; this.widgets = widgets; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load widgets"); + this.translate.get('Failed to load widgets').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -36,12 +38,12 @@ export class AdminWidgetsComponent { this.isUpdating = true; this.adminIntegrationsApi.toggleIntegration(widget.category, widget.type, widget.isEnabled).then(() => { this.isUpdating = false; - this.toaster.pop("success", "Widget updated"); + this.translate.get('Widget updated').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); widget.isEnabled = !widget.isEnabled; // revert change this.isUpdating = false; - this.toaster.pop("error", "Error updating widget"); + this.translate.get('Error updating widget').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -53,7 +55,7 @@ export class AdminWidgetsComponent { if (!component) { console.error("No known dialog component for " + widget.type); - this.toaster.pop("error", "Error opening configuration page"); + this.translate.get('Error opening configuration page').subscribe((res: string) => {this.toaster.pop("error", res); }); return; } diff --git a/web/app/app.component.ts b/web/app/app.component.ts index 01abfa2..0910fb2 100644 --- a/web/app/app.component.ts +++ b/web/app/app.component.ts @@ -1,5 +1,7 @@ import { Component } from "@angular/core"; import "../style/app.scss"; +import { TranslateService } from "@ngx-translate/core"; +import { HttpClient } from "@angular/common/http"; @Component({ selector: "my-app", // @@ -8,7 +10,13 @@ import "../style/app.scss"; }) export class AppComponent { - constructor() { - console.log("Dimension AppComponent constructed"); + constructor(public translate: TranslateService, public http: HttpClient) { + translate.addLangs(['en', 'de']); + translate.setDefaultLang('de'); + if (navigator.language === 'de') { + translate.use('de'); + } else { + translate.use('en'); + } } } diff --git a/web/app/app.module.ts b/web/app/app.module.ts index 6f5496e..191fa69 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -7,7 +7,7 @@ import { UiSwitchModule } from "angular2-ui-switch"; import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { routing } from "./app.routing"; import { FormsModule } from "@angular/forms"; -import { HttpClientModule } from "@angular/common/http"; +import { HttpClient, HttpClientModule } from "@angular/common/http"; import { BrowserModule } from "@angular/platform-browser"; import { AppComponent } from "./app.component"; import { HomeComponent } from "./home/home.component"; @@ -118,6 +118,13 @@ import { CKEditorModule } from "@ckeditor/ckeditor5-angular"; import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component"; import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/publish/publish.component"; import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component"; +import { TranslateLoader, TranslateModule } from "@ngx-translate/core"; +import { TranslateHttpLoader } from "@ngx-translate/http-loader"; + +// AoT requires an exported function for factories +export function HttpLoaderFactory(http: HttpClient) { + return new TranslateHttpLoader(http); +} @NgModule({ imports: [ @@ -133,6 +140,13 @@ import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.compo BootstrapModalModule, BreadcrumbsModule, CKEditorModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient] + } + }) ], declarations: [ AppComponent, diff --git a/web/app/app.routing.ts b/web/app/app.routing.ts index 1086ea8..4451919 100644 --- a/web/app/app.routing.ts +++ b/web/app/app.routing.ts @@ -183,7 +183,7 @@ const routes: Routes = [ { path: "etherpad", component: EtherpadWidgetConfigComponent, - data: {breadcrumb: "Etherpad Widgets", name: "Etherpad Widgets"}, + data: {breadcrumb: "Notes Widgets", name: "Notes Widgets"}, }, { path: "googlecalendar", diff --git a/web/app/configs/bridge/bridge.component.ts b/web/app/configs/bridge/bridge.component.ts index b5c100c..8ef7001 100644 --- a/web/app/configs/bridge/bridge.component.ts +++ b/web/app/configs/bridge/bridge.component.ts @@ -6,6 +6,7 @@ import { IntegrationsApiService } from "../../shared/services/integrations/integ import { ToasterService } from "angular2-toaster"; import { ServiceLocator } from "../../shared/registry/locator.service"; import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class BridgeComponent implements OnInit, OnDestroy { @@ -14,7 +15,6 @@ export class BridgeComponent implements OnInit, OnDestroy { public bridge: FE_Bridge; public newConfig: T; public roomId: string; - private routeQuerySubscription: Subscription; protected toaster = ServiceLocator.injector.get(ToasterService); @@ -22,7 +22,8 @@ export class BridgeComponent implements OnInit, OnDestroy { protected route = ServiceLocator.injector.get(ActivatedRoute); protected scalarClientApi = ServiceLocator.injector.get(ScalarClientApiService); - constructor(private integrationType: string) { + constructor(private integrationType: string, public translate: TranslateService) { + this.translate = translate; this.isLoading = true; this.isUpdating = false; } @@ -50,20 +51,20 @@ export class BridgeComponent implements OnInit, OnDestroy { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load configuration"); + this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save(): void { this.isUpdating = true; this.integrationsApi.setIntegrationConfiguration("bridge", this.integrationType, this.roomId, this.newConfig).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); }); this.bridge.config = this.newConfig; this.isUpdating = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Error updating configuration"); + this.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); }); this.isUpdating = false; }); } -} \ No newline at end of file +} diff --git a/web/app/configs/bridge/gitter/gitter.bridge.component.html b/web/app/configs/bridge/gitter/gitter.bridge.component.html index fc2d562..a5f23d3 100644 --- a/web/app/configs/bridge/gitter/gitter.bridge.component.html +++ b/web/app/configs/bridge/gitter/gitter.bridge.component.html @@ -2,18 +2,18 @@
- Bridge to Gitter + {{'Bridge to Gitter' | translate}}
- This room is bridged to "{{ bridge.config.link.gitterRoomName }}" on Gitter. + {{'This room is bridged to on Gitter' | translate}} "{{ bridge.config.link.gitterRoomName }}" {{'on Gitter' | translate}}.
@@ -24,4 +24,4 @@
- \ No newline at end of file + diff --git a/web/app/configs/bridge/gitter/gitter.bridge.component.ts b/web/app/configs/bridge/gitter/gitter.bridge.component.ts index 060b9c5..b9436f2 100644 --- a/web/app/configs/bridge/gitter/gitter.bridge.component.ts +++ b/web/app/configs/bridge/gitter/gitter.bridge.component.ts @@ -3,6 +3,7 @@ import { BridgeComponent } from "../bridge.component"; import { FE_GitterLink } from "../../../shared/models/gitter"; import { GitterApiService } from "../../../shared/services/integrations/gitter-api.service"; import { ScalarClientApiService } from "../../../shared/services/scalar/scalar-client-api.service"; +import { TranslateService } from "@ngx-translate/core"; interface GitterConfig { botUserId: string; @@ -18,8 +19,9 @@ export class GitterBridgeConfigComponent extends BridgeComponent { public gitterRoomName: string; public isBusy: boolean; - constructor(private gitter: GitterApiService, private scalar: ScalarClientApiService) { - super("gitter"); + constructor(private gitter: GitterApiService, private scalar: ScalarClientApiService, public translate: TranslateService) { + super("gitter", translate); + this.translate = translate; } public get isBridged(): boolean { @@ -35,7 +37,7 @@ export class GitterBridgeConfigComponent extends BridgeComponent { if (!e.response || !e.response.error || !e.response.error._error || e.response.error._error.message.indexOf("already in the room") === -1) { this.isBusy = false; - this.toaster.pop("error", "Error inviting bridge"); + this.translate.get('Error inviting bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); return; } } @@ -43,11 +45,11 @@ export class GitterBridgeConfigComponent extends BridgeComponent { this.gitter.bridgeRoom(this.roomId, this.gitterRoomName).then(link => { this.bridge.config.link = link; this.isBusy = false; - this.toaster.pop("success", "Bridge requested"); + this.translate.get('Bridge requested').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(error => { this.isBusy = false; console.error(error); - this.toaster.pop("error", "Error requesting bridge"); + this.translate.get('Error requesting bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -56,11 +58,11 @@ export class GitterBridgeConfigComponent extends BridgeComponent { this.gitter.unbridgeRoom(this.roomId).then(() => { this.bridge.config.link = null; this.isBusy = false; - this.toaster.pop("success", "Bridge removed"); + this.translate.get('Bridge removed').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(error => { this.isBusy = false; console.error(error); - this.toaster.pop("error", "Error removing bridge"); + this.translate.get('Error removing bridge').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } -} \ No newline at end of file +} diff --git a/web/app/configs/bridge/irc/irc.bridge.component.html b/web/app/configs/bridge/irc/irc.bridge.component.html index f518b15..2d400c4 100644 --- a/web/app/configs/bridge/irc/irc.bridge.component.html +++ b/web/app/configs/bridge/irc/irc.bridge.component.html @@ -2,18 +2,16 @@
- Add an IRC channel + {{'Add an IRC channel' | translate}}
- Bridging a channel requires authorization from a channel operator. When entering a channel below, a - bot will - join the channel to ensure it exists and has operators available. + {{'Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.' | translate}}
#
@@ -31,15 +29,15 @@
@@ -55,20 +53,20 @@
- IRC Networks + {{'IRC Networks' | translate}}
- - - + + + - + @@ -89,4 +87,4 @@ - \ No newline at end of file + diff --git a/web/app/configs/bridge/irc/irc.bridge.component.ts b/web/app/configs/bridge/irc/irc.bridge.component.ts index a02f9cb..8b56400 100644 --- a/web/app/configs/bridge/irc/irc.bridge.component.ts +++ b/web/app/configs/bridge/irc/irc.bridge.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { BridgeComponent } from "../bridge.component"; import { FE_IrcBridgeAvailableNetworks } from "../../../shared/models/irc"; import { IrcApiService } from "../../../shared/services/integrations/irc-api.service"; +import { TranslateService } from "@ngx-translate/core"; interface IrcConfig { availableNetworks: FE_IrcBridgeAvailableNetworks; @@ -34,8 +35,9 @@ export class IrcBridgeConfigComponent extends BridgeComponent { public op: string; public pending: LocalChannel[] = []; - constructor(private irc: IrcApiService) { - super("irc"); + constructor(private irc: IrcApiService, public translate: TranslateService) { + super("irc", translate); + this.translate = translate; } private resetForm() { @@ -55,7 +57,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent { public loadOps() { if (!this.channel.trim()) { - this.toaster.pop("warning", "Please enter a channel name"); + this.translate.get('Please enter a channel name').subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } @@ -68,7 +70,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent { }).catch(err => { console.error(err); this.loadingOps = false; - this.toaster.pop("error", "Error loading channel operators"); + this.translate.get('Error loading channel operators').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -86,7 +88,7 @@ export class IrcBridgeConfigComponent extends BridgeComponent { } catch (err) { console.error(err); this.requestingBridge = false; - this.toaster.pop("error", "Failed to make the bridge an administrator", "Please ensure you are an 'Admin' for the room"); + this.translate.get(['Failed to make the bridge an administrator', 'Please ensure you are an \'Admin\' for the room']).subscribe((res: string) => {this.toaster.pop("error", res[0], res[1]); }); return; } @@ -99,11 +101,11 @@ export class IrcBridgeConfigComponent extends BridgeComponent { pending: true, }); this.resetForm(); - this.toaster.pop("success", "Link requested!", "The operator selected will have to approve the bridge for it to work"); + this.translate.get(['Link requested!', 'The operator selected will have to approve the bridge for it to work']).subscribe((res: string) => {this.toaster.pop("success", res[0], res[1]); }); }).catch(err => { console.error(err); this.requestingBridge = false; - this.toaster.pop("error", "Failed to request a link"); + this.translate.get('Failed to request a link').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -133,10 +135,10 @@ export class IrcBridgeConfigComponent extends BridgeComponent { this.isUpdating = false; const idx = this.bridge.config.links[channel.networkId].findIndex(c => c.channelName === channel.name); if (idx !== -1) this.bridge.config.links[channel.networkId].splice(idx, 1); - this.toaster.pop("success", "Link removed"); + this.translate.get('Link removed').subscribe((res: string) => {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to remove link"); + this.translate.get('Failed to remove link').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } -} \ No newline at end of file +} diff --git a/web/app/configs/bridge/slack/slack.bridge.component.html b/web/app/configs/bridge/slack/slack.bridge.component.html index fbefc54..86bedc7 100644 --- a/web/app/configs/bridge/slack/slack.bridge.component.html +++ b/web/app/configs/bridge/slack/slack.bridge.component.html @@ -2,30 +2,28 @@
- Bridge to Slack + {{'Bridge to Slack' | translate}}
- This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as - rich bridging as the new approach. It is recommended to re-create the bridge with the new process. + {{'This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn\'t support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.' | translate}}
This room is bridged to "{{ bridge.config.link.channelName }}" on Slack.

- In order to bridge Slack channels, you'll need to authorize the bridge to access your teams - and channels. Please click the button below to do so. + {{'In order to bridge Slack channels, you\'ll need to authorize the bridge to access your teams and channels. Please click the button below to do so.' | translate}}

sign in with slack @@ -33,7 +31,7 @@
@@ -31,4 +31,4 @@
- \ No newline at end of file + diff --git a/web/app/configs/bridge/telegram/telegram.bridge.component.ts b/web/app/configs/bridge/telegram/telegram.bridge.component.ts index 07870d4..d133943 100644 --- a/web/app/configs/bridge/telegram/telegram.bridge.component.ts +++ b/web/app/configs/bridge/telegram/telegram.bridge.component.ts @@ -8,6 +8,7 @@ import { CannotUnbridgeDialogContext, TelegramCannotUnbridgeComponent } from "./cannot-unbridge/cannot-unbridge.component"; +import { TranslateService } from "@ngx-translate/core"; interface TelegramConfig { puppet: { @@ -39,8 +40,9 @@ export class TelegramBridgeConfigComponent extends BridgeComponent {this.toaster.pop("success", res); }); }).catch(error => { this.isUpdating = false; console.error(error); const body = error.json ? error.json() : null; - let message = "Error bridging room"; + let message = 'Error bridging room'; if (body) { - if (body["dim_errcode"] === "CHAT_ALREADY_BRIDGED") message = "That Telegram chat is already bridged to another room"; - if (body["dim_errcode"] === "ROOM_ALREADY_BRIDGED") message = "This room is already bridged to a Telegram chat"; - if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = "The Telegram bot has not been invited to the chat"; - if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = "You do not have permission to bridge that chat"; - } - this.toaster.pop("error", message); + if (body["dim_errcode"] === "CHAT_ALREADY_BRIDGED") message = 'That Telegram chat is already bridged to another room'; + if (body["dim_errcode"] === "ROOM_ALREADY_BRIDGED") message = 'This room is already bridged to a Telegram chat'; + if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = 'The Telegram bot has not been invited to the chat'; + if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = 'You do not have permission to bridge that chat'; + } + this.translate.get(message).subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -126,18 +128,17 @@ export class TelegramBridgeConfigComponent extends BridgeComponent {this.toaster.pop("success", res); }); }).catch(error => { this.isUpdating = false; console.error(error); - const body = error.json ? error.json() : null; - let message = "Error removing bridge"; + let message = 'Error removing bridge'; if (body) { - if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = "The Telegram bot has not been invited to the chat"; - if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = "You do not have permission to unbridge that chat"; + if (body["dim_errcode"] === "BOT_NOT_IN_CHAT") message = 'The Telegram bot has not been invited to the chat'; + if (body["dim_errcode"] === "NOT_ENOUGH_PERMISSIONS") message = 'You do not have permission to unbridge that chat'; } - this.toaster.pop("error", message); + this.translate.get(message).subscribe((res: string) => {this.toaster.pop("error", res); }); }); } -} \ No newline at end of file +} diff --git a/web/app/configs/bridge/webhooks/webhooks.bridge.component.html b/web/app/configs/bridge/webhooks/webhooks.bridge.component.html index a8ce37f..332635d 100644 --- a/web/app/configs/bridge/webhooks/webhooks.bridge.component.html +++ b/web/app/configs/bridge/webhooks/webhooks.bridge.component.html @@ -2,17 +2,17 @@
- Add a new webhook + {{'Add a new webhook' | translate}}
@@ -26,25 +26,25 @@
- + - + - + - + @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/web/app/configs/bridge/webhooks/webhooks.bridge.component.ts b/web/app/configs/bridge/webhooks/webhooks.bridge.component.ts index d9d4132..cc3d25f 100644 --- a/web/app/configs/bridge/webhooks/webhooks.bridge.component.ts +++ b/web/app/configs/bridge/webhooks/webhooks.bridge.component.ts @@ -3,6 +3,7 @@ import { BridgeComponent } from "../bridge.component"; import { FE_Webhook } from "../../../shared/models/webhooks"; import { WebhooksApiService } from "../../../shared/services/integrations/webhooks-api.service"; import { ScalarClientApiService } from "../../../shared/services/scalar/scalar-client-api.service"; +import { TranslateService } from "@ngx-translate/core"; interface WebhooksConfig { webhooks: FE_Webhook[]; @@ -18,8 +19,8 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent {this.toaster.pop("error", res); }); return; } } @@ -40,11 +41,11 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); this.isBusy = false; - this.toaster.pop("error", "Error creating webhook"); + this.translate.get('Error creating webhook').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -54,11 +55,11 @@ export class WebhooksBridgeConfigComponent extends BridgeComponent {this.toaster.pop("success", res); }); }).catch(err => { console.error(err); this.isBusy = false; - this.toaster.pop("error", "Error deleting webhook"); + this.translate.get('Error deleting webhook').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } -} \ No newline at end of file +} diff --git a/web/app/configs/complex-bot/complex-bot.component.ts b/web/app/configs/complex-bot/complex-bot.component.ts index c463b98..bd82eb3 100644 --- a/web/app/configs/complex-bot/complex-bot.component.ts +++ b/web/app/configs/complex-bot/complex-bot.component.ts @@ -6,6 +6,7 @@ import { IntegrationsApiService } from "../../shared/services/integrations/integ import { ToasterService } from "angular2-toaster"; import { ServiceLocator } from "../../shared/registry/locator.service"; import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service"; +import { TranslateService } from "@ngx-translate/core"; export class ComplexBotComponent implements OnInit, OnDestroy { @@ -22,7 +23,7 @@ export class ComplexBotComponent implements OnInit, OnDestroy { protected route = ServiceLocator.injector.get(ActivatedRoute); protected scalarClientApi = ServiceLocator.injector.get(ScalarClientApiService); - constructor(private integrationType: string) { + constructor(private integrationType: string, public translate: TranslateService) { this.isLoading = true; this.isUpdating = false; } @@ -50,21 +51,21 @@ export class ComplexBotComponent implements OnInit, OnDestroy { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Failed to load configuration"); + this.translate.get("Failed to load configuration").subscribe((res: string) => {this.toaster.pop("error", res); }); }); } public save(): void { this.isUpdating = true; this.integrationsApi.setIntegrationConfiguration("complex-bot", this.integrationType, this.roomId, this.newConfig).then(() => { - this.toaster.pop("success", "Configuration updated"); + this.translate.get("Configuration updated").subscribe((res: string) => {this.toaster.pop("success", res); }); this.bot.config = this.newConfig; this.newConfig = JSON.parse(JSON.stringify(this.bot.config)); this.isUpdating = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Error updating configuration"); + this.translate.get("Error updating configuration").subscribe((res: string) => {this.toaster.pop("error", res); }); this.isUpdating = false; }); } -} \ No newline at end of file +} diff --git a/web/app/configs/complex-bot/rss/rss.complex-bot.component.html b/web/app/configs/complex-bot/rss/rss.complex-bot.component.html index aae40ee..b41650a 100644 --- a/web/app/configs/complex-bot/rss/rss.complex-bot.component.html +++ b/web/app/configs/complex-bot/rss/rss.complex-bot.component.html @@ -2,7 +2,7 @@
- Feeds + {{'Feeds' | translate}}
@@ -10,8 +10,8 @@
- - + + @@ -22,7 +22,7 @@ @@ -38,7 +38,7 @@ @@ -48,11 +48,11 @@
ChannelNetworkActions{{'Channel' | translate}}{{'Network' | translate}}{{'Actions' | translate}}
No bridged channels{{'No bridged channels' | translate}}
@@ -80,7 +78,7 @@
NameType{{'Type' | translate}} URLActions{{'Actions' | translate}}
No webhooks{{'No webhooks' | translate}}
{{ hook.label }}No name{{'No name' | translate}} {{ hook.type }} {{ hook.url }}
URLAdded byActions{{'Added by' | translate}}{{'Actions' | translate}}
- \ No newline at end of file + diff --git a/web/app/configs/complex-bot/rss/rss.complex-bot.component.ts b/web/app/configs/complex-bot/rss/rss.complex-bot.component.ts index 0dfe578..f1ade30 100644 --- a/web/app/configs/complex-bot/rss/rss.complex-bot.component.ts +++ b/web/app/configs/complex-bot/rss/rss.complex-bot.component.ts @@ -1,6 +1,7 @@ import { ComplexBotComponent } from "../complex-bot.component"; import { Component } from "@angular/core"; import { SessionStorage } from "../../../shared/SessionStorage"; +import { TranslateService } from "@ngx-translate/core"; interface RssConfig { feeds: { @@ -24,13 +25,14 @@ export class RssComplexBotConfigComponent extends ComplexBotComponent public newFeedUrl = ""; - constructor() { - super("rss"); + constructor(public translate: TranslateService) { + super("rss", translate); + this.translate = translate; } public addFeed(): void { if (!this.newFeedUrl.trim()) { - this.toaster.pop('warning', 'Please enter a feed URL'); + this.translate.get('Please enter a feed URL').subscribe((res: string) => {this.toaster.pop('warning', res); }); return; } @@ -63,4 +65,4 @@ export class RssComplexBotConfigComponent extends ComplexBotComponent super.save(); } -} \ No newline at end of file +} diff --git a/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.html b/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.html index 9dab556..335a90e 100644 --- a/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.html +++ b/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.html @@ -2,50 +2,49 @@
- .travis.yml configuration and template information + {{'.travis.yml configuration and template information' | translate}}

- The following section needs to be added to your .travis.yml file in your repositories: + {{'The following section needs to be added to your' | translate}} .travis.yml {{'file in your repositories:' | translate}}

{{ travisYaml }}

- The following variables can be used in your template. This template is used to post a message to the - room when your webhook is activated. + {{'The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.' | translate}}

    -
  • {{ '%{repository_slug}' }} - The repository identifier (eg: "matrix-org/synapse")
  • -
  • {{ '%{repository_name}' }} - The repository name (eg: "synapse")
  • -
  • {{ '%{build_number}' }} - The build number
  • -
  • {{ '%{build_id}' }} - The build ID
  • -
  • {{ '%{branch}' }} - The branch name
  • -
  • {{ '%{commit}' }} - A short version of the commit SHA
  • -
  • {{ '%{commit_subject}' }} - The first line of the commit message
  • -
  • {{ '%{commit_message}' }} - The full commit message
  • -
  • {{ '%{author}' }} - The author of the commit
  • -
  • {{ '%{result}' }} - The result of the build
  • -
  • {{ '%{message}' }} - The message from Travis CI about the build
  • -
  • {{ '%{duration}' }} - The total duration of all builds in the matrix
  • -
  • {{ '%{elapsed_timed}' }} - The time it took to run the build
  • -
  • {{ '%{compare_url}' }} - A URL to see the changes which triggered the build
  • -
  • {{ '%{build_url}' }} - A URL to see the build information
  • +
  • {{ '%{repository_slug}' }} - {{'The repository identifier' | translate}} (eg: "matrix-org/synapse")
  • +
  • {{ '%{repository_name}' }} - {{'The repository name' | translate}} (eg: "synapse")
  • +
  • {{ '%{build_number}' }} - {{'The build number' | translate}}
  • +
  • {{ '%{build_id}' }} - {{'The build ID' | translate}}
  • +
  • {{ '%{branch}' }} - {{'The branch name' | translate}}
  • +
  • {{ '%{commit}' }} - {{'A short version of the commit SHA' | translate}}
  • +
  • {{ '%{commit_subject}' }} - {{'The first line of the commit message' | translate}}
  • +
  • {{ '%{commit_message}' }} - {{'The full commit message' | translate}}
  • +
  • {{ '%{author}' }} - {{'The author of the commit' | translate}}
  • +
  • {{ '%{result}' }} - {{'The result of the build' | translate}}
  • +
  • {{ '%{message}' }} - {{'The message from Travis CI about the build' | translate}}
  • +
  • {{ '%{duration}' }} - {{'The total duration of all builds in the matrix' | translate}}
  • +
  • {{ '%{elapsed_timed}' }} - {{'The time it took to run the build' | translate}}
  • +
  • {{ '%{compare_url}' }} - {{'A URL to see the changes which triggered the build' | translate}}
  • +
  • {{ '%{build_url}' }} - {{'A URL to see the build information' | translate}}
- Repositories + {{'Repositories' | translate}}
- - - - + + + + @@ -61,7 +60,7 @@ @@ -77,7 +76,7 @@ @@ -87,11 +86,11 @@
RepositoryTemplateAdded byActions{{'Repository' | translate}}{{'Template' | translate}}{{'Added by' | translate}}{{'Actions' | translate}}
- \ No newline at end of file + diff --git a/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.ts b/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.ts index e7d38d6..7cfae79 100644 --- a/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.ts +++ b/web/app/configs/complex-bot/travisci/travisci.complex-bot.component.ts @@ -1,6 +1,7 @@ import { ComplexBotComponent } from "../complex-bot.component"; import { Component } from "@angular/core"; import { SessionStorage } from "../../../shared/SessionStorage"; +import { TranslateService } from "@ngx-translate/core"; interface TravisCiConfig { webhookId: string; @@ -27,8 +28,9 @@ export class TravisCiComplexBotConfigComponent extends ComplexBotComponent {this.toaster.pop('warning', res); }); return; } @@ -90,4 +92,4 @@ export class TravisCiComplexBotConfigComponent extends ComplexBotComponent -
\ No newline at end of file +
diff --git a/web/app/configs/simple-bot/simple-bot.component.ts b/web/app/configs/simple-bot/simple-bot.component.ts index 658814f..c8cb89d 100644 --- a/web/app/configs/simple-bot/simple-bot.component.ts +++ b/web/app/configs/simple-bot/simple-bot.component.ts @@ -5,6 +5,7 @@ import { ScalarClientApiService } from "../../shared/services/scalar/scalar-clie import { IntegrationsApiService } from "../../shared/services/integrations/integrations-api.service"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { DialogRef } from "ngx-modialog"; +import { TranslateService } from "@ngx-translate/core"; export class SimpleBotConfigDialogContext extends BSModalContext { public bot: FE_SimpleBot; @@ -24,7 +25,9 @@ export class ConfigSimpleBotComponent { constructor(public dialog: DialogRef, private toaster: ToasterService, private scalar: ScalarClientApiService, - private integrationsApi: IntegrationsApiService) { + private integrationsApi: IntegrationsApiService, + public translate: TranslateService) { + this.translate = translate; this.bot = dialog.context.bot; this.roomId = dialog.context.roomId; @@ -41,8 +44,11 @@ export class ConfigSimpleBotComponent { this.bot._isUpdating = true; promise.then(() => { this.bot._isUpdating = false; - if (this.bot._inRoom) this.toaster.pop("success", this.bot.displayName + " was invited to the room"); - else this.toaster.pop("success", this.bot.displayName + " was removed from the room"); + if (this.bot._inRoom) { + this.translate.get('was invited to the room').subscribe((res: string) => {this.toaster.pop("success", this.bot.displayName + res); }); + } else { + this.translate.get('was removed from the room').subscribe((res: string) => {this.toaster.pop("success", this.bot.displayName + res); }); + } }).catch(err => { this.bot._inRoom = !this.bot._inRoom; // revert the status change this.bot._isUpdating = false; @@ -51,9 +57,8 @@ export class ConfigSimpleBotComponent { let errorMessage = null; if (err.json) errorMessage = err.json().error; if (err.response && err.response.error) errorMessage = err.response.error.message; - if (!errorMessage) errorMessage = "Could not update integration status"; - - this.toaster.pop("error", errorMessage); + if (!errorMessage) errorMessage = ""; + this.translate.get('Could not update integration status').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } -} \ No newline at end of file +} diff --git a/web/app/configs/stickerpicker/stickerpicker.component.html b/web/app/configs/stickerpicker/stickerpicker.component.html index c71a967..8c5b513 100644 --- a/web/app/configs/stickerpicker/stickerpicker.component.html +++ b/web/app/configs/stickerpicker/stickerpicker.component.html @@ -4,7 +4,7 @@
diff --git a/web/app/configs/stickerpicker/stickerpicker.component.ts b/web/app/configs/stickerpicker/stickerpicker.component.ts index d0640a7..e45b775 100644 --- a/web/app/configs/stickerpicker/stickerpicker.component.ts +++ b/web/app/configs/stickerpicker/stickerpicker.component.ts @@ -5,6 +5,7 @@ import { ToasterService } from "angular2-toaster"; import { MediaService } from "../../shared/services/media.service"; import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service"; import { WIDGET_STICKER_PICKER } from "../../shared/models/widget"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "stickerpicker.component.html", @@ -27,7 +28,9 @@ export class StickerpickerComponent implements OnInit { private media: MediaService, private scalarClient: ScalarClientApiService, private toaster: ToasterService, - private window: Window) { + private window: Window, + public translate?: TranslateService) { + this.translate = translate; this.isLoading = true; this.isUpdating = false; } @@ -38,7 +41,7 @@ export class StickerpickerComponent implements OnInit { this.isLoading = false; } catch (e) { console.error(e); - this.toaster.pop("error", "Failed to load sticker packs"); + this.translate.get('Failed to load sticker packs').subscribe((res: string) => {this.toaster.pop("error", res); }); } this.stickerApi.getConfig().then(config => { @@ -55,12 +58,12 @@ export class StickerpickerComponent implements OnInit { this.packs.splice(0, 0, pack); this.packUrl = ""; this.isImporting = false; - this.toaster.pop("success", "Stickerpack added"); + this.translate.get('Stickerpack added').subscribe((res: string) => {this.toaster.pop("success", res); }); this.addWidget(); }).catch(err => { console.error(err); this.isImporting = false; - this.toaster.pop("error", "Error adding stickerpack"); + this.translate.get('Error adding stickerpack').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } @@ -73,14 +76,13 @@ export class StickerpickerComponent implements OnInit { this.isUpdating = true; this.stickerApi.togglePackSelection(pack.id, pack.isSelected).then(() => { this.isUpdating = false; - this.toaster.pop("success", "Stickers updated"); - + this.translate.get('Stickers updated').subscribe((res: string) => {this.toaster.pop("success", res); }); if (this.packs.filter(p => p.isSelected).length > 0) this.addWidget(); }).catch(err => { console.error(err); pack.isSelected = !pack.isSelected; // revert change this.isUpdating = false; - this.toaster.pop("error", "Error updating stickers"); + this.translate.get('Error updating stickers').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } diff --git a/web/app/configs/widget/config-screen/config-screen.widget.component.html b/web/app/configs/widget/config-screen/config-screen.widget.component.html index 786f454..07526c0 100644 --- a/web/app/configs/widget/config-screen/config-screen.widget.component.html +++ b/web/app/configs/widget/config-screen/config-screen.widget.component.html @@ -4,7 +4,7 @@
- Add {{ widgetComponent.defaultName }} + {{ widgetComponent.defaultName | translate }} {{'Add' | translate}}
@@ -13,7 +13,7 @@
@@ -32,14 +32,14 @@
-
-
\ No newline at end of file + diff --git a/web/app/configs/widget/custom/custom.widget.component.html b/web/app/configs/widget/custom/custom.widget.component.html index f00ca1d..cd24296 100644 --- a/web/app/configs/widget/custom/custom.widget.component.html +++ b/web/app/configs/widget/custom/custom.widget.component.html @@ -1,18 +1,18 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/custom/custom.widget.component.ts b/web/app/configs/widget/custom/custom.widget.component.ts index 15951f1..0c818cc 100644 --- a/web/app/configs/widget/custom/custom.widget.component.ts +++ b/web/app/configs/widget/custom/custom.widget.component.ts @@ -1,13 +1,14 @@ import { WidgetComponent } from "../widget.component"; import { WIDGET_CUSTOM } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "custom.widget.component.html", styleUrls: ["custom.widget.component.scss"], }) export class CustomWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_CUSTOM, "Custom Widget", "generic"); + constructor(public translate: TranslateService) { + super(WIDGET_CUSTOM, "Custom Widget", "generic", translate); } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/etherpad/etherpad.widget.component.html b/web/app/configs/widget/etherpad/etherpad.widget.component.html index 7dcec02..304d10f 100644 --- a/web/app/configs/widget/etherpad/etherpad.widget.component.html +++ b/web/app/configs/widget/etherpad/etherpad.widget.component.html @@ -1,18 +1,18 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/etherpad/etherpad.widget.component.ts b/web/app/configs/widget/etherpad/etherpad.widget.component.ts index 4483b19..77f73dd 100644 --- a/web/app/configs/widget/etherpad/etherpad.widget.component.ts +++ b/web/app/configs/widget/etherpad/etherpad.widget.component.ts @@ -5,6 +5,7 @@ import { FE_EtherpadWidget } from "../../../shared/models/integration"; import { SessionStorage } from "../../../shared/SessionStorage"; import { NameService } from "../../../shared/services/name.service"; import * as url from "url"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "etherpad.widget.component.html", @@ -14,8 +15,8 @@ export class EtherpadWidgetConfigComponent extends WidgetComponent { private etherpadWidget: FE_EtherpadWidget = SessionStorage.editIntegration; - constructor(private nameService: NameService) { - super(WIDGET_ETHERPAD, "Etherpad", "generic", "etherpad", "padName"); + constructor(private nameService: NameService, public translate: TranslateService) { + super(WIDGET_ETHERPAD, "Notes", "generic", translate ,"etherpad", "padName"); } protected OnWidgetsDiscovered(widgets: EditableWidget[]): void { @@ -45,4 +46,4 @@ export class EtherpadWidgetConfigComponent extends WidgetComponent { widget.dimension.newUrl = template; widget.dimension.newName = name; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/google-calendar/gcal.widget.component.html b/web/app/configs/widget/google-calendar/gcal.widget.component.html index b7ecbbd..6213630 100644 --- a/web/app/configs/widget/google-calendar/gcal.widget.component.html +++ b/web/app/configs/widget/google-calendar/gcal.widget.component.html @@ -1,11 +1,11 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/google-calendar/gcal.widget.component.ts b/web/app/configs/widget/google-calendar/gcal.widget.component.ts index 8c2df3f..0323121 100644 --- a/web/app/configs/widget/google-calendar/gcal.widget.component.ts +++ b/web/app/configs/widget/google-calendar/gcal.widget.component.ts @@ -1,14 +1,15 @@ import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component"; import { EditableWidget, WIDGET_GOOGLE_CALENDAR } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "gcal.widget.component.html", styleUrls: ["gcal.widget.component.scss"], }) export class GoogleCalendarWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_GOOGLE_CALENDAR, "Google Calendar", DISABLE_AUTOMATIC_WRAPPING, "googleCalendar"); + constructor(public translate: TranslateService) { + super(WIDGET_GOOGLE_CALENDAR, "Google Calendar", DISABLE_AUTOMATIC_WRAPPING, translate , "googleCalendar"); } protected OnNewWidgetPrepared(widget: EditableWidget) { @@ -43,4 +44,4 @@ export class GoogleCalendarWidgetConfigComponent extends WidgetComponent { widget.dimension.newUrl = window.location.origin + "/widgets/gcal?calendarId=$shareId"; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/google-docs/gdoc.widget.component.html b/web/app/configs/widget/google-docs/gdoc.widget.component.html index 9551b14..4ca6cf9 100644 --- a/web/app/configs/widget/google-docs/gdoc.widget.component.html +++ b/web/app/configs/widget/google-docs/gdoc.widget.component.html @@ -1,11 +1,11 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/google-docs/gdoc.widget.component.ts b/web/app/configs/widget/google-docs/gdoc.widget.component.ts index a52ef53..1f3c87e 100644 --- a/web/app/configs/widget/google-docs/gdoc.widget.component.ts +++ b/web/app/configs/widget/google-docs/gdoc.widget.component.ts @@ -1,13 +1,14 @@ import { WidgetComponent } from "../widget.component"; import { WIDGET_GOOGLE_DOCS } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "gdoc.widget.component.html", styleUrls: ["gdoc.widget.component.scss"], }) export class GoogleDocsWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_GOOGLE_DOCS, "Google Doc", "generic", "googleDocs"); + constructor(public translate: TranslateService) { + super(WIDGET_GOOGLE_DOCS, "Google Doc", "generic", translate , "googleDocs"); } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/grafana/grafana.widget.component.html b/web/app/configs/widget/grafana/grafana.widget.component.html index b6397d4..25bc58f 100644 --- a/web/app/configs/widget/grafana/grafana.widget.component.html +++ b/web/app/configs/widget/grafana/grafana.widget.component.html @@ -1,19 +1,19 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/grafana/grafana.widget.component.ts b/web/app/configs/widget/grafana/grafana.widget.component.ts index 843e4ed..21e9f85 100644 --- a/web/app/configs/widget/grafana/grafana.widget.component.ts +++ b/web/app/configs/widget/grafana/grafana.widget.component.ts @@ -1,14 +1,15 @@ import { WidgetComponent } from "../widget.component"; import { EditableWidget, WIDGET_GRAFANA } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "grafana.widget.component.html", styleUrls: ["grafana.widget.component.scss"], }) export class GrafanaWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_GRAFANA, "Grafana", "generic-fullscreen", "grafana"); + constructor(public translate: TranslateService) { + super(WIDGET_GRAFANA, "Grafana", "generic-fullscreen", translate ,"grafana"); } protected OnWidgetsDiscovered(widgets: EditableWidget[]) { @@ -42,4 +43,4 @@ export class GrafanaWidgetConfigComponent extends WidgetComponent { } widget.dimension.newUrl = widget.dimension.newData.url; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/jitsi/jitsi.widget.component.html b/web/app/configs/widget/jitsi/jitsi.widget.component.html index 81675bb..c94cdda 100644 --- a/web/app/configs/widget/jitsi/jitsi.widget.component.html +++ b/web/app/configs/widget/jitsi/jitsi.widget.component.html @@ -1,11 +1,11 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/jitsi/jitsi.widget.component.ts b/web/app/configs/widget/jitsi/jitsi.widget.component.ts index 4152f97..634f1d7 100644 --- a/web/app/configs/widget/jitsi/jitsi.widget.component.ts +++ b/web/app/configs/widget/jitsi/jitsi.widget.component.ts @@ -5,6 +5,7 @@ import { FE_JitsiWidget } from "../../../shared/models/integration"; import { SessionStorage } from "../../../shared/SessionStorage"; import { NameService } from "../../../shared/services/name.service"; import * as url from "url"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "jitsi.widget.component.html", @@ -14,8 +15,8 @@ export class JitsiWidgetConfigComponent extends WidgetComponent { private jitsiWidget: FE_JitsiWidget = SessionStorage.editIntegration; - constructor(private nameService: NameService) { - super(WIDGET_JITSI, "Jitsi Video Conference", DISABLE_AUTOMATIC_WRAPPING); + constructor(private nameService: NameService, public translate: TranslateService) { + super(WIDGET_JITSI, "Jitsi Video Conference", DISABLE_AUTOMATIC_WRAPPING, translate); } protected OnWidgetsDiscovered(widgets: EditableWidget[]) { @@ -96,4 +97,4 @@ export class JitsiWidgetConfigComponent extends WidgetComponent { widget.dimension.newUrl = window.location.origin + "/widgets/jitsi" + widgetQueryString; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/spotify/spotify.widget.component.html b/web/app/configs/widget/spotify/spotify.widget.component.html index 39288f8..3008f45 100644 --- a/web/app/configs/widget/spotify/spotify.widget.component.html +++ b/web/app/configs/widget/spotify/spotify.widget.component.html @@ -1,12 +1,12 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/spotify/spotify.widget.component.ts b/web/app/configs/widget/spotify/spotify.widget.component.ts index 18774bb..ff7ae19 100644 --- a/web/app/configs/widget/spotify/spotify.widget.component.ts +++ b/web/app/configs/widget/spotify/spotify.widget.component.ts @@ -1,6 +1,7 @@ import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component"; import { EditableWidget, WIDGET_SPOTIFY } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "spotify.widget.component.html", @@ -8,8 +9,8 @@ import { Component } from "@angular/core"; }) export class SpotifyWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_SPOTIFY, "Spotify", DISABLE_AUTOMATIC_WRAPPING, "spotify"); + constructor(public translate: TranslateService) { + super(WIDGET_SPOTIFY, "Spotify", DISABLE_AUTOMATIC_WRAPPING, translate,"spotify"); } protected OnNewWidgetPrepared(widget: EditableWidget): void { @@ -27,4 +28,4 @@ export class SpotifyWidgetConfigComponent extends WidgetComponent { private setSpotifyUrl(widget: EditableWidget) { widget.dimension.newUrl = window.location.origin + "/widgets/spotify?uri=$uri"; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/tradingview/tradingview.widget.component.html b/web/app/configs/widget/tradingview/tradingview.widget.component.html index 4a01ab6..9cadad7 100644 --- a/web/app/configs/widget/tradingview/tradingview.widget.component.html +++ b/web/app/configs/widget/tradingview/tradingview.widget.component.html @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/tradingview/tradingview.widget.component.ts b/web/app/configs/widget/tradingview/tradingview.widget.component.ts index 397d57d..e9ba7f2 100644 --- a/web/app/configs/widget/tradingview/tradingview.widget.component.ts +++ b/web/app/configs/widget/tradingview/tradingview.widget.component.ts @@ -1,6 +1,7 @@ import { DISABLE_AUTOMATIC_WRAPPING, WidgetComponent } from "../widget.component"; import { EditableWidget, WIDGET_TRADINGVIEW } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "tradingview.widget.component.html", @@ -73,8 +74,8 @@ export class TradingViewWidgetConfigComponent extends WidgetComponent { {value: 'BITTREX:NEOUSDT', label: 'Neo / Tether'}, ]; - constructor() { - super(WIDGET_TRADINGVIEW, "TradingView Chart", DISABLE_AUTOMATIC_WRAPPING, "tradingView"); + constructor(public translate: TranslateService) { + super(WIDGET_TRADINGVIEW, "TradingView Chart", DISABLE_AUTOMATIC_WRAPPING, translate,"tradingView"); } protected OnNewWidgetPrepared(widget: EditableWidget): void { @@ -95,4 +96,4 @@ export class TradingViewWidgetConfigComponent extends WidgetComponent { widget.dimension.newTitle = pair ? pair.label : null; widget.dimension.newUrl = window.location.origin + "/widgets/tradingview?pair=$pair&interval=$interval"; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/twitch/twitch.widget.component.html b/web/app/configs/widget/twitch/twitch.widget.component.html index d3d9e0b..aa80a26 100644 --- a/web/app/configs/widget/twitch/twitch.widget.component.html +++ b/web/app/configs/widget/twitch/twitch.widget.component.html @@ -1,11 +1,11 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/twitch/twitch.widget.component.ts b/web/app/configs/widget/twitch/twitch.widget.component.ts index 29908dd..ff899ce 100644 --- a/web/app/configs/widget/twitch/twitch.widget.component.ts +++ b/web/app/configs/widget/twitch/twitch.widget.component.ts @@ -1,14 +1,15 @@ import { WidgetComponent } from "../widget.component"; import { EditableWidget, WIDGET_TWITCH } from "../../../shared/models/widget"; import { Component } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "twitch.widget.component.html", styleUrls: ["twitch.widget.component.scss"], }) export class TwitchWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_TWITCH, "Twitch Livestream", "video", "twitch"); + constructor(public translate: TranslateService) { + super(WIDGET_TWITCH, "Twitch Livestream", "video", translate ,"twitch"); } protected OnNewWidgetPrepared(widget: EditableWidget) { @@ -40,4 +41,4 @@ export class TwitchWidgetConfigComponent extends WidgetComponent { widget.dimension.newUrl = "https://player.twitch.tv/?channel=$channelName"; widget.dimension.newTitle = widget.dimension.newData.channelName; } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/widget.component.ts b/web/app/configs/widget/widget.component.ts index 9df9330..cd959bb 100644 --- a/web/app/configs/widget/widget.component.ts +++ b/web/app/configs/widget/widget.component.ts @@ -4,6 +4,7 @@ import { ScalarClientApiService } from "../../shared/services/scalar/scalar-clie import { ServiceLocator } from "../../shared/registry/locator.service"; import { SessionStorage } from "../../shared/SessionStorage"; import { OnInit } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; const SCALAR_WIDGET_LINKS = [ "https://scalar-staging.riot.im/scalar/api/widgets/__TYPE__.html?__PNAME__=", @@ -33,8 +34,10 @@ export class WidgetComponent implements OnInit { constructor(private widgetTypes: string[], public defaultName: string, private wrapperId = "generic", + public translate: TranslateService, private scalarWrapperId = null, private scalarWrapperUrlParamName = "url") { + this.translate = translate; this.isLoading = true; this.isUpdating = false; } @@ -258,12 +261,12 @@ export class WidgetComponent implements OnInit { try { this.OnWidgetBeforeAdd(this.newWidget); } catch (error) { - this.toaster.pop("warning", error.message); + this.translate.get(error.message).subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } if (!this.newWidget.dimension.newUrl || this.newWidget.dimension.newUrl.trim().length === 0) { - this.toaster.pop("warning", "Please enter a URL for the widget"); + this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {this.toaster.pop("warning", res ); }); return; } @@ -276,7 +279,7 @@ export class WidgetComponent implements OnInit { this.isUpdating = false; this.OnWidgetAfterAdd(this.newWidget); this.prepareNewWidget(); - this.toaster.pop("success", "Widget added!"); + this.translate.get("Widget added!").subscribe((res: string) => {this.toaster.pop("success", res); }); }) .catch(err => { this.isUpdating = false; @@ -300,7 +303,7 @@ export class WidgetComponent implements OnInit { } if (!widget.dimension.newUrl || widget.dimension.newUrl.trim().length === 0) { - this.toaster.pop("warning", "Please enter a URL for the widget"); + this.translate.get("Please enter a URL for the widget").subscribe((res: string) => {this.toaster.pop("warning", res); }); return; } @@ -311,7 +314,7 @@ export class WidgetComponent implements OnInit { .then(() => { this.isUpdating = false; this.OnWidgetAfterEdit(widget); - this.toaster.pop("success", "Widget updated!"); + this.translate.get("Widget updated!").subscribe((res: string) => {this.toaster.pop("success", res); }); }) .catch(err => { this.isUpdating = false; @@ -333,7 +336,7 @@ export class WidgetComponent implements OnInit { .then(() => { this.isUpdating = false; this.OnWidgetAfterDelete(widget); - this.toaster.pop("success", "Widget deleted!"); + this.translate.get("Widget deleted!").subscribe((res: string) => {this.toaster.pop("success", res); }); }) .catch(err => { this.isUpdating = false; @@ -434,4 +437,4 @@ export class WidgetComponent implements OnInit { protected OnWidgetAfterDelete(_widget: EditableWidget): void { // Component hook } -} \ No newline at end of file +} diff --git a/web/app/configs/widget/youtube/youtube.widget.component.html b/web/app/configs/widget/youtube/youtube.widget.component.html index 5dc53b7..dec8bf7 100644 --- a/web/app/configs/widget/youtube/youtube.widget.component.html +++ b/web/app/configs/widget/youtube/youtube.widget.component.html @@ -1,11 +1,11 @@ - \ No newline at end of file + diff --git a/web/app/configs/widget/youtube/youtube.widget.component.ts b/web/app/configs/widget/youtube/youtube.widget.component.ts index 28f8d15..0b38f94 100644 --- a/web/app/configs/widget/youtube/youtube.widget.component.ts +++ b/web/app/configs/widget/youtube/youtube.widget.component.ts @@ -4,14 +4,16 @@ import { Component } from "@angular/core"; import * as embed from "embed-video"; import * as $ from "jquery"; import * as url from "url"; +import { TranslateService } from "@ngx-translate/core"; @Component({ templateUrl: "youtube.widget.component.html", styleUrls: ["youtube.widget.component.scss"], }) export class YoutubeWidgetConfigComponent extends WidgetComponent { - constructor() { - super(WIDGET_YOUTUBE, "Video", "video", "youtube"); + constructor(public translate: TranslateService) { + super(WIDGET_YOUTUBE, "Video", "video", translate,"youtube"); + this.translate = translate; } protected OnNewWidgetPrepared(widget: EditableWidget) { @@ -45,12 +47,12 @@ export class YoutubeWidgetConfigComponent extends WidgetComponent { private setVideoUrl(widget: EditableWidget) { if (!widget.dimension.newData.videoUrl || widget.dimension.newData.videoUrl.trim().length === 0) { - throw new Error("Please enter a video URL"); + this.translate.get('Please enter a video URL').subscribe((res: string) => {throw new Error(res); }); } const videoUrl = this.getRealVideoUrl(widget.dimension.newData.videoUrl); if (!videoUrl) { - throw new Error("Please enter a YouTube, Vimeo, or DailyMotion video URL"); + this.translate.get('Please enter a YouTube, Vimeo, or DailyMotion video URL').subscribe((res: string) => {throw new Error(res); }); } widget.dimension.newUrl = videoUrl; @@ -83,4 +85,4 @@ export class YoutubeWidgetConfigComponent extends WidgetComponent { return videoUrl; } -} \ No newline at end of file +} diff --git a/web/app/home/home.component.html b/web/app/home/home.component.html index 20c63ea..6b2a893 100644 --- a/web/app/home/home.component.html +++ b/web/app/home/home.component.html @@ -1,12 +1,12 @@
-

An open source integration manager for Matrix

+

{{'An open source integration manager for Matrix' | translate}}

@@ -14,10 +14,10 @@
-

Try it out or run your own

+

{{'Try it out or' | translate}} {{'run your own' | translate}}

- Visit element.t2host.io and log in with your Matrix account - or point your Element config.json at our servers: + {{'Visit' | translate}} element.t2host.io + {{'and log in with your Matrix account or point your Element' | translate}} config.json {{'at our servers:' | translate}}

{{ integrationsConfig }}
@@ -29,21 +29,21 @@
-

Widgets

-

Add utility for everyone in your room by embedding an application.

+

{{'Widgets' | translate}}

+

{{'Add utility for everyone in your room by embedding an application.' | translate}}

- Jitsi +
- Etherpad + {{'Notes' | translate}}
- TradingView +
@@ -67,11 +67,11 @@
- Google Calendar + {{'Google Calendar' | translate}}
- Custom Widget + {{'Custom Widget' | translate}}
@@ -80,7 +80,7 @@

Bots

-

Bots bring entertainment or productivity to the room. They're here to help at your command.

+

{{'Bots bring entertainment or productivity to the room. They\'re here to help at your command.' | translate}}

@@ -93,27 +93,27 @@
- Guggy + {{'Guggy' | translate}}
- Giphy + {{'Giphy' | translate}}
- Imgur + {{'Imgur' | translate}}
- Google Image Search + {{'Google Image Search' | translate}}
- Wikipedia + {{'Wikipedia' | translate}}
- Travis CI + {{'Travis CI' | translate}}
@@ -121,15 +121,15 @@
- RSS Notifications + {{'RSS Notifications' | translate}}
- Echo + {{'Echo' | translate}}
- Custom Bots + {{'Custom Bots' | translate}}
@@ -138,7 +138,7 @@

Bridges

-

Bring the outside world into your room with bridges.

+

{{'Bring the outside world into your room with bridges.' | translate}}

@@ -167,25 +167,25 @@
-

Stickers

-

Have some fun and post a sticker.

+

{{'Stickers' | translate}}

+

{{'Have some fun and post a sticker.' | translate}}

- Huskies + {{'Huskies' | translate}}
- Cats + {{'Cats' | translate}}
- Cat Faces + {{'Cat Faces' | translate}}
- Loading Artist + {{'Loading Artist' | translate}}
@@ -194,7 +194,7 @@
diff --git a/web/app/page-header/page-header.component.ts b/web/app/page-header/page-header.component.ts index 2bbe7cb..30d659b 100644 --- a/web/app/page-header/page-header.component.ts +++ b/web/app/page-header/page-header.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; import { ActivatedRoute, NavigationEnd, PRIMARY_OUTLET, Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; @Component({ selector: "my-page-header", @@ -10,7 +11,8 @@ export class PageHeaderComponent { public pageName: string; - constructor(private router: Router, private activatedRoute: ActivatedRoute) { + constructor(private router: Router, private activatedRoute: ActivatedRoute, public translate: TranslateService) { + this.translate = translate; this.router.events.filter(ev => ev instanceof NavigationEnd).subscribe((ev: NavigationEnd) => { let currentRoute = this.activatedRoute.root; let url = ""; @@ -18,6 +20,7 @@ export class PageHeaderComponent { while (currentRoute.children.length > 0) { let children = currentRoute.children; children.forEach(route => { + if (route.snapshot.data['breadcrumb']){this.translate.get(route.snapshot.data['breadcrumb']).subscribe((res: string) => {route.snapshot.data['breadcrumb'] = res}); } currentRoute = route; url += "/" + route.snapshot.url.map(s => s.path).join("/"); if (route.outlet !== PRIMARY_OUTLET) return; diff --git a/web/app/riot/riot-home/home.component.html b/web/app/riot/riot-home/home.component.html index 72b42a5..ec7f4d2 100644 --- a/web/app/riot/riot-home/home.component.html +++ b/web/app/riot/riot-home/home.component.html @@ -6,29 +6,23 @@
-
- Looking for your sticker packs? Click here. -
+
{{'Looking for your sticker packs?' | translate}} {{'Click here' | translate}}.
-

This room is encrypted

- Integrations are not encrypted! - This means that some information about yourself and the - room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display - name, your username, your avatar, information about Element, and other similar details. Add integrations - with caution. +

{{'This room is encrypted' | translate}}

+ {{'Integrations are not encrypted!' | translate}} + {{'This means that some information about yourself and the room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display name, your username, your avatar, information about Element, and other similar details. Add integrations with caution.' | translate}}
-

This room is encrypted

- There are currently no integrations which support encrypted rooms. Sorry about that! +

{{'This room is encrypted' | translate}}

+ {{'There are currently no integrations which support encrypted rooms. Sorry about that!' | translate}}
-

No integrations available

- This room does not have any compatible integrations. Please contact the server owner if you're seeing - this message. +

{{'No integrations available' | translate}}

+ {{'This room does not have any compatible integrations. Please contact the server owner if you\'re seeing this message.' | translate}}
diff --git a/web/app/riot/riot-home/home.component.ts b/web/app/riot/riot-home/home.component.ts index 45a8579..7959246 100644 --- a/web/app/riot/riot-home/home.component.ts +++ b/web/app/riot/riot-home/home.component.ts @@ -12,6 +12,7 @@ import { Modal, overlayConfigFactory } from "ngx-modialog"; import { ConfigSimpleBotComponent, SimpleBotConfigDialogContext } from "../../configs/simple-bot/simple-bot.component"; import { ToasterService } from "angular2-toaster"; import { StickerApiService } from "../../shared/services/integrations/sticker-api.service"; +import { TranslateService } from "@ngx-translate/core"; const CATEGORY_MAP = { "Widgets": ["widget"], @@ -46,7 +47,9 @@ export class RiotHomeComponent { private adminApi: AdminApiService, private router: Router, private modal: Modal, - private toaster: ToasterService) { + private toaster: ToasterService, + public translate: TranslateService) { + this.translate = translate; let params: any = this.activatedRoute.snapshot.queryParams; this.requestedScreen = params.screen; @@ -64,7 +67,7 @@ export class RiotHomeComponent { console.error("Unable to load Dimension. Missing room ID or scalar token."); this.isError = true; this.isLoading = false; - this.errorMessage = "Unable to load Dimension - missing room ID or token."; + this.translate.get('Unable to load Dimension - missing room ID or token.').subscribe((res: string) => {this.errorMessage = res}); } else { this.roomId = params.room_id; SessionStorage.scalarToken = params.scalar_token; @@ -77,7 +80,7 @@ export class RiotHomeComponent { console.error("No user returned for token. Is the token registered in Dimension?"); this.isError = true; this.isLoading = false; - this.errorMessage = "Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!"; + this.translate.get('Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!').subscribe((res: string) => {this.errorMessage = res}); } else { this.userId = userId; console.log("Scalar token belongs to " + userId); @@ -88,7 +91,7 @@ export class RiotHomeComponent { console.error(err); this.isError = true; this.isLoading = false; - this.errorMessage = "Unable to communicate with Dimension due to an unknown error."; + this.translate.get('Unable to communicate with Dimension due to an unknown error.').subscribe((res: string) => {this.errorMessage = res}); }); } } @@ -131,8 +134,10 @@ export class RiotHomeComponent { public modifyIntegration(integration: FE_Integration) { if (!integration._isSupported) { console.log(this.userId + " tried to modify " + integration.displayName + " with error: " + integration._notSupportedReason); - const reason = integration.category === "widget" ? "You do not appear to have permission to modify widgets in this room" : integration._notSupportedReason; - this.toaster.pop("error", reason); + this.translate.get('You do not appear to have permission to modify widgets in this room').subscribe((res: string) => { + const reason = integration.category === "widget" ? res : integration._notSupportedReason; + this.toaster.pop("error", reason); + }); return; } @@ -189,7 +194,7 @@ export class RiotHomeComponent { console.error(err); this.isError = true; this.isLoading = false; - this.errorMessage = "Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server."; + this.translate.get('Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server.').subscribe((res: string) => {this.errorMessage = res}); }); this.stickerApi.getPacks().then(packs => { @@ -235,7 +240,7 @@ export class RiotHomeComponent { private async updateIntegrationState(integration: FE_Integration) { if (!integration.isOnline) { integration._isSupported = false; - integration._notSupportedReason = "This integration is offline or unavailable"; + this.translate.get('This integration is offline or unavailable').subscribe((res: string) => {integration._notSupportedReason = res}); return; } @@ -265,34 +270,55 @@ export class RiotHomeComponent { case "publicRoom": return this.scalar.getJoinRule(this.roomId).then(payload => { if (!payload.response) { - return Promise.reject("Could not communicate with Element"); + let message: string; + this.translate.get('Could not communicate with Element').subscribe((res: string) => {message = res}); + return Promise.reject(message); } const isPublic = payload.response.join_rule === "public"; if (isPublic !== requirement.expectedValue) { - return Promise.reject("The room must be " + (isPublic ? "non-public" : "public") + " to use this integration"); + let message: string; + let message1: string; + this.translate.get(['The room must be', 'to use this integration']).subscribe((res: string) => {message = res[0]; message1 = res[1]}); + return Promise.reject(message + (isPublic ? "non-public" : "public") + message1); } else return Promise.resolve(); }); case "canSendEventTypes": const processPayload = payload => { const response = payload.response; if (response === true) return Promise.resolve(); - if (response.error || response.error.message) - return Promise.reject("You cannot modify widgets in this room"); - return Promise.reject("Error communicating with Element"); + if (response.error || response.error.message){ + let message: string; + this.translate.get('You cannot modify widgets in this room').subscribe((res: string) => {message = res}); + return Promise.reject(message); + } + let message: string; + this.translate.get('Error communicating with Element').subscribe((res: string) => {message = res}); + return Promise.reject(message); }; let promiseChain = Promise.resolve(); requirement.argument.forEach(e => promiseChain = promiseChain.then(() => this.scalar.canSendEvent(this.roomId, e.type, e.isState).then(processPayload).catch(processPayload))); return promiseChain.then(() => { - if (!requirement.expectedValue) return Promise.reject("Expected to not be able to send specific event types"); + if (!requirement.expectedValue) { + let message: string; + this.translate.get('Expected to not be able to send specific event types').subscribe((res: string) => {message = res}); + return Promise.reject(message); + } }).catch(err => { console.error(err); - if (requirement.expectedValue) return Promise.reject("Expected to be able to send specific event types"); + if (requirement.expectedValue) { + let message: string; + this.translate.get('Expected to be able to send specific event types').subscribe((res: string) => {message = res}); + return Promise.reject(message); + } }); case "userInRoom": // TODO: Implement default: - return Promise.reject("Requirement '" + requirement.condition + "' not found"); + let message: string; + let message1: string; + this.translate.get(['Requirement', 'not found']).subscribe((res: string) => {message = res[0]; message1 = res[1]}); + return Promise.reject(message + requirement.condition + message1); } } } diff --git a/web/app/shared/directives/screenshot-capable.directive.ts b/web/app/shared/directives/screenshot-capable.directive.ts index ef0bc6d..32ff125 100644 --- a/web/app/shared/directives/screenshot-capable.directive.ts +++ b/web/app/shared/directives/screenshot-capable.directive.ts @@ -3,6 +3,7 @@ import { Subscription } from "rxjs/Subscription"; import { ScalarWidgetApi } from "../services/scalar/scalar-widget.api"; import { ScalarToWidgetRequest } from "../models/scalar-widget-actions"; import * as domtoimage from "dom-to-image"; +import { TranslateService } from "@ngx-translate/core"; @Directive({ selector: "[myScreenshotCapable]", @@ -11,7 +12,8 @@ export class ScreenshotCapableDirective implements OnInit, OnDestroy { private widgetApiSubscription: Subscription; - constructor(private el: ElementRef) { + constructor(private el: ElementRef, public translate: TranslateService) { + this.translate = translate; } @@ -28,7 +30,7 @@ export class ScreenshotCapableDirective implements OnInit, OnDestroy { private takeScreenshot(request: ScalarToWidgetRequest) { if (this.el.nativeElement.tagName === "IFRAME") { console.error("Attempted to take a screenshot of an iframe"); - ScalarWidgetApi.replyError(request, new Error("Cannot take screenshot of iframe"), "Failed to take screenshot: iframe not supported"); + this.translate.get('Failed to take screenshot: iframe not supported').subscribe((res: string) => {ScalarWidgetApi.replyError(request, new Error("Cannot take screenshot of iframe"), res); }); } else { domtoimage.toBlob(this.el.nativeElement).then(b => { if (!b) { @@ -38,7 +40,7 @@ export class ScreenshotCapableDirective implements OnInit, OnDestroy { ScalarWidgetApi.replyScreenshot(request, b); }).catch(error => { console.error(error); - ScalarWidgetApi.replyError(request, error, "Failed to take screenshot"); + this.translate.get('Failed to take screenshot').subscribe((res: string) => {ScalarWidgetApi.replyError(request, error, res); }); }); } } diff --git a/web/app/shared/models/integration.ts b/web/app/shared/models/integration.ts index a841e4d..755c769 100644 --- a/web/app/shared/models/integration.ts +++ b/web/app/shared/models/integration.ts @@ -92,4 +92,4 @@ export interface FE_IntegrationRequirement { condition: "publicRoom" | "canSendEventTypes" | "userInRoom"; argument: any; expectedValue: any; -} \ No newline at end of file +} diff --git a/web/app/widget-wrappers/generic/generic.component.html b/web/app/widget-wrappers/generic/generic.component.html index a78bcef..e0b5d12 100644 --- a/web/app/widget-wrappers/generic/generic.component.html +++ b/web/app/widget-wrappers/generic/generic.component.html @@ -5,9 +5,9 @@

-

Sorry, this content cannot be embedded

+

{{'Sorry, this content cannot be embedded' | translate}}

-
\ No newline at end of file +
diff --git a/web/app/widget-wrappers/jitsi/jitsi.component.html b/web/app/widget-wrappers/jitsi/jitsi.component.html index 65c586d..41efbdb 100644 --- a/web/app/widget-wrappers/jitsi/jitsi.component.html +++ b/web/app/widget-wrappers/jitsi/jitsi.component.html @@ -6,8 +6,8 @@

Jitsi Video Conference

- \ No newline at end of file + diff --git a/web/app/widget-wrappers/manager-test/manager-test.component.html b/web/app/widget-wrappers/manager-test/manager-test.component.html index f4cc133..2d2dab8 100644 --- a/web/app/widget-wrappers/manager-test/manager-test.component.html +++ b/web/app/widget-wrappers/manager-test/manager-test.component.html @@ -4,12 +4,12 @@
- You + {{'You' | translate}}
- Integrations + {{'Integrations' | translate}}
@@ -18,16 +18,14 @@

- Your client is too old to use this widget. Try upgrading your client to the latest available version, - or contact the author to try and diagnose the problem. Your client needs to support OpenID information - exchange. + {{'Your client is too old to use this widget. Try upgrading your client to the latest available version, or contact the author to try and diagnose the problem. Your client needs to support OpenID information exchange.' | translate}}

{{message}}

- \ No newline at end of file + diff --git a/web/app/widget-wrappers/manager-test/manager-test.component.ts b/web/app/widget-wrappers/manager-test/manager-test.component.ts index ec344c0..c85b136 100644 --- a/web/app/widget-wrappers/manager-test/manager-test.component.ts +++ b/web/app/widget-wrappers/manager-test/manager-test.component.ts @@ -3,6 +3,7 @@ import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api" import { CapableWidget, WIDGET_API_VERSION_OPENID } from "../capable-widget"; import { ActivatedRoute } from "@angular/router"; import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service"; +import { TranslateService } from "@ngx-translate/core"; @Component({ selector: "my-reauth-example-widget-wrapper", @@ -20,19 +21,21 @@ export class ManagerTestWidgetWrapperComponent extends CapableWidget implements public selfState = this.STATE_NEUTRAL; public managerState = this.STATE_NEUTRAL; public homeserverState = this.STATE_NEUTRAL; - public message = "Click the button to test your connection. This may cause your client to ask if it " + - "is okay to share your identity with the widget - this is required to test your connection to your " + - "homeserver."; + public message: string; constructor(activatedRoute: ActivatedRoute, private scalarApi: ScalarServerApiService, - private changeDetector: ChangeDetectorRef) { + private changeDetector: ChangeDetectorRef, + public translate: TranslateService) { super(); - + this.translate = translate; + this.translate.get('Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.').subscribe((res: string) => {this.message = res}); const params: any = activatedRoute.snapshot.queryParams; ScalarWidgetApi.widgetId = params.widgetId; } + + protected onSupportedVersionsFound(): void { super.onSupportedVersionsFound(); this.isSupported = this.doesSupportAtLeastVersion(WIDGET_API_VERSION_OPENID); @@ -47,44 +50,41 @@ export class ManagerTestWidgetWrapperComponent extends CapableWidget implements this.selfState = this.STATE_NEUTRAL; this.managerState = this.STATE_NEUTRAL; this.homeserverState = this.STATE_NEUTRAL; - - this.message = "Please accept the prompt to verify your identity."; + this.translate.get('Please accept the prompt to verify your identity.').subscribe((res: string) => {this.message = res}); this.isBusy = true; const response = await this.getOpenIdInfo(); if (response.blocked) { this.isBusy = false; this.selfState = this.STATE_ERROR; - this.message = "You have blocked this widget from verifying your identity."; + this.translate.get('You have blocked this widget from verifying your identity.').subscribe((res: string) => {this.message = res}); return; } this.selfState = this.STATE_OK; - this.message = "Checking connectivity to integration manager..."; + this.translate.get('Checking connectivity to integration manager...').subscribe((res: string) => {this.message = res}); try { await this.scalarApi.ping(); this.managerState = this.STATE_OK; - this.message = "Checking connectivity to homeserver..."; + this.translate.get('Checking connectivity to homeserver...').subscribe((res: string) => {this.message = res}); } catch (e) { console.error(e); this.isBusy = false; this.managerState = this.STATE_ERROR; - this.message = "Error checking if the integration manager is alive. This usually means that the manager " + - "which served this widget has gone offline."; + this.translate.get('Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.').subscribe((res: string) => {this.message = res}); return; } try { await this.scalarApi.register(response.openId); this.homeserverState = this.STATE_OK; - this.message = "You're all set! Click the button below to re-run the test."; + this.translate.get('You\'re all set! Click the button below to re-run the test.').subscribe((res: string) => {this.message = res}); this.isBusy = false; } catch (e) { this.isBusy = false; this.homeserverState = this.STATE_ERROR; - this.message = "Error contacting homeserver. This usually means your federation setup is incorrect, or " + - "your homeserver is offline. Consult your homeserver's documentation for how to set up federation."; + this.translate.get('Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver\'s documentation for how to set up federation.').subscribe((res: string) => {this.message = res}); } } } diff --git a/web/app/widget-wrappers/reauth-example/reauth-example.component.html b/web/app/widget-wrappers/reauth-example/reauth-example.component.html index 0b21bfe..8dabaa2 100644 --- a/web/app/widget-wrappers/reauth-example/reauth-example.component.html +++ b/web/app/widget-wrappers/reauth-example/reauth-example.component.html @@ -1,14 +1,14 @@
-

User ID: {{userId}}

+

{{'User ID:' | translate}} {{userId}}

{{stateMessage}}

-

You have blocked this widget from receiving credentials.

-

An error has occurred - see logs for details

+

{{'You have blocked this widget from receiving credentials.' | translate}}

+

{{'An error has occurred - see logs for details' | translate}}

Widget ID: {{widgetId}} -
\ No newline at end of file + diff --git a/web/app/widget-wrappers/reauth-example/reauth-example.component.ts b/web/app/widget-wrappers/reauth-example/reauth-example.component.ts index ad0a967..e97e21b 100644 --- a/web/app/widget-wrappers/reauth-example/reauth-example.component.ts +++ b/web/app/widget-wrappers/reauth-example/reauth-example.component.ts @@ -5,6 +5,7 @@ import { ActivatedRoute } from "@angular/router"; import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service"; import { SessionStorage } from "../../shared/SessionStorage"; import { FE_ScalarOpenIdRequestBody } from "../../shared/models/scalar-server-responses"; +import { TranslateService } from "@ngx-translate/core"; @Component({ selector: "my-reauth-example-widget-wrapper", @@ -18,12 +19,15 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement public userId: string; public blocked = false; public error = false; - public stateMessage = "Checking client version..."; + public stateMessage: string; constructor(activatedRoute: ActivatedRoute, private scalarApi: ScalarServerApiService, - private changeDetector: ChangeDetectorRef) { + private changeDetector: ChangeDetectorRef, + public translate: TranslateService) { super(); + this.translate = translate; + this.translate.get('Checking client version...').subscribe((res: string) => {this.stateMessage = res}); const params: any = activatedRoute.snapshot.queryParams; ScalarWidgetApi.widgetId = params.widgetId; @@ -40,7 +44,7 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement this.error = true; this.hasOpenId = false; this.blocked = false; - this.stateMessage = "Your client is too old to use this widget, sorry"; + this.translate.get('Your client is too old to use this widget, sorry').subscribe((res: string) => {this.stateMessage = res}); } else { this.busy = false; this.error = false; @@ -56,7 +60,7 @@ export class ReauthExampleWidgetWrapperComponent extends CapableWidget implement this.error = false; this.blocked = false; this.hasOpenId = false; - this.stateMessage = "Please accept the prompt to verify your identity"; + this.translate.get('Please accept the prompt to verify your identity').subscribe((res: string) => {this.stateMessage = res}); const response = await this.getOpenIdInfo(); if (response.blocked) { diff --git a/web/app/widget-wrappers/sticker-picker/sticker-picker.component.html b/web/app/widget-wrappers/sticker-picker/sticker-picker.component.html index 9d461af..2837a02 100644 --- a/web/app/widget-wrappers/sticker-picker/sticker-picker.component.html +++ b/web/app/widget-wrappers/sticker-picker/sticker-picker.component.html @@ -4,14 +4,13 @@
- There was a problem authenticating your use of this sticker picker. Please make sure you're using a client - that has Dimension enabled and correctly set up. + {{'There was a problem authenticating your use of this sticker picker. Please make sure you\'re using a client that has Dimension enabled and correctly set up.' | translate}}
- You have no sticker packs. - + {{'You have no sticker packs.' | translate}} +
@@ -43,4 +42,4 @@
- \ No newline at end of file + diff --git a/web/app/widget-wrappers/terms/terms.component.ts b/web/app/widget-wrappers/terms/terms.component.ts index fb434a1..935675b 100644 --- a/web/app/widget-wrappers/terms/terms.component.ts +++ b/web/app/widget-wrappers/terms/terms.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute } from "@angular/router"; import { WidgetApiService } from "../../shared/services/integrations/widget-api.service"; import { DomSanitizer, SafeHtml } from "@angular/platform-browser"; import { ToasterService } from "angular2-toaster"; +import { TranslateService } from "@ngx-translate/core"; @Component({ selector: "my-terms-widget-wrapper", @@ -17,7 +18,9 @@ export class TermsWidgetWrapperComponent implements OnInit { constructor(private activatedRoute: ActivatedRoute, private sanitizer: DomSanitizer, private toaster: ToasterService, - private widgetApi: WidgetApiService) { + private widgetApi: WidgetApiService, + public translate: TranslateService) { + this.translate = translate; } public ngOnInit(): void { @@ -28,7 +31,7 @@ export class TermsWidgetWrapperComponent implements OnInit { this.isLoading = false; }).catch(err => { console.error(err); - this.toaster.pop("error", "Error loading policy"); + this.translate.get('Error loading policy').subscribe((res: string) => {this.toaster.pop("error", res); }); }); } } diff --git a/web/public/assets/i18n/basisNewLang.json b/web/public/assets/i18n/basisNewLang.json new file mode 100644 index 0000000..3ccbc9f --- /dev/null +++ b/web/public/assets/i18n/basisNewLang.json @@ -0,0 +1,586 @@ +{ +"$padName and $roomId will be replaced during creation to help create a unique pad URL.":"", +".travis.yml configuration and template information":"", +"languages[code].langName version":"", +"was invited to the room":"", +"was removed from the room":"", +"is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).":"", +"matrix-appservice-gitter":"", +"is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.": "", +"matrix-appservice-irc": "", +"is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.": "", +"matrix-appservice-slack": "", +"is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they'd like to bridge.":"", +"mautrix-telegram":"", +"is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a 'relay bot' (all Matrix users are represented through a single bot in Telegram) or by making use of a user's real Telegram account (known as 'puppeting'). Currently only one Telegram bridge can be configured at a time.": "", +"matrix-appservice-webhooks": "", + "provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.":"", +"The author of the commit":"", +"The branch name":"", +"The build ID":"", +"The build number":"", +"A URL to see the build information":"", +"The full commit message":"", +"The first line of the commit message":"", +"A short version of the commit SHA":"", +"A URL to see the changes which triggered the build":"", +"The total duration of all builds in the matrix":"", +"The time it took to run the build":"", +"The message from Travis CI about the build":"", +"The repository name":"", +"The repository identifier":"", +"The result of the build":"", +"A few words here will help people understand what the bot does.":"", +"Access Token":"", +"Actions":"", +"Add":"", +"Add widgetComponent.defaultName ":"", +"Add a new custom bot":"", +"self-hosted Gitter bridge":"", +"Add a new self-hosted IRC Bridge":"", +"self-hosted Slack bridge":"", +"Add a new self-hosted Telegram bridge":"", +"Add a new self-hosted webhook bridge":"", +"Add a new webhook":"", +"Add an IRC channel":"", +"Add custom bot":"", +"Add matrix.org's bridge":"", +"Add matrix.org's go-neb":"", +"Add self-hosted bridge":"", +"Add self-hosted go-neb":"", +"Add some stickers":"", +"Add Sticker Packs":"", +"Add stickerpack":"", +"Add utility for everyone in your room by embedding an application.":"", +"Add Widget":"", +"Added by":"", +"Admin":"", +"Administrators":"", +"After inviting":"", +"to your Telegram chat, run the command": "", +"in the Telegram room to get the chat ID.": "", + "An error has occurred - see logs for details":"", +"An open source integration manager for Matrix":"", +"Api Key":"", +"API URL":"", +"Author":"", +"Avatar URL":"", +"Before users can use Dimension they must agree to the terms of service for using your instance. If you're using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.":"", +"Bot disabled":"", +"Bot enabled":"", +"Bot updated":"", +"Bots":"", +"Bots bring entertainment or productivity to the room. They're here to help at your command.":"", +"Bridge":"", +"Bridge removed":"", +"Bridge requested":"", +"Bridge to Gitter":"", +"Bridge to Slack":"", +"Bridge to Telegram":"", +"Bridge updated":"", +"Bridges":"", +"Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.":"", +"Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.":"", +"Bring the outside world into your room with bridges.":"", +"Cancel":"", +"Cat Faces":"", +"Cats":"", +"Channel":"", +"Channel Name":"", +"Chat ID":"", +"Check connection":"", +"Checking client version...":"", +"Checking connectivity to homeserver...":"", +"Checking connectivity to integration manager...":"", +"Click 'share' from your favourite playlist, artist, track, or album and paste the Spotify URI here.":"", +"Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.":"", +"Click the pencil icon to enable networks.":"", +"Click the pencil icon to enable the bots.":"", +"Click to start OpenID auth":"", +"Client ID":"", +"Client Secret":"", +"Client/Server URL":"", +"Close":"", +"Conference URL":"", +"Configuration":"", +"Configuration updated":"", +"Configuring integrations":"", +"Copy and paste this configuration to":"", +"on your homeserver and register it as an application service.": "", + "Could not communicate with Element":"", +"Could not connect to integrations server error":"", +"Could not get go-neb configuration":"", +"Could not load appservice configuration":"", +"Could not update integration status":"", +"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!":"", +"Create":"", +"Create draft":"", +"Custom Bots":"", +"Custom bots":"", +"Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can't have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.":"", +"Custom Widget":"", +"Custom Widgets":"", +"Dashboard":"", +"Default Pad URL Template":"", +"Delete":"", +"Description":"", +"Dimension":"", +"Display Name":"", +"Document URL":"", +"Draft created":"", +"Draft saved":"", +"Echo":"", +"Edit custom bot":"", +"Edit go-neb":"", +"Edit policy":"", +"Edit self-hosted Gitter bridge":"", +"Edit self-hosted Slack bridge":"", +"Edit self-hosted Telegram bridge":"", +"Edit self-hosted webhook bridge":"", +"eg: 1.1.0":"", +"Enabled":"", +"Enabled Bots":"", +"Enabled Features":"", +"Enabled Networks":"", +"Error adding matrix.org's Gitter Bridge":"", +"Error adding matrix.org's go-neb":"", +"Error adding matrix.org's IRC Bridge":"", +"Error adding matrix.org's Slack Bridge":"", +"Error adding stickerpack":"", +"Error bridging room":"", +"Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.":"", +"Error communicating with Element":"", +"Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver's documentation for how to set up federation.":"", +"Error creating appservice":"", +"Error creating document":"", +"Error creating matrix.org go-neb":"", +"Error creating matrix.org's Gitter Bridge":"", +"Error creating matrix.org's IRC Bridge":"", +"Error creating matrix.org's Slack Bridge":"", +"Error creating webhook":"", +"Error deleting webhook":"", +"Error getting channels for team":"", +"Error getting Slack authorization information":"", +"Error getting teams":"", +"Error importing sticker pack":"", +"Error inviting bridge":"", +"Error loading bridges":"", +"Error loading channel operators":"", +"Error loading configuration":"", +"Error loading go-neb configuration":"", +"Error loading policy":"", +"Error logging everyone out":"", +"Error opening configuration page":"", +"Error publishing policy":"", +"Error removing bridge":"", +"Error requesting bridge":"", +"Error saving policy":"", +"Error updating bot":"", +"Error updating configuration":"", +"Error updating integration":"", +"Error updating sticker pack":"", +"Error updating stickers":"", +"Error updating widget":"", +"Etherpad Widget Configuration":"", +"Everyone has been logged out":"", +"Expected to not be able to send specific event types":"", + "Expected to be able to send specific event types":"", +"Failed to configure the integration":"", +"Failed to create Gitter bridge":"", +"Failed to create IRC bridge":"", +"Failed to create Slack bridge":"", +"Failed to create Telegram bridge":"", +"Failed to create Webhook bridge":"", +"Failed to get an update Gitter bridge list":"", +"Failed to get an update IRC bridge list":"", +"Failed to get an update Slack bridge list":"", +"Failed to get an update Telegram bridge list":"", +"Failed to get an update Webhooks bridge list":"", +"Failed to get an updated bot list":"", +"Failed to load bridges":"", +"Failed to load configuration":"", +"Failed to load policies":"", +"Failed to load policy":"", +"Failed to load sticker packs":"", +"Failed to load widgets":"", +"Failed to make the bridge an administrator":"", +"Failed to remove link":"", +"Failed to request a link":"", +"Failed to take screenshot":"", +"Failed to take screenshot: iframe not supported":"", +"Failed to update Gitter bridge":"", +"Failed to update network":"", +"Failed to update Slack bridge":"", +"Failed to update Telegram bridge":"", +"Failed to update Webhook bridge":"", +"Federation Hostname":"", +"Federation URL":"", +"Feeds":"", +"GIFs can be large, and sometimes it is more desirable to have them downsized.":"", +"Giphy":"", +"Giphy Configuration":"", +"Gitter":"", +"Gitter Bridge":"", +"Gitter bridge added":"", +"Gitter Bridge Configuration":"", +"Gitter Bridge Configurations":"", +"Gitter bridge updated":"", +"Gitter Room":"", +"go-neb":"", +"go-neb appservice configuration":"", +"go-neb configuration":"", +"go-neb configurations":"", +"go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.":"", +"Google Calendar":"", +"Google Calendar Widgets":"", +"Google Configuration":"", +"Google Doc":"", +"Google Doc Widgets":"", +"Google Image Search":"", +"Grafana":"", +"Grafana URL":"", +"Grafana Widgets":"", +"Guggy":"", +"Guggy Configuration":"", +"Have some fun and post a sticker.":"", +"Here's the configuration options you'll need to update in your Element":"", +"Home":"", +"Homeserver":"", +"Huskies":"", +"If enabled, Dimension will recommend that users log in to their Matrix accounts.":"", +"If enabled, Dimension will recommend that users log in to their Telegram accounts.":"", +"If everything is set up correctly, you'll be able to access the admin area of Dimension by clicking the 3x3 grid in the top right of any room in Element. The gear icon":"", + "in the top right is where you can configure your bots, bridges, and widgets.": "", +"Image Size":"", +"Imgur":"", +"Imgur Configuration":"", +"Import from Telegram":"", +"In order to bridge Slack channels, you'll need to authorize the bridge to access your teams and channels. Please click the button below to do so.":"", +"Integration updated":"", +"Integrations":"", +"Integrations are not encrypted!":"", +"Interval":"", +"IRC":"", +"IRC Bridge":"", +"IRC Bridge added":"", +"IRC Bridge Configuration":"", +"IRC Bridge Configurations":"", +"IRC Networks":"", +"Jitsi":"", +"Jitsi Domain":"", +"Jitsi Script URL":"", +"Jitsi Video Conference":"", +"Jitsi Widget Configuration":"", +"Jitsi Widgets":"", +"Join":"", +"for news and updates. Don't forget to star the repository on": "", + "Join Conference":"", +"License":"", +"Link removed":"", +"Link requested!":"", +"Loading Artist":"", +"Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.":"", +"Logout confirmation":"", +"Logout Everyone":"", +"Looking for your sticker packs? Click here.":"", +"Manual troubleshooting may be requred":"", +"matrix.org's bridge":"", +"matrix.org's Gitter bridge added":"", +"matrix.org's go-neb":"", +"matrix.org's go-neb added":"", +"matrix.org's IRC bridge added":"", +"matrix.org's IRC Bridge Networks":"", +"matrix.org's Slack bridge added":"", +"My Policy":"", +"Name":"", +"Name: config.homeserver.name ":"", +"Network":"", +"Network disabled":"", +"Network enabled":"", +"New draft policy":"", +"New feed URL":"", +"New go-neb created":"", +"New policy":"", +"New repository name":"", +"New self-hosted go-neb":"", +"Next":"", +"No bridge configurations.":"", +"No bridged channels":"", +"No bridges.":"", +"No config component for bot.type":"", +"No custom bots.":"", +"No go-neb configurations.":"", +"No integrations available":"", +"No name":"", +"No policies written.":"", +"No sticker packs installed.":"", +"No webhooks":"", +"No, don't bridge":"", +"None":"", +"not specified":"d", +"Notes":"", +"Notes Widgets":"", +"Operator":"", +"Pad Name":"", +"Pad URL":"", +"Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.":"", +"Please accept the prompt to verify your identity":"", +"Please accept the prompt to verify your identity.":"", +"Please ensure you are an 'Admin' for the room":"", +"Please enter a channel name":"", +"Please enter a description for the bot":"", +"Please enter a Grafana URL":"", +"Please enter a name for all policies":"", +"Please enter a name for the bot":"", +"Please enter a repository":"", +"Please enter a shared calendar ID":"", +"Please enter a URL for the widget":"", +"Please enter a user ID for the bot":"", +"Please enter a version number":"", +"Please enter a video URL":"", +"Please enter a YouTube, Vimeo, or DailyMotion video URL":"", +"Please enter an access token for the bot":"", +"Please enter an avatar URL for the bot":"", +"Please enter text for all policies":"", +"Policy Name":"", +"Policy published":"", +"Policy text":"", +"Promote Matrix Puppeting":"", +"Promote Telegram Puppeting":"", +"Provisioning URL":"", +"Publish":"", +"Publish policy":"", +"Remove":"", +"Remove Widget":"", +"Repositories":"", +"Repository Template":"", +"Request Bridge":"", +"Requirement":"", +"not found": "", +"RSS Bot Configuration":"", +"RSS Notifications":"", +"Save":"", +"Save draft":"", +"Save Widget":"", +"Search Engine ID":"", +"Self-host your favourite bots, bridges, and widgets.":"", +"Self-hosted bridge":"", +"Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"", +"Self-hosted go-neb":"", +"Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.":"", +"Self-hosted IRC Bridge Networks":"", +"Self-hosted IRC bridges must have": "", +"provisioning":"", +"enabled in the configuration.":"", +"Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"", +"Self-hosted Telegram bridges must have":"", +"Self-hosted webhook bridges must have":"", +"Sessions":"", +"Sessions":"", +"Shared Calendar ID":"", +"Shared Secret":"", +"Slack":"", +"Slack Bridge":"", +"Slack bridge added":"", +"Slack Bridge Configuration":"", +"Slack Bridge Configurations":"", +"Slack bridge updated":"", +"Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you'll force Dimension to use your Jitsi domain at risk of having clients not respect it.":"", +"some_secret_value":"", +"Sorry, this content cannot be embedded":"", +"source":"", +"source on GitHub":"", +"Spotify":"", +"Spotify URI":"", +"Spotify Widgets":"", +"Start a conversation with":"", + "to create your own stickerpack.": "", +"Sticker pack updated":"", +"Sticker Pack: pack.displayName ":"", +"Sticker Packs":"", +"Sticker packs are not enabled on this Dimension instance.":"", +"Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the 'sticker picker' widget will be disabled.":"", +"Stickerpack added":"", +"Stickerpack URL":"", +"Stickers":"", +"Stickers updated":"", +"Team":"", +"Telegram":"", +"Telegram Bridge":"", +"Telegram bridge added":"", +"Telegram Bridge Configuration":"", +"Telegram Bridge Configurations":"", +"Telegram bridge updated":"", +"Telegram chat is already bridged":"", +"Telegram sticker pack imported":"", +"Template":"", +"Terms of Service":"", +"Test Configuration":"", +"That Telegram chat is already bridged to another room":"", +"That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not have the required permissions to be able to unbridge the other room.":"", +"The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.":"", +"The API key for":"", +"The API key for your Google Application.":"", +"The API key from":"", +"The appservice appears to be correctly set up":"", +"The appservice is not correctly set up":"", +"The client ID of your":"", + "Imgur Application": "", +"The client secret of your":"", +"The following section needs to be added to your":"", +"file in your repositories:": "", +"The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.":"", +"The operator selected will have to approve the bridge for it to work":"", +"The provisioning secret defined in the configuration.":"", +"The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.":"", +"The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.":"", +"The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.":"", +"The public URL for the bridge.":"", +"The room must be":"", +"to use this integration":"", +"The search engine ID":"", +"The shared secret defined in the configuration for provisioning.":"", +"The Telegram bot has not been invited to the chat":"", +"The translated name of your policy":"", +"The user ID that Dimension will invite to rooms.":"", +"The version number of this policy":"", +"There are currently no integrations which support encrypted rooms. Sorry about that!":"", +"There was a problem authenticating your use of this sticker picker. Please make sure you're using a client that has Dimension enabled and correctly set up.":"", +"This bot is handled by another go-neb instance":"", +"This bridge is offline or unavailable.":"", +"This can either be an MXC URI or a plain URL.":"", +"This integration is not supported in encrypted rooms":"", +"This integration is offline or unavailable":"", +"This is the domain that is used to host the conference.":"", +"This is the name Dimension will use to tell users which bot this is.":"", +"This is the prefix used for all bot users.":"", +"This is used by Dimension to force the bot to leave the room when the user removes the bot.":"", +"Learn more about access tokens.": "", +"This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.":"", +"This is where you put your policy's content.":"", +"This means that some information about yourself and the room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display name, your username, your avatar, information about Element, and other similar details. Add integrations with caution.":"", +"This room does not have any compatible integrations. Please contact the server owner if you're seeing this message.":"", +"This room is already bridged to a Telegram chat":"", +"This room is bridged to on Slack":"", +"This room is bridged to on Gitter":"", +"This room is bridged to on Telegram":"", + "on Slack": "", + "on Gitter": "", + "on Telegram": "", +"This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.":"", +"This room is encrypted":"", +"To get a URL, go to Grafana and click 'share' on a graph.":"", +"Tokens registered":"", +"Trading Pair":"", +"TradingView":"", +"TradingView Widgets":"", +"Travis CI":"", +"Travis CI Configuration":"", +"Try it out or":"", + "run your own": "", +"Twitch Livestream":"", +"Twitch Livestream Widgets":"", +"TwitchUsername":"", +"Type":"", +"Unable to communicate with Dimension due to an unknown error.":"", +"Unable to load Dimension - missing room ID or token.":"", +"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server.":"", +"Unbridge":"", +"Unbridge and continue":"", +"URL":"", +"Use downsized images":"", +"Use this domain as the default conference domain":"", +"User ID":"", +"User ID:":"", +"User Prefix":"", +"Utility User ID":"", +"Even in a private, or non-federated, environment federation needs to be enabled so Dimension can work correctly. Dimension should still work okay if federation on your homeserver is bound to a private interface instead of being public - just be sure to set the federation URL in your configuration.":"", + "Verify federation is enabled on your homeserver.": "", + "Using tools like the": "", + "federation tester": "", + ", make sure that federation is working on your homeserver.":"", + "Verify that federation is working on your homeserver.": "", + "The name, client/server URL, and access token all need to be valid and directed at your homeserver.":"", +"Verify the homeserver configuration in Dimension.": "", + "Version":"", +"Version number":"", +"Video URL":"", +"Visit":"", + "and log in with your Matrix account or point your Element": "", + "at our servers:": "", +"Webhook Bridge":"", +"Webhook bridge added":"", +"Webhook Bridge Configuration":"", +"Webhook bridge updated":"", +"Webhook created":"", +"Webhook deleted":"", +"Webhook Name":"", +"Webhooks":"", +"Webhooks Bridge Configuration":"", +"Welcome to Dimension!":"", +"When Element cannot reach Dimension or Dimension is unable to reach your homeserver an error saying 'Could not contact integrations server' shows up in every room. Before visiting us in":"", +"on Matrix, here's a few things to check:": "", + "Whiteboard":"", +"Whiteboard Name":"", +"Whiteboard URL":"", +"Whiteboard Widgets":"", +"Widget added!":"", +"Widget Blacklist":"", +"Widget deleted!":"", +"Widget ID: widgetId":"", +"Widget Name":"", +"Widget updated":"", +"Widget updated!":"", +"Widget URL":"", +"Widgets":"", +"Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.":"", +"Wikipedia":"", +"You":"", +"You cannot modify widgets in this room":"", +"You do not appear to have permission to modify widgets in this room":"", +"You do not have permission to bridge that chat":"", +"You do not have permission to unbridge that chat":"", +"You do not have the necessary permissions in this room to unbridge the channel.":"", +"You have blocked this widget from receiving credentials.":"", +"You have blocked this widget from verifying your identity.":"", +"You have no sticker packs.":"", +"You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge the other room and instead bridge it here?":"", +"Your client is too old to use this widget, sorry":"", +"Your client is too old to use this widget. Try upgrading your client to the latest available version, or contact the author to try and diagnose the problem. Your client needs to support OpenID information exchange.":"", +"Your Sticker Packs":"", +"your_api_key_here":"", +"your_client_id":"", +"your_client_secret":"", +"your_cx_id_here":"", +"You're all set! Click the button below to re-run the test.":"", +"YouTube":"", +"Youtube Video Widgets":"", + "The person selected here will be asked to approve or deny the bridge request.": "", + "Created by": "", + "under": "", + "A webpage embedded in the room.": "", + "Collaborate on documents with members of your room.": "", + "Share upcoming events in your room with a Google Calendar.": "", + "Embed a Twitch livestream into your room.": "", + "Monitor your favourite cryptocurrencies": "", + "Collaborate on and share documents using Google Docs.": "", + "Hold a video conference with Jitsi Meet": "", + "Share music with the room": "", + "A whiteboard app embedded in the room.": "", + "Embed a YouTube, Vimeo, or DailyMotion video in your room.": "", + "Embed a graph in the room": "", + "Jitsi Conference": "Jitsi Conference", + "Bridges IRC channels to rooms, supporting multiple networks": "", + "Bridges Telegram chats and channels to rooms on Matrix": "", + "Slack-compatible webhooks for your room": "", + "Bridges Gitter rooms to Matrix": "", + "Bridges Slack channels to Matrix": "", + "The most photogenic animal on the planet.": "", + "Cute cats": "", + "Cute cat faces": "", + "The official Loading Artist sticker pack!": "", + "disabled": "", + "Please enter a feed URL": "", + "Home": "Home", + "Dimension": "Dimension" +} diff --git a/web/public/assets/i18n/de.json b/web/public/assets/i18n/de.json new file mode 100644 index 0000000..d5d3bdf --- /dev/null +++ b/web/public/assets/i18n/de.json @@ -0,0 +1,588 @@ +{ +"$padName and $roomId will be replaced during creation to help create a unique pad URL.":"'$padName' und '$roomId' werden während der Erstellung ersetzt, um eine eindeutige Pad-URL zu erstellen.", +".travis.yml configuration and template information":".travis.yml Konfigurations- und Vorlageninformationen", +"languages[code].langName version":"languages[code].langName Version", +"was invited to the room":" wurde in den Raum eingeladen", +"was removed from the room":" wurde auf dem Raum entfernt", +"is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).":"ist ein Mehrzweck-Bot, der verschiedene Dienste wie Reaktions-GIFs und Github-Benachrichtigungen bereitstellen kann. Es gibt zwei Optionen für die Unterstützung von Go-NEB in Dimension: verwenden von matrix.org oder Selbsthosting. Jeder Go-NEB-Instanz können mehrere Dienste zugeordnet sein (D.h.: ein Go-NEB kann hier alles ausführen).", +"matrix-appservice-gitter":"matrix-appservice-gitter", +"is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.": "ist eine Gitter-Bridge, die eine Verbindung von Gitter-Räumen mit Matrix unterstützt. Matrix-Nutzer werden in Gitter als einzelne Bot-Benutzer dargestellt, Gitter-Nutzer werden jedoch als real aussehende Matrix-Nutzer im Raum dargestellt.", +"matrix-appservice-irc": "matrix-appservice-irc", +"is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.": "ist eine IRC-Bridge, die mehrere IRC-Netzwerke unterstützt. Dimension kann mehrere IRC-Bridges verwenden, um die Last in großen Installation besser auf mehrere Netzwerke zu verteilen.", +"matrix-appservice-slack": "matrix-appservice-slack", +"is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they'd like to bridge.":"ist eine Slack-Bridge, die eine Verbindung von Slack-Kanälen mit Matrix unterstützt. Benutzer autorisieren die Bridge, auf ihre Slack-Arbeitsbereiche zuzugreifen, und können von dort aus die Kanäle auswählen, die sie verbinden möchten.", +"mautrix-telegram":"mautrix-telegram", +"is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a 'relay bot' (all Matrix users are represented through a single bot in Telegram) or by making use of a user's real Telegram account (known as 'puppeting'). Currently only one Telegram bridge can be configured at a time.": "ist eine Telegramm-Bridge, die eine Verbindun von Telegram-Kanälen/-Supergruppen mit Matrix unterstützt. Dies kann über einen \"Relay-Bot\" (alle Matrix-Benutzer werden in Telegram durch einen einzelnen Bot dargestellt) oder über das echte Telegramm-Konto eines Benutzers (als \"Puppeting\" bezeichnet) erfolgen. Derzeit kann jeweils nur eine Telegramm-Bridge konfiguriert werden.", +"matrix-appservice-webhooks": "matrix-appservice-webhook", +"provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.":"bietet Slack-kompatible Webhooks für Matrix, mit denen Updates einfach in einen Raum gesendet werden können.", +"The author of the commit":"Der Autor des Commits", +"The branch name":"Der Name des Branches", +"The build ID":"Die Build-ID", +"The build number":"Die Build-Nummer", +"A URL to see the build information":"Eine URL, um die Build-Informationen anzuzeigen", +"The full commit message":"Die vollständige Commit-Nachricht", +"The first line of the commit message":"Die erste Zeile der Commit-Nachricht", +"A short version of the commit SHA":"Eine Kurzversion des Commit-SHA", +"A URL to see the changes which triggered the build":"Eine URL, um die Änderungen anzuzeigen, die den Build ausgelöst haben", +"The total duration of all builds in the matrix":"Die Gesamtdauer aller Builds", +"The time it took to run the build":"Die Zeit, die zum Ausführen des Builds benötigt wurde", +"The message from Travis CI about the build":"Die Nachricht von Travis CI über den Build", +"The repository name":"Der Repository-Name", +"The repository identifier":"Die Repository-ID", +"The result of the build":"Das Ergebnis des Builds", +"A few words here will help people understand what the bot does.":"Ein paar Worte hier helfen den Nutzern zu verstehen, was der Bot tut.", +"Access Token":"Access Token", +"Actions":"Aktionen", +"Add":"Hinzufügen", +"Add widgetComponent.defaultName ":" widgetComponent.defaultName hinzufügen", +"Add a new custom bot":"Benutzerdefinierten Bot hinzufügen", +"self-hosted Gitter bridge":"Selbst gehostete Gitter-Bridge ", +"Add a new self-hosted IRC Bridge":"Selbst gehostete IRC-Bridge hinzufügen", +"self-hosted Slack bridge":"Selbst gehostete Slack-Bridge ", +"self-hosted Telegram bridge":"Selbst gehostete Telegram-Bridge ", +"self-hosted webhook bridge":"Selbst gehostete Webhook-Bridge ", +"Add a new webhook":"Webhook hinzufügen", +"Add an IRC channel":"IRC-Channel hinzufügen", +"Add custom bot":"Benutzerdefinierten Bot hinzufügen", +"Add matrix.org's bridge":"matrix.org-Bridge hinzufügen", +"Add matrix.org's go-neb":"Go-NEB von matrix.org hinzufügen", +"Add self-hosted bridge":"Selbst gehostete Bridge hinzufügen", +"Add self-hosted go-neb":"Selbst gehosteten Go-NEB hinzufügen", +"Add some stickers":"Sticker hinzufügen", +"Add Sticker Packs":"Sticker-Packs hinzufügen", +"Add stickerpack":"Sticker-Pack hinzufügen", +"Add utility for everyone in your room by embedding an application.":"Fügen Sie ein Dienstprogramm für alle in Ihrem Raum hinzu, indem Sie eine Anwendung einbetten.", +"Add Widget":"Widget hinzufügen", +"Added by":"Hinzugefügt von", +"Admin":"Adminstrator", +"Administrators":"Administratoren", +"After inviting":"Nach der Einladung", +"to your Telegram chat, run the command": "zu Ihrem Telegramm-Chat, Fragen Sie mit dem Kommando", +"in the Telegram room to get the chat ID.": "im Telegrammraum, um die Chat-ID zu erhalten.", +"An error has occurred - see logs for details":"Ein Fehler ist aufgetreten - Details stehen im Log", +"An open source integration manager for Matrix":"Ein Open Source Integration-Manager für Matrix", +"Api Key":"API Key", +"API URL":"API URL", +"Author":"Autor", +"Avatar URL":"Avatar URL", +"Before users can use Dimension they must agree to the terms of service for using your instance. If you're using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.":"Bevor Benutzer Dimension verwenden können, müssen sie den Nutzungsbedingungen für die Verwendung Ihrer Instanz zustimmen. Wenn Sie matrix.org-Bridges verwenden, müssen Benutzer zusätzlich zu den hier hinzugefügten Bedingungen die Nutzungsbedingungen für Ihre Upstream-Integration-Manager (normalerweise scalar.vector.im) akzeptieren.", +"Bot disabled":"Bot deaktiviert", +"Bot enabled":"Bot aktiviert", +"Bot updated":"Bot aktualisiert", +"Bots":"Bots", +"Bots bring entertainment or productivity to the room. They're here to help at your command.":"Bots bringen Unterhaltung oder Produktivität in den Raum. Sie helfen auf Kommando.", +"Bridge":"Bridge", +"Bridge removed":"Bridge entfernt", +"Bridge requested":"Bridge angefordert", +"Bridge to Gitter":"Gitter-Bridge", +"Bridge to Slack":"Slack-Bridge", +"Bridge to Telegram":"Telegram-Bridge", +"Bridge updated":"Bridge aktualisiert", +"Bridges":"Bridges", +"Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.":"Über Bridges können Räume Nachrichten mit Drittanbieter-Netzwerken austauschen. Beispielsweise kann eine IRC-Bridge es IRC- und Matrix-Nutzern ermöglichen, miteinander zu kommunizieren.", +"Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.":"Das Verbindung mit einem Channel erfordert die Autorisierung des Channel-Betreibers. Wenn Sie einen Channel unten betreten, wird ein Bot dem Channel beitreten, um sicherzustellen, dass er existiert und verfügbar ist.", +"Bring the outside world into your room with bridges.":"Bringen Sie mit Bridges die Aussenwelt in Ihren Raum", +"Cancel":"Abbrechen", +"Cat Faces":"Katzen-Bilder", +"Cats":"Katzen", +"Channel":"Channel", +"Channel Name":"Channel-Name", +"Chat ID":"Chat-ID", +"Check connection":"Verbindung testen", +"Checking client version...":"Prüfe Client-Version…", +"Checking connectivity to homeserver...":"Prüfe Verbindung zum Home-Server…", +"Checking connectivity to integration manager...":"Prüfe Verbindung zum Integration-Manager…", +"Click 'share' from your favourite playlist, artist, track, or album and paste the Spotify URI here.":"Klicken Sie in Ihrer bevorzugten Wiedergabeliste, Ihrem bevorzugten Interpreten, Titel oder Album auf \"Teilen\" und fügen Sie den Spotify-URI hier ein.", +"Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.":"Klicken Sie auf die Schaltfläche, um Ihre Verbindung zu testen. Dies kann dazu führen, dass Ihr Client fragt, ob es in Ordnung ist, Ihre Identität mit dem Widget zu teilen. Dies ist erforderlich, um Ihre Verbindung zu Ihrem Home-Server zu testen.", +"Click the pencil icon to enable networks.":"Klicken Sie auf das Stift-Icon, um Netzwerke zu aktivieren", +"Click the pencil icon to enable the bots.":"Klicken Sie auf das Stift-Icon, um Bots zu aktivieren", +"Click to start OpenID auth":"OpenID-Authorisierung starten", +"Client ID":"Client-ID", +"Client Secret":"Client-Passwort", +"Client/Server URL":"Client/Server URL", +"Close":"Schliessen", +"Conference URL":"Konferenz-URL", +"Configuration":"Konfiguration", +"Configuration updated":"Konfiguration aktualisiert", +"Configuring integrations":"Integrationen konfigurieren", +"Copy and paste this configuration to":"Kopieren Sie diese Konfiguration und fügen Sie sie in", +"on your homeserver and register it as an application service.": "auf Ihrem Home-Server ein, um ihn Application-Service zu registrieren.", +"Could not communicate with Element":"Kommunikation mit Element fehlgeschlagen", +"Could not connect to integrations server error":"Keine Verbindung zum Integration-Server", +"Could not get go-neb configuration":"Go-NEB-Konfiguration konnte nicht geladen werden", +"Could not load appservice configuration":"App-Service-Konfiguration konne nicht geladen werden", +"Could not update integration status":"Status der Integration konnte nicht aktualisiert", +"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!":"Ihr Token konnte nicht überprüft werden. Bitte versuchen Sie, sich von Element abzumelden und wieder anzumelden. Sichern Sie unbedingt Ihren Encryption-Key!", +"Create":"Anlegen", +"Create draft":"Draft anlegen", +"Custom Bots":"Benutzerdefinierte Bots", +"Custom bots":"Benutzerdefinierte Bots", +"Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can't have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.":"Mit benutzerdefinierten Bots können Sie Dimension Ihre eigenen Bots hinzufügen, damit Benutzer sie ihren Räumen hinzufügen können. Diese Bots können keine Konfiguration haben und müssen Raumeinladungen selbst annehmen können. Alles, was Dimension tun wird, wenn ein Benutzer den Bot hinzufügen möchte, ist, ihn in den Raum einzuladen.", +"Custom Widget":"Benutzerdefiniertes Widget", +"Custom Widgets":"Benutzerdefinierte Widgets", +"Dashboard":"Dashboard", +"Default Pad URL Template":"Standard-Vorlage für Pad-URL", +"Delete":"Löschen", +"Description":"Beschreibung", +"Dimension":"Dimension", +"Display Name":"Anzeige-Name", +"Document URL":"Dokument-URL", +"Draft created":"Entwurf angelegt", +"Draft saved":"Entwurf gespeichert", +"Echo":"Echo", +"Edit custom bot":"Benutzerdefinierten Bot bearbeiten", +"Edit go-neb":"Go-NEB bearbeiten", +"Edit policy":"Nutzungsbedingungen bearbeiten", +"Edit self-hosted Gitter bridge":"Gitter-Bridge bearbeiten", +"Edit self-hosted Slack bridge":"Slack-Bridge bearbeiten", +"Edit self-hosted Telegram bridge":"Telegram-Bridge bearbeiten", +"Edit self-hosted webhook bridge":"Webhook-Bridge bearbeiten", +"eg: 1.1.0":"Z.B. 1.1.0", +"Enabled":"Aktiviert", +"Enabled Bots":"Bots aktivieren", +"Enabled Features":"Feature aktivieren", +"Enabled Networks":"Netzwerke aktivieren", +"Error adding matrix.org's Gitter Bridge":"Fehler beim Hinzufügen der Gitter-Bridge von matrix.og", +"Error adding matrix.org's go-neb":"Fehler beim Hinzufügen des Go-NEB von matrix.og", +"Error adding matrix.org's IRC Bridge":"Fehler beim Hinzufügen der IRC-Bridge von matrix.og", +"Error adding matrix.org's Slack Bridge":"Fehler beim Hinzufügen der Slack-Bridge von matrix.og", +"Error adding stickerpack":"Fehler beim Hinzufügen des Sticker-Packs", +"Error bridging room":"Fehler beim Verbinden des Raums", +"Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.":"Fehler beim Überprüfen, ob der Integrationsmanager aktiv ist. Dies bedeutet normalerweise, dass der Manager, der dieses Widget bereitgestellt hat, offline gegangen ist.", +"Error communicating with Element":"Fehler bei der Kommunikation mit Element", +"Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver's documentation for how to set up federation.":"Fehler beim Kontaktieren des Home-Servers. Dies bedeutet normalerweise, dass Ihr Federation-Setup falsch ist oder Ihr Home-Server offline ist. Informationen zum Einrichten von Federations finden Sie in der Dokumentation Ihres Home-Serverservers.", +"Error creating appservice":"Fehler beim Erstellen des App-Services", +"Error creating document":"Fehler beim Erstellen des Dokuments", +"Error creating matrix.org go-neb":"Fehler beim Erstellen des Go-NEB von matrix.og", +"Error creating matrix.org's Gitter Bridge":"Fehler beim Erstellen der Gitter-Bridge von matrix.og", +"Error creating matrix.org's IRC Bridge":"Fehler beim Erstellen der IRC-Bridge von matrix.og", +"Error creating matrix.org's Slack Bridge":"Fehler beim Erstellen der Slack-Bridge von matrix.og", +"Error creating webhook":"Fehler beim Erstellen des Webhooks", +"Error deleting webhook":"Fehler beim Löschen des Webhooks", +"Error getting channels for team":"Fehler beim Abfragen des Team-Channels", +"Error getting Slack authorization information":"Fehler beim Abfragen der Authorisierungsinformationen von Slack", +"Error getting teams":"Fehler bei der Abfrage der Teams", +"Error importing sticker pack":"Fehler beim Importieren des Sticker-Packs", +"Error inviting bridge":"Fehler beim Einladen der Bridge", +"Error loading bridges":"Fehler beim Laden der Bridges", +"Error loading channel operators":"Fehler beim Laden des Channel-Operators", +"Error loading configuration":"Fehler beim Laden der Konfiguration", +"Error loading go-neb configuration":"Fehler beim Laden der Go-NEB Konfiguration", +"Error loading policy":"Fehler beim Laden der Nutzungsbedingungen", +"Error logging everyone out":"Fehler beim Abmelden aller Nutzer", +"Error opening configuration page":"Fehler beim Öffnen der Konfigurationsseite", +"Error publishing policy":"Fehler beim Veröffentlichen der Nutzungsbedingungen", +"Error removing bridge":"Fehler beim Entfernen der Bridge", +"Error requesting bridge":"Fehler beim Anfordern der Bridge", +"Error saving policy":"Fehler beim Speichern der Nutzungsbedingungen", +"Error updating bot":"Fehler beim Aktualisieren des Bots", +"Error updating configuration":"Fehler beim Aktualisieren der Integration", +"Error updating integration":"Fehler beim Aktualisieren der Integration", +"Error updating sticker pack":"Fehler beim Aktualisieren des Sticker-Packs", +"Error updating stickers":"Fehler beim Aktualisieren der Sticker", +"Error updating widget":"Fehler beim Aktualisieren des Widgets", +"Etherpad Widget Configuration":"Etherpad Widget Konfiguration", +"Everyone has been logged out":"Alle Nutzer wurden ausgeloggt", +"Expected to not be able to send specific event types":"Es wird erwartet, dass bestimmte Ereignistypen nicht gesendet werden können", +"Expected to be able to send specific event types":"Es wird erwartet, dass bestimmte Ereignistypen gesendet werden können", +"Failed to configure the integration":"Die Integration konnte nicht konfiguriert werden", +"Failed to create Gitter bridge":"Die Gitter-Bridge konnte nicht angelegt werden", +"Failed to create IRC bridge":"Die IRC-Bridge konnte nicht angelegt werden", +"Failed to create Slack bridge":"Die Slack-Bridge konnte nicht angelegt werden", +"Failed to create Telegram bridge":"Die Telegram-Bridge konnte nicht angelegt werden", +"Failed to create Webhook bridge":"Die Webhook-Bridge konnte nicht angelegt werden", +"Failed to get an update Gitter bridge list":"Aktuelle Liste der Gitter-Bridges konnte nicht geladen werden", +"Failed to get an update IRC bridge list":"Aktuelle Liste der IRC-Bridges konnte nicht geladen werden", +"Failed to get an update Slack bridge list":"Aktuelle Liste der Slack-Bridges konnte nicht geladen werden", +"Failed to get an update Telegram bridge list":"Aktuelle Liste der Telegram-Bridges konnte nicht geladen werden", +"Failed to get an update Webhooks bridge list":"Aktuelle Liste der Webhook-Bridges konnte nicht geladen werden", +"Failed to get an updated bot list":"Aktuelle Liste der Bots konnte nicht geladen werden", +"Failed to load bridges":"Bridges konnten nicht geladen werden", +"Failed to load configuration":"Konfiguration konnte nicht geladen werden", +"Failed to load policies":"Nutzungsbedingungen konnten nicht geladen werden", +"Failed to load policy":"Nutzungsbedingung konnten nicht geladen werden", +"Failed to load sticker packs":"Sticker-Packs konnten nicht geladen werden", +"Failed to load widgets":"Widgets konnten nicht geladen werden", +"Failed to make the bridge an administrator":"Bridge konnte nicht zum Administrator gemacht werden ", +"Failed to remove link":"Link konnte nicht entfernt werden", +"Failed to request a link":"Fehler beim Anfordern eines Links", +"Failed to take screenshot":"Screenshot konnte nicht erstellt werden", +"Failed to take screenshot: iframe not supported":"Screenshot konnte nicht erstellt werden: IFrames werden nicht unterstützt", +"Failed to update Gitter bridge":"Gitter-Bridge konnte nicht aktualisiert werden", +"Failed to update network":"Netzwerk konnten nicht aktualisiert werden", +"Failed to update Slack bridge":"Slack-Bridge konnte nicht aktualisiert werden", +"Failed to update Telegram bridge":"Telegram-Bridge konnte nicht aktualisiert werden", +"Failed to update Webhook bridge":"Webhook-Bridge konnte nicht aktualisiert werden", +"Federation Hostname":"Federation-Hostname", +"Federation URL":"Federation-URL ", +"Feeds":"Feeds", +"GIFs can be large, and sometimes it is more desirable to have them downsized.":"GIFs können groß sein, und manchmal ist es wünschenswerter, sie zu verkleinern.", +"Giphy":"Giphy", +"Giphy Configuration":"Giphy-Konfiguration", +"Gitter":"Gitter", +"Gitter Bridge":"Gitter-Bridge", +"Gitter bridge added":"Gitter-Bridge hinzugefügt", +"Gitter Bridge Configuration":"Gitter-Bridge-Konfiguration", +"Gitter Bridge Configurations":"Gitter-Bridge-Konfigurationen", +"Gitter bridge updated":"Gitter-Bridge aktualisiert", +"Gitter Room":"Gitter-Raum", +"go-neb":"Go-NEB", +"go-neb appservice configuration":"Go-NEB-App-Service-Konfiguration", +"go-neb configuration":"Go-NEB-Konfiguration", +"go-neb configurations":"Go-NEB-Konfigurationen", +"go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.":"Go-NEB unterstützt viele verschiedene Arten von Bots, von denen jeder unten aufgeführt ist. Hier können Sie konfigurieren, welche Bots diese Go-NEB-Instanz verwenden soll.", +"Google Calendar":"Google Kalender", +"Google Calendar Widgets":"Google Kalender Widgets", +"Google Configuration":"Google Konfiguration", +"Google Doc":"Google Doc", +"Google Doc Widgets":"Google Doc Widgets", +"Google Image Search":"Google-Bildersuche", +"Grafana":"Grafana", +"Grafana URL":"Grafana-URL", +"Grafana Widgets":"Grafana Widgets", +"Guggy":"Guggy", +"Guggy Configuration":"Guggy-Konfiguration", +"Have some fun and post a sticker.":"Haben Sie etwas Spaß mit einem Sticker", +"Here's the configuration options you'll need to update in your Element":"Hier sind die Konfigurationsoptionen, die Sie in Ihrem Element aktualisieren müssen", +"Home":"Home", +"Homeserver":"Home-Server", +"Huskies":"Huskies", +"If enabled, Dimension will recommend that users log in to their Matrix accounts.":"Wenn diese Option aktiviert ist, empfiehlt Dimension, dass sich Benutzer bei ihrem Matrix-Konto anmelden.", +"If enabled, Dimension will recommend that users log in to their Telegram accounts.":"Wenn diese Option aktiviert ist, empfiehlt Dimension, dass sich Benutzer bei ihren Telegramm-Konto anmelden.", +"If everything is set up correctly, you'll be able to access the admin area of Dimension by clicking the 3x3 grid in the top right of any room in Element. The gear icon":"Wenn alles richtig eingerichtet ist, können Sie auf den Administrationsbereich von Dimension zugreifen, indem Sie auf das 3x3-Raster oben rechts in einem beliebigen Raum in Element klicken. Über das Zahnradsymbol", +"in the top right is where you can configure your bots, bridges, and widgets.": "oben rechts können Sie Ihre Bots, Bridges und Widgets konfigurieren.", +"Image Size":"Bildgröße", +"Imgur":"Imgur", +"Imgur Configuration":"Imgur-Konfiguration", +"Import from Telegram":"Import aus Telegram", +"In order to bridge Slack channels, you'll need to authorize the bridge to access your teams and channels. Please click the button below to do so.":"Um Slack-Kanäle zu verbinden, müssen Sie die Bridge für den Zugriff auf Ihre Teams und Kanäle autorisieren. Bitte klicken Sie dazu auf die Schaltfläche unten.", +"Integration updated":"Integration aktualisieren", +"Integrations":"Integrationen", +"Integrations are not encrypted!":"Integrationen sind nicht verschlüsselt!", +"Interval":"Intervall", +"IRC":"IRC", +"IRC Bridge":"IRC-Bridge", +"IRC Bridge added":"IRC-Bridge hinzufügen", +"IRC Bridge Configuration":"IRC-Bridge Konfiguration", +"IRC Bridge Configurations":"IRC-Bridge Konfigurationen", +"IRC Networks":"IRC-Netzwerke", +"Jitsi":"Jitsi", +"Jitsi Domain":"Jitsi Domain", +"Jitsi Script URL":"Jitsi Script-URL", +"Jitsi Video Conference":"Jitsi Video Konferenz", +"Jitsi Widget Configuration":"Jitsi Widget Konfiguration", +"Jitsi Widgets":"Jitsi Widgets", +"Join":"Treten Sie", +"for news and updates. Don't forget to star the repository on": "bei, um Neuigkeiten und Updates zu erhalten. Vergessen Sie nicht, dem Repository auf", +"Join Conference":"An der Konferenz teilnehmen", +"License":"Lizenz", +"Link removed":"Link entfernt", +"Link requested!":"Link angefordert!", +"Loading Artist":"Loading Artist", +"Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.":"Wenn Sie alle Nutzer abmelden, werden alle bekannten Anmeldetoken für Dimension- und Upstream-Integration-Manager deaktiviert. Die meisten Clients registrieren sich hinter den Kulissen automatisch erneut für ein Anmeldetoken, ähnlich wie beim ersten Erwerb eines Anmeldetokens.", +"Logout confirmation":"Abmelden bestätigen", +"Logout Everyone":"Alle Nutzer abmelden", +"Looking for your sticker packs?":"Suchen Sie nach Ihren Sticker-Packs?", + "Click here": "Klicken Sie hier", +"Manual troubleshooting may be requred":"Möglicherweise ist eine manuelle Fehlerbehebung erforderlich", +"matrix.org's bridge":"Bridge von matrix.org", +"matrix.org's Gitter bridge added":"Gitter-Bridge von matrix.org hinzugefügt", +"matrix.org's go-neb":"Go-NEB (matrix.org)", +"matrix.org's go-neb added":"Go-NEB von matrix.org hinzugefügt", +"matrix.org's IRC bridge added":"IRC-Bridge von matrix.org hinzugefügt", +"matrix.org's IRC Bridge Networks":"IRC-Bridge Netzwerke (matrix.org)", +"matrix.org's Slack bridge added":"Slack-Bridge von matrix.org hinzugefügt", +"My Policy":"Nutzungsbedingungen", +"Name":"Name", +"Name: config.homeserver.name ":"Name: config.homeserver.name ", +"Network":"Netzwerk", +"Network disabled":"Netzwerk deaktiviert", +"Network enabled":"Netzwerk aktiviert", +"New draft policy":"Neuer Entwurf", +"New feed URL":"Neue Feed-URL", +"New go-neb created":"Neue Go-NEB-Integraton angelegt", +"New policy":"Neue Nutzungsbedinungen", +"New repository name":"Neue Repository-Name", +"New self-hosted go-neb":"Neue selbst gehostete Go-NEB-Integration", +"Next":"Weiter", +"No bridge configurations.":"Keine Bridge-Konfigurationen", +"No bridged channels":"Keine verbundenen Channel", +"No bridges.":"Keine Bridges", +"No config component for bot.type":"Keine Konfigurationskomponente für bot.type vorhanden", +"No custom bots.":"Keine benutzerdefinierten Bots", +"No go-neb configurations.":"Keine Go-NEB-Konfigurationen", +"No integrations available":"Keine Integrationen verfügbar", +"No name":"Kein Name", +"No policies written.":"Keine Nutzungsbedingungen geschrieben.", +"No sticker packs installed.":"Keine Sticker-Packs installiert", +"No webhooks":"Keine Webhooks", +"No, don't bridge":"Nein, nicht verbinden", +"None":"Keine", +"not specified":"Nicht spezifiziert", +"Notes":"Notizen", +"Notes Widgets":"Notizen-Widgets", +"Operator":"Operator", +"Pad Name":"Pad-Name", +"Pad URL":"Pad-URL", +"Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.":"Teile Ihrer Konfiguration werden unten angezeigt. Um diese Werte zu ändern, bearbeiten Sie Ihre Konfiguration und starten Sie Dimension neu.", +"Please accept the prompt to verify your identity":"Bitte akzeptieren Sie die Überprüfung Ihrer Identität", +"Please accept the prompt to verify your identity.":"Bitte akzeptieren Sie die Überprüfung Ihrer Identität.", +"Please ensure you are an 'Admin' for the room":"Bitte stellen Sie sicher, dass Sie Administrator-Rechte für den Raum haben", +"Please enter a channel name":"Bitte einen Channel-Namen eingeben", +"Please enter a description for the bot":"Bitte eine Beschreibung für den Bot eingeben", +"Please enter a Grafana URL":"Bitte eine Grafana-URL eingeben", +"Please enter a name for all policies":"Bitte einen Namen für alle Nutzungsbedingungen eingeben", +"Please enter a name for the bot":"Bitte einen Namen für den Bot eingeben", +"Please enter a repository":"Bitte ein Repository angeben", +"Please enter a shared calendar ID":"Bitte eine Kalender-ID eingeben", +"Please enter a URL for the widget":"Bitte eine URL für das Widget eingeben", +"Please enter a user ID for the bot":"Bitte eine User-ID für den Bot eingeben", +"Please enter a version number":"Bitte eine Versionsnummer eingeben", +"Please enter a video URL":"Bitte eine Video-URL eingeben", +"Please enter a YouTube, Vimeo, or DailyMotion video URL":"Bitte geben Sie eine Video-URL von YouTube, Vimeo, oder DailyMotion ein", +"Please enter an access token for the bot":"Bitte einen Access Token für den Bot eingeben", +"Please enter an avatar URL for the bot":"Bitte eine Avatar-URL für den Bot eingeben", +"Please enter text for all policies":"Bitte alle Nutzungsbedingungen mit Texten versehen", +"Policy Name":"Name", +"Policy published":"Veröffentlicht", +"Policy text":"Text", +"Promote Matrix Puppeting":"Matrix-Puppeting ermöglichen", +"Promote Telegram Puppeting":"Telegram-Puppeting ermöglichen", +"Provisioning URL":"Provisioning URL", +"Publish":"Veröffentlichen", +"Publish policy":"Richtlinie veröffentlichen", +"Remove":"Entfernen", +"Remove Widget":"Widget entfernen", +"Repositories":"Repositorys", +"Repository Template":"Repository-Vorlage", +"Request Bridge":"Bridge anfordern", +"Requirement":"Anforderung ", +"not found": " nicht erfüllt", +"RSS Bot Configuration":"RSS Bot Konfiguration", +"RSS Notifications":"RSS Nachrichten", +"Save":"Speichern", +"Save draft":"Draft speichern", +"Save Widget":"Widget speichern", +"Search Engine ID":"Search-Engine-ID", +"Self-host your favourite bots, bridges, and widgets.":"Hosten Sie Ihre Lieblingsbots, Bridges und Widgets selbst.", +"Self-hosted bridge":"Selbst gehostete Bridge", +"Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"Bei selbst gehosteten Gitter-Bridges ist Provisioning aktiviert. Achten Sie darauf, die API nicht dem öffentlichen Internet auszusetzen.", +"Self-hosted go-neb":"Go-NEB (Selbst gehostet)", +"Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.":"Selbst gehostete Go-Neb-Instanzen werden von Application Services unterstützt, die auf Ihrem Home-Server installiert sind. Der Application Service ist für die dynamische Erstellung der Bots verantwortlich.", +"Self-hosted IRC Bridge Networks":"IRC-Bridge Netzwerke (Selbst gehostet)", +"Self-hosted IRC bridges must have": "Bei selbst gehosteten IRC-Bridges muss in der Konfiguration", +"provisioning":"Provisioning", +"enabled in the configuration.":"aktiviert sein.", +"Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"Bei selbst gehosteten Slack-Bridges ist Provisioning bereits aktiviert. Achten Sie darauf, die API nicht dem öffentlichen Internet auszusetzen.", +"Self-hosted Telegram bridges must have":"Bei selbst gehosteten Telegramm-Bridges muss in der Konfiguration", +"Self-hosted webhook bridges must have":"Bei selbst gehosteten Webhook-Bridges muss in der Konfiguration", +"Sessions":"Sessions", +"Sessions":"Einstellungen", +"Shared Calendar ID":"Freigegebene Kalender-ID", +"Shared Secret":"Shared Secret", +"Slack":"Slack", +"Slack Bridge":"Slack-Bridge", +"Slack bridge added":"Slack-Bridge hinzugefügt", +"Slack Bridge Configuration":"Slack-Bridge Konfiguration", +"Slack Bridge Configurations":"Slack-Bridge Konfigurationen", +"Slack bridge updated":"Slack-Bridge aktiviert", +"Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you'll force Dimension to use your Jitsi domain at risk of having clients not respect it.":"Einige Clients können Widgets erstellen, die nicht mit Dimension kompatibel sind. Daher verwendet Dimension standardmäßig jitsi.riot.im. Wenn Sie diese Option aktivieren, erzwingen Sie, dass Dimension Ihre Jitsi-Domain verwendet, wobei das Risiko besteht, dass Clients sie nicht akzeptieren.", +"some_secret_value":"Ein_Shared_Secret", +"Sorry, this content cannot be embedded":"Dieser Inhalt kann leider nicht eingebettet werden", +"source":"Quellcode", +"source on GitHub":"Quellcode bei GitHub", +"Spotify":"Spotify", +"Spotify URI":"Spotify-URI", +"Spotify Widgets":"Spotify-Widgets", +"Start a conversation with":"enden Sie Nachrichten an", + "to create your own stickerpack.": ", um Ihr eigenes Sticker-Pack zu erstellen.", +"Sticker pack updated":"Sticker-Pack aktualisiert", +"Sticker Pack: pack.displayName ":"Sticker-Pack: pack.displayName ", +"Sticker Packs":"Sticker-Packs", +"Sticker packs are not enabled on this Dimension instance.":"Sticker-Packs sind für diese Dimension-Instanz nicht aktiviert.", +"Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the 'sticker picker' widget will be disabled.":"Sticker-Packs bieten eine Möglichkeit, Meme oder Gefühle in einem Raum zu teilen. Hier können Sie auswählen, welche Sticker-Packs Nutzer dieser Dimension-Instanz verwenden können. Wenn keine Sticker-Packs aktiviert sind, wird das Widget 'Sticker-Picker' deaktiviert.", +"Stickerpack added":"Sticker-Pack hinzugefügt", +"Stickerpack URL":"Sticker-Pack-URL", +"Stickers":"Sticker", +"Stickers updated":"Sticker aktualisiert", +"Team":"Team", +"Telegram":"Telegram", +"Telegram Bridge":"Telegram-Bridge", +"Telegram bridge added":"Telegram-Bridge hinzugefügt", +"Telegram Bridge Configuration":"Telegram-Bridge Konfiguration", +"Telegram Bridge Configurations":"Telegram-Bridge Konfigurationen", +"Telegram bridge updated":"Telegram-Bridge aktualisiert", +"Telegram chat is already bridged":"Telegram-Chat ist schon verbunden", +"Telegram sticker pack imported":"Telegram-Sticker-Pack importiert", +"Template":"Vorlage", +"Terms of Service":"Nutzungsbedingungen", +"Test Configuration":"Konfiguration testen", +"That Telegram chat is already bridged to another room":"Diese Telegram-Chat ist schon mit einem anderen Raum verbunden", +"That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not have the required permissions to be able to unbridge the other room.":"Dieser Telegramm-Chat wird mit einem anderen Matrix-Raum verbunden und kann hier nicht verbunden werden. Leider verfügen Sie nicht über die erforderlichen Berechtigungen, um den anderen Raum zu verbinden.", +"The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.":"Die Admin-/API-URL für Go-NEB. Stellen Sie sicher, dass die Admin-API nicht der Außenwelt zugänglich gemacht wird, da dieser Endpunkt nicht abgesichert ist.", +"The API key for":"API-Key für", +"The API key for your Google Application.":"API-Key für Ihre Google-Applikation", +"The API key from":"API-Key von", +"The appservice appears to be correctly set up":"Der Appservice scheint korrekt eingerichtet zu sein", +"The appservice is not correctly set up":"Der Appservice ist nicht korrekt eingerichtet", +"The client ID of your":"Client-ID für Ihre", +"Imgur Application": "Imgur Applikation", +"The client secret of your":"Client-Secret für Ihre", +"The following section needs to be added to your":"Der folgende Abschnitt muss der Datei", +"file in your repositories:": "in Ihren Repositorys hinzugefügt werden:", +"The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.":"Die folgenden Variablen können in Ihrer Vorlage verwendet werden. Diese Vorlage wird verwendet, um eine Nachricht an den Raum zu senden, wenn Ihr Webhook aktiviert ist.", +"The operator selected will have to approve the bridge for it to work":"Der ausgewählte Operator muss die Verbindung genehmigen, damit sie funktioniert", +"The provisioning secret defined in the configuration.":"Das Shared Secret für Provisioning in der Konfiguration", +"The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.":"Die Provisioning-URL für die Bridge. Dies ist die öffentliche Adresse für die Bridge, gefolgt von dem in der Konfiguration angegebenen Provisioning-Präfix.", +"The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.":"Die Provisioning-URL für die Bridge. Dies entspricht normalerweise der in der Registrierung angegebenen URL. Diese API ist nicht authentifiziert und sollte mit Vorsicht behandelt werden.", +"The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.":"Die Provisioning-URL für die Bridge. Dies entspricht normalerweise der URL, die Ihr Home-Server für die Kommunikation mit der Bridge verwendet.", +"The public URL for the bridge.":"Öffentliche URL für die Bridge", +"The room must be":"Der Raum muss", +"to use this integration":"sein, damit diese Integration genutzt werden kann", +"The search engine ID":"Die Search-Engine-ID", +"The shared secret defined in the configuration for provisioning.":"Das in der Konfiguration für Provisioning definierte Shared Secret.", +"The Telegram bot has not been invited to the chat":"Der Telegram-Bot ist nicht zu diesem Chat eingeladen", +"The translated name of your policy":"Der übersetzte Name für die Nutzungsbedingungen", +"The user ID that Dimension will invite to rooms.":"Die User-ID, die Dimension in Räume einlädt.", +"The version number of this policy":"Die Versionsnummer für diese Nutzungsbedinungen", +"There are currently no integrations which support encrypted rooms. Sorry about that!":"Derzeit gibt es keine Integrationen, die verschlüsselte Räume unterstützen. Das tut mir leid!", +"There was a problem authenticating your use of this sticker picker. Please make sure you're using a client that has Dimension enabled and correctly set up.":"Beim Starten dieses Sticker-Pickers ist ein Problem aufgetreten. Stellen Sie sicher, dass Sie einen Client verwenden, für den Dimension aktiviert und korrekt eingerichtet ist.", +"This bot is handled by another go-neb instance":"Dieser Bot wird von einer anderen Go-NEB-Instanz verwaltet", +"This bridge is offline or unavailable.":"Bridge ist offline oder nicht erreichbar", +"This can either be an MXC URI or a plain URL.":"Dies kann entweder eine MXC-URI oder eine einfache URL sein.", +"This integration is not supported in encrypted rooms":"Diese Integration wird in verschlüsselten Räumen nicht unterstützt", +"This integration is offline or unavailable":"Diese Integration ist offline oder nicht erreichbar", +"This is the domain that is used to host the conference.":"Dies ist die Domain, die zum Hosten der Konferenz verwendet wird.", +"This is the name Dimension will use to tell users which bot this is.":"Dies ist der Name, den Dimension verwendet, um Benutzern mitzuteilen, um welchen Bot es sich handelt.", +"This is the prefix used for all bot users.":"Dies ist das Präfix, das für alle Bot-User verwendet wird.", +"This is used by Dimension to force the bot to leave the room when the user removes the bot.":"Dies wird von Dimension verwendet, um den Bot zu zwingen, den Raum zu verlassen, wenn der Benutzer den Bot entfernt.", +"Learn more about access tokens.": "Weitere Informationen zu Access Token.", +"This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.":"Dies wird verwendet, um das Jitsi-Widget zu erstellen. Es befindet sich normalerweise unter /libs/external_api.min.js unter Ihrer Domain.", +"This is where you put your policy's content.":"Hier kommt der Inhalt hin", +"This means that some information about yourself and the room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display name, your username, your avatar, information about Element, and other similar details. Add integrations with caution.":"Dies bedeutet, dass einige Informationen über Sie und den Raum möglicherweise an den Bot, die Bridge oder das Widget weitergegeben werden. Zu diesen Informationen gehören die Raum-ID, Ihr Anzeigename, Ihr Benutzername, Ihr Avatar, Informationen zu Element und andere ähnliche Details. Fügen Sie Integrationen mit Vorsicht hinzu.", +"This room does not have any compatible integrations. Please contact the server owner if you're seeing this message.":"Dieser Raum hat keine kompatiblen Integrationen. Bitte wenden Sie sich an den Server-Administrator, wenn diese Meldung angezeigt wird.", +"This room is already bridged to a Telegram chat":"Dieser Raum ist schon mit einem Telegram-Chat verbunden", + "This room is bridged to on Slack":"Dieser Raum ist mir Slack-Channel", + "This room is bridged to on Gitter":"Dieser Raum ist mit Gitter-Raum", + "This room is bridged to on Telegram":"Dieser Raum ist mit dem Telegram-Chat", + "on Slack": "verbunden.", + "on Gitter": "verbunden", + "on Telegram": "verbunden", +"This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.":"Dieser Raum wird durch Webhooks mit Slack verbunden. Webhook-Bridging ist veraltet und unterstützt kein so umfangreiches Bridging wie der neue Ansatz. Es wird empfohlen, die Bridge mit dem neuen Ansatz neu zu erstellen.", +"This room is encrypted":"Dieser Raum ist verschlüsselt", +"To get a URL, go to Grafana and click 'share' on a graph.":"Um eine URL zu erhalten, gehen Sie zu Grafana und klicken Sie in einem Diagramm auf 'Teilen'.", +"Tokens registered":"Registrierte Token", +"Trading Pair":"Trading Pair", +"TradingView":"TradingView", +"TradingView Widgets":"TradingView Widgets", +"Travis CI":"Travis CI", +"Travis CI Configuration":"Travis CI Konfiguration", + "Try it out or":"Probieren Sie es aus oder installieren Sie", + "run your own": "Ihre eigene Instanz", + "Twitch Livestream":"Twitch Livestream", +"Twitch Livestream Widgets":"Twitch Livestream Widgets", +"TwitchUsername":"TwitchUsername", +"Type":"Typ", +"Unable to communicate with Dimension due to an unknown error.":"Kommunikation mit Dimension aufgrund eines unbekannten Fehlers nicht möglich.", +"Unable to load Dimension - missing room ID or token.":"Dimension kann nicht geladen werden - fehlende Raum-ID oder fehlender Token.", +"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server.":"Dimension kann nicht eingerichtet werden. Diese Version von Element wird möglicherweise nicht unterstützt oder es liegt ein Problem mit dem Server vor.", +"Unbridge":"Verbindung trennen", +"Unbridge and continue":"Verbindung trennen und fortfahren", +"URL":"URL", +"Use downsized images":"Bilder verkleinern", +"Use this domain as the default conference domain":"Verwenden Sie diese Domain als Standarddomain für Konferenzen", +"User ID":"User ID", +"User ID:":"User-ID", +"User Prefix":"User-Präfix", +"Utility User ID":"Utility User-ID", +"Even in a private, or non-federated, environment federation needs to be enabled so Dimension can work correctly. Dimension should still work okay if federation on your homeserver is bound to a private interface instead of being public - just be sure to set the federation URL in your configuration.":"Selbst in einer privaten Umgebung muss Federation aktiviert werden, damit Dimension ordnungsgemäß funktioniert. Dimension sollte auch dann funktionieren, wenn Federation in Ihrem Home-Server an eine private Schnittstelle gebunden ist, anstatt öffentlich zu sein. Stellen Sie nur sicher, dass Sie die Federation-URL in Ihrer Konfiguration festlegen.", +"Verify federation is enabled on your homeserver.": "Stellen Sie sicher, dass Federation in Ihrem Home-Server aktiviert ist.", +"Using tools like the": "Sie können dafür Tools wie den", +"federation tester": "Federation-Tester", +", make sure that federation is working on your homeserver.":"nutzen, Stellen Sie sicher, dass der Verband auf Ihrem Heimserver funktioniert", +"Verify that federation is working on your homeserver.": "Stellen Sie sicher, dass Federation in Ihrem Home-Server funktioniert.", +"The name, client/server URL, and access token all need to be valid and directed at your homeserver.":"Der Name, die Client-/Server-URL und das Zugriffstoken müssen gültig sein und an Ihren Home-Server eingestellt sein.", +"Verify the homeserver configuration in Dimension.": "Überprüfen Sie die Home-Server-Konfiguration in Dimension.", +"Version":"Version", +"Version number":"Versionsnummer", +"Video URL":"Video URL", +"Visit":"Besuchen Sie", +"and log in with your Matrix account or point your Element": "und melden Sie sich mit Ihrem Matrix-Konto an oder ändern Sie in Ihrem Element die", +"at our servers:": ", so dass sie auf unseren Server verweist", +"Webhook Bridge":"Webhook-Bridge", +"Webhook bridge added":"Webhook-Bridge hinzugefügt", +"Webhook Bridge Configuration":"Webhook-Bridge Konfiguration", +"Webhook bridge updated":"Webhook-Bridge aktualisiert", +"Webhook created":"Webhook angelegt", +"Webhook deleted":"Webhook gelöscht", +"Webhook Name":"Webhook-Name", +"Webhooks":"Webhooks", +"Webhooks Bridge Configuration":"Webhook-Bridge Konfigurationen", +"Welcome to Dimension!":"Willkommen!", +"When Element cannot reach Dimension or Dimension is unable to reach your homeserver an error saying 'Could not contact integrations server' shows up in every room. Before visiting us in":"Wenn Element Dimension nicht erreichen kann oder Dimension Ihren Home-Server nicht erreichen kann, wird in jedem Raum die Fehlermeldung 'Keine Verbindung zum Integration-Server' angezeigt. Bevor Sie uns in", +"on Matrix, here's a few things to check:": "auf Matrix besuchen, prüfen Sie bitte:", +"Whiteboard":"Whiteboard", +"Whiteboard Name":"Whiteboard-Name", +"Whiteboard URL":"Whiteboard-URL", +"Whiteboard Widgets":"Whiteboard Widgets", +"Widget added!":"Widget hinzugefügt", +"Widget Blacklist":"Widget Sperrliste", +"Widget deleted!":"Widget gelöscht", +"Widget ID: widgetId":"Widget-ID: widgetId", +"Widget Name":"Widget-Name", +"Widget updated":"Widget aktualisiert", +"Widget updated!":"Widget aktualisiert!", +"Widget URL":"Widget-URL", +"Widgets":"Widgets", +"Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.":"Widgets sind kleine Webseiten, die in einen Matrix-Raum eingebettet werden können. Hier können Sie konfigurieren, welche Widgets Dimension Benutzern anbieten wird.", +"Wikipedia":"Wikipedia", +"You":"Sie", +"You cannot modify widgets in this room":"Sie können Widgets in diesem Raum nicht ändern", +"You do not appear to have permission to modify widgets in this room":"Sie scheinen keine Berechtigung zum Ändern von Widgets in diesem Raum zu haben", +"You do not have permission to bridge that chat":"Sie haben keine Berechtigung, diesen Chat zu verbinden", +"You do not have permission to unbridge that chat":"Sie haben keine Berechtigung, die Verbindung zu diesen Chat zu trennen", +"You do not have the necessary permissions in this room to unbridge the channel.":"Sie haben in diesem Raum nicht die erforderlichen Berechtigungen, um die Verbindung zu diesem Channel zu trennen.", +"You have blocked this widget from receiving credentials.":"Sie haben dieses Widget daran gehindert, Anmeldeinformationen zu erhalten.", +"You have blocked this widget from verifying your identity.":"Sie haben dieses Widget daran gehindert, Ihre Identität zu überprüfen.", +"You have no sticker packs.":"Sie haben keine Sticker-Packs", +"You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge the other room and instead bridge it here?":"Sie haben die entsprechenden Berechtigungen, um die Verbindung zum Chat zu trennen. Möchten Sie den anderen Raum öffnen und stattdessen hier verbinden?", +"Your client is too old to use this widget, sorry":"Ihr Client ist zu alt, um dieses Widget zu verwenden", +"Your client is too old to use this widget. Try upgrading your client to the latest available version, or contact the author to try and diagnose the problem. Your client needs to support OpenID information exchange.":"Ihr Client ist zu alt, um dieses Widget zu verwenden. Versuchen Sie, Ihren Client auf die neueste verfügbare Version zu aktualisieren, oder wenden Sie sich an den Autor, um das Problem zu diagnostizieren. Ihr Client muss den OpenID-Informationsaustausch unterstützen.", +"Your Sticker Packs":"Ihre Sticker-Packs", +"your_api_key_here":"Ihr_API_KEY_hier", +"your_client_id":"Ihre_Client_ID", +"your_client_secret":"Ihr_Client_Secret", +"your_cx_id_here":"Ihre_CX_ID_hier", +"You're all set! Click the button below to re-run the test.":"Sie sind fertig! Klicken Sie auf die Schaltfläche unten, um den Test erneut auszuführen.", +"YouTube":"YouTube", +"Youtube Video Widgets":"Youtube Video Widgets", +"The person selected here will be asked to approve or deny the bridge request.": "Die hier ausgewählte Person wird gebeten, die Brückenanforderung zu genehmigen oder abzulehnen.", +"Created by": "Erstellt von", +"under": "unter", + "A webpage embedded in the room.": "Eine Web-Seite in dem Raum eingebettet.", + "Collaborate on documents with members of your room.": "Zusammenarbeit an Dokumenten mit den Mitgliedern Ihres Raum.", + "Share upcoming events in your room with a Google Calendar.": "Teilen Sie bevorstehende Ereignisse in Ihrem Raum mit einem Google Kalender.", + "Embed a Twitch livestream into your room.": "Betten Sie einen Twitch-Livestream in Ihr Raum ein.", + "Monitor your favourite cryptocurrencies": "Überwachen Sie Ihre Lieblings cryptocurrencies", + "Collaborate on and share documents using Google Docs.": "Zusammenarbeit und teilen an Dokumenten mit Google Docs.", + "Hold a video conference with Jitsi Meet": "Halten Sie eine Videokonferenz mit Jitsi Meet ab.", + "Share music with the room": "Teile Musik mit dem Raum", + "A whiteboard app embedded in the room.": "Ein Whiteboard-App in dem Raum eingebettet.", + "Embed a YouTube, Vimeo, or DailyMotion video in your room.": "Betten Sie ein YouTube-, Vimeo- oder DailyMotion-Video in Ihr Raum ein.", + "Embed a graph in the room": "Betten Sie eine Grafik in den Raum ein.", + "Jitsi Conference": "Jitsi Konferenz", + "Bridges IRC channels to rooms, supporting multiple networks": "Überbrückt IRC-Kanäle mit Räumen und unterstützt mehrere Netzwerke", + "Bridges Telegram chats and channels to rooms on Matrix": "Überbrückt Telegramm-Chats und Kanäle zu Räumen auf Matrix", + "Slack-compatible webhooks for your room": "Slack-kompatible Webhooks für Ihr Raum", + "Bridges Gitter rooms to Matrix": "Überbrückt Gitter zu Räumen auf Matrix", + "Bridges Slack channels to Matrix": "Überbrückt Slack Kanäle auf Matrix", + "The most photogenic animal on the planet.": "Das fotogenste Tier der Welt.", + "Cute cats": "Süße katzen", + "Cute cat faces": "Süße Katze Gesichter", + "The official Loading Artist sticker pack!": "Das offizielle Loading Artist Sticker Pack!", + "disabled": "deaktiviert", + "Please enter a feed URL": "Bitte geben Sie eine Feed-URL ein", + "Home": "Home", + "Dimension": "Dimension" +} + diff --git a/web/public/assets/i18n/en.json b/web/public/assets/i18n/en.json new file mode 100644 index 0000000..808900f --- /dev/null +++ b/web/public/assets/i18n/en.json @@ -0,0 +1,587 @@ +{ +"$padName and $roomId will be replaced during creation to help create a unique pad URL.":"$padName and $roomId will be replaced during creation to help create a unique pad URL.", +".travis.yml configuration and template information":".travis.yml configuration and template information", +"languages[code].langName version":"languages[code].langName version", +"was invited to the room":"was invited to the room", +"was removed from the room":" was removed from the room", +"is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).":"go-neb is a multi-purpose bot that can provide various services, such as reaction GIFs and Github notifications. There are two options for go-neb support in Dimension: using matrix.org's or self-hosting it. Each go-neb instance can have multiple services associated with it (ie: one go-neb here can do everything).", +"matrix-appservice-gitter":"matrix-appservice-gitter", +"is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.": "is a Gitter bridge that supports bridging Gitter rooms to Matrix. Users on Matrix are represented as a single bot user in Gitter, however Gitter users are represented as real-looking Matrix users in the room.", +"matrix-appservice-irc": "matrix-appservice-irc", +"is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.": "is an IRC bridge that supports multiple IRC networks. Dimension is capable of using multiple IRC bridges to better distribute the load across multiple networks in large deployments.", +"matrix-appservice-slack": "matrix-appservice-slack", +"is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they'd like to bridge.":"is a Slack bridge that supports bridging Slack channels to Matrix. Users authorize the bridge to access their Slack workspaces and from there they can pick the channels they'd like to bridge.", +"mautrix-telegram":"mautrix-telegram", +"is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a 'relay bot' (all Matrix users are represented through a single bot in Telegram) or by making use of a user's real Telegram account (known as 'puppeting'). Currently only one Telegram bridge can be configured at a time.": "is a Telegram bridge that supports bridging channels/supergroups to Matrix. This can be done through a 'relay bot' (all Matrix users are represented through a single bot in Telegram) or by making use of a user's real Telegram account (known as 'puppeting'). Currently only one Telegram bridge can be configured at a time.", +"matrix-appservice-webhooks": "matrix-appservice-webhooks", +"provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.":"provides Slack-compatible webhooks for Matrix, making it easy to send updates into a room.", +"The author of the commit":"The author of the commit", +"The branch name":"The branch name", +"The build ID":"The build ID", +"The build number":"The build number", +"A URL to see the build information":"A URL to see the build information", +"The full commit message":"The full commit message", +"The first line of the commit message":"The first line of the commit message", +"A short version of the commit SHA":"A short version of the commit SHA", +"A URL to see the changes which triggered the build":"A URL to see the changes which triggered the build", +"The total duration of all builds in the matrix":"The total duration of all builds in the matrix", +"The time it took to run the build":"The time it took to run the build", +"The message from Travis CI about the build":"The message from Travis CI about the build", +"The repository name":"The repository name", +"The repository identifier":"The repository identifier", +"The result of the build":" '%result' - The result of the build", +"A few words here will help people understand what the bot does.":"A few words here will help people understand what the bot does.", +"Access Token":"Access Token", +"Actions":"Actions", +"Add":"Add", +"Add widgetComponent.defaultName ":"Add widgetComponent.defaultName ", +"Add a new custom bot":"Add a new custom bot", +"self-hosted Gitter bridge":"self-hosted Gitter bridge ", +"Add a new self-hosted IRC Bridge":"Add a new self-hosted IRC Bridge ", +"self-hosted Slack bridge":"self-hosted Slack bridge ", +"self-hosted Telegram bridge":"self-hosted Telegram bridge ", +"self-hosted webhook bridge":"self-hosted webhook bridge ", +"Add a new webhook":"Add a new webhook", +"Add an IRC channel":"Add an IRC channel", +"Add custom bot":"Add custom bot", +"Add matrix.org's bridge":"Add matrix.org's bridge", +"Add matrix.org's go-neb":"Add matrix.org's go-neb", +"Add self-hosted bridge":"Add self-hosted bridge", +"Add self-hosted go-neb":"Add self-hosted go-neb", +"Add some stickers":"Add some stickers", +"Add Sticker Packs":"Add Sticker Packs", +"Add stickerpack":"Add stickerpack", +"Add utility for everyone in your room by embedding an application.":"Add utility for everyone in your room by embedding an application.", +"Add Widget":"Add Widget", +"Added by":"Added by", +"Admin":"Admin", +"Administrators":"Administrators", + "After inviting":"After inviting", + "to your Telegram chat, run the command": "to your Telegram chat, run the command", + "in the Telegram room to get the chat ID.": "in the Telegram room to get the chat ID.", + "An error has occurred - see logs for details":"An error has occurred - see logs for details", +"An open source integration manager for Matrix":"An open source integration manager for Matrix", +"Api Key":"Api Key", +"API URL":"API URL", +"Author":"Author", +"Avatar URL":"Avatar URL", +"Before users can use Dimension they must agree to the terms of service for using your instance. If you're using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.":"Before users can use Dimension they must agree to the terms of service for using your instance. If you're using any matrix.org bridges, users will be required to accept the terms of service for your upstream integration managers (scalar.vector.im usually) in addition to the terms you add here.", +"Bot disabled":"Bot disabled", +"Bot enabled":"Bot enabled", +"Bot updated":"Bot updated", +"Bots":"Bots", +"Bots bring entertainment or productivity to the room. They're here to help at your command.":"Bots bring entertainment or productivity to the room. They're here to help at your command.", +"Bridge":"Bridge", +"Bridge removed":"Bridge removed", +"Bridge requested":"Bridge requested", +"Bridge to Gitter":"Bridge to Gitter", +"Bridge to Slack":"Bridge to Slack", +"Bridge to Telegram":"Bridge to Telegram", +"Bridge updated":"Bridge updated", +"Bridges":"Bridges", +"Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.":"Bridges provide a way for rooms to interact with and/or bring in events from a third party network. For example, an IRC bridge can allow IRC and matrix users to communicate with each other.", +"Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.":"Bridging a channel requires authorization from a channel operator. When entering a channel below, a bot will join the channel to ensure it exists and has operators available.", +"Bring the outside world into your room with bridges.":"Bring the outside world into your room with bridges.", +"Cancel":"Cancel", +"Cat Faces":"Cat Faces", +"Cats":"Cats", +"Channel":"Channel", +"Channel Name":"Channel Name", +"Chat ID":"Chat ID", +"Check connection":"Check connection", +"Checking client version...":"Checking client version...", +"Checking connectivity to homeserver...":"Checking connectivity to homeserver...", +"Checking connectivity to integration manager...":"Checking connectivity to integration manager...", +"Click 'share' from your favourite playlist, artist, track, or album and paste the Spotify URI here.":"Click 'share' from your favourite playlist, artist, track, or album and paste the Spotify URI here.", +"Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.":"Click the button to test your connection. This may cause your client to ask if it is okay to share your identity with the widget - this is required to test your connection to your homeserver.", +"Click the pencil icon to enable networks.":"Click the pencil icon to enable networks.", +"Click the pencil icon to enable the bots.":"Click the pencil icon to enable the bots.", +"Click to start OpenID auth":"Click to start OpenID auth", +"Client ID":"Client ID", +"Client Secret":"Client Secret", +"Client/Server URL":"Client/Server URL", +"Close":"Close", +"Conference URL":"Conference URL", +"Configuration":"Configuration", +"Configuration updated":"Configuration updated", +"Configuring integrations":"Configuring integrations", +"Copy and paste this configuration to":"", +"on your homeserver and register it as an application service.": "","Could not communicate with Element":"Could not communicate with Element", +"Could not connect to integrations server error":"Could not connect to integrations server error", +"Could not get go-neb configuration":"Could not get go-neb configuration", +"Could not load appservice configuration":"Could not load appservice configuration", +"Could not update integration status":"Could not update integration status", +"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!":"Could not verify your token. Please try logging out of Element and back in. Be sure to back up your encryption keys!", +"Create":"Create", +"Create draft":"Create draft", +"Custom Bots":"Custom Bots", +"Custom bots":"Custom bots", +"Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can't have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.":"Custom bots give you the ability to add your own bots to Dimension for users to add to their rooms. These bots can't have any configuration to them and must be able to accept room invites on their own. All Dimension will do when a user wants to add the bot is invite it to the room.", +"Custom Widget":"Custom Widget", +"Custom Widgets":"Custom Widgets", +"Dashboard":"Dashboard", +"Default Pad URL Template":"Default Pad URL Template", +"Delete":"Delete", +"Description":"Description", +"Dimension":"Dimension", +"Display Name":"Display Name", +"Document URL":"Document URL", +"Draft created":"Draft created", +"Draft saved":"Draft saved", +"Echo":"Echo", +"Edit custom bot":"Edit custom bot", +"Edit go-neb":"Edit go-neb", +"Edit policy":"Edit policy", +"Edit self-hosted Gitter bridge":"Edit self-hosted Gitter bridge", +"Edit self-hosted Slack bridge":"Edit self-hosted Slack bridge", +"Edit self-hosted Telegram bridge":"Edit self-hosted Telegram bridge", +"Edit self-hosted webhook bridge":"Edit self-hosted webhook bridge", +"eg: 1.1.0":"eg: 1.1.0", +"Enabled":"Enabled", +"Enabled Bots":"Enabled Bots", +"Enabled Features":"Enabled Features", +"Enabled Networks":"Enabled Networks", +"Error adding matrix.org's Gitter Bridge":"Error adding matrix.org's Gitter Bridge", +"Error adding matrix.org's go-neb":"Error adding matrix.org's go-neb", +"Error adding matrix.org's IRC Bridge":"Error adding matrix.org's IRC Bridge", +"Error adding matrix.org's Slack Bridge":"Error adding matrix.org's Slack Bridge", +"Error adding stickerpack":"Error adding stickerpack", +"Error bridging room":"Error bridging room", +"Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.":"Error checking if the integration manager is alive. This usually means that the manager which served this widget has gone offline.", +"Error communicating with Element":"Error communicating with Element", +"Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver's documentation for how to set up federation.":"Error contacting homeserver. This usually means your federation setup is incorrect, or your homeserver is offline. Consult your homeserver's documentation for how to set up federation.", +"Error creating appservice":"Error creating appservice", +"Error creating document":"Error creating document", +"Error creating matrix.org go-neb":"Error creating matrix.org go-neb", +"Error creating matrix.org's Gitter Bridge":"Error creating matrix.org's Gitter Bridge", +"Error creating matrix.org's IRC Bridge":"Error creating matrix.org's IRC Bridge", +"Error creating matrix.org's Slack Bridge":"Error creating matrix.org's Slack Bridge", +"Error creating webhook":"Error creating webhook", +"Error deleting webhook":"Error deleting webhook", +"Error getting channels for team":"Error getting channels for team", +"Error getting Slack authorization information":"Error getting Slack authorization information", +"Error getting teams":"Error getting teams", +"Error importing sticker pack":"Error importing sticker pack", +"Error inviting bridge":"Error inviting bridge", +"Error loading bridges":"Error loading bridges", +"Error loading channel operators":"Error loading channel operators", +"Error loading configuration":"Error loading configuration", +"Error loading go-neb configuration":"Error loading go-neb configuration", +"Error loading policy":"Error loading policy", +"Error logging everyone out":"Error logging everyone out", +"Error opening configuration page":"Error opening configuration page", +"Error publishing policy":"Error publishing policy", +"Error removing bridge":"Error removing bridge", +"Error requesting bridge":"Error requesting bridge", +"Error saving policy":"Error saving policy", +"Error updating bot":"Error updating bot", +"Error updating configuration":"Error updating configuration", +"Error updating integration":"Error updating integration", +"Error updating sticker pack":"Error updating sticker pack", +"Error updating stickers":"Error updating stickers", +"Error updating widget":"Error updating widget", +"Etherpad Widget Configuration":"Etherpad Widget Configuration", +"Everyone has been logged out":"Everyone has been logged out", +"Expected to not be able to send specific event types":"Expected to not be able to send specific event types", +"Expected to be able to send specific event types":"Expected to be able to send specific event types", +"Failed to configure the integration":"Failed to configure the integration", +"Failed to create Gitter bridge":"Failed to create Gitter bridge", +"Failed to create IRC bridge":"Failed to create IRC bridge", +"Failed to create Slack bridge":"Failed to create Slack bridge", +"Failed to create Telegram bridge":"Failed to create Telegram bridge", +"Failed to create Webhook bridge":"Failed to create Webhook bridge", +"Failed to get an update Gitter bridge list":"Failed to get an update Gitter bridge list", +"Failed to get an update IRC bridge list":"Failed to get an update IRC bridge list", +"Failed to get an update Slack bridge list":"Failed to get an update Slack bridge list", +"Failed to get an update Telegram bridge list":"Failed to get an update Telegram bridge list", +"Failed to get an update Webhooks bridge list":"Failed to get an update Webhooks bridge list", +"Failed to get an updated bot list":"Failed to get an updated bot list", +"Failed to load bridges":"Failed to load bridges", +"Failed to load configuration":"Failed to load configuration", +"Failed to load policies":"Failed to load policies", +"Failed to load policy":"Failed to load policy", +"Failed to load sticker packs":"Failed to load sticker packs", +"Failed to load widgets":"Failed to load widgets", +"Failed to make the bridge an administrator":"Failed to make the bridge an administrator", +"Failed to remove link":"Failed to remove link", +"Failed to request a link":"Failed to request a link", +"Failed to take screenshot":"Failed to take screenshot", +"Failed to take screenshot: iframe not supported":"Failed to take screenshot: iframe not supported", +"Failed to update Gitter bridge":"Failed to update Gitter bridge", +"Failed to update network":"Failed to update network", +"Failed to update Slack bridge":"Failed to update Slack bridge", +"Failed to update Telegram bridge":"Failed to update Telegram bridge", +"Failed to update Webhook bridge":"Failed to update Webhook bridge", +"Federation Hostname":"Federation Hostname", +"Federation URL":"Federation URL", +"Feeds":"Feeds", +"GIFs can be large, and sometimes it is more desirable to have them downsized.":"GIFs can be large, and sometimes it is more desirable to have them downsized.", +"Giphy":"Giphy", +"Giphy Configuration":"Giphy Configuration", +"Gitter":"Gitter", +"Gitter Bridge":"Gitter Bridge", +"Gitter bridge added":"Gitter bridge added", +"Gitter Bridge Configuration":"Gitter Bridge Configuration", +"Gitter Bridge Configurations":"Gitter Bridge Configurations", +"Gitter bridge updated":"Gitter bridge updated", +"Gitter Room":"Gitter Room", +"go-neb":"go-neb", +"go-neb appservice configuration":"go-neb appservice configuration", +"go-neb configuration":"go-neb configuration", +"go-neb configurations":"go-neb configurations", +"go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.":"go-neb supports many different types of bots, each of which is listed below. Here you can configure which bots this go-neb instance should use.", +"Google Calendar":"Google Calendar", +"Google Calendar Widgets":"Google Calendar Widgets", +"Google Configuration":"Google Configuration", +"Google Doc":"Google Doc", +"Google Doc Widgets":"Google Doc Widgets", +"Google Image Search":"Google Image Search", +"Grafana":"Grafana", +"Grafana URL":"Grafana URL", +"Grafana Widgets":"Grafana Widgets", +"Guggy":"Guggy", +"Guggy Configuration":"Guggy Configuration", +"Have some fun and post a sticker.":"Have some fun and post a sticker.", +"Here's the configuration options you'll need to update in your Element":"Here's the configuration options you'll need to update in your Element", +"Home":"Home", +"Homeserver":"Homeserver", +"Huskies":"Huskies", +"If enabled, Dimension will recommend that users log in to their Matrix accounts.":"If enabled, Dimension will recommend that users log in to their Matrix accounts.", +"If enabled, Dimension will recommend that users log in to their Telegram accounts.":"If enabled, Dimension will recommend that users log in to their Telegram accounts.", +"If everything is set up correctly, you'll be able to access the admin area of Dimension by clicking the 3x3 grid in the top right of any room in Element. The gear icon":"If everything is set up correctly, you'll be able to access the admin area of Dimension by clicking the 3x3 grid in the top right of any room in Element. The gear icon", +"in the top right is where you can configure your bots, bridges, and widgets.": "in the top right is where you can configure your bots, bridges, and widgets.", +"Image Size":"Image Size", +"Imgur":"Imgur", +"Imgur Configuration":"Imgur Configuration", +"Import from Telegram":"Import from Telegram", +"In order to bridge Slack channels, you'll need to authorize the bridge to access your teams and channels. Please click the button below to do so.":"In order to bridge Slack channels, you'll need to authorize the bridge to access your teams and channels. Please click the button below to do so.", +"Integration updated":"Integration updated", +"Integrations":"Integrations", +"Integrations are not encrypted!":"Integrations are not encrypted!", +"Interval":"Interval", +"IRC":"IRC", +"IRC Bridge":"IRC Bridge", +"IRC Bridge added":"IRC Bridge added", +"IRC Bridge Configuration":"IRC Bridge Configuration", +"IRC Bridge Configurations":"IRC Bridge Configurations", +"IRC Networks":"IRC Networks", +"Jitsi":"Jitsi", +"Jitsi Domain":"Jitsi Domain", +"Jitsi Script URL":"Jitsi Script URL", +"Jitsi Video Conference":"Jitsi Video Conference", +"Jitsi Widget Configuration":"Jitsi Widget Configuration", +"Jitsi Widgets":"Jitsi Widgets", +"Join":"Join", +"for news and updates. Don't forget to star the repository on": "for news and updates. Don't forget to star the repository on", +"Join Conference":"Join Conference", +"License":"License", +"Link removed":"Link removed", +"Link requested!":"Link requested!", +"Loading Artist":"Loading Artist", +"Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.":"Logging everyone out will disable all known login tokens for Dimension and upstream integration managers. Most clients will automatically re-register for a login token behind the scenes, similar to how a login token was first acquired.", +"Logout confirmation":"Logout confirmation", +"Logout Everyone":"Logout Everyone", +"Looking for your sticker packs?":"Looking for your sticker packs?", + "Click here": "Click here", +"Manual troubleshooting may be requred":"Manual troubleshooting may be requred", +"matrix.org's bridge":"matrix.org's bridge", +"matrix.org's Gitter bridge added":"matrix.org's Gitter bridge added", +"matrix.org's go-neb":"matrix.org's go-neb", +"matrix.org's go-neb added":"matrix.org's go-neb added", +"matrix.org's IRC bridge added":"matrix.org's IRC bridge added", +"matrix.org's IRC Bridge Networks":"matrix.org's IRC Bridge Networks", +"matrix.org's Slack bridge added":"matrix.org's Slack bridge added", +"My Policy":"My Policy", +"Name":"Name", +"Name: config.homeserver.name ":"Name: config.homeserver.name ", +"Network":"Network", +"Network disabled":"Network disabled", +"Network enabled":"Network enabled", +"New draft policy":"New draft policy", +"New feed URL":"New feed URL", +"New go-neb created":"New go-neb created", +"New policy":"New policy", +"New repository name":"New repository name", +"New self-hosted go-neb":"New self-hosted go-neb", +"Next":"Next", +"No bridge configurations.":"No bridge configurations.", +"No bridged channels":"No bridged channels", +"No bridges.":"No bridges.", +"No config component for bot.type":"No config component for bot.type", +"No custom bots.":"No custom bots.", +"No go-neb configurations.":"No go-neb configurations.", +"No integrations available":"No integrations available", +"No name":"No name", +"No policies written.":"No policies written.", +"No sticker packs installed.":"No sticker packs installed.", +"No webhooks":"No webhooks", +"No, don't bridge":"No, don't bridge", +"None":"None", +"not specified":"not specified", +"Notes":"Notes", +"Notes Widgets":"Notes Widgets", +"Operator":"Operator", +"Pad Name":"Pad Name", +"Pad URL":"Pad URL", +"Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.":"Parts of your configuration are displayed below. To change these values, edit your configuration and restart Dimension.", +"Please accept the prompt to verify your identity":"Please accept the prompt to verify your identity", +"Please accept the prompt to verify your identity.":"Please accept the prompt to verify your identity.", +"Please ensure you are an 'Admin' for the room":"Please ensure you are an 'Admin' for the room", +"Please enter a channel name":"Please enter a channel name", +"Please enter a description for the bot":"Please enter a description for the bot", +"Please enter a Grafana URL":"Please enter a Grafana URL", +"Please enter a name for all policies":"Please enter a name for all policies", +"Please enter a name for the bot":"Please enter a name for the bot", +"Please enter a repository":"Please enter a repository", +"Please enter a shared calendar ID":"Please enter a shared calendar ID", +"Please enter a URL for the widget":"Please enter a URL for the widget", +"Please enter a user ID for the bot":"Please enter a user ID for the bot", +"Please enter a version number":"Please enter a version number", +"Please enter a video URL":"Please enter a video URL", +"Please enter a YouTube, Vimeo, or DailyMotion video URL":"Please enter a YouTube, Vimeo, or DailyMotion video URL", +"Please enter an access token for the bot":"Please enter an access token for the bot", +"Please enter an avatar URL for the bot":"Please enter an avatar URL for the bot", +"Please enter text for all policies":"Please enter text for all policies", +"Policy Name":"Policy Name", +"Policy published":"Policy published", +"Policy text":"Policy text", +"Promote Matrix Puppeting":"Promote Matrix Puppeting", +"Promote Telegram Puppeting":"Promote Telegram Puppeting", +"Provisioning URL":"Provisioning URL", +"Publish":"Publish", +"Publish policy":"Publish policy", +"Remove":"Remove", +"Remove Widget":"Remove Widget", +"Repositories":"Repositories", +"Repository Template":"Repository Template", +"Request Bridge":"Request Bridge", +"Requirement":"Requirement ", +"not found": " not found", +"RSS Bot Configuration":"RSS Bot Configuration", +"RSS Notifications":"RSS Notifications", +"Save":"Save", +"Save draft":"Save draft", +"Save Widget":"Save Widget", +"Search Engine ID":"Search Engine ID", +"Self-host your favourite bots, bridges, and widgets.":"Self-host your favourite bots, bridges, and widgets.", +"Self-hosted bridge":"Self-hosted bridge", +"Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"Self-hosted Gitter bridges already have provisioning enabled. Be careful not to expose the API to the public internet.", +"Self-hosted go-neb":"Self-hosted go-neb", +"Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.":"Self-hosted go-neb instances are powered by application services installed on your homeserver. The application service is responsible for creating the bots dynamically.", +"Self-hosted IRC Bridge Networks":"Self-hosted IRC Bridge Networks", +"Self-hosted IRC bridges must have": "Self-hosted IRC bridges must have", +"provisioning":"provisioning", +"enabled in the configuration.":"enabled in the configuration.", +"Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.":"Self-hosted Slack bridges already have provisioning enabled. Be careful not to expose the API to the public internet.", +"Self-hosted Telegram bridges must have":"Self-hosted Telegram bridges must have", +"Self-hosted webhook bridges must have":"Self-hosted webhook bridges must have", +"Sessions":"Sessions", +"Sessions":"Settings", +"Shared Calendar ID":"Shared Calendar ID", +"Shared Secret":"Shared Secret", +"Slack":"Slack", +"Slack Bridge":"Slack Bridge", +"Slack bridge added":"Slack bridge added", +"Slack Bridge Configuration":"Slack Bridge Configuration", +"Slack Bridge Configurations":"Slack Bridge Configurations", +"Slack bridge updated":"Slack bridge updated", +"Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you'll force Dimension to use your Jitsi domain at risk of having clients not respect it.":"Some clients can create widgets that are not compatible with Dimension, making Dimension use jitsi.riot.im by default. By enabling this option, you'll force Dimension to use your Jitsi domain at risk of having clients not respect it.", +"some_secret_value":"some_secret_value", +"Sorry, this content cannot be embedded":"Sorry, this content cannot be embedded", +"source":"source", +"source on GitHub":"source on GitHub", +"Spotify":"Spotify", +"Spotify URI":"Spotify URI", +"Spotify Widgets":"Spotify Widgets", +"Start a conversation with":"Start a conversation with", +"to create your own stickerpack.": "to create your own stickerpack.", +"Sticker pack updated":"Sticker pack updated", +"Sticker Pack: pack.displayName ":"Sticker Pack: pack.displayName ", +"Sticker Packs":"Sticker Packs", +"Sticker packs are not enabled on this Dimension instance.":"Sticker packs are not enabled on this Dimension instance.", +"Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the 'sticker picker' widget will be disabled.":"Sticker packs provide a way to convey memes or feelings to others in a room. From here you're able to select which sticker packs users of this Dimension instance can use. If no sticker packs are enabled then the 'sticker picker' widget will be disabled.", +"Stickerpack added":"Stickerpack added", +"Stickerpack URL":"Stickerpack URL", +"Stickers":"Stickers", +"Stickers updated":"Stickers updated", +"Team":"Team", +"Telegram":"Telegram", +"Telegram Bridge":"Telegram Bridge", +"Telegram bridge added":"Telegram bridge added", +"Telegram Bridge Configuration":"Telegram Bridge Configuration", +"Telegram Bridge Configurations":"Telegram Bridge Configurations", +"Telegram bridge updated":"Telegram bridge updated", +"Telegram chat is already bridged":"Telegram chat is already bridged", +"Telegram sticker pack imported":"Telegram sticker pack imported", +"Template":"Template", +"Terms of Service":"Terms of Service", +"Test Configuration":"Test Configuration", +"That Telegram chat is already bridged to another room":"That Telegram chat is already bridged to another room", +"That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not have the required permissions to be able to unbridge the other room.":"That Telegram chat is bridged to another Matrix room and cannot be bridged here. Unfortunately, you do not have the required permissions to be able to unbridge the other room.", +"The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.":"The admin/api url for go-neb. Be sure to not expose the admin API to the outside world because this endpoint is not authenticated.", +"The API key for":"The API key for", +"The API key for your Google Application.":"The API key for your Google Application.", +"The API key from":"The API key from", +"The appservice appears to be correctly set up":"The appservice appears to be correctly set up", +"The appservice is not correctly set up":"The appservice is not correctly set up", +"The client ID of your":"The client ID of your", +"Imgur Application": "Imgur Application", +"The client secret of your":"The client secret of your", + "The following section needs to be added to your":"", + "file in your repositories:": "", + "The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.":"The following variables can be used in your template. This template is used to post a message to theroom when your webhook is activated.", +"The operator selected will have to approve the bridge for it to work":"The operator selected will have to approve the bridge for it to work", +"The provisioning secret defined in the configuration.":"The provisioning secret defined in the configuration.", +"The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.":"The provisioning URL for the bridge. This is the public address for the bridge followed by the provisioning prefix given in the configuration.", +"The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.":"The provisioning URL for the bridge. This is usually the same as the URL given in the registration. This API is not authenticated and should be treated with caution.", +"The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.":"The provisioning URL for the bridge. This is usually the same as the URL your homeserver uses to communicate with the bridge.", +"The public URL for the bridge.":"The public URL for the bridge.", +"The room must be":"The room must be", +"to use this integration":"to use this integration", +"The search engine ID":"The search engine ID", +"The shared secret defined in the configuration for provisioning.":"The shared secret defined in the configuration for provisioning.", +"The Telegram bot has not been invited to the chat":"The Telegram bot has not been invited to the chat", +"The translated name of your policy":"The translated name of your policy", +"The user ID that Dimension will invite to rooms.":"The user ID that Dimension will invite to rooms.", +"The version number of this policy":"The version number of this policy", +"There are currently no integrations which support encrypted rooms. Sorry about that!":"There are currently no integrations which support encrypted rooms. Sorry about that!", +"There was a problem authenticating your use of this sticker picker. Please make sure you're using a client that has Dimension enabled and correctly set up.":"There was a problem authenticating your use of this sticker picker. Please make sure you're using a client that has Dimension enabled and correctly set up.", +"This bot is handled by another go-neb instance":"This bot is handled by another go-neb instance", +"This bridge is offline or unavailable.":"This bridge is offline or unavailable.", +"This can either be an MXC URI or a plain URL.":"This can either be an MXC URI or a plain URL.", +"This integration is not supported in encrypted rooms":"This integration is not supported in encrypted rooms", +"This integration is offline or unavailable":"This integration is offline or unavailable", +"This is the domain that is used to host the conference.":"This is the domain that is used to host the conference.", +"This is the name Dimension will use to tell users which bot this is.":"This is the name Dimension will use to tell users which bot this is.", +"This is the prefix used for all bot users.":"This is the prefix used for all bot users.", +"This is used by Dimension to force the bot to leave the room when the user removes the bot.":"This is used by Dimension to force the bot to leave the room when the user removes the bot.", +"Learn more about access tokens.": "Learn more about access tokens.", +"This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.":"This is used to create the Jitsi widget. It is normally at /libs/external_api.min.js from your domain.", +"This is where you put your policy's content.":"This is where you put your policy's content.", +"This means that some information about yourself and the room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display name, your username, your avatar, information about Element, and other similar details. Add integrations with caution.":"This means that some information about yourself and the room may be leaked to the bot, bridge, or widget. This information includes the room ID, your display name, your username, your avatar, information about Element, and other similar details. Add integrations with caution.", +"This room does not have any compatible integrations. Please contact the server owner if you're seeing this message.":"This room does not have any compatible integrations. Please contact the server owner if you're seeing this message.", +"This room is already bridged to a Telegram chat":"This room is already bridged to a Telegram chat", + "This room is bridged to on Slack":"This room is bridged to", + "This room is bridged to on Gitter":"This room is bridged to", + "This room is bridged to on Telegram":"This room is bridged to", + "on Slack": "on Slack.", + "on Gitter": "on Gitter", + "on Telegram": "on Telegram", +"This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.":"This room is bridged to Slack using webhooks. Webhook bridging is legacy and doesn't support as rich bridging as the new approach. It is recommended to re-create the bridge with the new process.", +"This room is encrypted":"This room is encrypted", +"To get a URL, go to Grafana and click 'share' on a graph.":"To get a URL, go to Grafana and click 'share' on a graph.", +"Tokens registered":"Tokens registered", +"Trading Pair":"Trading Pair", +"TradingView":"TradingView", +"TradingView Widgets":"TradingView Widgets", +"Travis CI":"Travis CI", +"Travis CI Configuration":"Travis CI Configuration", + "Try it out or":"Try it out or", + "run your own": "run your own", + "Twitch Livestream":"Twitch Livestream", +"Twitch Livestream Widgets":"Twitch Livestream Widgets", +"TwitchUsername":"TwitchUsername", +"Type":"Type", +"Unable to communicate with Dimension due to an unknown error.":"Unable to communicate with Dimension due to an unknown error.", +"Unable to load Dimension - missing room ID or token.":"Unable to load Dimension - missing room ID or token.", +"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server.":"Unable to set up Dimension. This version of Element may not supported or there may be a problem with the server.", +"Unbridge":"Unbridge", +"Unbridge and continue":"Unbridge and continue", +"URL":"URL", +"Use downsized images":"Use downsized images", +"Use this domain as the default conference domain":"Use this domain as the default conference domain", +"User ID":"User ID", +"User ID:":"User ID:", +"User Prefix":"User Prefix", +"Utility User ID":"Utility User ID", + "Even in a private, or non-federated, environment federation needs to be enabled so Dimension can work correctly. Dimension should still work okay if federation on your homeserver is bound to a private interface instead of being public - just be sure to set the federation URL in your configuration.":"Even in a private, or non-federated, environment federation needs to be enabled so Dimension can work correctly. Dimension should still work okay if federation on your homeserver is bound to a private interface instead of being public - just be sure to set the federation URL in your configuration.", + "Verify federation is enabled on your homeserver.": "Verify federation is enabled on your homeserver.", + "Using tools like the": "Using tools like the", + "federation tester": "federation tester", + ", make sure that federation is working on your homeserver.":", make sure that federation is working on your homeserver.", + "Verify that federation is working on your homeserver.": "Verify that federation is working on your homeserver.", + "The name, client/server URL, and access token all need to be valid and directed at your homeserver.":"The name, client/server URL, and access token all need to be valid and directed at your homeserver.", + "Verify the homeserver configuration in Dimension.": "Verify the homeserver configuration in Dimension.", + "Version":"Version", +"Version number":"Version number", +"Video URL":"Video URL", +"Visit and log in with your Matrix account or point your Element config.json at our servers:":"Visit element.t2host.io and log in with your Matrix account or point your Element config.json at our servers:", + "Visit":"Visit", + "and log in with your Matrix account or point your Element": "and log in with your Matrix account or point your Element", + "at our servers:": "at our servers:", + "Webhook Bridge":"Webhook Bridge", +"Webhook bridge added":"Webhook bridge added", +"Webhook Bridge Configuration":"Webhook Bridge Configuration", +"Webhook bridge updated":"Webhook bridge updated", +"Webhook created":"Webhook created", +"Webhook deleted":"Webhook deleted", +"Webhook Name":"Webhook Name", +"Webhooks":"Webhooks", +"Webhooks Bridge Configuration":"Webhooks Bridge Configuration", +"Welcome to Dimension!":"Welcome to Dimension!", +"When Element cannot reach Dimension or Dimension is unable to reach your homeserver an error saying 'Could not contact integrations server' shows up in every room. Before visiting us in":"When Element cannot reach Dimension or Dimension is unable to reach your homeserver an error saying 'Could not contact integrations server' shows up in every room. Before visiting us in", +"on Matrix, here's a few things to check:": "on Matrix, here's a few things to check:", +"Whiteboard":"Whiteboard", +"Whiteboard Name":"Whiteboard Name", +"Whiteboard URL":"Whiteboard URL", +"Whiteboard Widgets":"Whiteboard Widgets", +"Widget added!":"Widget added!", +"Widget Blacklist":"Widget Blacklist", +"Widget deleted!":"Widget deleted!", +"Widget ID: widgetId":"Widget ID: widgetId", +"Widget Name":"Widget Name", +"Widget updated":"Widget updated", +"Widget updated!":"Widget updated!", +"Widget URL":"Widget URL", +"Widgets":"Widgets", +"Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.":"Widgets are small webpages that can be embedded in a Matrix room. Here you can configure which widgets Dimension will offer to users.", +"Wikipedia":"Wikipedia", +"You":"You", +"You cannot modify widgets in this room":"You cannot modify widgets in this room", +"You do not appear to have permission to modify widgets in this room":"You do not appear to have permission to modify widgets in this room", +"You do not have permission to bridge that chat":"You do not have permission to bridge that chat", +"You do not have permission to unbridge that chat":"You do not have permission to unbridge that chat", +"You do not have the necessary permissions in this room to unbridge the channel.":"You do not have the necessary permissions in this room to unbridge the channel.", +"You have blocked this widget from receiving credentials.":"You have blocked this widget from receiving credentials.", +"You have blocked this widget from verifying your identity.":"You have blocked this widget from verifying your identity.", +"You have no sticker packs.":"You have no sticker packs.", +"You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge the other room and instead bridge it here?":"You have the appropriate permissions to be able to unbridge the chat, however. Would you like to unbridge the other room and instead bridge it here?", +"Your client is too old to use this widget, sorry":"Your client is too old to use this widget, sorry", +"Your client is too old to use this widget. Try upgrading your client to the latest available version, or contact the author to try and diagnose the problem. Your client needs to support OpenID information exchange.":"Your client is too old to use this widget. Try upgrading your client to the latest available version, or contact the author to try and diagnose the problem. Your client needs to support OpenID information exchange.", +"Your Sticker Packs":"Your Sticker Packs", +"your_api_key_here":"your_api_key_here", +"your_client_id":"your_client_id", +"your_client_secret":"your_client_secret", +"your_cx_id_here":"your_cx_id_here", +"You're all set! Click the button below to re-run the test.":"You're all set! Click the button below to re-run the test.", +"YouTube":"YouTube", +"Youtube Video Widgets":"Youtube Video Widgets", +"The person selected here will be asked to approve or deny the bridge request.": "The person selected here will be asked to approve or deny the bridge request.", +"Created by": "Created by", +"under": "under", + "A webpage embedded in the room.": "A webpage embedded in the room.", + "Collaborate on documents with members of your room.": "Collaborate on documents with members of your room.", + "Share upcoming events in your room with a Google Calendar.": "Share upcoming events in your room with a Google Calendar.", + "Embed a Twitch livestream into your room.": "Embed a Twitch livestream into your room.", + "Monitor your favourite cryptocurrencies": "Monitor your favourite cryptocurrencies", + "Collaborate on and share documents using Google Docs.": "Collaborate on and share documents using Google Docs.", + "Hold a video conference with Jitsi Meet": "Hold a video conference with Jitsi Meet", + "Share music with the room": "Share music with the room", + "A whiteboard app embedded in the room.": "A whiteboard app embedded in the room.", + "Embed a YouTube, Vimeo, or DailyMotion video in your room.": "Embed a YouTube, Vimeo, or DailyMotion video in your room.", + "Embed a graph in the room": "Embed a graph in the room", + "Jitsi Conference": "Jitsi Conference", + "Bridges IRC channels to rooms, supporting multiple networks": "Bridges IRC channels to rooms, supporting multiple networks", + "Bridges Telegram chats and channels to rooms on Matrix": "Bridges Telegram chats and channels to rooms on Matrix", + "Slack-compatible webhooks for your room": "Slack-compatible webhooks for your room", + "Bridges Gitter rooms to Matrix": "Bridges Gitter rooms to Matrix", + "Bridges Slack channels to Matrix": "Bridges Slack channels to Matrix", + "The most photogenic animal on the planet.": "The most photogenic animal on the planet.", + "Cute cats": "Cute cats", + "Cute cat faces": "Cute cat faces", + "The official Loading Artist sticker pack!": "The official Loading Artist sticker pack!", + "disabled": "disabled", + "Please enter a feed URL": "Please enter a feed URL", + "Home": "Home", + "Dimension": "Dimension" +} diff --git a/web/public/img/avatars/whiteboard.png b/web/public/img/avatars/whiteboard.png new file mode 100644 index 0000000000000000000000000000000000000000..a246526b524676d0c107867b60265dfcc04dcaa0 GIT binary patch literal 12472 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 vfpw2f)!FEiU-%r0QkW#>3(V7O(#o0ib1n literal 0 HcmV?d00001 From c0e836890e363b3b20b3705f3f6f18fd6cbe490b Mon Sep 17 00:00:00 2001 From: Steffen Kolmer Date: Thu, 10 Dec 2020 12:54:54 +0100 Subject: [PATCH 2/2] Delete whiteboard.png --- web/public/img/avatars/whiteboard.png | Bin 12472 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 web/public/img/avatars/whiteboard.png diff --git a/web/public/img/avatars/whiteboard.png b/web/public/img/avatars/whiteboard.png deleted file mode 100644 index a246526b524676d0c107867b60265dfcc04dcaa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12472 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 vfpw2f)!FEiU-%r0QkW#>3(V7O(#o0ib1n