summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2017-11-05 23:31:21 +0100
committerLibravatar GitHub <noreply@github.com>2017-11-05 23:31:21 +0100
commit84bff14bf649969b3729b2c751b423d33e508f0b (patch)
treea585b92b88fa10998a7100b78152b2a18f388968
parentMerge pull request #213 from alecive/master (diff)
parentbump version to beta 12 (diff)
downloadferdium-app-84bff14bf649969b3729b2c751b423d33e508f0b.tar.gz
ferdium-app-84bff14bf649969b3729b2c751b423d33e508f0b.tar.zst
ferdium-app-84bff14bf649969b3729b2c751b423d33e508f0b.zip
Merge pull request #217 from meetfranz/developv5.0.0-beta.125.0.0-beta.12
Beta 12
-rw-r--r--.travis.yml20
-rw-r--r--CHANGELOG.md22
-rw-r--r--electron-builder.yml2
-rw-r--r--package.json5
-rw-r--r--src/actions/service.js1
-rw-r--r--src/api/server/ServerApi.js17
-rw-r--r--src/components/layout/Sidebar.js2
-rw-r--r--src/components/services/tabs/TabBarSortableList.js110
-rw-r--r--src/components/settings/services/EditServiceForm.js6
-rw-r--r--src/containers/settings/ServicesScreen.js2
-rw-r--r--src/i18n/languages.js4
-rw-r--r--src/i18n/locales/de.json1
-rw-r--r--src/i18n/locales/el-GR.json1
-rw-r--r--src/i18n/locales/en-US.json1
-rw-r--r--src/i18n/locales/es-ES.json168
-rw-r--r--src/i18n/locales/fr.json1
-rw-r--r--src/i18n/locales/it.json168
-rw-r--r--src/i18n/locales/ja.json6
-rw-r--r--src/i18n/locales/nb-NO.json169
-rw-r--r--src/i18n/locales/nl-BE.json7
-rw-r--r--src/i18n/locales/nl.json5
-rw-r--r--src/i18n/locales/pl.json1
-rw-r--r--src/i18n/locales/pt-BR.json8
-rw-r--r--src/i18n/locales/ru.json1
-rw-r--r--src/i18n/locales/ua.json1
-rw-r--r--src/i18n/locales/zh-Hant.json168
-rw-r--r--src/index.js16
-rw-r--r--src/lib/Menu.js58
-rw-r--r--src/lib/Tray.js38
-rw-r--r--src/models/Recipe.js19
-rw-r--r--src/models/Service.js7
-rw-r--r--src/stores/AppStore.js84
-rw-r--r--src/stores/ServicesStore.js20
-rw-r--r--src/webview/lib/RecipeWebview.js6
-rw-r--r--src/webview/notifications.js41
-rw-r--r--yarn.lock42
36 files changed, 1038 insertions, 190 deletions
diff --git a/.travis.yml b/.travis.yml
index 3ece585de..b3ebc4f25 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,36 @@
1matrix:
2 include:
3 - os: linux
4 dist: trusty
5 sudo: required
6 - os: osx
7 osx_image: xcode8.3
8
1language: node_js 9language: node_js
10
2before_script: 11before_script:
3- yarn add global gulp-cli@1.2.2 12- yarn add global gulp-cli@1.2.2
4- yarn add global gulpjs/gulp#4.0 13- yarn add global gulpjs/gulp#4.0
5- yarn add global node-sass 14- yarn add global node-sass
6- yarn install 15- yarn install
16
7script: 17script:
8- yarn lint 18- yarn lint
9- travis_wait yarn build 19- travis_wait yarn build
20
10node_js: 21node_js:
11- '7' 22- '7'
12os: osx 23
13osx_image: xcode8.3 24before_install:
25- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt install libx11-dev libxext-dev libxss-dev libxkbfile-dev; fi
26
14cache: yarn 27cache: yarn
28
15notifications: 29notifications:
16 email: false 30 email: false
17 slack: 31 slack:
18 secure: NjEDG+6YvJvFNwRT8t8XyVR145m+Pb1pmYgdBeuhqtJbMAr0IOb0lLLW9ixKEsL1NU+0R58QGiG9qqY+lLnMNpDYjzluFo0gQtl2NJrULT4xUFDSu65XTwoutKyvj+hoCsHiwrSrO2dHTx3ZK2vsSueg+8jM/xss7dTLA6BcTYl14wTOU37PqFQZk9JYR+Dfq1Jjhy/mq4BiAsb/1clNIulkjmRjSm6R0XT4ZsZZfj0ifXhL4cLGsUv2n+iePiX6bLwZPFjXV1COYTBafbCu17gw3nRMdNMMTDLbwrXXdJZFS/EjFOPgOhwF7CkZ3kSpB2ZIcAJxG7iAUl5j+jHBXc5dafRbjzE4oYve1vPexLoV3NjV76uANUFkcli6eHYD0uJoUJGBRbRGWp+8Bbw9EcBsn4s3vbf5XqHX3S46zvGgqX+LyhyMJQtEG/iv+9XOsOql18ryyejij0z1K7DxpI0gLV1ATZCphY1Fyz1yZDGlYN4ej/Rl2P1Q3yXilweJRF7Ts04w4U9iuP1u598/w++CKSu4q4EeEuqT/hIeFQUKUkwCEsO4xa39vhLPaxKrG9UEUH8OXN+NPZyTAK/LKuIX7C56O1kwvWNMWlPmTcvsq2RghvNTwgSGUIO0EKZKrQYAEG3Y/veSt5CgZoNzLgc/6Xj+g7daxUo9heLy26A= 32 secure: NjEDG+6YvJvFNwRT8t8XyVR145m+Pb1pmYgdBeuhqtJbMAr0IOb0lLLW9ixKEsL1NU+0R58QGiG9qqY+lLnMNpDYjzluFo0gQtl2NJrULT4xUFDSu65XTwoutKyvj+hoCsHiwrSrO2dHTx3ZK2vsSueg+8jM/xss7dTLA6BcTYl14wTOU37PqFQZk9JYR+Dfq1Jjhy/mq4BiAsb/1clNIulkjmRjSm6R0XT4ZsZZfj0ifXhL4cLGsUv2n+iePiX6bLwZPFjXV1COYTBafbCu17gw3nRMdNMMTDLbwrXXdJZFS/EjFOPgOhwF7CkZ3kSpB2ZIcAJxG7iAUl5j+jHBXc5dafRbjzE4oYve1vPexLoV3NjV76uANUFkcli6eHYD0uJoUJGBRbRGWp+8Bbw9EcBsn4s3vbf5XqHX3S46zvGgqX+LyhyMJQtEG/iv+9XOsOql18ryyejij0z1K7DxpI0gLV1ATZCphY1Fyz1yZDGlYN4ej/Rl2P1Q3yXilweJRF7Ts04w4U9iuP1u598/w++CKSu4q4EeEuqT/hIeFQUKUkwCEsO4xa39vhLPaxKrG9UEUH8OXN+NPZyTAK/LKuIX7C56O1kwvWNMWlPmTcvsq2RghvNTwgSGUIO0EKZKrQYAEG3Y/veSt5CgZoNzLgc/6Xj+g7daxUo9heLy26A=
33
19deploy: 34deploy:
20 provider: s3 35 provider: s3
21 access_key_id: AKIAIVRBS4YFL4ZBLCLA 36 access_key_id: AKIAIVRBS4YFL4ZBLCLA
@@ -29,6 +44,7 @@ deploy:
29 acl: public_read 44 acl: public_read
30 on: 45 on:
31 all_branches: true 46 all_branches: true
47
32env: 48env:
33 global: 49 global:
34 - secure: fddJzSmNYVX024jnhnFXEuAK1spEYi3y3RZdWaBtjQnzoObAxkcRW263JNpXQy+b7egnp2hSy8FvlQU+L967911F5Y70Pe3An4oI72hnS3DL4Njp2Dw5PwviwMA+X2ddWhzK4+k/JU6r8jBv1FGQ6ZjwSeaO/t8UKOsE8wDBFLRhnHqoR7QbM7zmKjzh/1oofunGbHsPOHmN4f7jBwSuSFTZltEENcQg3ZP++0NHU8UJdlpfqZOkro8v4AJMngAHeHlNtjwaAHdVv+6+kkwc4E/0Cy6YNyyBkbzipyngNY3GwnwzmNzvsfICD1TGklksjBlMQq7ld7eCiaYRNvyHVEmXJ17qlq7HhxkYgNy32hPRwb5Cv6o4M4tv8qS8UUk4W1RvBJ5fcmfZGQwGXPyQ/m85RJtrNfbYtr84jYcprTnSeji/9PuZv0f87dxELYm3DYmNUa1cgJqEdLUsEd0bMwUYNLnCSfu4ea2zxwir6LSBtJJCbGKxX87s5IOTrHkrWDe+PWd52v+UjQks7MBRlJnntTWo69Yy+ayXV1TnGVOHA5znHvPOvFlAF+y8tLGd4AGvehK1SAkf0+idmc9Q9xKk0QypT3ibjJui4D50p7sSajkzz3P2pUqOS/9HmjMfPMPN+Nl+48GU0CvB2aBGhdmp9vu54VaFzUaAGNGj4WI= 50 - secure: fddJzSmNYVX024jnhnFXEuAK1spEYi3y3RZdWaBtjQnzoObAxkcRW263JNpXQy+b7egnp2hSy8FvlQU+L967911F5Y70Pe3An4oI72hnS3DL4Njp2Dw5PwviwMA+X2ddWhzK4+k/JU6r8jBv1FGQ6ZjwSeaO/t8UKOsE8wDBFLRhnHqoR7QbM7zmKjzh/1oofunGbHsPOHmN4f7jBwSuSFTZltEENcQg3ZP++0NHU8UJdlpfqZOkro8v4AJMngAHeHlNtjwaAHdVv+6+kkwc4E/0Cy6YNyyBkbzipyngNY3GwnwzmNzvsfICD1TGklksjBlMQq7ld7eCiaYRNvyHVEmXJ17qlq7HhxkYgNy32hPRwb5Cv6o4M4tv8qS8UUk4W1RvBJ5fcmfZGQwGXPyQ/m85RJtrNfbYtr84jYcprTnSeji/9PuZv0f87dxELYm3DYmNUa1cgJqEdLUsEd0bMwUYNLnCSfu4ea2zxwir6LSBtJJCbGKxX87s5IOTrHkrWDe+PWd52v+UjQks7MBRlJnntTWo69Yy+ayXV1TnGVOHA5znHvPOvFlAF+y8tLGd4AGvehK1SAkf0+idmc9Q9xKk0QypT3ibjJui4D50p7sSajkzz3P2pUqOS/9HmjMfPMPN+Nl+48GU0CvB2aBGhdmp9vu54VaFzUaAGNGj4WI=
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6551ed51..5b5a0755c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,25 @@
1<a name="5.0.0-beta.12"></a>
2# [5.0.0-beta.12](https://github.com/meetfranz/franz/compare/v5.0.0-beta.11...v5.0.0-beta.12) (2017-11-05)
3
4### Features
5
6* **Menu:** Add "About Franz" Menu item to Windows/Linux ([a21b770](https://github.com/meetfranz/franz/commit/a21b770))
7* **Menu:** Add menu item to toggle (service) dev tools ([e8da383](https://github.com/meetfranz/franz/commit/e8da383))
8* **Translation:** Add italian translation ([ab348cc](https://github.com/meetfranz/franz/commit/ab348cc)) ([dnlup](https://github.com/dnlup))
9
10
11### Bug Fixes
12
13* **App:** Add checks to service url validation to prevent app freeze ([db8515f](https://github.com/meetfranz/franz/commit/db8515f))
14* **macOS:** Fix disable launch Franz on start ([34bba09](https://github.com/meetfranz/franz/commit/34bba09))
15* **Windows:** Launch Franz on start when selected ([34bba09](https://github.com/meetfranz/franz/commit/34bba09))
16* **Onboarding:** Fix issue with import of on-premise services ([7c7d27d](https://github.com/meetfranz/franz/commit/7c7d27d))
17* **Shortcuts:** Flip shortcut to navigate to next/previous service ([37d5923](https://github.com/meetfranz/franz/commit/37d5923))
18* **Windows:** Open Window when app is pinned to taskbar and minimized to system tray ([777814a](https://github.com/meetfranz/franz/commit/777814a))
19* **Recipes:** Recipe developers don't need Premium Supporter Account for debugging ([7a9947a](https://github.com/meetfranz/franz/commit/7a9947a)), closes [#23](https://github.com/meetfranz/franz/issues/23)
20
21
22
1<a name="5.0.0-beta.11"></a> 23<a name="5.0.0-beta.11"></a>
2# [5.0.0-beta.11](https://github.com/meetfranz/franz/compare/v5.0.0-beta.10...v5.0.0-beta.11) (2017-10-24) 24# [5.0.0-beta.11](https://github.com/meetfranz/franz/compare/v5.0.0-beta.10...v5.0.0-beta.11) (2017-10-24)
3 25
diff --git a/electron-builder.yml b/electron-builder.yml
index 0a01a03d8..3f7ad1e85 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -29,5 +29,5 @@ linux:
29 - target: deb 29 - target: deb
30 30
31nsis: 31nsis:
32 perMachine: true 32 perMachine: false
33 oneClick: true 33 oneClick: true
diff --git a/package.json b/package.json
index dcb05bf6a..057dc6d60 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
2 "name": "franz", 2 "name": "franz",
3 "productName": "Franz", 3 "productName": "Franz",
4 "appId": "com.meetfranz.franz", 4 "appId": "com.meetfranz.franz",
5 "version": "5.0.0-beta.11", 5 "version": "5.0.0-beta.12",
6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.", 6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.",
7 "copyright": "adlk x franz - Stefan Malzner", 7 "copyright": "adlk x franz - Stefan Malzner",
8 "main": "index.js", 8 "main": "index.js",
@@ -27,12 +27,13 @@
27 "license": "Apache-2.0", 27 "license": "Apache-2.0",
28 "dependencies": { 28 "dependencies": {
29 "@paulcbetts/system-idle-time": "^1.0.4", 29 "@paulcbetts/system-idle-time": "^1.0.4",
30 "address-rfc2822": "^2.0.1",
31 "auto-launch": "https://github.com/meetfranz/node-auto-launch.git",
30 "babel-polyfill": "^6.23.0", 32 "babel-polyfill": "^6.23.0",
31 "babel-runtime": "^6.23.0", 33 "babel-runtime": "^6.23.0",
32 "classnames": "^2.2.5", 34 "classnames": "^2.2.5",
33 "electron-fetch": "^1.1.0", 35 "electron-fetch": "^1.1.0",
34 "electron-spellchecker": "^1.2.0", 36 "electron-spellchecker": "^1.2.0",
35 "electron-squirrel-startup": "^1.0.0",
36 "electron-updater": "^2.4.3", 37 "electron-updater": "^2.4.3",
37 "electron-window-state": "^4.1.0", 38 "electron-window-state": "^4.1.0",
38 "fs-extra": "^3.0.1", 39 "fs-extra": "^3.0.1",
diff --git a/src/actions/service.js b/src/actions/service.js
index cdd4bbf16..ea6ea5acc 100644
--- a/src/actions/service.js
+++ b/src/actions/service.js
@@ -63,6 +63,7 @@ export default {
63 needle: PropTypes.string.isRequired, 63 needle: PropTypes.string.isRequired,
64 }, 64 },
65 resetFilter: {}, 65 resetFilter: {},
66 resetStatus: {},
66 reorder: { 67 reorder: {
67 oldIndex: PropTypes.number.isRequired, 68 oldIndex: PropTypes.number.isRequired,
68 newIndex: PropTypes.number.isRequired, 69 newIndex: PropTypes.number.isRequired,
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index 8b0b7563c..932b70cdc 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -499,7 +499,7 @@ export default class ServerApi {
499 499
500 return recipe; 500 return recipe;
501 }), 501 }),
502 ).catch(err => console.error(err)); 502 ).catch(err => console.error('Can\'t load recipe', err));
503 } 503 }
504 504
505 _mapRecipePreviewModel(recipes) { 505 _mapRecipePreviewModel(recipes) {
@@ -562,9 +562,16 @@ export default class ServerApi {
562 .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp'); 562 .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp');
563 563
564 const recipes = paths.map((id) => { 564 const recipes = paths.map((id) => {
565 // eslint-disable-next-line 565 let Recipe;
566 const Recipe = require(id)(RecipeModel); 566 try {
567 return new Recipe(loadRecipeConfig(id)); 567 // eslint-disable-next-line
568 Recipe = require(id)(RecipeModel);
569 return new Recipe(loadRecipeConfig(id));
570 } catch (err) {
571 console.error(err);
572 }
573
574 return false;
568 }).filter(recipe => recipe.id).map((data) => { 575 }).filter(recipe => recipe.id).map((data) => {
569 const recipe = data; 576 const recipe = data;
570 577
@@ -579,7 +586,7 @@ export default class ServerApi {
579 586
580 return recipes; 587 return recipes;
581 } catch (err) { 588 } catch (err) {
582 console.debug('Folder `recipe/dev` does not exist'); 589 console.debug('Could not load dev recipes');
583 return false; 590 return false;
584 } 591 }
585 } 592 }
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 4aee1ec60..6a5c0f365 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -52,7 +52,7 @@ export default class Sidebar extends Component {
52 <button 52 <button
53 onClick={openSettings} 53 onClick={openSettings}
54 className="sidebar__settings-button" 54 className="sidebar__settings-button"
55 data-tip={`Settings (${ctrlKey}+,)`} 55 data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`}
56 > 56 >
57 {isPremiumUser && ( 57 {isPremiumUser && (
58 <span className="emoji"> 58 <span className="emoji">
diff --git a/src/components/services/tabs/TabBarSortableList.js b/src/components/services/tabs/TabBarSortableList.js
index c0a68d1a5..e5ae36419 100644
--- a/src/components/services/tabs/TabBarSortableList.js
+++ b/src/components/services/tabs/TabBarSortableList.js
@@ -1,44 +1,78 @@
1import React from 'react'; 1import React, { Component } from 'react';
2import { observer } from 'mobx-react'; 2import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
3import PropTypes from 'prop-types';
3import { SortableContainer } from 'react-sortable-hoc'; 4import { SortableContainer } from 'react-sortable-hoc';
5import { defineMessages, intlShape } from 'react-intl';
4 6
5import TabItem from './TabItem'; 7import TabItem from './TabItem';
6import { ctrlKey } from '../../../environment'; 8import { ctrlKey } from '../../../environment';
7 9
8export default SortableContainer(observer(({ 10const messages = defineMessages({
9 services, 11 addNewService: {
10 setActive, 12 id: 'sidebar.addNewService',
11 reload, 13 defaultMessage: '!!!Add new service',
12 toggleNotifications, 14 },
13 deleteService, 15});
14 disableService, 16
15 openSettings, 17@observer
16}) => ( 18class TabBarSortableList extends Component {
17 <ul 19 static propTypes = {
18 className="tabs" 20 services: MobxPropTypes.arrayOrObservableArray.isRequired,
19 > 21 setActive: PropTypes.func.isRequired,
20 {services.map((service, index) => ( 22 openSettings: PropTypes.func.isRequired,
21 <TabItem 23 reload: PropTypes.func.isRequired,
22 key={service.id} 24 toggleNotifications: PropTypes.func.isRequired,
23 clickHandler={() => setActive({ serviceId: service.id })} 25 deleteService: PropTypes.func.isRequired,
24 service={service} 26 disableService: PropTypes.func.isRequired,
25 index={index} 27 }
26 shortcutIndex={index + 1} 28
27 reload={() => reload({ serviceId: service.id })} 29 static contextTypes = {
28 toggleNotifications={() => toggleNotifications({ serviceId: service.id })} 30 intl: intlShape,
29 deleteService={() => deleteService({ serviceId: service.id })} 31 };
30 disableService={() => disableService({ serviceId: service.id })} 32
31 openSettings={openSettings} 33 render() {
32 /> 34 const {
33 ))} 35 services,
34 <li> 36 setActive,
35 <button 37 reload,
36 className="sidebar__add-service" 38 toggleNotifications,
37 onClick={() => openSettings({ path: 'recipes' })} 39 deleteService,
38 data-tip={`Add new service (${ctrlKey}+N)`} 40 disableService,
41 openSettings,
42 } = this.props;
43
44 const { intl } = this.context;
45
46 return (
47 <ul
48 className="tabs"
39 > 49 >
40 <span className="mdi mdi-plus" /> 50 {services.map((service, index) => (
41 </button> 51 <TabItem
42 </li> 52 key={service.id}
43 </ul> 53 clickHandler={() => setActive({ serviceId: service.id })}
44))); 54 service={service}
55 index={index}
56 shortcutIndex={index + 1}
57 reload={() => reload({ serviceId: service.id })}
58 toggleNotifications={() => toggleNotifications({ serviceId: service.id })}
59 deleteService={() => deleteService({ serviceId: service.id })}
60 disableService={() => disableService({ serviceId: service.id })}
61 openSettings={openSettings}
62 />
63 ))}
64 <li>
65 <button
66 className="sidebar__add-service"
67 onClick={() => openSettings({ path: 'recipes' })}
68 data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`}
69 >
70 <span className="mdi mdi-plus" />
71 </button>
72 </li>
73 </ul>
74 );
75 }
76}
77
78export default SortableContainer(TabBarSortableList);
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index fac0f6b9a..9b359a78e 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -69,10 +69,6 @@ const messages = defineMessages({
69export default class EditServiceForm extends Component { 69export default class EditServiceForm extends Component {
70 static propTypes = { 70 static propTypes = {
71 recipe: PropTypes.instanceOf(Recipe).isRequired, 71 recipe: PropTypes.instanceOf(Recipe).isRequired,
72 // service: PropTypes.oneOfType([
73 // PropTypes.object,
74 // PropTypes.instanceOf(Service),
75 // ]),
76 service(props, propName) { 72 service(props, propName) {
77 if (props.action === 'edit' && !(props[propName] instanceof Service)) { 73 if (props.action === 'edit' && !(props[propName] instanceof Service)) {
78 return new Error(`'${propName}'' is expected to be of type 'Service' 74 return new Error(`'${propName}'' is expected to be of type 'Service'
@@ -207,7 +203,7 @@ export default class EditServiceForm extends Component {
207 )} 203 )}
208 {recipe.hasCustomUrl && ( 204 {recipe.hasCustomUrl && (
209 <TabItem title={intl.formatMessage(messages.tabOnPremise)}> 205 <TabItem title={intl.formatMessage(messages.tabOnPremise)}>
210 {user.isPremium ? ( 206 {user.isPremium || recipe.author.find(a => a.email === user.email) ? (
211 <div> 207 <div>
212 <Input field={form.$('customUrl')} /> 208 <Input field={form.$('customUrl')} />
213 {form.error === 'url-validation-error' && ( 209 {form.error === 'url-validation-error' && (
diff --git a/src/containers/settings/ServicesScreen.js b/src/containers/settings/ServicesScreen.js
index d0580041f..8cfe5efbf 100644
--- a/src/containers/settings/ServicesScreen.js
+++ b/src/containers/settings/ServicesScreen.js
@@ -18,6 +18,7 @@ export default class ServicesScreen extends Component {
18 18
19 componentWillUnmount() { 19 componentWillUnmount() {
20 this.props.actions.service.resetFilter(); 20 this.props.actions.service.resetFilter();
21 this.props.actions.service.resetStatus();
21 } 22 }
22 23
23 deleteService() { 24 deleteService() {
@@ -70,6 +71,7 @@ ServicesScreen.wrappedComponent.propTypes = {
70 toggleService: PropTypes.func.isRequired, 71 toggleService: PropTypes.func.isRequired,
71 filter: PropTypes.func.isRequired, 72 filter: PropTypes.func.isRequired,
72 resetFilter: PropTypes.func.isRequired, 73 resetFilter: PropTypes.func.isRequired,
74 resetStatus: PropTypes.func.isRequired,
73 }).isRequired, 75 }).isRequired,
74 }).isRequired, 76 }).isRequired,
75}; 77};
diff --git a/src/i18n/languages.js b/src/i18n/languages.js
index 9860295b3..72d7b26c1 100644
--- a/src/i18n/languages.js
+++ b/src/i18n/languages.js
@@ -10,4 +10,8 @@ module.exports = {
10 pl: 'Polish', 10 pl: 'Polish',
11 ru: 'РуÑÑкий', 11 ru: 'РуÑÑкий',
12 ua: 'УкраїнÑька', 12 ua: 'УкраїнÑька',
13 it: 'Italian',
14 'es-ES': 'Español - España',
15 'zh-Hant': 'Chinese (Traditional)',
16 'nb-NO': 'Norsk',
13}; 17};
diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json
index 0964169a8..80b66db08 100644
--- a/src/i18n/locales/de.json
+++ b/src/i18n/locales/de.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Neustarten & Aktualisierung installieren", 60 "infobar.buttonInstallUpdate": "Neustarten & Aktualisierung installieren",
61 "infobar.requiredRequestsFailed": "Dienste und Benutzerinformationen konnten nicht geladen werden", 61 "infobar.requiredRequestsFailed": "Dienste und Benutzerinformationen konnten nicht geladen werden",
62 "sidebar.settings": "Einstellungen", 62 "sidebar.settings": "Einstellungen",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Willkommen bei Franz", 64 "services.welcome": "Willkommen bei Franz",
64 "services.getStarted": "Loslegen", 65 "services.getStarted": "Loslegen",
65 "settings.account.headline": "Konto", 66 "settings.account.headline": "Konto",
diff --git a/src/i18n/locales/el-GR.json b/src/i18n/locales/el-GR.json
index dfada77a2..3710bc9a2 100644
--- a/src/i18n/locales/el-GR.json
+++ b/src/i18n/locales/el-GR.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Επανεκκίνηση & εγκατάσταση ενημεÏώσεων", 60 "infobar.buttonInstallUpdate": "Επανεκκίνηση & εγκατάσταση ενημεÏώσεων",
61 "infobar.requiredRequestsFailed": "Δεν ήταν δυνατή η φόÏτωση υπηÏεσιών και πληÏοφοÏιών χÏηστών", 61 "infobar.requiredRequestsFailed": "Δεν ήταν δυνατή η φόÏτωση υπηÏεσιών και πληÏοφοÏιών χÏηστών",
62 "sidebar.settings": "Ρυθμίσεις", 62 "sidebar.settings": "Ρυθμίσεις",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Καλώς οÏίσατε στον Franz", 64 "services.welcome": "Καλώς οÏίσατε στον Franz",
64 "services.getStarted": "Ξεκινήστε", 65 "services.getStarted": "Ξεκινήστε",
65 "settings.account.headline": "ΛογαÏιασμός", 66 "settings.account.headline": "ΛογαÏιασμός",
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index b9ed51b83..b1d260f0a 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Restart & install update", 60 "infobar.buttonInstallUpdate": "Restart & install update",
61 "infobar.requiredRequestsFailed": "Could not load services and user information", 61 "infobar.requiredRequestsFailed": "Could not load services and user information",
62 "sidebar.settings": "Settings", 62 "sidebar.settings": "Settings",
63 "sidebar.addNewService": "Add new service",
63 "services.welcome": "Welcome to Franz", 64 "services.welcome": "Welcome to Franz",
64 "services.getStarted": "Get started", 65 "services.getStarted": "Get started",
65 "settings.account.headline": "Account", 66 "settings.account.headline": "Account",
diff --git a/src/i18n/locales/es-ES.json b/src/i18n/locales/es-ES.json
new file mode 100644
index 000000000..f71b07b2d
--- /dev/null
+++ b/src/i18n/locales/es-ES.json
@@ -0,0 +1,168 @@
1{
2 "global.api.unhealthy": "No se pudo conectar con los servicios online de Franz",
3 "global.notConnectedToTheInternet": "No estás conectado a internet.",
4 "welcome.signupButton": "Crea una cuenta gratuita",
5 "welcome.loginButton": "Accede a tu cuenta",
6 "welcome.slogan": "Mensajería hecha para ti",
7 "login.headline": "Acceder",
8 "login.email.label": "Dirección de Email",
9 "login.password.label": "Contraseña",
10 "login.submit.label": "Acceder",
11 "login.invalidCredentials": "Email o contraseña no válidos",
12 "login.tokenExpired": "Tu sesión ha expirado. Por favor, accede de nuevo.",
13 "login.serverLogout": "Tu sesión ha expirado. Por favor, accede de nuevo.",
14 "login.link.signup": "Crea una cuenta gratuita",
15 "login.link.password": "Restablecer contraseña",
16 "password.headline": "Restablecer contraseña",
17 "password.email.label": "Dirección de Email",
18 "password.submit.label": "Enviar",
19 "password.noUser": "No hemos encontrado un usuario con ese email",
20 "password.successInfo": "Por favor, comprueba tu email",
21 "password.link.signup": "Crea una cuenta gratuita",
22 "password.link.login": "Accede a tu cuenta",
23 "signup.headline": "Crea tu cuenta",
24 "signup.firstname.label": "Nombre",
25 "signup.lastname.label": "Apellidos",
26 "signup.email.label": "Dirección de Email",
27 "signup.company.label": "Empresa",
28 "signup.password.label": "Contraseña",
29 "signup.submit.label": "Crear cuenta",
30 "signup.link.login": "¿Tienes ya una cuenta? Accede",
31 "signup.emailDuplicate": "Ya existe un usuario con esa dirección de email",
32 "signup.legal.info": "Al crear una cuenta de Franz aceptas los",
33 "signup.legal.terms": "Términos de servicio",
34 "signup.legal.privacy": "Política de privacidad",
35 "pricing.headline": "Ayuda a Franz",
36 "pricing.support.label": "Selecciona tu plan de ayuda",
37 "pricing.submit.label": "Quiero ayudar al desarrollo de Franz",
38 "pricing.link.skipPayment": "No quiero ayudar al desarrollo de Franz.",
39 "import.headline": "Importa tus servicios de Franz 4",
40 "import.notSupportedHeadline": "Servicios aún no disponibles en Franz 5",
41 "import.submit.label": "Importar servicios",
42 "import.skip.label": "Quiero añadir los servicios manualmente",
43 "invite.submit.label": "Enviar invitaciones",
44 "invite.headline.friends": "Invita a 3 de tus amigos o compañeros",
45 "invite.name.label": "Nombre",
46 "invite.email.label": "Dirección de Email",
47 "invite.skip.label": "Prefiero hacer esto luego",
48 "subscription.submit.label": "Quiero ayudar al desarrollo de Franz",
49 "subscription.paymentSessionError": "No se ha podido inicializar el formulario de pago",
50 "subscription.includedFeatures": "La cuenta de Franz Premium Supporter incluye",
51 "subscription.features.onpremise": "Añadir servicios in-situ/alojados como HipChat",
52 "subscription.features.customServices": "Servicios privados para ti y tu equipo",
53 "subscription.features.encryptedSync": "Sincronización de sesión encriptada",
54 "subscription.features.vpn": "Soporte para Proxy y VPN",
55 "subscription.features.ads": "¡Sin anuncios, para siempre!",
56 "subscription.features.comingSoon": "próximamente",
57 "infobar.servicesUpdated": "Tus servicios han sido actualizados.",
58 "infobar.updateAvailable": "Una nueva actualización para Franz está disponible.",
59 "infobar.buttonReloadServices": "Volver a cargar servicios",
60 "infobar.buttonInstallUpdate": "Reiniciar e instalar actualizaciones",
61 "infobar.requiredRequestsFailed": "No se han podido cargar los servicios y la información de usuario",
62 "sidebar.settings": "Ajustes",
63 "services.welcome": "Bienvenido a Franz",
64 "services.getStarted": "Comienza",
65 "settings.account.headline": "Mi cuenta",
66 "settings.account.headlineSubscription": "Tu suscripción",
67 "settings.account.headlineUpgrade": "Mejora tu cuenta y ayuda a Franz",
68 "settings.account.headlineInvoices": "Recibos",
69 "settings.account.manageSubscription.label": "Administra tu suscripción",
70 "settings.account.accountType.basic": "Cuenta Básica",
71 "settings.account.accountType.premium": "Cuenta Premium Supporter",
72 "settings.account.account.editButton": "Editar cuenta",
73 "settings.account.invoiceDownload": "Descargar",
74 "settings.account.userInfoRequestFailed": "No se ha podido cargar la información de usuario",
75 "settings.account.tryReloadUserInfoRequest": "TPrueba otra vez",
76 "settings.account.headlineProfile": "Actualizar perfil",
77 "settings.account.headlineAccount": "Información de la cuenta",
78 "settings.account.headlinePassword": "Cambiar contraseña",
79 "settings.account.successInfo": "Tus cambios han sido guardados",
80 "settings.account.buttonSave": "Actualizar perfil",
81 "settings.account.mining.thankyou": "Gracias por ayudar a Franz con tu procesador.",
82 "settings.account.mining.active": "Ahora mismo estás haciendo {hashes} cálculos por segundo.",
83 "settings.account.mining.moreInformation": "Obtén más información",
84 "settings.account.mining.cancel": "Cancelar minado",
85 "settings.navigation.availableServices": "Servicios disponibles",
86 "settings.navigation.yourServices": "Tus servicios",
87 "settings.navigation.account": "Cuenta",
88 "settings.navigation.settings": "Ajustes",
89 "settings.navigation.logout": "Desconectar",
90 "settings.recipes.headline": "Servicios disponibles",
91 "settings.recipes.mostPopular": "Más populares",
92 "settings.recipes.all": "Todos los servicios",
93 "settings.recipes.dev": "Desarrollo",
94 "settings.recipes.nothingFound": "Lo sentimos, no hemos encontrado nada.",
95 "settings.recipes.servicesSuccessfulAddedInfo": "Servicio añadido con éxito",
96 "settings.service.form.saveButton": "Guardar servicio",
97 "settings.service.form.deleteButton": "Eliminar servicio",
98 "settings.service.form.availableServices": "Servicios disponibles",
99 "settings.service.form.yourServices": "Tus servicios",
100 "settings.service.form.addServiceHeadline": "Añadir {name}",
101 "settings.service.form.editServiceHeadline": "Editar {name}",
102 "settings.service.form.tabHosted": "Alojados",
103 "settings.service.form.tabOnPremise": "Autoalojados â­ï¸",
104 "settings.service.form.customUrlValidationError": "No se ha podido validar el servidor personalizado {name}.",
105 "settings.service.form.customUrlPremiumInfo": "Para añadir servicios autoalojados necesitas una cuenta de Franz Premium Supporter.",
106 "settings.service.form.customUrlUpgradeAccount": "Mejora tu cuenta",
107 "settings.service.form.indirectMessageInfo": "Serás notificado sobre todos los nuevos mensajes en un canal, no solo @username, @channel, @here, ...",
108 "settings.service.error.headline": "Error",
109 "settings.service.error.goBack": "Volver a los servicios",
110 "settings.service.error.message": "No se ha podido cargar el servicio.",
111 "settings.services.tooltip.isDisabled": "Servicio deshabilitado",
112 "settings.services.tooltip.notificationsDisabled": "Notificaciones deshabilitadas",
113 "settings.services.headline": "Tus servicios",
114 "settings.services.noServicesAdded": "Aún no has añadido ningún servicio.",
115 "settings.services.discoverServices": "Descubrir servicios",
116 "settings.services.updatedInfo": "Tu cambios han sido guardados",
117 "settings.services.deletedInfo": "Se ha eliminado el servicio",
118 "settings.app.headline": "Ajustes",
119 "settings.app.headlineGeneral": "Generales",
120 "settings.app.headlineLanguage": "Idioma",
121 "settings.app.headlineUpdates": "Actualizaciones",
122 "settings.app.buttonSearchForUpdate": "Buscar actualizaciones",
123 "settings.app.buttonInstallUpdate": "Reiniciar e instalar actualizaciones",
124 "settings.app.updateStatusSearching": "Buscando actualizaciones",
125 "settings.app.updateStatusAvailable": "Actualización disponible, descargando...",
126 "settings.app.updateStatusUpToDate": "Estás utilizando la última versión de Franz",
127 "settings.app.form.autoLaunchOnStart": "Iniciar Franz al encender",
128 "settings.app.form.autoLaunchInBackground": "Abrir en segundo plano",
129 "settings.app.form.enableSystemTray": "Mostrar Franz en la barra de tareas",
130 "settings.app.form.minimizeToSystemTray": "Minimizar Franz a la barra de tareas",
131 "settings.app.form.runInBackground": "Mantener Franz abierto en segundo plano al cerrar la ventana",
132 "settings.app.form.language": "Idioma",
133 "settings.app.form.beta": "Incluir versiones beta",
134 "settings.app.currentVersion": "Versión actual:",
135 "settings.service.form.name": "Nombre",
136 "settings.service.form.enableService": "Habilitar servicio",
137 "settings.service.form.enableNotification": "Habilitar notificaciones",
138 "settings.service.form.team": "Equipo",
139 "settings.service.form.customUrl": "Servidor personalizado",
140 "settings.service.form.indirectMessages": "Mostrar señal para todos los mensajes nuevos",
141 "settings.user.form.firstname": "Nombre",
142 "settings.user.form.lastname": "Apellidos",
143 "settings.user.form.email": "Email",
144 "settings.user.form.currentPassword": "Contraseña actual",
145 "settings.user.form.newPassword": "Nueva contraseña",
146 "settings.user.form.accountType.label": "Tipo de cuenta",
147 "settings.user.form.accountType.individual": "Individual",
148 "settings.user.form.accountType.non-profit": "Sin ánimo de lucro",
149 "settings.user.form.accountType.company": "Empresa",
150 "subscription.type.free": "gratis",
151 "subscription.type.month": "mensual",
152 "subscription.type.year": "anual",
153 "subscription.type.mining": "Ayuda a Franz con tu procesador",
154 "subscription.mining.headline": "¿Cómo funciona?",
155 "subscription.mining.experimental": "experimental",
156 "subscription.mining.line1": "Al habilitar \"Ayuda a Franz con tu procesador\", Franz utilizará entre un 20-50% de tu CPU para minar la criptomoneda Monero, lo que equivale a aproximadamente 5$ anuales.",
157 "subscription.mining.line2": "Adaptaremos el uso de CPU basándonos en tu carga de trabajo para no vaciar tu batería ni realentizar tu ordenador.",
158 "subscription.mining.line3": "Siempre que el minero esté activo, tendrás acceso ilimitado a todas las ventajas de la cuenta Franz Premium Supporter.",
159 "subscription.mining.moreInformation": "Obtén más información sobre este plan.",
160 "subscriptionPopup.buttonCancel": "Cancelar",
161 "subscriptionPopup.buttonDone": "Hecho",
162 "tabs.item.reload": "Recargar",
163 "tabs.item.edit": "Editar",
164 "tabs.item.disableNotifications": "Desactivar notificaciones",
165 "tabs.item.enableNotification": "Activar notificaciones",
166 "tabs.item.disableService": "Deshabilitar servicio",
167 "tabs.item.deleteService": "Eliminar servicio"
168}
diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json
index 84cf54492..2863f47e4 100644
--- a/src/i18n/locales/fr.json
+++ b/src/i18n/locales/fr.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Redémarrer et installer la mise à jour", 60 "infobar.buttonInstallUpdate": "Redémarrer et installer la mise à jour",
61 "infobar.requiredRequestsFailed": "Impossible de charger les services et les informations de l'utilisateur", 61 "infobar.requiredRequestsFailed": "Impossible de charger les services et les informations de l'utilisateur",
62 "sidebar.settings": "Paramètres", 62 "sidebar.settings": "Paramètres",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Bienvenue sur Franz", 64 "services.welcome": "Bienvenue sur Franz",
64 "services.getStarted": "Commencer", 65 "services.getStarted": "Commencer",
65 "settings.account.headline": "Compte", 66 "settings.account.headline": "Compte",
diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json
new file mode 100644
index 000000000..dd87599bb
--- /dev/null
+++ b/src/i18n/locales/it.json
@@ -0,0 +1,168 @@
1{
2 "global.api.unhealthy": "Impossibile connettersi ai servizi online di Franz",
3 "global.notConnectedToTheInternet": "Non sei connesso ad internet.",
4 "welcome.signupButton": "Iscriviti gratis",
5 "welcome.loginButton": "Accedi",
6 "welcome.slogan": "Messagistica che lavora per te",
7 "login.headline": "Accedi",
8 "login.email.label": "Indirizzo email",
9 "login.password.label": "Password",
10 "login.submit.label": "Accedi",
11 "login.invalidCredentials": "Email o password non validi",
12 "login.tokenExpired": "La tua sessione è scaduta, accedi di nuovo per favore.",
13 "login.serverLogout": "La tua sessione è scaduta, accedi di nuovo per favore.",
14 "login.link.signup": "Iscriviti gratis",
15 "login.link.password": "Reimposta password",
16 "password.headline": "Reimposta password",
17 "password.email.label": "Indirizzo email",
18 "password.submit.label": "Invia",
19 "password.noUser": "Non è stato trovato nessun utente con questa email",
20 "password.successInfo": "Per favore controlla la tua email",
21 "password.link.signup": "Iscriviti gratis",
22 "password.link.login": "Accedi",
23 "signup.headline": "Accedi",
24 "signup.firstname.label": "Nome",
25 "signup.lastname.label": "Cognome",
26 "signup.email.label": "Indirizzo email",
27 "signup.company.label": "Azienda",
28 "signup.password.label": "Password",
29 "signup.submit.label": "Registrati",
30 "signup.link.login": "Hai già fatto l'iscrizione? Accedi",
31 "signup.emailDuplicate": "Esiste già un utente con questo indirizzo email",
32 "signup.legal.info": "Iscrivendoti a Franz accetti",
33 "signup.legal.terms": "Termini di servizio",
34 "signup.legal.privacy": "Informativa sulla Privacy",
35 "pricing.headline": "Supporta Franz",
36 "pricing.support.label": "Seleziona il tuo piano di sostegno",
37 "pricing.submit.label": "Voglio sostenere lo sviluppo di Franz",
38 "pricing.link.skipPayment": "Non voglio sostenere lo sviluppo Franz.",
39 "import.headline": "Importa i tuoi servizi di Franz 4",
40 "import.notSupportedHeadline": "Servzi non ancora supportati in Franz 5",
41 "import.submit.label": "Importa servizi",
42 "import.skip.label": "Voglio aggiungere i servizi a mano",
43 "invite.submit.label": "Manda inviti",
44 "invite.headline.friends": "Invita 3 dei tuoi amici o colleghi",
45 "invite.name.label": "Nome",
46 "invite.email.label": "Indirizzo email",
47 "invite.skip.label": "Voglio farlo dopo",
48 "subscription.submit.label": "Voglio sostenere lo sviluppo di Franz",
49 "subscription.paymentSessionError": "Impossibile inizializzare il modulo di pagamento",
50 "subscription.includedFeatures": "La sottoscrizione a pagamento Franz Premium Supporter include",
51 "subscription.features.onpremise": "Agiunge servizi on-premise/hosted come HipChat",
52 "subscription.features.customServices": "Servizi privati per te ed il tuo team",
53 "subscription.features.encryptedSync": "Sincronizzazione sessione crittografata",
54 "subscription.features.vpn": "Supporto di Proxy e VPN",
55 "subscription.features.ads": "Nessuna pubblicità",
56 "subscription.features.comingSoon": "Presto disponibile",
57 "infobar.servicesUpdated": "I tuoi servizi sono stati aggiornati.",
58 "infobar.updateAvailable": "È disponibile un nuovo aggiornamento per Franz.",
59 "infobar.buttonReloadServices": "Ricarica i servizi",
60 "infobar.buttonInstallUpdate": "Riavvia e installa l'aggiornamento",
61 "infobar.requiredRequestsFailed": "Impossibile caricare i servizi e le informazioni dell'utente",
62 "sidebar.settings": "Impostazioni",
63 "services.welcome": "Benvenuto in Franz",
64 "services.getStarted": "Inizia",
65 "settings.account.headline": "Conto",
66 "settings.account.headlineSubscription": "La tua sottoscrizione",
67 "settings.account.headlineUpgrade": "Aggiorna il tuo conto e supporta Franz",
68 "settings.account.headlineInvoices": "Fatture",
69 "settings.account.manageSubscription.label": "Gestisci la tua sottoscrizione",
70 "settings.account.accountType.basic": "Conto Base",
71 "settings.account.accountType.premium": "Conto Premium Supporter",
72 "settings.account.account.editButton": "Modifica conto",
73 "settings.account.invoiceDownload": "Scarica",
74 "settings.account.userInfoRequestFailed": "Impossibile caricare le informazioni dell'utente",
75 "settings.account.tryReloadUserInfoRequest": "Prova ancora",
76 "settings.account.headlineProfile": "Aggiorna profilo",
77 "settings.account.headlineAccount": "Informazioni sul conto",
78 "settings.account.headlinePassword": "Cambia la password",
79 "settings.account.successInfo": "Le tue modifiche sono state salvate",
80 "settings.account.buttonSave": "Aggiorna profilo",
81 "settings.account.mining.thankyou": "Grazie per supportare Franz con la tua potenza di calcolo.",
82 "settings.account.mining.active": "Al momento stai eseguendo {hashes} calcoli al secondo.",
83 "settings.account.mining.moreInformation": "Ottieni piú informazioni",
84 "settings.account.mining.cancel": "Annulla mining",
85 "settings.navigation.availableServices": "Servizi disponibili",
86 "settings.navigation.yourServices": "I tuoi servizi",
87 "settings.navigation.account": "Conto",
88 "settings.navigation.settings": "Impostazioni",
89 "settings.navigation.logout": "Disconnetti",
90 "settings.recipes.headline": "Servizi disponibili",
91 "settings.recipes.mostPopular": "Piú popolari",
92 "settings.recipes.all": "Tutti i servizi",
93 "settings.recipes.dev": "Sviluppo",
94 "settings.recipes.nothingFound": "Mi dispiace, nessuno servizio corrisponde alla tua ricerca.",
95 "settings.recipes.servicesSuccessfulAddedInfo": "Servizio aggiunto con successo",
96 "settings.service.form.saveButton": "Salva servizio",
97 "settings.service.form.deleteButton": "Elimina servizio",
98 "settings.service.form.availableServices": "Servizi disponibili",
99 "settings.service.form.yourServices": "I tuoi servizi",
100 "settings.service.form.addServiceHeadline": "Aggiungi {name}",
101 "settings.service.form.editServiceHeadline": "Modifica {name}",
102 "settings.service.form.tabHosted": "Hosted",
103 "settings.service.form.tabOnPremise": "Self hosted â­ï¸",
104 "settings.service.form.customUrlValidationError": "Impossibile validare il server personale {name}.",
105 "settings.service.form.customUrlPremiumInfo": "Per aggiungere servizi self hosted devi avere un conto Franz Premium Supporter.",
106 "settings.service.form.customUrlUpgradeAccount": "Aggiorna il tuo conto",
107 "settings.service.form.indirectMessageInfo": "Riceverai notifiche per tutti i nuovi messaggi in un canale, non solo @username, @channel, @here, ...",
108 "settings.service.error.headline": "Errore",
109 "settings.service.error.goBack": "Torna ai servizi",
110 "settings.service.error.message": "Impossibile caricare le specifiche del servizio.",
111 "settings.services.tooltip.isDisabled": "Il servizio è disabilitato",
112 "settings.services.tooltip.notificationsDisabled": "Le notifiche sono disabilitate",
113 "settings.services.headline": "I tuoi servizi",
114 "settings.services.noServicesAdded": "Non hai ancora aggiunto nessun servizio.",
115 "settings.services.discoverServices": "Trova servizi",
116 "settings.services.updatedInfo": "Le tue modifiche sono state salvate",
117 "settings.services.deletedInfo": "Il servizio è stato eliminato",
118 "settings.app.headline": "Impostazioni",
119 "settings.app.headlineGeneral": "Generale",
120 "settings.app.headlineLanguage": "Lingua",
121 "settings.app.headlineUpdates": "Aggiornamento",
122 "settings.app.buttonSearchForUpdate": "Controlla aggiornamento versione",
123 "settings.app.buttonInstallUpdate": "Riavvia e installa l'aggiornamento",
124 "settings.app.updateStatusSearching": "Sto cercando l'aggiornamento",
125 "settings.app.updateStatusAvailable": "Aggiornamento disponibile, scarico...",
126 "settings.app.updateStatusUpToDate": "You are using the latest version of Franz",
127 "settings.app.form.autoLaunchOnStart": "Lancia Franz all'avvio",
128 "settings.app.form.autoLaunchInBackground": "Apri in background",
129 "settings.app.form.enableSystemTray": "Mostra Franz nella zona delle notifiche di sistema",
130 "settings.app.form.minimizeToSystemTray": "Minimizza Franz nella zona delle notifiche di sistema",
131 "settings.app.form.runInBackground": "Maniteni Franz attivo in background quando chiudi la finestra",
132 "settings.app.form.language": "Lingua",
133 "settings.app.form.beta": "Includi versioni beta",
134 "settings.app.currentVersion": "Versione corrente:",
135 "settings.service.form.name": "Nome",
136 "settings.service.form.enableService": "Abilita servizio",
137 "settings.service.form.enableNotification": "Abilita notifiche",
138 "settings.service.form.team": "Team",
139 "settings.service.form.customUrl": "Server personale",
140 "settings.service.form.indirectMessages": "Mostra il badge del messaggio per tutti i nuovi messaggi",
141 "settings.user.form.firstname": "Nome",
142 "settings.user.form.lastname": "Cognome",
143 "settings.user.form.email": "Email",
144 "settings.user.form.currentPassword": "Password corrente",
145 "settings.user.form.newPassword": "Nuova password",
146 "settings.user.form.accountType.label": "Tipo di conto",
147 "settings.user.form.accountType.individual": "Individuale",
148 "settings.user.form.accountType.non-profit": "Non-Profit",
149 "settings.user.form.accountType.company": "Azienda",
150 "subscription.type.free": "gratis",
151 "subscription.type.month": "mese",
152 "subscription.type.year": "anno",
153 "subscription.type.mining": "Supporta Franz con della potenza di calcolo",
154 "subscription.mining.headline": "Come funziona?",
155 "subscription.mining.experimental": "sperimentale",
156 "subscription.mining.line1": "Abilitando \"Supporta Franz con della potenza di calcolo\",Franz userà circa il 20-50% della tua CPU per fare il mining della criptovaluta Monero che equivale approssimativamente a 5$/anno.",
157 "subscription.mining.line2": "Adatteremo l'utilizzo della CPU in base all tue abitudini di lavoro per non scaricare la tua batteria e rallentare la tua macchina.",
158 "subscription.mining.line3": "Fino a che il mining è attivo, avrai accesso illimitato a tutte le funzionalità del conto Franz Premium Supporter.",
159 "subscription.mining.moreInformation": "Ottieni più informazioni su questo piano.",
160 "subscriptionPopup.buttonCancel": "Annulla",
161 "subscriptionPopup.buttonDone": "Fatto",
162 "tabs.item.reload": "Ricarica",
163 "tabs.item.edit": "Modifica",
164 "tabs.item.disableNotifications": "Disabilita le notifiche",
165 "tabs.item.enableNotification": "Abilita le notifiche",
166 "tabs.item.disableService": "Disabilita servizio",
167 "tabs.item.deleteService": "Elimina servizio"
168}
diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json
index a283154c9..98b7cbb19 100644
--- a/src/i18n/locales/ja.json
+++ b/src/i18n/locales/ja.json
@@ -60,12 +60,13 @@
60 "infobar.buttonInstallUpdate": "å†èµ·å‹•ã—ã¦æ›´æ–°ã‚’インストールã™ã‚‹", 60 "infobar.buttonInstallUpdate": "å†èµ·å‹•ã—ã¦æ›´æ–°ã‚’インストールã™ã‚‹",
61 "infobar.requiredRequestsFailed": "サービスã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼æƒ…å ±ãŒèª­ã¿è¾¼ã‚ã¾ã›ã‚“", 61 "infobar.requiredRequestsFailed": "サービスã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼æƒ…å ±ãŒèª­ã¿è¾¼ã‚ã¾ã›ã‚“",
62 "sidebar.settings": "設定", 62 "sidebar.settings": "設定",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Franzã«ã‚ˆã†ã“ã", 64 "services.welcome": "Franzã«ã‚ˆã†ã“ã",
64 "services.getStarted": "ã¯ã˜ã‚ã‚‹", 65 "services.getStarted": "ã¯ã˜ã‚ã‚‹",
65 "settings.account.headline": "アカウント", 66 "settings.account.headline": "アカウント",
66 "settings.account.headlineSubscription": "サブスクリプション内容", 67 "settings.account.headlineSubscription": "サブスクリプション内容",
67 "settings.account.headlineUpgrade": "アカウントをアップグレードã—ã€Franzを支æ´ã™ã‚‹", 68 "settings.account.headlineUpgrade": "アカウントをアップグレードã—ã€Franzを支æ´ã™ã‚‹",
68 "settings.account.headlineInvoices": "Invoices", 69 "settings.account.headlineInvoices": "インボイス",
69 "settings.account.manageSubscription.label": "サブスクリプションã®ç®¡ç†", 70 "settings.account.manageSubscription.label": "サブスクリプションã®ç®¡ç†",
70 "settings.account.accountType.basic": "Basicアカウント", 71 "settings.account.accountType.basic": "Basicアカウント",
71 "settings.account.accountType.premium": "Premium Supporterアカウント", 72 "settings.account.accountType.premium": "Premium Supporterアカウント",
@@ -126,6 +127,7 @@
126 "settings.app.updateStatusUpToDate": "ãŠä½¿ã„ã®Franzã¯æœ€æ–°ã§ã™", 127 "settings.app.updateStatusUpToDate": "ãŠä½¿ã„ã®Franzã¯æœ€æ–°ã§ã™",
127 "settings.app.form.autoLaunchOnStart": "システム起動時ã«Franzã‚’é–‹ã", 128 "settings.app.form.autoLaunchOnStart": "システム起動時ã«Franzã‚’é–‹ã",
128 "settings.app.form.autoLaunchInBackground": "ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§é–‹ã", 129 "settings.app.form.autoLaunchInBackground": "ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§é–‹ã",
130 "settings.app.form.enableSystemTray": "Franzをシステムトレイã«è¡¨ç¤ºã™ã‚‹",
129 "settings.app.form.minimizeToSystemTray": "Franzをシステムトレイã«æœ€å°åŒ–ã™ã‚‹", 131 "settings.app.form.minimizeToSystemTray": "Franzをシステムトレイã«æœ€å°åŒ–ã™ã‚‹",
130 "settings.app.form.runInBackground": "ウインドウを閉ã˜ãŸéš›ã«Franzã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã•ã›ã¦ãŠã", 132 "settings.app.form.runInBackground": "ウインドウを閉ã˜ãŸéš›ã«Franzã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã•ã›ã¦ãŠã",
131 "settings.app.form.language": "言語", 133 "settings.app.form.language": "言語",
@@ -150,7 +152,7 @@
150 "subscription.type.month": "月間", 152 "subscription.type.month": "月間",
151 "subscription.type.year": "å¹´é–“", 153 "subscription.type.year": "å¹´é–“",
152 "subscription.type.mining": "PCã®å‡¦ç†èƒ½åŠ›ã‚’使ã£ã¦Franzを支æ´ã™ã‚‹", 154 "subscription.type.mining": "PCã®å‡¦ç†èƒ½åŠ›ã‚’使ã£ã¦Franzを支æ´ã™ã‚‹",
153 "subscription.mining.headline": "ã“ã‚Œã¯ã©ã®ã‚ˆã†ã«å‹•ä½œãã¦ãã‚‹ã‹", 155 "subscription.mining.headline": "ã“ã‚Œã¯ã©ã®ã‚ˆã†ãªä»•çµ„ã¿ã§ãã‹",
154 "subscription.mining.experimental": "実験的", 156 "subscription.mining.experimental": "実験的",
155 "subscription.mining.line1": "\"PCã®å‡¦ç†èƒ½åŠ›ã‚’使ã£ã¦Franzを支æ´ã™ã‚‹\"を有効ã«ã™ã‚‹ã“ã¨ã§ã€Franzã¯ãŠã‚ˆã20-50%ã®CPUパワーを暗å·é€šè²¨Moneroã®ãƒžã‚¤ãƒ‹ãƒ³ã‚°ã«ä½¿ç”¨ã—ã€ã“ã‚Œã¯ãŠã‚ˆãå¹´é–“ã§5ドル分ã«ã‚ãŸã‚Šã¾ã™ã€‚", 157 "subscription.mining.line1": "\"PCã®å‡¦ç†èƒ½åŠ›ã‚’使ã£ã¦Franzを支æ´ã™ã‚‹\"を有効ã«ã™ã‚‹ã“ã¨ã§ã€Franzã¯ãŠã‚ˆã20-50%ã®CPUパワーを暗å·é€šè²¨Moneroã®ãƒžã‚¤ãƒ‹ãƒ³ã‚°ã«ä½¿ç”¨ã—ã€ã“ã‚Œã¯ãŠã‚ˆãå¹´é–“ã§5ドル分ã«ã‚ãŸã‚Šã¾ã™ã€‚",
156 "subscription.mining.line2": "処ç†èƒ½åŠ›ã«åŸºã¥ã„ã¦CPUã®ä½¿ç”¨çŽ‡ã‚’é©å¿œã—ã¾ã™ã®ã§ãƒãƒƒãƒ†ãƒªãƒ¼ã‚’無駄ã«æ¶ˆè²»ã—ãŸã‚Šã€ã‚·ã‚¹ãƒ†ãƒ ã‚’é…ãã™ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。", 158 "subscription.mining.line2": "処ç†èƒ½åŠ›ã«åŸºã¥ã„ã¦CPUã®ä½¿ç”¨çŽ‡ã‚’é©å¿œã—ã¾ã™ã®ã§ãƒãƒƒãƒ†ãƒªãƒ¼ã‚’無駄ã«æ¶ˆè²»ã—ãŸã‚Šã€ã‚·ã‚¹ãƒ†ãƒ ã‚’é…ãã™ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。",
diff --git a/src/i18n/locales/nb-NO.json b/src/i18n/locales/nb-NO.json
new file mode 100644
index 000000000..976c54787
--- /dev/null
+++ b/src/i18n/locales/nb-NO.json
@@ -0,0 +1,169 @@
1{
2 "global.api.unhealthy": "Kan ikke koble til Franz' tjenester",
3 "global.notConnectedToTheInternet": "Du er ikke koblet til internett.",
4 "welcome.signupButton": "Opprett en gratis konto",
5 "welcome.loginButton": "Logg inn til din konto",
6 "welcome.slogan": "Teksting som funker for deg",
7 "login.headline": "Logg inn",
8 "login.email.label": "Email adresse",
9 "login.password.label": "Passord",
10 "login.submit.label": "Logg inn",
11 "login.invalidCredentials": "Ugyldig email eller passord",
12 "login.tokenExpired": "Din økt utløpte, vennligst logg inn igjen.",
13 "login.serverLogout": "Din økt utløpte, vennligst logg inn igjen.",
14 "login.link.signup": "Opprett en gratis konto",
15 "login.link.password": "Reset passord",
16 "password.headline": "Reset passord",
17 "password.email.label": "Email adresse",
18 "password.submit.label": "Send inn",
19 "password.noUser": "Ingen bruker med den emailen finnes",
20 "password.successInfo": "Vennligst sjekk din email",
21 "password.link.signup": "Opprett en gratis konto",
22 "password.link.login": "Logg inn til din konto",
23 "signup.headline": "Registrer deg",
24 "signup.firstname.label": "Fornavn",
25 "signup.lastname.label": "Etternavn",
26 "signup.email.label": "Email adresse",
27 "signup.company.label": "Firma",
28 "signup.password.label": "Passord",
29 "signup.submit.label": "Opprett konto",
30 "signup.link.login": "Har du allerede en konto? Logg inn",
31 "signup.emailDuplicate": "En konto med den epost adresse eksiterer allerede",
32 "signup.legal.info": "Ved å opprette en Franz konto aksepterer du",
33 "signup.legal.terms": "Vilkår for bruk",
34 "signup.legal.privacy": "Personvern",
35 "pricing.headline": "Støtt Franz",
36 "pricing.support.label": "Velg din støtteplan",
37 "pricing.submit.label": "Jeg vil støtte utviklingen av Franz",
38 "pricing.link.skipPayment": "Jeg vil ikke støtte utviklingen av Franz.",
39 "import.headline": "Importer dine Franz 4 tjenester",
40 "import.notSupportedHeadline": "Tjenester ikke enda støttet i Franz 5",
41 "import.submit.label": "Importer tjenester",
42 "import.skip.label": "Jeg vil legge til en tjeneste manuelt",
43 "invite.submit.label": "Send invitasjoner",
44 "invite.headline.friends": "Inviter 3 av dine venner eller kolleger",
45 "invite.name.label": "Navn",
46 "invite.email.label": "Email adresse",
47 "invite.skip.label": "Jeg vil gjøre dette senere",
48 "subscription.submit.label": "Jeg vil ikke støtte utviklingen av Franz",
49 "subscription.paymentSessionError": "Kunne ikke laste betalingsskjemaet",
50 "subscription.includedFeatures": "Betalte Franz Premium konto inkluderer",
51 "subscription.features.onpremise": "Legg til on-premise/hosted tjenester som HipChat",
52 "subscription.features.customServices": "Private tjenester for deg og ditt lag",
53 "subscription.features.encryptedSync": "Kryptert øktsynkronisering",
54 "subscription.features.vpn": "Proxy & VPN støtte",
55 "subscription.features.ads": "Ingen annonser, noensinne!",
56 "subscription.features.comingSoon": "Kommer snart",
57 "infobar.servicesUpdated": "Dine tjenester er oppdatert.",
58 "infobar.updateAvailable": "En ny oppdatering for Franz er tilgjengelig.",
59 "infobar.buttonReloadServices": "Oppdater tjenester",
60 "infobar.buttonInstallUpdate": "Restart & installer oppdatering",
61 "infobar.requiredRequestsFailed": "Kunne ikke laste tjenester og brukerinformasjon",
62 "sidebar.settings": "Innstillinger",
63 "sidebar.addNewService": "Legg til ny tjeneste",
64 "services.welcome": "Velkommen til Franz",
65 "services.getStarted": "Kom i gang",
66 "settings.account.headline": "Konto",
67 "settings.account.headlineSubscription": "Ditt abonnement",
68 "settings.account.headlineUpgrade": "Oppgrader din konto og støtt Franz",
69 "settings.account.headlineInvoices": "Fakturaer",
70 "settings.account.manageSubscription.label": "Administrer dine abonnement",
71 "settings.account.accountType.basic": "Enkel Konto",
72 "settings.account.accountType.premium": "Premium Konto",
73 "settings.account.account.editButton": "Rediger konto",
74 "settings.account.invoiceDownload": "Last ned",
75 "settings.account.userInfoRequestFailed": "Kunne ikke laste brukerinformasjon",
76 "settings.account.tryReloadUserInfoRequest": "Prøv igjen",
77 "settings.account.headlineProfile": "Oppdater profil",
78 "settings.account.headlineAccount": "Kontoinformasjon",
79 "settings.account.headlinePassword": "Endre passord",
80 "settings.account.successInfo": "Dine endringer er lagret",
81 "settings.account.buttonSave": "Oppdater profil",
82 "settings.account.mining.thankyou": "Takk for at du støtter Franz med din prosessorkraft.",
83 "settings.account.mining.active": "Du utfører nå {hashes} beregninger per sekund.",
84 "settings.account.mining.moreInformation": "FÃ¥ mer informasjon",
85 "settings.account.mining.cancel": "Avbryt mining",
86 "settings.navigation.availableServices": "Tilgjengelige tjenester",
87 "settings.navigation.yourServices": "Dine tjenester",
88 "settings.navigation.account": "Konto",
89 "settings.navigation.settings": "Innstillinger",
90 "settings.navigation.logout": "Logg ut",
91 "settings.recipes.headline": "Tilgjengelige tjenester",
92 "settings.recipes.mostPopular": "Mest populære",
93 "settings.recipes.all": "Alle tjenester",
94 "settings.recipes.dev": "Utvikling",
95 "settings.recipes.nothingFound": "Beklager, men ingen tjeneste samsvarer med søkeordet ditt.",
96 "settings.recipes.servicesSuccessfulAddedInfo": "Tjenesten ble lagt til",
97 "settings.service.form.saveButton": "Lagre tjeneste",
98 "settings.service.form.deleteButton": "Slett tjeneste",
99 "settings.service.form.availableServices": "Tilgjengelige tjenester",
100 "settings.service.form.yourServices": "Dine tjenester",
101 "settings.service.form.addServiceHeadline": "Legg til {name}",
102 "settings.service.form.editServiceHeadline": "Rediger {name}",
103 "settings.service.form.tabHosted": "Hosted",
104 "settings.service.form.tabOnPremise": "Selv hosted â­ï¸",
105 "settings.service.form.customUrlValidationError": "Kunne ikke validere egendefinert {name} server.",
106 "settings.service.form.customUrlPremiumInfo": "For å legge til selvhost-baserte tjenester trenger du en Franz Premium konto.",
107 "settings.service.form.customUrlUpgradeAccount": "Oppgrader din konto",
108 "settings.service.form.indirectMessageInfo": "Du vil bli varslet om alle nye meldinger i en kanal, ikke bare @brukernavn, @kanal, @here, ...",
109 "settings.service.error.headline": "Error",
110 "settings.service.error.goBack": "Tilbake til tjenester",
111 "settings.service.error.message": "Kunne ikke laste tjeneste oppskrift.",
112 "settings.services.tooltip.isDisabled": "Tjenesten er deaktivert",
113 "settings.services.tooltip.notificationsDisabled": "Varsler er deaktivert",
114 "settings.services.headline": "Dine tjenester",
115 "settings.services.noServicesAdded": "Du har ikke lagt til noen tjenester enda.",
116 "settings.services.discoverServices": "Oppdag tjenester",
117 "settings.services.updatedInfo": "Dine endringer er lagret",
118 "settings.services.deletedInfo": "Tjenester har blitt slettet",
119 "settings.app.headline": "Innstillinger",
120 "settings.app.headlineGeneral": "Genelert",
121 "settings.app.headlineLanguage": "Språk",
122 "settings.app.headlineUpdates": "Oppdateringer",
123 "settings.app.buttonSearchForUpdate": "Se etter oppdateringer",
124 "settings.app.buttonInstallUpdate": "Restart & installer oppdatering",
125 "settings.app.updateStatusSearching": "Søker etter en oppdatering",
126 "settings.app.updateStatusAvailable": "Oppdatering tilgjengelig, laster ned...",
127 "settings.app.updateStatusUpToDate": "Du bruker siste versjon av Franz",
128 "settings.app.form.autoLaunchOnStart": "Start Franz ved oppstart",
129 "settings.app.form.autoLaunchInBackground": "Ã…pne i bakgrunnen",
130 "settings.app.form.enableSystemTray": "Vis Franz i systemfeltet",
131 "settings.app.form.minimizeToSystemTray": "Minimer Franz til systemfeltet",
132 "settings.app.form.runInBackground": "Behold Franz i bakgrunnen når du lukker vinduet",
133 "settings.app.form.language": "Språk",
134 "settings.app.form.beta": "Inkluder beta versjoner",
135 "settings.app.currentVersion": "Gjeldende versjon:",
136 "settings.service.form.name": "Navn",
137 "settings.service.form.enableService": "Slå på tjeneste",
138 "settings.service.form.enableNotification": "Slå på varsler",
139 "settings.service.form.team": "Lag",
140 "settings.service.form.customUrl": "Egendefinert server",
141 "settings.service.form.indirectMessages": "Vis merke for alle nye meldinger",
142 "settings.user.form.firstname": "Fornavn",
143 "settings.user.form.lastname": "Etternavn",
144 "settings.user.form.email": "Email",
145 "settings.user.form.currentPassword": "Gjeldende passord",
146 "settings.user.form.newPassword": "Nytt passord",
147 "settings.user.form.accountType.label": "Konto type",
148 "settings.user.form.accountType.individual": "Individuell",
149 "settings.user.form.accountType.non-profit": "Non-Profit",
150 "settings.user.form.accountType.company": "Firma",
151 "subscription.type.free": "gratis",
152 "subscription.type.month": "måned",
153 "subscription.type.year": "Ã¥r",
154 "subscription.type.mining": "Støtt Franz med prosessorkraft",
155 "subscription.mining.headline": "Hvordan fungerer dette?",
156 "subscription.mining.experimental": "eksperimental",
157 "subscription.mining.line1": "Ved å aktivere \"Støtt Franz med prosessorkraft\" vil Franz bruke cirka 20-50% av prosessore din til å mine kryptovalutaen Monero, som vil tilsvare omtrent $5/år",
158 "subscription.mining.line2": "Vi vil tilpasse prosessor bruken basert på arbeidsadferd for å ikke tømme batteriet og senke hastigheten på maskinen din.",
159 "subscription.mining.line3": "SÃ¥ lenge du miner, har du ubegrenset tilgang til alle Franz Premium funksjoner.",
160 "subscription.mining.moreInformation": "FÃ¥ mer informasjon om denne planen.",
161 "subscriptionPopup.buttonCancel": "Kanseller",
162 "subscriptionPopup.buttonDone": "Ferdig",
163 "tabs.item.reload": "Reload",
164 "tabs.item.edit": "Rediger",
165 "tabs.item.disableNotifications": "Deaktiver varsler",
166 "tabs.item.enableNotification": "Aktiver varsler",
167 "tabs.item.disableService": "Deaktiver tjeneste",
168 "tabs.item.deleteService": "Slett tjeneste"
169}
diff --git a/src/i18n/locales/nl-BE.json b/src/i18n/locales/nl-BE.json
index 40cc14c50..a19d51b2b 100644
--- a/src/i18n/locales/nl-BE.json
+++ b/src/i18n/locales/nl-BE.json
@@ -54,12 +54,13 @@
54 "subscription.features.vpn": "Proxy & VPN ondersteuning", 54 "subscription.features.vpn": "Proxy & VPN ondersteuning",
55 "subscription.features.ads": "Geen reclame, nooit!", 55 "subscription.features.ads": "Geen reclame, nooit!",
56 "subscription.features.comingSoon": "komt binnenkort", 56 "subscription.features.comingSoon": "komt binnenkort",
57 "infobar.servicesUpdated": "Je services zijn geüpdated.", 57 "infobar.servicesUpdated": "Je services zijn geüpdatet.",
58 "infobar.updateAvailable": "Er is een nieuwe update van Franz beschikbaar.", 58 "infobar.updateAvailable": "Er is een nieuwe update van Franz beschikbaar.",
59 "infobar.buttonReloadServices": "Services herladen", 59 "infobar.buttonReloadServices": "Services herladen",
60 "infobar.buttonInstallUpdate": "Herstarten & update installeren", 60 "infobar.buttonInstallUpdate": "Herstarten & update installeren",
61 "infobar.requiredRequestsFailed": "Kon services en gebruikersinformatie niet laden", 61 "infobar.requiredRequestsFailed": "Kon services en gebruikersinformatie niet laden",
62 "sidebar.settings": "Instellingen", 62 "sidebar.settings": "Instellingen",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Welkom bij Franz", 64 "services.welcome": "Welkom bij Franz",
64 "services.getStarted": "Begin", 65 "services.getStarted": "Begin",
65 "settings.account.headline": "Account", 66 "settings.account.headline": "Account",
@@ -76,7 +77,7 @@
76 "settings.account.headlineProfile": "Profiel aanpassen", 77 "settings.account.headlineProfile": "Profiel aanpassen",
77 "settings.account.headlineAccount": "Accountinformatie", 78 "settings.account.headlineAccount": "Accountinformatie",
78 "settings.account.headlinePassword": "Wachtwoord veranderen", 79 "settings.account.headlinePassword": "Wachtwoord veranderen",
79 "settings.account.successInfo": "Je wijzigingen werden bewaard", 80 "settings.account.successInfo": "Je wijzigingen zijn opgeslagen",
80 "settings.account.buttonSave": "Profiel aanpassen", 81 "settings.account.buttonSave": "Profiel aanpassen",
81 "settings.account.mining.thankyou": "Bedankt om Franz te steunen met je rekenkracht.", 82 "settings.account.mining.thankyou": "Bedankt om Franz te steunen met je rekenkracht.",
82 "settings.account.mining.active": "Op dit moment maak je {hashes} berekeningen per seconde.", 83 "settings.account.mining.active": "Op dit moment maak je {hashes} berekeningen per seconde.",
@@ -113,7 +114,7 @@
113 "settings.services.headline": "Jouw services", 114 "settings.services.headline": "Jouw services",
114 "settings.services.noServicesAdded": "Je hebt nog geen services toegevoegd.", 115 "settings.services.noServicesAdded": "Je hebt nog geen services toegevoegd.",
115 "settings.services.discoverServices": "Services ontdekken", 116 "settings.services.discoverServices": "Services ontdekken",
116 "settings.services.updatedInfo": "Je veranderingen werden bewaard", 117 "settings.services.updatedInfo": "Je wijzigingen werden bewaard",
117 "settings.services.deletedInfo": "Service werd verwijderd", 118 "settings.services.deletedInfo": "Service werd verwijderd",
118 "settings.app.headline": "Instellingen", 119 "settings.app.headline": "Instellingen",
119 "settings.app.headlineGeneral": "Algemeen", 120 "settings.app.headlineGeneral": "Algemeen",
diff --git a/src/i18n/locales/nl.json b/src/i18n/locales/nl.json
index 159d1f328..aee1a52c8 100644
--- a/src/i18n/locales/nl.json
+++ b/src/i18n/locales/nl.json
@@ -10,7 +10,7 @@
10 "login.submit.label": "Inloggen", 10 "login.submit.label": "Inloggen",
11 "login.invalidCredentials": "E-mailadres of wachtwoord ongeldig", 11 "login.invalidCredentials": "E-mailadres of wachtwoord ongeldig",
12 "login.tokenExpired": "De sessie is verlopen, log opnieuw in alsjeblieft.", 12 "login.tokenExpired": "De sessie is verlopen, log opnieuw in alsjeblieft.",
13 "login.serverLogout": "De sessie is verlopen, log opnieuw in alsjeblieft..", 13 "login.serverLogout": "De sessie is verlopen, log opnieuw in alsjeblieft.",
14 "login.link.signup": "Maak een gratis account", 14 "login.link.signup": "Maak een gratis account",
15 "login.link.password": "Wachtwoord vergeten", 15 "login.link.password": "Wachtwoord vergeten",
16 "password.headline": "Wachtwoord vergeten", 16 "password.headline": "Wachtwoord vergeten",
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Herstart & installeer update", 60 "infobar.buttonInstallUpdate": "Herstart & installeer update",
61 "infobar.requiredRequestsFailed": "Kon services en gebruikerinformatie niet laden", 61 "infobar.requiredRequestsFailed": "Kon services en gebruikerinformatie niet laden",
62 "sidebar.settings": "Instellingen", 62 "sidebar.settings": "Instellingen",
63 "sidebar.addNewService": "Voeg nieuwe service toe",
63 "services.welcome": "Welkom bij Franz", 64 "services.welcome": "Welkom bij Franz",
64 "services.getStarted": "Beginnen", 65 "services.getStarted": "Beginnen",
65 "settings.account.headline": "Account", 66 "settings.account.headline": "Account",
@@ -157,7 +158,7 @@
157 "subscription.mining.line2": "We zullen het CPU-gebruik aanpassen aan je gebruik en daarmee voorkomen dat de batterij niet leegloopt of dat jij en je werk afgeremd wordt.", 158 "subscription.mining.line2": "We zullen het CPU-gebruik aanpassen aan je gebruik en daarmee voorkomen dat de batterij niet leegloopt of dat jij en je werk afgeremd wordt.",
158 "subscription.mining.line3": "Zolang de miner actief is, heb je onbeperkt toegang tot alle Franz Premium Supporter Features.", 159 "subscription.mining.line3": "Zolang de miner actief is, heb je onbeperkt toegang tot alle Franz Premium Supporter Features.",
159 "subscription.mining.moreInformation": "Verkrijg meer informatie over dit plan.", 160 "subscription.mining.moreInformation": "Verkrijg meer informatie over dit plan.",
160 "subscriptionPopup.buttonCancel": "Cancel", 161 "subscriptionPopup.buttonCancel": "Annuleer",
161 "subscriptionPopup.buttonDone": "Klaar", 162 "subscriptionPopup.buttonDone": "Klaar",
162 "tabs.item.reload": "Herlaad", 163 "tabs.item.reload": "Herlaad",
163 "tabs.item.edit": "Bewerk", 164 "tabs.item.edit": "Bewerk",
diff --git a/src/i18n/locales/pl.json b/src/i18n/locales/pl.json
index 1a8e9ad54..a884ef319 100644
--- a/src/i18n/locales/pl.json
+++ b/src/i18n/locales/pl.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Uruchom ponownie i zainstaluj aktualizacje", 60 "infobar.buttonInstallUpdate": "Uruchom ponownie i zainstaluj aktualizacje",
61 "infobar.requiredRequestsFailed": "Nie można wczytać usług i informacji o użytkowniku", 61 "infobar.requiredRequestsFailed": "Nie można wczytać usług i informacji o użytkowniku",
62 "sidebar.settings": "Ustawienia", 62 "sidebar.settings": "Ustawienia",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Witaj w aplikcji Franz", 64 "services.welcome": "Witaj w aplikcji Franz",
64 "services.getStarted": "Zacznij", 65 "services.getStarted": "Zacznij",
65 "settings.account.headline": "Konto", 66 "settings.account.headline": "Konto",
diff --git a/src/i18n/locales/pt-BR.json b/src/i18n/locales/pt-BR.json
index 38f0836a7..8a139a4f5 100644
--- a/src/i18n/locales/pt-BR.json
+++ b/src/i18n/locales/pt-BR.json
@@ -59,7 +59,8 @@
59 "infobar.buttonReloadServices": "Recarregar serviços", 59 "infobar.buttonReloadServices": "Recarregar serviços",
60 "infobar.buttonInstallUpdate": "Reiniciar & instalar atualização", 60 "infobar.buttonInstallUpdate": "Reiniciar & instalar atualização",
61 "infobar.requiredRequestsFailed": "Não foi possível carregar serviços e informações do usuário", 61 "infobar.requiredRequestsFailed": "Não foi possível carregar serviços e informações do usuário",
62 "sidebar.settings": "Configurações", 62 "sidebar.addNewService": "!!!Add new service",
63 "sidebar.settings": "Ajustes",
63 "services.welcome": "Bem-vindo ao Franz", 64 "services.welcome": "Bem-vindo ao Franz",
64 "services.getStarted": "Começar", 65 "services.getStarted": "Começar",
65 "settings.account.headline": "Conta", 66 "settings.account.headline": "Conta",
@@ -85,7 +86,7 @@
85 "settings.navigation.availableServices": "Serviços disponíveis", 86 "settings.navigation.availableServices": "Serviços disponíveis",
86 "settings.navigation.yourServices": "Seus serviços", 87 "settings.navigation.yourServices": "Seus serviços",
87 "settings.navigation.account": "Conta", 88 "settings.navigation.account": "Conta",
88 "settings.navigation.settings": "Configurações", 89 "settings.navigation.settings": "Ajustes",
89 "settings.navigation.logout": "Logout", 90 "settings.navigation.logout": "Logout",
90 "settings.recipes.headline": "Serviços disponíveis", 91 "settings.recipes.headline": "Serviços disponíveis",
91 "settings.recipes.mostPopular": "Mais populares", 92 "settings.recipes.mostPopular": "Mais populares",
@@ -115,7 +116,7 @@
115 "settings.services.discoverServices": "Descobrir serviços", 116 "settings.services.discoverServices": "Descobrir serviços",
116 "settings.services.updatedInfo": "Suas mudanças foram salvas", 117 "settings.services.updatedInfo": "Suas mudanças foram salvas",
117 "settings.services.deletedInfo": "Serviço apagado", 118 "settings.services.deletedInfo": "Serviço apagado",
118 "settings.app.headline": "Configurações", 119 "settings.app.headline": "Ajustes",
119 "settings.app.headlineGeneral": "Geral", 120 "settings.app.headlineGeneral": "Geral",
120 "settings.app.headlineLanguage": "Idioma", 121 "settings.app.headlineLanguage": "Idioma",
121 "settings.app.headlineUpdates": "Atualizações", 122 "settings.app.headlineUpdates": "Atualizações",
@@ -126,6 +127,7 @@
126 "settings.app.updateStatusUpToDate": "Você está usando a última versão do Franz", 127 "settings.app.updateStatusUpToDate": "Você está usando a última versão do Franz",
127 "settings.app.form.autoLaunchOnStart": "Abrir o Franz iniciar o sistema", 128 "settings.app.form.autoLaunchOnStart": "Abrir o Franz iniciar o sistema",
128 "settings.app.form.autoLaunchInBackground": "Abrir no fundo", 129 "settings.app.form.autoLaunchInBackground": "Abrir no fundo",
130 "settings.app.form.enableSystemTray": "Mostrar o Franz na bandeja do sistema",
129 "settings.app.form.minimizeToSystemTray": "Minimizar o Franz para a bandeja do sistema", 131 "settings.app.form.minimizeToSystemTray": "Minimizar o Franz para a bandeja do sistema",
130 "settings.app.form.runInBackground": "Manter o Franz no fundo quando fechar a janela", 132 "settings.app.form.runInBackground": "Manter o Franz no fundo quando fechar a janela",
131 "settings.app.form.language": "Idioma", 133 "settings.app.form.language": "Idioma",
diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json
index 44ced9e43..97b746097 100644
--- a/src/i18n/locales/ru.json
+++ b/src/i18n/locales/ru.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "ПерезапуÑтить и обновить", 60 "infobar.buttonInstallUpdate": "ПерезапуÑтить и обновить",
61 "infobar.requiredRequestsFailed": "Ðевозможно загрузить ÑервиÑÑ‹ и информацию пользователÑ", 61 "infobar.requiredRequestsFailed": "Ðевозможно загрузить ÑервиÑÑ‹ и информацию пользователÑ",
62 "sidebar.settings": "ÐаÑтройки", 62 "sidebar.settings": "ÐаÑтройки",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "Добро пожаловать во Franz", 64 "services.welcome": "Добро пожаловать во Franz",
64 "services.getStarted": "Ðачать работу", 65 "services.getStarted": "Ðачать работу",
65 "settings.account.headline": "Ðккаунт", 66 "settings.account.headline": "Ðккаунт",
diff --git a/src/i18n/locales/ua.json b/src/i18n/locales/ua.json
index 63135e52c..fcb99c4e4 100644
--- a/src/i18n/locales/ua.json
+++ b/src/i18n/locales/ua.json
@@ -60,6 +60,7 @@
60 "infobar.buttonInstallUpdate": "Перезавантажити Ñ– вÑтановити оновленнÑ", 60 "infobar.buttonInstallUpdate": "Перезавантажити Ñ– вÑтановити оновленнÑ",
61 "infobar.requiredRequestsFailed": "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑервіÑи та інформацію кориÑтувача", 61 "infobar.requiredRequestsFailed": "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑервіÑи та інформацію кориÑтувача",
62 "sidebar.settings": "ÐалаштуваннÑ", 62 "sidebar.settings": "ÐалаштуваннÑ",
63 "sidebar.addNewService": "!!!Add new service",
63 "services.welcome": "ЛаÑкаво проÑимо в Franz", 64 "services.welcome": "ЛаÑкаво проÑимо в Franz",
64 "services.getStarted": "Почати", 65 "services.getStarted": "Почати",
65 "settings.account.headline": "Ðкаунт", 66 "settings.account.headline": "Ðкаунт",
diff --git a/src/i18n/locales/zh-Hant.json b/src/i18n/locales/zh-Hant.json
new file mode 100644
index 000000000..e52b9ca26
--- /dev/null
+++ b/src/i18n/locales/zh-Hant.json
@@ -0,0 +1,168 @@
1{
2 "global.api.unhealthy": "無法連接到Franz網路æœå‹™",
3 "global.notConnectedToTheInternet": "您未連上網際網路",
4 "welcome.signupButton": "建立一個å…費帳戶",
5 "welcome.loginButton": "登入",
6 "welcome.slogan": "Messaging that works for you",
7 "login.headline": "登入",
8 "login.email.label": "é›»å­éƒµä»¶ä¿¡ç®±",
9 "login.password.label": "密碼",
10 "login.submit.label": "登入",
11 "login.invalidCredentials": "é›»å­éƒµä»¶å¸³æˆ¶æˆ–密碼有誤",
12 "login.tokenExpired": "登入狀態éŽæœŸï¼Œè«‹é‡æ–°ç™»å…¥",
13 "login.serverLogout": "登入狀態éŽæœŸï¼Œè«‹é‡æ–°ç™»å…¥",
14 "login.link.signup": "建立一個å…費帳戶",
15 "login.link.password": "密碼é‡è¨­",
16 "password.headline": "密碼é‡è¨­",
17 "password.email.label": "é›»å­éƒµä»¶ä¿¡ç®±",
18 "password.submit.label": "é€å‡º",
19 "password.noUser": "此電å­éƒµä»¶å¸³æˆ¶ä¸å­˜åœ¨",
20 "password.successInfo": "è«‹é‡æ–°ç¢ºèªæ‚¨çš„é›»å­éƒµä»¶ä¿¡ç®±",
21 "password.link.signup": "建立一個å…費帳戶",
22 "password.link.login": "登入您的帳戶",
23 "signup.headline": "註冊",
24 "signup.firstname.label": "åå­",
25 "signup.lastname.label": "姓æ°",
26 "signup.email.label": "é›»å­éƒµä»¶ä¿¡ç®±",
27 "signup.company.label": "å…¬å¸",
28 "signup.password.label": "密碼",
29 "signup.submit.label": "建立帳戶",
30 "signup.link.login": "您已有一個帳戶,請å•æ˜¯å¦è¦ç™»å…¥ï¼Ÿ",
31 "signup.emailDuplicate": "此電å­éƒµä»¶ä¿¡ç®±å·²è¢«è¨»å†Š",
32 "signup.legal.info": "在建立帳戶åŒæ™‚,您åŒæ„:",
33 "signup.legal.terms": "æœå‹™æ¢æ¬¾",
34 "signup.legal.privacy": "éš±ç§è²æ˜Ž",
35 "pricing.headline": "贊助 Franz",
36 "pricing.support.label": "é¸æ“‡è´ŠåŠ©æ–¹æ¡ˆ",
37 "pricing.submit.label": "我想å”助 Franz 的開發",
38 "pricing.link.skipPayment": "我ä¸æƒ³å”助 Franz 的開發",
39 "import.headline": "匯入您的 Franz 4 æœå‹™",
40 "import.notSupportedHeadline": "æ­¤æœå‹™ä¸è¢« Franz 5 支æŒ",
41 "import.submit.label": "匯入æœå‹™",
42 "import.skip.label": "我想手動匯入",
43 "invite.submit.label": "Send invites",
44 "invite.headline.friends": "邀請三個人",
45 "invite.name.label": "åå­",
46 "invite.email.label": "é›»å­éƒµä»¶ä¿¡ç®±",
47 "invite.skip.label": "我想晚點進行",
48 "subscription.submit.label": "我想å”助 Franz 的開發",
49 "subscription.paymentSessionError": "無法åˆå§‹åŒ–付費表單",
50 "subscription.includedFeatures": "Paid Franz Premium Supporter Account includes",
51 "subscription.features.onpremise": "Add on-premise/hosted services like HipChat",
52 "subscription.features.customServices": "Private services for you and your team",
53 "subscription.features.encryptedSync": "Encrypted session synchronization",
54 "subscription.features.vpn": "æ”¯æ´ Proxy & VPN",
55 "subscription.features.ads": "ä¸å†æœ‰ä»»ä½•å»£å‘Š",
56 "subscription.features.comingSoon": "敬請期待",
57 "infobar.servicesUpdated": "您的æœå‹™å·²æ›´æ–°",
58 "infobar.updateAvailable": "有新的更新å¯å®‰è£",
59 "infobar.buttonReloadServices": "é‡æ–°è¼‰å…¥",
60 "infobar.buttonInstallUpdate": "é‡æ–°å•Ÿå‹•ä¸¦ä¸”æ›´æ–°",
61 "infobar.requiredRequestsFailed": "無法載入æœå‹™èˆ‡å¸³æˆ¶è³‡è¨Š",
62 "sidebar.settings": "設定",
63 "services.welcome": "歡迎使用 Franz",
64 "services.getStarted": "開始使用",
65 "settings.account.headline": "帳戶",
66 "settings.account.headlineSubscription": "您的訂閱",
67 "settings.account.headlineUpgrade": "å‡ç´šå¸³æˆ¶ä»¥åŠè´ŠåŠ© Franz",
68 "settings.account.headlineInvoices": "Invoices",
69 "settings.account.manageSubscription.label": "管ç†è¨‚é–±",
70 "settings.account.accountType.basic": "基本帳戶",
71 "settings.account.accountType.premium": "Premium Supporter Account",
72 "settings.account.account.editButton": "更改帳戶資訊",
73 "settings.account.invoiceDownload": "下載",
74 "settings.account.userInfoRequestFailed": "無法載入帳戶資訊",
75 "settings.account.tryReloadUserInfoRequest": "è«‹é‡è©¦",
76 "settings.account.headlineProfile": "更新帳戶資訊",
77 "settings.account.headlineAccount": "帳戶資訊",
78 "settings.account.headlinePassword": "更改密碼",
79 "settings.account.successInfo": "您的更改已經儲存",
80 "settings.account.buttonSave": "更新帳戶資訊",
81 "settings.account.mining.thankyou": "æ„Ÿè¬æ‚¨è´ŠåŠ©é‹ç®—能力",
82 "settings.account.mining.active": "您ç¾åœ¨æ¯ç§’執行 {hashes} 個計算",
83 "settings.account.mining.moreInformation": "å–得更多資訊",
84 "settings.account.mining.cancel": "å–消贊助é‹ç®—",
85 "settings.navigation.availableServices": "å¯ç”¨æœå‹™",
86 "settings.navigation.yourServices": "您的æœå‹™",
87 "settings.navigation.account": "帳戶",
88 "settings.navigation.settings": "設定",
89 "settings.navigation.logout": "登出",
90 "settings.recipes.headline": "å¯ç”¨æœå‹™",
91 "settings.recipes.mostPopular": "熱門",
92 "settings.recipes.all": "全部",
93 "settings.recipes.dev": "開發中",
94 "settings.recipes.nothingFound": "抱歉,找ä¸åˆ°æ‚¨æ‰€è¦çš„æœå‹™",
95 "settings.recipes.servicesSuccessfulAddedInfo": "新增æœå‹™æˆåŠŸ",
96 "settings.service.form.saveButton": "儲存",
97 "settings.service.form.deleteButton": "刪除",
98 "settings.service.form.availableServices": "å¯ç”¨æœå‹™",
99 "settings.service.form.yourServices": "您的æœå‹™",
100 "settings.service.form.addServiceHeadline": "新增 {name}",
101 "settings.service.form.editServiceHeadline": "更改 {name}",
102 "settings.service.form.tabHosted": "Hosted",
103 "settings.service.form.tabOnPremise": "Self hosted â­ï¸",
104 "settings.service.form.customUrlValidationError": "Could not validate custom {name} server.",
105 "settings.service.form.customUrlPremiumInfo": "To add self hosted services, you need a Franz Premium Supporter Account.",
106 "settings.service.form.customUrlUpgradeAccount": "å‡ç´šå¸³æˆ¶",
107 "settings.service.form.indirectMessageInfo": "除了 @username, @channel, @here 之外,當您åƒèˆ‡çš„é »é“有訊æ¯æ™‚,就會通知",
108 "settings.service.error.headline": "錯誤",
109 "settings.service.error.goBack": "返回",
110 "settings.service.error.message": "無法載入æœå‹™å…ƒä»¶",
111 "settings.services.tooltip.isDisabled": "å·²åœç”¨æœå‹™",
112 "settings.services.tooltip.notificationsDisabled": "å·²åœç”¨é€šçŸ¥",
113 "settings.services.headline": "您的æœå‹™",
114 "settings.services.noServicesAdded": "您還沒加入任何æœå‹™",
115 "settings.services.discoverServices": "æœå‹™åˆ—表",
116 "settings.services.updatedInfo": "更動已經儲存",
117 "settings.services.deletedInfo": "æœå‹™å·²åˆªé™¤",
118 "settings.app.headline": "設定",
119 "settings.app.headlineGeneral": "一般",
120 "settings.app.headlineLanguage": "語言",
121 "settings.app.headlineUpdates": "æ›´æ–°",
122 "settings.app.buttonSearchForUpdate": "檢查更新",
123 "settings.app.buttonInstallUpdate": "é‡æ–°é–‹å•Ÿä¸¦ä¸”æ›´æ–°",
124 "settings.app.updateStatusSearching": "檢查更新中...",
125 "settings.app.updateStatusAvailable": "有å¯ç”¨æ›´æ–°ï¼Œä¸‹è¼‰ä¸­...",
126 "settings.app.updateStatusUpToDate": "已經是最新版本了",
127 "settings.app.form.autoLaunchOnStart": "開機時啟動",
128 "settings.app.form.autoLaunchInBackground": "背景啟動",
129 "settings.app.form.enableSystemTray": "在系統匣上顯示",
130 "settings.app.form.minimizeToSystemTray": "最å°åŒ–至系統匣",
131 "settings.app.form.runInBackground": "關閉時ä¿æŒåœ¨èƒŒæ™¯é‹ä½œ",
132 "settings.app.form.language": "語言",
133 "settings.app.form.beta": "包å«é–‹ç™¼ä¸­ç‰ˆæœ¬",
134 "settings.app.currentVersion": "當å‰ç‰ˆæœ¬ï¼š",
135 "settings.service.form.name": "Name",
136 "settings.service.form.enableService": "啟用æœå‹™",
137 "settings.service.form.enableNotification": "啟用通知",
138 "settings.service.form.team": "Team",
139 "settings.service.form.customUrl": "Custom server",
140 "settings.service.form.indirectMessages": "é‡å°å…¨éƒ¨è¨Šæ¯é¡¯ç¤ºé€šçŸ¥",
141 "settings.user.form.firstname": "åå­",
142 "settings.user.form.lastname": "姓æ°",
143 "settings.user.form.email": "é›»å­éƒµä»¶ä¿¡ç®±",
144 "settings.user.form.currentPassword": "舊密碼",
145 "settings.user.form.newPassword": "新密碼",
146 "settings.user.form.accountType.label": "帳戶類型",
147 "settings.user.form.accountType.individual": "個人",
148 "settings.user.form.accountType.non-profit": "éžç‡Ÿåˆ©",
149 "settings.user.form.accountType.company": "å…¬å¸",
150 "subscription.type.free": "å…è²»",
151 "subscription.type.month": "月",
152 "subscription.type.year": "å¹´",
153 "subscription.type.mining": "用您機器的計算能力來贊助 Franz",
154 "subscription.mining.headline": "如何進行的?",
155 "subscription.mining.experimental": "實驗性功能",
156 "subscription.mining.line1": "Franz é‹ç”¨æ‚¨CPUçš„20%至50%çš„é‹ç®—能力來挖門羅幣(一種開æºåŠ å¯†è²¨å¹£ï¼‰ï¼Œæ¯å¹´ç´„莫å¯å¾—到5美元。",
157 "subscription.mining.line2": "我們會調整é‹ç®—強度,é¿å…消耗éŽå¤šé›»æ± é›»é‡åŠå½±éŸ¿æ•ˆèƒ½ã€‚",
158 "subscription.mining.line3": "當您å…許我們挖掘門羅幣之時,我們便å…許您使用全部的加值æœå‹™ã€‚",
159 "subscription.mining.moreInformation": "å–得更多資訊",
160 "subscriptionPopup.buttonCancel": "å–消",
161 "subscriptionPopup.buttonDone": "完æˆ",
162 "tabs.item.reload": "é‡æ–°è¼‰å…¥",
163 "tabs.item.edit": "更改",
164 "tabs.item.disableNotifications": "åœç”¨é€šçŸ¥",
165 "tabs.item.enableNotification": "啟用通知",
166 "tabs.item.disableService": "åœç”¨æœå‹™",
167 "tabs.item.deleteService": "刪除æœå‹™"
168}
diff --git a/src/index.js b/src/index.js
index 9ca059f48..a3aa14732 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,18 +2,14 @@ import { app, BrowserWindow, shell } from 'electron';
2import fs from 'fs-extra'; 2import fs from 'fs-extra';
3import path from 'path'; 3import path from 'path';
4 4
5/* eslint-disable */
6if (require('electron-squirrel-startup')) app.quit();
7
8import windowStateKeeper from 'electron-window-state'; 5import windowStateKeeper from 'electron-window-state';
9 6
10import { isDevMode, isWindows } from './environment'; 7import { isDevMode, isWindows } from './environment';
11import ipcApi from './electron/ipc-api'; 8import ipcApi from './electron/ipc-api';
12import Tray from './lib/Tray'; 9import Tray from './lib/Tray';
13import Settings from './electron/Settings'; 10import Settings from './electron/Settings';
14import { appId } from './package.json'; 11import { appId } from './package.json'; // eslint-disable-line import/no-unresolved
15import './electron/exception'; 12import './electron/exception';
16/* eslint-enable */
17 13
18// Keep a global reference of the window object, if you don't, the window will 14// Keep a global reference of the window object, if you don't, the window will
19// be closed automatically when the JavaScript object is garbage collected. 15// be closed automatically when the JavaScript object is garbage collected.
@@ -22,6 +18,7 @@ let willQuitApp = false;
22 18
23// Ensure that the recipe directory exists 19// Ensure that the recipe directory exists
24fs.ensureDir(path.join(app.getPath('userData'), 'recipes')); 20fs.ensureDir(path.join(app.getPath('userData'), 'recipes'));
21fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp'));
25 22
26// Set App ID for Windows 23// Set App ID for Windows
27if (isWindows) { 24if (isWindows) {
@@ -66,7 +63,7 @@ const createWindow = async () => {
66 }); 63 });
67 64
68 // Initialize System Tray 65 // Initialize System Tray
69 const trayIcon = new Tray(mainWindow); 66 const trayIcon = new Tray();
70 67
71 // Initialize ipcApi 68 // Initialize ipcApi
72 ipcApi({ mainWindow, settings, trayIcon }); 69 ipcApi({ mainWindow, settings, trayIcon });
@@ -114,6 +111,13 @@ const createWindow = async () => {
114 app.isMaximized = true; 111 app.isMaximized = true;
115 }); 112 });
116 113
114 mainWindow.on('close', (e) => {
115 if (settings.get('minimizeToSystemTray')) {
116 e.preventDefault();
117 mainWindow.minimize();
118 }
119 });
120
117 mainWindow.on('unmaximize', () => { 121 mainWindow.on('unmaximize', () => {
118 app.isMaximized = false; 122 app.isMaximized = false;
119 }); 123 });
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index a6cde4d36..8f0a92c3d 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -1,9 +1,9 @@
1import { remote, shell } from 'electron'; 1import { remote, shell } from 'electron';
2import { autorun, computed, observable, toJS } from 'mobx'; 2import { autorun, computed, observable, toJS } from 'mobx';
3 3
4import { isDevMode, isMac } from '../environment'; 4import { isMac } from '../environment';
5 5
6const { app, Menu } = remote; 6const { app, Menu, dialog } = remote;
7 7
8const template = [ 8const template = [
9 { 9 {
@@ -84,6 +84,28 @@ const template = [
84 label: 'Learn More', 84 label: 'Learn More',
85 click() { shell.openExternal('http://meetfranz.com'); }, 85 click() { shell.openExternal('http://meetfranz.com'); },
86 }, 86 },
87 {
88 label: 'Changelog',
89 click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); },
90 },
91 {
92 type: 'separator',
93 },
94 {
95 label: 'Support',
96 click() { shell.openExternal('http://meetfranz.com/support'); },
97 },
98 {
99 type: 'separator',
100 },
101 {
102 label: 'Terms of Service',
103 click() { shell.openExternal('https://meetfranz.com/terms'); },
104 },
105 {
106 label: 'Privacy Statement',
107 click() { shell.openExternal('https://meetfranz.com/privacy'); },
108 },
87 ], 109 ],
88 }, 110 },
89]; 111];
@@ -101,17 +123,15 @@ export default class FranzMenu {
101 _build() { 123 _build() {
102 const tpl = toJS(this.tpl); 124 const tpl = toJS(this.tpl);
103 125
104 if (isDevMode) { 126 tpl[1].submenu.push({
105 tpl[1].submenu.push({ 127 role: 'toggledevtools',
106 role: 'toggledevtools', 128 }, {
107 }, { 129 label: 'Toggle Service Developer Tools',
108 label: 'Toggle Service Developer Tools', 130 accelerator: 'CmdOrCtrl+Shift+Alt+i',
109 accelerator: 'CmdOrCtrl+Shift+Alt+i', 131 click: () => {
110 click: () => { 132 this.actions.service.openDevToolsForActiveService();
111 this.actions.service.openDevToolsForActiveService(); 133 },
112 }, 134 });
113 });
114 }
115 135
116 tpl[1].submenu.unshift({ 136 tpl[1].submenu.unshift({
117 label: 'Reload Service', 137 label: 'Reload Service',
@@ -218,6 +238,18 @@ export default class FranzMenu {
218 role: 'front', 238 role: 'front',
219 }, 239 },
220 ]; 240 ];
241 } else {
242 tpl[4].submenu.unshift({
243 role: 'about',
244 click: () => {
245 dialog.showMessageBox({
246 type: 'info',
247 title: 'Franz',
248 message: 'Franz',
249 detail: `Version: ${remote.app.getVersion()}\nRelease: ${process.versions.electron} / ${process.platform} / ${process.arch}`,
250 });
251 },
252 });
221 } 253 }
222 254
223 const serviceTpl = this.serviceTpl; 255 const serviceTpl = this.serviceTpl;
diff --git a/src/lib/Tray.js b/src/lib/Tray.js
index 67150971e..2efe71a71 100644
--- a/src/lib/Tray.js
+++ b/src/lib/Tray.js
@@ -6,12 +6,9 @@ const INDICATOR_TRAY_PLAIN = 'tray';
6const INDICATOR_TRAY_UNREAD = 'tray-unread'; 6const INDICATOR_TRAY_UNREAD = 'tray-unread';
7 7
8export default class TrayIcon { 8export default class TrayIcon {
9 mainWindow = null;
10 trayIcon = null; 9 trayIcon = null;
11 10 indicator = 0;
12 constructor(mainWindow) { 11 themeChangeSubscriberId = null;
13 this.mainWindow = mainWindow;
14 }
15 12
16 show() { 13 show() {
17 if (this.trayIcon) return; 14 if (this.trayIcon) return;
@@ -21,7 +18,7 @@ export default class TrayIcon {
21 { 18 {
22 label: 'Show Franz', 19 label: 'Show Franz',
23 click() { 20 click() {
24 this.mainWindow.show(); 21 app.mainWindow.show();
25 }, 22 },
26 }, { 23 }, {
27 label: 'Quit Franz', 24 label: 'Quit Franz',
@@ -35,30 +32,45 @@ export default class TrayIcon {
35 this.trayIcon.setContextMenu(trayMenu); 32 this.trayIcon.setContextMenu(trayMenu);
36 33
37 this.trayIcon.on('click', () => { 34 this.trayIcon.on('click', () => {
38 this.mainWindow.show(); 35 app.mainWindow.show();
39 }); 36 });
37
38 if (process.platform === 'darwin') {
39 this.themeChangeSubscriberId = systemPreferences.subscribeNotification('AppleInterfaceThemeChangedNotification', () => {
40 this._refreshIcon();
41 });
42 }
40 } 43 }
41 44
42 hide() { 45 hide() {
43 if (this.trayIcon) { 46 if (!this.trayIcon) return;
44 this.trayIcon.destroy(); 47
45 this.trayIcon = null; 48 this.trayIcon.destroy();
49 this.trayIcon = null;
50
51 if (process.platform === 'darwin' && this.themeChangeSubscriberId) {
52 systemPreferences.unsubscribeNotification(this.themeChangeSubscriberId);
53 this.themeChangeSubscriberId = null;
46 } 54 }
47 } 55 }
48 56
49 setIndicator(indicator) { 57 setIndicator(indicator) {
58 this.indicator = indicator;
59 this._refreshIcon();
60 }
61
62 _refreshIcon() {
50 if (!this.trayIcon) return; 63 if (!this.trayIcon) return;
51 64
52 this.trayIcon.setImage(this._getAsset('tray', indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); 65 this.trayIcon.setImage(this._getAsset('tray', this.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN));
53 66
54 if (process.platform === 'darwin') { 67 if (process.platform === 'darwin') {
55 this.trayIcon.setPressedImage( 68 this.trayIcon.setPressedImage(
56 this._getAsset('tray', `${indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), 69 this._getAsset('tray', `${this.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`),
57 ); 70 );
58 } 71 }
59 } 72 }
60 73
61
62 _getAsset(type, asset) { 74 _getAsset(type, asset) {
63 let platform = process.platform; 75 let platform = process.platform;
64 76
diff --git a/src/models/Recipe.js b/src/models/Recipe.js
index 43a3450b1..9971df77c 100644
--- a/src/models/Recipe.js
+++ b/src/models/Recipe.js
@@ -1,7 +1,8 @@
1import emailParser from 'address-rfc2822';
2
1export default class Recipe { 3export default class Recipe {
2 id = ''; 4 id = '';
3 name = ''; 5 name = '';
4 author = '';
5 description = ''; 6 description = '';
6 version = '1.0'; 7 version = '1.0';
7 path = ''; 8 path = '';
@@ -25,12 +26,13 @@ export default class Recipe {
25 } 26 }
26 27
27 if (!data.id) { 28 if (!data.id) {
28 throw Error('Recipe requires Id'); 29 // Franz 4 recipes do not have an Id
30 throw Error(`Recipe '${data.name}' requires Id`);
29 } 31 }
30 32
31 this.id = data.id || this.id; 33 this.id = data.id || this.id;
32 this.name = data.name || this.name; 34 this.name = data.name || this.name;
33 this.author = data.author || this.author; 35 this.rawAuthor = data.author || this.author;
34 this.description = data.description || this.description; 36 this.description = data.description || this.description;
35 this.version = data.version || this.version; 37 this.version = data.version || this.version;
36 this.path = data.path; 38 this.path = data.path;
@@ -49,4 +51,15 @@ export default class Recipe {
49 51
50 this.message = data.config.message || this.message; 52 this.message = data.config.message || this.message;
51 } 53 }
54
55 get author() {
56 try {
57 const addresses = emailParser.parse(this.rawAuthor);
58 return addresses.map(a => ({ email: a.address, name: a.phrase }));
59 } catch (err) {
60 console.warn(`Not a valid author for ${this.name}`);
61 }
62
63 return [];
64 }
52} 65}
diff --git a/src/models/Service.js b/src/models/Service.js
index 7a0310ebc..484252e7c 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -58,7 +58,12 @@ export default class Service {
58 58
59 @computed get url() { 59 @computed get url() {
60 if (this.recipe.hasCustomUrl && this.customUrl) { 60 if (this.recipe.hasCustomUrl && this.customUrl) {
61 let url = normalizeUrl(this.customUrl); 61 let url;
62 try {
63 url = normalizeUrl(this.customUrl);
64 } catch (err) {
65 console.error(`Service (${this.recipe.name}): '${this.customUrl}' is not a valid Url.`);
66 }
62 67
63 if (typeof this.recipe.buildUrl === 'function') { 68 if (typeof this.recipe.buildUrl === 'function') {
64 url = this.recipe.buildUrl(url); 69 url = this.recipe.buildUrl(url);
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 7dbef985d..ecfd621d3 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -2,19 +2,23 @@ import { remote, ipcRenderer, shell } from 'electron';
2import { action, observable } from 'mobx'; 2import { action, observable } from 'mobx';
3import moment from 'moment'; 3import moment from 'moment';
4import key from 'keymaster'; 4import key from 'keymaster';
5import path from 'path'; 5// import path from 'path';
6import idleTimer from '@paulcbetts/system-idle-time'; 6import idleTimer from '@paulcbetts/system-idle-time';
7import AutoLaunch from 'auto-launch';
7 8
8import Store from './lib/Store'; 9import Store from './lib/Store';
9import Request from './lib/Request'; 10import Request from './lib/Request';
10import { CHECK_INTERVAL } from '../config'; 11import { CHECK_INTERVAL } from '../config';
11import { isMac, isLinux } from '../environment'; 12import { isMac } from '../environment';
12import locales from '../i18n/translations'; 13import locales from '../i18n/translations';
13import { gaEvent } from '../lib/analytics'; 14import { gaEvent } from '../lib/analytics';
14import Miner from '../lib/Miner'; 15import Miner from '../lib/Miner';
15 16
16const { app, getCurrentWindow, powerMonitor } = remote; 17const { app, powerMonitor } = remote;
17const defaultLocale = 'en-US'; 18const defaultLocale = 'en-US';
19const autoLauncher = new AutoLaunch({
20 name: 'Franz',
21});
18 22
19export default class AppStore extends Store { 23export default class AppStore extends Store {
20 updateStatusTypes = { 24 updateStatusTypes = {
@@ -41,7 +45,7 @@ export default class AppStore extends Store {
41 miner = null; 45 miner = null;
42 @observable minerHashrate = 0.0; 46 @observable minerHashrate = 0.0;
43 47
44 constructor(...args: any) { 48 constructor(...args) {
45 super(...args); 49 super(...args);
46 50
47 // Register action handlers 51 // Register action handlers
@@ -112,24 +116,15 @@ export default class AppStore extends Store {
112 setTimeout(window.location.reload, 5000); 116 setTimeout(window.location.reload, 5000);
113 }); 117 });
114 118
115 // Open Dev Tools (even in production mode)
116 key('⌘+ctrl+shift+alt+i, ctrl+shift+alt+i', () => {
117 getCurrentWindow().toggleDevTools();
118 });
119
120 key('⌘+ctrl+shift+alt+pageup, ctrl+shift+alt+pageup', () => {
121 this.actions.service.openDevToolsForActiveService();
122 });
123
124 // Set active the next service 119 // Set active the next service
125 key( 120 key(
126 '⌘+pagedown, ctrl+pagedown, ⌘+shift+tab, ctrl+shift+tab', () => { 121 '⌘+pagedown, ctrl+pagedown, ⌘+tab, ctrl+tab', () => {
127 this.actions.service.setActiveNext(); 122 this.actions.service.setActiveNext();
128 }); 123 });
129 124
130 // Set active the prev service 125 // Set active the prev service
131 key( 126 key(
132 '⌘+pageup, ctrl+pageup, ⌘+tab, ctrl+tab', () => { 127 '⌘+pageup, ctrl+pageup, ⌘+shift+tab, ctrl+shift+tab', () => {
133 this.actions.service.setActivePrev(); 128 this.actions.service.setActivePrev();
134 }); 129 });
135 130
@@ -161,33 +156,24 @@ export default class AppStore extends Store {
161 indicator = '•'; 156 indicator = '•';
162 } else if (unreadDirectMessageCount === 0 && unreadIndirectMessageCount === 0) { 157 } else if (unreadDirectMessageCount === 0 && unreadIndirectMessageCount === 0) {
163 indicator = 0; 158 indicator = 0;
159 } else {
160 indicator = parseInt(indicator, 10);
164 } 161 }
165 162
166 ipcRenderer.send('updateAppIndicator', { indicator }); 163 ipcRenderer.send('updateAppIndicator', { indicator });
167 } 164 }
168 165
169 @action _launchOnStartup({ enable, openInBackground }) { 166 @action _launchOnStartup({ enable }) {
170 this.autoLaunchOnStart = enable; 167 this.autoLaunchOnStart = enable;
171 168
172 let settings = { 169 try {
173 openAtLogin: enable, 170 if (enable) {
174 }; 171 autoLauncher.enable();
175 172 } else {
176 // For Windows 173 autoLauncher.disable();
177 if (process.platform === 'win32') {
178 settings = Object.assign({
179 openAsHidden: openInBackground,
180 path: app.getPath('exe'),
181 args: [
182 '--processStart', `"${path.basename(app.getPath('exe'))}"`,
183 ],
184 }, settings);
185
186 if (openInBackground) {
187 settings.args.push(
188 '--process-start-args', '"--hidden"',
189 );
190 } 174 }
175 } catch (err) {
176 console.warn(err);
191 } 177 }
192 178
193 gaEvent('App', enable ? 'enable autostart' : 'disable autostart'); 179 gaEvent('App', enable ? 'enable autostart' : 'disable autostart');
@@ -296,31 +282,19 @@ export default class AppStore extends Store {
296 } 282 }
297 283
298 async _autoStart() { 284 async _autoStart() {
299 if (!isLinux) { 285 this.autoLaunchOnStart = await this._checkAutoStart();
300 this._checkAutoStart();
301
302 // we need to wait until the settings request is resolved
303 await this.stores.settings.allSettingsRequest;
304 286
305 // We don't set autostart on first launch for macOS as disabling 287 // we need to wait until the settings request is resolved
306 // the option is currently broken 288 await this.stores.settings.allSettingsRequest;
307 // https://github.com/meetfranz/franz/issues/17
308 // https://github.com/electron/electron/issues/10880
309 if (process.platform === 'darwin') return;
310 289
311 if (!this.stores.settings.all.appStarts) { 290 if (!this.stores.settings.all.appStarts) {
312 this.actions.app.launchOnStartup({ 291 this.actions.app.launchOnStartup({
313 enable: true, 292 enable: true,
314 }); 293 });
315 }
316 } 294 }
317 } 295 }
318 296
319 _checkAutoStart() { 297 async _checkAutoStart() {
320 const loginItem = app.getLoginItemSettings({ 298 return autoLauncher.isEnabled() || false;
321 path: app.getPath('exe'),
322 });
323
324 this.autoLaunchOnStart = loginItem.openAtLogin;
325 } 299 }
326} 300}
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 19db05494..1d895d532 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -41,6 +41,7 @@ export default class ServicesStore extends Store {
41 this.actions.service.openWindow.listen(this._openWindow.bind(this)); 41 this.actions.service.openWindow.listen(this._openWindow.bind(this));
42 this.actions.service.filter.listen(this._filter.bind(this)); 42 this.actions.service.filter.listen(this._filter.bind(this));
43 this.actions.service.resetFilter.listen(this._resetFilter.bind(this)); 43 this.actions.service.resetFilter.listen(this._resetFilter.bind(this));
44 this.actions.service.resetStatus.listen(this._resetStatus.bind(this));
44 this.actions.service.reload.listen(this._reload.bind(this)); 45 this.actions.service.reload.listen(this._reload.bind(this));
45 this.actions.service.reloadActive.listen(this._reloadActive.bind(this)); 46 this.actions.service.reloadActive.listen(this._reloadActive.bind(this));
46 this.actions.service.reloadAll.listen(this._reloadAll.bind(this)); 47 this.actions.service.reloadAll.listen(this._reloadAll.bind(this));
@@ -144,12 +145,12 @@ export default class ServicesStore extends Store {
144 serviceData.name = data.name; 145 serviceData.name = data.name;
145 } 146 }
146 147
147 if (data.team) { 148 if (data.team && !data.customURL) {
148 serviceData.team = data.team; 149 serviceData.team = data.team;
149 } 150 }
150 151
151 if (data.team) { 152 if (data.team && data.customURL) {
152 serviceData.customUrl = data.customURL; 153 serviceData.customUrl = data.team;
153 } 154 }
154 155
155 this.actions.service.createService({ 156 this.actions.service.createService({
@@ -157,8 +158,6 @@ export default class ServicesStore extends Store {
157 serviceData, 158 serviceData,
158 redirect: false, 159 redirect: false,
159 }); 160 });
160
161 return 'hello world';
162 } 161 }
163 162
164 @action async _updateService({ serviceId, serviceData, redirect = true }) { 163 @action async _updateService({ serviceId, serviceData, redirect = true }) {
@@ -295,9 +294,12 @@ export default class ServicesStore extends Store {
295 } 294 }
296 295
297 if (service.isNotificationEnabled) { 296 if (service.isNotificationEnabled) {
297 const title = typeof args[0].title === 'string' ? args[0].title : service.name;
298 options.body = typeof options.body === 'string' ? options.body : '';
299
298 this.actions.app.notify({ 300 this.actions.app.notify({
299 notificationId: args[0].notificationId, 301 notificationId: args[0].notificationId,
300 title: args[0].title, 302 title,
301 options, 303 options,
302 serviceId, 304 serviceId,
303 }); 305 });
@@ -338,6 +340,10 @@ export default class ServicesStore extends Store {
338 this.filterNeedle = null; 340 this.filterNeedle = null;
339 } 341 }
340 342
343 @action _resetStatus() {
344 this.actionStatus = [];
345 }
346
341 @action _reload({ serviceId }) { 347 @action _reload({ serviceId }) {
342 const service = this.one(serviceId); 348 const service = this.one(serviceId);
343 service.resetMessageCount(); 349 service.resetMessageCount();
@@ -383,7 +389,7 @@ export default class ServicesStore extends Store {
383 data.forEach((s) => { 389 data.forEach((s) => {
384 const service = s; 390 const service = s;
385 391
386 service.order = this.one(s.id).order; 392 service.order = services[s.id];
387 }); 393 });
388 }); 394 });
389 395
diff --git a/src/webview/lib/RecipeWebview.js b/src/webview/lib/RecipeWebview.js
index 1787f85e2..b8acc1258 100644
--- a/src/webview/lib/RecipeWebview.js
+++ b/src/webview/lib/RecipeWebview.js
@@ -64,6 +64,12 @@ class RecipeWebview {
64 }); 64 });
65 } 65 }
66 66
67 onNotify(fn) {
68 if (typeof fn === 'function') {
69 window.Notification.onNotify = fn;
70 }
71 }
72
67 initialize(fn) { 73 initialize(fn) {
68 if (typeof fn === 'function') { 74 if (typeof fn === 'function') {
69 fn(); 75 fn();
diff --git a/src/webview/notifications.js b/src/webview/notifications.js
index 97ce9d69b..4055b10de 100644
--- a/src/webview/notifications.js
+++ b/src/webview/notifications.js
@@ -1,45 +1,46 @@
1const { ipcRenderer } = require('electron'); 1const { ipcRenderer } = require('electron');
2const uuidV1 = require('uuid/v1'); 2const uuidV1 = require('uuid/v1');
3// const FranzNotificationStore = [];
4 3
5class Notification { 4class Notification {
5 static permission = 'granted';
6
6 constructor(title = '', options = {}) { 7 constructor(title = '', options = {}) {
7 this.title = title; 8 this.title = title;
8 this.options = options; 9 this.options = options;
9 this.notificationId = uuidV1(); 10 this.notificationId = uuidV1();
10 this.onclick = () => {};
11 11
12 ipcRenderer.sendToHost('notification', { 12 ipcRenderer.sendToHost('notification', this.onNotify({
13 notificationId: this.notificationId, 13 notificationId: this.notificationId,
14 title, 14 title,
15 options, 15 options,
16 }); 16 }));
17 17
18 ipcRenderer.on(`notification-onclick:${this.notificationId}`, () => { 18 ipcRenderer.once(`notification-onclick:${this.notificationId}`, () => {
19 this.onclick(); 19 this.onclick();
20 }); 20 });
21 } 21 }
22}
23 22
24Notification.permission = 'granted'; 23 static requestPermission(cb = null) {
24 if (!cb) {
25 return new Promise((resolve) => {
26 resolve(Notification.permission);
27 });
28 }
25 29
26Notification.requestPermission = (cb = null) => { 30 if (typeof (cb) === 'function') {
27 console.log(this); 31 return cb(Notification.permission);
28 if (!cb) { 32 }
29 return new Promise((resolve) => { 33
30 resolve(Notification.permission); 34 return Notification.permission;
31 });
32 } 35 }
33 36
34 if (typeof (cb) === 'function') { 37 onNotify(data) {
35 return cb(Notification.permission); 38 return data;
36 } 39 }
37 40
38 return Notification.permission; 41 onClick() {}
39};
40 42
41Notification.close = () => { 43 close() {}
42 // no implementation yet 44}
43};
44 45
45window.Notification = Notification; 46window.Notification = Notification;
diff --git a/yarn.lock b/yarn.lock
index 4e596b555..0bedbac27 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -32,8 +32,8 @@
32 underscore "^1.6.0" 32 underscore "^1.6.0"
33 33
34"@paulcbetts/spellchecker@^4.0.5": 34"@paulcbetts/spellchecker@^4.0.5":
35 version "4.0.5" 35 version "4.0.6"
36 resolved "https://registry.yarnpkg.com/@paulcbetts/spellchecker/-/spellchecker-4.0.5.tgz#4ea9bfb85faba53c094c0809a18986bf44265c5f" 36 resolved "https://registry.yarnpkg.com/@paulcbetts/spellchecker/-/spellchecker-4.0.6.tgz#79ef1f9c19c5a3156921ccaa9ffdc3efbbee47e3"
37 dependencies: 37 dependencies:
38 nan "^2.0.0" 38 nan "^2.0.0"
39 39
@@ -80,6 +80,12 @@ acorn@^5.1.1:
80 version "5.1.2" 80 version "5.1.2"
81 resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" 81 resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
82 82
83address-rfc2822@^2.0.1:
84 version "2.0.1"
85 resolved "https://registry.yarnpkg.com/address-rfc2822/-/address-rfc2822-2.0.1.tgz#1a1bdb942b5e20e2c1ba5d5f396d5824ff7ae6ea"
86 dependencies:
87 email-addresses "^3.0.0"
88
83after@0.8.2: 89after@0.8.2:
84 version "0.8.2" 90 version "0.8.2"
85 resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" 91 resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
@@ -151,6 +157,10 @@ anymatch@^1.3.0:
151 micromatch "^2.1.5" 157 micromatch "^2.1.5"
152 normalize-path "^2.0.0" 158 normalize-path "^2.0.0"
153 159
160applescript@^1.0.0:
161 version "1.0.0"
162 resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317"
163
154aproba@^1.0.3: 164aproba@^1.0.3:
155 version "1.1.2" 165 version "1.1.2"
156 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" 166 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
@@ -319,6 +329,16 @@ asynckit@^0.4.0:
319 version "0.4.0" 329 version "0.4.0"
320 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 330 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
321 331
332"auto-launch@https://github.com/meetfranz/node-auto-launch.git":
333 version "5.0.1"
334 resolved "https://github.com/meetfranz/node-auto-launch.git#b90a0470467eb84435e6554ae9db1e2c6db79e61"
335 dependencies:
336 applescript "^1.0.0"
337 mkdirp "^0.5.1"
338 path-is-absolute "^1.0.0"
339 untildify "^3.0.2"
340 winreg "1.2.2"
341
322aws-sign2@~0.6.0: 342aws-sign2@~0.6.0:
323 version "0.6.0" 343 version "0.6.0"
324 resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" 344 resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
@@ -1998,12 +2018,6 @@ electron-spellchecker@^1.2.0:
1998 rxjs-serial-subscription "^0.1.1" 2018 rxjs-serial-subscription "^0.1.1"
1999 spawn-rx "^2.0.7" 2019 spawn-rx "^2.0.7"
2000 2020
2001electron-squirrel-startup@^1.0.0:
2002 version "1.0.0"
2003 resolved "https://registry.yarnpkg.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz#19b4e55933fa0ef8f556784b9c660f772546a0b8"
2004 dependencies:
2005 debug "^2.2.0"
2006
2007electron-to-chromium@^1.3.18: 2021electron-to-chromium@^1.3.18:
2008 version "1.3.20" 2022 version "1.3.20"
2009 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz#2eedd5ccbae7ddc557f68ad1fce9c172e915e4e5" 2023 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz#2eedd5ccbae7ddc557f68ad1fce9c172e915e4e5"
@@ -2041,6 +2055,10 @@ electron@^1.7.9:
2041 electron-download "^3.0.1" 2055 electron-download "^3.0.1"
2042 extract-zip "^1.0.3" 2056 extract-zip "^1.0.3"
2043 2057
2058email-addresses@^3.0.0:
2059 version "3.0.1"
2060 resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.0.1.tgz#c1fc20c189e7f96d4012d375db5feaccdd24391c"
2061
2044emojis-list@^2.0.0: 2062emojis-list@^2.0.0:
2045 version "2.1.0" 2063 version "2.1.0"
2046 resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" 2064 resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
@@ -5949,6 +5967,10 @@ universalify@^0.1.0:
5949 version "0.1.1" 5967 version "0.1.1"
5950 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" 5968 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
5951 5969
5970untildify@^3.0.2:
5971 version "3.0.2"
5972 resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.2.tgz#7f1f302055b3fea0f3e81dc78eb36766cb65e3f1"
5973
5952unzip-response@^2.0.1: 5974unzip-response@^2.0.1:
5953 version "2.0.1" 5975 version "2.0.1"
5954 resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" 5976 resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
@@ -6133,6 +6155,10 @@ window-size@^0.1.4:
6133 version "0.1.4" 6155 version "0.1.4"
6134 resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" 6156 resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
6135 6157
6158winreg@1.2.2:
6159 version "1.2.2"
6160 resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.2.tgz#8509afa3b71c5bbd110a6d7c6247ec67736c598f"
6161
6136word-wrap@^1.0.3: 6162word-wrap@^1.0.3:
6137 version "1.2.3" 6163 version "1.2.3"
6138 resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 6164 resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"