aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Amine Mouafik <amine@mouafik.fr>2019-05-12 20:00:41 +0700
committerLibravatar Amine Mouafik <amine@mouafik.fr>2019-05-12 20:00:41 +0700
commitd8a1d5f9151cc31f4c2b5c0096a35e49b2c74d61 (patch)
tree3974d449d8ef389fc61bf880ae758b5debc22a80 /src
parentUse dark background in SVG logo (diff)
parentUpdate CHANGELOG.md (diff)
downloadferdium-app-d8a1d5f9151cc31f4c2b5c0096a35e49b2c74d61.tar.gz
ferdium-app-d8a1d5f9151cc31f4c2b5c0096a35e49b2c74d61.tar.zst
ferdium-app-d8a1d5f9151cc31f4c2b5c0096a35e49b2c74d61.zip
Merge tag 'v5.1.0'
# Conflicts: # README.md # src/components/layout/AppLayout.js
Diffstat (limited to 'src')
-rw-r--r--src/actions/index.js8
-rw-r--r--src/actions/lib/actions.js33
-rw-r--r--src/actions/service.js5
-rw-r--r--src/api/PaymentApi.js8
-rw-r--r--src/api/server/ServerApi.js198
-rw-r--r--src/api/utils/auth.js28
-rw-r--r--src/app.js7
-rw-r--r--src/components/layout/AppLayout.js78
-rw-r--r--src/components/layout/Sidebar.js49
-rw-r--r--src/components/services/content/ServiceView.js139
-rw-r--r--src/components/services/content/ServiceWebview.js145
-rw-r--r--src/components/services/content/Services.js7
-rw-r--r--src/components/services/content/WebviewCrashHandler.js7
-rw-r--r--src/components/services/tabs/Tabbar.js4
-rw-r--r--src/components/settings/account/AccountDashboard.js199
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js46
-rw-r--r--src/components/settings/services/EditServiceForm.js16
-rw-r--r--src/components/settings/services/ServicesDashboard.js2
-rw-r--r--src/components/settings/settings/EditSettingsForm.js9
-rw-r--r--src/components/settings/team/TeamDashboard.js152
-rw-r--r--src/components/settings/user/EditUserForm.js25
-rw-r--r--src/components/subscription/SubscriptionForm.js67
-rw-r--r--src/components/subscription/SubscriptionPopup.js3
-rw-r--r--src/components/ui/AppLoader/index.js4
-rw-r--r--src/components/ui/FullscreenLoader/index.js4
-rw-r--r--src/components/ui/Infobox.js17
-rw-r--r--src/components/ui/Modal/index.js26
-rw-r--r--src/components/ui/Modal/styles.js1
-rw-r--r--src/components/ui/PremiumFeatureContainer/index.js21
-rw-r--r--src/components/ui/PremiumFeatureContainer/styles.js5
-rw-r--r--src/components/ui/ServiceIcon.js67
-rw-r--r--src/components/ui/WebviewLoader/index.js18
-rw-r--r--src/config.js35
-rw-r--r--src/containers/auth/AuthLayoutContainer.js38
-rw-r--r--src/containers/auth/ImportScreen.js5
-rw-r--r--src/containers/auth/InviteScreen.js5
-rw-r--r--src/containers/auth/LoginScreen.js5
-rw-r--r--src/containers/auth/PasswordScreen.js5
-rw-r--r--src/containers/auth/PricingScreen.js5
-rw-r--r--src/containers/auth/SignupScreen.js5
-rw-r--r--src/containers/auth/WelcomeScreen.js5
-rw-r--r--src/containers/layout/AppLayoutContainer.js21
-rw-r--r--src/containers/settings/AccountScreen.js56
-rw-r--r--src/containers/settings/EditServiceScreen.js45
-rw-r--r--src/containers/settings/EditSettingsScreen.js21
-rw-r--r--src/containers/settings/EditUserScreen.js49
-rw-r--r--src/containers/settings/InviteScreen.js6
-rw-r--r--src/containers/settings/RecipesScreen.js6
-rw-r--r--src/containers/settings/ServicesScreen.js5
-rw-r--r--src/containers/settings/SettingsWindow.js2
-rw-r--r--src/containers/settings/TeamScreen.js57
-rw-r--r--src/containers/subscription/SubscriptionFormScreen.js39
-rw-r--r--src/electron/ipc-api/autoUpdate.js9
-rw-r--r--src/environment.js29
-rw-r--r--src/features/announcements/actions.js10
-rw-r--r--src/features/announcements/api.js33
-rw-r--r--src/features/announcements/components/AnnouncementScreen.js286
-rw-r--r--src/features/announcements/index.js32
-rw-r--r--src/features/announcements/store.js144
-rw-r--r--src/features/basicAuth/Component.js1
-rw-r--r--src/features/basicAuth/index.js12
-rw-r--r--src/features/delayApp/Component.js2
-rw-r--r--src/features/delayApp/index.js11
-rwxr-xr-xsrc/features/settingsWS/actions.js10
-rwxr-xr-xsrc/features/settingsWS/index.js29
-rwxr-xr-xsrc/features/settingsWS/state.js13
-rwxr-xr-xsrc/features/settingsWS/store.js130
-rw-r--r--src/features/shareFranz/Component.js166
-rw-r--r--src/features/shareFranz/index.js52
-rw-r--r--src/features/spellchecker/index.js6
-rw-r--r--src/features/utils/ActionBinding.js29
-rw-r--r--src/features/utils/FeatureStore.js40
-rw-r--r--src/features/utils/FeatureStore.test.js92
-rw-r--r--src/features/workspaces/actions.js26
-rw-r--r--src/features/workspaces/api.js66
-rw-r--r--src/features/workspaces/components/CreateWorkspaceForm.js100
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.js212
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.js246
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.js137
-rw-r--r--src/features/workspaces/components/WorkspaceItem.js45
-rw-r--r--src/features/workspaces/components/WorkspaceServiceListItem.js75
-rw-r--r--src/features/workspaces/components/WorkspaceSwitchingIndicator.js91
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js209
-rw-r--r--src/features/workspaces/containers/EditWorkspaceScreen.js60
-rw-r--r--src/features/workspaces/containers/WorkspacesScreen.js42
-rw-r--r--src/features/workspaces/index.js37
-rw-r--r--src/features/workspaces/models/Workspace.js25
-rw-r--r--src/features/workspaces/store.js323
-rw-r--r--src/helpers/asar-helpers.js3
-rw-r--r--src/helpers/i18n-helpers.js27
-rw-r--r--src/helpers/url-helpers.js15
-rw-r--r--src/i18n/globalMessages.js20
-rw-r--r--src/i18n/languages.js3
-rw-r--r--src/i18n/locales/ca.json78
-rw-r--r--src/i18n/locales/cs.json88
-rw-r--r--src/i18n/locales/de.json152
-rw-r--r--src/i18n/locales/defaultMessages.json4603
-rw-r--r--src/i18n/locales/el.json74
-rw-r--r--src/i18n/locales/en-US.json498
-rw-r--r--src/i18n/locales/es.json84
-rw-r--r--src/i18n/locales/fr.json94
-rw-r--r--src/i18n/locales/ga.json70
-rw-r--r--src/i18n/locales/hr.json70
-rw-r--r--src/i18n/locales/hu.json150
-rw-r--r--src/i18n/locales/id.json100
-rw-r--r--src/i18n/locales/it.json106
-rw-r--r--src/i18n/locales/ja.json88
-rw-r--r--src/i18n/locales/ka.json70
-rw-r--r--src/i18n/locales/nl-BE.json252
-rw-r--r--src/i18n/locales/nl.json88
-rw-r--r--src/i18n/locales/pl.json96
-rw-r--r--src/i18n/locales/pt-BR.json88
-rw-r--r--src/i18n/locales/pt.json138
-rw-r--r--src/i18n/locales/ru.json116
-rw-r--r--src/i18n/locales/sk.json70
-rw-r--r--src/i18n/locales/sr.json70
-rw-r--r--src/i18n/locales/tr.json132
-rw-r--r--src/i18n/locales/uk.json122
-rw-r--r--src/i18n/locales/whitelist_en-US.json2
-rw-r--r--src/i18n/locales/zh-TW.json152
-rw-r--r--src/i18n/manage-translations.js9
-rw-r--r--src/i18n/messages/src/components/auth/Import.json54
-rw-r--r--src/i18n/messages/src/components/auth/Invite.json93
-rw-r--r--src/i18n/messages/src/components/auth/Login.json119
-rw-r--r--src/i18n/messages/src/components/auth/Password.json93
-rw-r--r--src/i18n/messages/src/components/auth/Pricing.json54
-rw-r--r--src/i18n/messages/src/components/auth/Signup.json158
-rw-r--r--src/i18n/messages/src/components/auth/Welcome.json28
-rw-r--r--src/i18n/messages/src/components/layout/AppLayout.json80
-rw-r--r--src/i18n/messages/src/components/layout/Sidebar.json80
-rw-r--r--src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json67
-rw-r--r--src/i18n/messages/src/components/services/content/ServiceDisabled.json28
-rw-r--r--src/i18n/messages/src/components/services/content/Services.json28
-rw-r--r--src/i18n/messages/src/components/services/content/WebviewCrashHandler.json54
-rw-r--r--src/i18n/messages/src/components/services/tabs/TabItem.json119
-rw-r--r--src/i18n/messages/src/components/settings/account/AccountDashboard.json197
-rw-r--r--src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json106
-rw-r--r--src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json106
-rw-r--r--src/i18n/messages/src/components/settings/services/EditServiceForm.json288
-rw-r--r--src/i18n/messages/src/components/settings/services/ServiceError.json54
-rw-r--r--src/i18n/messages/src/components/settings/services/ServiceItem.json41
-rw-r--r--src/i18n/messages/src/components/settings/services/ServicesDashboard.json119
-rw-r--r--src/i18n/messages/src/components/settings/settings/EditSettingsForm.json236
-rw-r--r--src/i18n/messages/src/components/settings/team/TeamDashboard.json80
-rw-r--r--src/i18n/messages/src/components/settings/user/EditUserForm.json80
-rw-r--r--src/i18n/messages/src/components/subscription/SubscriptionForm.json184
-rw-r--r--src/i18n/messages/src/components/subscription/SubscriptionPopup.json28
-rw-r--r--src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json15
-rw-r--r--src/i18n/messages/src/components/ui/WebviewLoader/index.json15
-rw-r--r--src/i18n/messages/src/components/util/ErrorBoundary/index.json28
-rw-r--r--src/i18n/messages/src/containers/settings/EditServiceScreen.json197
-rw-r--r--src/i18n/messages/src/containers/settings/EditSettingsScreen.json158
-rw-r--r--src/i18n/messages/src/containers/settings/EditUserScreen.json119
-rw-r--r--src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json15
-rw-r--r--src/i18n/messages/src/features/delayApp/Component.json41
-rw-r--r--src/i18n/messages/src/features/shareFranz/Component.json93
-rw-r--r--src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json28
-rw-r--r--src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json93
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json106
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json28
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json15
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json106
-rw-r--r--src/i18n/messages/src/helpers/validation-helpers.json67
-rw-r--r--src/i18n/messages/src/i18n/globalMessages.json80
-rw-r--r--src/i18n/messages/src/lib/Menu.json691
-rw-r--r--src/index.js161
-rw-r--r--src/lib/Menu.js218
-rw-r--r--src/lib/Tray.js8
-rw-r--r--src/lib/analytics.js26
-rw-r--r--src/models/Service.js2
-rw-r--r--src/stores/AppStore.js84
-rw-r--r--src/stores/FeaturesStore.js35
-rw-r--r--src/stores/PaymentStore.js17
-rw-r--r--src/stores/RecipePreviewsStore.js3
-rw-r--r--src/stores/RequestStore.js3
-rw-r--r--src/stores/ServicesStore.js30
-rw-r--r--src/stores/UIStore.js14
-rw-r--r--src/stores/UserStore.js32
-rw-r--r--src/stores/index.js4
-rw-r--r--src/stores/lib/Reaction.js19
-rw-r--r--src/stores/lib/Request.js6
-rw-r--r--src/styles/auth.scss2
-rw-r--r--src/styles/badge.scss3
-rw-r--r--src/styles/info-bar.scss4
-rw-r--r--src/styles/layout.scss22
-rw-r--r--src/styles/settings.scss40
-rw-r--r--src/styles/toggle.scss2
-rw-r--r--src/theme/dark/index.js19
-rw-r--r--src/theme/default/index.js35
-rw-r--r--src/webview/contextMenu.js33
-rw-r--r--src/webview/recipe.js56
-rw-r--r--src/webview/spellchecker.js11
192 files changed, 15859 insertions, 1870 deletions
diff --git a/src/actions/index.js b/src/actions/index.js
index 59acabb0b..fc525afeb 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -11,6 +11,8 @@ import payment from './payment';
11import news from './news'; 11import news from './news';
12import settings from './settings'; 12import settings from './settings';
13import requests from './requests'; 13import requests from './requests';
14import announcements from '../features/announcements/actions';
15import workspaces from '../features/workspaces/actions';
14 16
15const actions = Object.assign({}, { 17const actions = Object.assign({}, {
16 service, 18 service,
@@ -25,4 +27,8 @@ const actions = Object.assign({}, {
25 requests, 27 requests,
26}); 28});
27 29
28export default defineActions(actions, PropTypes.checkPropTypes); 30export default Object.assign(
31 defineActions(actions, PropTypes.checkPropTypes),
32 { announcements },
33 { workspaces },
34);
diff --git a/src/actions/lib/actions.js b/src/actions/lib/actions.js
index 499018d70..b38db9946 100644
--- a/src/actions/lib/actions.js
+++ b/src/actions/lib/actions.js
@@ -1,18 +1,27 @@
1export const createActionsFromDefinitions = (actionDefinitions, validate) => {
2 const actions = {};
3 Object.keys(actionDefinitions).forEach((actionName) => {
4 const action = (params = {}) => {
5 const schema = actionDefinitions[actionName];
6 validate(schema, params, actionName);
7 action.notify(params);
8 };
9 actions[actionName] = action;
10 action.listeners = [];
11 action.listen = listener => action.listeners.push(listener);
12 action.off = (listener) => {
13 const { listeners } = action;
14 listeners.splice(listeners.indexOf(listener), 1);
15 };
16 action.notify = params => action.listeners.forEach(listener => listener(params));
17 });
18 return actions;
19};
20
1export default (definitions, validate) => { 21export default (definitions, validate) => {
2 const newActions = {}; 22 const newActions = {};
3 Object.keys(definitions).forEach((scopeName) => { 23 Object.keys(definitions).forEach((scopeName) => {
4 newActions[scopeName] = {}; 24 newActions[scopeName] = createActionsFromDefinitions(definitions[scopeName], validate);
5 Object.keys(definitions[scopeName]).forEach((actionName) => {
6 const action = (params) => {
7 const schema = definitions[scopeName][actionName];
8 validate(schema, params, actionName);
9 action.notify(params);
10 };
11 newActions[scopeName][actionName] = action;
12 action.listeners = [];
13 action.listen = listener => action.listeners.push(listener);
14 action.notify = params => action.listeners.forEach(listener => listener(params));
15 });
16 }); 25 });
17 return newActions; 26 return newActions;
18}; 27};
diff --git a/src/actions/service.js b/src/actions/service.js
index 5d483b12a..ce62560a9 100644
--- a/src/actions/service.js
+++ b/src/actions/service.js
@@ -1,9 +1,11 @@
1import PropTypes from 'prop-types'; 1import PropTypes from 'prop-types';
2import ServiceModel from '../models/Service';
2 3
3export default { 4export default {
4 setActive: { 5 setActive: {
5 serviceId: PropTypes.string.isRequired, 6 serviceId: PropTypes.string.isRequired,
6 }, 7 },
8 blurActive: {},
7 setActiveNext: {}, 9 setActiveNext: {},
8 setActivePrev: {}, 10 setActivePrev: {},
9 showAddServiceInterface: { 11 showAddServiceInterface: {
@@ -36,6 +38,9 @@ export default {
36 serviceId: PropTypes.string.isRequired, 38 serviceId: PropTypes.string.isRequired,
37 webview: PropTypes.object.isRequired, 39 webview: PropTypes.object.isRequired,
38 }, 40 },
41 detachService: {
42 service: PropTypes.instanceOf(ServiceModel).isRequired,
43 },
39 focusService: { 44 focusService: {
40 serviceId: PropTypes.string.isRequired, 45 serviceId: PropTypes.string.isRequired,
41 }, 46 },
diff --git a/src/api/PaymentApi.js b/src/api/PaymentApi.js
index 3f6bb442e..7325151e9 100644
--- a/src/api/PaymentApi.js
+++ b/src/api/PaymentApi.js
@@ -11,12 +11,4 @@ export default class PaymentApi {
11 getHostedPage(planId) { 11 getHostedPage(planId) {
12 return this.server.getHostedPage(planId); 12 return this.server.getHostedPage(planId);
13 } 13 }
14
15 getDashboardUrl() {
16 return this.server.getPaymentDashboardUrl();
17 }
18
19 getOrders() {
20 return this.server.getSubscriptionOrders();
21 }
22} 14}
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index 2871769a9..a9ce202ff 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -3,7 +3,6 @@ import path from 'path';
3import tar from 'tar'; 3import tar from 'tar';
4import fs from 'fs-extra'; 4import fs from 'fs-extra';
5import { remote } from 'electron'; 5import { remote } from 'electron';
6import localStorage from 'mobx-localstorage';
7 6
8import ServiceModel from '../../models/Service'; 7import ServiceModel from '../../models/Service';
9import RecipePreviewModel from '../../models/RecipePreview'; 8import RecipePreviewModel from '../../models/RecipePreview';
@@ -16,6 +15,7 @@ import OrderModel from '../../models/Order';
16import { sleep } from '../../helpers/async-helpers'; 15import { sleep } from '../../helpers/async-helpers';
17 16
18import { API } from '../../environment'; 17import { API } from '../../environment';
18import { prepareAuthRequest, sendAuthRequest } from '../utils/auth';
19 19
20import { 20import {
21 getRecipeDirectory, 21 getRecipeDirectory,
@@ -39,6 +39,7 @@ const { default: fetch } = remote.require('electron-fetch');
39 39
40const SERVER_URL = API; 40const SERVER_URL = API;
41const API_VERSION = 'v1'; 41const API_VERSION = 'v1';
42const API_URL = `${SERVER_URL}/${API_VERSION}`;
42 43
43export default class ServerApi { 44export default class ServerApi {
44 recipePreviews = []; 45 recipePreviews = [];
@@ -47,12 +48,12 @@ export default class ServerApi {
47 48
48 // User 49 // User
49 async login(email, passwordHash) { 50 async login(email, passwordHash) {
50 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/auth/login`, this._prepareAuthRequest({ 51 const request = await sendAuthRequest(`${API_URL}/auth/login`, {
51 method: 'POST', 52 method: 'POST',
52 headers: { 53 headers: {
53 Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, 54 Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`,
54 }, 55 },
55 }, false)); 56 }, false);
56 if (!request.ok) { 57 if (!request.ok) {
57 throw request; 58 throw request;
58 } 59 }
@@ -63,10 +64,10 @@ export default class ServerApi {
63 } 64 }
64 65
65 async signup(data) { 66 async signup(data) {
66 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/auth/signup`, this._prepareAuthRequest({ 67 const request = await sendAuthRequest(`${API_URL}/auth/signup`, {
67 method: 'POST', 68 method: 'POST',
68 body: JSON.stringify(data), 69 body: JSON.stringify(data),
69 }, false)); 70 }, false);
70 if (!request.ok) { 71 if (!request.ok) {
71 throw request; 72 throw request;
72 } 73 }
@@ -77,10 +78,10 @@ export default class ServerApi {
77 } 78 }
78 79
79 async inviteUser(data) { 80 async inviteUser(data) {
80 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/invite`, this._prepareAuthRequest({ 81 const request = await sendAuthRequest(`${API_URL}/invite`, {
81 method: 'POST', 82 method: 'POST',
82 body: JSON.stringify(data), 83 body: JSON.stringify(data),
83 })); 84 });
84 if (!request.ok) { 85 if (!request.ok) {
85 throw request; 86 throw request;
86 } 87 }
@@ -90,12 +91,12 @@ export default class ServerApi {
90 } 91 }
91 92
92 async retrievePassword(email) { 93 async retrievePassword(email) {
93 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/auth/password`, this._prepareAuthRequest({ 94 const request = await sendAuthRequest(`${API_URL}/auth/password`, {
94 method: 'POST', 95 method: 'POST',
95 body: JSON.stringify({ 96 body: JSON.stringify({
96 email, 97 email,
97 }), 98 }),
98 }, false)); 99 }, false);
99 if (!request.ok) { 100 if (!request.ok) {
100 throw request; 101 throw request;
101 } 102 }
@@ -106,9 +107,7 @@ export default class ServerApi {
106 } 107 }
107 108
108 async userInfo() { 109 async userInfo() {
109 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me`, this._prepareAuthRequest({ 110 const request = await sendAuthRequest(`${API_URL}/me`);
110 method: 'GET',
111 }));
112 if (!request.ok) { 111 if (!request.ok) {
113 throw request; 112 throw request;
114 } 113 }
@@ -121,10 +120,10 @@ export default class ServerApi {
121 } 120 }
122 121
123 async updateUserInfo(data) { 122 async updateUserInfo(data) {
124 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me`, this._prepareAuthRequest({ 123 const request = await sendAuthRequest(`${API_URL}/me`, {
125 method: 'PUT', 124 method: 'PUT',
126 body: JSON.stringify(data), 125 body: JSON.stringify(data),
127 })); 126 });
128 if (!request.ok) { 127 if (!request.ok) {
129 throw request; 128 throw request;
130 } 129 }
@@ -136,9 +135,9 @@ export default class ServerApi {
136 } 135 }
137 136
138 async deleteAccount() { 137 async deleteAccount() {
139 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me`, this._prepareAuthRequest({ 138 const request = await sendAuthRequest(`${API_URL}/me`, {
140 method: 'DELETE', 139 method: 'DELETE',
141 })); 140 });
142 if (!request.ok) { 141 if (!request.ok) {
143 throw request; 142 throw request;
144 } 143 }
@@ -150,9 +149,7 @@ export default class ServerApi {
150 149
151 // Services 150 // Services
152 async getServices() { 151 async getServices() {
153 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me/services`, this._prepareAuthRequest({ 152 const request = await sendAuthRequest(`${API_URL}/me/services`);
154 method: 'GET',
155 }));
156 if (!request.ok) { 153 if (!request.ok) {
157 throw request; 154 throw request;
158 } 155 }
@@ -165,12 +162,12 @@ export default class ServerApi {
165 } 162 }
166 163
167 async createService(recipeId, data) { 164 async createService(recipeId, data) {
168 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/service`, this._prepareAuthRequest({ 165 const request = await sendAuthRequest(`${API_URL}/service`, {
169 method: 'POST', 166 method: 'POST',
170 body: JSON.stringify(Object.assign({ 167 body: JSON.stringify(Object.assign({
171 recipeId, 168 recipeId,
172 }, data)), 169 }, data)),
173 })); 170 });
174 if (!request.ok) { 171 if (!request.ok) {
175 throw request; 172 throw request;
176 } 173 }
@@ -195,10 +192,10 @@ export default class ServerApi {
195 await this.uploadServiceIcon(serviceId, data.iconFile); 192 await this.uploadServiceIcon(serviceId, data.iconFile);
196 } 193 }
197 194
198 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/service/${serviceId}`, this._prepareAuthRequest({ 195 const request = await sendAuthRequest(`${API_URL}/service/${serviceId}`, {
199 method: 'PUT', 196 method: 'PUT',
200 body: JSON.stringify(data), 197 body: JSON.stringify(data),
201 })); 198 });
202 199
203 if (!request.ok) { 200 if (!request.ok) {
204 throw request; 201 throw request;
@@ -216,14 +213,14 @@ export default class ServerApi {
216 const formData = new FormData(); 213 const formData = new FormData();
217 formData.append('icon', icon); 214 formData.append('icon', icon);
218 215
219 const requestData = this._prepareAuthRequest({ 216 const requestData = prepareAuthRequest({
220 method: 'PUT', 217 method: 'PUT',
221 body: formData, 218 body: formData,
222 }); 219 });
223 220
224 delete requestData.headers['Content-Type']; 221 delete requestData.headers['Content-Type'];
225 222
226 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/service/${serviceId}`, requestData); 223 const request = await window.fetch(`${API_URL}/service/${serviceId}`, requestData);
227 224
228 if (!request.ok) { 225 if (!request.ok) {
229 throw request; 226 throw request;
@@ -235,10 +232,10 @@ export default class ServerApi {
235 } 232 }
236 233
237 async reorderService(data) { 234 async reorderService(data) {
238 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/service/reorder`, this._prepareAuthRequest({ 235 const request = await sendAuthRequest(`${API_URL}/service/reorder`, {
239 method: 'PUT', 236 method: 'PUT',
240 body: JSON.stringify(data), 237 body: JSON.stringify(data),
241 })); 238 });
242 if (!request.ok) { 239 if (!request.ok) {
243 throw request; 240 throw request;
244 } 241 }
@@ -248,9 +245,9 @@ export default class ServerApi {
248 } 245 }
249 246
250 async deleteService(id) { 247 async deleteService(id) {
251 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/service/${id}`, this._prepareAuthRequest({ 248 const request = await sendAuthRequest(`${API_URL}/service/${id}`, {
252 method: 'DELETE', 249 method: 'DELETE',
253 })); 250 });
254 if (!request.ok) { 251 if (!request.ok) {
255 throw request; 252 throw request;
256 } 253 }
@@ -264,30 +261,26 @@ export default class ServerApi {
264 261
265 // Features 262 // Features
266 async getDefaultFeatures() { 263 async getDefaultFeatures() {
267 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/features/default`, this._prepareAuthRequest({ 264 const request = await sendAuthRequest(`${API_URL}/features/default`);
268 method: 'GET',
269 }));
270 if (!request.ok) { 265 if (!request.ok) {
271 throw request; 266 throw request;
272 } 267 }
273 const data = await request.json(); 268 const data = await request.json();
274 269
275 const features = data; 270 const features = data;
276 console.debug('ServerApi::getDefaultFeatures resolves', features); 271 debug('ServerApi::getDefaultFeatures resolves', features);
277 return features; 272 return features;
278 } 273 }
279 274
280 async getFeatures() { 275 async getFeatures() {
281 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/features`, this._prepareAuthRequest({ 276 const request = await sendAuthRequest(`${API_URL}/features`);
282 method: 'GET',
283 }));
284 if (!request.ok) { 277 if (!request.ok) {
285 throw request; 278 throw request;
286 } 279 }
287 const data = await request.json(); 280 const data = await request.json();
288 281
289 const features = data; 282 const features = data;
290 console.debug('ServerApi::getFeatures resolves', features); 283 debug('ServerApi::getFeatures resolves', features);
291 return features; 284 return features;
292 } 285 }
293 286
@@ -314,10 +307,10 @@ export default class ServerApi {
314 } 307 }
315 308
316 async getRecipeUpdates(recipeVersions) { 309 async getRecipeUpdates(recipeVersions) {
317 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/update`, this._prepareAuthRequest({ 310 const request = await sendAuthRequest(`${API_URL}/recipes/update`, {
318 method: 'POST', 311 method: 'POST',
319 body: JSON.stringify(recipeVersions), 312 body: JSON.stringify(recipeVersions),
320 })); 313 });
321 if (!request.ok) { 314 if (!request.ok) {
322 throw request; 315 throw request;
323 } 316 }
@@ -328,29 +321,19 @@ export default class ServerApi {
328 321
329 // Recipes Previews 322 // Recipes Previews
330 async getRecipePreviews() { 323 async getRecipePreviews() {
331 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes`, this._prepareAuthRequest({ 324 const request = await sendAuthRequest(`${API_URL}/recipes`);
332 method: 'GET', 325 if (!request.ok) throw request;
333 }));
334 if (!request.ok) {
335 throw request;
336 }
337 const data = await request.json(); 326 const data = await request.json();
338
339 const recipePreviews = this._mapRecipePreviewModel(data); 327 const recipePreviews = this._mapRecipePreviewModel(data);
340 debug('ServerApi::getRecipes resolves', recipePreviews); 328 debug('ServerApi::getRecipes resolves', recipePreviews);
341
342 return recipePreviews; 329 return recipePreviews;
343 } 330 }
344 331
345 async getFeaturedRecipePreviews() { 332 async getFeaturedRecipePreviews() {
346 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/popular`, this._prepareAuthRequest({ 333 const request = await sendAuthRequest(`${API_URL}/recipes/popular`);
347 method: 'GET', 334 if (!request.ok) throw request;
348 }));
349 if (!request.ok) {
350 throw request;
351 }
352 const data = await request.json();
353 335
336 const data = await request.json();
354 // data = this._addLocalRecipesToPreviews(data); 337 // data = this._addLocalRecipesToPreviews(data);
355 338
356 const recipePreviews = this._mapRecipePreviewModel(data); 339 const recipePreviews = this._mapRecipePreviewModel(data);
@@ -359,14 +342,11 @@ export default class ServerApi {
359 } 342 }
360 343
361 async searchRecipePreviews(needle) { 344 async searchRecipePreviews(needle) {
362 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/search?needle=${needle}`, this._prepareAuthRequest({ 345 const url = `${API_URL}/recipes/search?needle=${needle}`;
363 method: 'GET', 346 const request = await sendAuthRequest(url);
364 })); 347 if (!request.ok) throw request;
365 if (!request.ok) {
366 throw request;
367 }
368 const data = await request.json();
369 348
349 const data = await request.json();
370 const recipePreviews = this._mapRecipePreviewModel(data); 350 const recipePreviews = this._mapRecipePreviewModel(data);
371 debug('ServerApi::searchRecipePreviews resolves', recipePreviews); 351 debug('ServerApi::searchRecipePreviews resolves', recipePreviews);
372 return recipePreviews; 352 return recipePreviews;
@@ -375,10 +355,9 @@ export default class ServerApi {
375 async getRecipePackage(recipeId) { 355 async getRecipePackage(recipeId) {
376 try { 356 try {
377 const recipesDirectory = path.join(app.getPath('userData'), 'recipes'); 357 const recipesDirectory = path.join(app.getPath('userData'), 'recipes');
378
379 const recipeTempDirectory = path.join(recipesDirectory, 'temp', recipeId); 358 const recipeTempDirectory = path.join(recipesDirectory, 'temp', recipeId);
380 const archivePath = path.join(recipeTempDirectory, 'recipe.tar.gz'); 359 const archivePath = path.join(recipeTempDirectory, 'recipe.tar.gz');
381 const packageUrl = `${SERVER_URL}/${API_VERSION}/recipes/download/${recipeId}`; 360 const packageUrl = `${API_URL}/recipes/download/${recipeId}`;
382 361
383 fs.ensureDirSync(recipeTempDirectory); 362 fs.ensureDirSync(recipeTempDirectory);
384 const res = await fetch(packageUrl); 363 const res = await fetch(packageUrl);
@@ -415,26 +394,21 @@ export default class ServerApi {
415 394
416 // Payment 395 // Payment
417 async getPlans() { 396 async getPlans() {
418 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/payment/plans`, this._prepareAuthRequest({ 397 const request = await sendAuthRequest(`${API_URL}/payment/plans`);
419 method: 'GET', 398 if (!request.ok) throw request;
420 }));
421 if (!request.ok) {
422 throw request;
423 }
424 const data = await request.json(); 399 const data = await request.json();
425
426 const plan = new PlanModel(data); 400 const plan = new PlanModel(data);
427 debug('ServerApi::getPlans resolves', plan); 401 debug('ServerApi::getPlans resolves', plan);
428 return plan; 402 return plan;
429 } 403 }
430 404
431 async getHostedPage(planId) { 405 async getHostedPage(planId) {
432 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/payment/init`, this._prepareAuthRequest({ 406 const request = await sendAuthRequest(`${API_URL}/payment/init`, {
433 method: 'POST', 407 method: 'POST',
434 body: JSON.stringify({ 408 body: JSON.stringify({
435 planId, 409 planId,
436 }), 410 }),
437 })); 411 });
438 if (!request.ok) { 412 if (!request.ok) {
439 throw request; 413 throw request;
440 } 414 }
@@ -444,43 +418,11 @@ export default class ServerApi {
444 return data; 418 return data;
445 } 419 }
446 420
447 async getPaymentDashboardUrl() {
448 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me/billing`, this._prepareAuthRequest({
449 method: 'GET',
450 }));
451 if (!request.ok) {
452 throw request;
453 }
454 const data = await request.json();
455
456 debug('ServerApi::getPaymentDashboardUrl resolves', data);
457 return data;
458 }
459
460 async getSubscriptionOrders() {
461 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/me/subscription`, this._prepareAuthRequest({
462 method: 'GET',
463 }));
464 if (!request.ok) {
465 throw request;
466 }
467 const data = await request.json();
468 const orders = this._mapOrderModels(data);
469 debug('ServerApi::getSubscriptionOrders resolves', orders);
470 return orders;
471 }
472
473 // News 421 // News
474 async getLatestNews() { 422 async getLatestNews() {
475 // eslint-disable-next-line 423 const url = `${API_URL}/news?platform=${os.platform()}&arch=${os.arch()}&version=${app.getVersion()}`;
476 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/news?platform=${os.platform()}&arch=${os.arch()}&version=${app.getVersion()}`, 424 const request = await sendAuthRequest(url);
477 this._prepareAuthRequest({ 425 if (!request.ok) throw request;
478 method: 'GET',
479 }));
480
481 if (!request.ok) {
482 throw request;
483 }
484 const data = await request.json(); 426 const data = await request.json();
485 const news = this._mapNewsModels(data); 427 const news = this._mapNewsModels(data);
486 debug('ServerApi::getLatestNews resolves', news); 428 debug('ServerApi::getLatestNews resolves', news);
@@ -488,23 +430,16 @@ export default class ServerApi {
488 } 430 }
489 431
490 async hideNews(id) { 432 async hideNews(id) {
491 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/news/${id}/read`, 433 const request = await sendAuthRequest(`${API_URL}/news/${id}/read`);
492 this._prepareAuthRequest({ 434 if (!request.ok) throw request;
493 method: 'GET',
494 }));
495
496 if (!request.ok) {
497 throw request;
498 }
499
500 debug('ServerApi::hideNews resolves', id); 435 debug('ServerApi::hideNews resolves', id);
501 } 436 }
502 437
503 // Health Check 438 // Health Check
504 async healthCheck() { 439 async healthCheck() {
505 const request = await window.fetch(`${SERVER_URL}/health`, this._prepareAuthRequest({ 440 const request = await sendAuthRequest(`${SERVER_URL}/health`, {
506 method: 'GET', 441 method: 'GET',
507 }, false)); 442 }, false);
508 if (!request.ok) { 443 if (!request.ok) {
509 throw request; 444 throw request;
510 } 445 }
@@ -520,10 +455,7 @@ export default class ServerApi {
520 if (Object.prototype.hasOwnProperty.call(config, 'services')) { 455 if (Object.prototype.hasOwnProperty.call(config, 'services')) {
521 const services = await Promise.all(config.services.map(async (s) => { 456 const services = await Promise.all(config.services.map(async (s) => {
522 const service = s; 457 const service = s;
523 const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/${s.service}`, 458 const request = await sendAuthRequest(`${API_URL}/recipes/${s.service}`);
524 this._prepareAuthRequest({
525 method: 'GET',
526 }));
527 459
528 if (request.status === 200) { 460 if (request.status === 200) {
529 const data = await request.json(); 461 const data = await request.json();
@@ -546,9 +478,7 @@ export default class ServerApi {
546 // Helper 478 // Helper
547 async _mapServiceModels(services) { 479 async _mapServiceModels(services) {
548 const recipes = services.map(s => s.recipeId); 480 const recipes = services.map(s => s.recipeId);
549
550 await this._bulkRecipeCheck(recipes); 481 await this._bulkRecipeCheck(recipes);
551
552 /* eslint-disable no-return-await */ 482 /* eslint-disable no-return-await */
553 return Promise.all(services.map(async service => await this._prepareServiceModel(service))); 483 return Promise.all(services.map(async service => await this._prepareServiceModel(service)));
554 /* eslint-enable no-return-await */ 484 /* eslint-enable no-return-await */
@@ -632,26 +562,6 @@ export default class ServerApi {
632 }).filter(orderItem => orderItem !== null); 562 }).filter(orderItem => orderItem !== null);
633 } 563 }
634 564
635 _prepareAuthRequest(options, auth = true) {
636 const request = Object.assign(options, {
637 mode: 'cors',
638 headers: Object.assign({
639 'Content-Type': 'application/json',
640 'X-Franz-Source': 'desktop',
641 'X-Franz-Version': app.getVersion(),
642 'X-Franz-platform': process.platform,
643 'X-Franz-Timezone-Offset': new Date().getTimezoneOffset(),
644 'X-Franz-System-Locale': app.getLocale(),
645 }, options.headers),
646 });
647
648 if (auth) {
649 request.headers.Authorization = `Bearer ${localStorage.getItem('authToken')}`;
650 }
651
652 return request;
653 }
654
655 _getDevRecipes() { 565 _getDevRecipes() {
656 const recipesDirectory = getDevRecipeDirectory(); 566 const recipesDirectory = getDevRecipeDirectory();
657 try { 567 try {
diff --git a/src/api/utils/auth.js b/src/api/utils/auth.js
new file mode 100644
index 000000000..6dbdeaa7f
--- /dev/null
+++ b/src/api/utils/auth.js
@@ -0,0 +1,28 @@
1import { remote } from 'electron';
2import localStorage from 'mobx-localstorage';
3
4const { app } = remote;
5
6export const prepareAuthRequest = (options = { method: 'GET' }, auth = true) => {
7 const request = Object.assign(options, {
8 mode: 'cors',
9 headers: Object.assign({
10 'Content-Type': 'application/json',
11 'X-Franz-Source': 'desktop',
12 'X-Franz-Version': app.getVersion(),
13 'X-Franz-platform': process.platform,
14 'X-Franz-Timezone-Offset': new Date().getTimezoneOffset(),
15 'X-Franz-System-Locale': app.getLocale(),
16 }, options.headers),
17 });
18
19 if (auth) {
20 request.headers.Authorization = `Bearer ${localStorage.getItem('authToken')}`;
21 }
22
23 return request;
24};
25
26export const sendAuthRequest = (url, options, auth) => (
27 window.fetch(url, prepareAuthRequest(options, auth))
28);
diff --git a/src/app.js b/src/app.js
index 6660feb46..f6092bf60 100644
--- a/src/app.js
+++ b/src/app.js
@@ -27,6 +27,7 @@ import RecipesScreen from './containers/settings/RecipesScreen';
27import ServicesScreen from './containers/settings/ServicesScreen'; 27import ServicesScreen from './containers/settings/ServicesScreen';
28import EditServiceScreen from './containers/settings/EditServiceScreen'; 28import EditServiceScreen from './containers/settings/EditServiceScreen';
29import AccountScreen from './containers/settings/AccountScreen'; 29import AccountScreen from './containers/settings/AccountScreen';
30import TeamScreen from './containers/settings/TeamScreen';
30import EditUserScreen from './containers/settings/EditUserScreen'; 31import EditUserScreen from './containers/settings/EditUserScreen';
31import EditSettingsScreen from './containers/settings/EditSettingsScreen'; 32import EditSettingsScreen from './containers/settings/EditSettingsScreen';
32import InviteSettingsScreen from './containers/settings/InviteScreen'; 33import InviteSettingsScreen from './containers/settings/InviteScreen';
@@ -39,6 +40,9 @@ import PricingScreen from './containers/auth/PricingScreen';
39import InviteScreen from './containers/auth/InviteScreen'; 40import InviteScreen from './containers/auth/InviteScreen';
40import AuthLayoutContainer from './containers/auth/AuthLayoutContainer'; 41import AuthLayoutContainer from './containers/auth/AuthLayoutContainer';
41import SubscriptionPopupScreen from './containers/subscription/SubscriptionPopupScreen'; 42import SubscriptionPopupScreen from './containers/subscription/SubscriptionPopupScreen';
43import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen';
44import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen';
45import { WORKSPACES_ROUTES } from './features/workspaces';
42 46
43// Add Polyfills 47// Add Polyfills
44smoothScroll.polyfill(); 48smoothScroll.polyfill();
@@ -75,8 +79,11 @@ window.addEventListener('load', () => {
75 <Route path="/settings/recipes/:filter" component={RecipesScreen} /> 79 <Route path="/settings/recipes/:filter" component={RecipesScreen} />
76 <Route path="/settings/services" component={ServicesScreen} /> 80 <Route path="/settings/services" component={ServicesScreen} />
77 <Route path="/settings/services/:action/:id" component={EditServiceScreen} /> 81 <Route path="/settings/services/:action/:id" component={EditServiceScreen} />
82 <Route path={WORKSPACES_ROUTES.ROOT} component={WorkspacesScreen} />
83 <Route path={WORKSPACES_ROUTES.EDIT} component={EditWorkspaceScreen} />
78 <Route path="/settings/user" component={AccountScreen} /> 84 <Route path="/settings/user" component={AccountScreen} />
79 <Route path="/settings/user/edit" component={EditUserScreen} /> 85 <Route path="/settings/user/edit" component={EditUserScreen} />
86 <Route path="/settings/team" component={TeamScreen} />
80 <Route path="/settings/app" component={EditSettingsScreen} /> 87 <Route path="/settings/app" component={EditSettingsScreen} />
81 <Route path="/settings/invite" component={InviteSettingsScreen} /> 88 <Route path="/settings/invite" component={InviteSettingsScreen} />
82 </Route> 89 </Route>
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index a1641bc4a..d0476ef04 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -3,14 +3,20 @@ import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import { TitleBar } from 'electron-react-titlebar'; 5import { TitleBar } from 'electron-react-titlebar';
6import injectSheet from 'react-jss';
6 7
7import InfoBar from '../ui/InfoBar'; 8import InfoBar from '../ui/InfoBar';
8import { Component as BasicAuth } from '../../features/basicAuth'; 9import { Component as BasicAuth } from '../../features/basicAuth';
10import { Component as ShareFranz } from '../../features/shareFranz';
9import ErrorBoundary from '../util/ErrorBoundary'; 11import ErrorBoundary from '../util/ErrorBoundary';
10 12
11// import globalMessages from '../../i18n/globalMessages'; 13// import globalMessages from '../../i18n/globalMessages';
12 14
13import { isWindows } from '../../environment'; 15import { isWindows } from '../../environment';
16import AnnouncementScreen from '../../features/announcements/components/AnnouncementScreen';
17import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator';
18import { workspaceStore } from '../../features/workspaces';
19import { announcementActions } from '../../features/announcements/actions';
14 20
15function createMarkup(HTMLString) { 21function createMarkup(HTMLString) {
16 return { __html: HTMLString }; 22 return { __html: HTMLString };
@@ -43,18 +49,30 @@ const messages = defineMessages({
43 }, 49 },
44}); 50});
45 51
46export default 52const styles = theme => ({
47@observer 53 appContent: {
54 width: `calc(100% + ${theme.workspaces.drawer.width}px)`,
55 transition: 'transform 0.5s ease',
56 transform() {
57 return workspaceStore.isWorkspaceDrawerOpen ? 'translateX(0)' : `translateX(-${theme.workspaces.drawer.width}px)`;
58 },
59 },
60});
61
62@injectSheet(styles) @observer
48class AppLayout extends Component { 63class AppLayout extends Component {
49 static propTypes = { 64 static propTypes = {
65 classes: PropTypes.object.isRequired,
50 isFullScreen: PropTypes.bool.isRequired, 66 isFullScreen: PropTypes.bool.isRequired,
51 sidebar: PropTypes.element.isRequired, 67 sidebar: PropTypes.element.isRequired,
68 workspacesDrawer: PropTypes.element.isRequired,
52 services: PropTypes.element.isRequired, 69 services: PropTypes.element.isRequired,
53 children: PropTypes.element, 70 children: PropTypes.element,
54 news: MobxPropTypes.arrayOrObservableArray.isRequired, 71 news: MobxPropTypes.arrayOrObservableArray.isRequired,
55 // isOnline: PropTypes.bool.isRequired, 72 // isOnline: PropTypes.bool.isRequired,
56 showServicesUpdatedInfoBar: PropTypes.bool.isRequired, 73 showServicesUpdatedInfoBar: PropTypes.bool.isRequired,
57 appUpdateIsDownloaded: PropTypes.bool.isRequired, 74 appUpdateIsDownloaded: PropTypes.bool.isRequired,
75 nextAppReleaseVersion: PropTypes.string,
58 removeNewsItem: PropTypes.func.isRequired, 76 removeNewsItem: PropTypes.func.isRequired,
59 reloadServicesAfterUpdate: PropTypes.func.isRequired, 77 reloadServicesAfterUpdate: PropTypes.func.isRequired,
60 installAppUpdate: PropTypes.func.isRequired, 78 installAppUpdate: PropTypes.func.isRequired,
@@ -63,10 +81,13 @@ class AppLayout extends Component {
63 retryRequiredRequests: PropTypes.func.isRequired, 81 retryRequiredRequests: PropTypes.func.isRequired,
64 areRequiredRequestsLoading: PropTypes.bool.isRequired, 82 areRequiredRequestsLoading: PropTypes.bool.isRequired,
65 darkMode: PropTypes.bool.isRequired, 83 darkMode: PropTypes.bool.isRequired,
84 isDelayAppScreenVisible: PropTypes.bool.isRequired,
85 isAnnouncementVisible: PropTypes.bool.isRequired,
66 }; 86 };
67 87
68 static defaultProps = { 88 static defaultProps = {
69 children: [], 89 children: [],
90 nextAppReleaseVersion: null,
70 }; 91 };
71 92
72 static contextTypes = { 93 static contextTypes = {
@@ -75,7 +96,9 @@ class AppLayout extends Component {
75 96
76 render() { 97 render() {
77 const { 98 const {
99 classes,
78 isFullScreen, 100 isFullScreen,
101 workspacesDrawer,
79 sidebar, 102 sidebar,
80 services, 103 services,
81 children, 104 children,
@@ -83,6 +106,7 @@ class AppLayout extends Component {
83 news, 106 news,
84 showServicesUpdatedInfoBar, 107 showServicesUpdatedInfoBar,
85 appUpdateIsDownloaded, 108 appUpdateIsDownloaded,
109 nextAppReleaseVersion,
86 removeNewsItem, 110 removeNewsItem,
87 reloadServicesAfterUpdate, 111 reloadServicesAfterUpdate,
88 installAppUpdate, 112 installAppUpdate,
@@ -91,6 +115,8 @@ class AppLayout extends Component {
91 retryRequiredRequests, 115 retryRequiredRequests,
92 areRequiredRequestsLoading, 116 areRequiredRequestsLoading,
93 darkMode, 117 darkMode,
118 isDelayAppScreenVisible,
119 isAnnouncementVisible,
94 } = this.props; 120 } = this.props;
95 121
96 const { intl } = this.context; 122 const { intl } = this.context;
@@ -99,29 +125,23 @@ class AppLayout extends Component {
99 <ErrorBoundary> 125 <ErrorBoundary>
100 <div className={darkMode ? 'theme__dark' : ''}> 126 <div className={darkMode ? 'theme__dark' : ''}>
101 <div className="app"> 127 <div className="app">
102 {isWindows && !isFullScreen && ( 128 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />}
103 <TitleBar 129 <div className={`app__content ${classes.appContent}`}>
104 menu={window.franz.menu.template} 130 {workspacesDrawer}
105 icon="assets/images/logo.svg"
106 />
107 )}
108 <div className="app__content">
109 {sidebar} 131 {sidebar}
110 <div className="app__service"> 132 <div className="app__service">
111 {news.length > 0 133 <WorkspaceSwitchingIndicator />
112 && news.map(item => ( 134 {news.length > 0 && news.map(item => (
113 <InfoBar 135 <InfoBar
114 key={item.id} 136 key={item.id}
115 position="top" 137 position="top"
116 type={item.type} 138 type={item.type}
117 sticky={item.sticky} 139 sticky={item.sticky}
118 onHide={() => removeNewsItem({ newsId: item.id })} 140 onHide={() => removeNewsItem({ newsId: item.id })}
119 > 141 >
120 <span 142 <span dangerouslySetInnerHTML={createMarkup(item.message)} />
121 dangerouslySetInnerHTML={createMarkup(item.message)} 143 </InfoBar>
122 /> 144 ))}
123 </InfoBar>
124 ))}
125 {/* {!isOnline && ( 145 {/* {!isOnline && (
126 <InfoBar 146 <InfoBar
127 type="danger" 147 type="danger"
@@ -164,12 +184,18 @@ class AppLayout extends Component {
164 <span className="mdi mdi-information" /> 184 <span className="mdi mdi-information" />
165 {intl.formatMessage(messages.updateAvailable)} 185 {intl.formatMessage(messages.updateAvailable)}
166 {' '} 186 {' '}
167 <a href="https://meetfranz.com/changelog" target="_blank"> 187 <button
188 className="info-bar__inline-button"
189 type="button"
190 onClick={() => announcementActions.show({ targetVersion: nextAppReleaseVersion })}
191 >
168 <u>{intl.formatMessage(messages.changelog)}</u> 192 <u>{intl.formatMessage(messages.changelog)}</u>
169 </a> 193 </button>
170 </InfoBar> 194 </InfoBar>
171 )} 195 )}
172 <BasicAuth /> 196 <BasicAuth />
197 <ShareFranz />
198 {isAnnouncementVisible && (<AnnouncementScreen />)}
173 {services} 199 {services}
174 </div> 200 </div>
175 </div> 201 </div>
@@ -180,3 +206,5 @@ class AppLayout extends Component {
180 ); 206 );
181 } 207 }
182} 208}
209
210export default AppLayout;
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 609a3b604..36c1f2e39 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -6,6 +6,8 @@ import { observer } from 'mobx-react';
6 6
7import Tabbar from '../services/tabs/Tabbar'; 7import Tabbar from '../services/tabs/Tabbar';
8import { ctrlKey } from '../../environment'; 8import { ctrlKey } from '../../environment';
9import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../../features/workspaces';
10import { gaEvent } from '../../lib/analytics';
9 11
10const messages = defineMessages({ 12const messages = defineMessages({
11 settings: { 13 settings: {
@@ -24,6 +26,14 @@ const messages = defineMessages({
24 id: 'sidebar.unmuteApp', 26 id: 'sidebar.unmuteApp',
25 defaultMessage: '!!!Enable notifications & audio', 27 defaultMessage: '!!!Enable notifications & audio',
26 }, 28 },
29 openWorkspaceDrawer: {
30 id: 'sidebar.openWorkspaceDrawer',
31 defaultMessage: '!!!Open workspace drawer',
32 },
33 closeWorkspaceDrawer: {
34 id: 'sidebar.closeWorkspaceDrawer',
35 defaultMessage: '!!!Close workspace drawer',
36 },
27}); 37});
28 38
29export default @observer class Sidebar extends Component { 39export default @observer class Sidebar extends Component {
@@ -31,7 +41,9 @@ export default @observer class Sidebar extends Component {
31 openSettings: PropTypes.func.isRequired, 41 openSettings: PropTypes.func.isRequired,
32 toggleMuteApp: PropTypes.func.isRequired, 42 toggleMuteApp: PropTypes.func.isRequired,
33 isAppMuted: PropTypes.bool.isRequired, 43 isAppMuted: PropTypes.bool.isRequired,
34 } 44 isWorkspaceDrawerOpen: PropTypes.bool.isRequired,
45 toggleWorkspaceDrawer: PropTypes.func.isRequired,
46 };
35 47
36 static contextTypes = { 48 static contextTypes = {
37 intl: intlShape, 49 intl: intlShape,
@@ -53,9 +65,23 @@ export default @observer class Sidebar extends Component {
53 this.setState({ tooltipEnabled: false }); 65 this.setState({ tooltipEnabled: false });
54 } 66 }
55 67
68 updateToolTip() {
69 this.disableToolTip();
70 setTimeout(this.enableToolTip.bind(this));
71 }
72
56 render() { 73 render() {
57 const { openSettings, toggleMuteApp, isAppMuted } = this.props; 74 const {
75 openSettings,
76 toggleMuteApp,
77 isAppMuted,
78 isWorkspaceDrawerOpen,
79 toggleWorkspaceDrawer,
80 } = this.props;
58 const { intl } = this.context; 81 const { intl } = this.context;
82 const workspaceToggleMessage = (
83 isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer
84 );
59 85
60 return ( 86 return (
61 <div className="sidebar"> 87 <div className="sidebar">
@@ -64,9 +90,26 @@ export default @observer class Sidebar extends Component {
64 enableToolTip={() => this.enableToolTip()} 90 enableToolTip={() => this.enableToolTip()}
65 disableToolTip={() => this.disableToolTip()} 91 disableToolTip={() => this.disableToolTip()}
66 /> 92 />
93 {workspaceStore.isFeatureEnabled ? (
94 <button
95 type="button"
96 onClick={() => {
97 toggleWorkspaceDrawer();
98 this.updateToolTip();
99 gaEvent(GA_CATEGORY_WORKSPACES, 'toggleDrawer', 'sidebar');
100 }}
101 className={`sidebar__button sidebar__button--workspaces ${isWorkspaceDrawerOpen ? 'is-active' : ''}`}
102 data-tip={`${intl.formatMessage(workspaceToggleMessage)} (${ctrlKey}+D)`}
103 >
104 <i className="mdi mdi-view-grid" />
105 </button>
106 ) : null}
67 <button 107 <button
68 type="button" 108 type="button"
69 onClick={toggleMuteApp} 109 onClick={() => {
110 toggleMuteApp();
111 this.updateToolTip();
112 }}
70 className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} 113 className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`}
71 data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`} 114 data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`}
72 > 115 >
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
new file mode 100644
index 000000000..13148b9b3
--- /dev/null
+++ b/src/components/services/content/ServiceView.js
@@ -0,0 +1,139 @@
1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types';
3import { autorun } from 'mobx';
4import { observer } from 'mobx-react';
5import classnames from 'classnames';
6
7import ServiceModel from '../../../models/Service';
8import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
9import WebviewLoader from '../../ui/WebviewLoader';
10import WebviewCrashHandler from './WebviewCrashHandler';
11import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler';
12import ServiceDisabled from './ServiceDisabled';
13import ServiceWebview from './ServiceWebview';
14
15export default @observer class ServiceView extends Component {
16 static propTypes = {
17 service: PropTypes.instanceOf(ServiceModel).isRequired,
18 setWebviewReference: PropTypes.func.isRequired,
19 detachService: PropTypes.func.isRequired,
20 reload: PropTypes.func.isRequired,
21 edit: PropTypes.func.isRequired,
22 enable: PropTypes.func.isRequired,
23 isActive: PropTypes.bool,
24 };
25
26 static defaultProps = {
27 isActive: false,
28 };
29
30 state = {
31 forceRepaint: false,
32 targetUrl: '',
33 statusBarVisible: false,
34 };
35
36 autorunDisposer = null;
37
38 forceRepaintTimeout = null;
39
40 componentDidMount() {
41 this.autorunDisposer = autorun(() => {
42 if (this.props.service.isActive) {
43 this.setState({ forceRepaint: true });
44 this.forceRepaintTimeout = setTimeout(() => {
45 this.setState({ forceRepaint: false });
46 }, 100);
47 }
48 });
49 }
50
51 componentWillUnmount() {
52 this.autorunDisposer();
53 clearTimeout(this.forceRepaintTimeout);
54 }
55
56 updateTargetUrl = (event) => {
57 let visible = true;
58 if (event.url === '' || event.url === '#') {
59 visible = false;
60 }
61 this.setState({
62 targetUrl: event.url,
63 statusBarVisible: visible,
64 });
65 };
66
67 render() {
68 const {
69 detachService,
70 service,
71 setWebviewReference,
72 reload,
73 edit,
74 enable,
75 } = this.props;
76
77 const webviewClasses = classnames({
78 services__webview: true,
79 'services__webview-wrapper': true,
80 'is-active': service.isActive,
81 'services__webview--force-repaint': this.state.forceRepaint,
82 });
83
84 let statusBar = null;
85 if (this.state.statusBarVisible) {
86 statusBar = (
87 <StatusBarTargetUrl text={this.state.targetUrl} />
88 );
89 }
90
91 return (
92 <div className={webviewClasses}>
93 {service.isActive && service.isEnabled && (
94 <Fragment>
95 {service.hasCrashed && (
96 <WebviewCrashHandler
97 name={service.recipe.name}
98 webview={service.webview}
99 reload={reload}
100 />
101 )}
102 {service.isEnabled && service.isLoading && service.isFirstLoad && (
103 <WebviewLoader
104 loaded={false}
105 name={service.name}
106 />
107 )}
108 {service.isError && (
109 <WebviewErrorHandler
110 name={service.recipe.name}
111 errorMessage={service.errorMessage}
112 reload={reload}
113 edit={edit}
114 />
115 )}
116 </Fragment>
117 )}
118 {!service.isEnabled ? (
119 <Fragment>
120 {service.isActive && (
121 <ServiceDisabled
122 name={service.recipe.name}
123 webview={service.webview}
124 enable={enable}
125 />
126 )}
127 </Fragment>
128 ) : (
129 <ServiceWebview
130 service={service}
131 setWebviewReference={setWebviewReference}
132 detachService={detachService}
133 />
134 )}
135 {statusBar}
136 </div>
137 );
138 }
139}
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index bb577e4cc..7252c695f 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -1,145 +1,50 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { autorun } from 'mobx';
4import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
5import Webview from 'react-electron-web-view'; 4import ElectronWebView from 'react-electron-web-view';
6import classnames from 'classnames';
7 5
8import ServiceModel from '../../../models/Service'; 6import ServiceModel from '../../../models/Service';
9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
10import WebviewLoader from '../../ui/WebviewLoader';
11import WebviewCrashHandler from './WebviewCrashHandler';
12import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler';
13import ServiceDisabled from './ServiceDisabled';
14 7
15export default @observer class ServiceWebview extends Component { 8@observer
9class ServiceWebview extends Component {
16 static propTypes = { 10 static propTypes = {
17 service: PropTypes.instanceOf(ServiceModel).isRequired, 11 service: PropTypes.instanceOf(ServiceModel).isRequired,
18 setWebviewReference: PropTypes.func.isRequired, 12 setWebviewReference: PropTypes.func.isRequired,
19 reload: PropTypes.func.isRequired, 13 detachService: PropTypes.func.isRequired,
20 edit: PropTypes.func.isRequired,
21 enable: PropTypes.func.isRequired,
22 isActive: PropTypes.bool,
23 }; 14 };
24 15
25 static defaultProps = {
26 isActive: false,
27 };
28
29 state = {
30 forceRepaint: false,
31 targetUrl: '',
32 statusBarVisible: false,
33 };
34
35 autorunDisposer = null;
36
37 webview = null; 16 webview = null;
38 17
39 componentDidMount() {
40 this.autorunDisposer = autorun(() => {
41 if (this.props.service.isActive) {
42 this.setState({ forceRepaint: true });
43 setTimeout(() => {
44 this.setState({ forceRepaint: false });
45 }, 100);
46 }
47 });
48 }
49
50 componentWillUnmount() { 18 componentWillUnmount() {
51 this.autorunDisposer(); 19 const { service, detachService } = this.props;
52 } 20 detachService({ service });
53
54 updateTargetUrl = (event) => {
55 let visible = true;
56 if (event.url === '' || event.url === '#') {
57 visible = false;
58 }
59 this.setState({
60 targetUrl: event.url,
61 statusBarVisible: visible,
62 });
63 } 21 }
64 22
65 render() { 23 render() {
66 const { 24 const {
67 service, 25 service,
68 setWebviewReference, 26 setWebviewReference,
69 reload,
70 edit,
71 enable,
72 } = this.props; 27 } = this.props;
73 28
74 const webviewClasses = classnames({
75 services__webview: true,
76 'services__webview-wrapper': true,
77 'is-active': service.isActive,
78 'services__webview--force-repaint': this.state.forceRepaint,
79 });
80
81 let statusBar = null;
82 if (this.state.statusBarVisible) {
83 statusBar = (
84 <StatusBarTargetUrl text={this.state.targetUrl} />
85 );
86 }
87
88 return ( 29 return (
89 <div className={webviewClasses}> 30 <ElectronWebView
90 {service.isActive && service.isEnabled && ( 31 ref={(webview) => { this.webview = webview; }}
91 <Fragment> 32 autosize
92 {service.hasCrashed && ( 33 src={service.url}
93 <WebviewCrashHandler 34 preload="./webview/recipe.js"
94 name={service.recipe.name} 35 partition={`persist:service-${service.id}`}
95 webview={service.webview} 36 onDidAttach={() => {
96 reload={reload} 37 setWebviewReference({
97 /> 38 serviceId: service.id,
98 )} 39 webview: this.webview.view,
99 {service.isEnabled && service.isLoading && service.isFirstLoad && ( 40 });
100 <WebviewLoader 41 }}
101 loaded={false} 42 onUpdateTargetUrl={this.updateTargetUrl}
102 name={service.name} 43 useragent={service.userAgent}
103 /> 44 allowpopups
104 )} 45 />
105 {service.isError && (
106 <WebviewErrorHandler
107 name={service.recipe.name}
108 errorMessage={service.errorMessage}
109 reload={reload}
110 edit={edit}
111 />
112 )}
113 </Fragment>
114 )}
115 {!service.isEnabled ? (
116 <Fragment>
117 {service.isActive && (
118 <ServiceDisabled
119 name={service.recipe.name}
120 webview={service.webview}
121 enable={enable}
122 />
123 )}
124 </Fragment>
125 ) : (
126 <Webview
127 ref={(element) => { this.webview = element; }}
128 autosize
129 src={service.url}
130 preload="./webview/recipe.js"
131 partition={`persist:service-${service.id}`}
132 onDidAttach={() => setWebviewReference({
133 serviceId: service.id,
134 webview: this.webview.view,
135 })}
136 onUpdateTargetUrl={this.updateTargetUrl}
137 useragent={service.userAgent}
138 allowpopups
139 />
140 )}
141 {statusBar}
142 </div>
143 ); 46 );
144 } 47 }
145} 48}
49
50export default ServiceWebview;
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 54f16ba12..8f8c38a11 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -4,7 +4,7 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, intlShape } from 'react-intl';
6 6
7import Webview from './ServiceWebview'; 7import ServiceView from './ServiceView';
8import Appear from '../../ui/effects/Appear'; 8import Appear from '../../ui/effects/Appear';
9 9
10const messages = defineMessages({ 10const messages = defineMessages({
@@ -22,6 +22,7 @@ export default @observer class Services extends Component {
22 static propTypes = { 22 static propTypes = {
23 services: MobxPropTypes.arrayOrObservableArray, 23 services: MobxPropTypes.arrayOrObservableArray,
24 setWebviewReference: PropTypes.func.isRequired, 24 setWebviewReference: PropTypes.func.isRequired,
25 detachService: PropTypes.func.isRequired,
25 handleIPCMessage: PropTypes.func.isRequired, 26 handleIPCMessage: PropTypes.func.isRequired,
26 openWindow: PropTypes.func.isRequired, 27 openWindow: PropTypes.func.isRequired,
27 reload: PropTypes.func.isRequired, 28 reload: PropTypes.func.isRequired,
@@ -42,6 +43,7 @@ export default @observer class Services extends Component {
42 services, 43 services,
43 handleIPCMessage, 44 handleIPCMessage,
44 setWebviewReference, 45 setWebviewReference,
46 detachService,
45 openWindow, 47 openWindow,
46 reload, 48 reload,
47 openSettings, 49 openSettings,
@@ -71,11 +73,12 @@ export default @observer class Services extends Component {
71 </Appear> 73 </Appear>
72 )} 74 )}
73 {services.map(service => ( 75 {services.map(service => (
74 <Webview 76 <ServiceView
75 key={service.id} 77 key={service.id}
76 service={service} 78 service={service}
77 handleIPCMessage={handleIPCMessage} 79 handleIPCMessage={handleIPCMessage}
78 setWebviewReference={setWebviewReference} 80 setWebviewReference={setWebviewReference}
81 detachService={detachService}
79 openWindow={openWindow} 82 openWindow={openWindow}
80 reload={() => reload({ serviceId: service.id })} 83 reload={() => reload({ serviceId: service.id })}
81 edit={() => openSettings({ path: `services/edit/${service.id}` })} 84 edit={() => openSettings({ path: `services/edit/${service.id}` })}
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 42bc3c877..7a69dba87 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import ms from 'ms';
5 6
6import Button from '../../ui/Button'; 7import Button from '../../ui/Button';
7 8
@@ -35,12 +36,12 @@ export default @observer class WebviewCrashHandler extends Component {
35 }; 36 };
36 37
37 state = { 38 state = {
38 countdown: 10000, 39 countdown: ms('10s'),
39 } 40 }
40 41
41 countdownInterval = null; 42 countdownInterval = null;
42 43
43 countdownIntervalTimeout = 1000; 44 countdownIntervalTimeout = ms('1s');
44 45
45 46
46 componentDidMount() { 47 componentDidMount() {
@@ -75,7 +76,7 @@ export default @observer class WebviewCrashHandler extends Component {
75 <p className="footnote"> 76 <p className="footnote">
76 {intl.formatMessage(messages.autoReload, { 77 {intl.formatMessage(messages.autoReload, {
77 name, 78 name,
78 seconds: this.state.countdown / 1000, 79 seconds: this.state.countdown / ms('1s'),
79 })} 80 })}
80 </p> 81 </p>
81 </div> 82 </div>
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index dd5c2140f..5e8260ad0 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -19,7 +19,7 @@ export default @observer class TabBar extends Component {
19 updateService: PropTypes.func.isRequired, 19 updateService: PropTypes.func.isRequired,
20 showMessageBadgeWhenMutedSetting: PropTypes.bool.isRequired, 20 showMessageBadgeWhenMutedSetting: PropTypes.bool.isRequired,
21 showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired, 21 showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired,
22 } 22 };
23 23
24 onSortEnd = ({ oldIndex, newIndex }) => { 24 onSortEnd = ({ oldIndex, newIndex }) => {
25 const { 25 const {
@@ -45,7 +45,7 @@ export default @observer class TabBar extends Component {
45 redirect: false, 45 redirect: false,
46 }); 46 });
47 } 47 }
48 } 48 };
49 49
50 disableService({ serviceId }) { 50 disableService({ serviceId }) {
51 this.toggleService({ serviceId, isEnabled: false }); 51 this.toggleService({ serviceId, isEnabled: false });
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 9c9543749..3f6964b6b 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -3,12 +3,11 @@ import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import moment from 'moment'; 6import { ProBadge } from '@meetfranz/ui';
7 7
8import Loader from '../../ui/Loader'; 8import Loader from '../../ui/Loader';
9import Button from '../../ui/Button'; 9import Button from '../../ui/Button';
10import Infobox from '../../ui/Infobox'; 10import Infobox from '../../ui/Infobox';
11import Link from '../../ui/Link';
12import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; 11import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen';
13 12
14const messages = defineMessages({ 13const messages = defineMessages({
@@ -24,10 +23,6 @@ const messages = defineMessages({
24 id: 'settings.account.headlineUpgrade', 23 id: 'settings.account.headlineUpgrade',
25 defaultMessage: '!!!Upgrade your Account', 24 defaultMessage: '!!!Upgrade your Account',
26 }, 25 },
27 headlineInvoices: {
28 id: 'settings.account.headlineInvoices',
29 defaultMessage: '!!Invoices',
30 },
31 headlineDangerZone: { 26 headlineDangerZone: {
32 id: 'settings.account.headlineDangerZone', 27 id: 'settings.account.headlineDangerZone',
33 defaultMessage: '!!Danger Zone', 28 defaultMessage: '!!Danger Zone',
@@ -44,14 +39,14 @@ const messages = defineMessages({
44 id: 'settings.account.accountType.premium', 39 id: 'settings.account.accountType.premium',
45 defaultMessage: '!!!Premium Supporter Account', 40 defaultMessage: '!!!Premium Supporter Account',
46 }, 41 },
47 accountTypeEnterprise: {
48 id: 'settings.account.accountType.enterprise',
49 defaultMessage: '!!!Enterprise Account',
50 },
51 accountEditButton: { 42 accountEditButton: {
52 id: 'settings.account.account.editButton', 43 id: 'settings.account.account.editButton',
53 defaultMessage: '!!!Edit Account', 44 defaultMessage: '!!!Edit Account',
54 }, 45 },
46 invoicesButton: {
47 id: 'settings.account.headlineInvoices',
48 defaultMessage: '!!Invoices',
49 },
55 invoiceDownload: { 50 invoiceDownload: {
56 id: 'settings.account.invoiceDownload', 51 id: 'settings.account.invoiceDownload',
57 defaultMessage: '!!!Download', 52 defaultMessage: '!!!Download',
@@ -81,19 +76,17 @@ const messages = defineMessages({
81export default @observer class AccountDashboard extends Component { 76export default @observer class AccountDashboard extends Component {
82 static propTypes = { 77 static propTypes = {
83 user: MobxPropTypes.observableObject.isRequired, 78 user: MobxPropTypes.observableObject.isRequired,
84 orders: MobxPropTypes.arrayOrObservableArray.isRequired,
85 isLoading: PropTypes.bool.isRequired, 79 isLoading: PropTypes.bool.isRequired,
86 isLoadingOrdersInfo: PropTypes.bool.isRequired,
87 isLoadingPlans: PropTypes.bool.isRequired, 80 isLoadingPlans: PropTypes.bool.isRequired,
88 isCreatingPaymentDashboardUrl: PropTypes.bool.isRequired,
89 userInfoRequestFailed: PropTypes.bool.isRequired, 81 userInfoRequestFailed: PropTypes.bool.isRequired,
90 retryUserInfoRequest: PropTypes.func.isRequired, 82 retryUserInfoRequest: PropTypes.func.isRequired,
91 openDashboard: PropTypes.func.isRequired,
92 openExternalUrl: PropTypes.func.isRequired,
93 onCloseSubscriptionWindow: PropTypes.func.isRequired, 83 onCloseSubscriptionWindow: PropTypes.func.isRequired,
94 deleteAccount: PropTypes.func.isRequired, 84 deleteAccount: PropTypes.func.isRequired,
95 isLoadingDeleteAccount: PropTypes.bool.isRequired, 85 isLoadingDeleteAccount: PropTypes.bool.isRequired,
96 isDeleteAccountSuccessful: PropTypes.bool.isRequired, 86 isDeleteAccountSuccessful: PropTypes.bool.isRequired,
87 openEditAccount: PropTypes.func.isRequired,
88 openBilling: PropTypes.func.isRequired,
89 openInvoices: PropTypes.func.isRequired,
97 }; 90 };
98 91
99 static contextTypes = { 92 static contextTypes = {
@@ -103,12 +96,7 @@ export default @observer class AccountDashboard extends Component {
103 render() { 96 render() {
104 const { 97 const {
105 user, 98 user,
106 orders,
107 isLoading, 99 isLoading,
108 isCreatingPaymentDashboardUrl,
109 openDashboard,
110 openExternalUrl,
111 isLoadingOrdersInfo,
112 isLoadingPlans, 100 isLoadingPlans,
113 userInfoRequestFailed, 101 userInfoRequestFailed,
114 retryUserInfoRequest, 102 retryUserInfoRequest,
@@ -116,6 +104,9 @@ export default @observer class AccountDashboard extends Component {
116 deleteAccount, 104 deleteAccount,
117 isLoadingDeleteAccount, 105 isLoadingDeleteAccount,
118 isDeleteAccountSuccessful, 106 isDeleteAccountSuccessful,
107 openEditAccount,
108 openBilling,
109 openInvoices,
119 } = this.props; 110 } = this.props;
120 const { intl } = this.context; 111 const { intl } = this.context;
121 112
@@ -153,116 +144,56 @@ export default @observer class AccountDashboard extends Component {
153 src="./assets/images/logo.svg" 144 src="./assets/images/logo.svg"
154 alt="" 145 alt=""
155 /> 146 />
156 {user.isPremium && (
157 <span
158 className="account__avatar-premium emoji"
159 data-tip="Premium Supporter Account"
160 >
161 <img src="./assets/images/emoji/star.png" alt="" />
162 </span>
163 )}
164 </div> 147 </div>
165 <div className="account__info"> 148 <div className="account__info">
166 <h2> 149 <h2>
167 {`${user.firstname} ${user.lastname}`} 150 <span className="username">{`${user.firstname} ${user.lastname}`}</span>
151 {user.isPremium && (
152 <>
153 {' '}
154 <ProBadge />
155 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span>
156 </>
157 )}
168 </h2> 158 </h2>
169 {user.organization && `${user.organization}, `} 159 {user.organization && `${user.organization}, `}
170 {user.email} 160 {user.email}
171 <br />
172 {!user.isEnterprise && !user.isPremium && (
173 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span>
174 )}
175 {user.isPremium && ( 161 {user.isPremium && (
176 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span> 162 <div className="manage-user-links">
177 )} 163 <Button
178 {user.isEnterprise && ( 164 label={intl.formatMessage(messages.accountEditButton)}
179 <span className="badge badge--success">{intl.formatMessage(messages.accountTypeEnterprise)}</span> 165 className="franz-form__button--inverted"
166 onClick={openEditAccount}
167 />
168 {user.isSubscriptionOwner && (
169 <>
170 <Button
171 label={intl.formatMessage(messages.manageSubscriptionButtonLabel)}
172 className="franz-form__button--inverted"
173 onClick={openBilling}
174 />
175 <Button
176 label={intl.formatMessage(messages.invoicesButton)}
177 className="franz-form__button--inverted"
178 onClick={openInvoices}
179 />
180 </>
181 )}
182 </div>
180 )} 183 )}
181 </div> 184 </div>
182 <Link to="/settings/user/edit" className="button"> 185 {!user.isPremium && (
183 {intl.formatMessage(messages.accountEditButton)} 186 <Button
184 </Link> 187 label={intl.formatMessage(messages.accountEditButton)}
185 {user.emailValidated} 188 className="franz-form__button--inverted"
186 </div> 189 onClick={openEditAccount}
187 </div> 190 />
188 )}
189
190 {user.isSubscriptionOwner && (
191 isLoadingOrdersInfo ? (
192 <Loader />
193 ) : (
194 <div className="account franz-form">
195 {orders.length > 0 && (
196 <Fragment>
197 <div className="account__box">
198 <h2>{intl.formatMessage(messages.headlineSubscription)}</h2>
199 <div className="account__subscription">
200 {orders[0].name}
201 <span className="badge">{orders[0].price}</span>
202 <Button
203 label={intl.formatMessage(messages.manageSubscriptionButtonLabel)}
204 className="account__subscription-button franz-form__button--inverted"
205 loaded={!isCreatingPaymentDashboardUrl}
206 onClick={() => openDashboard()}
207 />
208 </div>
209 </div>
210 <div className="account__box">
211 <h2>{intl.formatMessage(messages.headlineInvoices)}</h2>
212 <table className="invoices">
213 <tbody>
214 {orders.map(order => (
215 <tr key={order.id}>
216 <td className="invoices__date">
217 {moment(order.date).format('DD.MM.YYYY')}
218 </td>
219 <td className="invoices__action">
220 <button
221 type="button"
222 onClick={() => openExternalUrl(order.invoiceUrl)}
223 >
224 {intl.formatMessage(messages.invoiceDownload)}
225 </button>
226 </td>
227 </tr>
228 ))}
229 </tbody>
230 </table>
231 </div>
232 </Fragment>
233 )} 191 )}
234 </div> 192 </div>
235 )
236 )}
237
238 {user.isEnterprise && (
239 <div className="account">
240 <div className="account__box">
241 <h2>{user.company.name}</h2>
242 <p>
243 Technical contact:&nbsp;
244 <Link
245 className="link"
246 target="_blank"
247 to={`mailto:${user.company.contact.technical}?subject=Franz`}
248 >
249 {user.company.contact.technical}
250 </Link>
251 <br />
252 General contact:&nbsp;
253 <Link
254 className="link"
255 target="_blank"
256 to={`mailto:${user.company.contact.default}?subject=Franz`}
257 >
258 {user.company.contact.default}
259 </Link>
260 </p>
261 </div>
262 </div> 193 </div>
263 )} 194 )}
264 195
265 {!user.isEnterprise && !user.isPremium && ( 196 {!user.isPremium && (
266 isLoadingPlans ? ( 197 isLoadingPlans ? (
267 <Loader /> 198 <Loader />
268 ) : ( 199 ) : (
@@ -277,27 +208,25 @@ export default @observer class AccountDashboard extends Component {
277 ) 208 )
278 )} 209 )}
279 210
280 {!user.isEnterprise && ( 211 <div className="account franz-form">
281 <div className="account franz-form"> 212 <div className="account__box">
282 <div className="account__box"> 213 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2>
283 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2> 214 {!isDeleteAccountSuccessful && (
284 {!isDeleteAccountSuccessful && ( 215 <div className="account__subscription">
285 <div className="account__subscription"> 216 <p>{intl.formatMessage(messages.deleteInfo)}</p>
286 <p>{intl.formatMessage(messages.deleteInfo)}</p> 217 <Button
287 <Button 218 label={intl.formatMessage(messages.deleteAccount)}
288 label={intl.formatMessage(messages.deleteAccount)} 219 buttonType="danger"
289 buttonType="danger" 220 onClick={() => deleteAccount()}
290 onClick={() => deleteAccount()} 221 loaded={!isLoadingDeleteAccount}
291 loaded={!isLoadingDeleteAccount} 222 />
292 />
293 </div>
294 )}
295 {isDeleteAccountSuccessful && (
296 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
297 )}
298 </div> 223 </div>
224 )}
225 {isDeleteAccountSuccessful && (
226 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
227 )}
299 </div> 228 </div>
300 )} 229 </div>
301 </Fragment> 230 </Fragment>
302 )} 231 )}
303 </div> 232 </div>
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 953f702f8..df4b3b3b2 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -2,8 +2,12 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, intlShape } from 'react-intl';
4import { inject, observer } from 'mobx-react'; 4import { inject, observer } from 'mobx-react';
5import { ProBadge } from '@meetfranz/ui';
5 6
6import Link from '../../ui/Link'; 7import Link from '../../ui/Link';
8import { workspaceStore } from '../../../features/workspaces';
9import UIStore from '../../../stores/UIStore';
10import UserStore from '../../../stores/UserStore';
7 11
8const messages = defineMessages({ 12const messages = defineMessages({
9 availableServices: { 13 availableServices: {
@@ -14,10 +18,18 @@ const messages = defineMessages({
14 id: 'settings.navigation.yourServices', 18 id: 'settings.navigation.yourServices',
15 defaultMessage: '!!!Your services', 19 defaultMessage: '!!!Your services',
16 }, 20 },
21 yourWorkspaces: {
22 id: 'settings.navigation.yourWorkspaces',
23 defaultMessage: '!!!Your workspaces',
24 },
17 account: { 25 account: {
18 id: 'settings.navigation.account', 26 id: 'settings.navigation.account',
19 defaultMessage: '!!!Account', 27 defaultMessage: '!!!Account',
20 }, 28 },
29 team: {
30 id: 'settings.navigation.team',
31 defaultMessage: '!!!Manage Team',
32 },
21 settings: { 33 settings: {
22 id: 'settings.navigation.settings', 34 id: 'settings.navigation.settings',
23 defaultMessage: '!!!Settings', 35 defaultMessage: '!!!Settings',
@@ -34,7 +46,12 @@ const messages = defineMessages({
34 46
35export default @inject('stores') @observer class SettingsNavigation extends Component { 47export default @inject('stores') @observer class SettingsNavigation extends Component {
36 static propTypes = { 48 static propTypes = {
49 stores: PropTypes.shape({
50 ui: PropTypes.instanceOf(UIStore).isRequired,
51 user: PropTypes.instanceOf(UserStore).isRequired,
52 }).isRequired,
37 serviceCount: PropTypes.number.isRequired, 53 serviceCount: PropTypes.number.isRequired,
54 workspaceCount: PropTypes.number.isRequired,
38 }; 55 };
39 56
40 static contextTypes = { 57 static contextTypes = {
@@ -42,7 +59,9 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
42 }; 59 };
43 60
44 render() { 61 render() {
45 const { serviceCount } = this.props; 62 const { serviceCount, workspaceCount, stores } = this.props;
63 const { isDarkThemeActive } = stores.ui;
64 const { router, user } = stores;
46 const { intl } = this.context; 65 const { intl } = this.context;
47 66
48 return ( 67 return (
@@ -63,6 +82,21 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
63 {' '} 82 {' '}
64 <span className="badge">{serviceCount}</span> 83 <span className="badge">{serviceCount}</span>
65 </Link> 84 </Link>
85 {workspaceStore.isFeatureEnabled ? (
86 <Link
87 to="/settings/workspaces"
88 className="settings-navigation__link"
89 activeClassName="is-active"
90 >
91 {intl.formatMessage(messages.yourWorkspaces)}
92 {' '}
93 {workspaceStore.isPremiumUpgradeRequired ? (
94 <ProBadge inverted={!isDarkThemeActive && workspaceStore.isSettingsRouteActive} />
95 ) : (
96 <span className="badge">{workspaceCount}</span>
97 )}
98 </Link>
99 ) : null}
66 <Link 100 <Link
67 to="/settings/user" 101 to="/settings/user"
68 className="settings-navigation__link" 102 className="settings-navigation__link"
@@ -71,6 +105,16 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
71 {intl.formatMessage(messages.account)} 105 {intl.formatMessage(messages.account)}
72 </Link> 106 </Link>
73 <Link 107 <Link
108 to="/settings/team"
109 className="settings-navigation__link"
110 activeClassName="is-active"
111 >
112 {intl.formatMessage(messages.team)}
113 {!user.data.isPremium && (
114 <ProBadge inverted={!isDarkThemeActive && router.location.pathname === '/settings/team'} />
115 )}
116 </Link>
117 <Link
74 to="/settings/app" 118 to="/settings/app"
75 className="settings-navigation__link" 119 className="settings-navigation__link"
76 activeClassName="is-active" 120 activeClassName="is-active"
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 468d85c45..4ba2eb844 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -128,7 +128,8 @@ export default @observer class EditServiceForm extends Component {
128 isSaving: PropTypes.bool.isRequired, 128 isSaving: PropTypes.bool.isRequired,
129 isDeleting: PropTypes.bool.isRequired, 129 isDeleting: PropTypes.bool.isRequired,
130 isProxyFeatureEnabled: PropTypes.bool.isRequired, 130 isProxyFeatureEnabled: PropTypes.bool.isRequired,
131 isProxyFeaturePremiumFeature: PropTypes.bool.isRequired, 131 isProxyPremiumFeature: PropTypes.bool.isRequired,
132 isSpellcheckerPremiumFeature: PropTypes.bool.isRequired,
132 }; 133 };
133 134
134 static defaultProps = { 135 static defaultProps = {
@@ -191,7 +192,8 @@ export default @observer class EditServiceForm extends Component {
191 isDeleting, 192 isDeleting,
192 onDelete, 193 onDelete,
193 isProxyFeatureEnabled, 194 isProxyFeatureEnabled,
194 isProxyFeaturePremiumFeature, 195 isProxyPremiumFeature,
196 isSpellcheckerPremiumFeature,
195 } = this.props; 197 } = this.props;
196 const { intl } = this.context; 198 const { intl } = this.context;
197 199
@@ -339,14 +341,20 @@ export default @observer class EditServiceForm extends Component {
339 </div> 341 </div>
340 </div> 342 </div>
341 343
342 <PremiumFeatureContainer> 344 <PremiumFeatureContainer
345 condition={isSpellcheckerPremiumFeature}
346 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }}
347 >
343 <div className="settings__settings-group"> 348 <div className="settings__settings-group">
344 <Select field={form.$('spellcheckerLanguage')} /> 349 <Select field={form.$('spellcheckerLanguage')} />
345 </div> 350 </div>
346 </PremiumFeatureContainer> 351 </PremiumFeatureContainer>
347 352
348 {isProxyFeatureEnabled && ( 353 {isProxyFeatureEnabled && (
349 <PremiumFeatureContainer condition={isProxyFeaturePremiumFeature}> 354 <PremiumFeatureContainer
355 condition={isProxyPremiumFeature}
356 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'proxy' }}
357 >
350 <div className="settings__settings-group"> 358 <div className="settings__settings-group">
351 <h3> 359 <h3>
352 {intl.formatMessage(messages.headlineProxy)} 360 {intl.formatMessage(messages.headlineProxy)}
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index a12df7372..53bae12df 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -65,7 +65,7 @@ export default @observer class ServicesDashboard extends Component {
65 65
66 static defaultProps = { 66 static defaultProps = {
67 searchNeedle: '', 67 searchNeedle: '',
68 } 68 };
69 69
70 static contextTypes = { 70 static contextTypes = {
71 intl: intlShape, 71 intl: intlShape,
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index a92e559f3..efd453356 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -81,6 +81,10 @@ const messages = defineMessages({
81 id: 'settings.app.restartRequired', 81 id: 'settings.app.restartRequired',
82 defaultMessage: '!!!Changes require restart', 82 defaultMessage: '!!!Changes require restart',
83 }, 83 },
84 languageDisclaimer: {
85 id: 'settings.app.languageDisclaimer',
86 defaultMessage: '!!!Official translations are English & German. All other languages are community based translations.',
87 },
84}); 88});
85 89
86export default @observer class EditSettingsForm extends Component { 90export default @observer class EditSettingsForm extends Component {
@@ -170,6 +174,7 @@ export default @observer class EditSettingsForm extends Component {
170 <Select field={form.$('locale')} showLabel={false} /> 174 <Select field={form.$('locale')} showLabel={false} />
171 <PremiumFeatureContainer 175 <PremiumFeatureContainer
172 condition={isSpellcheckerPremiumFeature} 176 condition={isSpellcheckerPremiumFeature}
177 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'spellchecker' }}
173 > 178 >
174 <Fragment> 179 <Fragment>
175 <Toggle 180 <Toggle
@@ -238,6 +243,10 @@ export default @observer class EditSettingsForm extends Component {
238 {intl.formatMessage(messages.currentVersion)} 243 {intl.formatMessage(messages.currentVersion)}
239 {' '} 244 {' '}
240 {remote.app.getVersion()} 245 {remote.app.getVersion()}
246 <p className="settings__message">
247 <span className="mdi mdi-information" />
248 {intl.formatMessage(messages.languageDisclaimer)}
249 </p>
241 </form> 250 </form>
242 </div> 251 </div>
243 </div> 252 </div>
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js
new file mode 100644
index 000000000..82c517fcb
--- /dev/null
+++ b/src/components/settings/team/TeamDashboard.js
@@ -0,0 +1,152 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import ReactTooltip from 'react-tooltip';
6import injectSheet from 'react-jss';
7
8import Loader from '../../ui/Loader';
9import Button from '../../ui/Button';
10import Infobox from '../../ui/Infobox';
11import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
12
13const messages = defineMessages({
14 headline: {
15 id: 'settings.team.headline',
16 defaultMessage: '!!!Team',
17 },
18 contentHeadline: {
19 id: 'settings.team.contentHeadline',
20 defaultMessage: '!!!Franz for Teams',
21 },
22 intro: {
23 id: 'settings.team.intro',
24 defaultMessage: '!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.',
25 },
26 copy: {
27 id: 'settings.team.copy',
28 defaultMessage: '!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!',
29 },
30 manageButton: {
31 id: 'settings.team.manageAction',
32 defaultMessage: '!!!Manage your Team on meetfranz.com',
33 },
34 upgradeButton: {
35 id: 'settings.team.upgradeAction',
36 defaultMessage: '!!!Upgrade your Account',
37 },
38});
39
40const styles = {
41 cta: {
42 margin: [40, 'auto'],
43 },
44 container: {
45 display: 'flex',
46 flexDirection: 'column',
47 height: 'auto',
48
49 '@media(min-width: 800px)': {
50 flexDirection: 'row',
51 },
52 },
53 content: {
54 height: 'auto',
55 order: 1,
56
57 '@media(min-width: 800px)': {
58 order: 0,
59 },
60 },
61 image: {
62 display: 'block',
63 height: 150,
64 order: 0,
65 margin: [0, 'auto', 40, 'auto'],
66
67 '@media(min-width: 800px)': {
68 marginLeft: 40,
69 order: 1,
70 },
71 },
72};
73
74
75export default @injectSheet(styles) @observer class TeamDashboard extends Component {
76 static propTypes = {
77 isLoading: PropTypes.bool.isRequired,
78 userInfoRequestFailed: PropTypes.bool.isRequired,
79 retryUserInfoRequest: PropTypes.func.isRequired,
80 openTeamManagement: PropTypes.func.isRequired,
81 classes: PropTypes.object.isRequired,
82 };
83
84 static contextTypes = {
85 intl: intlShape,
86 };
87
88 render() {
89 const {
90 isLoading,
91 userInfoRequestFailed,
92 retryUserInfoRequest,
93 openTeamManagement,
94 classes,
95 } = this.props;
96 const { intl } = this.context;
97
98 return (
99 <div className="settings__main">
100 <div className="settings__header">
101 <span className="settings__header-item">
102 {intl.formatMessage(messages.headline)}
103 </span>
104 </div>
105 <div className="settings__body">
106 {isLoading && (
107 <Loader />
108 )}
109
110 {!isLoading && userInfoRequestFailed && (
111 <Infobox
112 icon="alert"
113 type="danger"
114 ctaLabel={intl.formatMessage(messages.tryReloadUserInfoRequest)}
115 ctaLoading={isLoading}
116 ctaOnClick={retryUserInfoRequest}
117 >
118 {intl.formatMessage(messages.userInfoRequestFailed)}
119 </Infobox>
120 )}
121
122 {!userInfoRequestFailed && (
123 <>
124 {!isLoading && (
125 <>
126 <PremiumFeatureContainer>
127 <>
128 <h1>{intl.formatMessage(messages.contentHeadline)}</h1>
129 <div className={classes.container}>
130 <div className={classes.content}>
131 <p>{intl.formatMessage(messages.intro)}</p>
132 <p>{intl.formatMessage(messages.copy)}</p>
133 </div>
134 <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Franz for Teams" />
135 </div>
136 <Button
137 label={intl.formatMessage(messages.manageButton)}
138 onClick={openTeamManagement}
139 className={classes.cta}
140 />
141 </>
142 </PremiumFeatureContainer>
143 </>
144 )}
145 </>
146 )}
147 </div>
148 <ReactTooltip place="right" type="dark" effect="solid" />
149 </div>
150 );
151 }
152}
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index 0e3ac6b10..a1a353e57 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -3,11 +3,10 @@ import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6 6import { Input } from '@meetfranz/forms';
7// import { Link } from 'react-router';
8 7
9import Form from '../../../lib/Form'; 8import Form from '../../../lib/Form';
10import Input from '../../ui/Input'; 9// import Input from '../../ui/Input';
11import Button from '../../ui/Button'; 10import Button from '../../ui/Button';
12import Radio from '../../ui/Radio'; 11import Radio from '../../ui/Radio';
13import Infobox from '../../ui/Infobox'; 12import Infobox from '../../ui/Infobox';
@@ -39,13 +38,12 @@ const messages = defineMessages({
39 }, 38 },
40}); 39});
41 40
42export default @observer class EditServiceForm extends Component { 41export default @observer class EditUserForm extends Component {
43 static propTypes = { 42 static propTypes = {
44 status: MobxPropTypes.observableArray.isRequired, 43 status: MobxPropTypes.observableArray.isRequired,
45 form: PropTypes.instanceOf(Form).isRequired, 44 form: PropTypes.instanceOf(Form).isRequired,
46 onSubmit: PropTypes.func.isRequired, 45 onSubmit: PropTypes.func.isRequired,
47 isSaving: PropTypes.bool.isRequired, 46 isSaving: PropTypes.bool.isRequired,
48 isEnterprise: PropTypes.bool.isRequired,
49 }; 47 };
50 48
51 static contextTypes = { 49 static contextTypes = {
@@ -68,7 +66,6 @@ export default @observer class EditServiceForm extends Component {
68 // user, 66 // user,
69 status, 67 status,
70 form, 68 form,
71 isEnterprise,
72 isSaving, 69 isSaving,
73 } = this.props; 70 } = this.props;
74 const { intl } = this.context; 71 const { intl } = this.context;
@@ -98,23 +95,21 @@ export default @observer class EditServiceForm extends Component {
98 )} 95 )}
99 <h2>{intl.formatMessage(messages.headlineAccount)}</h2> 96 <h2>{intl.formatMessage(messages.headlineAccount)}</h2>
100 <div className="grid__row"> 97 <div className="grid__row">
101 <Input field={form.$('firstname')} focus /> 98 <Input {...form.$('firstname').bind()} focus />
102 <Input field={form.$('lastname')} /> 99 <Input {...form.$('lastname').bind()} />
103 </div> 100 </div>
104 <Input field={form.$('email')} /> 101 <Input {...form.$('email').bind()} />
105 {!isEnterprise && ( 102 <Radio field={form.$('accountType')} />
106 <Radio field={form.$('accountType')} /> 103 {form.$('accountType').value === 'company' && (
107 )}
108 {!isEnterprise && form.$('accountType').value === 'company' && (
109 <Input field={form.$('organization')} /> 104 <Input field={form.$('organization')} />
110 )} 105 )}
111 <h2>{intl.formatMessage(messages.headlinePassword)}</h2> 106 <h2>{intl.formatMessage(messages.headlinePassword)}</h2>
112 <Input 107 <Input
113 field={form.$('oldPassword')} 108 {...form.$('oldPassword').bind()}
114 showPasswordToggle 109 showPasswordToggle
115 /> 110 />
116 <Input 111 <Input
117 field={form.$('newPassword')} 112 {...form.$('newPassword').bind()}
118 showPasswordToggle 113 showPasswordToggle
119 scorePassword 114 scorePassword
120 /> 115 />
diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js
index 90da8ddc3..50f1e0522 100644
--- a/src/components/subscription/SubscriptionForm.js
+++ b/src/components/subscription/SubscriptionForm.js
@@ -35,31 +35,33 @@ const messages = defineMessages({
35 id: 'subscription.includedFeatures', 35 id: 'subscription.includedFeatures',
36 defaultMessage: '!!!The Franz Premium Supporter Account includes', 36 defaultMessage: '!!!The Franz Premium Supporter Account includes',
37 }, 37 },
38 features: { 38 onpremise: {
39 onpremise: { 39 id: 'subscription.features.onpremise.mattermost',
40 id: 'subscription.features.onpremise.mattermost', 40 defaultMessage: '!!!Add on-premise/hosted services like Mattermost',
41 defaultMessage: '!!!Add on-premise/hosted services like Mattermost', 41 },
42 }, 42 noInterruptions: {
43 noInterruptions: { 43 id: 'subscription.features.noInterruptions',
44 id: 'subscription.features.noInterruptions', 44 defaultMessage: '!!!No app delays & nagging to upgrade license',
45 defaultMessage: '!!!No app delays & nagging to upgrade license', 45 },
46 }, 46 proxy: {
47 proxy: { 47 id: 'subscription.features.proxy',
48 id: 'subscription.features.proxy', 48 defaultMessage: '!!!Proxy support for services',
49 defaultMessage: '!!!Proxy support for services', 49 },
50 }, 50 spellchecker: {
51 spellchecker: { 51 id: 'subscription.features.spellchecker',
52 id: 'subscription.features.spellchecker', 52 defaultMessage: '!!!Support for Spellchecker',
53 defaultMessage: '!!!Support for Spellchecker', 53 },
54 }, 54 workspaces: {
55 ads: { 55 id: 'subscription.features.workspaces',
56 id: 'subscription.features.ads', 56 defaultMessage: '!!!Organize your services in workspaces',
57 defaultMessage: '!!!No ads, ever!', 57 },
58 }, 58 ads: {
59 comingSoon: { 59 id: 'subscription.features.ads',
60 id: 'subscription.features.comingSoon', 60 defaultMessage: '!!!No ads, ever!',
61 defaultMessage: '!!!coming soon', 61 },
62 }, 62 comingSoon: {
63 id: 'subscription.features.comingSoon',
64 defaultMessage: '!!!coming soon',
63 }, 65 },
64 euTaxInfo: { 66 euTaxInfo: {
65 id: 'subscription.euTaxInfo', 67 id: 'subscription.euTaxInfo',
@@ -85,7 +87,7 @@ export default @observer class SubscriptionForm extends Component {
85 showSkipOption: false, 87 showSkipOption: false,
86 skipAction: () => null, 88 skipAction: () => null,
87 skipButtonLabel: '', 89 skipButtonLabel: '',
88 } 90 };
89 91
90 static contextTypes = { 92 static contextTypes = {
91 intl: intlShape, 93 intl: intlShape,
@@ -162,18 +164,21 @@ export default @observer class SubscriptionForm extends Component {
162 </p> 164 </p>
163 <div className="subscription"> 165 <div className="subscription">
164 <ul className="subscription__premium-features"> 166 <ul className="subscription__premium-features">
165 <li>{intl.formatMessage(messages.features.onpremise)}</li> 167 <li>{intl.formatMessage(messages.onpremise)}</li>
168 <li>
169 {intl.formatMessage(messages.noInterruptions)}
170 </li>
166 <li> 171 <li>
167 {intl.formatMessage(messages.features.noInterruptions)} 172 {intl.formatMessage(messages.spellchecker)}
168 </li> 173 </li>
169 <li> 174 <li>
170 {intl.formatMessage(messages.features.spellchecker)} 175 {intl.formatMessage(messages.proxy)}
171 </li> 176 </li>
172 <li> 177 <li>
173 {intl.formatMessage(messages.features.proxy)} 178 {intl.formatMessage(messages.workspaces)}
174 </li> 179 </li>
175 <li> 180 <li>
176 {intl.formatMessage(messages.features.ads)} 181 {intl.formatMessage(messages.ads)}
177 </li> 182 </li>
178 </ul> 183 </ul>
179 </div> 184 </div>
diff --git a/src/components/subscription/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js
index b5d7c4b2d..0f6f0260f 100644
--- a/src/components/subscription/SubscriptionPopup.js
+++ b/src/components/subscription/SubscriptionPopup.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import Webview from 'react-electron-web-view'; 5import Webview from 'react-electron-web-view';
6import ms from 'ms';
6 7
7import Button from '../ui/Button'; 8import Button from '../ui/Button';
8 9
@@ -42,7 +43,7 @@ export default @observer class SubscriptionPopup extends Component {
42 43
43 setTimeout(() => { 44 setTimeout(() => {
44 this.props.closeWindow(); 45 this.props.closeWindow();
45 }, 4000); 46 }, ms('4s'));
46 } 47 }
47 48
48 render() { 49 render() {
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js
index 61053f6d1..b0c7fed7b 100644
--- a/src/components/ui/AppLoader/index.js
+++ b/src/components/ui/AppLoader/index.js
@@ -23,11 +23,11 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
23 static propTypes = { 23 static propTypes = {
24 classes: PropTypes.object.isRequired, 24 classes: PropTypes.object.isRequired,
25 theme: PropTypes.object.isRequired, 25 theme: PropTypes.object.isRequired,
26 } 26 };
27 27
28 state = { 28 state = {
29 step: 0, 29 step: 0,
30 } 30 };
31 31
32 interval = null; 32 interval = null;
33 33
diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js
index 6ecf4d395..06dab1eb6 100644
--- a/src/components/ui/FullscreenLoader/index.js
+++ b/src/components/ui/FullscreenLoader/index.js
@@ -16,13 +16,13 @@ export default @observer @withTheme @injectSheet(styles) class FullscreenLoader
16 theme: PropTypes.object.isRequired, 16 theme: PropTypes.object.isRequired,
17 spinnerColor: PropTypes.string, 17 spinnerColor: PropTypes.string,
18 children: PropTypes.node, 18 children: PropTypes.node,
19 } 19 };
20 20
21 static defaultProps = { 21 static defaultProps = {
22 className: null, 22 className: null,
23 spinnerColor: null, 23 spinnerColor: null,
24 children: null, 24 children: null,
25 } 25 };
26 26
27 render() { 27 render() {
28 const { 28 const {
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js
index a33c6474a..0917ee9f0 100644
--- a/src/components/ui/Infobox.js
+++ b/src/components/ui/Infobox.js
@@ -13,6 +13,8 @@ export default @observer class Infobox extends Component {
13 ctaLabel: PropTypes.string, 13 ctaLabel: PropTypes.string,
14 ctaLoading: PropTypes.bool, 14 ctaLoading: PropTypes.bool,
15 dismissable: PropTypes.bool, 15 dismissable: PropTypes.bool,
16 onDismiss: PropTypes.func,
17 onSeen: PropTypes.func,
16 }; 18 };
17 19
18 static defaultProps = { 20 static defaultProps = {
@@ -22,12 +24,19 @@ export default @observer class Infobox extends Component {
22 ctaOnClick: () => null, 24 ctaOnClick: () => null,
23 ctaLabel: '', 25 ctaLabel: '',
24 ctaLoading: false, 26 ctaLoading: false,
27 onDismiss: () => null,
28 onSeen: () => null,
25 }; 29 };
26 30
27 state = { 31 state = {
28 dismissed: false, 32 dismissed: false,
29 }; 33 };
30 34
35 componentDidMount() {
36 const { onSeen } = this.props;
37 if (onSeen) onSeen();
38 }
39
31 render() { 40 render() {
32 const { 41 const {
33 children, 42 children,
@@ -37,6 +46,7 @@ export default @observer class Infobox extends Component {
37 ctaLoading, 46 ctaLoading,
38 ctaOnClick, 47 ctaOnClick,
39 dismissable, 48 dismissable,
49 onDismiss,
40 } = this.props; 50 } = this.props;
41 51
42 if (this.state.dismissed) { 52 if (this.state.dismissed) {
@@ -76,9 +86,10 @@ export default @observer class Infobox extends Component {
76 {dismissable && ( 86 {dismissable && (
77 <button 87 <button
78 type="button" 88 type="button"
79 onClick={() => this.setState({ 89 onClick={() => {
80 dismissed: true, 90 this.setState({ dismissed: true });
81 })} 91 if (onDismiss) onDismiss();
92 }}
82 className="infobox__delete mdi mdi-close" 93 className="infobox__delete mdi mdi-close"
83 /> 94 />
84 )} 95 )}
diff --git a/src/components/ui/Modal/index.js b/src/components/ui/Modal/index.js
index d84e4c713..0b7154760 100644
--- a/src/components/ui/Modal/index.js
+++ b/src/components/ui/Modal/index.js
@@ -3,9 +3,12 @@ import ReactModal from 'react-modal';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import injectCSS from 'react-jss'; 5import injectCSS from 'react-jss';
6import { Icon } from '@meetfranz/ui';
6 7
7import styles from './styles'; 8import styles from './styles';
8 9
10// ReactModal.setAppElement('#root');
11
9export default @injectCSS(styles) class Modal extends Component { 12export default @injectCSS(styles) class Modal extends Component {
10 static propTypes = { 13 static propTypes = {
11 children: PropTypes.node.isRequired, 14 children: PropTypes.node.isRequired,
@@ -14,11 +17,15 @@ export default @injectCSS(styles) class Modal extends Component {
14 isOpen: PropTypes.bool.isRequired, 17 isOpen: PropTypes.bool.isRequired,
15 portal: PropTypes.string, 18 portal: PropTypes.string,
16 close: PropTypes.func.isRequired, 19 close: PropTypes.func.isRequired,
20 shouldCloseOnOverlayClick: PropTypes.bool,
21 showClose: PropTypes.bool,
17 } 22 }
18 23
19 static defaultProps = { 24 static defaultProps = {
20 className: null, 25 className: null,
21 portal: 'modal-portal', 26 portal: 'modal-portal',
27 shouldCloseOnOverlayClick: false,
28 showClose: true,
22 } 29 }
23 30
24 render() { 31 render() {
@@ -29,6 +36,8 @@ export default @injectCSS(styles) class Modal extends Component {
29 isOpen, 36 isOpen,
30 portal, 37 portal,
31 close, 38 close,
39 shouldCloseOnOverlayClick,
40 showClose,
32 } = this.props; 41 } = this.props;
33 42
34 return ( 43 return (
@@ -42,14 +51,17 @@ export default @injectCSS(styles) class Modal extends Component {
42 overlayClassName={classes.overlay} 51 overlayClassName={classes.overlay}
43 portal={portal} 52 portal={portal}
44 onRequestClose={close} 53 onRequestClose={close}
54 shouldCloseOnOverlayClick={shouldCloseOnOverlayClick}
45 > 55 >
46 {/* <button 56 {showClose && close && (
47 type="button" 57 <button
48 className={classnames({ 58 type="button"
49 [`${classes.close}`]: true, 59 className={classes.close}
50 'mdi mdi-close': true, 60 onClick={close}
51 })} 61 >
52 /> */} 62 <Icon icon="mdiClose" size={1.5} />
63 </button>
64 )}
53 <div className={classes.content}> 65 <div className={classes.content}>
54 {children} 66 {children}
55 </div> 67 </div>
diff --git a/src/components/ui/Modal/styles.js b/src/components/ui/Modal/styles.js
index 56fecbf55..49b970c97 100644
--- a/src/components/ui/Modal/styles.js
+++ b/src/components/ui/Modal/styles.js
@@ -28,5 +28,6 @@ export default theme => ({
28 position: 'absolute', 28 position: 'absolute',
29 top: 0, 29 top: 0,
30 right: 0, 30 right: 0,
31 padding: 20,
31 }, 32 },
32}); 33});
diff --git a/src/components/ui/PremiumFeatureContainer/index.js b/src/components/ui/PremiumFeatureContainer/index.js
index 67cd6af0b..3c1e0fac3 100644
--- a/src/components/ui/PremiumFeatureContainer/index.js
+++ b/src/components/ui/PremiumFeatureContainer/index.js
@@ -9,6 +9,7 @@ import { oneOrManyChildElements } from '../../../prop-types';
9import UserStore from '../../../stores/UserStore'; 9import UserStore from '../../../stores/UserStore';
10 10
11import styles from './styles'; 11import styles from './styles';
12import { gaEvent } from '../../../lib/analytics';
12 13
13const messages = defineMessages({ 14const messages = defineMessages({
14 action: { 15 action: {
@@ -17,14 +18,21 @@ const messages = defineMessages({
17 }, 18 },
18}); 19});
19 20
20export default @inject('stores', 'actions') @injectSheet(styles) @observer class PremiumFeatureContainer extends Component { 21@inject('stores', 'actions') @injectSheet(styles) @observer
22class PremiumFeatureContainer extends Component {
21 static propTypes = { 23 static propTypes = {
22 classes: PropTypes.object.isRequired, 24 classes: PropTypes.object.isRequired,
23 condition: PropTypes.bool, 25 condition: PropTypes.bool,
26 gaEventInfo: PropTypes.shape({
27 category: PropTypes.string.isRequired,
28 event: PropTypes.string.isRequired,
29 label: PropTypes.string,
30 }),
24 }; 31 };
25 32
26 static defaultProps = { 33 static defaultProps = {
27 condition: true, 34 condition: true,
35 gaEventInfo: null,
28 }; 36 };
29 37
30 static contextTypes = { 38 static contextTypes = {
@@ -38,6 +46,7 @@ export default @inject('stores', 'actions') @injectSheet(styles) @observer class
38 actions, 46 actions,
39 condition, 47 condition,
40 stores, 48 stores,
49 gaEventInfo,
41 } = this.props; 50 } = this.props;
42 51
43 const { intl } = this.context; 52 const { intl } = this.context;
@@ -49,7 +58,13 @@ export default @inject('stores', 'actions') @injectSheet(styles) @observer class
49 <button 58 <button
50 className={classes.actionButton} 59 className={classes.actionButton}
51 type="button" 60 type="button"
52 onClick={() => actions.ui.openSettings({ path: 'user' })} 61 onClick={() => {
62 actions.ui.openSettings({ path: 'user' });
63 if (gaEventInfo) {
64 const { category, event, label } = gaEventInfo;
65 gaEvent(category, event, label);
66 }
67 }}
53 > 68 >
54 {intl.formatMessage(messages.action)} 69 {intl.formatMessage(messages.action)}
55 </button> 70 </button>
@@ -73,3 +88,5 @@ PremiumFeatureContainer.wrappedComponent.propTypes = {
73 }).isRequired, 88 }).isRequired,
74 }).isRequired, 89 }).isRequired,
75}; 90};
91
92export default PremiumFeatureContainer;
diff --git a/src/components/ui/PremiumFeatureContainer/styles.js b/src/components/ui/PremiumFeatureContainer/styles.js
index 81d6666c6..41881e044 100644
--- a/src/components/ui/PremiumFeatureContainer/styles.js
+++ b/src/components/ui/PremiumFeatureContainer/styles.js
@@ -6,6 +6,7 @@ export default theme => ({
6 padding: 20, 6 padding: 20,
7 'border-radius': theme.borderRadius, 7 'border-radius': theme.borderRadius,
8 pointerEvents: 'none', 8 pointerEvents: 'none',
9 height: 'auto',
9 }, 10 },
10 titleContainer: { 11 titleContainer: {
11 display: 'flex', 12 display: 'flex',
@@ -19,14 +20,14 @@ export default theme => ({
19 color: theme.colorSubscriptionContainerActionButtonColor, 20 color: theme.colorSubscriptionContainerActionButtonColor,
20 'margin-left': 'auto', 21 'margin-left': 'auto',
21 'border-radius': theme.borderRadiusSmall, 22 'border-radius': theme.borderRadiusSmall,
22 padding: [2, 4], 23 padding: [4, 8],
23 'font-size': 12, 24 'font-size': 12,
24 pointerEvents: 'initial', 25 pointerEvents: 'initial',
25 }, 26 },
26 content: { 27 content: {
27 opacity: 0.5, 28 opacity: 0.5,
28 'margin-top': 20, 29 'margin-top': 20,
29 '& :last-child': { 30 '& > :last-child': {
30 'margin-bottom': 0, 31 'margin-bottom': 0,
31 }, 32 },
32 }, 33 },
diff --git a/src/components/ui/ServiceIcon.js b/src/components/ui/ServiceIcon.js
new file mode 100644
index 000000000..0b9155a4e
--- /dev/null
+++ b/src/components/ui/ServiceIcon.js
@@ -0,0 +1,67 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import classnames from 'classnames';
6
7import ServiceModel from '../../models/Service';
8
9const styles = theme => ({
10 root: {
11 height: 'auto',
12 },
13 icon: {
14 width: theme.serviceIcon.width,
15 },
16 isCustomIcon: {
17 width: theme.serviceIcon.isCustom.width,
18 border: theme.serviceIcon.isCustom.border,
19 borderRadius: theme.serviceIcon.isCustom.borderRadius,
20 },
21 isDisabled: {
22 filter: 'grayscale(100%)',
23 opacity: '.5',
24 },
25});
26
27@injectSheet(styles) @observer
28class ServiceIcon extends Component {
29 static propTypes = {
30 classes: PropTypes.object.isRequired,
31 service: PropTypes.instanceOf(ServiceModel).isRequired,
32 className: PropTypes.string,
33 };
34
35 static defaultProps = {
36 className: '',
37 };
38
39 render() {
40 const {
41 classes,
42 className,
43 service,
44 } = this.props;
45
46 return (
47 <div
48 className={classnames([
49 classes.root,
50 className,
51 ])}
52 >
53 <img
54 src={service.icon}
55 className={classnames([
56 classes.icon,
57 service.isEnabled ? null : classes.isDisabled,
58 service.hasCustomIcon ? classes.isCustomIcon : null,
59 ])}
60 alt=""
61 />
62 </div>
63 );
64 }
65}
66
67export default ServiceIcon;
diff --git a/src/components/ui/WebviewLoader/index.js b/src/components/ui/WebviewLoader/index.js
index 3a3dbbe49..58b6b6f1b 100644
--- a/src/components/ui/WebviewLoader/index.js
+++ b/src/components/ui/WebviewLoader/index.js
@@ -2,23 +2,35 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { defineMessages, intlShape } from 'react-intl';
5 6
6import FullscreenLoader from '../FullscreenLoader'; 7import FullscreenLoader from '../FullscreenLoader';
7
8import styles from './styles'; 8import styles from './styles';
9 9
10const messages = defineMessages({
11 loading: {
12 id: 'service.webviewLoader.loading',
13 defaultMessage: '!!!Loading',
14 },
15});
16
10export default @observer @injectSheet(styles) class WebviewLoader extends Component { 17export default @observer @injectSheet(styles) class WebviewLoader extends Component {
11 static propTypes = { 18 static propTypes = {
12 name: PropTypes.string.isRequired, 19 name: PropTypes.string.isRequired,
13 classes: PropTypes.object.isRequired, 20 classes: PropTypes.object.isRequired,
14 } 21 };
22
23 static contextTypes = {
24 intl: intlShape,
25 };
15 26
16 render() { 27 render() {
17 const { classes, name } = this.props; 28 const { classes, name } = this.props;
29 const { intl } = this.context;
18 return ( 30 return (
19 <FullscreenLoader 31 <FullscreenLoader
20 className={classes.component} 32 className={classes.component}
21 title={`Loading ${name}`} 33 title={`${intl.formatMessage(messages.loading)} ${name}`}
22 /> 34 />
23 ); 35 );
24 } 36 }
diff --git a/src/config.js b/src/config.js
index 789ddd1a0..5bc318545 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,14 +1,30 @@
1import electron from 'electron'; 1import electron from 'electron';
2import path from 'path'; 2import path from 'path';
3import isDevMode from 'electron-is-dev';
4import ms from 'ms';
5
6import { asarPath } from './helpers/asar-helpers';
3 7
4const app = process.type === 'renderer' ? electron.remote.app : electron.app; 8const app = process.type === 'renderer' ? electron.remote.app : electron.app;
5const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences; 9const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences;
6 10
7export const CHECK_INTERVAL = 1000 * 3600; // How often should we perform checks 11export const CHECK_INTERVAL = ms('1h'); // How often should we perform checks
12
8export const LOCAL_API = 'http://localhost:3000'; 13export const LOCAL_API = 'http://localhost:3000';
9export const DEV_API = 'https://dev.franzinfra.com'; 14export const DEV_API = 'https://dev.franzinfra.com';
10export const LIVE_API = 'https://api.franzinfra.com'; 15export const LIVE_API = 'https://api.franzinfra.com';
11export const GA_ID = 'UA-74126766-10'; 16
17export const LOCAL_WS_API = 'ws://localhost:3000';
18export const DEV_WS_API = 'wss://dev.franzinfra.com';
19export const LIVE_WS_API = 'wss://api.franzinfra.com';
20
21export const LOCAL_API_WEBSITE = 'http://localhost:3333';
22export const DEV_API_WEBSITE = 'https://meetfranz.com';
23export const LIVE_API_WEBSITE = 'https://meetfranz.com';
24
25export const STATS_API = 'https://stats.franzinfra.com';
26
27export const GA_ID = !isDevMode ? 'UA-74126766-10' : 'UA-74126766-12';
12 28
13export const DEFAULT_APP_SETTINGS = { 29export const DEFAULT_APP_SETTINGS = {
14 autoLaunchInBackground: false, 30 autoLaunchInBackground: false,
@@ -32,11 +48,14 @@ export const DEFAULT_FEATURES_CONFIG = {
32 isSpellcheckerPremiumFeature: false, 48 isSpellcheckerPremiumFeature: false,
33 needToWaitToProceed: false, 49 needToWaitToProceed: false,
34 needToWaitToProceedConfig: { 50 needToWaitToProceedConfig: {
35 delayOffset: 3600000, 51 delayOffset: ms('1h'),
36 wait: 10000, 52 wait: ms('10s'),
37 }, 53 },
38 isServiceProxyEnabled: false, 54 isServiceProxyEnabled: false,
39 isServiceProxyPremiumFeature: true, 55 isServiceProxyPremiumFeature: true,
56 isAnnouncementsEnabled: true,
57 isWorkspacePremiumFeature: true,
58 isWorkspaceEnabled: false,
40}; 59};
41 60
42export const DEFAULT_WINDOW_OPTIONS = { 61export const DEFAULT_WINDOW_OPTIONS = {
@@ -57,4 +76,10 @@ export const FILE_SYSTEM_SETTINGS_TYPES = [
57export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config'); 76export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config');
58 77
59// Replacing app.asar is not beautiful but unforunately necessary 78// Replacing app.asar is not beautiful but unforunately necessary
60export const DICTIONARY_PATH = path.join(__dirname, 'dictionaries').replace('app.asar', 'app.asar.unpacked'); 79export const DICTIONARY_PATH = asarPath(path.join(__dirname, 'dictionaries'));
80
81export const ALLOWED_PROTOCOLS = [
82 'https:',
83 'http:',
84 'ftp:',
85];
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js
index 762929dc6..e63f40c06 100644
--- a/src/containers/auth/AuthLayoutContainer.js
+++ b/src/containers/auth/AuthLayoutContainer.js
@@ -1,6 +1,8 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { ThemeProvider } from 'react-jss';
5import { theme } from '@meetfranz/theme';
4 6
5import AuthLayout from '../../components/auth/AuthLayout'; 7import AuthLayout from '../../components/auth/AuthLayout';
6import AppStore from '../../stores/AppStore'; 8import AppStore from '../../stores/AppStore';
@@ -21,30 +23,38 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
21 const { 23 const {
22 stores, actions, children, location, 24 stores, actions, children, location,
23 } = this.props; 25 } = this.props;
24 const { app, features, globalError } = stores; 26 const {
27 app, features, globalError, settings,
28 } = stores;
25 29
26 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting 30 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting
27 && !features.defaultFeaturesRequest.wasExecuted; 31 && !features.defaultFeaturesRequest.wasExecuted;
28 32
33 const themeType = theme(settings.app.darkMode ? 'dark' : 'default');
34
29 if (isLoadingBaseFeatures) { 35 if (isLoadingBaseFeatures) {
30 return ( 36 return (
31 <AppLoader /> 37 <ThemeProvider theme={theme(themeType)}>
38 <AppLoader />
39 </ThemeProvider>
32 ); 40 );
33 } 41 }
34 42
35 return ( 43 return (
36 <AuthLayout 44 <ThemeProvider theme={theme(themeType)}>
37 error={globalError.response} 45 <AuthLayout
38 pathname={location.pathname} 46 error={globalError.response}
39 isOnline={app.isOnline} 47 pathname={location.pathname}
40 isAPIHealthy={!app.healthCheckRequest.isError} 48 isOnline={app.isOnline}
41 retryHealthCheck={actions.app.healthCheck} 49 isAPIHealthy={!app.healthCheckRequest.isError}
42 isHealthCheckLoading={app.healthCheckRequest.isExecuting} 50 retryHealthCheck={actions.app.healthCheck}
43 isFullScreen={app.isFullScreen} 51 isHealthCheckLoading={app.healthCheckRequest.isExecuting}
44 darkMode={app.isSystemDarkModeEnabled} 52 isFullScreen={app.isFullScreen}
45 > 53 darkMode={app.isSystemDarkModeEnabled}
46 {children} 54 >
47 </AuthLayout> 55 {children}
56 </AuthLayout>
57 </ThemeProvider>
48 ); 58 );
49 } 59 }
50} 60}
diff --git a/src/containers/auth/ImportScreen.js b/src/containers/auth/ImportScreen.js
index fc46f8b54..4a93891d6 100644
--- a/src/containers/auth/ImportScreen.js
+++ b/src/containers/auth/ImportScreen.js
@@ -3,13 +3,8 @@ import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import Import from '../../components/auth/Import'; 4import Import from '../../components/auth/Import';
5import UserStore from '../../stores/UserStore'; 5import UserStore from '../../stores/UserStore';
6import { gaPage } from '../../lib/analytics';
7 6
8export default @inject('stores', 'actions') @observer class ImportScreen extends Component { 7export default @inject('stores', 'actions') @observer class ImportScreen extends Component {
9 componentDidMount() {
10 gaPage('Auth/Import');
11 }
12
13 render() { 8 render() {
14 const { actions, stores } = this.props; 9 const { actions, stores } = this.props;
15 10
diff --git a/src/containers/auth/InviteScreen.js b/src/containers/auth/InviteScreen.js
index 26bf97038..66afaf7e1 100644
--- a/src/containers/auth/InviteScreen.js
+++ b/src/containers/auth/InviteScreen.js
@@ -2,13 +2,8 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import Invite from '../../components/auth/Invite'; 4import Invite from '../../components/auth/Invite';
5import { gaPage } from '../../lib/analytics';
6 5
7export default @inject('stores', 'actions') @observer class InviteScreen extends Component { 6export default @inject('stores', 'actions') @observer class InviteScreen extends Component {
8 componentDidMount() {
9 gaPage('Auth/Invite');
10 }
11
12 render() { 7 render() {
13 const { actions } = this.props; 8 const { actions } = this.props;
14 9
diff --git a/src/containers/auth/LoginScreen.js b/src/containers/auth/LoginScreen.js
index 865bd38f8..e5ee10785 100644
--- a/src/containers/auth/LoginScreen.js
+++ b/src/containers/auth/LoginScreen.js
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import Login from '../../components/auth/Login'; 4import Login from '../../components/auth/Login';
5import UserStore from '../../stores/UserStore'; 5import UserStore from '../../stores/UserStore';
6import { gaPage } from '../../lib/analytics';
7 6
8import { globalError as globalErrorPropType } from '../../prop-types'; 7import { globalError as globalErrorPropType } from '../../prop-types';
9 8
@@ -12,10 +11,6 @@ export default @inject('stores', 'actions') @observer class LoginScreen extends
12 error: globalErrorPropType.isRequired, 11 error: globalErrorPropType.isRequired,
13 }; 12 };
14 13
15 componentDidMount() {
16 gaPage('Auth/Login');
17 }
18
19 render() { 14 render() {
20 const { actions, stores, error } = this.props; 15 const { actions, stores, error } = this.props;
21 return ( 16 return (
diff --git a/src/containers/auth/PasswordScreen.js b/src/containers/auth/PasswordScreen.js
index 236fd2031..5b238860e 100644
--- a/src/containers/auth/PasswordScreen.js
+++ b/src/containers/auth/PasswordScreen.js
@@ -3,13 +3,8 @@ import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import Password from '../../components/auth/Password'; 4import Password from '../../components/auth/Password';
5import UserStore from '../../stores/UserStore'; 5import UserStore from '../../stores/UserStore';
6import { gaPage } from '../../lib/analytics';
7 6
8export default @inject('stores', 'actions') @observer class PasswordScreen extends Component { 7export default @inject('stores', 'actions') @observer class PasswordScreen extends Component {
9 componentDidMount() {
10 gaPage('Auth/Password Retrieve');
11 }
12
13 render() { 8 render() {
14 const { actions, stores } = this.props; 9 const { actions, stores } = this.props;
15 10
diff --git a/src/containers/auth/PricingScreen.js b/src/containers/auth/PricingScreen.js
index 34b512e15..8d179a170 100644
--- a/src/containers/auth/PricingScreen.js
+++ b/src/containers/auth/PricingScreen.js
@@ -6,7 +6,6 @@ import { RouterStore } from 'mobx-react-router';
6import Pricing from '../../components/auth/Pricing'; 6import Pricing from '../../components/auth/Pricing';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
8import PaymentStore from '../../stores/PaymentStore'; 8import PaymentStore from '../../stores/PaymentStore';
9import { gaPage } from '../../lib/analytics';
10 9
11import { globalError as globalErrorPropType } from '../../prop-types'; 10import { globalError as globalErrorPropType } from '../../prop-types';
12 11
@@ -15,10 +14,6 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend
15 error: globalErrorPropType.isRequired, 14 error: globalErrorPropType.isRequired,
16 }; 15 };
17 16
18 componentDidMount() {
19 gaPage('Auth/Pricing');
20 }
21
22 render() { 17 render() {
23 const { actions, stores, error } = this.props; 18 const { actions, stores, error } = this.props;
24 19
diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js
index caf75de90..efc7ea4c1 100644
--- a/src/containers/auth/SignupScreen.js
+++ b/src/containers/auth/SignupScreen.js
@@ -4,7 +4,6 @@ import { inject, observer } from 'mobx-react';
4 4
5import Signup from '../../components/auth/Signup'; 5import Signup from '../../components/auth/Signup';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import { gaPage } from '../../lib/analytics';
8 7
9import { globalError as globalErrorPropType } from '../../prop-types'; 8import { globalError as globalErrorPropType } from '../../prop-types';
10 9
@@ -13,10 +12,6 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
13 error: globalErrorPropType.isRequired, 12 error: globalErrorPropType.isRequired,
14 }; 13 };
15 14
16 componentDidMount() {
17 gaPage('Auth/Signup');
18 }
19
20 render() { 15 render() {
21 const { actions, stores, error } = this.props; 16 const { actions, stores, error } = this.props;
22 return ( 17 return (
diff --git a/src/containers/auth/WelcomeScreen.js b/src/containers/auth/WelcomeScreen.js
index 2c120f81c..75182345a 100644
--- a/src/containers/auth/WelcomeScreen.js
+++ b/src/containers/auth/WelcomeScreen.js
@@ -5,13 +5,8 @@ import { inject, observer } from 'mobx-react';
5import Welcome from '../../components/auth/Welcome'; 5import Welcome from '../../components/auth/Welcome';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; 7import RecipePreviewsStore from '../../stores/RecipePreviewsStore';
8import { gaPage } from '../../lib/analytics';
9 8
10export default @inject('stores', 'actions') @observer class LoginScreen extends Component { 9export default @inject('stores', 'actions') @observer class LoginScreen extends Component {
11 componentDidMount() {
12 gaPage('Auth/Welcome');
13 }
14
15 render() { 10 render() {
16 const { user, recipePreviews } = this.props.stores; 11 const { user, recipePreviews } = this.props.stores;
17 12
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 749912c59..d2891a6a4 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -20,6 +20,10 @@ import Services from '../../components/services/content/Services';
20import AppLoader from '../../components/ui/AppLoader'; 20import AppLoader from '../../components/ui/AppLoader';
21 21
22import { state as delayAppState } from '../../features/delayApp'; 22import { state as delayAppState } from '../../features/delayApp';
23import { workspaceActions } from '../../features/workspaces/actions';
24import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer';
25import { workspaceStore } from '../../features/workspaces';
26import { announcementsStore } from '../../features/announcements';
23 27
24export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { 28export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component {
25 static defaultProps = { 29 static defaultProps = {
@@ -42,6 +46,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
42 setActive, 46 setActive,
43 handleIPCMessage, 47 handleIPCMessage,
44 setWebviewReference, 48 setWebviewReference,
49 detachService,
45 openWindow, 50 openWindow,
46 reorder, 51 reorder,
47 reload, 52 reload,
@@ -81,6 +86,15 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
81 ); 86 );
82 } 87 }
83 88
89 const workspacesDrawer = (
90 <WorkspaceDrawer
91 getServicesForWorkspace={workspace => (
92 workspace ? workspaceStore.getWorkspaceServices(workspace).map(s => s.name) : services.all.map(s => s.name)
93 )}
94 onUpgradeAccountClick={() => openSettings({ path: 'user' })}
95 />
96 );
97
84 const sidebar = ( 98 const sidebar = (
85 <Sidebar 99 <Sidebar
86 services={services.allDisplayed} 100 services={services.allDisplayed}
@@ -95,6 +109,8 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
95 deleteService={deleteService} 109 deleteService={deleteService}
96 updateService={updateService} 110 updateService={updateService}
97 toggleMuteApp={toggleMuteApp} 111 toggleMuteApp={toggleMuteApp}
112 toggleWorkspaceDrawer={workspaceActions.toggleWorkspaceDrawer}
113 isWorkspaceDrawerOpen={workspaceStore.isWorkspaceDrawerOpen}
98 showMessageBadgeWhenMutedSetting={settings.all.app.showMessageBadgeWhenMuted} 114 showMessageBadgeWhenMutedSetting={settings.all.app.showMessageBadgeWhenMuted}
99 showMessageBadgesEvenWhenMuted={ui.showMessageBadgesEvenWhenMuted} 115 showMessageBadgesEvenWhenMuted={ui.showMessageBadgesEvenWhenMuted}
100 /> 116 />
@@ -105,6 +121,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
105 services={services.allDisplayedUnordered} 121 services={services.allDisplayedUnordered}
106 handleIPCMessage={handleIPCMessage} 122 handleIPCMessage={handleIPCMessage}
107 setWebviewReference={setWebviewReference} 123 setWebviewReference={setWebviewReference}
124 detachService={detachService}
108 openWindow={openWindow} 125 openWindow={openWindow}
109 reload={reload} 126 reload={reload}
110 openSettings={openSettings} 127 openSettings={openSettings}
@@ -119,7 +136,9 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
119 isOnline={app.isOnline} 136 isOnline={app.isOnline}
120 showServicesUpdatedInfoBar={ui.showServicesUpdatedInfoBar} 137 showServicesUpdatedInfoBar={ui.showServicesUpdatedInfoBar}
121 appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED} 138 appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED}
139 nextAppReleaseVersion={app.nextAppReleaseVersion}
122 sidebar={sidebar} 140 sidebar={sidebar}
141 workspacesDrawer={workspacesDrawer}
123 services={servicesContainer} 142 services={servicesContainer}
124 news={news.latest} 143 news={news.latest}
125 removeNewsItem={hide} 144 removeNewsItem={hide}
@@ -132,6 +151,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
132 areRequiredRequestsLoading={requests.areRequiredRequestsLoading} 151 areRequiredRequestsLoading={requests.areRequiredRequestsLoading}
133 darkMode={settings.all.app.darkMode} 152 darkMode={settings.all.app.darkMode}
134 isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} 153 isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible}
154 isAnnouncementVisible={announcementsStore.isAnnouncementVisible}
135 > 155 >
136 {React.Children.count(children) > 0 ? children : null} 156 {React.Children.count(children) > 0 ? children : null}
137 </AppLayout> 157 </AppLayout>
@@ -160,6 +180,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
160 toggleAudio: PropTypes.func.isRequired, 180 toggleAudio: PropTypes.func.isRequired,
161 handleIPCMessage: PropTypes.func.isRequired, 181 handleIPCMessage: PropTypes.func.isRequired,
162 setWebviewReference: PropTypes.func.isRequired, 182 setWebviewReference: PropTypes.func.isRequired,
183 detachService: PropTypes.func.isRequired,
163 openWindow: PropTypes.func.isRequired, 184 openWindow: PropTypes.func.isRequired,
164 reloadUpdatedServices: PropTypes.func.isRequired, 185 reloadUpdatedServices: PropTypes.func.isRequired,
165 updateService: PropTypes.func.isRequired, 186 updateService: PropTypes.func.isRequired,
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index d681d5226..b3f967353 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -1,4 +1,3 @@
1import { remote } from 'electron';
2import React, { Component } from 'react'; 1import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
4import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
@@ -6,92 +5,55 @@ import { inject, observer } from 'mobx-react';
6import PaymentStore from '../../stores/PaymentStore'; 5import PaymentStore from '../../stores/PaymentStore';
7import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
8import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
9import { gaPage } from '../../lib/analytics';
10 8
11import AccountDashboard from '../../components/settings/account/AccountDashboard'; 9import AccountDashboard from '../../components/settings/account/AccountDashboard';
12import ErrorBoundary from '../../components/util/ErrorBoundary'; 10import ErrorBoundary from '../../components/util/ErrorBoundary';
13 11import { WEBSITE } from '../../environment';
14const { BrowserWindow } = remote;
15 12
16export default @inject('stores', 'actions') @observer class AccountScreen extends Component { 13export default @inject('stores', 'actions') @observer class AccountScreen extends Component {
17 componentWillMount() {
18 const {
19 user,
20 } = this.props.stores;
21
22 user.getUserInfoRequest.invalidate({ immediately: true });
23 }
24
25 componentDidMount() {
26 gaPage('Settings/Account Dashboard');
27 }
28
29 onCloseWindow() { 14 onCloseWindow() {
30 const { user, payment } = this.props.stores; 15 const { user } = this.props.stores;
31 user.getUserInfoRequest.invalidate({ immediately: true }); 16 user.getUserInfoRequest.invalidate({ immediately: true });
32 payment.ordersDataRequest.invalidate({ immediately: true });
33 } 17 }
34 18
35 reloadData() { 19 reloadData() {
36 const { user, payment } = this.props.stores; 20 const { user, payment } = this.props.stores;
37 21
38 user.getUserInfoRequest.reload(); 22 user.getUserInfoRequest.reload();
39 payment.ordersDataRequest.reload();
40 payment.plansRequest.reload(); 23 payment.plansRequest.reload();
41 } 24 }
42 25
43 async handlePaymentDashboard() { 26 handleWebsiteLink(route) {
44 const { actions, stores } = this.props; 27 const { actions, stores } = this.props;
45 28
46 actions.payment.createDashboardUrl(); 29 const url = `${WEBSITE}${route}?authToken=${stores.user.authToken}&utm_source=app&utm_medium=account_dashboard`;
47 30 console.log(url);
48 const dashboard = await stores.payment.createDashboardUrlRequest;
49
50 if (dashboard.url) {
51 const paymentWindow = new BrowserWindow({
52 title: '🔒 Franz Subscription Dashboard',
53 parent: remote.getCurrentWindow(),
54 modal: false,
55 width: 900,
56 minWidth: 600,
57 webPreferences: {
58 nodeIntegration: false,
59 },
60 });
61 paymentWindow.loadURL(dashboard.url);
62 31
63 paymentWindow.on('closed', () => { 32 actions.app.openExternalUrl({ url });
64 this.onCloseWindow();
65 });
66 }
67 } 33 }
68 34
69 render() { 35 render() {
70 const { user, payment } = this.props.stores; 36 const { user, payment } = this.props.stores;
71 const { openExternalUrl } = this.props.actions.app;
72 const { user: userActions } = this.props.actions; 37 const { user: userActions } = this.props.actions;
73 38
74 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting; 39 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting;
75 const isLoadingOrdersInfo = payment.ordersDataRequest.isExecuting;
76 const isLoadingPlans = payment.plansRequest.isExecuting; 40 const isLoadingPlans = payment.plansRequest.isExecuting;
77 41
78 return ( 42 return (
79 <ErrorBoundary> 43 <ErrorBoundary>
80 <AccountDashboard 44 <AccountDashboard
81 user={user.data} 45 user={user.data}
82 orders={payment.orders}
83 isLoading={isLoadingUserInfo} 46 isLoading={isLoadingUserInfo}
84 isLoadingOrdersInfo={isLoadingOrdersInfo}
85 isLoadingPlans={isLoadingPlans} 47 isLoadingPlans={isLoadingPlans}
86 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} 48 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError}
87 retryUserInfoRequest={() => this.reloadData()} 49 retryUserInfoRequest={() => this.reloadData()}
88 isCreatingPaymentDashboardUrl={payment.createDashboardUrlRequest.isExecuting}
89 openDashboard={price => this.handlePaymentDashboard(price)}
90 openExternalUrl={url => openExternalUrl({ url })}
91 onCloseSubscriptionWindow={() => this.onCloseWindow()} 50 onCloseSubscriptionWindow={() => this.onCloseWindow()}
92 deleteAccount={userActions.delete} 51 deleteAccount={userActions.delete}
93 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} 52 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting}
94 isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError} 53 isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError}
54 openEditAccount={() => this.handleWebsiteLink('/user/profile')}
55 openBilling={() => this.handleWebsiteLink('/user/billing')}
56 openInvoices={() => this.handleWebsiteLink('/user/invoices')}
95 /> 57 />
96 </ErrorBoundary> 58 </ErrorBoundary>
97 ); 59 );
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index b46908344..870ca4ecd 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -9,7 +9,6 @@ import ServicesStore from '../../stores/ServicesStore';
9import SettingsStore from '../../stores/SettingsStore'; 9import SettingsStore from '../../stores/SettingsStore';
10import FeaturesStore from '../../stores/FeaturesStore'; 10import FeaturesStore from '../../stores/FeaturesStore';
11import Form from '../../lib/Form'; 11import Form from '../../lib/Form';
12import { gaPage } from '../../lib/analytics';
13 12
14import ServiceError from '../../components/settings/services/ServiceError'; 13import ServiceError from '../../components/settings/services/ServiceError';
15import EditServiceForm from '../../components/settings/services/EditServiceForm'; 14import EditServiceForm from '../../components/settings/services/EditServiceForm';
@@ -19,9 +18,12 @@ import { required, url, oneRequired } from '../../helpers/validation-helpers';
19import { getSelectOptions } from '../../helpers/i18n-helpers'; 18import { getSelectOptions } from '../../helpers/i18n-helpers';
20 19
21import { config as proxyFeature } from '../../features/serviceProxy'; 20import { config as proxyFeature } from '../../features/serviceProxy';
21import { config as spellcheckerFeature } from '../../features/spellchecker';
22 22
23import { SPELLCHECKER_LOCALES } from '../../i18n/languages'; 23import { SPELLCHECKER_LOCALES } from '../../i18n/languages';
24 24
25import globalMessages from '../../i18n/globalMessages';
26
25const messages = defineMessages({ 27const messages = defineMessages({
26 name: { 28 name: {
27 id: 'settings.service.form.name', 29 id: 'settings.service.form.name',
@@ -83,14 +85,6 @@ const messages = defineMessages({
83 id: 'settings.service.form.proxy.password', 85 id: 'settings.service.form.proxy.password',
84 defaultMessage: '!!!Password', 86 defaultMessage: '!!!Password',
85 }, 87 },
86 spellcheckerLanguage: {
87 id: 'settings.service.form.spellcheckerLanguage',
88 defaultMessage: '!!!Spell checking Language',
89 },
90 spellcheckerSystemDefault: {
91 id: 'settings.service.form.spellcheckerLanguage.default',
92 defaultMessage: '!!!Use System Default ({default})',
93 },
94}); 88});
95 89
96export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component { 90export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component {
@@ -98,10 +92,6 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
98 intl: intlShape, 92 intl: intlShape,
99 }; 93 };
100 94
101 componentDidMount() {
102 gaPage('Settings/Service/Edit');
103 }
104
105 onSubmit(data) { 95 onSubmit(data) {
106 const { action } = this.props.router.params; 96 const { action } = this.props.router.params;
107 const { recipes, services } = this.props.stores; 97 const { recipes, services } = this.props.stores;
@@ -118,12 +108,26 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
118 } 108 }
119 109
120 prepareForm(recipe, service, proxy) { 110 prepareForm(recipe, service, proxy) {
111 const {
112 intl,
113 } = this.context;
114
115 const {
116 stores,
117 } = this.props;
118
119 let defaultSpellcheckerLanguage = SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage];
120
121 if (stores.settings.app.spellcheckerLanguage === 'automatic') {
122 defaultSpellcheckerLanguage = intl.formatMessage(globalMessages.spellcheckerAutomaticDetectionShort);
123 }
124
121 const spellcheckerLanguage = getSelectOptions({ 125 const spellcheckerLanguage = getSelectOptions({
122 locales: SPELLCHECKER_LOCALES, 126 locales: SPELLCHECKER_LOCALES,
123 resetToDefaultText: this.context.intl.formatMessage(messages.spellcheckerSystemDefault, { default: SPELLCHECKER_LOCALES[this.props.stores.settings.app.spellcheckerLanguage] }), 127 resetToDefaultText: intl.formatMessage(globalMessages.spellcheckerSystemDefault, { default: defaultSpellcheckerLanguage }),
128 automaticDetectionText: stores.settings.app.spellcheckerLanguage !== 'automatic' ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection) : '',
124 }); 129 });
125 130
126 const { intl } = this.context;
127 const config = { 131 const config = {
128 fields: { 132 fields: {
129 name: { 133 name: {
@@ -160,13 +164,13 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
160 isDarkModeEnabled: { 164 isDarkModeEnabled: {
161 label: intl.formatMessage(messages.enableDarkMode), 165 label: intl.formatMessage(messages.enableDarkMode),
162 value: service.isDarkModeEnabled, 166 value: service.isDarkModeEnabled,
163 default: this.props.stores.settings.app.darkMode, 167 default: stores.settings.app.darkMode,
164 }, 168 },
165 spellcheckerLanguage: { 169 spellcheckerLanguage: {
166 label: intl.formatMessage(messages.spellcheckerLanguage), 170 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
167 value: service.spellcheckerLanguage, 171 value: service.spellcheckerLanguage,
168 options: spellcheckerLanguage, 172 options: spellcheckerLanguage,
169 disabled: !this.props.stores.settings.app.enableSpellchecking, 173 disabled: !stores.settings.app.enableSpellchecking,
170 }, 174 },
171 }, 175 },
172 }; 176 };
@@ -220,7 +224,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
220 } 224 }
221 225
222 if (proxy.isEnabled) { 226 if (proxy.isEnabled) {
223 const serviceProxyConfig = this.props.stores.settings.proxy[service.id] || {}; 227 const serviceProxyConfig = stores.settings.proxy[service.id] || {};
224 228
225 Object.assign(config.fields, { 229 Object.assign(config.fields, {
226 proxy: { 230 proxy: {
@@ -326,7 +330,8 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
326 onSubmit={d => this.onSubmit(d)} 330 onSubmit={d => this.onSubmit(d)}
327 onDelete={() => this.deleteService()} 331 onDelete={() => this.deleteService()}
328 isProxyFeatureEnabled={proxyFeature.isEnabled} 332 isProxyFeatureEnabled={proxyFeature.isEnabled}
329 isProxyFeaturePremiumFeature={proxyFeature.isPremium} 333 isProxyPremiumFeature={proxyFeature.isPremium}
334 isSpellcheckerPremiumFeature={spellcheckerFeature.isPremium}
330 /> 335 />
331 </ErrorBoundary> 336 </ErrorBoundary>
332 ); 337 );
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index f1706a721..97c1fa3b1 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -8,16 +8,16 @@ import SettingsStore from '../../stores/SettingsStore';
8import UserStore from '../../stores/UserStore'; 8import UserStore from '../../stores/UserStore';
9import Form from '../../lib/Form'; 9import Form from '../../lib/Form';
10import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages'; 10import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages';
11import { gaPage } from '../../lib/analytics';
12import { DEFAULT_APP_SETTINGS } from '../../config'; 11import { DEFAULT_APP_SETTINGS } from '../../config';
13import { config as spellcheckerConfig } from '../../features/spellchecker'; 12import { config as spellcheckerConfig } from '../../features/spellchecker';
14 13
15import { getSelectOptions } from '../../helpers/i18n-helpers'; 14import { getSelectOptions } from '../../helpers/i18n-helpers';
16 15
17
18import EditSettingsForm from '../../components/settings/settings/EditSettingsForm'; 16import EditSettingsForm from '../../components/settings/settings/EditSettingsForm';
19import ErrorBoundary from '../../components/util/ErrorBoundary'; 17import ErrorBoundary from '../../components/util/ErrorBoundary';
20 18
19import globalMessages from '../../i18n/globalMessages';
20
21const messages = defineMessages({ 21const messages = defineMessages({
22 autoLaunchOnStart: { 22 autoLaunchOnStart: {
23 id: 'settings.app.form.autoLaunchOnStart', 23 id: 'settings.app.form.autoLaunchOnStart',
@@ -63,10 +63,6 @@ const messages = defineMessages({
63 id: 'settings.app.form.enableGPUAcceleration', 63 id: 'settings.app.form.enableGPUAcceleration',
64 defaultMessage: '!!!Enable GPU Acceleration', 64 defaultMessage: '!!!Enable GPU Acceleration',
65 }, 65 },
66 spellcheckerLanguage: {
67 id: 'settings.app.form.spellcheckerLanguage',
68 defaultMessage: '!!!Language for spell checking',
69 },
70 beta: { 66 beta: {
71 id: 'settings.app.form.beta', 67 id: 'settings.app.form.beta',
72 defaultMessage: '!!!Include beta versions', 68 defaultMessage: '!!!Include beta versions',
@@ -78,10 +74,6 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
78 intl: intlShape, 74 intl: intlShape,
79 }; 75 };
80 76
81 componentDidMount() {
82 gaPage('Settings/App');
83 }
84
85 onSubmit(settingsData) { 77 onSubmit(settingsData) {
86 const { app, settings, user } = this.props.actions; 78 const { app, settings, user } = this.props.actions;
87 79
@@ -125,6 +117,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
125 117
126 const spellcheckingLanguages = getSelectOptions({ 118 const spellcheckingLanguages = getSelectOptions({
127 locales: SPELLCHECKER_LOCALES, 119 locales: SPELLCHECKER_LOCALES,
120 automaticDetectionText: this.context.intl.formatMessage(globalMessages.spellcheckerAutomaticDetection),
128 }); 121 });
129 122
130 const config = { 123 const config = {
@@ -166,11 +159,11 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
166 }, 159 },
167 enableSpellchecking: { 160 enableSpellchecking: {
168 label: intl.formatMessage(messages.enableSpellchecking), 161 label: intl.formatMessage(messages.enableSpellchecking),
169 value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : settings.all.app.enableSpellchecking, 162 value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : settings.all.app.enableSpellchecking,
170 default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, 163 default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : DEFAULT_APP_SETTINGS.enableSpellchecking,
171 }, 164 },
172 spellcheckerLanguage: { 165 spellcheckerLanguage: {
173 label: intl.formatMessage(messages.spellcheckerLanguage), 166 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
174 value: settings.all.app.spellcheckerLanguage, 167 value: settings.all.app.spellcheckerLanguage,
175 options: spellcheckingLanguages, 168 options: spellcheckingLanguages,
176 default: DEFAULT_APP_SETTINGS.spellcheckerLanguage, 169 default: DEFAULT_APP_SETTINGS.spellcheckerLanguage,
@@ -230,7 +223,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
230 cacheSize={cacheSize} 223 cacheSize={cacheSize}
231 isClearingAllCache={isClearingAllCache} 224 isClearingAllCache={isClearingAllCache}
232 onClearAllCache={clearAllCache} 225 onClearAllCache={clearAllCache}
233 isSpellcheckerPremiumFeature={spellcheckerConfig.isPremiumFeature} 226 isSpellcheckerPremiumFeature={spellcheckerConfig.isPremium}
234 /> 227 />
235 </ErrorBoundary> 228 </ErrorBoundary>
236 ); 229 );
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index 3d35effc5..81f689400 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -9,7 +9,6 @@ import EditUserForm from '../../components/settings/user/EditUserForm';
9import ErrorBoundary from '../../components/util/ErrorBoundary'; 9import ErrorBoundary from '../../components/util/ErrorBoundary';
10 10
11import { required, email, minLength } from '../../helpers/validation-helpers'; 11import { required, email, minLength } from '../../helpers/validation-helpers';
12import { gaPage } from '../../lib/analytics';
13 12
14const messages = defineMessages({ 13const messages = defineMessages({
15 firstname: { 14 firstname: {
@@ -24,23 +23,21 @@ const messages = defineMessages({
24 id: 'settings.user.form.email', 23 id: 'settings.user.form.email',
25 defaultMessage: '!!!Email', 24 defaultMessage: '!!!Email',
26 }, 25 },
27 accountType: { 26 accountTypeLabel: {
28 label: { 27 id: 'settings.user.form.accountType.label',
29 id: 'settings.user.form.accountType.label', 28 defaultMessage: '!!!Account type',
30 defaultMessage: '!!!Account type', 29 },
31 }, 30 accountTypeIndividual: {
32 individual: { 31 id: 'settings.user.form.accountType.individual',
33 id: 'settings.user.form.accountType.individual', 32 defaultMessage: '!!!Individual',
34 defaultMessage: '!!!Individual', 33 },
35 }, 34 accountTypeNonProfit: {
36 nonProfit: { 35 id: 'settings.user.form.accountType.non-profit',
37 id: 'settings.user.form.accountType.non-profit', 36 defaultMessage: '!!!Non-Profit',
38 defaultMessage: '!!!Non-Profit', 37 },
39 }, 38 accountTypeCompany: {
40 company: { 39 id: 'settings.user.form.accountType.company',
41 id: 'settings.user.form.accountType.company', 40 defaultMessage: '!!!Company',
42 defaultMessage: '!!!Company',
43 },
44 }, 41 },
45 currentPassword: { 42 currentPassword: {
46 id: 'settings.user.form.currentPassword', 43 id: 'settings.user.form.currentPassword',
@@ -57,10 +54,6 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
57 intl: intlShape, 54 intl: intlShape,
58 }; 55 };
59 56
60 componentDidMount() {
61 gaPage('Settings/Account/Edit');
62 }
63
64 componentWillUnmount() { 57 componentWillUnmount() {
65 this.props.actions.user.resetStatus(); 58 this.props.actions.user.resetStatus();
66 } 59 }
@@ -99,21 +92,21 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
99 accountType: { 92 accountType: {
100 value: user.accountType, 93 value: user.accountType,
101 validators: [required], 94 validators: [required],
102 label: intl.formatMessage(messages.accountType.label), 95 label: intl.formatMessage(messages.accountTypeLabel),
103 options: [{ 96 options: [{
104 value: 'individual', 97 value: 'individual',
105 label: intl.formatMessage(messages.accountType.individual), 98 label: intl.formatMessage(messages.accountTypeIndividual),
106 }, { 99 }, {
107 value: 'non-profit', 100 value: 'non-profit',
108 label: intl.formatMessage(messages.accountType.nonProfit), 101 label: intl.formatMessage(messages.accountTypeNonProfit),
109 }, { 102 }, {
110 value: 'company', 103 value: 'company',
111 label: intl.formatMessage(messages.accountType.company), 104 label: intl.formatMessage(messages.accountTypeCompany),
112 }], 105 }],
113 }, 106 },
114 organization: { 107 organization: {
115 label: intl.formatMessage(messages.accountType.company), 108 label: intl.formatMessage(messages.accountTypeCompany),
116 placeholder: intl.formatMessage(messages.accountType.company), 109 placeholder: intl.formatMessage(messages.accountTypeCompany),
117 value: user.organization, 110 value: user.organization,
118 }, 111 },
119 oldPassword: { 112 oldPassword: {
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js
index cd36610e4..cc36849e8 100644
--- a/src/containers/settings/InviteScreen.js
+++ b/src/containers/settings/InviteScreen.js
@@ -5,13 +5,7 @@ import { inject, observer } from 'mobx-react';
5import Invite from '../../components/auth/Invite'; 5import Invite from '../../components/auth/Invite';
6import ErrorBoundary from '../../components/util/ErrorBoundary'; 6import ErrorBoundary from '../../components/util/ErrorBoundary';
7 7
8import { gaPage } from '../../lib/analytics';
9
10export default @inject('stores', 'actions') @observer class InviteScreen extends Component { 8export default @inject('stores', 'actions') @observer class InviteScreen extends Component {
11 componentDidMount() {
12 gaPage('Settings/Invite');
13 }
14
15 componentWillUnmount() { 9 componentWillUnmount() {
16 this.props.stores.user.inviteRequest.reset(); 10 this.props.stores.user.inviteRequest.reset();
17 } 11 }
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index b3d758c87..eda5ae54c 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -7,7 +7,6 @@ import RecipePreviewsStore from '../../stores/RecipePreviewsStore';
7import RecipeStore from '../../stores/RecipesStore'; 7import RecipeStore from '../../stores/RecipesStore';
8import ServiceStore from '../../stores/ServicesStore'; 8import ServiceStore from '../../stores/ServicesStore';
9import UserStore from '../../stores/UserStore'; 9import UserStore from '../../stores/UserStore';
10import { gaPage } from '../../lib/analytics';
11 10
12import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; 11import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard';
13import ErrorBoundary from '../../components/util/ErrorBoundary'; 12import ErrorBoundary from '../../components/util/ErrorBoundary';
@@ -33,20 +32,15 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
33 autorunDisposer = null; 32 autorunDisposer = null;
34 33
35 componentDidMount() { 34 componentDidMount() {
36 gaPage('Settings/Recipe Dashboard/Featured');
37
38 this.autorunDisposer = autorun(() => { 35 this.autorunDisposer = autorun(() => {
39 const { filter } = this.props.params; 36 const { filter } = this.props.params;
40 const { currentFilter } = this.state; 37 const { currentFilter } = this.state;
41 38
42 if (filter === 'all' && currentFilter !== 'all') { 39 if (filter === 'all' && currentFilter !== 'all') {
43 gaPage('Settings/Recipe Dashboard/All');
44 this.setState({ currentFilter: 'all' }); 40 this.setState({ currentFilter: 'all' });
45 } else if (filter === 'featured' && currentFilter !== 'featured') { 41 } else if (filter === 'featured' && currentFilter !== 'featured') {
46 gaPage('Settings/Recipe Dashboard/Featured');
47 this.setState({ currentFilter: 'featured' }); 42 this.setState({ currentFilter: 'featured' });
48 } else if (filter === 'dev' && currentFilter !== 'dev') { 43 } else if (filter === 'dev' && currentFilter !== 'dev') {
49 gaPage('Settings/Recipe Dashboard/Dev');
50 this.setState({ currentFilter: 'dev' }); 44 this.setState({ currentFilter: 'dev' });
51 } 45 }
52 }); 46 });
diff --git a/src/containers/settings/ServicesScreen.js b/src/containers/settings/ServicesScreen.js
index b70a5506e..a501bf530 100644
--- a/src/containers/settings/ServicesScreen.js
+++ b/src/containers/settings/ServicesScreen.js
@@ -6,16 +6,11 @@ import { RouterStore } from 'mobx-react-router';
6// import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; 6// import RecipePreviewsStore from '../../stores/RecipePreviewsStore';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
8import ServiceStore from '../../stores/ServicesStore'; 8import ServiceStore from '../../stores/ServicesStore';
9import { gaPage } from '../../lib/analytics';
10 9
11import ServicesDashboard from '../../components/settings/services/ServicesDashboard'; 10import ServicesDashboard from '../../components/settings/services/ServicesDashboard';
12import ErrorBoundary from '../../components/util/ErrorBoundary'; 11import ErrorBoundary from '../../components/util/ErrorBoundary';
13 12
14export default @inject('stores', 'actions') @observer class ServicesScreen extends Component { 13export default @inject('stores', 'actions') @observer class ServicesScreen extends Component {
15 componentDidMount() {
16 gaPage('Settings/Service Dashboard');
17 }
18
19 componentWillUnmount() { 14 componentWillUnmount() {
20 this.props.actions.service.resetFilter(); 15 this.props.actions.service.resetFilter();
21 this.props.actions.service.resetStatus(); 16 this.props.actions.service.resetStatus();
diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js
index 6d9e0ee77..663b9e2e4 100644
--- a/src/containers/settings/SettingsWindow.js
+++ b/src/containers/settings/SettingsWindow.js
@@ -7,6 +7,7 @@ import ServicesStore from '../../stores/ServicesStore';
7import Layout from '../../components/settings/SettingsLayout'; 7import Layout from '../../components/settings/SettingsLayout';
8import Navigation from '../../components/settings/navigation/SettingsNavigation'; 8import Navigation from '../../components/settings/navigation/SettingsNavigation';
9import ErrorBoundary from '../../components/util/ErrorBoundary'; 9import ErrorBoundary from '../../components/util/ErrorBoundary';
10import { workspaceStore } from '../../features/workspaces';
10 11
11export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { 12export default @inject('stores', 'actions') @observer class SettingsContainer extends Component {
12 render() { 13 render() {
@@ -16,6 +17,7 @@ export default @inject('stores', 'actions') @observer class SettingsContainer ex
16 const navigation = ( 17 const navigation = (
17 <Navigation 18 <Navigation
18 serviceCount={stores.services.all.length} 19 serviceCount={stores.services.all.length}
20 workspaceCount={workspaceStore.workspaces.length}
19 /> 21 />
20 ); 22 );
21 23
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js
new file mode 100644
index 000000000..c69d5ad08
--- /dev/null
+++ b/src/containers/settings/TeamScreen.js
@@ -0,0 +1,57 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4
5import UserStore from '../../stores/UserStore';
6import AppStore from '../../stores/AppStore';
7
8import TeamDashboard from '../../components/settings/team/TeamDashboard';
9import ErrorBoundary from '../../components/util/ErrorBoundary';
10import { WEBSITE } from '../../environment';
11
12export default @inject('stores', 'actions') @observer class TeamScreen extends Component {
13 handleWebsiteLink(route) {
14 const { actions, stores } = this.props;
15
16 const url = `${WEBSITE}${route}?authToken=${stores.user.authToken}&utm_source=app&utm_medium=account_dashboard`;
17 console.log(url);
18
19 actions.app.openExternalUrl({ url });
20 }
21
22 render() {
23 const { user } = this.props.stores;
24
25 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting;
26
27 return (
28 <ErrorBoundary>
29 <TeamDashboard
30 isLoading={isLoadingUserInfo}
31 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError}
32 retryUserInfoRequest={() => this.reloadData()}
33 openTeamManagement={() => this.handleWebsiteLink('/user/team')}
34 />
35 </ErrorBoundary>
36 );
37 }
38}
39
40TeamScreen.wrappedComponent.propTypes = {
41 stores: PropTypes.shape({
42 user: PropTypes.instanceOf(UserStore).isRequired,
43 app: PropTypes.instanceOf(AppStore).isRequired,
44 }).isRequired,
45 actions: PropTypes.shape({
46 payment: PropTypes.shape({
47 createDashboardUrl: PropTypes.func.isRequired,
48 }).isRequired,
49 app: PropTypes.shape({
50 openExternalUrl: PropTypes.func.isRequired,
51 }).isRequired,
52 user: PropTypes.shape({
53 update: PropTypes.func.isRequired,
54 delete: PropTypes.func.isRequired,
55 }).isRequired,
56 }).isRequired,
57};
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js
index 3eb7b6255..cb67ee7f2 100644
--- a/src/containers/subscription/SubscriptionFormScreen.js
+++ b/src/containers/subscription/SubscriptionFormScreen.js
@@ -43,26 +43,31 @@ export default @inject('stores', 'actions') @observer class SubscriptionFormScre
43 }); 43 });
44 44
45 const hostedPage = await stores.payment.createHostedPageRequest; 45 const hostedPage = await stores.payment.createHostedPageRequest;
46 const url = `file://${__dirname}/../../index.html#/payment/${encodeURIComponent(hostedPage.url)}`;
47 46
48 if (hostedPage.url) { 47 if (hostedPage.url) {
49 const paymentWindow = new BrowserWindow({ 48 if (hostedPage.legacyCheckoutFlow) {
50 parent: remote.getCurrentWindow(), 49 const paymentWindow = new BrowserWindow({
51 modal: true, 50 parent: remote.getCurrentWindow(),
52 title: '🔒 Franz Supporter License', 51 modal: true,
53 width: 600, 52 title: '🔒 Franz Supporter License',
54 height: window.innerHeight - 100, 53 width: 600,
55 maxWidth: 600, 54 height: window.innerHeight - 100,
56 minWidth: 600, 55 maxWidth: 600,
57 webPreferences: { 56 minWidth: 600,
58 nodeIntegration: true, 57 webPreferences: {
59 }, 58 nodeIntegration: true,
60 }); 59 },
61 paymentWindow.loadURL(url); 60 });
61 paymentWindow.loadURL(`file://${__dirname}/../../index.html#/payment/${encodeURIComponent(hostedPage.url)}`);
62 62
63 paymentWindow.on('closed', () => { 63 paymentWindow.on('closed', () => {
64 onCloseWindow(); 64 onCloseWindow();
65 }); 65 });
66 } else {
67 actions.app.openExternalUrl({
68 url: hostedPage.url,
69 });
70 }
66 } 71 }
67 } 72 }
68 73
diff --git a/src/electron/ipc-api/autoUpdate.js b/src/electron/ipc-api/autoUpdate.js
index 83dd83712..9a04c1958 100644
--- a/src/electron/ipc-api/autoUpdate.js
+++ b/src/electron/ipc-api/autoUpdate.js
@@ -4,7 +4,7 @@ import { autoUpdater } from 'electron-updater';
4const debug = require('debug')('Franz:ipcApi:autoUpdate'); 4const debug = require('debug')('Franz:ipcApi:autoUpdate');
5 5
6export default (params) => { 6export default (params) => {
7 if (process.platform === 'darwin' || process.platform === 'win32') { 7 if (process.platform === 'darwin' || process.platform === 'win32' || process.env.APPIMAGE) {
8 ipcMain.on('autoUpdate', (event, args) => { 8 ipcMain.on('autoUpdate', (event, args) => {
9 try { 9 try {
10 autoUpdater.autoInstallOnAppQuit = false; 10 autoUpdater.autoInstallOnAppQuit = false;
@@ -30,9 +30,12 @@ export default (params) => {
30 params.mainWindow.webContents.send('autoUpdate', { available: false }); 30 params.mainWindow.webContents.send('autoUpdate', { available: false });
31 }); 31 });
32 32
33 autoUpdater.on('update-available', () => { 33 autoUpdater.on('update-available', (event) => {
34 debug('update-available'); 34 debug('update-available');
35 params.mainWindow.webContents.send('autoUpdate', { available: true }); 35 params.mainWindow.webContents.send('autoUpdate', {
36 version: event.version,
37 available: true,
38 });
36 }); 39 });
37 40
38 autoUpdater.on('download-progress', (progressObj) => { 41 autoUpdater.on('download-progress', (progressObj) => {
diff --git a/src/environment.js b/src/environment.js
index e1762129b..ae7a67e4d 100644
--- a/src/environment.js
+++ b/src/environment.js
@@ -1,10 +1,22 @@
1import { LIVE_API, DEV_API, LOCAL_API } from './config'; 1import isDev from 'electron-is-dev';
2 2
3export const isDevMode = Boolean(process.execPath.match(/[\\/]electron/)); 3import {
4 LIVE_API,
5 DEV_API,
6 LOCAL_API,
7 LOCAL_API_WEBSITE,
8 DEV_API_WEBSITE,
9 LIVE_API_WEBSITE,
10 LIVE_WS_API,
11 LOCAL_WS_API,
12 DEV_WS_API,
13} from './config';
14
15export const isDevMode = isDev;
4export const useLiveAPI = process.env.LIVE_API; 16export const useLiveAPI = process.env.LIVE_API;
5export const useLocalAPI = process.env.LOCAL_API; 17export const useLocalAPI = process.env.LOCAL_API;
6 18
7let platform = process.platform; 19let { platform } = process;
8if (process.env.OS_PLATFORM) { 20if (process.env.OS_PLATFORM) {
9 platform = process.env.OS_PLATFORM; 21 platform = process.env.OS_PLATFORM;
10} 22}
@@ -17,12 +29,23 @@ export const ctrlKey = isMac ? '⌘' : 'Ctrl';
17export const cmdKey = isMac ? 'Cmd' : 'Ctrl'; 29export const cmdKey = isMac ? 'Cmd' : 'Ctrl';
18 30
19let api; 31let api;
32let wsApi;
33let web;
20if (!isDevMode || (isDevMode && useLiveAPI)) { 34if (!isDevMode || (isDevMode && useLiveAPI)) {
21 api = LIVE_API; 35 api = LIVE_API;
36 wsApi = LIVE_WS_API;
37 web = LIVE_API_WEBSITE;
22} else if (isDevMode && useLocalAPI) { 38} else if (isDevMode && useLocalAPI) {
23 api = LOCAL_API; 39 api = LOCAL_API;
40 wsApi = LOCAL_WS_API;
41 web = LOCAL_API_WEBSITE;
24} else { 42} else {
25 api = DEV_API; 43 api = DEV_API;
44 wsApi = DEV_WS_API;
45 web = DEV_API_WEBSITE;
26} 46}
27 47
28export const API = api; 48export const API = api;
49export const API_VERSION = 'v1';
50export const WS_API = wsApi;
51export const WEBSITE = web;
diff --git a/src/features/announcements/actions.js b/src/features/announcements/actions.js
new file mode 100644
index 000000000..bab496314
--- /dev/null
+++ b/src/features/announcements/actions.js
@@ -0,0 +1,10 @@
1import PropTypes from 'prop-types';
2import { createActionsFromDefinitions } from '../../actions/lib/actions';
3
4export const announcementActions = createActionsFromDefinitions({
5 show: {
6 targetVersion: PropTypes.string,
7 },
8}, PropTypes.checkPropTypes);
9
10export default announcementActions;
diff --git a/src/features/announcements/api.js b/src/features/announcements/api.js
new file mode 100644
index 000000000..a581bd8de
--- /dev/null
+++ b/src/features/announcements/api.js
@@ -0,0 +1,33 @@
1import { remote } from 'electron';
2import Request from '../../stores/lib/Request';
3import { API, API_VERSION } from '../../environment';
4
5const debug = require('debug')('Franz:feature:announcements:api');
6
7export const announcementsApi = {
8 async getCurrentVersion() {
9 debug('getting current version of electron app');
10 return Promise.resolve(remote.app.getVersion());
11 },
12
13 async getChangelog(version) {
14 debug('fetching release changelog from Github');
15 const url = `https://api.github.com/repos/meetfranz/franz/releases/tags/v${version}`;
16 const request = await window.fetch(url, { method: 'GET' });
17 if (!request.ok) return null;
18 const data = await request.json();
19 return data.body;
20 },
21
22 async getAnnouncement(version) {
23 debug('fetching release announcement from api');
24 const url = `${API}/${API_VERSION}/announcements/${version}`;
25 const response = await window.fetch(url, { method: 'GET' });
26 if (!response.ok) return null;
27 return response.json();
28 },
29};
30
31export const getCurrentVersionRequest = new Request(announcementsApi, 'getCurrentVersion');
32export const getChangelogRequest = new Request(announcementsApi, 'getChangelog');
33export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncement');
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js
new file mode 100644
index 000000000..dfce6cdd5
--- /dev/null
+++ b/src/features/announcements/components/AnnouncementScreen.js
@@ -0,0 +1,286 @@
1import React, { Component } from 'react';
2import marked from 'marked';
3import PropTypes from 'prop-types';
4import { inject, observer } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl';
6import injectSheet from 'react-jss';
7import { Button } from '@meetfranz/forms';
8
9import { announcementsStore } from '../index';
10import UIStore from '../../../stores/UIStore';
11import { gaEvent } from '../../../lib/analytics';
12
13const renderer = new marked.Renderer();
14
15renderer.link = (href, title, text) => `<a target="_blank" href="${href}" title="${title}">${text}</a>`;
16
17const markedOptions = { sanitize: true, renderer };
18
19const messages = defineMessages({
20 headline: {
21 id: 'feature.announcements.changelog.headline',
22 defaultMessage: '!!!Changes in Franz {version}',
23 },
24});
25
26const smallScreen = '1000px';
27
28const styles = theme => ({
29 container: {
30 background: theme.colorBackground,
31 position: 'absolute',
32 top: 0,
33 zIndex: 140,
34 width: '100%',
35 height: '100%',
36 overflowY: 'auto',
37 },
38 headline: {
39 color: theme.colorHeadline,
40 margin: [25, 0, 40],
41 // 'max-width': 500,
42 'text-align': 'center',
43 'line-height': '1.3em',
44 },
45 announcement: {
46 height: 'auto',
47
48 [`@media(min-width: ${smallScreen})`]: {
49 display: 'flex',
50 flexDirection: 'column',
51 justifyContent: 'center',
52 height: '100vh',
53 },
54 },
55 main: {
56 display: 'flex',
57 flexDirection: 'column',
58 flexGrow: 1,
59 justifyContent: 'center',
60
61 '& h1': {
62 margin: [40, 0, 15],
63 fontSize: 70,
64 color: theme.styleTypes.primary.accent,
65 textAlign: 'center',
66
67 [`@media(min-width: ${smallScreen})`]: {
68 marginTop: 0,
69 },
70 },
71 '& h2': {
72 fontSize: 30,
73 fontWeight: 300,
74 color: theme.colorText,
75 textAlign: 'center',
76 marginBottom: 60,
77 },
78 },
79 mainBody: {
80 display: 'flex',
81 flexDirection: 'column',
82 alignItems: 'center',
83 width: 'calc(100% - 80px)',
84 height: 'auto',
85 margin: '0 auto',
86 [`@media(min-width: ${smallScreen})`]: {
87 flexDirection: 'row',
88 justifyContent: 'center',
89 },
90 },
91 mainImage: {
92 minWidth: 250,
93 maxWidth: 400,
94 margin: '0 auto',
95 marginBottom: 40,
96 '& img': {
97 width: '100%',
98 },
99 [`@media(min-width: ${smallScreen})`]: {
100 margin: 0,
101 },
102 },
103 mainText: {
104 height: 'auto',
105 maxWidth: 600,
106 textAlign: 'center',
107 '& p': {
108 lineHeight: '1.5em',
109 },
110 [`@media(min-width: ${smallScreen})`]: {
111 textAlign: 'left',
112 },
113 },
114 mainCtaButton: {
115 textAlign: 'center',
116 marginTop: 40,
117 [`@media(min-width: ${smallScreen})`]: {
118 textAlign: 'left',
119 },
120 },
121 spotlight: {
122 height: 'auto',
123 background: theme.announcements.spotlight.background,
124 padding: [40, 0],
125 marginTop: 80,
126 [`@media(min-width: ${smallScreen})`]: {
127 marginTop: 0,
128 justifyContent: 'center',
129 alignItems: 'flex-start',
130 display: 'flex',
131 flexDirection: 'row',
132 },
133 },
134 spotlightTopicContainer: {
135 textAlign: 'center',
136 marginBottom: 20,
137
138 [`@media(min-width: ${smallScreen})`]: {
139 marginBottom: 0,
140 minWidth: 250,
141 maxWidth: 330,
142 width: '100%',
143 textAlign: 'right',
144 marginRight: 60,
145 },
146 },
147 spotlightContentContainer: {
148 textAlign: 'center',
149 [`@media(min-width: ${smallScreen})`]: {
150 height: 'auto',
151 maxWidth: 600,
152 paddingRight: 40,
153 textAlign: 'left',
154 },
155 '& p': {
156 lineHeight: '1.5em',
157 },
158 },
159 spotlightTopic: {
160 fontSize: 20,
161 marginBottom: 5,
162 letterSpacing: 0,
163 fontWeight: 100,
164 },
165 spotlightSubject: {
166 fontSize: 20,
167 },
168 changelog: {
169 padding: [0, 60],
170 maxWidth: 700,
171 margin: [100, 'auto'],
172 height: 'auto',
173
174 '& h3': {
175 fontSize: '24px',
176 margin: '1.5em 0 1em 0',
177 },
178 '& li': {
179 marginBottom: '1em',
180 lineHeight: '1.4em',
181 },
182 '& div': {
183 height: 'auto',
184 },
185 },
186});
187
188
189@inject('stores', 'actions') @injectSheet(styles) @observer
190class AnnouncementScreen extends Component {
191 static propTypes = {
192 classes: PropTypes.object.isRequired,
193 stores: PropTypes.shape({
194 ui: PropTypes.instanceOf(UIStore).isRequired,
195 }).isRequired,
196 };
197
198 static contextTypes = {
199 intl: intlShape,
200 };
201
202 render() {
203 const { classes, stores } = this.props;
204 const { intl } = this.context;
205 const { changelog, announcement } = announcementsStore;
206 const themeImage = stores.ui.isDarkThemeActive ? 'dark' : 'light';
207 return (
208 <div className={classes.container}>
209 {announcement && (
210 <div className={classes.announcement}>
211 <div className={classes.main}>
212 <h1>{announcement.main.headline}</h1>
213 <h2>{announcement.main.subHeadline}</h2>
214 <div className={classes.mainBody}>
215 <div className={classes.mainImage}>
216 <img
217 src={announcement.main.image[themeImage]}
218 alt=""
219 />
220 </div>
221 <div className={classes.mainText}>
222 <div
223 dangerouslySetInnerHTML={{
224 __html: marked(announcement.main.text, markedOptions),
225 }}
226 />
227 <div className={classes.mainCtaButton}>
228 <Button
229 label={announcement.main.cta.label}
230 onClick={() => {
231 const { analytics } = announcement.main.cta;
232 window.location.href = `#${announcement.main.cta.href}`;
233 gaEvent(analytics.category, analytics.action, announcement.main.cta.label);
234 }}
235 />
236 </div>
237 </div>
238 </div>
239 </div>
240 {announcement.spotlight && (
241 <div className={classes.spotlight}>
242 <div className={classes.spotlightTopicContainer}>
243 <h2 className={classes.spotlightTopic}>{announcement.spotlight.title}</h2>
244 <h3 className={classes.spotlightSubject}>{announcement.spotlight.subject}</h3>
245 </div>
246 <div className={classes.spotlightContentContainer}>
247 <div
248 dangerouslySetInnerHTML={{
249 __html: marked(announcement.spotlight.text, markedOptions),
250 }}
251 />
252 <div className={classes.mainCtaButton}>
253 <Button
254 label={announcement.spotlight.cta.label}
255 onClick={() => {
256 const { analytics } = announcement.spotlight.cta;
257 window.location.href = `#${announcement.spotlight.cta.href}`;
258 gaEvent(analytics.category, analytics.action, announcement.spotlight.cta.label);
259 }}
260 />
261 </div>
262 </div>
263 </div>
264 )}
265 </div>
266 )}
267 {changelog && (
268 <div className={classes.changelog}>
269 <h1 className={classes.headline}>
270 {intl.formatMessage(messages.headline, {
271 version: announcementsStore.currentVersion,
272 })}
273 </h1>
274 <div
275 dangerouslySetInnerHTML={{
276 __html: marked(changelog, markedOptions),
277 }}
278 />
279 </div>
280 )}
281 </div>
282 );
283 }
284}
285
286export default AnnouncementScreen;
diff --git a/src/features/announcements/index.js b/src/features/announcements/index.js
new file mode 100644
index 000000000..4658b976f
--- /dev/null
+++ b/src/features/announcements/index.js
@@ -0,0 +1,32 @@
1import { reaction } from 'mobx';
2import { AnnouncementsStore } from './store';
3
4const debug = require('debug')('Franz:feature:announcements');
5
6export const GA_CATEGORY_ANNOUNCEMENTS = 'Announcements';
7
8export const announcementsStore = new AnnouncementsStore();
9
10export default function initAnnouncements(stores, actions) {
11 // const { features } = stores;
12
13 // Toggle workspace feature
14 reaction(
15 () => (
16 true
17 // features.features.isAnnouncementsEnabled
18 ),
19 (isEnabled) => {
20 if (isEnabled) {
21 debug('Initializing `announcements` feature');
22 announcementsStore.start(stores, actions);
23 } else if (announcementsStore.isFeatureActive) {
24 debug('Disabling `announcements` feature');
25 announcementsStore.stop();
26 }
27 },
28 {
29 fireImmediately: true,
30 },
31 );
32}
diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js
new file mode 100644
index 000000000..7ecc0e346
--- /dev/null
+++ b/src/features/announcements/store.js
@@ -0,0 +1,144 @@
1import {
2 action,
3 computed,
4 observable,
5 reaction,
6} from 'mobx';
7import semver from 'semver';
8import localStorage from 'mobx-localstorage';
9
10import { FeatureStore } from '../utils/FeatureStore';
11import { GA_CATEGORY_ANNOUNCEMENTS } from '.';
12import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api';
13import { announcementActions } from './actions';
14import { createActionBindings } from '../utils/ActionBinding';
15import { createReactions } from '../../stores/lib/Reaction';
16import { gaEvent } from '../../lib/analytics';
17
18const LOCAL_STORAGE_KEY = 'announcements';
19
20const debug = require('debug')('Franz:feature:announcements:store');
21
22export class AnnouncementsStore extends FeatureStore {
23 @observable targetVersion = null;
24
25 @observable isAnnouncementVisible = false;
26
27 @observable isFeatureActive = false;
28
29 @computed get changelog() {
30 return getChangelogRequest.result;
31 }
32
33 @computed get announcement() {
34 return getAnnouncementRequest.result;
35 }
36
37 @computed get areNewsAvailable() {
38 const isChangelogAvailable = getChangelogRequest.wasExecuted && !!this.changelog;
39 const isAnnouncementAvailable = getAnnouncementRequest.wasExecuted && !!this.announcement;
40 return isChangelogAvailable || isAnnouncementAvailable;
41 }
42
43 @computed get settings() {
44 return localStorage.getItem(LOCAL_STORAGE_KEY) || {};
45 }
46
47 @computed get lastSeenAnnouncementVersion() {
48 return this.settings.lastSeenAnnouncementVersion || null;
49 }
50
51 @computed get currentVersion() {
52 return getCurrentVersionRequest.result;
53 }
54
55 @computed get isNewUser() {
56 return this.stores.settings.stats.appStarts <= 1;
57 }
58
59 async start(stores, actions) {
60 debug('AnnouncementsStore::start');
61 this.stores = stores;
62 this.actions = actions;
63 getCurrentVersionRequest.execute();
64
65 this._registerActions(createActionBindings([
66 [announcementActions.show, this._showAnnouncement],
67 ]));
68
69 this._reactions = createReactions([
70 this._fetchAnnouncements,
71 this._showAnnouncementToUsersWhoUpdatedApp,
72 ]);
73 this._registerReactions(this._reactions);
74 this.isFeatureActive = true;
75 }
76
77 stop() {
78 super.stop();
79 debug('AnnouncementsStore::stop');
80 this.isFeatureActive = false;
81 this.isAnnouncementVisible = false;
82 }
83
84 // ======= HELPERS ======= //
85
86 _updateSettings = (changes) => {
87 localStorage.setItem(LOCAL_STORAGE_KEY, {
88 ...this.settings,
89 ...changes,
90 });
91 };
92
93 // ======= ACTIONS ======= //
94
95 @action _showAnnouncement = ({ targetVersion } = {}) => {
96 if (!this.areNewsAvailable) return;
97 this.targetVersion = targetVersion || this.currentVersion;
98 this.isAnnouncementVisible = true;
99 this.actions.service.blurActive();
100 this._updateSettings({
101 lastSeenAnnouncementVersion: this.currentVersion,
102 });
103 const dispose = reaction(
104 () => this.stores.services.active,
105 () => {
106 this._hideAnnouncement();
107 dispose();
108 },
109 );
110
111 gaEvent(GA_CATEGORY_ANNOUNCEMENTS, 'show');
112 };
113
114 @action _hideAnnouncement() {
115 this.isAnnouncementVisible = false;
116 }
117
118 // ======= REACTIONS ========
119
120 _showAnnouncementToUsersWhoUpdatedApp = () => {
121 const { announcement, isNewUser } = this;
122 // Check if there is an announcement and on't show announcements to new users
123 if (!announcement || isNewUser) return;
124
125 // Check if the user has already used current version (= has seen the announcement)
126 const { currentVersion, lastSeenAnnouncementVersion } = this;
127 if (semver.gt(currentVersion, lastSeenAnnouncementVersion || '0.0.0')) {
128 debug(`${currentVersion} < ${lastSeenAnnouncementVersion}: announcement is shown`);
129 this._showAnnouncement();
130 }
131 };
132
133 _fetchAnnouncements = () => {
134 const targetVersion = this.targetVersion || this.currentVersion;
135 if (!targetVersion) return;
136 getChangelogRequest.execute(targetVersion);
137 // We only fetch announcements for current / older versions
138 if (targetVersion <= this.currentVersion) {
139 getAnnouncementRequest.execute(targetVersion);
140 } else {
141 getAnnouncementRequest.reset();
142 }
143 }
144}
diff --git a/src/features/basicAuth/Component.js b/src/features/basicAuth/Component.js
index 13395fb40..a8252acb7 100644
--- a/src/features/basicAuth/Component.js
+++ b/src/features/basicAuth/Component.js
@@ -62,6 +62,7 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo
62 isOpen={isModalVisible} 62 isOpen={isModalVisible}
63 className={classes.modal} 63 className={classes.modal}
64 close={this.cancel.bind(this)} 64 close={this.cancel.bind(this)}
65 showClose={false}
65 > 66 >
66 <h1>Sign in</h1> 67 <h1>Sign in</h1>
67 <p> 68 <p>
diff --git a/src/features/basicAuth/index.js b/src/features/basicAuth/index.js
index 03269582c..89607824b 100644
--- a/src/features/basicAuth/index.js
+++ b/src/features/basicAuth/index.js
@@ -6,7 +6,7 @@ import BasicAuthComponent from './Component';
6const debug = require('debug')('Franz:feature:basicAuth'); 6const debug = require('debug')('Franz:feature:basicAuth');
7 7
8const defaultState = { 8const defaultState = {
9 isModalVisible: false, 9 isModalVisible: true,
10 service: null, 10 service: null,
11 authInfo: null, 11 authInfo: null,
12}; 12};
@@ -15,7 +15,6 @@ export const state = observable(defaultState);
15 15
16export function resetState() { 16export function resetState() {
17 Object.assign(state, defaultState); 17 Object.assign(state, defaultState);
18 console.log('reset state', state);
19} 18}
20 19
21export default function initialize() { 20export default function initialize() {
@@ -31,15 +30,6 @@ export default function initialize() {
31 state.authInfo = data.authInfo; 30 state.authInfo = data.authInfo;
32 state.isModalVisible = true; 31 state.isModalVisible = true;
33 }); 32 });
34
35 // autorun(() => {
36 // // if (state.serviceId) {
37 // // const service = stores.services.one(state.serviceId);
38 // // if (service) {
39 // // state.service = service;
40 // // }
41 // // }
42 // });
43} 33}
44 34
45export function mainIpcHandler(mainWindow, authInfo) { 35export function mainIpcHandler(mainWindow, authInfo) {
diff --git a/src/features/delayApp/Component.js b/src/features/delayApp/Component.js
index ff84510e8..ff0f1f2f8 100644
--- a/src/features/delayApp/Component.js
+++ b/src/features/delayApp/Component.js
@@ -38,7 +38,7 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp
38 38
39 state = { 39 state = {
40 countdown: config.delayDuration, 40 countdown: config.delayDuration,
41 } 41 };
42 42
43 countdownInterval = null; 43 countdownInterval = null;
44 44
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js
index 28aa50eb2..67f0fc5e6 100644
--- a/src/features/delayApp/index.js
+++ b/src/features/delayApp/index.js
@@ -3,7 +3,7 @@ import moment from 'moment';
3import DelayAppComponent from './Component'; 3import DelayAppComponent from './Component';
4 4
5import { DEFAULT_FEATURES_CONFIG } from '../../config'; 5import { DEFAULT_FEATURES_CONFIG } from '../../config';
6import { gaEvent } from '../../lib/analytics'; 6import { gaEvent, gaPage } from '../../lib/analytics';
7 7
8const debug = require('debug')('Franz:feature:delayApp'); 8const debug = require('debug')('Franz:feature:delayApp');
9 9
@@ -28,8 +28,12 @@ export default function init(stores) {
28 let shownAfterLaunch = false; 28 let shownAfterLaunch = false;
29 let timeLastDelay = moment(); 29 let timeLastDelay = moment();
30 30
31 window.franz.features.delayApp = {
32 state,
33 };
34
31 reaction( 35 reaction(
32 () => stores.features.features.needToWaitToProceed && !stores.user.data.isPremium, 36 () => stores.user.isLoggedIn && stores.features.features.needToWaitToProceed && !stores.user.data.isPremium,
33 (isEnabled) => { 37 (isEnabled) => {
34 if (isEnabled) { 38 if (isEnabled) {
35 debug('Enabling `delayApp` feature'); 39 debug('Enabling `delayApp` feature');
@@ -50,7 +54,8 @@ export default function init(stores) {
50 debug(`App will be delayed for ${config.delayDuration / 1000}s`); 54 debug(`App will be delayed for ${config.delayDuration / 1000}s`);
51 55
52 setVisibility(true); 56 setVisibility(true);
53 gaEvent('delayApp', 'show', 'Delay App Feature'); 57 gaPage('/delayApp');
58 gaEvent('DelayApp', 'show', 'Delay App Feature');
54 59
55 timeLastDelay = moment(); 60 timeLastDelay = moment();
56 shownAfterLaunch = true; 61 shownAfterLaunch = true;
diff --git a/src/features/settingsWS/actions.js b/src/features/settingsWS/actions.js
new file mode 100755
index 000000000..631670c8a
--- /dev/null
+++ b/src/features/settingsWS/actions.js
@@ -0,0 +1,10 @@
1import PropTypes from 'prop-types';
2import { createActionsFromDefinitions } from '../../actions/lib/actions';
3
4export const settingsWSActions = createActionsFromDefinitions({
5 greet: {
6 name: PropTypes.string.isRequired,
7 },
8}, PropTypes.checkPropTypes);
9
10export default settingsWSActions;
diff --git a/src/features/settingsWS/index.js b/src/features/settingsWS/index.js
new file mode 100755
index 000000000..2064d2973
--- /dev/null
+++ b/src/features/settingsWS/index.js
@@ -0,0 +1,29 @@
1import { reaction } from 'mobx';
2import { SettingsWSStore } from './store';
3
4const debug = require('debug')('Franz:feature:settingsWS');
5
6export const settingsStore = new SettingsWSStore();
7
8export default function initSettingsWebSocket(stores, actions) {
9 const { features } = stores;
10
11 // Toggle SettingsWebSocket feature
12 reaction(
13 () => (
14 features.features.isSettingsWSEnabled
15 ),
16 (isEnabled) => {
17 if (isEnabled) {
18 debug('Initializing `settingsWS` feature');
19 settingsStore.start(stores, actions);
20 } else if (settingsStore) {
21 debug('Disabling `settingsWS` feature');
22 settingsStore.stop();
23 }
24 },
25 {
26 fireImmediately: true,
27 },
28 );
29}
diff --git a/src/features/settingsWS/state.js b/src/features/settingsWS/state.js
new file mode 100755
index 000000000..7b16b2b6e
--- /dev/null
+++ b/src/features/settingsWS/state.js
@@ -0,0 +1,13 @@
1import { observable } from 'mobx';
2
3const defaultState = {
4 isFeatureActive: false,
5};
6
7export const settingsWSState = observable(defaultState);
8
9export function resetState() {
10 Object.assign(settingsWSState, defaultState);
11}
12
13export default settingsWSState;
diff --git a/src/features/settingsWS/store.js b/src/features/settingsWS/store.js
new file mode 100755
index 000000000..167a70d10
--- /dev/null
+++ b/src/features/settingsWS/store.js
@@ -0,0 +1,130 @@
1import { observable } from 'mobx';
2import WebSocket from 'ws';
3import ms from 'ms';
4
5import { FeatureStore } from '../utils/FeatureStore';
6import { createReactions } from '../../stores/lib/Reaction';
7import { WS_API } from '../../environment';
8
9const debug = require('debug')('Franz:feature:settingsWS:store');
10
11export class SettingsWSStore extends FeatureStore {
12 stores = null;
13
14 actions = null;
15
16 ws = null;
17
18 pingTimeout = null;
19
20 reconnectTimeout = null;
21
22 @observable connected = false;
23
24 start(stores, actions) {
25 this.stores = stores;
26 this.actions = actions;
27
28 this._registerReactions(createReactions([
29 this._initialize.bind(this),
30 this._reconnect.bind(this),
31 this._close.bind(this),
32 ]));
33 }
34
35 connect() {
36 try {
37 const wsURL = `${WS_API}/ws/${this.stores.user.data.id}`;
38 debug('Setting up WebSocket to', wsURL);
39
40 this.ws = new WebSocket(wsURL);
41
42 this.ws.on('open', () => {
43 debug('Opened WebSocket');
44 this.send({
45 action: 'authorize',
46 token: this.stores.user.authToken,
47 });
48
49 this.connected = true;
50
51 this.heartbeat();
52 });
53
54 this.ws.on('message', (data) => {
55 const resp = JSON.parse(data);
56 debug('Received message', resp);
57
58 if (resp.id) {
59 this.stores.user.getUserInfoRequest.patch((result) => {
60 if (!result) return;
61
62 debug('Patching user object with new values');
63 Object.assign(result, resp);
64 });
65 }
66 });
67
68 this.ws.on('ping', this.heartbeat.bind(this));
69 } catch (err) {
70 console.err(err);
71 }
72 }
73
74 heartbeat() {
75 debug('Heartbeat');
76 clearTimeout(this.pingTimeout);
77
78 this.pingTimeout = setTimeout(() => {
79 debug('Terminating connection, reconnecting in 35');
80 this.ws.terminate();
81
82 this.connected = false;
83 }, ms('35s'));
84 }
85
86 send(data) {
87 if (this.ws && this.ws.readyState === 1) {
88 this.ws.send(JSON.stringify(data));
89 debug('Sending data', data);
90 } else {
91 debug('WebSocket is not initialized');
92 }
93 }
94
95 // Reactions
96
97 _initialize() {
98 if (this.stores.user.data.id && !this.ws) {
99 this.connect();
100 }
101 }
102
103 _reconnect() {
104 if (!this.connected) {
105 debug('Trying to reconnect in 30s');
106 this.reconnectTimeout = setInterval(() => {
107 debug('Trying to reconnect');
108 this.connect();
109 }, ms('30s'));
110 } else {
111 debug('Clearing reconnect interval');
112 clearInterval(this.reconnectTimeout);
113 }
114 }
115
116 _close() {
117 if (!this.stores.user.isLoggedIn) {
118 debug('Stopping reactions');
119 this._stopReactions();
120
121 if (this.ws) {
122 debug('Terminating connection');
123 this.ws.terminate();
124 this.ws = null;
125 }
126 }
127 }
128}
129
130export default SettingsWSStore;
diff --git a/src/features/shareFranz/Component.js b/src/features/shareFranz/Component.js
new file mode 100644
index 000000000..8d1d595c5
--- /dev/null
+++ b/src/features/shareFranz/Component.js
@@ -0,0 +1,166 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer, inject } from 'mobx-react';
4import injectSheet from 'react-jss';
5import { defineMessages, intlShape } from 'react-intl';
6import { Button } from '@meetfranz/forms';
7import { H1, Icon } from '@meetfranz/ui';
8
9import Modal from '../../components/ui/Modal';
10import { state } from '.';
11import { gaEvent } from '../../lib/analytics';
12import ServicesStore from '../../stores/ServicesStore';
13
14const messages = defineMessages({
15 headline: {
16 id: 'feature.shareFranz.headline',
17 defaultMessage: '!!!Franz is better together!',
18 },
19 text: {
20 id: 'feature.shareFranz.text',
21 defaultMessage: '!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.',
22 },
23 actionsEmail: {
24 id: 'feature.shareFranz.action.email',
25 defaultMessage: '!!!Share as email',
26 },
27 actionsFacebook: {
28 id: 'feature.shareFranz.action.facebook',
29 defaultMessage: '!!!Share on Facebook',
30 },
31 actionsTwitter: {
32 id: 'feature.shareFranz.action.twitter',
33 defaultMessage: '!!!Share on Twitter',
34 },
35 shareTextEmail: {
36 id: 'feature.shareFranz.shareText.email',
37 defaultMessage: '!!! I\'ve added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com',
38 },
39 shareTextTwitter: {
40 id: 'feature.shareFranz.shareText.twitter',
41 defaultMessage: '!!! I\'ve added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger',
42 },
43});
44
45const styles = theme => ({
46 modal: {
47 width: '80%',
48 maxWidth: 600,
49 background: theme.styleTypes.primary.accent,
50 textAlign: 'center',
51 color: theme.styleTypes.primary.contrast,
52 },
53 heartContainer: {
54 display: 'flex',
55 justifyContent: 'center',
56 borderRadius: '100%',
57 background: theme.brandDanger,
58 padding: 20,
59 width: 100,
60 height: 100,
61 margin: [-70, 'auto', 30],
62 },
63 heart: {
64 fill: theme.styleTypes.primary.contrast,
65 },
66 headline: {
67 textAlign: 'center',
68 fontSize: 40,
69 marginBottom: 20,
70 },
71 actions: {
72 display: 'flex',
73 justifyContent: 'space-between',
74 marginTop: 30,
75 },
76 cta: {
77 background: theme.styleTypes.primary.contrast,
78 color: theme.styleTypes.primary.accent,
79
80 '& svg': {
81 fill: theme.styleTypes.primary.accent,
82 },
83 },
84});
85
86export default @injectSheet(styles) @inject('stores') @observer class ShareFranzModal extends Component {
87 static propTypes = {
88 classes: PropTypes.object.isRequired,
89 };
90
91 static contextTypes = {
92 intl: intlShape,
93 };
94
95 close() {
96 state.isModalVisible = false;
97 }
98
99 render() {
100 const { isModalVisible } = state;
101
102 const {
103 classes,
104 stores,
105 } = this.props;
106
107 const serviceCount = stores.services.all.length;
108
109 const { intl } = this.context;
110
111 return (
112 <Modal
113 isOpen={isModalVisible}
114 className={classes.modal}
115 shouldCloseOnOverlayClick
116 close={this.close.bind(this)}
117 >
118 <div className={classes.heartContainer}>
119 <Icon icon="mdiHeart" className={classes.heart} size={4} />
120 </div>
121 <H1 className={classes.headline}>
122 {intl.formatMessage(messages.headline)}
123 </H1>
124 <p>{intl.formatMessage(messages.text)}</p>
125 <div className={classes.actions}>
126 <Button
127 label={intl.formatMessage(messages.actionsEmail)}
128 className={classes.cta}
129 icon="mdiEmail"
130 href={`mailto:?subject=Meet the cool app Franz&body=${intl.formatMessage(messages.shareTextEmail, { count: serviceCount })}}`}
131 target="_blank"
132 onClick={() => {
133 gaEvent('Share Franz', 'share', 'Share via email');
134 }}
135 />
136 <Button
137 label={intl.formatMessage(messages.actionsFacebook)}
138 className={classes.cta}
139 icon="mdiFacebookBox"
140 href="https://www.facebook.com/sharer/sharer.php?u=https://www.meetfranz.com?utm_source=facebook&utm_medium=referral&utm_campaign=share-button"
141 target="_blank"
142 onClick={() => {
143 gaEvent('Share Franz', 'share', 'Share via Facebook');
144 }}
145 />
146 <Button
147 label={intl.formatMessage(messages.actionsTwitter)}
148 className={classes.cta}
149 icon="mdiTwitter"
150 href={`http://twitter.com/intent/tweet?status=${intl.formatMessage(messages.shareTextTwitter, { count: serviceCount })}`}
151 target="_blank"
152 onClick={() => {
153 gaEvent('Share Franz', 'share', 'Share via Twitter');
154 }}
155 />
156 </div>
157 </Modal>
158 );
159 }
160}
161
162ShareFranzModal.wrappedComponent.propTypes = {
163 stores: PropTypes.shape({
164 services: PropTypes.instanceOf(ServicesStore).isRequired,
165 }).isRequired,
166};
diff --git a/src/features/shareFranz/index.js b/src/features/shareFranz/index.js
new file mode 100644
index 000000000..87deacef4
--- /dev/null
+++ b/src/features/shareFranz/index.js
@@ -0,0 +1,52 @@
1import { observable, reaction } from 'mobx';
2import ms from 'ms';
3
4import { state as delayAppState } from '../delayApp';
5import { gaEvent, gaPage } from '../../lib/analytics';
6
7export { default as Component } from './Component';
8
9const debug = require('debug')('Franz:feature:shareFranz');
10
11const defaultState = {
12 isModalVisible: false,
13 lastShown: null,
14};
15
16export const state = observable(defaultState);
17
18export default function initialize(stores) {
19 debug('Initialize shareFranz feature');
20
21 window.franz.features.shareFranz = {
22 state,
23 };
24
25 function showModal() {
26 debug('Showing share window');
27
28 state.isModalVisible = true;
29
30 gaEvent('Share Franz', 'show');
31 gaPage('/share-modal');
32 }
33
34 reaction(
35 () => stores.user.isLoggedIn,
36 () => {
37 setTimeout(() => {
38 if (stores.settings.stats.appStarts % 50 === 0) {
39 if (delayAppState.isDelayAppScreenVisible) {
40 debug('Delaying share modal by 5 minutes');
41 setTimeout(() => showModal(), ms('5m'));
42 } else {
43 showModal();
44 }
45 }
46 }, ms('2s'));
47 },
48 {
49 fireImmediately: true,
50 },
51 );
52}
diff --git a/src/features/spellchecker/index.js b/src/features/spellchecker/index.js
index 63506103c..79a2172b4 100644
--- a/src/features/spellchecker/index.js
+++ b/src/features/spellchecker/index.js
@@ -5,7 +5,7 @@ import { DEFAULT_FEATURES_CONFIG } from '../../config';
5const debug = require('debug')('Franz:feature:spellchecker'); 5const debug = require('debug')('Franz:feature:spellchecker');
6 6
7export const config = observable({ 7export const config = observable({
8 isPremiumFeature: DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature, 8 isPremium: DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature,
9}); 9});
10 10
11export default function init(stores) { 11export default function init(stores) {
@@ -14,9 +14,9 @@ export default function init(stores) {
14 autorun(() => { 14 autorun(() => {
15 const { isSpellcheckerPremiumFeature } = stores.features.features; 15 const { isSpellcheckerPremiumFeature } = stores.features.features;
16 16
17 config.isPremiumFeature = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature; 17 config.isPremium = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature;
18 18
19 if (!stores.user.data.isPremium && config.isPremiumFeature && stores.settings.app.enableSpellchecking) { 19 if (!stores.user.data.isPremium && config.isPremium && stores.settings.app.enableSpellchecking) {
20 debug('Override settings.spellcheckerEnabled flag to false'); 20 debug('Override settings.spellcheckerEnabled flag to false');
21 21
22 Object.assign(stores.settings.app, { 22 Object.assign(stores.settings.app, {
diff --git a/src/features/utils/ActionBinding.js b/src/features/utils/ActionBinding.js
new file mode 100644
index 000000000..497aa071b
--- /dev/null
+++ b/src/features/utils/ActionBinding.js
@@ -0,0 +1,29 @@
1export default class ActionBinding {
2 action;
3
4 isActive = false;
5
6 constructor(action) {
7 this.action = action;
8 }
9
10 start() {
11 if (!this.isActive) {
12 const { action } = this;
13 action[0].listen(action[1]);
14 this.isActive = true;
15 }
16 }
17
18 stop() {
19 if (this.isActive) {
20 const { action } = this;
21 action[0].off(action[1]);
22 this.isActive = false;
23 }
24 }
25}
26
27export const createActionBindings = actions => (
28 actions.map(a => new ActionBinding(a))
29);
diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js
new file mode 100644
index 000000000..0bc10e176
--- /dev/null
+++ b/src/features/utils/FeatureStore.js
@@ -0,0 +1,40 @@
1export class FeatureStore {
2 _actions = [];
3
4 _reactions = [];
5
6 stop() {
7 this._stopActions();
8 this._stopReactions();
9 }
10
11 // ACTIONS
12
13 _registerActions(actions) {
14 this._actions = actions;
15 this._startActions();
16 }
17
18 _startActions(actions = this._actions) {
19 actions.forEach(a => a.start());
20 }
21
22 _stopActions(actions = this._actions) {
23 actions.forEach(a => a.stop());
24 }
25
26 // REACTIONS
27
28 _registerReactions(reactions) {
29 this._reactions = reactions;
30 this._startReactions();
31 }
32
33 _startReactions(reactions = this._reactions) {
34 reactions.forEach(r => r.start());
35 }
36
37 _stopReactions(reactions = this._reactions) {
38 reactions.forEach(r => r.stop());
39 }
40}
diff --git a/src/features/utils/FeatureStore.test.js b/src/features/utils/FeatureStore.test.js
new file mode 100644
index 000000000..92308bf52
--- /dev/null
+++ b/src/features/utils/FeatureStore.test.js
@@ -0,0 +1,92 @@
1import PropTypes from 'prop-types';
2import { observable } from 'mobx';
3import { FeatureStore } from './FeatureStore';
4import { createActionsFromDefinitions } from '../../actions/lib/actions';
5import { createActionBindings } from './ActionBinding';
6import { createReactions } from '../../stores/lib/Reaction';
7
8const actions = createActionsFromDefinitions({
9 countUp: {},
10}, PropTypes.checkPropTypes);
11
12class TestFeatureStore extends FeatureStore {
13 @observable count = 0;
14
15 reactionInvokedCount = 0;
16
17 start() {
18 this._registerActions(createActionBindings([
19 [actions.countUp, this._countUp],
20 ]));
21 this._registerReactions(createReactions([
22 this._countReaction,
23 ]));
24 }
25
26 _countUp = () => {
27 this.count += 1;
28 };
29
30 _countReaction = () => {
31 this.reactionInvokedCount += 1;
32 }
33}
34
35describe('FeatureStore', () => {
36 let store = null;
37
38 beforeEach(() => {
39 store = new TestFeatureStore();
40 });
41
42 describe('registering actions', () => {
43 it('starts the actions', () => {
44 store.start();
45 actions.countUp();
46 expect(store.count).toBe(1);
47 });
48 it('starts the reactions', () => {
49 store.start();
50 actions.countUp();
51 expect(store.reactionInvokedCount).toBe(1);
52 });
53 });
54
55 describe('stopping the store', () => {
56 it('stops the actions', () => {
57 store.start();
58 actions.countUp();
59 store.stop();
60 actions.countUp();
61 expect(store.count).toBe(1);
62 });
63 it('stops the reactions', () => {
64 store.start();
65 actions.countUp();
66 store.stop();
67 store.count += 1;
68 expect(store.reactionInvokedCount).toBe(1);
69 });
70 });
71
72 describe('toggling the store', () => {
73 it('restarts the actions correctly', () => {
74 store.start();
75 actions.countUp();
76 store.stop();
77 actions.countUp();
78 store.start();
79 actions.countUp();
80 expect(store.count).toBe(2);
81 });
82 it('restarts the reactions correctly', () => {
83 store.start();
84 actions.countUp();
85 store.stop();
86 actions.countUp();
87 store.start();
88 actions.countUp();
89 expect(store.count).toBe(2);
90 });
91 });
92});
diff --git a/src/features/workspaces/actions.js b/src/features/workspaces/actions.js
new file mode 100644
index 000000000..a85f8f57f
--- /dev/null
+++ b/src/features/workspaces/actions.js
@@ -0,0 +1,26 @@
1import PropTypes from 'prop-types';
2import Workspace from './models/Workspace';
3import { createActionsFromDefinitions } from '../../actions/lib/actions';
4
5export const workspaceActions = createActionsFromDefinitions({
6 edit: {
7 workspace: PropTypes.instanceOf(Workspace).isRequired,
8 },
9 create: {
10 name: PropTypes.string.isRequired,
11 },
12 delete: {
13 workspace: PropTypes.instanceOf(Workspace).isRequired,
14 },
15 update: {
16 workspace: PropTypes.instanceOf(Workspace).isRequired,
17 },
18 activate: {
19 workspace: PropTypes.instanceOf(Workspace).isRequired,
20 },
21 deactivate: {},
22 toggleWorkspaceDrawer: {},
23 openWorkspaceSettings: {},
24}, PropTypes.checkPropTypes);
25
26export default workspaceActions;
diff --git a/src/features/workspaces/api.js b/src/features/workspaces/api.js
new file mode 100644
index 000000000..0ec20c9ea
--- /dev/null
+++ b/src/features/workspaces/api.js
@@ -0,0 +1,66 @@
1import { pick } from 'lodash';
2import { sendAuthRequest } from '../../api/utils/auth';
3import { API, API_VERSION } from '../../environment';
4import Request from '../../stores/lib/Request';
5import Workspace from './models/Workspace';
6
7const debug = require('debug')('Franz:feature:workspaces:api');
8
9export const workspaceApi = {
10 getUserWorkspaces: async () => {
11 const url = `${API}/${API_VERSION}/workspace`;
12 debug('getUserWorkspaces GET', url);
13 const result = await sendAuthRequest(url, { method: 'GET' });
14 debug('getUserWorkspaces RESULT', result);
15 if (!result.ok) throw result;
16 const workspaces = await result.json();
17 return workspaces.map(data => new Workspace(data));
18 },
19
20 createWorkspace: async (name) => {
21 const url = `${API}/${API_VERSION}/workspace`;
22 const options = {
23 method: 'POST',
24 body: JSON.stringify({ name }),
25 };
26 debug('createWorkspace POST', url, options);
27 const result = await sendAuthRequest(url, options);
28 debug('createWorkspace RESULT', result);
29 if (!result.ok) throw result;
30 return new Workspace(await result.json());
31 },
32
33 deleteWorkspace: async (workspace) => {
34 const url = `${API}/${API_VERSION}/workspace/${workspace.id}`;
35 debug('deleteWorkspace DELETE', url);
36 const result = await sendAuthRequest(url, { method: 'DELETE' });
37 debug('deleteWorkspace RESULT', result);
38 if (!result.ok) throw result;
39 return true;
40 },
41
42 updateWorkspace: async (workspace) => {
43 const url = `${API}/${API_VERSION}/workspace/${workspace.id}`;
44 const options = {
45 method: 'PUT',
46 body: JSON.stringify(pick(workspace, ['name', 'services'])),
47 };
48 debug('updateWorkspace UPDATE', url, options);
49 const result = await sendAuthRequest(url, options);
50 debug('updateWorkspace RESULT', result);
51 if (!result.ok) throw result;
52 return new Workspace(await result.json());
53 },
54};
55
56export const getUserWorkspacesRequest = new Request(workspaceApi, 'getUserWorkspaces');
57export const createWorkspaceRequest = new Request(workspaceApi, 'createWorkspace');
58export const deleteWorkspaceRequest = new Request(workspaceApi, 'deleteWorkspace');
59export const updateWorkspaceRequest = new Request(workspaceApi, 'updateWorkspace');
60
61export const resetApiRequests = () => {
62 getUserWorkspacesRequest.reset();
63 createWorkspaceRequest.reset();
64 deleteWorkspaceRequest.reset();
65 updateWorkspaceRequest.reset();
66};
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js
new file mode 100644
index 000000000..cddbb2b04
--- /dev/null
+++ b/src/features/workspaces/components/CreateWorkspaceForm.js
@@ -0,0 +1,100 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import { Input, Button } from '@meetfranz/forms';
6import injectSheet from 'react-jss';
7import Form from '../../../lib/Form';
8import { required } from '../../../helpers/validation-helpers';
9import { gaEvent } from '../../../lib/analytics';
10import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../index';
11
12const messages = defineMessages({
13 submitButton: {
14 id: 'settings.workspace.add.form.submitButton',
15 defaultMessage: '!!!Create workspace',
16 },
17 name: {
18 id: 'settings.workspace.add.form.name',
19 defaultMessage: '!!!Name',
20 },
21});
22
23const styles = () => ({
24 form: {
25 display: 'flex',
26 },
27 input: {
28 flexGrow: 1,
29 marginRight: '10px',
30 },
31 submitButton: {
32 height: 'inherit',
33 },
34});
35
36@injectSheet(styles) @observer
37class CreateWorkspaceForm extends Component {
38 static contextTypes = {
39 intl: intlShape,
40 };
41
42 static propTypes = {
43 classes: PropTypes.object.isRequired,
44 isSubmitting: PropTypes.bool.isRequired,
45 onSubmit: PropTypes.func.isRequired,
46 };
47
48 form = (() => {
49 const { intl } = this.context;
50 return new Form({
51 fields: {
52 name: {
53 label: intl.formatMessage(messages.name),
54 placeholder: intl.formatMessage(messages.name),
55 value: '',
56 validators: [required],
57 },
58 },
59 });
60 })();
61
62 submitForm() {
63 const { form } = this;
64 form.submit({
65 onSuccess: async (f) => {
66 const { onSubmit } = this.props;
67 const values = f.values();
68 onSubmit(values);
69 gaEvent(GA_CATEGORY_WORKSPACES, 'create', values.name);
70 },
71 });
72 }
73
74 render() {
75 const { intl } = this.context;
76 const { classes, isSubmitting } = this.props;
77 const { form } = this;
78 return (
79 <div className={classes.form}>
80 <Input
81 className={classes.input}
82 {...form.$('name').bind()}
83 showLabel={false}
84 onEnterKey={this.submitForm.bind(this, form)}
85 focus={workspaceStore.isUserAllowedToUseFeature}
86 />
87 <Button
88 className={classes.submitButton}
89 type="submit"
90 label={intl.formatMessage(messages.submitButton)}
91 onClick={this.submitForm.bind(this, form)}
92 busy={isSubmitting}
93 buttonType={isSubmitting ? 'secondary' : 'primary'}
94 />
95 </div>
96 );
97 }
98}
99
100export default CreateWorkspaceForm;
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js
new file mode 100644
index 000000000..e602ebd5a
--- /dev/null
+++ b/src/features/workspaces/components/EditWorkspaceForm.js
@@ -0,0 +1,212 @@
1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import { Link } from 'react-router';
6import { Input, Button } from '@meetfranz/forms';
7import injectSheet from 'react-jss';
8
9import Workspace from '../models/Workspace';
10import Service from '../../../models/Service';
11import Form from '../../../lib/Form';
12import { required } from '../../../helpers/validation-helpers';
13import WorkspaceServiceListItem from './WorkspaceServiceListItem';
14import Request from '../../../stores/lib/Request';
15import { gaEvent } from '../../../lib/analytics';
16import { GA_CATEGORY_WORKSPACES } from '../index';
17
18const messages = defineMessages({
19 buttonDelete: {
20 id: 'settings.workspace.form.buttonDelete',
21 defaultMessage: '!!!Delete workspace',
22 },
23 buttonSave: {
24 id: 'settings.workspace.form.buttonSave',
25 defaultMessage: '!!!Save workspace',
26 },
27 name: {
28 id: 'settings.workspace.form.name',
29 defaultMessage: '!!!Name',
30 },
31 yourWorkspaces: {
32 id: 'settings.workspace.form.yourWorkspaces',
33 defaultMessage: '!!!Your workspaces',
34 },
35 servicesInWorkspaceHeadline: {
36 id: 'settings.workspace.form.servicesInWorkspaceHeadline',
37 defaultMessage: '!!!Services in this Workspace',
38 },
39 noServicesAdded: {
40 id: 'settings.services.noServicesAdded',
41 defaultMessage: '!!!You haven\'t added any services yet.',
42 },
43 discoverServices: {
44 id: 'settings.services.discoverServices',
45 defaultMessage: '!!!Discover services',
46 },
47});
48
49const styles = () => ({
50 nameInput: {
51 height: 'auto',
52 },
53 serviceList: {
54 height: 'auto',
55 },
56});
57
58@injectSheet(styles) @observer
59class EditWorkspaceForm extends Component {
60 static contextTypes = {
61 intl: intlShape,
62 };
63
64 static propTypes = {
65 classes: PropTypes.object.isRequired,
66 onDelete: PropTypes.func.isRequired,
67 onSave: PropTypes.func.isRequired,
68 services: PropTypes.arrayOf(PropTypes.instanceOf(Service)).isRequired,
69 workspace: PropTypes.instanceOf(Workspace).isRequired,
70 updateWorkspaceRequest: PropTypes.instanceOf(Request).isRequired,
71 deleteWorkspaceRequest: PropTypes.instanceOf(Request).isRequired,
72 };
73
74 form = this.prepareWorkspaceForm(this.props.workspace);
75
76 componentWillReceiveProps(nextProps) {
77 const { workspace } = this.props;
78 if (workspace.id !== nextProps.workspace.id) {
79 this.form = this.prepareWorkspaceForm(nextProps.workspace);
80 }
81 }
82
83 prepareWorkspaceForm(workspace) {
84 const { intl } = this.context;
85 return new Form({
86 fields: {
87 name: {
88 label: intl.formatMessage(messages.name),
89 placeholder: intl.formatMessage(messages.name),
90 value: workspace.name,
91 validators: [required],
92 },
93 services: {
94 value: workspace.services.slice(),
95 },
96 },
97 });
98 }
99
100 save(form) {
101 form.submit({
102 onSuccess: async (f) => {
103 const { onSave } = this.props;
104 const values = f.values();
105 onSave(values);
106 gaEvent(GA_CATEGORY_WORKSPACES, 'save');
107 },
108 onError: async () => {},
109 });
110 }
111
112 delete() {
113 const { onDelete } = this.props;
114 onDelete();
115 gaEvent(GA_CATEGORY_WORKSPACES, 'delete');
116 }
117
118 toggleService(service) {
119 const servicesField = this.form.$('services');
120 const serviceIds = servicesField.value;
121 if (serviceIds.includes(service.id)) {
122 serviceIds.splice(serviceIds.indexOf(service.id), 1);
123 } else {
124 serviceIds.push(service.id);
125 }
126 servicesField.set(serviceIds);
127 }
128
129 render() {
130 const { intl } = this.context;
131 const {
132 classes,
133 workspace,
134 services,
135 deleteWorkspaceRequest,
136 updateWorkspaceRequest,
137 } = this.props;
138 const { form } = this;
139 const workspaceServices = form.$('services').value;
140 const isDeleting = deleteWorkspaceRequest.isExecuting;
141 const isSaving = updateWorkspaceRequest.isExecuting;
142 return (
143 <div className="settings__main">
144 <div className="settings__header">
145 <span className="settings__header-item">
146 <Link to="/settings/workspaces">
147 {intl.formatMessage(messages.yourWorkspaces)}
148 </Link>
149 </span>
150 <span className="separator" />
151 <span className="settings__header-item">
152 {workspace.name}
153 </span>
154 </div>
155 <div className="settings__body">
156 <div className={classes.nameInput}>
157 <Input {...form.$('name').bind()} />
158 </div>
159 <h2>{intl.formatMessage(messages.servicesInWorkspaceHeadline)}</h2>
160 <div className={classes.serviceList}>
161 {services.length === 0 ? (
162 <div className="align-middle settings__empty-state">
163 {/* ===== Empty state ===== */}
164 <p className="settings__empty-text">
165 <span className="emoji">
166 <img src="./assets/images/emoji/sad.png" alt="" />
167 </span>
168 {intl.formatMessage(messages.noServicesAdded)}
169 </p>
170 <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link>
171 </div>
172 ) : (
173 <Fragment>
174 {services.map(s => (
175 <WorkspaceServiceListItem
176 key={s.id}
177 service={s}
178 isInWorkspace={workspaceServices.includes(s.id)}
179 onToggle={() => this.toggleService(s)}
180 />
181 ))}
182 </Fragment>
183 )}
184 </div>
185 </div>
186 <div className="settings__controls">
187 {/* ===== Delete Button ===== */}
188 <Button
189 label={intl.formatMessage(messages.buttonDelete)}
190 loaded={false}
191 busy={isDeleting}
192 buttonType={isDeleting ? 'secondary' : 'danger'}
193 className="settings__delete-button"
194 disabled={isDeleting}
195 onClick={this.delete.bind(this)}
196 />
197 {/* ===== Save Button ===== */}
198 <Button
199 type="submit"
200 label={intl.formatMessage(messages.buttonSave)}
201 busy={isSaving}
202 buttonType={isSaving ? 'secondary' : 'primary'}
203 onClick={this.save.bind(this, form)}
204 disabled={isSaving}
205 />
206 </div>
207 </div>
208 );
209 }
210}
211
212export default EditWorkspaceForm;
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js
new file mode 100644
index 000000000..684e50dd0
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceDrawer.js
@@ -0,0 +1,246 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import { defineMessages, FormattedHTMLMessage, intlShape } from 'react-intl';
6import { H1, Icon, ProBadge } from '@meetfranz/ui';
7import { Button } from '@meetfranz/forms/lib';
8import ReactTooltip from 'react-tooltip';
9
10import WorkspaceDrawerItem from './WorkspaceDrawerItem';
11import { workspaceActions } from '../actions';
12import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../index';
13import { gaEvent } from '../../../lib/analytics';
14
15const messages = defineMessages({
16 headline: {
17 id: 'workspaceDrawer.headline',
18 defaultMessage: '!!!Workspaces',
19 },
20 allServices: {
21 id: 'workspaceDrawer.allServices',
22 defaultMessage: '!!!All services',
23 },
24 workspacesSettingsTooltip: {
25 id: 'workspaceDrawer.workspacesSettingsTooltip',
26 defaultMessage: '!!!Workspaces settings',
27 },
28 workspaceFeatureInfo: {
29 id: 'workspaceDrawer.workspaceFeatureInfo',
30 defaultMessage: '!!!Info about workspace feature',
31 },
32 premiumCtaButtonLabel: {
33 id: 'workspaceDrawer.premiumCtaButtonLabel',
34 defaultMessage: '!!!Create your first workspace',
35 },
36 reactivatePremiumAccount: {
37 id: 'workspaceDrawer.reactivatePremiumAccountLabel',
38 defaultMessage: '!!!Reactivate premium account',
39 },
40 addNewWorkspaceLabel: {
41 id: 'workspaceDrawer.addNewWorkspaceLabel',
42 defaultMessage: '!!!add new workspace',
43 },
44 premiumFeatureBadge: {
45 id: 'workspaceDrawer.proFeatureBadge',
46 defaultMessage: '!!!Premium feature',
47 },
48});
49
50const styles = theme => ({
51 drawer: {
52 background: theme.workspaces.drawer.background,
53 width: `${theme.workspaces.drawer.width}px`,
54 },
55 headline: {
56 fontSize: '24px',
57 marginTop: '38px',
58 marginBottom: '25px',
59 marginLeft: theme.workspaces.drawer.padding,
60 },
61 headlineProBadge: {
62 marginRight: 15,
63 },
64 workspacesSettingsButton: {
65 float: 'right',
66 marginRight: theme.workspaces.drawer.padding,
67 marginTop: '2px',
68 },
69 workspacesSettingsButtonIcon: {
70 fill: theme.workspaces.drawer.buttons.color,
71 '&:hover': {
72 fill: theme.workspaces.drawer.buttons.hoverColor,
73 },
74 },
75 workspaces: {
76 height: 'auto',
77 },
78 premiumAnnouncement: {
79 padding: '20px',
80 paddingTop: '0',
81 height: 'auto',
82 },
83 premiumCtaButton: {
84 marginTop: '20px',
85 width: '100%',
86 color: 'white !important',
87 },
88 addNewWorkspaceLabel: {
89 height: 'auto',
90 color: theme.workspaces.drawer.buttons.color,
91 marginTop: 40,
92 textAlign: 'center',
93 '& > svg': {
94 fill: theme.workspaces.drawer.buttons.color,
95 },
96 '& > span': {
97 fontSize: '13px',
98 marginLeft: 10,
99 position: 'relative',
100 top: -3,
101 },
102 '&:hover': {
103 color: theme.workspaces.drawer.buttons.hoverColor,
104 '& > svg': {
105 fill: theme.workspaces.drawer.buttons.hoverColor,
106 },
107 },
108 },
109});
110
111@injectSheet(styles) @observer
112class WorkspaceDrawer extends Component {
113 static propTypes = {
114 classes: PropTypes.object.isRequired,
115 getServicesForWorkspace: PropTypes.func.isRequired,
116 onUpgradeAccountClick: PropTypes.func.isRequired,
117 };
118
119 static contextTypes = {
120 intl: intlShape,
121 };
122
123 componentDidMount() {
124 ReactTooltip.rebuild();
125 }
126
127 render() {
128 const {
129 classes,
130 getServicesForWorkspace,
131 onUpgradeAccountClick,
132 } = this.props;
133 const { intl } = this.context;
134 const {
135 activeWorkspace,
136 isSwitchingWorkspace,
137 nextWorkspace,
138 workspaces,
139 } = workspaceStore;
140 const actualWorkspace = isSwitchingWorkspace ? nextWorkspace : activeWorkspace;
141 return (
142 <div className={classes.drawer}>
143 <H1 className={classes.headline}>
144 {workspaceStore.isPremiumUpgradeRequired && (
145 <span
146 className={classes.headlineProBadge}
147 data-tip={`${intl.formatMessage(messages.premiumFeatureBadge)}`}
148 >
149 <ProBadge />
150 </span>
151 )}
152 {intl.formatMessage(messages.headline)}
153 <span
154 className={classes.workspacesSettingsButton}
155 onClick={() => {
156 workspaceActions.openWorkspaceSettings();
157 gaEvent(GA_CATEGORY_WORKSPACES, 'settings', 'drawerHeadline');
158 }}
159 data-tip={`${intl.formatMessage(messages.workspacesSettingsTooltip)}`}
160 >
161 <Icon
162 icon="mdiSettings"
163 size={1.5}
164 className={classes.workspacesSettingsButtonIcon}
165 />
166 </span>
167 </H1>
168 {workspaceStore.isPremiumUpgradeRequired ? (
169 <div className={classes.premiumAnnouncement}>
170 <FormattedHTMLMessage {...messages.workspaceFeatureInfo} />
171 {workspaceStore.userHasWorkspaces ? (
172 <Button
173 className={classes.premiumCtaButton}
174 buttonType="primary"
175 label={intl.formatMessage(messages.reactivatePremiumAccount)}
176 icon="mdiStar"
177 onClick={() => {
178 onUpgradeAccountClick();
179 gaEvent('User', 'upgrade', 'workspaceDrawer');
180 }}
181 />
182 ) : (
183 <Button
184 className={classes.premiumCtaButton}
185 buttonType="primary"
186 label={intl.formatMessage(messages.premiumCtaButtonLabel)}
187 icon="mdiPlusBox"
188 onClick={() => {
189 workspaceActions.openWorkspaceSettings();
190 gaEvent(GA_CATEGORY_WORKSPACES, 'add', 'drawerPremiumCta');
191 }}
192 />
193 )}
194 </div>
195 ) : (
196 <div className={classes.workspaces}>
197 <WorkspaceDrawerItem
198 name={intl.formatMessage(messages.allServices)}
199 onClick={() => {
200 workspaceActions.deactivate();
201 workspaceActions.toggleWorkspaceDrawer();
202 gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'drawer');
203 }}
204 services={getServicesForWorkspace(null)}
205 isActive={actualWorkspace == null}
206 />
207 {workspaces.map(workspace => (
208 <WorkspaceDrawerItem
209 key={workspace.id}
210 name={workspace.name}
211 isActive={actualWorkspace === workspace}
212 onClick={() => {
213 if (actualWorkspace === workspace) return;
214 workspaceActions.activate({ workspace });
215 workspaceActions.toggleWorkspaceDrawer();
216 gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'drawer');
217 }}
218 onContextMenuEditClick={() => workspaceActions.edit({ workspace })}
219 services={getServicesForWorkspace(workspace)}
220 />
221 ))}
222 <div
223 className={classes.addNewWorkspaceLabel}
224 onClick={() => {
225 workspaceActions.openWorkspaceSettings();
226 gaEvent(GA_CATEGORY_WORKSPACES, 'add', 'drawerAddLabel');
227 }}
228 >
229 <Icon
230 icon="mdiPlusBox"
231 size={1}
232 className={classes.workspacesSettingsButtonIcon}
233 />
234 <span>
235 {intl.formatMessage(messages.addNewWorkspaceLabel)}
236 </span>
237 </div>
238 </div>
239 )}
240 <ReactTooltip place="right" type="dark" effect="solid" />
241 </div>
242 );
243 }
244}
245
246export default WorkspaceDrawer;
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js
new file mode 100644
index 000000000..59a2144d3
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.js
@@ -0,0 +1,137 @@
1import { remote } from 'electron';
2import React, { Component } from 'react';
3import PropTypes from 'prop-types';
4import { observer } from 'mobx-react';
5import injectSheet from 'react-jss';
6import classnames from 'classnames';
7import { defineMessages, intlShape } from 'react-intl';
8
9const { Menu } = remote;
10
11const messages = defineMessages({
12 noServicesAddedYet: {
13 id: 'workspaceDrawer.item.noServicesAddedYet',
14 defaultMessage: '!!!No services added yet',
15 },
16 contextMenuEdit: {
17 id: 'workspaceDrawer.item.contextMenuEdit',
18 defaultMessage: '!!!edit',
19 },
20});
21
22const styles = theme => ({
23 item: {
24 height: '67px',
25 padding: `15px ${theme.workspaces.drawer.padding}px`,
26 borderBottom: `1px solid ${theme.workspaces.drawer.listItem.border}`,
27 transition: 'background-color 300ms ease-out',
28 '&:first-child': {
29 borderTop: `1px solid ${theme.workspaces.drawer.listItem.border}`,
30 },
31 '&:hover': {
32 backgroundColor: theme.workspaces.drawer.listItem.hoverBackground,
33 },
34 },
35 isActiveItem: {
36 backgroundColor: theme.workspaces.drawer.listItem.activeBackground,
37 '&:hover': {
38 backgroundColor: theme.workspaces.drawer.listItem.activeBackground,
39 },
40 },
41 name: {
42 marginTop: '4px',
43 color: theme.workspaces.drawer.listItem.name.color,
44 },
45 activeName: {
46 color: theme.workspaces.drawer.listItem.name.activeColor,
47 },
48 services: {
49 display: 'block',
50 fontSize: '11px',
51 marginTop: '5px',
52 color: theme.workspaces.drawer.listItem.services.color,
53 whiteSpace: 'nowrap',
54 textOverflow: 'ellipsis',
55 overflow: 'hidden',
56 lineHeight: '15px',
57 },
58 activeServices: {
59 color: theme.workspaces.drawer.listItem.services.active,
60 },
61});
62
63@injectSheet(styles) @observer
64class WorkspaceDrawerItem extends Component {
65 static propTypes = {
66 classes: PropTypes.object.isRequired,
67 isActive: PropTypes.bool.isRequired,
68 name: PropTypes.string.isRequired,
69 onClick: PropTypes.func.isRequired,
70 services: PropTypes.arrayOf(PropTypes.string).isRequired,
71 onContextMenuEditClick: PropTypes.func,
72 };
73
74 static defaultProps = {
75 onContextMenuEditClick: null,
76 };
77
78 static contextTypes = {
79 intl: intlShape,
80 };
81
82 render() {
83 const {
84 classes,
85 isActive,
86 name,
87 onClick,
88 onContextMenuEditClick,
89 services,
90 } = this.props;
91 const { intl } = this.context;
92
93 const contextMenuTemplate = [{
94 label: name,
95 enabled: false,
96 }, {
97 type: 'separator',
98 }, {
99 label: intl.formatMessage(messages.contextMenuEdit),
100 click: onContextMenuEditClick,
101 }];
102
103 const contextMenu = Menu.buildFromTemplate(contextMenuTemplate);
104
105 return (
106 <div
107 className={classnames([
108 classes.item,
109 isActive ? classes.isActiveItem : null,
110 ])}
111 onClick={onClick}
112 onContextMenu={() => (
113 onContextMenuEditClick && contextMenu.popup(remote.getCurrentWindow())
114 )}
115 >
116 <span
117 className={classnames([
118 classes.name,
119 isActive ? classes.activeName : null,
120 ])}
121 >
122 {name}
123 </span>
124 <span
125 className={classnames([
126 classes.services,
127 isActive ? classes.activeServices : null,
128 ])}
129 >
130 {services.length ? services.join(', ') : intl.formatMessage(messages.noServicesAddedYet)}
131 </span>
132 </div>
133 );
134 }
135}
136
137export default WorkspaceDrawerItem;
diff --git a/src/features/workspaces/components/WorkspaceItem.js b/src/features/workspaces/components/WorkspaceItem.js
new file mode 100644
index 000000000..cc4b1a3ba
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceItem.js
@@ -0,0 +1,45 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { intlShape } from 'react-intl';
4import { observer } from 'mobx-react';
5import injectSheet from 'react-jss';
6
7import Workspace from '../models/Workspace';
8
9const styles = theme => ({
10 row: {
11 height: theme.workspaces.settings.listItems.height,
12 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`,
13 '&:hover': {
14 background: theme.workspaces.settings.listItems.hoverBgColor,
15 },
16 },
17 columnName: {},
18});
19
20@injectSheet(styles) @observer
21class WorkspaceItem extends Component {
22 static propTypes = {
23 classes: PropTypes.object.isRequired,
24 workspace: PropTypes.instanceOf(Workspace).isRequired,
25 onItemClick: PropTypes.func.isRequired,
26 };
27
28 static contextTypes = {
29 intl: intlShape,
30 };
31
32 render() {
33 const { classes, workspace, onItemClick } = this.props;
34
35 return (
36 <tr className={classes.row}>
37 <td onClick={() => onItemClick(workspace)}>
38 {workspace.name}
39 </td>
40 </tr>
41 );
42 }
43}
44
45export default WorkspaceItem;
diff --git a/src/features/workspaces/components/WorkspaceServiceListItem.js b/src/features/workspaces/components/WorkspaceServiceListItem.js
new file mode 100644
index 000000000..e05b21440
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceServiceListItem.js
@@ -0,0 +1,75 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import classnames from 'classnames';
6import { Toggle } from '@meetfranz/forms';
7
8import Service from '../../../models/Service';
9import ServiceIcon from '../../../components/ui/ServiceIcon';
10
11const styles = theme => ({
12 listItem: {
13 height: theme.workspaces.settings.listItems.height,
14 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`,
15 display: 'flex',
16 alignItems: 'center',
17 },
18 serviceIcon: {
19 padding: theme.workspaces.settings.listItems.padding,
20 },
21 toggle: {
22 height: 'auto',
23 margin: 0,
24 },
25 label: {
26 padding: theme.workspaces.settings.listItems.padding,
27 flexGrow: 1,
28 },
29 disabledLabel: {
30 color: theme.workspaces.settings.listItems.disabled.color,
31 },
32});
33
34@injectSheet(styles) @observer
35class WorkspaceServiceListItem extends Component {
36 static propTypes = {
37 classes: PropTypes.object.isRequired,
38 isInWorkspace: PropTypes.bool.isRequired,
39 onToggle: PropTypes.func.isRequired,
40 service: PropTypes.instanceOf(Service).isRequired,
41 };
42
43 render() {
44 const {
45 classes,
46 isInWorkspace,
47 onToggle,
48 service,
49 } = this.props;
50
51 return (
52 <div className={classes.listItem}>
53 <ServiceIcon
54 className={classes.serviceIcon}
55 service={service}
56 />
57 <span
58 className={classnames([
59 classes.label,
60 service.isEnabled ? null : classes.disabledLabel,
61 ])}
62 >
63 {service.name}
64 </span>
65 <Toggle
66 className={classes.toggle}
67 checked={isInWorkspace}
68 onChange={onToggle}
69 />
70 </div>
71 );
72 }
73}
74
75export default WorkspaceServiceListItem;
diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
new file mode 100644
index 000000000..c4a800a7b
--- /dev/null
+++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
@@ -0,0 +1,91 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import classnames from 'classnames';
6import { Loader } from '@meetfranz/ui';
7import { defineMessages, intlShape } from 'react-intl';
8
9import { workspaceStore } from '../index';
10
11const messages = defineMessages({
12 switchingTo: {
13 id: 'workspaces.switchingIndicator.switchingTo',
14 defaultMessage: '!!!Switching to',
15 },
16});
17
18const styles = theme => ({
19 wrapper: {
20 display: 'flex',
21 alignItems: 'flex-start',
22 position: 'absolute',
23 transition: 'width 0.5s ease',
24 width: '100%',
25 marginTop: '20px',
26 },
27 wrapperWhenDrawerIsOpen: {
28 width: `calc(100% - ${theme.workspaces.drawer.width}px)`,
29 },
30 component: {
31 background: 'rgba(20, 20, 20, 0.4)',
32 padding: '10px 20px',
33 display: 'flex',
34 width: 'auto',
35 height: 'auto',
36 margin: [0, 'auto'],
37 borderRadius: 6,
38 alignItems: 'center',
39 zIndex: 200,
40 },
41 spinner: {
42 width: 40,
43 height: 40,
44 marginRight: 10,
45 },
46 message: {
47 fontSize: 16,
48 whiteSpace: 'nowrap',
49 color: theme.colorAppLoaderSpinner,
50 },
51});
52
53@injectSheet(styles) @observer
54class WorkspaceSwitchingIndicator extends Component {
55 static propTypes = {
56 classes: PropTypes.object.isRequired,
57 theme: PropTypes.object.isRequired,
58 };
59
60 static contextTypes = {
61 intl: intlShape,
62 };
63
64 render() {
65 const { classes, theme } = this.props;
66 const { intl } = this.context;
67 const { isSwitchingWorkspace, isWorkspaceDrawerOpen, nextWorkspace } = workspaceStore;
68 if (!isSwitchingWorkspace) return null;
69 const nextWorkspaceName = nextWorkspace ? nextWorkspace.name : 'All services';
70 return (
71 <div
72 className={classnames([
73 classes.wrapper,
74 isWorkspaceDrawerOpen ? classes.wrapperWhenDrawerIsOpen : null,
75 ])}
76 >
77 <div className={classes.component}>
78 <Loader
79 className={classes.spinner}
80 color={theme.workspaces.switchingIndicator.spinnerColor}
81 />
82 <p className={classes.message}>
83 {`${intl.formatMessage(messages.switchingTo)} ${nextWorkspaceName}`}
84 </p>
85 </div>
86 </div>
87 );
88 }
89}
90
91export default WorkspaceSwitchingIndicator;
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js
new file mode 100644
index 000000000..09c98ab8c
--- /dev/null
+++ b/src/features/workspaces/components/WorkspacesDashboard.js
@@ -0,0 +1,209 @@
1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import injectSheet from 'react-jss';
6import { Infobox } from '@meetfranz/ui';
7
8import Loader from '../../../components/ui/Loader';
9import WorkspaceItem from './WorkspaceItem';
10import CreateWorkspaceForm from './CreateWorkspaceForm';
11import Request from '../../../stores/lib/Request';
12import Appear from '../../../components/ui/effects/Appear';
13import { workspaceStore } from '../index';
14import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer';
15
16const messages = defineMessages({
17 headline: {
18 id: 'settings.workspaces.headline',
19 defaultMessage: '!!!Your workspaces',
20 },
21 noServicesAdded: {
22 id: 'settings.workspaces.noWorkspacesAdded',
23 defaultMessage: '!!!You haven\'t added any workspaces yet.',
24 },
25 workspacesRequestFailed: {
26 id: 'settings.workspaces.workspacesRequestFailed',
27 defaultMessage: '!!!Could not load your workspaces',
28 },
29 tryReloadWorkspaces: {
30 id: 'settings.workspaces.tryReloadWorkspaces',
31 defaultMessage: '!!!Try again',
32 },
33 updatedInfo: {
34 id: 'settings.workspaces.updatedInfo',
35 defaultMessage: '!!!Your changes have been saved',
36 },
37 deletedInfo: {
38 id: 'settings.workspaces.deletedInfo',
39 defaultMessage: '!!!Workspace has been deleted',
40 },
41 workspaceFeatureInfo: {
42 id: 'settings.workspaces.workspaceFeatureInfo',
43 defaultMessage: '!!!Info about workspace feature',
44 },
45 workspaceFeatureHeadline: {
46 id: 'settings.workspaces.workspaceFeatureHeadline',
47 defaultMessage: '!!!Less is More: Introducing Franz Workspaces',
48 },
49});
50
51const styles = theme => ({
52 table: {
53 width: '100%',
54 '& td': {
55 padding: '10px',
56 },
57 },
58 createForm: {
59 height: 'auto',
60 },
61 appear: {
62 height: 'auto',
63 },
64 premiumAnnouncement: {
65 padding: '20px',
66 backgroundColor: '#3498db',
67 marginLeft: '-20px',
68 marginBottom: '20px',
69 height: 'auto',
70 color: 'white',
71 borderRadius: theme.borderRadius,
72 },
73});
74
75@injectSheet(styles) @observer
76class WorkspacesDashboard extends Component {
77 static propTypes = {
78 classes: PropTypes.object.isRequired,
79 getUserWorkspacesRequest: PropTypes.instanceOf(Request).isRequired,
80 createWorkspaceRequest: PropTypes.instanceOf(Request).isRequired,
81 deleteWorkspaceRequest: PropTypes.instanceOf(Request).isRequired,
82 updateWorkspaceRequest: PropTypes.instanceOf(Request).isRequired,
83 onCreateWorkspaceSubmit: PropTypes.func.isRequired,
84 onWorkspaceClick: PropTypes.func.isRequired,
85 workspaces: MobxPropTypes.arrayOrObservableArray.isRequired,
86 };
87
88 static contextTypes = {
89 intl: intlShape,
90 };
91
92 render() {
93 const {
94 classes,
95 getUserWorkspacesRequest,
96 createWorkspaceRequest,
97 deleteWorkspaceRequest,
98 updateWorkspaceRequest,
99 onCreateWorkspaceSubmit,
100 onWorkspaceClick,
101 workspaces,
102 } = this.props;
103 const { intl } = this.context;
104 return (
105 <div className="settings__main">
106 <div className="settings__header">
107 <h1>{intl.formatMessage(messages.headline)}</h1>
108 </div>
109 <div className="settings__body">
110
111 {/* ===== Workspace updated info ===== */}
112 {updateWorkspaceRequest.wasExecuted && updateWorkspaceRequest.result && (
113 <Appear className={classes.appear}>
114 <Infobox
115 type="success"
116 icon="mdiCheckboxMarkedCircleOutline"
117 dismissable
118 onUnmount={updateWorkspaceRequest.reset}
119 >
120 {intl.formatMessage(messages.updatedInfo)}
121 </Infobox>
122 </Appear>
123 )}
124
125 {/* ===== Workspace deleted info ===== */}
126 {deleteWorkspaceRequest.wasExecuted && deleteWorkspaceRequest.result && (
127 <Appear className={classes.appear}>
128 <Infobox
129 type="success"
130 icon="mdiCheckboxMarkedCircleOutline"
131 dismissable
132 onUnmount={deleteWorkspaceRequest.reset}
133 >
134 {intl.formatMessage(messages.deletedInfo)}
135 </Infobox>
136 </Appear>
137 )}
138
139 {workspaceStore.isPremiumUpgradeRequired && (
140 <div className={classes.premiumAnnouncement}>
141 <h2>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h2>
142 <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p>
143 </div>
144 )}
145
146 <PremiumFeatureContainer
147 condition={workspaceStore.isPremiumFeature}
148 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }}
149 >
150 {/* ===== Create workspace form ===== */}
151 <div className={classes.createForm}>
152 <CreateWorkspaceForm
153 isSubmitting={createWorkspaceRequest.isExecuting}
154 onSubmit={onCreateWorkspaceSubmit}
155 />
156 </div>
157 {getUserWorkspacesRequest.isExecuting ? (
158 <Loader />
159 ) : (
160 <Fragment>
161 {/* ===== Workspace could not be loaded error ===== */}
162 {getUserWorkspacesRequest.error ? (
163 <Infobox
164 icon="alert"
165 type="danger"
166 ctaLabel={intl.formatMessage(messages.tryReloadWorkspaces)}
167 ctaLoading={getUserWorkspacesRequest.isExecuting}
168 ctaOnClick={getUserWorkspacesRequest.retry}
169 >
170 {intl.formatMessage(messages.workspacesRequestFailed)}
171 </Infobox>
172 ) : (
173 <Fragment>
174 {workspaces.length === 0 ? (
175 <div className="align-middle settings__empty-state">
176 {/* ===== Workspaces empty state ===== */}
177 <p className="settings__empty-text">
178 <span className="emoji">
179 <img src="./assets/images/emoji/sad.png" alt="" />
180 </span>
181 {intl.formatMessage(messages.noServicesAdded)}
182 </p>
183 </div>
184 ) : (
185 <table className={classes.table}>
186 {/* ===== Workspaces list ===== */}
187 <tbody>
188 {workspaces.map(workspace => (
189 <WorkspaceItem
190 key={workspace.id}
191 workspace={workspace}
192 onItemClick={w => onWorkspaceClick(w)}
193 />
194 ))}
195 </tbody>
196 </table>
197 )}
198 </Fragment>
199 )}
200 </Fragment>
201 )}
202 </PremiumFeatureContainer>
203 </div>
204 </div>
205 );
206 }
207}
208
209export default WorkspacesDashboard;
diff --git a/src/features/workspaces/containers/EditWorkspaceScreen.js b/src/features/workspaces/containers/EditWorkspaceScreen.js
new file mode 100644
index 000000000..248b40131
--- /dev/null
+++ b/src/features/workspaces/containers/EditWorkspaceScreen.js
@@ -0,0 +1,60 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types';
4
5import ErrorBoundary from '../../../components/util/ErrorBoundary';
6import EditWorkspaceForm from '../components/EditWorkspaceForm';
7import ServicesStore from '../../../stores/ServicesStore';
8import Workspace from '../models/Workspace';
9import { workspaceStore } from '../index';
10import { deleteWorkspaceRequest, updateWorkspaceRequest } from '../api';
11
12@inject('stores', 'actions') @observer
13class EditWorkspaceScreen extends Component {
14 static propTypes = {
15 actions: PropTypes.shape({
16 workspace: PropTypes.shape({
17 delete: PropTypes.func.isRequired,
18 }),
19 }).isRequired,
20 stores: PropTypes.shape({
21 services: PropTypes.instanceOf(ServicesStore).isRequired,
22 }).isRequired,
23 };
24
25 onDelete = () => {
26 const { workspaceBeingEdited } = workspaceStore;
27 const { actions } = this.props;
28 if (!workspaceBeingEdited) return null;
29 actions.workspaces.delete({ workspace: workspaceBeingEdited });
30 };
31
32 onSave = (values) => {
33 const { workspaceBeingEdited } = workspaceStore;
34 const { actions } = this.props;
35 const workspace = new Workspace(
36 Object.assign({}, workspaceBeingEdited, values),
37 );
38 actions.workspaces.update({ workspace });
39 };
40
41 render() {
42 const { workspaceBeingEdited } = workspaceStore;
43 const { stores } = this.props;
44 if (!workspaceBeingEdited) return null;
45 return (
46 <ErrorBoundary>
47 <EditWorkspaceForm
48 workspace={workspaceBeingEdited}
49 services={stores.services.all}
50 onDelete={this.onDelete}
51 onSave={this.onSave}
52 updateWorkspaceRequest={updateWorkspaceRequest}
53 deleteWorkspaceRequest={deleteWorkspaceRequest}
54 />
55 </ErrorBoundary>
56 );
57 }
58}
59
60export default EditWorkspaceScreen;
diff --git a/src/features/workspaces/containers/WorkspacesScreen.js b/src/features/workspaces/containers/WorkspacesScreen.js
new file mode 100644
index 000000000..2ab565fa1
--- /dev/null
+++ b/src/features/workspaces/containers/WorkspacesScreen.js
@@ -0,0 +1,42 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types';
4import WorkspacesDashboard from '../components/WorkspacesDashboard';
5import ErrorBoundary from '../../../components/util/ErrorBoundary';
6import { workspaceStore } from '../index';
7import {
8 createWorkspaceRequest,
9 deleteWorkspaceRequest,
10 getUserWorkspacesRequest,
11 updateWorkspaceRequest,
12} from '../api';
13
14@inject('actions') @observer
15class WorkspacesScreen extends Component {
16 static propTypes = {
17 actions: PropTypes.shape({
18 workspace: PropTypes.shape({
19 edit: PropTypes.func.isRequired,
20 }),
21 }).isRequired,
22 };
23
24 render() {
25 const { actions } = this.props;
26 return (
27 <ErrorBoundary>
28 <WorkspacesDashboard
29 workspaces={workspaceStore.workspaces}
30 getUserWorkspacesRequest={getUserWorkspacesRequest}
31 createWorkspaceRequest={createWorkspaceRequest}
32 deleteWorkspaceRequest={deleteWorkspaceRequest}
33 updateWorkspaceRequest={updateWorkspaceRequest}
34 onCreateWorkspaceSubmit={data => actions.workspaces.create(data)}
35 onWorkspaceClick={w => actions.workspaces.edit({ workspace: w })}
36 />
37 </ErrorBoundary>
38 );
39 }
40}
41
42export default WorkspacesScreen;
diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js
new file mode 100644
index 000000000..ad9023b8b
--- /dev/null
+++ b/src/features/workspaces/index.js
@@ -0,0 +1,37 @@
1import { reaction } from 'mobx';
2import WorkspacesStore from './store';
3import { resetApiRequests } from './api';
4
5const debug = require('debug')('Franz:feature:workspaces');
6
7export const GA_CATEGORY_WORKSPACES = 'Workspaces';
8
9export const workspaceStore = new WorkspacesStore();
10
11export default function initWorkspaces(stores, actions) {
12 stores.workspaces = workspaceStore;
13 const { features } = stores;
14
15 // Toggle workspace feature
16 reaction(
17 () => features.features.isWorkspaceEnabled,
18 (isEnabled) => {
19 if (isEnabled && !workspaceStore.isFeatureActive) {
20 debug('Initializing `workspaces` feature');
21 workspaceStore.start(stores, actions);
22 } else if (workspaceStore.isFeatureActive) {
23 debug('Disabling `workspaces` feature');
24 workspaceStore.stop();
25 resetApiRequests();
26 }
27 },
28 {
29 fireImmediately: true,
30 },
31 );
32}
33
34export const WORKSPACES_ROUTES = {
35 ROOT: '/settings/workspaces',
36 EDIT: '/settings/workspaces/:action/:id',
37};
diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.js
new file mode 100644
index 000000000..6c73d7095
--- /dev/null
+++ b/src/features/workspaces/models/Workspace.js
@@ -0,0 +1,25 @@
1import { observable } from 'mobx';
2
3export default class Workspace {
4 id = null;
5
6 @observable name = null;
7
8 @observable order = null;
9
10 @observable services = [];
11
12 @observable userId = null;
13
14 constructor(data) {
15 if (!data.id) {
16 throw Error('Workspace requires Id');
17 }
18
19 this.id = data.id;
20 this.name = data.name;
21 this.order = data.order;
22 this.services.replace(data.services);
23 this.userId = data.userId;
24 }
25}
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js
new file mode 100644
index 000000000..e11513d1f
--- /dev/null
+++ b/src/features/workspaces/store.js
@@ -0,0 +1,323 @@
1import {
2 computed,
3 observable,
4 action,
5} from 'mobx';
6import localStorage from 'mobx-localstorage';
7import { matchRoute } from '../../helpers/routing-helpers';
8import { workspaceActions } from './actions';
9import { FeatureStore } from '../utils/FeatureStore';
10import {
11 createWorkspaceRequest,
12 deleteWorkspaceRequest,
13 getUserWorkspacesRequest,
14 updateWorkspaceRequest,
15} from './api';
16import { WORKSPACES_ROUTES } from './index';
17import { createReactions } from '../../stores/lib/Reaction';
18import { createActionBindings } from '../utils/ActionBinding';
19
20const debug = require('debug')('Franz:feature:workspaces:store');
21
22export default class WorkspacesStore extends FeatureStore {
23 @observable isFeatureEnabled = false;
24
25 @observable isFeatureActive = false;
26
27 @observable isPremiumFeature = true;
28
29 @observable isPremiumUpgradeRequired = true;
30
31 @observable activeWorkspace = null;
32
33 @observable nextWorkspace = null;
34
35 @observable workspaceBeingEdited = null;
36
37 @observable isSwitchingWorkspace = false;
38
39 @observable isWorkspaceDrawerOpen = false;
40
41 @observable isSettingsRouteActive = null;
42
43 @computed get workspaces() {
44 if (!this.isFeatureActive) return [];
45 return getUserWorkspacesRequest.result || [];
46 }
47
48 @computed get settings() {
49 return localStorage.getItem('workspaces') || {};
50 }
51
52 @computed get userHasWorkspaces() {
53 return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0;
54 }
55
56 @computed get isUserAllowedToUseFeature() {
57 return !this.isPremiumUpgradeRequired;
58 }
59
60 // ========== PRIVATE PROPERTIES ========= //
61
62 _wasDrawerOpenBeforeSettingsRoute = null;
63
64 _freeUserActions = [];
65
66 _premiumUserActions = [];
67
68 _allActions = [];
69
70 _freeUserReactions = [];
71
72 _premiumUserReactions = [];
73
74 _allReactions = [];
75
76 // ========== PUBLIC API ========= //
77
78 start(stores, actions) {
79 debug('WorkspacesStore::start');
80 this.stores = stores;
81 this.actions = actions;
82
83 // ACTIONS
84
85 this._freeUserActions = createActionBindings([
86 [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer],
87 [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings],
88 ]);
89 this._premiumUserActions = createActionBindings([
90 [workspaceActions.edit, this._edit],
91 [workspaceActions.create, this._create],
92 [workspaceActions.delete, this._delete],
93 [workspaceActions.update, this._update],
94 [workspaceActions.activate, this._setActiveWorkspace],
95 [workspaceActions.deactivate, this._deactivateActiveWorkspace],
96 ]);
97 this._allActions = this._freeUserActions.concat(this._premiumUserActions);
98 this._registerActions(this._allActions);
99
100 // REACTIONS
101
102 this._freeUserReactions = createReactions([
103 this._stopPremiumActionsAndReactions,
104 this._openDrawerWithSettingsReaction,
105 this._setFeatureEnabledReaction,
106 this._setIsPremiumFeatureReaction,
107 this._cleanupInvalidServiceReferences,
108 ]);
109 this._premiumUserReactions = createReactions([
110 this._setActiveServiceOnWorkspaceSwitchReaction,
111 this._activateLastUsedWorkspaceReaction,
112 this._setWorkspaceBeingEditedReaction,
113 ]);
114 this._allReactions = this._freeUserReactions.concat(this._premiumUserReactions);
115
116 this._registerReactions(this._allReactions);
117
118 getUserWorkspacesRequest.execute();
119 this.isFeatureActive = true;
120 }
121
122 stop() {
123 super.stop();
124 debug('WorkspacesStore::stop');
125 this.isFeatureActive = false;
126 this.activeWorkspace = null;
127 this.nextWorkspace = null;
128 this.workspaceBeingEdited = null;
129 this.isSwitchingWorkspace = false;
130 this.isWorkspaceDrawerOpen = false;
131 }
132
133 filterServicesByActiveWorkspace = (services) => {
134 const { activeWorkspace, isFeatureActive } = this;
135 if (isFeatureActive && activeWorkspace) {
136 return this.getWorkspaceServices(activeWorkspace);
137 }
138 return services;
139 };
140
141 getWorkspaceServices(workspace) {
142 const { services } = this.stores;
143 return workspace.services.map(id => services.one(id)).filter(s => !!s);
144 }
145
146 // ========== PRIVATE METHODS ========= //
147
148 _getWorkspaceById = id => this.workspaces.find(w => w.id === id);
149
150 _updateSettings = (changes) => {
151 localStorage.setItem('workspaces', {
152 ...this.settings,
153 ...changes,
154 });
155 };
156
157 // Actions
158
159 @action _edit = ({ workspace }) => {
160 this.stores.router.push(`/settings/workspaces/edit/${workspace.id}`);
161 };
162
163 @action _create = async ({ name }) => {
164 try {
165 const workspace = await createWorkspaceRequest.execute(name);
166 await getUserWorkspacesRequest.result.push(workspace);
167 this._edit({ workspace });
168 } catch (error) {
169 throw error;
170 }
171 };
172
173 @action _delete = async ({ workspace }) => {
174 try {
175 await deleteWorkspaceRequest.execute(workspace);
176 await getUserWorkspacesRequest.result.remove(workspace);
177 this.stores.router.push('/settings/workspaces');
178 } catch (error) {
179 throw error;
180 }
181 };
182
183 @action _update = async ({ workspace }) => {
184 try {
185 await updateWorkspaceRequest.execute(workspace);
186 // Path local result optimistically
187 const localWorkspace = this._getWorkspaceById(workspace.id);
188 Object.assign(localWorkspace, workspace);
189 this.stores.router.push('/settings/workspaces');
190 } catch (error) {
191 throw error;
192 }
193 };
194
195 @action _setActiveWorkspace = ({ workspace }) => {
196 // Indicate that we are switching to another workspace
197 this.isSwitchingWorkspace = true;
198 this.nextWorkspace = workspace;
199 // Delay switching to next workspace so that the services loading does not drag down UI
200 setTimeout(() => {
201 this.activeWorkspace = workspace;
202 this._updateSettings({ lastActiveWorkspace: workspace.id });
203 }, 100);
204 // Indicate that we are done switching to the next workspace
205 setTimeout(() => {
206 this.isSwitchingWorkspace = false;
207 this.nextWorkspace = null;
208 }, 1000);
209 };
210
211 @action _deactivateActiveWorkspace = () => {
212 // Indicate that we are switching to default workspace
213 this.isSwitchingWorkspace = true;
214 this.nextWorkspace = null;
215 this._updateSettings({ lastActiveWorkspace: null });
216 // Delay switching to next workspace so that the services loading does not drag down UI
217 setTimeout(() => {
218 this.activeWorkspace = null;
219 }, 100);
220 // Indicate that we are done switching to the default workspace
221 setTimeout(() => { this.isSwitchingWorkspace = false; }, 1000);
222 };
223
224 @action _toggleWorkspaceDrawer = () => {
225 this.isWorkspaceDrawerOpen = !this.isWorkspaceDrawerOpen;
226 };
227
228 @action _openWorkspaceSettings = () => {
229 this.actions.ui.openSettings({ path: 'workspaces' });
230 };
231
232 // Reactions
233
234 _setFeatureEnabledReaction = () => {
235 const { isWorkspaceEnabled } = this.stores.features.features;
236 this.isFeatureEnabled = isWorkspaceEnabled;
237 };
238
239 _setIsPremiumFeatureReaction = () => {
240 const { features, user } = this.stores;
241 const { isPremium } = user.data;
242 const { isWorkspacePremiumFeature } = features.features;
243 this.isPremiumFeature = isWorkspacePremiumFeature;
244 this.isPremiumUpgradeRequired = isWorkspacePremiumFeature && !isPremium;
245 };
246
247 _setWorkspaceBeingEditedReaction = () => {
248 const { pathname } = this.stores.router.location;
249 const match = matchRoute('/settings/workspaces/edit/:id', pathname);
250 if (match) {
251 this.workspaceBeingEdited = this._getWorkspaceById(match.id);
252 }
253 };
254
255 _setActiveServiceOnWorkspaceSwitchReaction = () => {
256 if (!this.isFeatureActive) return;
257 if (this.activeWorkspace) {
258 const services = this.stores.services.allDisplayed;
259 const activeService = services.find(s => s.isActive);
260 const workspaceServices = this.getWorkspaceServices(this.activeWorkspace);
261 if (workspaceServices.length <= 0) return;
262 const isActiveServiceInWorkspace = workspaceServices.includes(activeService);
263 if (!isActiveServiceInWorkspace) {
264 this.actions.service.setActive({ serviceId: workspaceServices[0].id });
265 }
266 }
267 };
268
269 _activateLastUsedWorkspaceReaction = () => {
270 if (!this.activeWorkspace && this.userHasWorkspaces) {
271 const { lastActiveWorkspace } = this.settings;
272 if (lastActiveWorkspace) {
273 const workspace = this._getWorkspaceById(lastActiveWorkspace);
274 if (workspace) this._setActiveWorkspace({ workspace });
275 }
276 }
277 };
278
279 _openDrawerWithSettingsReaction = () => {
280 const { router } = this.stores;
281 const isWorkspaceSettingsRoute = router.location.pathname.includes(WORKSPACES_ROUTES.ROOT);
282 const isSwitchingToSettingsRoute = !this.isSettingsRouteActive && isWorkspaceSettingsRoute;
283 const isLeavingSettingsRoute = !isWorkspaceSettingsRoute && this.isSettingsRouteActive;
284
285 if (isSwitchingToSettingsRoute) {
286 this.isSettingsRouteActive = true;
287 this._wasDrawerOpenBeforeSettingsRoute = this.isWorkspaceDrawerOpen;
288 if (!this._wasDrawerOpenBeforeSettingsRoute) {
289 workspaceActions.toggleWorkspaceDrawer();
290 }
291 } else if (isLeavingSettingsRoute) {
292 this.isSettingsRouteActive = false;
293 if (!this._wasDrawerOpenBeforeSettingsRoute && this.isWorkspaceDrawerOpen) {
294 workspaceActions.toggleWorkspaceDrawer();
295 }
296 }
297 };
298
299 _cleanupInvalidServiceReferences = () => {
300 const { services } = this.stores;
301 let invalidServiceReferencesExist = false;
302 this.workspaces.forEach((workspace) => {
303 workspace.services.forEach((serviceId) => {
304 if (!services.one(serviceId)) {
305 invalidServiceReferencesExist = true;
306 }
307 });
308 });
309 if (invalidServiceReferencesExist) {
310 getUserWorkspacesRequest.execute();
311 }
312 };
313
314 _stopPremiumActionsAndReactions = () => {
315 if (!this.isUserAllowedToUseFeature) {
316 this._stopActions(this._premiumUserActions);
317 this._stopReactions(this._premiumUserReactions);
318 } else {
319 this._startActions(this._premiumUserActions);
320 this._startReactions(this._premiumUserReactions);
321 }
322 }
323}
diff --git a/src/helpers/asar-helpers.js b/src/helpers/asar-helpers.js
new file mode 100644
index 000000000..9e4380c06
--- /dev/null
+++ b/src/helpers/asar-helpers.js
@@ -0,0 +1,3 @@
1export function asarPath(dir = '') {
2 return dir.replace('app.asar', 'app.asar.unpacked');
3}
diff --git a/src/helpers/i18n-helpers.js b/src/helpers/i18n-helpers.js
index 091b86b06..84146dd8c 100644
--- a/src/helpers/i18n-helpers.js
+++ b/src/helpers/i18n-helpers.js
@@ -28,22 +28,33 @@ export function getLocale({
28 return localeStr; 28 return localeStr;
29} 29}
30 30
31export function getSelectOptions({ locales, resetToDefaultText = '' }) { 31export function getSelectOptions({ locales, resetToDefaultText = '', automaticDetectionText = '' }) {
32 let options = []; 32 const options = [];
33 33
34 if (resetToDefaultText) { 34 if (resetToDefaultText) {
35 options = [ 35 options.push(
36 { 36 {
37 value: '', 37 value: '',
38 label: resetToDefaultText, 38 label: resetToDefaultText,
39 }, {
40 value: '───',
41 label: '───',
42 disabled: true,
43 }, 39 },
44 ]; 40 );
45 } 41 }
46 42
43 if (automaticDetectionText) {
44 options.push(
45 {
46 value: 'automatic',
47 label: automaticDetectionText,
48 },
49 );
50 }
51
52 options.push({
53 value: '───',
54 label: '───',
55 disabled: true,
56 });
57
47 Object.keys(locales).sort(Intl.Collator().compare).forEach((key) => { 58 Object.keys(locales).sort(Intl.Collator().compare).forEach((key) => {
48 options.push({ 59 options.push({
49 value: key, 60 value: key,
diff --git a/src/helpers/url-helpers.js b/src/helpers/url-helpers.js
new file mode 100644
index 000000000..750d1f00c
--- /dev/null
+++ b/src/helpers/url-helpers.js
@@ -0,0 +1,15 @@
1import { URL } from 'url';
2
3import { ALLOWED_PROTOCOLS } from '../config';
4
5const debug = require('debug')('Franz:Helpers:url');
6
7export function isValidExternalURL(url) {
8 const parsedUrl = new URL(url);
9
10 const isAllowed = ALLOWED_PROTOCOLS.includes(parsedUrl.protocol);
11
12 debug('protocol check is', isAllowed, 'for:', url);
13
14 return isAllowed;
15}
diff --git a/src/i18n/globalMessages.js b/src/i18n/globalMessages.js
index 2c724ff6f..1b5ece223 100644
--- a/src/i18n/globalMessages.js
+++ b/src/i18n/globalMessages.js
@@ -1,10 +1,6 @@
1import { defineMessages } from 'react-intl'; 1import { defineMessages } from 'react-intl';
2 2
3export default defineMessages({ 3export default defineMessages({
4 upgradeAccount: {
5 id: 'global.premium.upgradeAccount',
6 defaultMessage: '!!!Please upgrade your account to add a new service.',
7 },
8 APIUnhealthy: { 4 APIUnhealthy: {
9 id: 'global.api.unhealthy', 5 id: 'global.api.unhealthy',
10 defaultMessage: '!!!Can\'t connect to Franz Online Services', 6 defaultMessage: '!!!Can\'t connect to Franz Online Services',
@@ -13,4 +9,20 @@ export default defineMessages({
13 id: 'global.notConnectedToTheInternet', 9 id: 'global.notConnectedToTheInternet',
14 defaultMessage: '!!!You are not connected to the internet.', 10 defaultMessage: '!!!You are not connected to the internet.',
15 }, 11 },
12 spellcheckerLanguage: {
13 id: 'global.spellchecking.language',
14 defaultMessage: '!!!Spell checking language',
15 },
16 spellcheckerSystemDefault: {
17 id: 'global.spellchecker.useDefault',
18 defaultMessage: '!!!Use System Default ({default})',
19 },
20 spellcheckerAutomaticDetection: {
21 id: 'global.spellchecking.autodetect',
22 defaultMessage: '!!!Detect language automatically',
23 },
24 spellcheckerAutomaticDetectionShort: {
25 id: 'global.spellchecking.autodetect.short',
26 defaultMessage: '!!!Automatic',
27 },
16}); 28});
diff --git a/src/i18n/languages.js b/src/i18n/languages.js
index aa3f2316a..9ddcc3519 100644
--- a/src/i18n/languages.js
+++ b/src/i18n/languages.js
@@ -35,7 +35,8 @@ export const SPELLCHECKER_LOCALES = {
35 'da-dk': 'Dansk', 35 'da-dk': 'Dansk',
36 'de-de': 'Deutsch', 36 'de-de': 'Deutsch',
37 'el-gr': 'ελληνικά (Greek)', 37 'el-gr': 'ελληνικά (Greek)',
38 'en-us': 'English', 38 'en-gb': 'English (GB)',
39 'en-us': 'English (US)',
39 'es-es': 'Español', 40 'es-es': 'Español',
40 'et-ee': 'Estonian', 41 'et-ee': 'Estonian',
41 'fa-ir': 'Ùارسی (Persian)', 42 'fa-ir': 'Ùارسی (Persian)',
diff --git a/src/i18n/locales/ca.json b/src/i18n/locales/ca.json
index ed6f7bacd..b2aaaa070 100644
--- a/src/i18n/locales/ca.json
+++ b/src/i18n/locales/ca.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Recarrega", 2 "app.errorHandler.action" : "Recarrega",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Quelcom ha anat malament",
4 "feature.announcements.changelog.headline" : "Canvis en Franz {version}",
4 "feature.delayApp.action" : "Aconsegueix una llicència de suport per a Franz", 5 "feature.delayApp.action" : "Aconsegueix una llicència de suport per a Franz",
5 "feature.delayApp.headline" : "Si us plau, compra una llicència de suport per a Franz per saltar l'espera", 6 "feature.delayApp.headline" : "Si us plau, compra una llicència de suport per a Franz per saltar l'espera",
6 "feature.delayApp.text" : "Franz continuarà en {seconds} segons", 7 "feature.delayApp.text" : "Franz continuarà en {seconds} segons",
8 "feature.shareFranz.action.email" : "Envia com a correu",
9 "feature.shareFranz.action.facebook" : "Compartir en Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "No es pot connectar amb els serveis en línia de Franz", 15 "global.api.unhealthy" : "No es pot connectar amb els serveis en línia de Franz",
8 "global.notConnectedToTheInternet" : "No esteu connectat a Internet.", 16 "global.notConnectedToTheInternet" : "No esteu connectat a Internet.",
17 "global.spellchecker.useDefault" : "Utilitzar el predeterminat del sistema ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Corrector ortogràfic",
9 "import.headline" : "Importa els teus serveis Franz 4", 21 "import.headline" : "Importa els teus serveis Franz 4",
10 "import.notSupportedHeadline" : "Serveis que encara no s'admeten a Franz 5", 22 "import.notSupportedHeadline" : "Serveis que encara no s'admeten a Franz 5",
11 "import.skip.label" : "Vull afegir serveis manualment", 23 "import.skip.label" : "Vull afegir serveis manualment",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Accedir", 44 "login.submit.label" : "Accedir",
33 "login.tokenExpired" : "La teva sessió ha caducat, torna a iniciar la sessió.", 45 "login.tokenExpired" : "La teva sessió ha caducat, torna a iniciar la sessió.",
34 "menu.app.about" : "Sobre Franz", 46 "menu.app.about" : "Sobre Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Amaga", 48 "menu.app.hide" : "Amaga",
36 "menu.app.hideOthers" : "Amaga altres", 49 "menu.app.hideOthers" : "Amaga altres",
37 "menu.app.quit" : "Surt", 50 "menu.app.quit" : "Surt",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Suport", 72 "menu.help.support" : "Suport",
60 "menu.help.tos" : "Condicions del Servei", 73 "menu.help.tos" : "Condicions del Servei",
61 "menu.services" : "Serveis", 74 "menu.services" : "Serveis",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Afegeix un servei...", 76 "menu.services.addNewService" : "Afegeix un servei...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Visualitza", 78 "menu.view" : "Visualitza",
64 "menu.view.enterFullScreen" : "Inicia la pantalla completa", 79 "menu.view.enterFullScreen" : "Inicia la pantalla completa",
65 "menu.view.exitFullScreen" : "Surt de pantalla completa", 80 "menu.view.exitFullScreen" : "Surt de pantalla completa",
@@ -74,6 +89,11 @@
74 "menu.window" : "Finestra", 89 "menu.window" : "Finestra",
75 "menu.window.close" : "Tanca", 90 "menu.window.close" : "Tanca",
76 "menu.window.minimize" : "Minimitza", 91 "menu.window.minimize" : "Minimitza",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Tots els serveis",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Correu electrònic", 97 "password.email.label" : "Correu electrònic",
78 "password.headline" : "Restablir contrasenya", 98 "password.headline" : "Restablir contrasenya",
79 "password.link.login" : "Inicia la sessió al teu compte", 99 "password.link.login" : "Inicia la sessió al teu compte",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Edita {name}", 116 "service.errorHandler.editAction" : "Edita {name}",
97 "service.errorHandler.headline" : "Oh no!", 117 "service.errorHandler.headline" : "Oh no!",
98 "service.errorHandler.message" : "Error", 118 "service.errorHandler.message" : "Error",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} ha fallat al carregar",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Introducció", 121 "services.getStarted" : "Introducció",
101 "services.welcome" : "Benvingut a Franz", 122 "services.welcome" : "Benvingut a Franz",
102 "settings.account.account.editButton" : "Editar Compte", 123 "settings.account.account.editButton" : "Editar Compte",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Descarregar", 138 "settings.account.invoiceDownload" : "Descarregar",
118 "settings.account.manageSubscription.label" : "Gestioneu la vostra subscripció", 139 "settings.account.manageSubscription.label" : "Gestioneu la vostra subscripció",
119 "settings.account.successInfo" : "S'han desat els canvis", 140 "settings.account.successInfo" : "S'han desat els canvis",
141 "settings.account.tryReloadServices" : "Torna a provar-ho",
120 "settings.account.tryReloadUserInfoRequest" : "Torna a provar-ho", 142 "settings.account.tryReloadUserInfoRequest" : "Torna a provar-ho",
121 "settings.account.userInfoRequestFailed" : "No s'ha pogut carregar la informació de l'usuari", 143 "settings.account.userInfoRequestFailed" : "No s'ha pogut carregar la informació de l'usuari",
122 "settings.app.buttonClearAllCache" : "Buida la memòria cau", 144 "settings.app.buttonClearAllCache" : "Buida la memòria cau",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Inclou versions beta", 151 "settings.app.form.beta" : "Inclou versions beta",
130 "settings.app.form.darkMode" : "Uneix-te al Cantó Fosc", 152 "settings.app.form.darkMode" : "Uneix-te al Cantó Fosc",
131 "settings.app.form.enableGPUAcceleration" : "Activar acceleració GPU", 153 "settings.app.form.enableGPUAcceleration" : "Activar acceleració GPU",
132 "settings.app.form.enableMenuBar" : "Mostra Franz a la barra de menú",
133 "settings.app.form.enableSpellchecking" : "Habilita la comprobació ortogràfica", 154 "settings.app.form.enableSpellchecking" : "Habilita la comprobació ortogràfica",
134 "settings.app.form.enableSystemTray" : "Mostra Franz a la safata del sistema", 155 "settings.app.form.enableSystemTray" : "Mostra Franz a la safata del sistema",
135 "settings.app.form.hideDockIcon" : "Oculta la icona de Franz al Dock",
136 "settings.app.form.language" : "Idioma", 156 "settings.app.form.language" : "Idioma",
137 "settings.app.form.minimizeToSystemTray" : "Minimitza Franz a la safata del sistema", 157 "settings.app.form.minimizeToSystemTray" : "Minimitza Franz a la safata del sistema",
138 "settings.app.form.runInBackground" : "Mantén a Franz en segon pla en tancar la finestra", 158 "settings.app.form.runInBackground" : "Mantén a Franz en segon pla en tancar la finestra",
139 "settings.app.form.showDisabledServices" : "Mostra les pestanyes dels serveis desactivats", 159 "settings.app.form.showDisabledServices" : "Mostra les pestanyes dels serveis desactivats",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostra la insígnia de missatges no llegits quan les notificacions estiguin desactivades", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostra la insígnia de missatges no llegits quan les notificacions estiguin desactivades",
141 "settings.app.form.spellcheckerLanguage" : "Corrector ortogràfic",
142 "settings.app.headline" : "Configuració", 161 "settings.app.headline" : "Configuració",
143 "settings.app.headlineAdvanced" : "Avançat", 162 "settings.app.headlineAdvanced" : "Avançat",
144 "settings.app.headlineAppearance" : "Aparença", 163 "settings.app.headlineAppearance" : "Aparença",
145 "settings.app.headlineGeneral" : "General", 164 "settings.app.headlineGeneral" : "General",
146 "settings.app.headlineLanguage" : "Idioma", 165 "settings.app.headlineLanguage" : "Idioma",
147 "settings.app.headlineUpdates" : "Actualitzacions", 166 "settings.app.headlineUpdates" : "Actualitzacions",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Els canvis requereixen reiniciar", 168 "settings.app.restartRequired" : "Els canvis requereixen reiniciar",
149 "settings.app.subheadlineCache" : "Memòria cau", 169 "settings.app.subheadlineCache" : "Memòria cau",
150 "settings.app.translationHelp" : "Ajuda'ns a traduir Franz en la teva llengua.", 170 "settings.app.translationHelp" : "Ajuda'ns a traduir Franz en la teva llengua.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Convidar amics", 177 "settings.navigation.inviteFriends" : "Convidar amics",
158 "settings.navigation.logout" : "Sortir", 178 "settings.navigation.logout" : "Sortir",
159 "settings.navigation.settings" : "Configuració", 179 "settings.navigation.settings" : "Configuració",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Els vostres serveis", 181 "settings.navigation.yourServices" : "Els vostres serveis",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Tots els serveis", 183 "settings.recipes.all" : "Tots els serveis",
162 "settings.recipes.dev" : "Desenvolupament", 184 "settings.recipes.dev" : "Desenvolupament",
163 "settings.recipes.headline" : "Serveis disponibles", 185 "settings.recipes.headline" : "Serveis disponibles",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Mostra la insígnia de missatge per a tots els missatges nous", 214 "settings.service.form.indirectMessages" : "Mostra la insígnia de missatge per a tots els missatges nous",
193 "settings.service.form.isMutedInfo" : "Quan es desactiva, tots els sons de notificació i reproducció d'àudio es silenciaran", 215 "settings.service.form.isMutedInfo" : "Quan es desactiva, tots els sons de notificació i reproducció d'àudio es silenciaran",
194 "settings.service.form.name" : "Nom", 216 "settings.service.form.name" : "Nom",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Ajustaments Proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Host Proxy \/ IP", 218 "settings.service.form.proxy.host" : "Host Proxy \/ IP",
197 "settings.service.form.proxy.info" : "Els ajustaments del Proxy no es sincronitzaran amb els servidors de Franz", 219 "settings.service.form.proxy.info" : "Els ajustaments del Proxy no es sincronitzaran amb els servidors de Franz",
198 "settings.service.form.proxy.isEnabled" : "Utilitzar Proxy", 220 "settings.service.form.proxy.isEnabled" : "Utilitzar Proxy",
199 "settings.service.form.proxy.password" : "Contrasenya (opcional)", 221 "settings.service.form.proxy.password" : "Contrasenya (opcional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Siusplau, reinicieu el Franz després de canviar els ajustaments de proxy",
202 "settings.service.form.proxy.user" : "Usuari (opcional)", 224 "settings.service.form.proxy.user" : "Usuari (opcional)",
203 "settings.service.form.saveButton" : "Desa el servei", 225 "settings.service.form.saveButton" : "Desa el servei",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Allotjat", 226 "settings.service.form.tabHosted" : "Allotjat",
207 "settings.service.form.tabOnPremise" : "Allotjat per si mateix â­ï¸", 227 "settings.service.form.tabOnPremise" : "Allotjat per si mateix â­ï¸",
208 "settings.service.form.team" : "Equip", 228 "settings.service.form.team" : "Equip",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Descobrir serveis", 232 "settings.services.discoverServices" : "Descobrir serveis",
213 "settings.services.headline" : "Els vostres serveis", 233 "settings.services.headline" : "Els vostres serveis",
214 "settings.services.noServicesAdded" : "Encara no heu afegit cap servei.", 234 "settings.services.noServicesAdded" : "Encara no heu afegit cap servei.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "El servei està desactivat", 236 "settings.services.tooltip.isDisabled" : "El servei està desactivat",
216 "settings.services.tooltip.isMuted" : "Tots els sons estan desactivats", 237 "settings.services.tooltip.isMuted" : "Tots els sons estan desactivats",
217 "settings.services.tooltip.notificationsDisabled" : "Les notificacions estan desactivades", 238 "settings.services.tooltip.notificationsDisabled" : "Les notificacions estan desactivades",
218 "settings.services.updatedInfo" : "S'han desat els canvis", 239 "settings.services.updatedInfo" : "S'han desat els canvis",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Equip",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Empresa", 246 "settings.user.form.accountType.company" : "Empresa",
220 "settings.user.form.accountType.individual" : "Individual", 247 "settings.user.form.accountType.individual" : "Individual",
221 "settings.user.form.accountType.label" : "Tipus de compte", 248 "settings.user.form.accountType.label" : "Tipus de compte",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Nom", 252 "settings.user.form.firstname" : "Nom",
226 "settings.user.form.lastname" : "Cognoms", 253 "settings.user.form.lastname" : "Cognoms",
227 "settings.user.form.newPassword" : "Nova contrasenya", 254 "settings.user.form.newPassword" : "Nova contrasenya",
255 "settings.workspace.add.form.name" : "Nom",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Nom",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Torna a provar-ho",
266 "settings.workspaces.updatedInfo" : "S'han desat els canvis",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Afegeix nou servei", 270 "sidebar.addNewService" : "Afegeix nou servei",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Desactivar notificacions i àudio", 272 "sidebar.muteApp" : "Desactivar notificacions i àudio",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Configuració", 274 "sidebar.settings" : "Configuració",
231 "sidebar.unmuteApp" : "Activar notificacions i àudio", 275 "sidebar.unmuteApp" : "Activar notificacions i àudio",
232 "signup.company.label" : "Empresa", 276 "signup.company.label" : "Empresa",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Residents d'EU: es poden aplicar impostos locals", 288 "subscription.euTaxInfo" : "Residents d'EU: es poden aplicar impostos locals",
245 "subscription.features.ads" : "Sense anuncis, mai!", 289 "subscription.features.ads" : "Sense anuncis, mai!",
246 "subscription.features.comingSoon" : "properament", 290 "subscription.features.comingSoon" : "properament",
247 "subscription.features.encryptedSync" : "Sincronització de sessió xifrada",
248 "subscription.features.noInterruptions" : "Sense retards ni molestes actualitzacions de llicències ", 291 "subscription.features.noInterruptions" : "Sense retards ni molestes actualitzacions de llicències ",
249 "subscription.features.onpremise" : "Afegiu serveis en premissa\/allotjats com HipChat",
250 "subscription.features.onpremise.mattermost" : "Afegir serveis allotjats com Mattermost", 292 "subscription.features.onpremise.mattermost" : "Afegir serveis allotjats com Mattermost",
251 "subscription.features.proxy" : "Suport de Proxy per a serveis", 293 "subscription.features.proxy" : "Suport de Proxy per a serveis",
252 "subscription.features.spellchecker" : "Suport per corrector ortogràfic", 294 "subscription.features.spellchecker" : "Suport per corrector ortogràfic",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "El compte de pagament Franz Premium Supporter inclou", 296 "subscription.includedFeatures" : "El compte de pagament Franz Premium Supporter inclou",
254 "subscription.paymentSessionError" : "No s'ha pogut inicialitzar el formulari de pagament", 297 "subscription.paymentSessionError" : "No s'ha pogut inicialitzar el formulari de pagament",
255 "subscription.submit.label" : "Vull donar suport al desenvolupament de Franz", 298 "subscription.submit.label" : "Vull donar suport al desenvolupament de Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Recarrega", 312 "tabs.item.reload" : "Recarrega",
270 "validation.email" : "{field} no es vàlid", 313 "validation.email" : "{field} no es vàlid",
271 "validation.minLength" : "{field} ha de ser al menys {length} caràcters de llargada", 314 "validation.minLength" : "{field} ha de ser al menys {length} caràcters de llargada",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} es requerit", 316 "validation.required" : "{field} es requerit",
273 "validation.url" : "{field} es una URL no vàlida", 317 "validation.url" : "{field} es una URL no vàlida",
274 "welcome.loginButton" : "Inicia sessió al teu compte", 318 "welcome.loginButton" : "Inicia sessió al teu compte",
275 "welcome.signupButton" : "Crea un compte gratuït", 319 "welcome.signupButton" : "Crea un compte gratuït",
276 "welcome.slogan" : "Crea un compte gratuït" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Tots els serveis",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/cs.json b/src/i18n/locales/cs.json
index b8bfd2526..aadfeffbc 100644
--- a/src/i18n/locales/cs.json
+++ b/src/i18n/locales/cs.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Obnovit", 2 "app.errorHandler.action" : "Obnovit",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Něco se pokazilo",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Podpoř Franz a získej Supporter licenci",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "Kup si Franz Supporter licenci a nebudeÅ¡ už muset Äekat",
7 "feature.delayApp.text" : "Franz bude pokraÄovat v {seconds} sekundách.",
8 "feature.shareFranz.action.email" : "Poslat jako e-mail",
9 "feature.shareFranz.action.facebook" : "Sdílet na Facebooku",
10 "feature.shareFranz.action.twitter" : "Sdílet na Twitteru",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Nemůžeme připojit Franz k online službám", 15 "global.api.unhealthy" : "Nemůžeme připojit Franz k online službám",
8 "global.notConnectedToTheInternet" : "Připojení k internetu není k dispozici.", 16 "global.notConnectedToTheInternet" : "Připojení k internetu není k dispozici.",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Oprava překlepů jazyka",
9 "import.headline" : "Importovat služby z Franz 4", 21 "import.headline" : "Importovat služby z Franz 4",
10 "import.notSupportedHeadline" : "Služby nejsou podporovány ve verzi Franz 5", 22 "import.notSupportedHeadline" : "Služby nejsou podporovány ve verzi Franz 5",
11 "import.skip.label" : "Chci pÅ™idat službu ruÄnÄ›", 23 "import.skip.label" : "Chci pÅ™idat službu ruÄnÄ›",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Přihlásit se", 44 "login.submit.label" : "Přihlásit se",
33 "login.tokenExpired" : "Sezení vypršelo, prosím přihlaste se znovu", 45 "login.tokenExpired" : "Sezení vypršelo, prosím přihlaste se znovu",
34 "menu.app.about" : "O aplikaci", 46 "menu.app.about" : "O aplikaci",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Skrýt", 48 "menu.app.hide" : "Skrýt",
36 "menu.app.hideOthers" : "Skryt ostatní", 49 "menu.app.hideOthers" : "Skryt ostatní",
37 "menu.app.quit" : "UkonÄit", 50 "menu.app.quit" : "UkonÄit",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Podpora", 72 "menu.help.support" : "Podpora",
60 "menu.help.tos" : "Podmínky použití", 73 "menu.help.tos" : "Podmínky použití",
61 "menu.services" : "Služby", 74 "menu.services" : "Služby",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Přidat novou službu...", 76 "menu.services.addNewService" : "Přidat novou službu...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Zobrazení", 78 "menu.view" : "Zobrazení",
64 "menu.view.enterFullScreen" : "Spustit režim celé obrazovky", 79 "menu.view.enterFullScreen" : "Spustit režim celé obrazovky",
65 "menu.view.exitFullScreen" : "UkonÄit celoobrazovkový režim", 80 "menu.view.exitFullScreen" : "UkonÄit celoobrazovkový režim",
@@ -74,6 +89,11 @@
74 "menu.window" : "Okno", 89 "menu.window" : "Okno",
75 "menu.window.close" : "Zavřít", 90 "menu.window.close" : "Zavřít",
76 "menu.window.minimize" : "Minimalizovat", 91 "menu.window.minimize" : "Minimalizovat",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Všechny služby",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-mailová adresa", 97 "password.email.label" : "E-mailová adresa",
78 "password.headline" : "Obnovit heslo", 98 "password.headline" : "Obnovit heslo",
79 "password.link.login" : "PÅ™ihlásit se k úÄtu", 99 "password.link.login" : "PÅ™ihlásit se k úÄtu",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Pro emailovou adresu nebyl nalezený žádný uživatel", 101 "password.noUser" : "Pro emailovou adresu nebyl nalezený žádný uživatel",
82 "password.submit.label" : "Odeslat", 102 "password.submit.label" : "Odeslat",
83 "password.successInfo" : "Prosím, zkontrolujte svůj e-mail", 103 "password.successInfo" : "Prosím, zkontrolujte svůj e-mail",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "VylepÅ¡i si svůj úÄet",
85 "pricing.headline" : "Podpořit Franz", 105 "pricing.headline" : "Podpořit Franz",
86 "pricing.link.skipPayment" : "Nechci podporovat vývoj aplikace Franz.", 106 "pricing.link.skipPayment" : "Nechci podporovat vývoj aplikace Franz.",
87 "pricing.submit.label" : "Chci podpořit vývoj aplikace Franz", 107 "pricing.submit.label" : "Chci podpořit vývoj aplikace Franz",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Upravit {name}", 116 "service.errorHandler.editAction" : "Upravit {name}",
97 "service.errorHandler.headline" : "Ale ne!", 117 "service.errorHandler.headline" : "Ale ne!",
98 "service.errorHandler.message" : "Chyba", 118 "service.errorHandler.message" : "Chyba",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} se nepodaÅ™ilo naÄíst.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "ZaÄnÄ›me", 121 "services.getStarted" : "ZaÄnÄ›me",
101 "services.welcome" : "Vítejte v programu Franz", 122 "services.welcome" : "Vítejte v programu Franz",
102 "settings.account.account.editButton" : "Upravit úÄet", 123 "settings.account.account.editButton" : "Upravit úÄet",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Stáhnout", 138 "settings.account.invoiceDownload" : "Stáhnout",
118 "settings.account.manageSubscription.label" : "Spravovat vaše předplatné", 139 "settings.account.manageSubscription.label" : "Spravovat vaše předplatné",
119 "settings.account.successInfo" : "Vaše změny byly uloženy", 140 "settings.account.successInfo" : "Vaše změny byly uloženy",
141 "settings.account.tryReloadServices" : "Zkusit opět",
120 "settings.account.tryReloadUserInfoRequest" : "Zkusit opět", 142 "settings.account.tryReloadUserInfoRequest" : "Zkusit opět",
121 "settings.account.userInfoRequestFailed" : "Nelze naÄíst informace o uživateli.", 143 "settings.account.userInfoRequestFailed" : "Nelze naÄíst informace o uživateli.",
122 "settings.app.buttonClearAllCache" : "Vyprázdnit mezipaměti", 144 "settings.app.buttonClearAllCache" : "Vyprázdnit mezipaměti",
@@ -127,24 +149,22 @@
127 "settings.app.form.autoLaunchInBackground" : "Spustit na pozadí", 149 "settings.app.form.autoLaunchInBackground" : "Spustit na pozadí",
128 "settings.app.form.autoLaunchOnStart" : "Spustit Franz při startu", 150 "settings.app.form.autoLaunchOnStart" : "Spustit Franz při startu",
129 "settings.app.form.beta" : "Zahrnout beta verze", 151 "settings.app.form.beta" : "Zahrnout beta verze",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Připoj se k Temné straně",
131 "settings.app.form.enableGPUAcceleration" : "Aktivovat GPU zrychlení", 153 "settings.app.form.enableGPUAcceleration" : "Aktivovat GPU zrychlení",
132 "settings.app.form.enableMenuBar" : "Zobraz Franz v Menu nabídce",
133 "settings.app.form.enableSpellchecking" : "Zapnout kontrolu pravopisu", 154 "settings.app.form.enableSpellchecking" : "Zapnout kontrolu pravopisu",
134 "settings.app.form.enableSystemTray" : "Zobrazit Franz v systémové liště", 155 "settings.app.form.enableSystemTray" : "Zobrazit Franz v systémové liště",
135 "settings.app.form.hideDockIcon" : "Schovej ikonu Franz v Docku",
136 "settings.app.form.language" : "Jazyk", 156 "settings.app.form.language" : "Jazyk",
137 "settings.app.form.minimizeToSystemTray" : "Minimalizovat Franz do systémové lišty", 157 "settings.app.form.minimizeToSystemTray" : "Minimalizovat Franz do systémové lišty",
138 "settings.app.form.runInBackground" : "Ponechat Franze v pozadí při zavírání okna", 158 "settings.app.form.runInBackground" : "Ponechat Franze v pozadí při zavírání okna",
139 "settings.app.form.showDisabledServices" : "Zobrazit záložky vypnutých služeb", 159 "settings.app.form.showDisabledServices" : "Zobrazit záložky vypnutých služeb",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Zobrazit odznak pro nepÅ™eÄtené zprávy když jsou upozornÄ›ní vypnutá", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Zobrazit odznak pro nepÅ™eÄtené zprávy když jsou upozornÄ›ní vypnutá",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Nastavení", 161 "settings.app.headline" : "Nastavení",
143 "settings.app.headlineAdvanced" : "PokroÄilé", 162 "settings.app.headlineAdvanced" : "PokroÄilé",
144 "settings.app.headlineAppearance" : "Vzhled", 163 "settings.app.headlineAppearance" : "Vzhled",
145 "settings.app.headlineGeneral" : "Obecné", 164 "settings.app.headlineGeneral" : "Obecné",
146 "settings.app.headlineLanguage" : "Jazyk", 165 "settings.app.headlineLanguage" : "Jazyk",
147 "settings.app.headlineUpdates" : "Aktualizace", 166 "settings.app.headlineUpdates" : "Aktualizace",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Změny vyžadují restart", 168 "settings.app.restartRequired" : "Změny vyžadují restart",
149 "settings.app.subheadlineCache" : "Mezipaměť", 169 "settings.app.subheadlineCache" : "Mezipaměť",
150 "settings.app.translationHelp" : "Pomozte nám přeložit Franz do svého jazyka.", 170 "settings.app.translationHelp" : "Pomozte nám přeložit Franz do svého jazyka.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Pozvi přátele", 177 "settings.navigation.inviteFriends" : "Pozvi přátele",
158 "settings.navigation.logout" : "Odhlásit", 178 "settings.navigation.logout" : "Odhlásit",
159 "settings.navigation.settings" : "Nastavení", 179 "settings.navigation.settings" : "Nastavení",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Vaše služby", 181 "settings.navigation.yourServices" : "Vaše služby",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Všechny služby", 183 "settings.recipes.all" : "Všechny služby",
162 "settings.recipes.dev" : "Vývoj", 184 "settings.recipes.dev" : "Vývoj",
163 "settings.recipes.headline" : "Dostupné služby", 185 "settings.recipes.headline" : "Dostupné služby",
@@ -179,7 +201,7 @@
179 "settings.service.form.editServiceHeadline" : "Upravit {name}", 201 "settings.service.form.editServiceHeadline" : "Upravit {name}",
180 "settings.service.form.enableAudio" : "Zapnout zvuk", 202 "settings.service.form.enableAudio" : "Zapnout zvuk",
181 "settings.service.form.enableBadge" : "Ukázat odznaky nepÅ™eÄtených zpráv", 203 "settings.service.form.enableBadge" : "Ukázat odznaky nepÅ™eÄtených zpráv",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Povolit Tmavý vzhled",
183 "settings.service.form.enableNotification" : "Povolit upozornění", 205 "settings.service.form.enableNotification" : "Povolit upozornění",
184 "settings.service.form.enableService" : "Povolit službu", 206 "settings.service.form.enableService" : "Povolit službu",
185 "settings.service.form.headlineBadges" : "Odznaky nepÅ™eÄtených zpráv", 207 "settings.service.form.headlineBadges" : "Odznaky nepÅ™eÄtených zpráv",
@@ -192,7 +214,7 @@
192 "settings.service.form.indirectMessages" : "Zobrazovat znak zprávy pro všechny nové zprávy", 214 "settings.service.form.indirectMessages" : "Zobrazovat znak zprávy pro všechny nové zprávy",
193 "settings.service.form.isMutedInfo" : "Pokud je vypnuto, všechny zvuky notifikací a jiného audia budou ztišeny", 215 "settings.service.form.isMutedInfo" : "Pokud je vypnuto, všechny zvuky notifikací a jiného audia budou ztišeny",
194 "settings.service.form.name" : "Jméno", 216 "settings.service.form.name" : "Jméno",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Nastavení HTTP\/HTTPS Proxy",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Use Proxy",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "Uložit službu", 225 "settings.service.form.saveButton" : "Uložit službu",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hostováno", 226 "settings.service.form.tabHosted" : "Hostováno",
207 "settings.service.form.tabOnPremise" : "SamostatnÄ› hostované â­ï¸", 227 "settings.service.form.tabOnPremise" : "SamostatnÄ› hostované â­ï¸",
208 "settings.service.form.team" : "Tým", 228 "settings.service.form.team" : "Tým",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Objevte služby", 232 "settings.services.discoverServices" : "Objevte služby",
213 "settings.services.headline" : "Vaše služby", 233 "settings.services.headline" : "Vaše služby",
214 "settings.services.noServicesAdded" : "Doposud jste nepřidali žádné služby.", 234 "settings.services.noServicesAdded" : "Doposud jste nepřidali žádné služby.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Služba je zakázána", 236 "settings.services.tooltip.isDisabled" : "Služba je zakázána",
216 "settings.services.tooltip.isMuted" : "Všechny zvuky jsou ztišeny", 237 "settings.services.tooltip.isMuted" : "Všechny zvuky jsou ztišeny",
217 "settings.services.tooltip.notificationsDisabled" : "Oznámení jsou zakázána", 238 "settings.services.tooltip.notificationsDisabled" : "Oznámení jsou zakázána",
218 "settings.services.updatedInfo" : "Vaše změny byly uloženy", 239 "settings.services.updatedInfo" : "Vaše změny byly uloženy",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Tým",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "SpoleÄnost", 246 "settings.user.form.accountType.company" : "SpoleÄnost",
220 "settings.user.form.accountType.individual" : "Jednotlivec", 247 "settings.user.form.accountType.individual" : "Jednotlivec",
221 "settings.user.form.accountType.label" : "Druh úÄtu", 248 "settings.user.form.accountType.label" : "Druh úÄtu",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Jméno", 252 "settings.user.form.firstname" : "Jméno",
226 "settings.user.form.lastname" : "Příjmení", 253 "settings.user.form.lastname" : "Příjmení",
227 "settings.user.form.newPassword" : "Nové heslo", 254 "settings.user.form.newPassword" : "Nové heslo",
255 "settings.workspace.add.form.name" : "Jméno",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Jméno",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Zkusit opět",
266 "settings.workspaces.updatedInfo" : "Vaše změny byly uloženy",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Přidat novou službu", 270 "sidebar.addNewService" : "Přidat novou službu",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Vypnout upozornění a zvuky", 272 "sidebar.muteApp" : "Vypnout upozornění a zvuky",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Nastavení", 274 "sidebar.settings" : "Nastavení",
231 "sidebar.unmuteApp" : "Zapnout upozornění a zvuky", 275 "sidebar.unmuteApp" : "Zapnout upozornění a zvuky",
232 "signup.company.label" : "SpoleÄnost", 276 "signup.company.label" : "SpoleÄnost",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Pro obyvatelé EU: mohou být aplikovány lokální daně", 288 "subscription.euTaxInfo" : "Pro obyvatelé EU: mohou být aplikovány lokální daně",
245 "subscription.features.ads" : "Žádné reklamy, nikdy!", 289 "subscription.features.ads" : "Žádné reklamy, nikdy!",
246 "subscription.features.comingSoon" : "již brzy", 290 "subscription.features.comingSoon" : "již brzy",
247 "subscription.features.encryptedSync" : "Šifrovaná synchronizace relací",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Přidat hostované služby jako HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Placený úÄet Premium Supporter Franz zahrnuje", 296 "subscription.includedFeatures" : "Placený úÄet Premium Supporter Franz zahrnuje",
254 "subscription.paymentSessionError" : "Nebylo možné inicializovat platbu od", 297 "subscription.paymentSessionError" : "Nebylo možné inicializovat platbu od",
255 "subscription.submit.label" : "Chci podpořit vývoj aplikace Franz", 298 "subscription.submit.label" : "Chci podpořit vývoj aplikace Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Obnovit", 312 "tabs.item.reload" : "Obnovit",
270 "validation.email" : "{field} není validní", 313 "validation.email" : "{field} není validní",
271 "validation.minLength" : "{field} musí být alespoň {length} znaků dlouhé", 314 "validation.minLength" : "{field} musí být alespoň {length} znaků dlouhé",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} je povinné", 316 "validation.required" : "{field} je povinné",
273 "validation.url" : "{field} není validní URL", 317 "validation.url" : "{field} není validní URL",
274 "welcome.loginButton" : "PÅ™ihlášení do vaÅ¡eho úÄtu", 318 "welcome.loginButton" : "PÅ™ihlášení do vaÅ¡eho úÄtu",
275 "welcome.signupButton" : "VytvoÅ™it úÄet zdarma", 319 "welcome.signupButton" : "VytvoÅ™it úÄet zdarma",
276 "welcome.slogan" : "Zprávy, které pracují pro vás" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Všechny služby",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json
index b5abb56d4..bd5193177 100644
--- a/src/i18n/locales/de.json
+++ b/src/i18n/locales/de.json
@@ -1,30 +1,42 @@
1{ 1{
2 "app.errorHandler.action" : "Neuladen", 2 "app.errorHandler.action" : "Neu laden",
3 "app.errorHandler.headline" : "Es trat ein Fehler auf", 3 "app.errorHandler.headline" : "Es ist ein Fehler aufgetreten",
4 "feature.delayApp.action" : "Upgrade deinen Account", 4 "feature.announcements.changelog.headline" : "Was ist neu in Franz {version}",
5 "feature.delayApp.headline" : "Erspare dir das Warten mit einer Franz Supporter Lizenz", 5 "feature.delayApp.action" : "Hol dir Franz Premium!",
6 "feature.delayApp.text" : "Es geht in {seconds} Sekunden weiter.", 6 "feature.delayApp.headline" : "Erspare dir das Warten mit Franz Premium!",
7 "global.api.unhealthy" : "Verbindung mit dem Franz Online Service fehlgeschlagen", 7 "feature.delayApp.text" : "In {seconds} Sekunden geht's weiter!",
8 "feature.shareFranz.action.email" : "Als E-Mail senden",
9 "feature.shareFranz.action.facebook" : "Auf Facebook teilen",
10 "feature.shareFranz.action.twitter" : "Auf Twitter teilen",
11 "feature.shareFranz.headline" : "Gemeinsam ist Franz noch besser!",
12 "feature.shareFranz.shareText.email" : "Ich verwende Franz! Hol dir jetzt die kostenlose App für WhatsApp, Messenger, Slack, Skype und viele mehr auf www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "Ich habe {count} Services zu Franz hinzugefügt! Hol dir die kostenlose App für WhatsApp, Messenger, Slack, Skype und viele mehr auf www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Bitte erzähle deinen Freunden und Kolleginnen, warum du Franz toll findest.",
15 "global.api.unhealthy" : "Verbindung zum Franz Online Service fehlgeschlagen",
8 "global.notConnectedToTheInternet" : "Du bist nicht mit dem Internet verbunden.", 16 "global.notConnectedToTheInternet" : "Du bist nicht mit dem Internet verbunden.",
9 "import.headline" : "Deine Franz 4 Dienste importieren", 17 "global.spellchecker.useDefault" : "Standard benutzen ({default})",
18 "global.spellchecking.autodetect" : "Sprache automatisch erkennen",
19 "global.spellchecking.autodetect.short" : "Automatisch",
20 "global.spellchecking.language" : "Sprache für Rechtschreibprüfung",
21 "import.headline" : "Deine Franz-4-Dienste importieren",
10 "import.notSupportedHeadline" : "Dienste, die noch nicht von Franz 5 unterstützt werden", 22 "import.notSupportedHeadline" : "Dienste, die noch nicht von Franz 5 unterstützt werden",
11 "import.skip.label" : "Ich möchte Dienste selbst hinzufügen", 23 "import.skip.label" : "Ich möchte Dienste selbst hinzufügen",
12 "import.submit.label" : "Dienste importieren", 24 "import.submit.label" : "Dienste importieren",
13 "infobar.buttonChangelog" : "Was ist neu?", 25 "infobar.buttonChangelog" : "Was gibt es Neues?",
14 "infobar.buttonInstallUpdate" : "Neu starten & Update installieren", 26 "infobar.buttonInstallUpdate" : "Neu starten & Update installieren",
15 "infobar.buttonReloadServices" : "Dienste neuladen", 27 "infobar.buttonReloadServices" : "Dienste neu laden",
16 "infobar.requiredRequestsFailed" : "Dienste und Benutzerinformationen konnten nicht geladen werden", 28 "infobar.requiredRequestsFailed" : "Dienste und Benutzerinformationen konnten nicht geladen werden",
17 "infobar.servicesUpdated" : "Deine Dienste wurden aktualisiert.", 29 "infobar.servicesUpdated" : "Deine Dienste wurden aktualisiert.",
18 "infobar.updateAvailable" : "Eine neue Version von Franz ist verfügbar.", 30 "infobar.updateAvailable" : "Eine neue Version von Franz ist verfügbar!",
19 "invite.email.label" : "E-Mail-Adresse", 31 "invite.email.label" : "E-Mail-Adresse",
20 "invite.headline.friends" : "Lade 3 Freunde oder Kollegen ein", 32 "invite.headline.friends" : "Lade drei Freunde oder Kolleginnen ein!",
21 "invite.name.label" : "Name", 33 "invite.name.label" : "Name",
22 "invite.skip.label" : "Ich möchte das später tun", 34 "invite.skip.label" : "Jetzt nicht! Ich möchte das später tun.",
23 "invite.submit.label" : "Einladungen schicken", 35 "invite.submit.label" : "Einladungen schicken",
24 "invite.successInfo" : "Die Einladungen wurden erfolgreich gesendet.", 36 "invite.successInfo" : "Die Einladungen wurden erfolgreich versendet.",
25 "login.email.label" : "E-Mail-Adresse", 37 "login.email.label" : "E-Mail-Adresse",
26 "login.headline" : "Anmelden", 38 "login.headline" : "Anmelden",
27 "login.invalidCredentials" : "E-Mail Adresse oder Passwort ungültig", 39 "login.invalidCredentials" : "E-Mail-Adresse oder Passwort ungültig",
28 "login.link.password" : "Passwort zurücksetzen", 40 "login.link.password" : "Passwort zurücksetzen",
29 "login.link.signup" : "Kostenloses Konto erstellen", 41 "login.link.signup" : "Kostenloses Konto erstellen",
30 "login.password.label" : "Passwort", 42 "login.password.label" : "Passwort",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Anmelden", 44 "login.submit.label" : "Anmelden",
33 "login.tokenExpired" : "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an.", 45 "login.tokenExpired" : "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an.",
34 "menu.app.about" : "Ãœber Franz", 46 "menu.app.about" : "Ãœber Franz",
47 "menu.app.announcement" : "Was ist neu?",
35 "menu.app.hide" : "Ausblenden", 48 "menu.app.hide" : "Ausblenden",
36 "menu.app.hideOthers" : "Andere ausblenden", 49 "menu.app.hideOthers" : "Andere ausblenden",
37 "menu.app.quit" : "Beenden", 50 "menu.app.quit" : "Beenden",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Hilfe", 72 "menu.help.support" : "Hilfe",
60 "menu.help.tos" : "Nutzungsbedingungen", 73 "menu.help.tos" : "Nutzungsbedingungen",
61 "menu.services" : "Dienste", 74 "menu.services" : "Dienste",
75 "menu.services.activatePreviousService" : "Vorheriger Dienst",
62 "menu.services.addNewService" : "Dienst hinzufügen", 76 "menu.services.addNewService" : "Dienst hinzufügen",
77 "menu.services.setNextServiceActive" : "Nächster Dienst",
63 "menu.view" : "Darstellung", 78 "menu.view" : "Darstellung",
64 "menu.view.enterFullScreen" : "Vollbildmodus", 79 "menu.view.enterFullScreen" : "Vollbildmodus",
65 "menu.view.exitFullScreen" : "Vollbildmodus aus", 80 "menu.view.exitFullScreen" : "Vollbildmodus aus",
@@ -74,9 +89,14 @@
74 "menu.window" : "Fenster", 89 "menu.window" : "Fenster",
75 "menu.window.close" : "Schließen", 90 "menu.window.close" : "Schließen",
76 "menu.window.minimize" : "Minimieren", 91 "menu.window.minimize" : "Minimieren",
77 "password.email.label" : "E-Mail Adresse", 92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Neuen Workspace hinzufügen",
94 "menu.workspaces.closeWorkspaceDrawer" : "Workspaces öffnen",
95 "menu.workspaces.defaultWorkspace" : "Alle Dienste",
96 "menu.workspaces.openWorkspaceDrawer" : "Workspaces schließen",
97 "password.email.label" : "E-Mail-Adresse",
78 "password.headline" : "Passwort zurücksetzen", 98 "password.headline" : "Passwort zurücksetzen",
79 "password.link.login" : "An Deinem Konto anmelden", 99 "password.link.login" : "Mit deinem Konto anmelden",
80 "password.link.signup" : "Kostenloses Konto erstellen", 100 "password.link.signup" : "Kostenloses Konto erstellen",
81 "password.noUser" : "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", 101 "password.noUser" : "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.",
82 "password.submit.label" : "Absenden", 102 "password.submit.label" : "Absenden",
@@ -86,28 +106,29 @@
86 "pricing.link.skipPayment" : "Ich möchte die Entwicklung von Franz nicht unterstützen.", 106 "pricing.link.skipPayment" : "Ich möchte die Entwicklung von Franz nicht unterstützen.",
87 "pricing.submit.label" : "Ich möchte die Entwicklung von Franz unterstützen.", 107 "pricing.submit.label" : "Ich möchte die Entwicklung von Franz unterstützen.",
88 "pricing.support.label" : "Wie möchtest Du Franz unterstützen?", 108 "pricing.support.label" : "Wie möchtest Du Franz unterstützen?",
89 "service.crashHandler.action" : "{name} neuladen", 109 "service.crashHandler.action" : "{name} neu laden",
90 "service.crashHandler.autoReload" : "{name} wird in {seconds} Sekunden automatisch wiederhergestellt", 110 "service.crashHandler.autoReload" : "{name} wird in {seconds} Sekunden automatisch wiederhergestellt",
91 "service.crashHandler.headline" : "Oh nein!", 111 "service.crashHandler.headline" : "Oh nein!",
92 "service.crashHandler.text" : "{name} hat einen Fehler verursacht.", 112 "service.crashHandler.text" : "{name} hat einen Fehler verursacht.",
93 "service.disabledHandler.action" : "{name} aktivieren", 113 "service.disabledHandler.action" : "{name} aktivieren",
94 "service.disabledHandler.headline" : "{name} ist deaktiviert", 114 "service.disabledHandler.headline" : "{name} ist deaktiviert",
95 "service.errorHandler.action" : "{name} neuladen", 115 "service.errorHandler.action" : "{name} neu laden",
96 "service.errorHandler.editAction" : "{name} bearbeiten", 116 "service.errorHandler.editAction" : "{name} bearbeiten",
97 "service.errorHandler.headline" : "Oh nein!", 117 "service.errorHandler.headline" : "Oh nein!",
98 "service.errorHandler.message" : "Fehler", 118 "service.errorHandler.message" : "Fehler",
99 "service.errorHandler.text" : "{name} konnte nicht geladen werden.", 119 "service.errorHandler.text" : "{name} konnte nicht geladen werden.",
100 "services.getStarted" : "Loslegen", 120 "service.webviewLoader.loading" : "Lade",
101 "services.welcome" : "Willkommen bei Franz.", 121 "services.getStarted" : "Los geht's!",
122 "services.welcome" : "Willkommen bei Franz!",
102 "settings.account.account.editButton" : "Konto bearbeiten", 123 "settings.account.account.editButton" : "Konto bearbeiten",
103 "settings.account.accountType.basic" : "Basis Konto", 124 "settings.account.accountType.basic" : "Basis-Konto",
104 "settings.account.accountType.premium" : "Premium-Supporter Konto", 125 "settings.account.accountType.premium" : "Premium Lizenz",
105 "settings.account.buttonSave" : "Profil aktualisieren", 126 "settings.account.buttonSave" : "Profil aktualisieren",
106 "settings.account.deleteAccount" : "Benutzerkonto löschen", 127 "settings.account.deleteAccount" : "Benutzerkonto löschen",
107 "settings.account.deleteEmailSent" : "Du hast eine Email zur Bestätigung der Löschung Deines Benutzerkontos erhalten. Dein Benutzerkonto und Deine Daten können nach der Löschung nicht wiederhergestellt werden!", 128 "settings.account.deleteEmailSent" : "Du hast eine E-Mail zur Bestätigung der Löschung Deines Benutzerkontos erhalten. Dein Benutzerkonto und Deine Daten können nach der Löschung nicht wiederhergestellt werden!",
108 "settings.account.deleteInfo" : "Wenn du dein Franz Benutzerkonto nicht mehr länger benötigst, kannst du hier deinen Account und alle dazugehörigen Daten löschen.", 129 "settings.account.deleteInfo" : "Wenn du dein Franz-Benutzerkonto nicht mehr länger benötigst, kannst du es hier mit allen dazugehörigen Daten löschen.",
109 "settings.account.headline" : "Konto", 130 "settings.account.headline" : "Konto",
110 "settings.account.headlineAccount" : "Konto Informationen", 131 "settings.account.headlineAccount" : "Konto-Informationen",
111 "settings.account.headlineDangerZone" : "Benutzerkonto löschen", 132 "settings.account.headlineDangerZone" : "Benutzerkonto löschen",
112 "settings.account.headlineInvoices" : "Rechnungen", 133 "settings.account.headlineInvoices" : "Rechnungen",
113 "settings.account.headlinePassword" : "Passwort ändern", 134 "settings.account.headlinePassword" : "Passwort ändern",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Herunterladen", 138 "settings.account.invoiceDownload" : "Herunterladen",
118 "settings.account.manageSubscription.label" : "Dein Abonnement verwalten", 139 "settings.account.manageSubscription.label" : "Dein Abonnement verwalten",
119 "settings.account.successInfo" : "Deine Änderungen wurden gespeichert", 140 "settings.account.successInfo" : "Deine Änderungen wurden gespeichert",
141 "settings.account.tryReloadServices" : "Erneut versuchen",
120 "settings.account.tryReloadUserInfoRequest" : "Erneut versuchen", 142 "settings.account.tryReloadUserInfoRequest" : "Erneut versuchen",
121 "settings.account.userInfoRequestFailed" : "Benutzerinformationen konnten nicht geladen werden", 143 "settings.account.userInfoRequestFailed" : "Benutzerinformationen konnten nicht geladen werden",
122 "settings.app.buttonClearAllCache" : "Cache leeren", 144 "settings.app.buttonClearAllCache" : "Cache leeren",
@@ -127,43 +149,43 @@
127 "settings.app.form.autoLaunchInBackground" : "Im Hintergrund öffnen", 149 "settings.app.form.autoLaunchInBackground" : "Im Hintergrund öffnen",
128 "settings.app.form.autoLaunchOnStart" : "Franz beim Systemstart ausführen", 150 "settings.app.form.autoLaunchOnStart" : "Franz beim Systemstart ausführen",
129 "settings.app.form.beta" : "Beta-Versionen einbeziehen", 151 "settings.app.form.beta" : "Beta-Versionen einbeziehen",
130 "settings.app.form.darkMode" : "Die dunkle Seite erwartet dich (Dark Mode)", 152 "settings.app.form.darkMode" : "Die dunkle Seite erwartet dich! (Dark Mode)",
131 "settings.app.form.enableGPUAcceleration" : "Hardwarebeschleunigung aktivieren", 153 "settings.app.form.enableGPUAcceleration" : "Hardwarebeschleunigung aktivieren",
132 "settings.app.form.enableMenuBar" : "Franz in Menüleiste anzeigen",
133 "settings.app.form.enableSpellchecking" : "Rechtschreibprüfung aktivieren", 154 "settings.app.form.enableSpellchecking" : "Rechtschreibprüfung aktivieren",
134 "settings.app.form.enableSystemTray" : "Franz im Infobereich anzeigen", 155 "settings.app.form.enableSystemTray" : "Franz im Infobereich anzeigen",
135 "settings.app.form.hideDockIcon" : "Franz Icon im Dock ausblenden",
136 "settings.app.form.language" : "Sprache", 156 "settings.app.form.language" : "Sprache",
137 "settings.app.form.minimizeToSystemTray" : "Franz in den Infobereich minimieren", 157 "settings.app.form.minimizeToSystemTray" : "Franz in den Infobereich minimieren",
138 "settings.app.form.runInBackground" : "Franz im Hintergrund behalten, wenn das Fenster geschlossen wird", 158 "settings.app.form.runInBackground" : "Franz im Hintergrund behalten, wenn das Fenster geschlossen wird",
139 "settings.app.form.showDisabledServices" : "Deaktivierte Services-Tabs anzeigen", 159 "settings.app.form.showDisabledServices" : "Deaktivierte Services-Tabs anzeigen",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Ungelesene Nachrichten zeigen, wenn die Benachrichtigungen deaktiviert sind", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Ungelesene Nachrichten zeigen, wenn die Benachrichtigungen deaktiviert sind",
141 "settings.app.form.spellcheckerLanguage" : "Sprache für Rechtschreibprüfung",
142 "settings.app.headline" : "Einstellungen", 161 "settings.app.headline" : "Einstellungen",
143 "settings.app.headlineAdvanced" : "Erweitert", 162 "settings.app.headlineAdvanced" : "Erweitert",
144 "settings.app.headlineAppearance" : "Darstellung", 163 "settings.app.headlineAppearance" : "Darstellung",
145 "settings.app.headlineGeneral" : "Allgemeines", 164 "settings.app.headlineGeneral" : "Allgemeines",
146 "settings.app.headlineLanguage" : "Sprache", 165 "settings.app.headlineLanguage" : "Sprache",
147 "settings.app.headlineUpdates" : "Updates", 166 "settings.app.headlineUpdates" : "Updates",
167 "settings.app.languageDisclaimer" : "Offizielle Ãœbersetzungen: Englisch & Deutsch. Alle anderen Sprachen sind Ãœbersetzungen der Franz Community.",
148 "settings.app.restartRequired" : "Änderungen werden erst nach einem Neustart wirksam.", 168 "settings.app.restartRequired" : "Änderungen werden erst nach einem Neustart wirksam.",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Hilf uns, Franz in Deine Sprache zu übersetzen.", 170 "settings.app.translationHelp" : "Hilf uns, Franz in Deine Sprache zu übersetzen.",
151 "settings.app.updateStatusAvailable" : "Update verfügbar, lädt herunter...", 171 "settings.app.updateStatusAvailable" : "Update verfügbar, lädt herunter ...",
152 "settings.app.updateStatusSearching" : "Suche nach Updates", 172 "settings.app.updateStatusSearching" : "Suche nach Updates",
153 "settings.app.updateStatusUpToDate" : "Du nutzt die aktuellste Version von Franz", 173 "settings.app.updateStatusUpToDate" : "Du nutzt die aktuellste Version von Franz",
154 "settings.invite.headline" : "Lade 3 Deiner Freunde ein", 174 "settings.invite.headline" : "Lade drei Deiner Freunde ein",
155 "settings.navigation.account" : "Konto", 175 "settings.navigation.account" : "Konto",
156 "settings.navigation.availableServices" : "Verfügbare Dienste", 176 "settings.navigation.availableServices" : "Verfügbare Dienste",
157 "settings.navigation.inviteFriends" : "Freunde einladen", 177 "settings.navigation.inviteFriends" : "Freunde einladen",
158 "settings.navigation.logout" : "Abmelden", 178 "settings.navigation.logout" : "Abmelden",
159 "settings.navigation.settings" : "Einstellungen", 179 "settings.navigation.settings" : "Einstellungen",
180 "settings.navigation.team" : "Team verwalten",
160 "settings.navigation.yourServices" : "Deine Dienste", 181 "settings.navigation.yourServices" : "Deine Dienste",
182 "settings.navigation.yourWorkspaces" : "Deine Workspaces",
161 "settings.recipes.all" : "Alle Dienste", 183 "settings.recipes.all" : "Alle Dienste",
162 "settings.recipes.dev" : "Entwicklung", 184 "settings.recipes.dev" : "Entwicklung",
163 "settings.recipes.headline" : "Verfügbare Dienste", 185 "settings.recipes.headline" : "Verfügbare Dienste",
164 "settings.recipes.missingService" : "Fehlt ein Dienst?", 186 "settings.recipes.missingService" : "Fehlt ein Dienst?",
165 "settings.recipes.mostPopular" : "Am beliebtesten", 187 "settings.recipes.mostPopular" : "Am beliebtesten",
166 "settings.recipes.nothingFound" : "Entschuldigung, aber der von Dir gesuchte Dienst konnte nicht gefunden werden.", 188 "settings.recipes.nothingFound" : "Entschuldigung, der gesuchte Dienst konnte nicht gefunden werden.",
167 "settings.recipes.servicesSuccessfulAddedInfo" : "Dienst erfolgreich hinzugefügt", 189 "settings.recipes.servicesSuccessfulAddedInfo" : "Dienst erfolgreich hinzugefügt",
168 "settings.searchService" : "Dienst suchen", 190 "settings.searchService" : "Dienst suchen",
169 "settings.service.error.goBack" : "Zurück zu den Diensten", 191 "settings.service.error.goBack" : "Zurück zu den Diensten",
@@ -172,7 +194,7 @@
172 "settings.service.form.addServiceHeadline" : "{name} hinzufügen", 194 "settings.service.form.addServiceHeadline" : "{name} hinzufügen",
173 "settings.service.form.availableServices" : "Verfügbare Dienste", 195 "settings.service.form.availableServices" : "Verfügbare Dienste",
174 "settings.service.form.customUrl" : "Eigener Server", 196 "settings.service.form.customUrl" : "Eigener Server",
175 "settings.service.form.customUrlPremiumInfo" : "Um einen selbst gehosteten Dienst hinzuzufügen, brauchst Du ein Franz Premium-Supporter Konto.", 197 "settings.service.form.customUrlPremiumInfo" : "Um einen selbst gehosteten Dienst hinzuzufügen, brauchst Du ein Franz Premium Konto.",
176 "settings.service.form.customUrlUpgradeAccount" : "Dein Konto upgraden", 198 "settings.service.form.customUrlUpgradeAccount" : "Dein Konto upgraden",
177 "settings.service.form.customUrlValidationError" : "Dein {name}-Server konnte nicht verifiziert werden.", 199 "settings.service.form.customUrlValidationError" : "Dein {name}-Server konnte nicht verifiziert werden.",
178 "settings.service.form.deleteButton" : "Dienst löschen", 200 "settings.service.form.deleteButton" : "Dienst löschen",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Nachrichten-Badge für alle neuen Nachrichten anzeigen", 214 "settings.service.form.indirectMessages" : "Nachrichten-Badge für alle neuen Nachrichten anzeigen",
193 "settings.service.form.isMutedInfo" : "Sämtliche Wiedergabe von Tönen wird deaktiviert", 215 "settings.service.form.isMutedInfo" : "Sämtliche Wiedergabe von Tönen wird deaktiviert",
194 "settings.service.form.name" : "Name", 216 "settings.service.form.name" : "Name",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Einstellungen", 217 "settings.service.form.proxy.headline" : "HTTP-\/HTTPS-Proxy-Einstellungen",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy Einstellungen werden nicht mit den Franz Servern synchronisiert.", 219 "settings.service.form.proxy.info" : "Proxy-Einstellungen werden nicht mit den Franz Servern synchronisiert.",
198 "settings.service.form.proxy.isEnabled" : "Proxy Server verwenden", 220 "settings.service.form.proxy.isEnabled" : "Proxy-Server verwenden",
199 "settings.service.form.proxy.password" : "Passwort (optional)", 221 "settings.service.form.proxy.password" : "Passwort (optional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Bitte starte Franz nach dem Ändern der Proxy Einstellungen neu.", 223 "settings.service.form.proxy.restartInfo" : "Bitte starte Franz nach dem Ändern der Proxy-Einstellungen neu.",
202 "settings.service.form.proxy.user" : "Benutzer (optional)", 224 "settings.service.form.proxy.user" : "Benutzer (optional)",
203 "settings.service.form.saveButton" : "Dienst speichern", 225 "settings.service.form.saveButton" : "Dienst speichern",
204 "settings.service.form.spellcheckerLanguage" : "Sprache für Rechtschreibprüfung",
205 "settings.service.form.spellcheckerLanguage.default" : "Standard benutzen ({default})",
206 "settings.service.form.tabHosted" : "Gehostet", 226 "settings.service.form.tabHosted" : "Gehostet",
207 "settings.service.form.tabOnPremise" : "Selbst gehostet â­ï¸", 227 "settings.service.form.tabOnPremise" : "Selbst gehostet â­ï¸",
208 "settings.service.form.team" : "Team", 228 "settings.service.form.team" : "Team",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Dienste entdecken", 232 "settings.services.discoverServices" : "Dienste entdecken",
213 "settings.services.headline" : "Deine Dienste", 233 "settings.services.headline" : "Deine Dienste",
214 "settings.services.noServicesAdded" : "Du hast noch keine Dienste hinzugefügt.", 234 "settings.services.noServicesAdded" : "Du hast noch keine Dienste hinzugefügt.",
235 "settings.services.servicesRequestFailed" : "Dienste konnten nicht geladen werden",
215 "settings.services.tooltip.isDisabled" : "Dienst ist deaktiviert", 236 "settings.services.tooltip.isDisabled" : "Dienst ist deaktiviert",
216 "settings.services.tooltip.isMuted" : "Alle Töne sind deaktiviert", 237 "settings.services.tooltip.isMuted" : "Alle Töne sind deaktiviert",
217 "settings.services.tooltip.notificationsDisabled" : "Benachrichtigungen deaktiviert", 238 "settings.services.tooltip.notificationsDisabled" : "Benachrichtigungen deaktiviert",
218 "settings.services.updatedInfo" : "Deine Änderungen wurden gespeichert", 239 "settings.services.updatedInfo" : "Deine Änderungen wurden gespeichert",
240 "settings.team.contentHeadline" : "Franz für Teams",
241 "settings.team.copy" : "Mit Franz für Teams kannst du Kolleginnen und Kollegen per Email-Invite in dein Team einladen und ihre Abonnments in den Einstellungen deines Accounts verwalten. Verschwende keine Zeit mehr damit, Lizenzen für jedes Teammitglied einzeln einzurichten, vergiss mehrfache Rechnungen und unterschiedliche Abrechnungszeiträume - alles unter einem Dach.",
242 "settings.team.headline" : "Team",
243 "settings.team.intro" : "Mit Franz für Teams kannst du Premium Lizenzen für Kolleginnen und Kollegen oder Freunde und Familienmitglieder kaufen und verwalten - so viele du willst.",
244 "settings.team.manageAction" : "Verwalte dein Team auf meetfranz.com",
245 "settings.team.upgradeAction" : "Account Upgrade durchführen",
219 "settings.user.form.accountType.company" : "Firma", 246 "settings.user.form.accountType.company" : "Firma",
220 "settings.user.form.accountType.individual" : "Einzelperson", 247 "settings.user.form.accountType.individual" : "Einzelperson",
221 "settings.user.form.accountType.label" : "Konto-Typ", 248 "settings.user.form.accountType.label" : "Konto-Typ",
@@ -225,32 +252,48 @@
225 "settings.user.form.firstname" : "Vorname", 252 "settings.user.form.firstname" : "Vorname",
226 "settings.user.form.lastname" : "Nachname", 253 "settings.user.form.lastname" : "Nachname",
227 "settings.user.form.newPassword" : "Neues Passwort", 254 "settings.user.form.newPassword" : "Neues Passwort",
255 "settings.workspace.add.form.name" : "Name",
256 "settings.workspace.add.form.submitButton" : "Workspace erstellen",
257 "settings.workspace.form.buttonDelete" : "Workspace löschen",
258 "settings.workspace.form.buttonSave" : "Workspace speichern",
259 "settings.workspace.form.name" : "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in diesem Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Deine Workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace wurde gelöscht",
263 "settings.workspaces.headline" : "Deine Workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "Du hast noch keine Workspaces hinzugefügt",
265 "settings.workspaces.tryReloadWorkspaces" : "Erneut versuchen",
266 "settings.workspaces.updatedInfo" : "Deine Änderungen wurden gespeichert",
267 "settings.workspaces.workspaceFeatureHeadline" : "Weniger ist mehr: Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Mit Franz Workspaces hast du alles im Blick, was gerade wichtig ist - und nur das. Erstelle unterschiedliche Sets von Services, und wechsle jederzeit zwischen ihnen hin und her. Du entscheidest welche Services du wann und wo brauchst, um ungestört arbeiten zu können - oder zu Hause besser abzuschalten.",
269 "settings.workspaces.workspacesRequestFailed" : "Workspaces konnte nicht geladen werden",
228 "sidebar.addNewService" : "Neuen Dienst hinzufügen", 270 "sidebar.addNewService" : "Neuen Dienst hinzufügen",
271 "sidebar.closeWorkspaceDrawer" : "Workspaces schließen",
229 "sidebar.muteApp" : "Benachrichtigungen & Audio deaktivieren", 272 "sidebar.muteApp" : "Benachrichtigungen & Audio deaktivieren",
273 "sidebar.openWorkspaceDrawer" : "Workspaces öffnen",
230 "sidebar.settings" : "Einstellungen", 274 "sidebar.settings" : "Einstellungen",
231 "sidebar.unmuteApp" : "Benachrichtigungen & Audio aktivieren", 275 "sidebar.unmuteApp" : "Benachrichtigungen & Audio aktivieren",
232 "signup.company.label" : "Firma", 276 "signup.company.label" : "Firma",
233 "signup.email.label" : "E-Mail Adresse", 277 "signup.email.label" : "E-Mail-Adresse",
234 "signup.emailDuplicate" : "Es existiert bereits ein Benutzer mit dieser E-Mail Adresse.", 278 "signup.emailDuplicate" : "Es existiert bereits ein Benutzer mit dieser E-Mail Adresse.",
235 "signup.firstname.label" : "Vorname", 279 "signup.firstname.label" : "Vorname",
236 "signup.headline" : "Anmelden", 280 "signup.headline" : "Anmelden",
237 "signup.lastname.label" : "Nachname", 281 "signup.lastname.label" : "Nachname",
238 "signup.legal.info" : "Mit der Erstellung eines Franz Kontos akzeptierst Du die", 282 "signup.legal.info" : "Mit der Erstellung eines Franz-Kontos akzeptierst Du die",
239 "signup.legal.privacy" : "Datenschutzerklärung", 283 "signup.legal.privacy" : "Datenschutzerklärung",
240 "signup.legal.terms" : "Nutzungsbedingungen", 284 "signup.legal.terms" : "Nutzungsbedingungen",
241 "signup.link.login" : "Du hast bereits ein Konto? Melde Dich an.", 285 "signup.link.login" : "Du hast bereits ein Konto? Melde Dich an.",
242 "signup.password.label" : "Passwort", 286 "signup.password.label" : "Passwort",
243 "signup.submit.label" : "Konto erstellen", 287 "signup.submit.label" : "Konto erstellen",
244 "subscription.euTaxInfo" : "Preise sind exklusive Steuern.", 288 "subscription.euTaxInfo" : "Preise zuzüglich allfälliger Steuern",
245 "subscription.features.ads" : "Werbefrei auf Lebenszeit!", 289 "subscription.features.ads" : "Werbefrei auf Lebenszeit!",
246 "subscription.features.comingSoon" : "folgt bald", 290 "subscription.features.comingSoon" : "folgt bald",
247 "subscription.features.encryptedSync" : "Verschlüsselte Sitzungs-Synchronisation", 291 "subscription.features.noInterruptions" : "Verwende Franz ohne Wartezeiten",
248 "subscription.features.noInterruptions" : "Keine Wartezeiten um Franz zu verwenden", 292 "subscription.features.onpremise.mattermost" : "Integration von gehosteten Diensten wie Mattermost",
249 "subscription.features.onpremise" : "Integration von gehosteten Diensten, wie HipChat",
250 "subscription.features.onpremise.mattermost" : "Integration von gehosteten Diensten, wie Mattermost",
251 "subscription.features.proxy" : "Proxy Support für Dienste", 293 "subscription.features.proxy" : "Proxy Support für Dienste",
252 "subscription.features.spellchecker" : "Unterstützung für Rechtschreibprüfung", 294 "subscription.features.spellchecker" : "Unterstützung für Rechtschreibprüfung",
253 "subscription.includedFeatures" : "Bezahlte Franz Premium Support Konten beinhalten", 295 "subscription.features.workspaces" : "Organisiere deine Services in Workspaces",
296 "subscription.includedFeatures" : "Bezahlte Franz Premium Lizenzen beinhalten",
254 "subscription.paymentSessionError" : "Das Zahlungs-Formular konnte nicht geladen werden.", 297 "subscription.paymentSessionError" : "Das Zahlungs-Formular konnte nicht geladen werden.",
255 "subscription.submit.label" : "Ich möchte die Entwicklung von Franz unterstützen", 298 "subscription.submit.label" : "Ich möchte die Entwicklung von Franz unterstützen",
256 "subscription.type.free" : "kostenlos", 299 "subscription.type.free" : "kostenlos",
@@ -266,12 +309,23 @@
266 "tabs.item.enableAudio" : "Audio aktivieren", 309 "tabs.item.enableAudio" : "Audio aktivieren",
267 "tabs.item.enableNotification" : "Benachrichtigungen aktivieren", 310 "tabs.item.enableNotification" : "Benachrichtigungen aktivieren",
268 "tabs.item.enableService" : "Dienst aktivieren", 311 "tabs.item.enableService" : "Dienst aktivieren",
269 "tabs.item.reload" : "Neuladen", 312 "tabs.item.reload" : "Neu laden",
270 "validation.email" : "{field} ist ungültig", 313 "validation.email" : "{field} ist ungültig",
271 "validation.minLength" : "{field} muss mindestens {length} Zeichen enthalten", 314 "validation.minLength" : "{field} muss mindestens {length} Zeichen enthalten",
315 "validation.oneRequired" : "Mindestens ein Wert wird benötigt",
272 "validation.required" : "{field} wird benötigt", 316 "validation.required" : "{field} wird benötigt",
273 "validation.url" : "{field} ist keine gültige URL", 317 "validation.url" : "{field} ist keine gültige URL",
274 "welcome.loginButton" : "Bei Franz einloggen", 318 "welcome.loginButton" : "Bei Franz einloggen",
275 "welcome.signupButton" : "Kostenloses Konto erstellen", 319 "welcome.signupButton" : "Kostenloses Konto erstellen",
276 "welcome.slogan" : "Kommunikation, die für Dich funktioniert" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Neuen Workspace hinzufügen",
321 "workspaceDrawer.allServices" : "Alle Dienste",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "Bearbeiten",
324 "workspaceDrawer.item.noServicesAddedYet" : "Noch keine Services hinzugefügt",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Erstelle deinen ersten Workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium Feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Premium Account aktivieren",
328 "workspaceDrawer.workspaceFeatureInfo" : "Mit Franz Workspaces hast du alles im Blick, was gerade wichtig ist - und nur das. Erstelle unterschiedliche Sets von Services, und wechsle jederzeit zwischen ihnen hin und her. Du entscheidest welche Services du wann und wo brauchst, um ungestört arbeiten zu können - oder zu Hause besser abzuschalten.",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Workspaces bearbeiten",
330 "workspaces.switchingIndicator.switchingTo" : "Wechsle zu"
277} 331}
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json
new file mode 100644
index 000000000..632eb38fd
--- /dev/null
+++ b/src/i18n/locales/defaultMessages.json
@@ -0,0 +1,4603 @@
1[
2 {
3 "descriptors": [
4 {
5 "defaultMessage": "!!!Import your Franz 4 services",
6 "end": {
7 "column": 3,
8 "line": 16
9 },
10 "file": "src/components/auth/Import.js",
11 "id": "import.headline",
12 "start": {
13 "column": 12,
14 "line": 13
15 }
16 },
17 {
18 "defaultMessage": "!!!Services not yet supported in Franz 5",
19 "end": {
20 "column": 3,
21 "line": 20
22 },
23 "file": "src/components/auth/Import.js",
24 "id": "import.notSupportedHeadline",
25 "start": {
26 "column": 24,
27 "line": 17
28 }
29 },
30 {
31 "defaultMessage": "!!!Import {count} services",
32 "end": {
33 "column": 3,
34 "line": 24
35 },
36 "file": "src/components/auth/Import.js",
37 "id": "import.submit.label",
38 "start": {
39 "column": 21,
40 "line": 21
41 }
42 },
43 {
44 "defaultMessage": "!!!I want to add services manually",
45 "end": {
46 "column": 3,
47 "line": 28
48 },
49 "file": "src/components/auth/Import.js",
50 "id": "import.skip.label",
51 "start": {
52 "column": 19,
53 "line": 25
54 }
55 }
56 ],
57 "path": "src/components/auth/Import.json"
58 },
59 {
60 "descriptors": [
61 {
62 "defaultMessage": "!!!Invite Friends",
63 "end": {
64 "column": 3,
65 "line": 19
66 },
67 "file": "src/components/auth/Invite.js",
68 "id": "settings.invite.headline",
69 "start": {
70 "column": 20,
71 "line": 16
72 }
73 },
74 {
75 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
76 "end": {
77 "column": 3,
78 "line": 23
79 },
80 "file": "src/components/auth/Invite.js",
81 "id": "invite.headline.friends",
82 "start": {
83 "column": 12,
84 "line": 20
85 }
86 },
87 {
88 "defaultMessage": "!!!Name",
89 "end": {
90 "column": 3,
91 "line": 27
92 },
93 "file": "src/components/auth/Invite.js",
94 "id": "invite.name.label",
95 "start": {
96 "column": 13,
97 "line": 24
98 }
99 },
100 {
101 "defaultMessage": "!!!Email address",
102 "end": {
103 "column": 3,
104 "line": 31
105 },
106 "file": "src/components/auth/Invite.js",
107 "id": "invite.email.label",
108 "start": {
109 "column": 14,
110 "line": 28
111 }
112 },
113 {
114 "defaultMessage": "!!!Send invites",
115 "end": {
116 "column": 3,
117 "line": 35
118 },
119 "file": "src/components/auth/Invite.js",
120 "id": "invite.submit.label",
121 "start": {
122 "column": 21,
123 "line": 32
124 }
125 },
126 {
127 "defaultMessage": "!!!I want to do this later",
128 "end": {
129 "column": 3,
130 "line": 39
131 },
132 "file": "src/components/auth/Invite.js",
133 "id": "invite.skip.label",
134 "start": {
135 "column": 19,
136 "line": 36
137 }
138 },
139 {
140 "defaultMessage": "!!!Invitations sent successfully",
141 "end": {
142 "column": 3,
143 "line": 43
144 },
145 "file": "src/components/auth/Invite.js",
146 "id": "invite.successInfo",
147 "start": {
148 "column": 21,
149 "line": 40
150 }
151 }
152 ],
153 "path": "src/components/auth/Invite.json"
154 },
155 {
156 "descriptors": [
157 {
158 "defaultMessage": "!!!Sign in",
159 "end": {
160 "column": 3,
161 "line": 20
162 },
163 "file": "src/components/auth/Login.js",
164 "id": "login.headline",
165 "start": {
166 "column": 12,
167 "line": 17
168 }
169 },
170 {
171 "defaultMessage": "!!!Email address",
172 "end": {
173 "column": 3,
174 "line": 24
175 },
176 "file": "src/components/auth/Login.js",
177 "id": "login.email.label",
178 "start": {
179 "column": 14,
180 "line": 21
181 }
182 },
183 {
184 "defaultMessage": "!!!Password",
185 "end": {
186 "column": 3,
187 "line": 28
188 },
189 "file": "src/components/auth/Login.js",
190 "id": "login.password.label",
191 "start": {
192 "column": 17,
193 "line": 25
194 }
195 },
196 {
197 "defaultMessage": "!!!Sign in",
198 "end": {
199 "column": 3,
200 "line": 32
201 },
202 "file": "src/components/auth/Login.js",
203 "id": "login.submit.label",
204 "start": {
205 "column": 21,
206 "line": 29
207 }
208 },
209 {
210 "defaultMessage": "!!!Email or password not valid",
211 "end": {
212 "column": 3,
213 "line": 36
214 },
215 "file": "src/components/auth/Login.js",
216 "id": "login.invalidCredentials",
217 "start": {
218 "column": 22,
219 "line": 33
220 }
221 },
222 {
223 "defaultMessage": "!!!Your session expired, please login again.",
224 "end": {
225 "column": 3,
226 "line": 40
227 },
228 "file": "src/components/auth/Login.js",
229 "id": "login.tokenExpired",
230 "start": {
231 "column": 16,
232 "line": 37
233 }
234 },
235 {
236 "defaultMessage": "!!!Your session expired, please login again.",
237 "end": {
238 "column": 3,
239 "line": 44
240 },
241 "file": "src/components/auth/Login.js",
242 "id": "login.serverLogout",
243 "start": {
244 "column": 16,
245 "line": 41
246 }
247 },
248 {
249 "defaultMessage": "!!!Create a free account",
250 "end": {
251 "column": 3,
252 "line": 48
253 },
254 "file": "src/components/auth/Login.js",
255 "id": "login.link.signup",
256 "start": {
257 "column": 14,
258 "line": 45
259 }
260 },
261 {
262 "defaultMessage": "!!!Forgot password",
263 "end": {
264 "column": 3,
265 "line": 52
266 },
267 "file": "src/components/auth/Login.js",
268 "id": "login.link.password",
269 "start": {
270 "column": 16,
271 "line": 49
272 }
273 }
274 ],
275 "path": "src/components/auth/Login.json"
276 },
277 {
278 "descriptors": [
279 {
280 "defaultMessage": "!!!Forgot password",
281 "end": {
282 "column": 3,
283 "line": 17
284 },
285 "file": "src/components/auth/Password.js",
286 "id": "password.headline",
287 "start": {
288 "column": 12,
289 "line": 14
290 }
291 },
292 {
293 "defaultMessage": "!!!Email address",
294 "end": {
295 "column": 3,
296 "line": 21
297 },
298 "file": "src/components/auth/Password.js",
299 "id": "password.email.label",
300 "start": {
301 "column": 14,
302 "line": 18
303 }
304 },
305 {
306 "defaultMessage": "!!!Submit",
307 "end": {
308 "column": 3,
309 "line": 25
310 },
311 "file": "src/components/auth/Password.js",
312 "id": "password.submit.label",
313 "start": {
314 "column": 21,
315 "line": 22
316 }
317 },
318 {
319 "defaultMessage": "!!!Your new password was sent to your email address",
320 "end": {
321 "column": 3,
322 "line": 29
323 },
324 "file": "src/components/auth/Password.js",
325 "id": "password.successInfo",
326 "start": {
327 "column": 15,
328 "line": 26
329 }
330 },
331 {
332 "defaultMessage": "!!!No user affiliated with that email address",
333 "end": {
334 "column": 3,
335 "line": 33
336 },
337 "file": "src/components/auth/Password.js",
338 "id": "password.noUser",
339 "start": {
340 "column": 10,
341 "line": 30
342 }
343 },
344 {
345 "defaultMessage": "!!!Create a free account",
346 "end": {
347 "column": 3,
348 "line": 37
349 },
350 "file": "src/components/auth/Password.js",
351 "id": "password.link.signup",
352 "start": {
353 "column": 14,
354 "line": 34
355 }
356 },
357 {
358 "defaultMessage": "!!!Sign in to your account",
359 "end": {
360 "column": 3,
361 "line": 41
362 },
363 "file": "src/components/auth/Password.js",
364 "id": "password.link.login",
365 "start": {
366 "column": 13,
367 "line": 38
368 }
369 }
370 ],
371 "path": "src/components/auth/Password.json"
372 },
373 {
374 "descriptors": [
375 {
376 "defaultMessage": "!!!Support Franz",
377 "end": {
378 "column": 3,
379 "line": 16
380 },
381 "file": "src/components/auth/Pricing.js",
382 "id": "pricing.headline",
383 "start": {
384 "column": 12,
385 "line": 13
386 }
387 },
388 {
389 "defaultMessage": "!!!Select your support plan",
390 "end": {
391 "column": 3,
392 "line": 20
393 },
394 "file": "src/components/auth/Pricing.js",
395 "id": "pricing.support.label",
396 "start": {
397 "column": 23,
398 "line": 17
399 }
400 },
401 {
402 "defaultMessage": "!!!Support the development of Franz",
403 "end": {
404 "column": 3,
405 "line": 24
406 },
407 "file": "src/components/auth/Pricing.js",
408 "id": "pricing.submit.label",
409 "start": {
410 "column": 21,
411 "line": 21
412 }
413 },
414 {
415 "defaultMessage": "!!!I don't want to support the development of Franz.",
416 "end": {
417 "column": 3,
418 "line": 28
419 },
420 "file": "src/components/auth/Pricing.js",
421 "id": "pricing.link.skipPayment",
422 "start": {
423 "column": 15,
424 "line": 25
425 }
426 }
427 ],
428 "path": "src/components/auth/Pricing.json"
429 },
430 {
431 "descriptors": [
432 {
433 "defaultMessage": "!!!Sign up",
434 "end": {
435 "column": 3,
436 "line": 21
437 },
438 "file": "src/components/auth/Signup.js",
439 "id": "signup.headline",
440 "start": {
441 "column": 12,
442 "line": 18
443 }
444 },
445 {
446 "defaultMessage": "!!!Firstname",
447 "end": {
448 "column": 3,
449 "line": 25
450 },
451 "file": "src/components/auth/Signup.js",
452 "id": "signup.firstname.label",
453 "start": {
454 "column": 18,
455 "line": 22
456 }
457 },
458 {
459 "defaultMessage": "!!!Lastname",
460 "end": {
461 "column": 3,
462 "line": 29
463 },
464 "file": "src/components/auth/Signup.js",
465 "id": "signup.lastname.label",
466 "start": {
467 "column": 17,
468 "line": 26
469 }
470 },
471 {
472 "defaultMessage": "!!!Email address",
473 "end": {
474 "column": 3,
475 "line": 33
476 },
477 "file": "src/components/auth/Signup.js",
478 "id": "signup.email.label",
479 "start": {
480 "column": 14,
481 "line": 30
482 }
483 },
484 {
485 "defaultMessage": "!!!Company",
486 "end": {
487 "column": 3,
488 "line": 37
489 },
490 "file": "src/components/auth/Signup.js",
491 "id": "signup.company.label",
492 "start": {
493 "column": 16,
494 "line": 34
495 }
496 },
497 {
498 "defaultMessage": "!!!Password",
499 "end": {
500 "column": 3,
501 "line": 41
502 },
503 "file": "src/components/auth/Signup.js",
504 "id": "signup.password.label",
505 "start": {
506 "column": 17,
507 "line": 38
508 }
509 },
510 {
511 "defaultMessage": "!!!By creating a Franz account you accept the",
512 "end": {
513 "column": 3,
514 "line": 45
515 },
516 "file": "src/components/auth/Signup.js",
517 "id": "signup.legal.info",
518 "start": {
519 "column": 13,
520 "line": 42
521 }
522 },
523 {
524 "defaultMessage": "!!!Terms of service",
525 "end": {
526 "column": 3,
527 "line": 49
528 },
529 "file": "src/components/auth/Signup.js",
530 "id": "signup.legal.terms",
531 "start": {
532 "column": 9,
533 "line": 46
534 }
535 },
536 {
537 "defaultMessage": "!!!Privacy Statement",
538 "end": {
539 "column": 3,
540 "line": 53
541 },
542 "file": "src/components/auth/Signup.js",
543 "id": "signup.legal.privacy",
544 "start": {
545 "column": 11,
546 "line": 50
547 }
548 },
549 {
550 "defaultMessage": "!!!Create account",
551 "end": {
552 "column": 3,
553 "line": 57
554 },
555 "file": "src/components/auth/Signup.js",
556 "id": "signup.submit.label",
557 "start": {
558 "column": 21,
559 "line": 54
560 }
561 },
562 {
563 "defaultMessage": "!!!Already have an account, sign in?",
564 "end": {
565 "column": 3,
566 "line": 61
567 },
568 "file": "src/components/auth/Signup.js",
569 "id": "signup.link.login",
570 "start": {
571 "column": 13,
572 "line": 58
573 }
574 },
575 {
576 "defaultMessage": "!!!A user with that email address already exists",
577 "end": {
578 "column": 3,
579 "line": 65
580 },
581 "file": "src/components/auth/Signup.js",
582 "id": "signup.emailDuplicate",
583 "start": {
584 "column": 18,
585 "line": 62
586 }
587 }
588 ],
589 "path": "src/components/auth/Signup.json"
590 },
591 {
592 "descriptors": [
593 {
594 "defaultMessage": "!!!Create a free account",
595 "end": {
596 "column": 3,
597 "line": 12
598 },
599 "file": "src/components/auth/Welcome.js",
600 "id": "welcome.signupButton",
601 "start": {
602 "column": 16,
603 "line": 9
604 }
605 },
606 {
607 "defaultMessage": "!!!Login to your account",
608 "end": {
609 "column": 3,
610 "line": 16
611 },
612 "file": "src/components/auth/Welcome.js",
613 "id": "welcome.loginButton",
614 "start": {
615 "column": 15,
616 "line": 13
617 }
618 }
619 ],
620 "path": "src/components/auth/Welcome.json"
621 },
622 {
623 "descriptors": [
624 {
625 "defaultMessage": "!!!Your services have been updated.",
626 "end": {
627 "column": 3,
628 "line": 30
629 },
630 "file": "src/components/layout/AppLayout.js",
631 "id": "infobar.servicesUpdated",
632 "start": {
633 "column": 19,
634 "line": 27
635 }
636 },
637 {
638 "defaultMessage": "!!!A new update for Franz is available.",
639 "end": {
640 "column": 3,
641 "line": 34
642 },
643 "file": "src/components/layout/AppLayout.js",
644 "id": "infobar.updateAvailable",
645 "start": {
646 "column": 19,
647 "line": 31
648 }
649 },
650 {
651 "defaultMessage": "!!!Reload services",
652 "end": {
653 "column": 3,
654 "line": 38
655 },
656 "file": "src/components/layout/AppLayout.js",
657 "id": "infobar.buttonReloadServices",
658 "start": {
659 "column": 24,
660 "line": 35
661 }
662 },
663 {
664 "defaultMessage": "!!!Changelog",
665 "end": {
666 "column": 3,
667 "line": 42
668 },
669 "file": "src/components/layout/AppLayout.js",
670 "id": "infobar.buttonChangelog",
671 "start": {
672 "column": 13,
673 "line": 39
674 }
675 },
676 {
677 "defaultMessage": "!!!Restart & install update",
678 "end": {
679 "column": 3,
680 "line": 46
681 },
682 "file": "src/components/layout/AppLayout.js",
683 "id": "infobar.buttonInstallUpdate",
684 "start": {
685 "column": 23,
686 "line": 43
687 }
688 },
689 {
690 "defaultMessage": "!!!Could not load services and user information",
691 "end": {
692 "column": 3,
693 "line": 50
694 },
695 "file": "src/components/layout/AppLayout.js",
696 "id": "infobar.requiredRequestsFailed",
697 "start": {
698 "column": 26,
699 "line": 47
700 }
701 }
702 ],
703 "path": "src/components/layout/AppLayout.json"
704 },
705 {
706 "descriptors": [
707 {
708 "defaultMessage": "!!!Settings",
709 "end": {
710 "column": 3,
711 "line": 16
712 },
713 "file": "src/components/layout/Sidebar.js",
714 "id": "sidebar.settings",
715 "start": {
716 "column": 12,
717 "line": 13
718 }
719 },
720 {
721 "defaultMessage": "!!!Add new service",
722 "end": {
723 "column": 3,
724 "line": 20
725 },
726 "file": "src/components/layout/Sidebar.js",
727 "id": "sidebar.addNewService",
728 "start": {
729 "column": 17,
730 "line": 17
731 }
732 },
733 {
734 "defaultMessage": "!!!Disable notifications & audio",
735 "end": {
736 "column": 3,
737 "line": 24
738 },
739 "file": "src/components/layout/Sidebar.js",
740 "id": "sidebar.muteApp",
741 "start": {
742 "column": 8,
743 "line": 21
744 }
745 },
746 {
747 "defaultMessage": "!!!Enable notifications & audio",
748 "end": {
749 "column": 3,
750 "line": 28
751 },
752 "file": "src/components/layout/Sidebar.js",
753 "id": "sidebar.unmuteApp",
754 "start": {
755 "column": 10,
756 "line": 25
757 }
758 },
759 {
760 "defaultMessage": "!!!Open workspace drawer",
761 "end": {
762 "column": 3,
763 "line": 32
764 },
765 "file": "src/components/layout/Sidebar.js",
766 "id": "sidebar.openWorkspaceDrawer",
767 "start": {
768 "column": 23,
769 "line": 29
770 }
771 },
772 {
773 "defaultMessage": "!!!Close workspace drawer",
774 "end": {
775 "column": 3,
776 "line": 36
777 },
778 "file": "src/components/layout/Sidebar.js",
779 "id": "sidebar.closeWorkspaceDrawer",
780 "start": {
781 "column": 24,
782 "line": 33
783 }
784 }
785 ],
786 "path": "src/components/layout/Sidebar.json"
787 },
788 {
789 "descriptors": [
790 {
791 "defaultMessage": "!!!Oh no!",
792 "end": {
793 "column": 3,
794 "line": 15
795 },
796 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
797 "id": "service.errorHandler.headline",
798 "start": {
799 "column": 12,
800 "line": 12
801 }
802 },
803 {
804 "defaultMessage": "!!!{name} has failed to load.",
805 "end": {
806 "column": 3,
807 "line": 19
808 },
809 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
810 "id": "service.errorHandler.text",
811 "start": {
812 "column": 8,
813 "line": 16
814 }
815 },
816 {
817 "defaultMessage": "!!!Reload {name}",
818 "end": {
819 "column": 3,
820 "line": 23
821 },
822 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
823 "id": "service.errorHandler.action",
824 "start": {
825 "column": 10,
826 "line": 20
827 }
828 },
829 {
830 "defaultMessage": "!!!Edit {name}",
831 "end": {
832 "column": 3,
833 "line": 27
834 },
835 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
836 "id": "service.errorHandler.editAction",
837 "start": {
838 "column": 14,
839 "line": 24
840 }
841 },
842 {
843 "defaultMessage": "!!!Error:",
844 "end": {
845 "column": 3,
846 "line": 31
847 },
848 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
849 "id": "service.errorHandler.message",
850 "start": {
851 "column": 16,
852 "line": 28
853 }
854 }
855 ],
856 "path": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.json"
857 },
858 {
859 "descriptors": [
860 {
861 "defaultMessage": "!!!{name} is disabled",
862 "end": {
863 "column": 3,
864 "line": 12
865 },
866 "file": "src/components/services/content/ServiceDisabled.js",
867 "id": "service.disabledHandler.headline",
868 "start": {
869 "column": 12,
870 "line": 9
871 }
872 },
873 {
874 "defaultMessage": "!!!Enable {name}",
875 "end": {
876 "column": 3,
877 "line": 16
878 },
879 "file": "src/components/services/content/ServiceDisabled.js",
880 "id": "service.disabledHandler.action",
881 "start": {
882 "column": 10,
883 "line": 13
884 }
885 }
886 ],
887 "path": "src/components/services/content/ServiceDisabled.json"
888 },
889 {
890 "descriptors": [
891 {
892 "defaultMessage": "!!!Welcome to Franz",
893 "end": {
894 "column": 3,
895 "line": 14
896 },
897 "file": "src/components/services/content/Services.js",
898 "id": "services.welcome",
899 "start": {
900 "column": 11,
901 "line": 11
902 }
903 },
904 {
905 "defaultMessage": "!!!Get started",
906 "end": {
907 "column": 3,
908 "line": 18
909 },
910 "file": "src/components/services/content/Services.js",
911 "id": "services.getStarted",
912 "start": {
913 "column": 14,
914 "line": 15
915 }
916 }
917 ],
918 "path": "src/components/services/content/Services.json"
919 },
920 {
921 "descriptors": [
922 {
923 "defaultMessage": "!!!Oh no!",
924 "end": {
925 "column": 3,
926 "line": 13
927 },
928 "file": "src/components/services/content/WebviewCrashHandler.js",
929 "id": "service.crashHandler.headline",
930 "start": {
931 "column": 12,
932 "line": 10
933 }
934 },
935 {
936 "defaultMessage": "!!!{name} has caused an error.",
937 "end": {
938 "column": 3,
939 "line": 17
940 },
941 "file": "src/components/services/content/WebviewCrashHandler.js",
942 "id": "service.crashHandler.text",
943 "start": {
944 "column": 8,
945 "line": 14
946 }
947 },
948 {
949 "defaultMessage": "!!!Reload {name}",
950 "end": {
951 "column": 3,
952 "line": 21
953 },
954 "file": "src/components/services/content/WebviewCrashHandler.js",
955 "id": "service.crashHandler.action",
956 "start": {
957 "column": 10,
958 "line": 18
959 }
960 },
961 {
962 "defaultMessage": "!!!Trying to automatically restore {name} in {seconds} seconds",
963 "end": {
964 "column": 3,
965 "line": 25
966 },
967 "file": "src/components/services/content/WebviewCrashHandler.js",
968 "id": "service.crashHandler.autoReload",
969 "start": {
970 "column": 14,
971 "line": 22
972 }
973 }
974 ],
975 "path": "src/components/services/content/WebviewCrashHandler.json"
976 },
977 {
978 "descriptors": [
979 {
980 "defaultMessage": "!!!Reload",
981 "end": {
982 "column": 3,
983 "line": 18
984 },
985 "file": "src/components/services/tabs/TabItem.js",
986 "id": "tabs.item.reload",
987 "start": {
988 "column": 10,
989 "line": 15
990 }
991 },
992 {
993 "defaultMessage": "!!!Edit",
994 "end": {
995 "column": 3,
996 "line": 22
997 },
998 "file": "src/components/services/tabs/TabItem.js",
999 "id": "tabs.item.edit",
1000 "start": {
1001 "column": 8,
1002 "line": 19
1003 }
1004 },
1005 {
1006 "defaultMessage": "!!!Disable notifications",
1007 "end": {
1008 "column": 3,
1009 "line": 26
1010 },
1011 "file": "src/components/services/tabs/TabItem.js",
1012 "id": "tabs.item.disableNotifications",
1013 "start": {
1014 "column": 24,
1015 "line": 23
1016 }
1017 },
1018 {
1019 "defaultMessage": "!!!Enable notifications",
1020 "end": {
1021 "column": 3,
1022 "line": 30
1023 },
1024 "file": "src/components/services/tabs/TabItem.js",
1025 "id": "tabs.item.enableNotification",
1026 "start": {
1027 "column": 23,
1028 "line": 27
1029 }
1030 },
1031 {
1032 "defaultMessage": "!!!Disable audio",
1033 "end": {
1034 "column": 3,
1035 "line": 34
1036 },
1037 "file": "src/components/services/tabs/TabItem.js",
1038 "id": "tabs.item.disableAudio",
1039 "start": {
1040 "column": 16,
1041 "line": 31
1042 }
1043 },
1044 {
1045 "defaultMessage": "!!!Enable audio",
1046 "end": {
1047 "column": 3,
1048 "line": 38
1049 },
1050 "file": "src/components/services/tabs/TabItem.js",
1051 "id": "tabs.item.enableAudio",
1052 "start": {
1053 "column": 15,
1054 "line": 35
1055 }
1056 },
1057 {
1058 "defaultMessage": "!!!Disable Service",
1059 "end": {
1060 "column": 3,
1061 "line": 42
1062 },
1063 "file": "src/components/services/tabs/TabItem.js",
1064 "id": "tabs.item.disableService",
1065 "start": {
1066 "column": 18,
1067 "line": 39
1068 }
1069 },
1070 {
1071 "defaultMessage": "!!!Enable Service",
1072 "end": {
1073 "column": 3,
1074 "line": 46
1075 },
1076 "file": "src/components/services/tabs/TabItem.js",
1077 "id": "tabs.item.enableService",
1078 "start": {
1079 "column": 17,
1080 "line": 43
1081 }
1082 },
1083 {
1084 "defaultMessage": "!!!Delete Service",
1085 "end": {
1086 "column": 3,
1087 "line": 50
1088 },
1089 "file": "src/components/services/tabs/TabItem.js",
1090 "id": "tabs.item.deleteService",
1091 "start": {
1092 "column": 17,
1093 "line": 47
1094 }
1095 }
1096 ],
1097 "path": "src/components/services/tabs/TabItem.json"
1098 },
1099 {
1100 "descriptors": [
1101 {
1102 "defaultMessage": "!!!Account",
1103 "end": {
1104 "column": 3,
1105 "line": 17
1106 },
1107 "file": "src/components/settings/account/AccountDashboard.js",
1108 "id": "settings.account.headline",
1109 "start": {
1110 "column": 12,
1111 "line": 14
1112 }
1113 },
1114 {
1115 "defaultMessage": "!!!Your Subscription",
1116 "end": {
1117 "column": 3,
1118 "line": 21
1119 },
1120 "file": "src/components/settings/account/AccountDashboard.js",
1121 "id": "settings.account.headlineSubscription",
1122 "start": {
1123 "column": 24,
1124 "line": 18
1125 }
1126 },
1127 {
1128 "defaultMessage": "!!!Upgrade your Account",
1129 "end": {
1130 "column": 3,
1131 "line": 25
1132 },
1133 "file": "src/components/settings/account/AccountDashboard.js",
1134 "id": "settings.account.headlineUpgrade",
1135 "start": {
1136 "column": 19,
1137 "line": 22
1138 }
1139 },
1140 {
1141 "defaultMessage": "!!Danger Zone",
1142 "end": {
1143 "column": 3,
1144 "line": 29
1145 },
1146 "file": "src/components/settings/account/AccountDashboard.js",
1147 "id": "settings.account.headlineDangerZone",
1148 "start": {
1149 "column": 22,
1150 "line": 26
1151 }
1152 },
1153 {
1154 "defaultMessage": "!!!Manage your subscription",
1155 "end": {
1156 "column": 3,
1157 "line": 33
1158 },
1159 "file": "src/components/settings/account/AccountDashboard.js",
1160 "id": "settings.account.manageSubscription.label",
1161 "start": {
1162 "column": 33,
1163 "line": 30
1164 }
1165 },
1166 {
1167 "defaultMessage": "!!!Basic Account",
1168 "end": {
1169 "column": 3,
1170 "line": 37
1171 },
1172 "file": "src/components/settings/account/AccountDashboard.js",
1173 "id": "settings.account.accountType.basic",
1174 "start": {
1175 "column": 20,
1176 "line": 34
1177 }
1178 },
1179 {
1180 "defaultMessage": "!!!Premium Supporter Account",
1181 "end": {
1182 "column": 3,
1183 "line": 41
1184 },
1185 "file": "src/components/settings/account/AccountDashboard.js",
1186 "id": "settings.account.accountType.premium",
1187 "start": {
1188 "column": 22,
1189 "line": 38
1190 }
1191 },
1192 {
1193 "defaultMessage": "!!!Edit Account",
1194 "end": {
1195 "column": 3,
1196 "line": 45
1197 },
1198 "file": "src/components/settings/account/AccountDashboard.js",
1199 "id": "settings.account.account.editButton",
1200 "start": {
1201 "column": 21,
1202 "line": 42
1203 }
1204 },
1205 {
1206 "defaultMessage": "!!Invoices",
1207 "end": {
1208 "column": 3,
1209 "line": 49
1210 },
1211 "file": "src/components/settings/account/AccountDashboard.js",
1212 "id": "settings.account.headlineInvoices",
1213 "start": {
1214 "column": 18,
1215 "line": 46
1216 }
1217 },
1218 {
1219 "defaultMessage": "!!!Download",
1220 "end": {
1221 "column": 3,
1222 "line": 53
1223 },
1224 "file": "src/components/settings/account/AccountDashboard.js",
1225 "id": "settings.account.invoiceDownload",
1226 "start": {
1227 "column": 19,
1228 "line": 50
1229 }
1230 },
1231 {
1232 "defaultMessage": "!!!Could not load user information",
1233 "end": {
1234 "column": 3,
1235 "line": 57
1236 },
1237 "file": "src/components/settings/account/AccountDashboard.js",
1238 "id": "settings.account.userInfoRequestFailed",
1239 "start": {
1240 "column": 25,
1241 "line": 54
1242 }
1243 },
1244 {
1245 "defaultMessage": "!!!Try again",
1246 "end": {
1247 "column": 3,
1248 "line": 61
1249 },
1250 "file": "src/components/settings/account/AccountDashboard.js",
1251 "id": "settings.account.tryReloadUserInfoRequest",
1252 "start": {
1253 "column": 28,
1254 "line": 58
1255 }
1256 },
1257 {
1258 "defaultMessage": "!!!Delete account",
1259 "end": {
1260 "column": 3,
1261 "line": 65
1262 },
1263 "file": "src/components/settings/account/AccountDashboard.js",
1264 "id": "settings.account.deleteAccount",
1265 "start": {
1266 "column": 17,
1267 "line": 62
1268 }
1269 },
1270 {
1271 "defaultMessage": "!!!If you don't need your Franz account any longer, you can delete your account and all related data here.",
1272 "end": {
1273 "column": 3,
1274 "line": 69
1275 },
1276 "file": "src/components/settings/account/AccountDashboard.js",
1277 "id": "settings.account.deleteInfo",
1278 "start": {
1279 "column": 14,
1280 "line": 66
1281 }
1282 },
1283 {
1284 "defaultMessage": "!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
1285 "end": {
1286 "column": 3,
1287 "line": 73
1288 },
1289 "file": "src/components/settings/account/AccountDashboard.js",
1290 "id": "settings.account.deleteEmailSent",
1291 "start": {
1292 "column": 19,
1293 "line": 70
1294 }
1295 }
1296 ],
1297 "path": "src/components/settings/account/AccountDashboard.json"
1298 },
1299 {
1300 "descriptors": [
1301 {
1302 "defaultMessage": "!!!Available services",
1303 "end": {
1304 "column": 3,
1305 "line": 16
1306 },
1307 "file": "src/components/settings/navigation/SettingsNavigation.js",
1308 "id": "settings.navigation.availableServices",
1309 "start": {
1310 "column": 21,
1311 "line": 13
1312 }
1313 },
1314 {
1315 "defaultMessage": "!!!Your services",
1316 "end": {
1317 "column": 3,
1318 "line": 20
1319 },
1320 "file": "src/components/settings/navigation/SettingsNavigation.js",
1321 "id": "settings.navigation.yourServices",
1322 "start": {
1323 "column": 16,
1324 "line": 17
1325 }
1326 },
1327 {
1328 "defaultMessage": "!!!Your workspaces",
1329 "end": {
1330 "column": 3,
1331 "line": 24
1332 },
1333 "file": "src/components/settings/navigation/SettingsNavigation.js",
1334 "id": "settings.navigation.yourWorkspaces",
1335 "start": {
1336 "column": 18,
1337 "line": 21
1338 }
1339 },
1340 {
1341 "defaultMessage": "!!!Account",
1342 "end": {
1343 "column": 3,
1344 "line": 28
1345 },
1346 "file": "src/components/settings/navigation/SettingsNavigation.js",
1347 "id": "settings.navigation.account",
1348 "start": {
1349 "column": 11,
1350 "line": 25
1351 }
1352 },
1353 {
1354 "defaultMessage": "!!!Manage Team",
1355 "end": {
1356 "column": 3,
1357 "line": 32
1358 },
1359 "file": "src/components/settings/navigation/SettingsNavigation.js",
1360 "id": "settings.navigation.team",
1361 "start": {
1362 "column": 8,
1363 "line": 29
1364 }
1365 },
1366 {
1367 "defaultMessage": "!!!Settings",
1368 "end": {
1369 "column": 3,
1370 "line": 36
1371 },
1372 "file": "src/components/settings/navigation/SettingsNavigation.js",
1373 "id": "settings.navigation.settings",
1374 "start": {
1375 "column": 12,
1376 "line": 33
1377 }
1378 },
1379 {
1380 "defaultMessage": "!!!Invite Friends",
1381 "end": {
1382 "column": 3,
1383 "line": 40
1384 },
1385 "file": "src/components/settings/navigation/SettingsNavigation.js",
1386 "id": "settings.navigation.inviteFriends",
1387 "start": {
1388 "column": 17,
1389 "line": 37
1390 }
1391 },
1392 {
1393 "defaultMessage": "!!!Logout",
1394 "end": {
1395 "column": 3,
1396 "line": 44
1397 },
1398 "file": "src/components/settings/navigation/SettingsNavigation.js",
1399 "id": "settings.navigation.logout",
1400 "start": {
1401 "column": 10,
1402 "line": 41
1403 }
1404 }
1405 ],
1406 "path": "src/components/settings/navigation/SettingsNavigation.json"
1407 },
1408 {
1409 "descriptors": [
1410 {
1411 "defaultMessage": "!!!Available Services",
1412 "end": {
1413 "column": 3,
1414 "line": 18
1415 },
1416 "file": "src/components/settings/recipes/RecipesDashboard.js",
1417 "id": "settings.recipes.headline",
1418 "start": {
1419 "column": 12,
1420 "line": 15
1421 }
1422 },
1423 {
1424 "defaultMessage": "!!!Search service",
1425 "end": {
1426 "column": 3,
1427 "line": 22
1428 },
1429 "file": "src/components/settings/recipes/RecipesDashboard.js",
1430 "id": "settings.searchService",
1431 "start": {
1432 "column": 17,
1433 "line": 19
1434 }
1435 },
1436 {
1437 "defaultMessage": "!!!Most popular",
1438 "end": {
1439 "column": 3,
1440 "line": 26
1441 },
1442 "file": "src/components/settings/recipes/RecipesDashboard.js",
1443 "id": "settings.recipes.mostPopular",
1444 "start": {
1445 "column": 22,
1446 "line": 23
1447 }
1448 },
1449 {
1450 "defaultMessage": "!!!All services",
1451 "end": {
1452 "column": 3,
1453 "line": 30
1454 },
1455 "file": "src/components/settings/recipes/RecipesDashboard.js",
1456 "id": "settings.recipes.all",
1457 "start": {
1458 "column": 14,
1459 "line": 27
1460 }
1461 },
1462 {
1463 "defaultMessage": "!!!Development",
1464 "end": {
1465 "column": 3,
1466 "line": 34
1467 },
1468 "file": "src/components/settings/recipes/RecipesDashboard.js",
1469 "id": "settings.recipes.dev",
1470 "start": {
1471 "column": 14,
1472 "line": 31
1473 }
1474 },
1475 {
1476 "defaultMessage": "!!!Sorry, but no service matched your search term.",
1477 "end": {
1478 "column": 3,
1479 "line": 38
1480 },
1481 "file": "src/components/settings/recipes/RecipesDashboard.js",
1482 "id": "settings.recipes.nothingFound",
1483 "start": {
1484 "column": 16,
1485 "line": 35
1486 }
1487 },
1488 {
1489 "defaultMessage": "!!!Service successfully added",
1490 "end": {
1491 "column": 3,
1492 "line": 42
1493 },
1494 "file": "src/components/settings/recipes/RecipesDashboard.js",
1495 "id": "settings.recipes.servicesSuccessfulAddedInfo",
1496 "start": {
1497 "column": 31,
1498 "line": 39
1499 }
1500 },
1501 {
1502 "defaultMessage": "!!!Missing a service?",
1503 "end": {
1504 "column": 3,
1505 "line": 46
1506 },
1507 "file": "src/components/settings/recipes/RecipesDashboard.js",
1508 "id": "settings.recipes.missingService",
1509 "start": {
1510 "column": 18,
1511 "line": 43
1512 }
1513 }
1514 ],
1515 "path": "src/components/settings/recipes/RecipesDashboard.json"
1516 },
1517 {
1518 "descriptors": [
1519 {
1520 "defaultMessage": "!!!Save service",
1521 "end": {
1522 "column": 3,
1523 "line": 25
1524 },
1525 "file": "src/components/settings/services/EditServiceForm.js",
1526 "id": "settings.service.form.saveButton",
1527 "start": {
1528 "column": 15,
1529 "line": 22
1530 }
1531 },
1532 {
1533 "defaultMessage": "!!!Delete Service",
1534 "end": {
1535 "column": 3,
1536 "line": 29
1537 },
1538 "file": "src/components/settings/services/EditServiceForm.js",
1539 "id": "settings.service.form.deleteButton",
1540 "start": {
1541 "column": 17,
1542 "line": 26
1543 }
1544 },
1545 {
1546 "defaultMessage": "!!!Available services",
1547 "end": {
1548 "column": 3,
1549 "line": 33
1550 },
1551 "file": "src/components/settings/services/EditServiceForm.js",
1552 "id": "settings.service.form.availableServices",
1553 "start": {
1554 "column": 21,
1555 "line": 30
1556 }
1557 },
1558 {
1559 "defaultMessage": "!!!Your services",
1560 "end": {
1561 "column": 3,
1562 "line": 37
1563 },
1564 "file": "src/components/settings/services/EditServiceForm.js",
1565 "id": "settings.service.form.yourServices",
1566 "start": {
1567 "column": 16,
1568 "line": 34
1569 }
1570 },
1571 {
1572 "defaultMessage": "!!!Add {name}",
1573 "end": {
1574 "column": 3,
1575 "line": 41
1576 },
1577 "file": "src/components/settings/services/EditServiceForm.js",
1578 "id": "settings.service.form.addServiceHeadline",
1579 "start": {
1580 "column": 22,
1581 "line": 38
1582 }
1583 },
1584 {
1585 "defaultMessage": "!!!Edit {name}",
1586 "end": {
1587 "column": 3,
1588 "line": 45
1589 },
1590 "file": "src/components/settings/services/EditServiceForm.js",
1591 "id": "settings.service.form.editServiceHeadline",
1592 "start": {
1593 "column": 23,
1594 "line": 42
1595 }
1596 },
1597 {
1598 "defaultMessage": "!!!Hosted",
1599 "end": {
1600 "column": 3,
1601 "line": 49
1602 },
1603 "file": "src/components/settings/services/EditServiceForm.js",
1604 "id": "settings.service.form.tabHosted",
1605 "start": {
1606 "column": 13,
1607 "line": 46
1608 }
1609 },
1610 {
1611 "defaultMessage": "!!!Self hosted â­ï¸",
1612 "end": {
1613 "column": 3,
1614 "line": 53
1615 },
1616 "file": "src/components/settings/services/EditServiceForm.js",
1617 "id": "settings.service.form.tabOnPremise",
1618 "start": {
1619 "column": 16,
1620 "line": 50
1621 }
1622 },
1623 {
1624 "defaultMessage": "!!!Use the hosted {name} service.",
1625 "end": {
1626 "column": 3,
1627 "line": 57
1628 },
1629 "file": "src/components/settings/services/EditServiceForm.js",
1630 "id": "settings.service.form.useHostedService",
1631 "start": {
1632 "column": 20,
1633 "line": 54
1634 }
1635 },
1636 {
1637 "defaultMessage": "!!!Could not validate custom {name} server.",
1638 "end": {
1639 "column": 3,
1640 "line": 61
1641 },
1642 "file": "src/components/settings/services/EditServiceForm.js",
1643 "id": "settings.service.form.customUrlValidationError",
1644 "start": {
1645 "column": 28,
1646 "line": 58
1647 }
1648 },
1649 {
1650 "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.",
1651 "end": {
1652 "column": 3,
1653 "line": 65
1654 },
1655 "file": "src/components/settings/services/EditServiceForm.js",
1656 "id": "settings.service.form.customUrlPremiumInfo",
1657 "start": {
1658 "column": 24,
1659 "line": 62
1660 }
1661 },
1662 {
1663 "defaultMessage": "!!!Upgrade your account",
1664 "end": {
1665 "column": 3,
1666 "line": 69
1667 },
1668 "file": "src/components/settings/services/EditServiceForm.js",
1669 "id": "settings.service.form.customUrlUpgradeAccount",
1670 "start": {
1671 "column": 27,
1672 "line": 66
1673 }
1674 },
1675 {
1676 "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...",
1677 "end": {
1678 "column": 3,
1679 "line": 73
1680 },
1681 "file": "src/components/settings/services/EditServiceForm.js",
1682 "id": "settings.service.form.indirectMessageInfo",
1683 "start": {
1684 "column": 23,
1685 "line": 70
1686 }
1687 },
1688 {
1689 "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted",
1690 "end": {
1691 "column": 3,
1692 "line": 77
1693 },
1694 "file": "src/components/settings/services/EditServiceForm.js",
1695 "id": "settings.service.form.isMutedInfo",
1696 "start": {
1697 "column": 15,
1698 "line": 74
1699 }
1700 },
1701 {
1702 "defaultMessage": "!!!Notifications",
1703 "end": {
1704 "column": 3,
1705 "line": 81
1706 },
1707 "file": "src/components/settings/services/EditServiceForm.js",
1708 "id": "settings.service.form.headlineNotifications",
1709 "start": {
1710 "column": 25,
1711 "line": 78
1712 }
1713 },
1714 {
1715 "defaultMessage": "!!!Unread message badges",
1716 "end": {
1717 "column": 3,
1718 "line": 85
1719 },
1720 "file": "src/components/settings/services/EditServiceForm.js",
1721 "id": "settings.service.form.headlineBadges",
1722 "start": {
1723 "column": 18,
1724 "line": 82
1725 }
1726 },
1727 {
1728 "defaultMessage": "!!!General",
1729 "end": {
1730 "column": 3,
1731 "line": 89
1732 },
1733 "file": "src/components/settings/services/EditServiceForm.js",
1734 "id": "settings.service.form.headlineGeneral",
1735 "start": {
1736 "column": 19,
1737 "line": 86
1738 }
1739 },
1740 {
1741 "defaultMessage": "!!!Delete",
1742 "end": {
1743 "column": 3,
1744 "line": 93
1745 },
1746 "file": "src/components/settings/services/EditServiceForm.js",
1747 "id": "settings.service.form.iconDelete",
1748 "start": {
1749 "column": 14,
1750 "line": 90
1751 }
1752 },
1753 {
1754 "defaultMessage": "!!!Drop your image, or click here",
1755 "end": {
1756 "column": 3,
1757 "line": 97
1758 },
1759 "file": "src/components/settings/services/EditServiceForm.js",
1760 "id": "settings.service.form.iconUpload",
1761 "start": {
1762 "column": 14,
1763 "line": 94
1764 }
1765 },
1766 {
1767 "defaultMessage": "!!!HTTP/HTTPS Proxy Settings",
1768 "end": {
1769 "column": 3,
1770 "line": 101
1771 },
1772 "file": "src/components/settings/services/EditServiceForm.js",
1773 "id": "settings.service.form.proxy.headline",
1774 "start": {
1775 "column": 17,
1776 "line": 98
1777 }
1778 },
1779 {
1780 "defaultMessage": "!!!Please restart Franz after changing proxy Settings.",
1781 "end": {
1782 "column": 3,
1783 "line": 105
1784 },
1785 "file": "src/components/settings/services/EditServiceForm.js",
1786 "id": "settings.service.form.proxy.restartInfo",
1787 "start": {
1788 "column": 20,
1789 "line": 102
1790 }
1791 },
1792 {
1793 "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.",
1794 "end": {
1795 "column": 3,
1796 "line": 109
1797 },
1798 "file": "src/components/settings/services/EditServiceForm.js",
1799 "id": "settings.service.form.proxy.info",
1800 "start": {
1801 "column": 13,
1802 "line": 106
1803 }
1804 }
1805 ],
1806 "path": "src/components/settings/services/EditServiceForm.json"
1807 },
1808 {
1809 "descriptors": [
1810 {
1811 "defaultMessage": "!!!Error",
1812 "end": {
1813 "column": 3,
1814 "line": 13
1815 },
1816 "file": "src/components/settings/services/ServiceError.js",
1817 "id": "settings.service.error.headline",
1818 "start": {
1819 "column": 12,
1820 "line": 10
1821 }
1822 },
1823 {
1824 "defaultMessage": "!!!Back to services",
1825 "end": {
1826 "column": 3,
1827 "line": 17
1828 },
1829 "file": "src/components/settings/services/ServiceError.js",
1830 "id": "settings.service.error.goBack",
1831 "start": {
1832 "column": 10,
1833 "line": 14
1834 }
1835 },
1836 {
1837 "defaultMessage": "!!!Available services",
1838 "end": {
1839 "column": 3,
1840 "line": 21
1841 },
1842 "file": "src/components/settings/services/ServiceError.js",
1843 "id": "settings.service.form.availableServices",
1844 "start": {
1845 "column": 21,
1846 "line": 18
1847 }
1848 },
1849 {
1850 "defaultMessage": "!!!Could not load service recipe.",
1851 "end": {
1852 "column": 3,
1853 "line": 25
1854 },
1855 "file": "src/components/settings/services/ServiceError.js",
1856 "id": "settings.service.error.message",
1857 "start": {
1858 "column": 16,
1859 "line": 22
1860 }
1861 }
1862 ],
1863 "path": "src/components/settings/services/ServiceError.json"
1864 },
1865 {
1866 "descriptors": [
1867 {
1868 "defaultMessage": "!!!Service is disabled",
1869 "end": {
1870 "column": 3,
1871 "line": 14
1872 },
1873 "file": "src/components/settings/services/ServiceItem.js",
1874 "id": "settings.services.tooltip.isDisabled",
1875 "start": {
1876 "column": 21,
1877 "line": 11
1878 }
1879 },
1880 {
1881 "defaultMessage": "!!!Notifications are disabled",
1882 "end": {
1883 "column": 3,
1884 "line": 18
1885 },
1886 "file": "src/components/settings/services/ServiceItem.js",
1887 "id": "settings.services.tooltip.notificationsDisabled",
1888 "start": {
1889 "column": 32,
1890 "line": 15
1891 }
1892 },
1893 {
1894 "defaultMessage": "!!!All sounds are muted",
1895 "end": {
1896 "column": 3,
1897 "line": 22
1898 },
1899 "file": "src/components/settings/services/ServiceItem.js",
1900 "id": "settings.services.tooltip.isMuted",
1901 "start": {
1902 "column": 18,
1903 "line": 19
1904 }
1905 }
1906 ],
1907 "path": "src/components/settings/services/ServiceItem.json"
1908 },
1909 {
1910 "descriptors": [
1911 {
1912 "defaultMessage": "!!!Your services",
1913 "end": {
1914 "column": 3,
1915 "line": 17
1916 },
1917 "file": "src/components/settings/services/ServicesDashboard.js",
1918 "id": "settings.services.headline",
1919 "start": {
1920 "column": 12,
1921 "line": 14
1922 }
1923 },
1924 {
1925 "defaultMessage": "!!!Search service",
1926 "end": {
1927 "column": 3,
1928 "line": 21
1929 },
1930 "file": "src/components/settings/services/ServicesDashboard.js",
1931 "id": "settings.searchService",
1932 "start": {
1933 "column": 17,
1934 "line": 18
1935 }
1936 },
1937 {
1938 "defaultMessage": "!!!You haven't added any services yet.",
1939 "end": {
1940 "column": 3,
1941 "line": 25
1942 },
1943 "file": "src/components/settings/services/ServicesDashboard.js",
1944 "id": "settings.services.noServicesAdded",
1945 "start": {
1946 "column": 19,
1947 "line": 22
1948 }
1949 },
1950 {
1951 "defaultMessage": "!!!Sorry, but no service matched your search term.",
1952 "end": {
1953 "column": 3,
1954 "line": 29
1955 },
1956 "file": "src/components/settings/services/ServicesDashboard.js",
1957 "id": "settings.recipes.nothingFound",
1958 "start": {
1959 "column": 18,
1960 "line": 26
1961 }
1962 },
1963 {
1964 "defaultMessage": "!!!Discover services",
1965 "end": {
1966 "column": 3,
1967 "line": 33
1968 },
1969 "file": "src/components/settings/services/ServicesDashboard.js",
1970 "id": "settings.services.discoverServices",
1971 "start": {
1972 "column": 20,
1973 "line": 30
1974 }
1975 },
1976 {
1977 "defaultMessage": "!!!Could not load your services",
1978 "end": {
1979 "column": 3,
1980 "line": 37
1981 },
1982 "file": "src/components/settings/services/ServicesDashboard.js",
1983 "id": "settings.services.servicesRequestFailed",
1984 "start": {
1985 "column": 25,
1986 "line": 34
1987 }
1988 },
1989 {
1990 "defaultMessage": "!!!Try again",
1991 "end": {
1992 "column": 3,
1993 "line": 41
1994 },
1995 "file": "src/components/settings/services/ServicesDashboard.js",
1996 "id": "settings.account.tryReloadServices",
1997 "start": {
1998 "column": 21,
1999 "line": 38
2000 }
2001 },
2002 {
2003 "defaultMessage": "!!!Your changes have been saved",
2004 "end": {
2005 "column": 3,
2006 "line": 45
2007 },
2008 "file": "src/components/settings/services/ServicesDashboard.js",
2009 "id": "settings.services.updatedInfo",
2010 "start": {
2011 "column": 15,
2012 "line": 42
2013 }
2014 },
2015 {
2016 "defaultMessage": "!!!Service has been deleted",
2017 "end": {
2018 "column": 3,
2019 "line": 49
2020 },
2021 "file": "src/components/settings/services/ServicesDashboard.js",
2022 "id": "settings.services.deletedInfo",
2023 "start": {
2024 "column": 15,
2025 "line": 46
2026 }
2027 }
2028 ],
2029 "path": "src/components/settings/services/ServicesDashboard.json"
2030 },
2031 {
2032 "descriptors": [
2033 {
2034 "defaultMessage": "!!!Settings",
2035 "end": {
2036 "column": 3,
2037 "line": 19
2038 },
2039 "file": "src/components/settings/settings/EditSettingsForm.js",
2040 "id": "settings.app.headline",
2041 "start": {
2042 "column": 12,
2043 "line": 16
2044 }
2045 },
2046 {
2047 "defaultMessage": "!!!General",
2048 "end": {
2049 "column": 3,
2050 "line": 23
2051 },
2052 "file": "src/components/settings/settings/EditSettingsForm.js",
2053 "id": "settings.app.headlineGeneral",
2054 "start": {
2055 "column": 19,
2056 "line": 20
2057 }
2058 },
2059 {
2060 "defaultMessage": "!!!Language",
2061 "end": {
2062 "column": 3,
2063 "line": 27
2064 },
2065 "file": "src/components/settings/settings/EditSettingsForm.js",
2066 "id": "settings.app.headlineLanguage",
2067 "start": {
2068 "column": 20,
2069 "line": 24
2070 }
2071 },
2072 {
2073 "defaultMessage": "!!!Updates",
2074 "end": {
2075 "column": 3,
2076 "line": 31
2077 },
2078 "file": "src/components/settings/settings/EditSettingsForm.js",
2079 "id": "settings.app.headlineUpdates",
2080 "start": {
2081 "column": 19,
2082 "line": 28
2083 }
2084 },
2085 {
2086 "defaultMessage": "!!!Appearance",
2087 "end": {
2088 "column": 3,
2089 "line": 35
2090 },
2091 "file": "src/components/settings/settings/EditSettingsForm.js",
2092 "id": "settings.app.headlineAppearance",
2093 "start": {
2094 "column": 22,
2095 "line": 32
2096 }
2097 },
2098 {
2099 "defaultMessage": "!!!Advanced",
2100 "end": {
2101 "column": 3,
2102 "line": 39
2103 },
2104 "file": "src/components/settings/settings/EditSettingsForm.js",
2105 "id": "settings.app.headlineAdvanced",
2106 "start": {
2107 "column": 20,
2108 "line": 36
2109 }
2110 },
2111 {
2112 "defaultMessage": "!!!Help us to translate Franz into your language.",
2113 "end": {
2114 "column": 3,
2115 "line": 43
2116 },
2117 "file": "src/components/settings/settings/EditSettingsForm.js",
2118 "id": "settings.app.translationHelp",
2119 "start": {
2120 "column": 19,
2121 "line": 40
2122 }
2123 },
2124 {
2125 "defaultMessage": "!!!Cache",
2126 "end": {
2127 "column": 3,
2128 "line": 47
2129 },
2130 "file": "src/components/settings/settings/EditSettingsForm.js",
2131 "id": "settings.app.subheadlineCache",
2132 "start": {
2133 "column": 20,
2134 "line": 44
2135 }
2136 },
2137 {
2138 "defaultMessage": "!!!Franz cache is currently using {size} of disk space.",
2139 "end": {
2140 "column": 3,
2141 "line": 51
2142 },
2143 "file": "src/components/settings/settings/EditSettingsForm.js",
2144 "id": "settings.app.cacheInfo",
2145 "start": {
2146 "column": 13,
2147 "line": 48
2148 }
2149 },
2150 {
2151 "defaultMessage": "!!!Clear cache",
2152 "end": {
2153 "column": 3,
2154 "line": 55
2155 },
2156 "file": "src/components/settings/settings/EditSettingsForm.js",
2157 "id": "settings.app.buttonClearAllCache",
2158 "start": {
2159 "column": 23,
2160 "line": 52
2161 }
2162 },
2163 {
2164 "defaultMessage": "!!!Check for updates",
2165 "end": {
2166 "column": 3,
2167 "line": 59
2168 },
2169 "file": "src/components/settings/settings/EditSettingsForm.js",
2170 "id": "settings.app.buttonSearchForUpdate",
2171 "start": {
2172 "column": 25,
2173 "line": 56
2174 }
2175 },
2176 {
2177 "defaultMessage": "!!!Restart & install update",
2178 "end": {
2179 "column": 3,
2180 "line": 63
2181 },
2182 "file": "src/components/settings/settings/EditSettingsForm.js",
2183 "id": "settings.app.buttonInstallUpdate",
2184 "start": {
2185 "column": 23,
2186 "line": 60
2187 }
2188 },
2189 {
2190 "defaultMessage": "!!!Is searching for update",
2191 "end": {
2192 "column": 3,
2193 "line": 67
2194 },
2195 "file": "src/components/settings/settings/EditSettingsForm.js",
2196 "id": "settings.app.updateStatusSearching",
2197 "start": {
2198 "column": 25,
2199 "line": 64
2200 }
2201 },
2202 {
2203 "defaultMessage": "!!!Update available, downloading...",
2204 "end": {
2205 "column": 3,
2206 "line": 71
2207 },
2208 "file": "src/components/settings/settings/EditSettingsForm.js",
2209 "id": "settings.app.updateStatusAvailable",
2210 "start": {
2211 "column": 25,
2212 "line": 68
2213 }
2214 },
2215 {
2216 "defaultMessage": "!!!You are using the latest version of Franz",
2217 "end": {
2218 "column": 3,
2219 "line": 75
2220 },
2221 "file": "src/components/settings/settings/EditSettingsForm.js",
2222 "id": "settings.app.updateStatusUpToDate",
2223 "start": {
2224 "column": 24,
2225 "line": 72
2226 }
2227 },
2228 {
2229 "defaultMessage": "!!!Current version:",
2230 "end": {
2231 "column": 3,
2232 "line": 79
2233 },
2234 "file": "src/components/settings/settings/EditSettingsForm.js",
2235 "id": "settings.app.currentVersion",
2236 "start": {
2237 "column": 18,
2238 "line": 76
2239 }
2240 },
2241 {
2242 "defaultMessage": "!!!Changes require restart",
2243 "end": {
2244 "column": 3,
2245 "line": 83
2246 },
2247 "file": "src/components/settings/settings/EditSettingsForm.js",
2248 "id": "settings.app.restartRequired",
2249 "start": {
2250 "column": 29,
2251 "line": 80
2252 }
2253 },
2254 {
2255 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
2256 "end": {
2257 "column": 3,
2258 "line": 87
2259 },
2260 "file": "src/components/settings/settings/EditSettingsForm.js",
2261 "id": "settings.app.languageDisclaimer",
2262 "start": {
2263 "column": 22,
2264 "line": 84
2265 }
2266 }
2267 ],
2268 "path": "src/components/settings/settings/EditSettingsForm.json"
2269 },
2270 {
2271 "descriptors": [
2272 {
2273 "defaultMessage": "!!!Team",
2274 "end": {
2275 "column": 3,
2276 "line": 17
2277 },
2278 "file": "src/components/settings/team/TeamDashboard.js",
2279 "id": "settings.team.headline",
2280 "start": {
2281 "column": 12,
2282 "line": 14
2283 }
2284 },
2285 {
2286 "defaultMessage": "!!!Franz for Teams",
2287 "end": {
2288 "column": 3,
2289 "line": 21
2290 },
2291 "file": "src/components/settings/team/TeamDashboard.js",
2292 "id": "settings.team.contentHeadline",
2293 "start": {
2294 "column": 19,
2295 "line": 18
2296 }
2297 },
2298 {
2299 "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
2300 "end": {
2301 "column": 3,
2302 "line": 25
2303 },
2304 "file": "src/components/settings/team/TeamDashboard.js",
2305 "id": "settings.team.intro",
2306 "start": {
2307 "column": 9,
2308 "line": 22
2309 }
2310 },
2311 {
2312 "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
2313 "end": {
2314 "column": 3,
2315 "line": 29
2316 },
2317 "file": "src/components/settings/team/TeamDashboard.js",
2318 "id": "settings.team.copy",
2319 "start": {
2320 "column": 8,
2321 "line": 26
2322 }
2323 },
2324 {
2325 "defaultMessage": "!!!Manage your Team on meetfranz.com",
2326 "end": {
2327 "column": 3,
2328 "line": 33
2329 },
2330 "file": "src/components/settings/team/TeamDashboard.js",
2331 "id": "settings.team.manageAction",
2332 "start": {
2333 "column": 16,
2334 "line": 30
2335 }
2336 },
2337 {
2338 "defaultMessage": "!!!Upgrade your Account",
2339 "end": {
2340 "column": 3,
2341 "line": 37
2342 },
2343 "file": "src/components/settings/team/TeamDashboard.js",
2344 "id": "settings.team.upgradeAction",
2345 "start": {
2346 "column": 17,
2347 "line": 34
2348 }
2349 }
2350 ],
2351 "path": "src/components/settings/team/TeamDashboard.json"
2352 },
2353 {
2354 "descriptors": [
2355 {
2356 "defaultMessage": "!!!Account",
2357 "end": {
2358 "column": 3,
2359 "line": 18
2360 },
2361 "file": "src/components/settings/user/EditUserForm.js",
2362 "id": "settings.account.headline",
2363 "start": {
2364 "column": 12,
2365 "line": 15
2366 }
2367 },
2368 {
2369 "defaultMessage": "!!!Update Profile",
2370 "end": {
2371 "column": 3,
2372 "line": 22
2373 },
2374 "file": "src/components/settings/user/EditUserForm.js",
2375 "id": "settings.account.headlineProfile",
2376 "start": {
2377 "column": 19,
2378 "line": 19
2379 }
2380 },
2381 {
2382 "defaultMessage": "!!!Account Information",
2383 "end": {
2384 "column": 3,
2385 "line": 26
2386 },
2387 "file": "src/components/settings/user/EditUserForm.js",
2388 "id": "settings.account.headlineAccount",
2389 "start": {
2390 "column": 19,
2391 "line": 23
2392 }
2393 },
2394 {
2395 "defaultMessage": "!!!Change Password",
2396 "end": {
2397 "column": 3,
2398 "line": 30
2399 },
2400 "file": "src/components/settings/user/EditUserForm.js",
2401 "id": "settings.account.headlinePassword",
2402 "start": {
2403 "column": 20,
2404 "line": 27
2405 }
2406 },
2407 {
2408 "defaultMessage": "!!!Your changes have been saved",
2409 "end": {
2410 "column": 3,
2411 "line": 34
2412 },
2413 "file": "src/components/settings/user/EditUserForm.js",
2414 "id": "settings.account.successInfo",
2415 "start": {
2416 "column": 15,
2417 "line": 31
2418 }
2419 },
2420 {
2421 "defaultMessage": "!!!Update profile",
2422 "end": {
2423 "column": 3,
2424 "line": 38
2425 },
2426 "file": "src/components/settings/user/EditUserForm.js",
2427 "id": "settings.account.buttonSave",
2428 "start": {
2429 "column": 14,
2430 "line": 35
2431 }
2432 }
2433 ],
2434 "path": "src/components/settings/user/EditUserForm.json"
2435 },
2436 {
2437 "descriptors": [
2438 {
2439 "defaultMessage": "!!!Support the development of Franz",
2440 "end": {
2441 "column": 3,
2442 "line": 17
2443 },
2444 "file": "src/components/subscription/SubscriptionForm.js",
2445 "id": "subscription.submit.label",
2446 "start": {
2447 "column": 21,
2448 "line": 14
2449 }
2450 },
2451 {
2452 "defaultMessage": "!!!Could not initialize payment form",
2453 "end": {
2454 "column": 3,
2455 "line": 21
2456 },
2457 "file": "src/components/subscription/SubscriptionForm.js",
2458 "id": "subscription.paymentSessionError",
2459 "start": {
2460 "column": 23,
2461 "line": 18
2462 }
2463 },
2464 {
2465 "defaultMessage": "!!!free",
2466 "end": {
2467 "column": 3,
2468 "line": 25
2469 },
2470 "file": "src/components/subscription/SubscriptionForm.js",
2471 "id": "subscription.type.free",
2472 "start": {
2473 "column": 12,
2474 "line": 22
2475 }
2476 },
2477 {
2478 "defaultMessage": "!!!month",
2479 "end": {
2480 "column": 3,
2481 "line": 29
2482 },
2483 "file": "src/components/subscription/SubscriptionForm.js",
2484 "id": "subscription.type.month",
2485 "start": {
2486 "column": 15,
2487 "line": 26
2488 }
2489 },
2490 {
2491 "defaultMessage": "!!!year",
2492 "end": {
2493 "column": 3,
2494 "line": 33
2495 },
2496 "file": "src/components/subscription/SubscriptionForm.js",
2497 "id": "subscription.type.year",
2498 "start": {
2499 "column": 14,
2500 "line": 30
2501 }
2502 },
2503 {
2504 "defaultMessage": "!!!The Franz Premium Supporter Account includes",
2505 "end": {
2506 "column": 3,
2507 "line": 37
2508 },
2509 "file": "src/components/subscription/SubscriptionForm.js",
2510 "id": "subscription.includedFeatures",
2511 "start": {
2512 "column": 20,
2513 "line": 34
2514 }
2515 },
2516 {
2517 "defaultMessage": "!!!Add on-premise/hosted services like Mattermost",
2518 "end": {
2519 "column": 3,
2520 "line": 41
2521 },
2522 "file": "src/components/subscription/SubscriptionForm.js",
2523 "id": "subscription.features.onpremise.mattermost",
2524 "start": {
2525 "column": 13,
2526 "line": 38
2527 }
2528 },
2529 {
2530 "defaultMessage": "!!!No app delays & nagging to upgrade license",
2531 "end": {
2532 "column": 3,
2533 "line": 45
2534 },
2535 "file": "src/components/subscription/SubscriptionForm.js",
2536 "id": "subscription.features.noInterruptions",
2537 "start": {
2538 "column": 19,
2539 "line": 42
2540 }
2541 },
2542 {
2543 "defaultMessage": "!!!Proxy support for services",
2544 "end": {
2545 "column": 3,
2546 "line": 49
2547 },
2548 "file": "src/components/subscription/SubscriptionForm.js",
2549 "id": "subscription.features.proxy",
2550 "start": {
2551 "column": 9,
2552 "line": 46
2553 }
2554 },
2555 {
2556 "defaultMessage": "!!!Support for Spellchecker",
2557 "end": {
2558 "column": 3,
2559 "line": 53
2560 },
2561 "file": "src/components/subscription/SubscriptionForm.js",
2562 "id": "subscription.features.spellchecker",
2563 "start": {
2564 "column": 16,
2565 "line": 50
2566 }
2567 },
2568 {
2569 "defaultMessage": "!!!Organize your services in workspaces",
2570 "end": {
2571 "column": 3,
2572 "line": 57
2573 },
2574 "file": "src/components/subscription/SubscriptionForm.js",
2575 "id": "subscription.features.workspaces",
2576 "start": {
2577 "column": 14,
2578 "line": 54
2579 }
2580 },
2581 {
2582 "defaultMessage": "!!!No ads, ever!",
2583 "end": {
2584 "column": 3,
2585 "line": 61
2586 },
2587 "file": "src/components/subscription/SubscriptionForm.js",
2588 "id": "subscription.features.ads",
2589 "start": {
2590 "column": 7,
2591 "line": 58
2592 }
2593 },
2594 {
2595 "defaultMessage": "!!!coming soon",
2596 "end": {
2597 "column": 3,
2598 "line": 65
2599 },
2600 "file": "src/components/subscription/SubscriptionForm.js",
2601 "id": "subscription.features.comingSoon",
2602 "start": {
2603 "column": 14,
2604 "line": 62
2605 }
2606 },
2607 {
2608 "defaultMessage": "!!!EU residents: local sales tax may apply",
2609 "end": {
2610 "column": 3,
2611 "line": 69
2612 },
2613 "file": "src/components/subscription/SubscriptionForm.js",
2614 "id": "subscription.euTaxInfo",
2615 "start": {
2616 "column": 13,
2617 "line": 66
2618 }
2619 }
2620 ],
2621 "path": "src/components/subscription/SubscriptionForm.json"
2622 },
2623 {
2624 "descriptors": [
2625 {
2626 "defaultMessage": "!!!Cancel",
2627 "end": {
2628 "column": 3,
2629 "line": 14
2630 },
2631 "file": "src/components/subscription/SubscriptionPopup.js",
2632 "id": "subscriptionPopup.buttonCancel",
2633 "start": {
2634 "column": 16,
2635 "line": 11
2636 }
2637 },
2638 {
2639 "defaultMessage": "!!!Done",
2640 "end": {
2641 "column": 3,
2642 "line": 18
2643 },
2644 "file": "src/components/subscription/SubscriptionPopup.js",
2645 "id": "subscriptionPopup.buttonDone",
2646 "start": {
2647 "column": 14,
2648 "line": 15
2649 }
2650 }
2651 ],
2652 "path": "src/components/subscription/SubscriptionPopup.json"
2653 },
2654 {
2655 "descriptors": [
2656 {
2657 "defaultMessage": "!!!Upgrade account",
2658 "end": {
2659 "column": 3,
2660 "line": 18
2661 },
2662 "file": "src/components/ui/PremiumFeatureContainer/index.js",
2663 "id": "premiumFeature.button.upgradeAccount",
2664 "start": {
2665 "column": 10,
2666 "line": 15
2667 }
2668 }
2669 ],
2670 "path": "src/components/ui/PremiumFeatureContainer/index.json"
2671 },
2672 {
2673 "descriptors": [
2674 {
2675 "defaultMessage": "!!!Loading",
2676 "end": {
2677 "column": 3,
2678 "line": 14
2679 },
2680 "file": "src/components/ui/WebviewLoader/index.js",
2681 "id": "service.webviewLoader.loading",
2682 "start": {
2683 "column": 11,
2684 "line": 11
2685 }
2686 }
2687 ],
2688 "path": "src/components/ui/WebviewLoader/index.json"
2689 },
2690 {
2691 "descriptors": [
2692 {
2693 "defaultMessage": "!!!Something went wrong.",
2694 "end": {
2695 "column": 3,
2696 "line": 14
2697 },
2698 "file": "src/components/util/ErrorBoundary/index.js",
2699 "id": "app.errorHandler.headline",
2700 "start": {
2701 "column": 12,
2702 "line": 11
2703 }
2704 },
2705 {
2706 "defaultMessage": "!!!Reload",
2707 "end": {
2708 "column": 3,
2709 "line": 18
2710 },
2711 "file": "src/components/util/ErrorBoundary/index.js",
2712 "id": "app.errorHandler.action",
2713 "start": {
2714 "column": 10,
2715 "line": 15
2716 }
2717 }
2718 ],
2719 "path": "src/components/util/ErrorBoundary/index.json"
2720 },
2721 {
2722 "descriptors": [
2723 {
2724 "defaultMessage": "!!!Name",
2725 "end": {
2726 "column": 3,
2727 "line": 31
2728 },
2729 "file": "src/containers/settings/EditServiceScreen.js",
2730 "id": "settings.service.form.name",
2731 "start": {
2732 "column": 8,
2733 "line": 28
2734 }
2735 },
2736 {
2737 "defaultMessage": "!!!Enable service",
2738 "end": {
2739 "column": 3,
2740 "line": 35
2741 },
2742 "file": "src/containers/settings/EditServiceScreen.js",
2743 "id": "settings.service.form.enableService",
2744 "start": {
2745 "column": 17,
2746 "line": 32
2747 }
2748 },
2749 {
2750 "defaultMessage": "!!!Enable Notifications",
2751 "end": {
2752 "column": 3,
2753 "line": 39
2754 },
2755 "file": "src/containers/settings/EditServiceScreen.js",
2756 "id": "settings.service.form.enableNotification",
2757 "start": {
2758 "column": 22,
2759 "line": 36
2760 }
2761 },
2762 {
2763 "defaultMessage": "!!!Show unread message badges",
2764 "end": {
2765 "column": 3,
2766 "line": 43
2767 },
2768 "file": "src/containers/settings/EditServiceScreen.js",
2769 "id": "settings.service.form.enableBadge",
2770 "start": {
2771 "column": 15,
2772 "line": 40
2773 }
2774 },
2775 {
2776 "defaultMessage": "!!!Enable audio",
2777 "end": {
2778 "column": 3,
2779 "line": 47
2780 },
2781 "file": "src/containers/settings/EditServiceScreen.js",
2782 "id": "settings.service.form.enableAudio",
2783 "start": {
2784 "column": 15,
2785 "line": 44
2786 }
2787 },
2788 {
2789 "defaultMessage": "!!!Team",
2790 "end": {
2791 "column": 3,
2792 "line": 51
2793 },
2794 "file": "src/containers/settings/EditServiceScreen.js",
2795 "id": "settings.service.form.team",
2796 "start": {
2797 "column": 8,
2798 "line": 48
2799 }
2800 },
2801 {
2802 "defaultMessage": "!!!Custom server",
2803 "end": {
2804 "column": 3,
2805 "line": 55
2806 },
2807 "file": "src/containers/settings/EditServiceScreen.js",
2808 "id": "settings.service.form.customUrl",
2809 "start": {
2810 "column": 13,
2811 "line": 52
2812 }
2813 },
2814 {
2815 "defaultMessage": "!!!Show message badge for all new messages",
2816 "end": {
2817 "column": 3,
2818 "line": 59
2819 },
2820 "file": "src/containers/settings/EditServiceScreen.js",
2821 "id": "settings.service.form.indirectMessages",
2822 "start": {
2823 "column": 20,
2824 "line": 56
2825 }
2826 },
2827 {
2828 "defaultMessage": "!!!Custom icon",
2829 "end": {
2830 "column": 3,
2831 "line": 63
2832 },
2833 "file": "src/containers/settings/EditServiceScreen.js",
2834 "id": "settings.service.form.icon",
2835 "start": {
2836 "column": 8,
2837 "line": 60
2838 }
2839 },
2840 {
2841 "defaultMessage": "!!!Enable Dark Mode",
2842 "end": {
2843 "column": 3,
2844 "line": 67
2845 },
2846 "file": "src/containers/settings/EditServiceScreen.js",
2847 "id": "settings.service.form.enableDarkMode",
2848 "start": {
2849 "column": 18,
2850 "line": 64
2851 }
2852 },
2853 {
2854 "defaultMessage": "!!!Use Proxy",
2855 "end": {
2856 "column": 3,
2857 "line": 71
2858 },
2859 "file": "src/containers/settings/EditServiceScreen.js",
2860 "id": "settings.service.form.proxy.isEnabled",
2861 "start": {
2862 "column": 15,
2863 "line": 68
2864 }
2865 },
2866 {
2867 "defaultMessage": "!!!Proxy Host/IP",
2868 "end": {
2869 "column": 3,
2870 "line": 75
2871 },
2872 "file": "src/containers/settings/EditServiceScreen.js",
2873 "id": "settings.service.form.proxy.host",
2874 "start": {
2875 "column": 13,
2876 "line": 72
2877 }
2878 },
2879 {
2880 "defaultMessage": "!!!Port",
2881 "end": {
2882 "column": 3,
2883 "line": 79
2884 },
2885 "file": "src/containers/settings/EditServiceScreen.js",
2886 "id": "settings.service.form.proxy.port",
2887 "start": {
2888 "column": 13,
2889 "line": 76
2890 }
2891 },
2892 {
2893 "defaultMessage": "!!!User",
2894 "end": {
2895 "column": 3,
2896 "line": 83
2897 },
2898 "file": "src/containers/settings/EditServiceScreen.js",
2899 "id": "settings.service.form.proxy.user",
2900 "start": {
2901 "column": 13,
2902 "line": 80
2903 }
2904 },
2905 {
2906 "defaultMessage": "!!!Password",
2907 "end": {
2908 "column": 3,
2909 "line": 87
2910 },
2911 "file": "src/containers/settings/EditServiceScreen.js",
2912 "id": "settings.service.form.proxy.password",
2913 "start": {
2914 "column": 17,
2915 "line": 84
2916 }
2917 }
2918 ],
2919 "path": "src/containers/settings/EditServiceScreen.json"
2920 },
2921 {
2922 "descriptors": [
2923 {
2924 "defaultMessage": "!!!Launch Franz on start",
2925 "end": {
2926 "column": 3,
2927 "line": 25
2928 },
2929 "file": "src/containers/settings/EditSettingsScreen.js",
2930 "id": "settings.app.form.autoLaunchOnStart",
2931 "start": {
2932 "column": 21,
2933 "line": 22
2934 }
2935 },
2936 {
2937 "defaultMessage": "!!!Open in background",
2938 "end": {
2939 "column": 3,
2940 "line": 29
2941 },
2942 "file": "src/containers/settings/EditSettingsScreen.js",
2943 "id": "settings.app.form.autoLaunchInBackground",
2944 "start": {
2945 "column": 26,
2946 "line": 26
2947 }
2948 },
2949 {
2950 "defaultMessage": "!!!Keep Franz in background when closing the window",
2951 "end": {
2952 "column": 3,
2953 "line": 33
2954 },
2955 "file": "src/containers/settings/EditSettingsScreen.js",
2956 "id": "settings.app.form.runInBackground",
2957 "start": {
2958 "column": 19,
2959 "line": 30
2960 }
2961 },
2962 {
2963 "defaultMessage": "!!!Show Franz in system tray",
2964 "end": {
2965 "column": 3,
2966 "line": 37
2967 },
2968 "file": "src/containers/settings/EditSettingsScreen.js",
2969 "id": "settings.app.form.enableSystemTray",
2970 "start": {
2971 "column": 20,
2972 "line": 34
2973 }
2974 },
2975 {
2976 "defaultMessage": "!!!Minimize Franz to system tray",
2977 "end": {
2978 "column": 3,
2979 "line": 41
2980 },
2981 "file": "src/containers/settings/EditSettingsScreen.js",
2982 "id": "settings.app.form.minimizeToSystemTray",
2983 "start": {
2984 "column": 24,
2985 "line": 38
2986 }
2987 },
2988 {
2989 "defaultMessage": "!!!Language",
2990 "end": {
2991 "column": 3,
2992 "line": 45
2993 },
2994 "file": "src/containers/settings/EditSettingsScreen.js",
2995 "id": "settings.app.form.language",
2996 "start": {
2997 "column": 12,
2998 "line": 42
2999 }
3000 },
3001 {
3002 "defaultMessage": "!!!Dark Mode",
3003 "end": {
3004 "column": 3,
3005 "line": 49
3006 },
3007 "file": "src/containers/settings/EditSettingsScreen.js",
3008 "id": "settings.app.form.darkMode",
3009 "start": {
3010 "column": 12,
3011 "line": 46
3012 }
3013 },
3014 {
3015 "defaultMessage": "!!!Display disabled services tabs",
3016 "end": {
3017 "column": 3,
3018 "line": 53
3019 },
3020 "file": "src/containers/settings/EditSettingsScreen.js",
3021 "id": "settings.app.form.showDisabledServices",
3022 "start": {
3023 "column": 24,
3024 "line": 50
3025 }
3026 },
3027 {
3028 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
3029 "end": {
3030 "column": 3,
3031 "line": 57
3032 },
3033 "file": "src/containers/settings/EditSettingsScreen.js",
3034 "id": "settings.app.form.showMessagesBadgesWhenMuted",
3035 "start": {
3036 "column": 29,
3037 "line": 54
3038 }
3039 },
3040 {
3041 "defaultMessage": "!!!Enable spell checking",
3042 "end": {
3043 "column": 3,
3044 "line": 61
3045 },
3046 "file": "src/containers/settings/EditSettingsScreen.js",
3047 "id": "settings.app.form.enableSpellchecking",
3048 "start": {
3049 "column": 23,
3050 "line": 58
3051 }
3052 },
3053 {
3054 "defaultMessage": "!!!Enable GPU Acceleration",
3055 "end": {
3056 "column": 3,
3057 "line": 65
3058 },
3059 "file": "src/containers/settings/EditSettingsScreen.js",
3060 "id": "settings.app.form.enableGPUAcceleration",
3061 "start": {
3062 "column": 25,
3063 "line": 62
3064 }
3065 },
3066 {
3067 "defaultMessage": "!!!Include beta versions",
3068 "end": {
3069 "column": 3,
3070 "line": 69
3071 },
3072 "file": "src/containers/settings/EditSettingsScreen.js",
3073 "id": "settings.app.form.beta",
3074 "start": {
3075 "column": 8,
3076 "line": 66
3077 }
3078 }
3079 ],
3080 "path": "src/containers/settings/EditSettingsScreen.json"
3081 },
3082 {
3083 "descriptors": [
3084 {
3085 "defaultMessage": "!!!Firstname",
3086 "end": {
3087 "column": 3,
3088 "line": 17
3089 },
3090 "file": "src/containers/settings/EditUserScreen.js",
3091 "id": "settings.user.form.firstname",
3092 "start": {
3093 "column": 13,
3094 "line": 14
3095 }
3096 },
3097 {
3098 "defaultMessage": "!!!Lastname",
3099 "end": {
3100 "column": 3,
3101 "line": 21
3102 },
3103 "file": "src/containers/settings/EditUserScreen.js",
3104 "id": "settings.user.form.lastname",
3105 "start": {
3106 "column": 12,
3107 "line": 18
3108 }
3109 },
3110 {
3111 "defaultMessage": "!!!Email",
3112 "end": {
3113 "column": 3,
3114 "line": 25
3115 },
3116 "file": "src/containers/settings/EditUserScreen.js",
3117 "id": "settings.user.form.email",
3118 "start": {
3119 "column": 9,
3120 "line": 22
3121 }
3122 },
3123 {
3124 "defaultMessage": "!!!Account type",
3125 "end": {
3126 "column": 3,
3127 "line": 29
3128 },
3129 "file": "src/containers/settings/EditUserScreen.js",
3130 "id": "settings.user.form.accountType.label",
3131 "start": {
3132 "column": 20,
3133 "line": 26
3134 }
3135 },
3136 {
3137 "defaultMessage": "!!!Individual",
3138 "end": {
3139 "column": 3,
3140 "line": 33
3141 },
3142 "file": "src/containers/settings/EditUserScreen.js",
3143 "id": "settings.user.form.accountType.individual",
3144 "start": {
3145 "column": 25,
3146 "line": 30
3147 }
3148 },
3149 {
3150 "defaultMessage": "!!!Non-Profit",
3151 "end": {
3152 "column": 3,
3153 "line": 37
3154 },
3155 "file": "src/containers/settings/EditUserScreen.js",
3156 "id": "settings.user.form.accountType.non-profit",
3157 "start": {
3158 "column": 24,
3159 "line": 34
3160 }
3161 },
3162 {
3163 "defaultMessage": "!!!Company",
3164 "end": {
3165 "column": 3,
3166 "line": 41
3167 },
3168 "file": "src/containers/settings/EditUserScreen.js",
3169 "id": "settings.user.form.accountType.company",
3170 "start": {
3171 "column": 22,
3172 "line": 38
3173 }
3174 },
3175 {
3176 "defaultMessage": "!!!Current password",
3177 "end": {
3178 "column": 3,
3179 "line": 45
3180 },
3181 "file": "src/containers/settings/EditUserScreen.js",
3182 "id": "settings.user.form.currentPassword",
3183 "start": {
3184 "column": 19,
3185 "line": 42
3186 }
3187 },
3188 {
3189 "defaultMessage": "!!!New password",
3190 "end": {
3191 "column": 3,
3192 "line": 49
3193 },
3194 "file": "src/containers/settings/EditUserScreen.js",
3195 "id": "settings.user.form.newPassword",
3196 "start": {
3197 "column": 15,
3198 "line": 46
3199 }
3200 }
3201 ],
3202 "path": "src/containers/settings/EditUserScreen.json"
3203 },
3204 {
3205 "descriptors": [
3206 {
3207 "defaultMessage": "!!!Changes in Franz {version}",
3208 "end": {
3209 "column": 3,
3210 "line": 23
3211 },
3212 "file": "src/features/announcements/components/AnnouncementScreen.js",
3213 "id": "feature.announcements.changelog.headline",
3214 "start": {
3215 "column": 12,
3216 "line": 20
3217 }
3218 }
3219 ],
3220 "path": "src/features/announcements/components/AnnouncementScreen.json"
3221 },
3222 {
3223 "descriptors": [
3224 {
3225 "defaultMessage": "!!!Please purchase license to skip waiting",
3226 "end": {
3227 "column": 3,
3228 "line": 18
3229 },
3230 "file": "src/features/delayApp/Component.js",
3231 "id": "feature.delayApp.headline",
3232 "start": {
3233 "column": 12,
3234 "line": 15
3235 }
3236 },
3237 {
3238 "defaultMessage": "!!!Get a Franz Supporter License",
3239 "end": {
3240 "column": 3,
3241 "line": 22
3242 },
3243 "file": "src/features/delayApp/Component.js",
3244 "id": "feature.delayApp.action",
3245 "start": {
3246 "column": 10,
3247 "line": 19
3248 }
3249 },
3250 {
3251 "defaultMessage": "!!!Franz will continue in {seconds} seconds.",
3252 "end": {
3253 "column": 3,
3254 "line": 26
3255 },
3256 "file": "src/features/delayApp/Component.js",
3257 "id": "feature.delayApp.text",
3258 "start": {
3259 "column": 8,
3260 "line": 23
3261 }
3262 }
3263 ],
3264 "path": "src/features/delayApp/Component.json"
3265 },
3266 {
3267 "descriptors": [
3268 {
3269 "defaultMessage": "!!!Franz is better together!",
3270 "end": {
3271 "column": 3,
3272 "line": 18
3273 },
3274 "file": "src/features/shareFranz/Component.js",
3275 "id": "feature.shareFranz.headline",
3276 "start": {
3277 "column": 12,
3278 "line": 15
3279 }
3280 },
3281 {
3282 "defaultMessage": "!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
3283 "end": {
3284 "column": 3,
3285 "line": 22
3286 },
3287 "file": "src/features/shareFranz/Component.js",
3288 "id": "feature.shareFranz.text",
3289 "start": {
3290 "column": 8,
3291 "line": 19
3292 }
3293 },
3294 {
3295 "defaultMessage": "!!!Share as email",
3296 "end": {
3297 "column": 3,
3298 "line": 26
3299 },
3300 "file": "src/features/shareFranz/Component.js",
3301 "id": "feature.shareFranz.action.email",
3302 "start": {
3303 "column": 16,
3304 "line": 23
3305 }
3306 },
3307 {
3308 "defaultMessage": "!!!Share on Facebook",
3309 "end": {
3310 "column": 3,
3311 "line": 30
3312 },
3313 "file": "src/features/shareFranz/Component.js",
3314 "id": "feature.shareFranz.action.facebook",
3315 "start": {
3316 "column": 19,
3317 "line": 27
3318 }
3319 },
3320 {
3321 "defaultMessage": "!!!Share on Twitter",
3322 "end": {
3323 "column": 3,
3324 "line": 34
3325 },
3326 "file": "src/features/shareFranz/Component.js",
3327 "id": "feature.shareFranz.action.twitter",
3328 "start": {
3329 "column": 18,
3330 "line": 31
3331 }
3332 },
3333 {
3334 "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
3335 "end": {
3336 "column": 3,
3337 "line": 38
3338 },
3339 "file": "src/features/shareFranz/Component.js",
3340 "id": "feature.shareFranz.shareText.email",
3341 "start": {
3342 "column": 18,
3343 "line": 35
3344 }
3345 },
3346 {
3347 "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger",
3348 "end": {
3349 "column": 3,
3350 "line": 42
3351 },
3352 "file": "src/features/shareFranz/Component.js",
3353 "id": "feature.shareFranz.shareText.twitter",
3354 "start": {
3355 "column": 20,
3356 "line": 39
3357 }
3358 }
3359 ],
3360 "path": "src/features/shareFranz/Component.json"
3361 },
3362 {
3363 "descriptors": [
3364 {
3365 "defaultMessage": "!!!Create workspace",
3366 "end": {
3367 "column": 3,
3368 "line": 16
3369 },
3370 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
3371 "id": "settings.workspace.add.form.submitButton",
3372 "start": {
3373 "column": 16,
3374 "line": 13
3375 }
3376 },
3377 {
3378 "defaultMessage": "!!!Name",
3379 "end": {
3380 "column": 3,
3381 "line": 20
3382 },
3383 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
3384 "id": "settings.workspace.add.form.name",
3385 "start": {
3386 "column": 8,
3387 "line": 17
3388 }
3389 }
3390 ],
3391 "path": "src/features/workspaces/components/CreateWorkspaceForm.json"
3392 },
3393 {
3394 "descriptors": [
3395 {
3396 "defaultMessage": "!!!Delete workspace",
3397 "end": {
3398 "column": 3,
3399 "line": 22
3400 },
3401 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3402 "id": "settings.workspace.form.buttonDelete",
3403 "start": {
3404 "column": 16,
3405 "line": 19
3406 }
3407 },
3408 {
3409 "defaultMessage": "!!!Save workspace",
3410 "end": {
3411 "column": 3,
3412 "line": 26
3413 },
3414 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3415 "id": "settings.workspace.form.buttonSave",
3416 "start": {
3417 "column": 14,
3418 "line": 23
3419 }
3420 },
3421 {
3422 "defaultMessage": "!!!Name",
3423 "end": {
3424 "column": 3,
3425 "line": 30
3426 },
3427 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3428 "id": "settings.workspace.form.name",
3429 "start": {
3430 "column": 8,
3431 "line": 27
3432 }
3433 },
3434 {
3435 "defaultMessage": "!!!Your workspaces",
3436 "end": {
3437 "column": 3,
3438 "line": 34
3439 },
3440 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3441 "id": "settings.workspace.form.yourWorkspaces",
3442 "start": {
3443 "column": 18,
3444 "line": 31
3445 }
3446 },
3447 {
3448 "defaultMessage": "!!!Services in this Workspace",
3449 "end": {
3450 "column": 3,
3451 "line": 38
3452 },
3453 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3454 "id": "settings.workspace.form.servicesInWorkspaceHeadline",
3455 "start": {
3456 "column": 31,
3457 "line": 35
3458 }
3459 },
3460 {
3461 "defaultMessage": "!!!You haven't added any services yet.",
3462 "end": {
3463 "column": 3,
3464 "line": 42
3465 },
3466 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3467 "id": "settings.services.noServicesAdded",
3468 "start": {
3469 "column": 19,
3470 "line": 39
3471 }
3472 },
3473 {
3474 "defaultMessage": "!!!Discover services",
3475 "end": {
3476 "column": 3,
3477 "line": 46
3478 },
3479 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
3480 "id": "settings.services.discoverServices",
3481 "start": {
3482 "column": 20,
3483 "line": 43
3484 }
3485 }
3486 ],
3487 "path": "src/features/workspaces/components/EditWorkspaceForm.json"
3488 },
3489 {
3490 "descriptors": [
3491 {
3492 "defaultMessage": "!!!Workspaces",
3493 "end": {
3494 "column": 3,
3495 "line": 19
3496 },
3497 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3498 "id": "workspaceDrawer.headline",
3499 "start": {
3500 "column": 12,
3501 "line": 16
3502 }
3503 },
3504 {
3505 "defaultMessage": "!!!All services",
3506 "end": {
3507 "column": 3,
3508 "line": 23
3509 },
3510 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3511 "id": "workspaceDrawer.allServices",
3512 "start": {
3513 "column": 15,
3514 "line": 20
3515 }
3516 },
3517 {
3518 "defaultMessage": "!!!Workspaces settings",
3519 "end": {
3520 "column": 3,
3521 "line": 27
3522 },
3523 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3524 "id": "workspaceDrawer.workspacesSettingsTooltip",
3525 "start": {
3526 "column": 29,
3527 "line": 24
3528 }
3529 },
3530 {
3531 "defaultMessage": "!!!Info about workspace feature",
3532 "end": {
3533 "column": 3,
3534 "line": 31
3535 },
3536 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3537 "id": "workspaceDrawer.workspaceFeatureInfo",
3538 "start": {
3539 "column": 24,
3540 "line": 28
3541 }
3542 },
3543 {
3544 "defaultMessage": "!!!Create your first workspace",
3545 "end": {
3546 "column": 3,
3547 "line": 35
3548 },
3549 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3550 "id": "workspaceDrawer.premiumCtaButtonLabel",
3551 "start": {
3552 "column": 25,
3553 "line": 32
3554 }
3555 },
3556 {
3557 "defaultMessage": "!!!Reactivate premium account",
3558 "end": {
3559 "column": 3,
3560 "line": 39
3561 },
3562 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3563 "id": "workspaceDrawer.reactivatePremiumAccountLabel",
3564 "start": {
3565 "column": 28,
3566 "line": 36
3567 }
3568 },
3569 {
3570 "defaultMessage": "!!!add new workspace",
3571 "end": {
3572 "column": 3,
3573 "line": 43
3574 },
3575 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3576 "id": "workspaceDrawer.addNewWorkspaceLabel",
3577 "start": {
3578 "column": 24,
3579 "line": 40
3580 }
3581 },
3582 {
3583 "defaultMessage": "!!!Premium feature",
3584 "end": {
3585 "column": 3,
3586 "line": 47
3587 },
3588 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
3589 "id": "workspaceDrawer.proFeatureBadge",
3590 "start": {
3591 "column": 23,
3592 "line": 44
3593 }
3594 }
3595 ],
3596 "path": "src/features/workspaces/components/WorkspaceDrawer.json"
3597 },
3598 {
3599 "descriptors": [
3600 {
3601 "defaultMessage": "!!!No services added yet",
3602 "end": {
3603 "column": 3,
3604 "line": 15
3605 },
3606 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
3607 "id": "workspaceDrawer.item.noServicesAddedYet",
3608 "start": {
3609 "column": 22,
3610 "line": 12
3611 }
3612 },
3613 {
3614 "defaultMessage": "!!!edit",
3615 "end": {
3616 "column": 3,
3617 "line": 19
3618 },
3619 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
3620 "id": "workspaceDrawer.item.contextMenuEdit",
3621 "start": {
3622 "column": 19,
3623 "line": 16
3624 }
3625 }
3626 ],
3627 "path": "src/features/workspaces/components/WorkspaceDrawerItem.json"
3628 },
3629 {
3630 "descriptors": [
3631 {
3632 "defaultMessage": "!!!Your workspaces",
3633 "end": {
3634 "column": 3,
3635 "line": 20
3636 },
3637 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3638 "id": "settings.workspaces.headline",
3639 "start": {
3640 "column": 12,
3641 "line": 17
3642 }
3643 },
3644 {
3645 "defaultMessage": "!!!You haven't added any workspaces yet.",
3646 "end": {
3647 "column": 3,
3648 "line": 24
3649 },
3650 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3651 "id": "settings.workspaces.noWorkspacesAdded",
3652 "start": {
3653 "column": 19,
3654 "line": 21
3655 }
3656 },
3657 {
3658 "defaultMessage": "!!!Could not load your workspaces",
3659 "end": {
3660 "column": 3,
3661 "line": 28
3662 },
3663 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3664 "id": "settings.workspaces.workspacesRequestFailed",
3665 "start": {
3666 "column": 27,
3667 "line": 25
3668 }
3669 },
3670 {
3671 "defaultMessage": "!!!Try again",
3672 "end": {
3673 "column": 3,
3674 "line": 32
3675 },
3676 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3677 "id": "settings.workspaces.tryReloadWorkspaces",
3678 "start": {
3679 "column": 23,
3680 "line": 29
3681 }
3682 },
3683 {
3684 "defaultMessage": "!!!Your changes have been saved",
3685 "end": {
3686 "column": 3,
3687 "line": 36
3688 },
3689 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3690 "id": "settings.workspaces.updatedInfo",
3691 "start": {
3692 "column": 15,
3693 "line": 33
3694 }
3695 },
3696 {
3697 "defaultMessage": "!!!Workspace has been deleted",
3698 "end": {
3699 "column": 3,
3700 "line": 40
3701 },
3702 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3703 "id": "settings.workspaces.deletedInfo",
3704 "start": {
3705 "column": 15,
3706 "line": 37
3707 }
3708 },
3709 {
3710 "defaultMessage": "!!!Info about workspace feature",
3711 "end": {
3712 "column": 3,
3713 "line": 44
3714 },
3715 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3716 "id": "settings.workspaces.workspaceFeatureInfo",
3717 "start": {
3718 "column": 24,
3719 "line": 41
3720 }
3721 },
3722 {
3723 "defaultMessage": "!!!Less is More: Introducing Franz Workspaces",
3724 "end": {
3725 "column": 3,
3726 "line": 48
3727 },
3728 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
3729 "id": "settings.workspaces.workspaceFeatureHeadline",
3730 "start": {
3731 "column": 28,
3732 "line": 45
3733 }
3734 }
3735 ],
3736 "path": "src/features/workspaces/components/WorkspacesDashboard.json"
3737 },
3738 {
3739 "descriptors": [
3740 {
3741 "defaultMessage": "!!!Switching to",
3742 "end": {
3743 "column": 3,
3744 "line": 15
3745 },
3746 "file": "src/features/workspaces/components/WorkspaceSwitchingIndicator.js",
3747 "id": "workspaces.switchingIndicator.switchingTo",
3748 "start": {
3749 "column": 15,
3750 "line": 12
3751 }
3752 }
3753 ],
3754 "path": "src/features/workspaces/components/WorkspaceSwitchingIndicator.json"
3755 },
3756 {
3757 "descriptors": [
3758 {
3759 "defaultMessage": "!!!Field is required",
3760 "end": {
3761 "column": 3,
3762 "line": 7
3763 },
3764 "file": "src/helpers/validation-helpers.js",
3765 "id": "validation.required",
3766 "start": {
3767 "column": 12,
3768 "line": 4
3769 }
3770 },
3771 {
3772 "defaultMessage": "!!!Email not valid",
3773 "end": {
3774 "column": 3,
3775 "line": 11
3776 },
3777 "file": "src/helpers/validation-helpers.js",
3778 "id": "validation.email",
3779 "start": {
3780 "column": 9,
3781 "line": 8
3782 }
3783 },
3784 {
3785 "defaultMessage": "!!!Not a valid URL",
3786 "end": {
3787 "column": 3,
3788 "line": 15
3789 },
3790 "file": "src/helpers/validation-helpers.js",
3791 "id": "validation.url",
3792 "start": {
3793 "column": 7,
3794 "line": 12
3795 }
3796 },
3797 {
3798 "defaultMessage": "!!!Too few characters",
3799 "end": {
3800 "column": 3,
3801 "line": 19
3802 },
3803 "file": "src/helpers/validation-helpers.js",
3804 "id": "validation.minLength",
3805 "start": {
3806 "column": 13,
3807 "line": 16
3808 }
3809 },
3810 {
3811 "defaultMessage": "!!!At least one is required",
3812 "end": {
3813 "column": 3,
3814 "line": 23
3815 },
3816 "file": "src/helpers/validation-helpers.js",
3817 "id": "validation.oneRequired",
3818 "start": {
3819 "column": 15,
3820 "line": 20
3821 }
3822 }
3823 ],
3824 "path": "src/helpers/validation-helpers.json"
3825 },
3826 {
3827 "descriptors": [
3828 {
3829 "defaultMessage": "!!!Can't connect to Franz Online Services",
3830 "end": {
3831 "column": 3,
3832 "line": 7
3833 },
3834 "file": "src/i18n/globalMessages.js",
3835 "id": "global.api.unhealthy",
3836 "start": {
3837 "column": 16,
3838 "line": 4
3839 }
3840 },
3841 {
3842 "defaultMessage": "!!!You are not connected to the internet.",
3843 "end": {
3844 "column": 3,
3845 "line": 11
3846 },
3847 "file": "src/i18n/globalMessages.js",
3848 "id": "global.notConnectedToTheInternet",
3849 "start": {
3850 "column": 29,
3851 "line": 8
3852 }
3853 },
3854 {
3855 "defaultMessage": "!!!Spell checking language",
3856 "end": {
3857 "column": 3,
3858 "line": 15
3859 },
3860 "file": "src/i18n/globalMessages.js",
3861 "id": "global.spellchecking.language",
3862 "start": {
3863 "column": 24,
3864 "line": 12
3865 }
3866 },
3867 {
3868 "defaultMessage": "!!!Use System Default ({default})",
3869 "end": {
3870 "column": 3,
3871 "line": 19
3872 },
3873 "file": "src/i18n/globalMessages.js",
3874 "id": "global.spellchecker.useDefault",
3875 "start": {
3876 "column": 29,
3877 "line": 16
3878 }
3879 },
3880 {
3881 "defaultMessage": "!!!Detect language automatically",
3882 "end": {
3883 "column": 3,
3884 "line": 23
3885 },
3886 "file": "src/i18n/globalMessages.js",
3887 "id": "global.spellchecking.autodetect",
3888 "start": {
3889 "column": 34,
3890 "line": 20
3891 }
3892 },
3893 {
3894 "defaultMessage": "!!!Automatic",
3895 "end": {
3896 "column": 3,
3897 "line": 27
3898 },
3899 "file": "src/i18n/globalMessages.js",
3900 "id": "global.spellchecking.autodetect.short",
3901 "start": {
3902 "column": 39,
3903 "line": 24
3904 }
3905 }
3906 ],
3907 "path": "src/i18n/globalMessages.json"
3908 },
3909 {
3910 "descriptors": [
3911 {
3912 "defaultMessage": "!!!Edit",
3913 "end": {
3914 "column": 3,
3915 "line": 18
3916 },
3917 "file": "src/lib/Menu.js",
3918 "id": "menu.edit",
3919 "start": {
3920 "column": 8,
3921 "line": 15
3922 }
3923 },
3924 {
3925 "defaultMessage": "!!!Undo",
3926 "end": {
3927 "column": 3,
3928 "line": 22
3929 },
3930 "file": "src/lib/Menu.js",
3931 "id": "menu.edit.undo",
3932 "start": {
3933 "column": 8,
3934 "line": 19
3935 }
3936 },
3937 {
3938 "defaultMessage": "!!!Redo",
3939 "end": {
3940 "column": 3,
3941 "line": 26
3942 },
3943 "file": "src/lib/Menu.js",
3944 "id": "menu.edit.redo",
3945 "start": {
3946 "column": 8,
3947 "line": 23
3948 }
3949 },
3950 {
3951 "defaultMessage": "!!!Cut",
3952 "end": {
3953 "column": 3,
3954 "line": 30
3955 },
3956 "file": "src/lib/Menu.js",
3957 "id": "menu.edit.cut",
3958 "start": {
3959 "column": 7,
3960 "line": 27
3961 }
3962 },
3963 {
3964 "defaultMessage": "!!!Copy",
3965 "end": {
3966 "column": 3,
3967 "line": 34
3968 },
3969 "file": "src/lib/Menu.js",
3970 "id": "menu.edit.copy",
3971 "start": {
3972 "column": 8,
3973 "line": 31
3974 }
3975 },
3976 {
3977 "defaultMessage": "!!!Paste",
3978 "end": {
3979 "column": 3,
3980 "line": 38
3981 },
3982 "file": "src/lib/Menu.js",
3983 "id": "menu.edit.paste",
3984 "start": {
3985 "column": 9,
3986 "line": 35
3987 }
3988 },
3989 {
3990 "defaultMessage": "!!!Paste And Match Style",
3991 "end": {
3992 "column": 3,
3993 "line": 42
3994 },
3995 "file": "src/lib/Menu.js",
3996 "id": "menu.edit.pasteAndMatchStyle",
3997 "start": {
3998 "column": 22,
3999 "line": 39
4000 }
4001 },
4002 {
4003 "defaultMessage": "!!!Delete",
4004 "end": {
4005 "column": 3,
4006 "line": 46
4007 },
4008 "file": "src/lib/Menu.js",
4009 "id": "menu.edit.delete",
4010 "start": {
4011 "column": 10,
4012 "line": 43
4013 }
4014 },
4015 {
4016 "defaultMessage": "!!!Select All",
4017 "end": {
4018 "column": 3,
4019 "line": 50
4020 },
4021 "file": "src/lib/Menu.js",
4022 "id": "menu.edit.selectAll",
4023 "start": {
4024 "column": 13,
4025 "line": 47
4026 }
4027 },
4028 {
4029 "defaultMessage": "!!!Speech",
4030 "end": {
4031 "column": 3,
4032 "line": 54
4033 },
4034 "file": "src/lib/Menu.js",
4035 "id": "menu.edit.speech",
4036 "start": {
4037 "column": 10,
4038 "line": 51
4039 }
4040 },
4041 {
4042 "defaultMessage": "!!!Start Speaking",
4043 "end": {
4044 "column": 3,
4045 "line": 58
4046 },
4047 "file": "src/lib/Menu.js",
4048 "id": "menu.edit.startSpeaking",
4049 "start": {
4050 "column": 17,
4051 "line": 55
4052 }
4053 },
4054 {
4055 "defaultMessage": "!!!Stop Speaking",
4056 "end": {
4057 "column": 3,
4058 "line": 62
4059 },
4060 "file": "src/lib/Menu.js",
4061 "id": "menu.edit.stopSpeaking",
4062 "start": {
4063 "column": 16,
4064 "line": 59
4065 }
4066 },
4067 {
4068 "defaultMessage": "!!!Start Dictation",
4069 "end": {
4070 "column": 3,
4071 "line": 66
4072 },
4073 "file": "src/lib/Menu.js",
4074 "id": "menu.edit.startDictation",
4075 "start": {
4076 "column": 18,
4077 "line": 63
4078 }
4079 },
4080 {
4081 "defaultMessage": "!!!Emoji & Symbols",
4082 "end": {
4083 "column": 3,
4084 "line": 70
4085 },
4086 "file": "src/lib/Menu.js",
4087 "id": "menu.edit.emojiSymbols",
4088 "start": {
4089 "column": 16,
4090 "line": 67
4091 }
4092 },
4093 {
4094 "defaultMessage": "!!!Actual Size",
4095 "end": {
4096 "column": 3,
4097 "line": 74
4098 },
4099 "file": "src/lib/Menu.js",
4100 "id": "menu.view.resetZoom",
4101 "start": {
4102 "column": 13,
4103 "line": 71
4104 }
4105 },
4106 {
4107 "defaultMessage": "!!!Zoom In",
4108 "end": {
4109 "column": 3,
4110 "line": 78
4111 },
4112 "file": "src/lib/Menu.js",
4113 "id": "menu.view.zoomIn",
4114 "start": {
4115 "column": 10,
4116 "line": 75
4117 }
4118 },
4119 {
4120 "defaultMessage": "!!!Zoom Out",
4121 "end": {
4122 "column": 3,
4123 "line": 82
4124 },
4125 "file": "src/lib/Menu.js",
4126 "id": "menu.view.zoomOut",
4127 "start": {
4128 "column": 11,
4129 "line": 79
4130 }
4131 },
4132 {
4133 "defaultMessage": "!!!Enter Full Screen",
4134 "end": {
4135 "column": 3,
4136 "line": 86
4137 },
4138 "file": "src/lib/Menu.js",
4139 "id": "menu.view.enterFullScreen",
4140 "start": {
4141 "column": 19,
4142 "line": 83
4143 }
4144 },
4145 {
4146 "defaultMessage": "!!!Exit Full Screen",
4147 "end": {
4148 "column": 3,
4149 "line": 90
4150 },
4151 "file": "src/lib/Menu.js",
4152 "id": "menu.view.exitFullScreen",
4153 "start": {
4154 "column": 18,
4155 "line": 87
4156 }
4157 },
4158 {
4159 "defaultMessage": "!!!Toggle Full Screen",
4160 "end": {
4161 "column": 3,
4162 "line": 94
4163 },
4164 "file": "src/lib/Menu.js",
4165 "id": "menu.view.toggleFullScreen",
4166 "start": {
4167 "column": 20,
4168 "line": 91
4169 }
4170 },
4171 {
4172 "defaultMessage": "!!!Toggle Developer Tools",
4173 "end": {
4174 "column": 3,
4175 "line": 98
4176 },
4177 "file": "src/lib/Menu.js",
4178 "id": "menu.view.toggleDevTools",
4179 "start": {
4180 "column": 18,
4181 "line": 95
4182 }
4183 },
4184 {
4185 "defaultMessage": "!!!Toggle Service Developer Tools",
4186 "end": {
4187 "column": 3,
4188 "line": 102
4189 },
4190 "file": "src/lib/Menu.js",
4191 "id": "menu.view.toggleServiceDevTools",
4192 "start": {
4193 "column": 25,
4194 "line": 99
4195 }
4196 },
4197 {
4198 "defaultMessage": "!!!Reload Service",
4199 "end": {
4200 "column": 3,
4201 "line": 106
4202 },
4203 "file": "src/lib/Menu.js",
4204 "id": "menu.view.reloadService",
4205 "start": {
4206 "column": 17,
4207 "line": 103
4208 }
4209 },
4210 {
4211 "defaultMessage": "!!!Reload Franz",
4212 "end": {
4213 "column": 3,
4214 "line": 110
4215 },
4216 "file": "src/lib/Menu.js",
4217 "id": "menu.view.reloadFranz",
4218 "start": {
4219 "column": 15,
4220 "line": 107
4221 }
4222 },
4223 {
4224 "defaultMessage": "!!!Minimize",
4225 "end": {
4226 "column": 3,
4227 "line": 114
4228 },
4229 "file": "src/lib/Menu.js",
4230 "id": "menu.window.minimize",
4231 "start": {
4232 "column": 12,
4233 "line": 111
4234 }
4235 },
4236 {
4237 "defaultMessage": "!!!Close",
4238 "end": {
4239 "column": 3,
4240 "line": 118
4241 },
4242 "file": "src/lib/Menu.js",
4243 "id": "menu.window.close",
4244 "start": {
4245 "column": 9,
4246 "line": 115
4247 }
4248 },
4249 {
4250 "defaultMessage": "!!!Learn More",
4251 "end": {
4252 "column": 3,
4253 "line": 122
4254 },
4255 "file": "src/lib/Menu.js",
4256 "id": "menu.help.learnMore",
4257 "start": {
4258 "column": 13,
4259 "line": 119
4260 }
4261 },
4262 {
4263 "defaultMessage": "!!!Changelog",
4264 "end": {
4265 "column": 3,
4266 "line": 126
4267 },
4268 "file": "src/lib/Menu.js",
4269 "id": "menu.help.changelog",
4270 "start": {
4271 "column": 13,
4272 "line": 123
4273 }
4274 },
4275 {
4276 "defaultMessage": "!!!Support",
4277 "end": {
4278 "column": 3,
4279 "line": 130
4280 },
4281 "file": "src/lib/Menu.js",
4282 "id": "menu.help.support",
4283 "start": {
4284 "column": 11,
4285 "line": 127
4286 }
4287 },
4288 {
4289 "defaultMessage": "!!!Terms of Service",
4290 "end": {
4291 "column": 3,
4292 "line": 134
4293 },
4294 "file": "src/lib/Menu.js",
4295 "id": "menu.help.tos",
4296 "start": {
4297 "column": 7,
4298 "line": 131
4299 }
4300 },
4301 {
4302 "defaultMessage": "!!!Privacy Statement",
4303 "end": {
4304 "column": 3,
4305 "line": 138
4306 },
4307 "file": "src/lib/Menu.js",
4308 "id": "menu.help.privacy",
4309 "start": {
4310 "column": 11,
4311 "line": 135
4312 }
4313 },
4314 {
4315 "defaultMessage": "!!!File",
4316 "end": {
4317 "column": 3,
4318 "line": 142
4319 },
4320 "file": "src/lib/Menu.js",
4321 "id": "menu.file",
4322 "start": {
4323 "column": 8,
4324 "line": 139
4325 }
4326 },
4327 {
4328 "defaultMessage": "!!!View",
4329 "end": {
4330 "column": 3,
4331 "line": 146
4332 },
4333 "file": "src/lib/Menu.js",
4334 "id": "menu.view",
4335 "start": {
4336 "column": 8,
4337 "line": 143
4338 }
4339 },
4340 {
4341 "defaultMessage": "!!!Services",
4342 "end": {
4343 "column": 3,
4344 "line": 150
4345 },
4346 "file": "src/lib/Menu.js",
4347 "id": "menu.services",
4348 "start": {
4349 "column": 12,
4350 "line": 147
4351 }
4352 },
4353 {
4354 "defaultMessage": "!!!Window",
4355 "end": {
4356 "column": 3,
4357 "line": 154
4358 },
4359 "file": "src/lib/Menu.js",
4360 "id": "menu.window",
4361 "start": {
4362 "column": 10,
4363 "line": 151
4364 }
4365 },
4366 {
4367 "defaultMessage": "!!!Help",
4368 "end": {
4369 "column": 3,
4370 "line": 158
4371 },
4372 "file": "src/lib/Menu.js",
4373 "id": "menu.help",
4374 "start": {
4375 "column": 8,
4376 "line": 155
4377 }
4378 },
4379 {
4380 "defaultMessage": "!!!About Franz",
4381 "end": {
4382 "column": 3,
4383 "line": 162
4384 },
4385 "file": "src/lib/Menu.js",
4386 "id": "menu.app.about",
4387 "start": {
4388 "column": 9,
4389 "line": 159
4390 }
4391 },
4392 {
4393 "defaultMessage": "!!!What's new?",
4394 "end": {
4395 "column": 3,
4396 "line": 166
4397 },
4398 "file": "src/lib/Menu.js",
4399 "id": "menu.app.announcement",
4400 "start": {
4401 "column": 16,
4402 "line": 163
4403 }
4404 },
4405 {
4406 "defaultMessage": "!!!Settings",
4407 "end": {
4408 "column": 3,
4409 "line": 170
4410 },
4411 "file": "src/lib/Menu.js",
4412 "id": "menu.app.settings",
4413 "start": {
4414 "column": 12,
4415 "line": 167
4416 }
4417 },
4418 {
4419 "defaultMessage": "!!!Hide",
4420 "end": {
4421 "column": 3,
4422 "line": 174
4423 },
4424 "file": "src/lib/Menu.js",
4425 "id": "menu.app.hide",
4426 "start": {
4427 "column": 8,
4428 "line": 171
4429 }
4430 },
4431 {
4432 "defaultMessage": "!!!Hide Others",
4433 "end": {
4434 "column": 3,
4435 "line": 178
4436 },
4437 "file": "src/lib/Menu.js",
4438 "id": "menu.app.hideOthers",
4439 "start": {
4440 "column": 14,
4441 "line": 175
4442 }
4443 },
4444 {
4445 "defaultMessage": "!!!Unhide",
4446 "end": {
4447 "column": 3,
4448 "line": 182
4449 },
4450 "file": "src/lib/Menu.js",
4451 "id": "menu.app.unhide",
4452 "start": {
4453 "column": 10,
4454 "line": 179
4455 }
4456 },
4457 {
4458 "defaultMessage": "!!!Quit",
4459 "end": {
4460 "column": 3,
4461 "line": 186
4462 },
4463 "file": "src/lib/Menu.js",
4464 "id": "menu.app.quit",
4465 "start": {
4466 "column": 8,
4467 "line": 183
4468 }
4469 },
4470 {
4471 "defaultMessage": "!!!Add New Service...",
4472 "end": {
4473 "column": 3,
4474 "line": 190
4475 },
4476 "file": "src/lib/Menu.js",
4477 "id": "menu.services.addNewService",
4478 "start": {
4479 "column": 17,
4480 "line": 187
4481 }
4482 },
4483 {
4484 "defaultMessage": "!!!Add New Workspace...",
4485 "end": {
4486 "column": 3,
4487 "line": 194
4488 },
4489 "file": "src/lib/Menu.js",
4490 "id": "menu.workspaces.addNewWorkspace",
4491 "start": {
4492 "column": 19,
4493 "line": 191
4494 }
4495 },
4496 {
4497 "defaultMessage": "!!!Open workspace drawer",
4498 "end": {
4499 "column": 3,
4500 "line": 198
4501 },
4502 "file": "src/lib/Menu.js",
4503 "id": "menu.workspaces.openWorkspaceDrawer",
4504 "start": {
4505 "column": 23,
4506 "line": 195
4507 }
4508 },
4509 {
4510 "defaultMessage": "!!!Close workspace drawer",
4511 "end": {
4512 "column": 3,
4513 "line": 202
4514 },
4515 "file": "src/lib/Menu.js",
4516 "id": "menu.workspaces.closeWorkspaceDrawer",
4517 "start": {
4518 "column": 24,
4519 "line": 199
4520 }
4521 },
4522 {
4523 "defaultMessage": "!!!Activate next service...",
4524 "end": {
4525 "column": 3,
4526 "line": 206
4527 },
4528 "file": "src/lib/Menu.js",
4529 "id": "menu.services.setNextServiceActive",
4530 "start": {
4531 "column": 23,
4532 "line": 203
4533 }
4534 },
4535 {
4536 "defaultMessage": "!!!Activate previous service...",
4537 "end": {
4538 "column": 3,
4539 "line": 210
4540 },
4541 "file": "src/lib/Menu.js",
4542 "id": "menu.services.activatePreviousService",
4543 "start": {
4544 "column": 27,
4545 "line": 207
4546 }
4547 },
4548 {
4549 "defaultMessage": "!!!Disable notifications & audio",
4550 "end": {
4551 "column": 3,
4552 "line": 214
4553 },
4554 "file": "src/lib/Menu.js",
4555 "id": "sidebar.muteApp",
4556 "start": {
4557 "column": 11,
4558 "line": 211
4559 }
4560 },
4561 {
4562 "defaultMessage": "!!!Enable notifications & audio",
4563 "end": {
4564 "column": 3,
4565 "line": 218
4566 },
4567 "file": "src/lib/Menu.js",
4568 "id": "sidebar.unmuteApp",
4569 "start": {
4570 "column": 13,
4571 "line": 215
4572 }
4573 },
4574 {
4575 "defaultMessage": "!!!Workspaces",
4576 "end": {
4577 "column": 3,
4578 "line": 222
4579 },
4580 "file": "src/lib/Menu.js",
4581 "id": "menu.workspaces",
4582 "start": {
4583 "column": 14,
4584 "line": 219
4585 }
4586 },
4587 {
4588 "defaultMessage": "!!!Default",
4589 "end": {
4590 "column": 3,
4591 "line": 226
4592 },
4593 "file": "src/lib/Menu.js",
4594 "id": "menu.workspaces.defaultWorkspace",
4595 "start": {
4596 "column": 20,
4597 "line": 223
4598 }
4599 }
4600 ],
4601 "path": "src/lib/Menu.json"
4602 }
4603] \ No newline at end of file
diff --git a/src/i18n/locales/el.json b/src/i18n/locales/el.json
index 671eecd41..0ff4b5abb 100644
--- a/src/i18n/locales/el.json
+++ b/src/i18n/locales/el.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "ΕπαναφόÏτωση", 2 "app.errorHandler.action" : "ΕπαναφόÏτωση",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Κάτι δεν λειτουÏγεί",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz θα συνεχίσει σε {seconds} δευτεÏόλεπτα.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Δεν είναι δυνατή η σÏνδεση με τις ζωντανές υπηÏεσίες του Franz", 15 "global.api.unhealthy" : "Δεν είναι δυνατή η σÏνδεση με τις ζωντανές υπηÏεσίες του Franz",
8 "global.notConnectedToTheInternet" : "Έχετε αποσυνδεθεί από το Διαδίκτυο", 16 "global.notConnectedToTheInternet" : "Έχετε αποσυνδεθεί από το Διαδίκτυο",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "Εισαγάγετε τις υπηÏεσίες σας Franz 4", 21 "import.headline" : "Εισαγάγετε τις υπηÏεσίες σας Franz 4",
10 "import.notSupportedHeadline" : "ΥπηÏεσίες που δεν υποστηÏίζονται ακόμα στο Franz 5", 22 "import.notSupportedHeadline" : "ΥπηÏεσίες που δεν υποστηÏίζονται ακόμα στο Franz 5",
11 "import.skip.label" : "Θέλω να Ï€Ïοσθέσω υπηÏεσίες χειÏοκίνητα", 23 "import.skip.label" : "Θέλω να Ï€Ïοσθέσω υπηÏεσίες χειÏοκίνητα",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "ΣÏνδεση", 44 "login.submit.label" : "ΣÏνδεση",
33 "login.tokenExpired" : "Η συνεδÏία σας έληξε, συνδεθείτε ξανά.", 45 "login.tokenExpired" : "Η συνεδÏία σας έληξε, συνδεθείτε ξανά.",
34 "menu.app.about" : "Σχετικά με το Franz", 46 "menu.app.about" : "Σχετικά με το Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "ΑπόκÏυψη", 48 "menu.app.hide" : "ΑπόκÏυψη",
36 "menu.app.hideOthers" : "ΑπόκÏυψη των άλλων", 49 "menu.app.hideOthers" : "ΑπόκÏυψη των άλλων",
37 "menu.app.quit" : "Έξοδος", 50 "menu.app.quit" : "Έξοδος",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "ΥποστήÏιξη", 72 "menu.help.support" : "ΥποστήÏιξη",
60 "menu.help.tos" : "ÎŒÏοι ΧÏήσης", 73 "menu.help.tos" : "ÎŒÏοι ΧÏήσης",
61 "menu.services" : "ΥπηÏεσίες", 74 "menu.services" : "ΥπηÏεσίες",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Îέα ΥπηÏεσία", 76 "menu.services.addNewService" : "Îέα ΥπηÏεσία",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "ΠÏοβολή", 78 "menu.view" : "ΠÏοβολή",
64 "menu.view.enterFullScreen" : "ΠλήÏης Οθόνη", 79 "menu.view.enterFullScreen" : "ΠλήÏης Οθόνη",
65 "menu.view.exitFullScreen" : "Έξοδος από πλήÏη οθόνη", 80 "menu.view.exitFullScreen" : "Έξοδος από πλήÏη οθόνη",
@@ -74,6 +89,11 @@
74 "menu.window" : "ΠαÏάθυÏο", 89 "menu.window" : "ΠαÏάθυÏο",
75 "menu.window.close" : "Κλείσιμο", 90 "menu.window.close" : "Κλείσιμο",
76 "menu.window.minimize" : "Ελαχιστοποίηση", 91 "menu.window.minimize" : "Ελαχιστοποίηση",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Όλες οι υπηÏεσίες",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "ΔιεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου", 97 "password.email.label" : "ΔιεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου",
78 "password.headline" : "ΕπαναφοÏά ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης", 98 "password.headline" : "ΕπαναφοÏά ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης",
79 "password.link.login" : "ΣÏνδεση στο λογαÏιασμό σας", 99 "password.link.login" : "ΣÏνδεση στο λογαÏιασμό σας",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "Ω, όχι!", 117 "service.errorHandler.headline" : "Ω, όχι!",
98 "service.errorHandler.message" : "Σφάλμα", 118 "service.errorHandler.message" : "Σφάλμα",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Ξεκινήστε", 121 "services.getStarted" : "Ξεκινήστε",
101 "services.welcome" : "Καλώς οÏίσατε στον Franz", 122 "services.welcome" : "Καλώς οÏίσατε στον Franz",
102 "settings.account.account.editButton" : "ΕπεξεÏγασία λογαÏιασμοÏ", 123 "settings.account.account.editButton" : "ΕπεξεÏγασία λογαÏιασμοÏ",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Λήψη", 138 "settings.account.invoiceDownload" : "Λήψη",
118 "settings.account.manageSubscription.label" : "ΔιαχείÏιση της συνδÏομής σας", 139 "settings.account.manageSubscription.label" : "ΔιαχείÏιση της συνδÏομής σας",
119 "settings.account.successInfo" : "Οι αλλαγές σας έχουν αποθηκευτεί", 140 "settings.account.successInfo" : "Οι αλλαγές σας έχουν αποθηκευτεί",
141 "settings.account.tryReloadServices" : "Δοκιμάστε ξανά",
120 "settings.account.tryReloadUserInfoRequest" : "Δοκιμάστε ξανά", 142 "settings.account.tryReloadUserInfoRequest" : "Δοκιμάστε ξανά",
121 "settings.account.userInfoRequestFailed" : "Δεν ήταν δυνατή η φόÏτωση πληÏοφοÏιών χÏήστη", 143 "settings.account.userInfoRequestFailed" : "Δεν ήταν δυνατή η φόÏτωση πληÏοφοÏιών χÏήστη",
122 "settings.app.buttonClearAllCache" : "ΚαθαÏισμός λανθάνουσας μνήμης", 144 "settings.app.buttonClearAllCache" : "ΚαθαÏισμός λανθάνουσας μνήμης",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "ΣυμπεÏιλάβετε εκδόσεις beta", 151 "settings.app.form.beta" : "ΣυμπεÏιλάβετε εκδόσεις beta",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "ΕνεÏγοποιήση Ενίσχυσης GPU ", 153 "settings.app.form.enableGPUAcceleration" : "ΕνεÏγοποιήση Ενίσχυσης GPU ",
132 "settings.app.form.enableMenuBar" : "Εμφάνιση ΓÏαμμής ÎœÎµÎ½Î¿Ï Franz",
133 "settings.app.form.enableSpellchecking" : "ΕνεÏγοποίηση οÏθογÏÎ±Ï†Î¹ÎºÎ¿Ï ÎµÎ»Î­Î³Ï‡Î¿Ï…", 154 "settings.app.form.enableSpellchecking" : "ΕνεÏγοποίηση οÏθογÏÎ±Ï†Î¹ÎºÎ¿Ï ÎµÎ»Î­Î³Ï‡Î¿Ï…",
134 "settings.app.form.enableSystemTray" : "Εμφάνιση του Franz στη γÏαμμή ειδοποιήσεων", 155 "settings.app.form.enableSystemTray" : "Εμφάνιση του Franz στη γÏαμμή ειδοποιήσεων",
135 "settings.app.form.hideDockIcon" : "ΑπόκÏυψη εικονιδίου Franz",
136 "settings.app.form.language" : "Γλώσσα", 156 "settings.app.form.language" : "Γλώσσα",
137 "settings.app.form.minimizeToSystemTray" : "Ελαχιστοποίηση του Franz στη γÏαμμή ειδοποιήσεων", 157 "settings.app.form.minimizeToSystemTray" : "Ελαχιστοποίηση του Franz στη γÏαμμή ειδοποιήσεων",
138 "settings.app.form.runInBackground" : "ΚÏατήστε το Franz στο παÏασκήνιο κατά το κλείσιμο του παÏαθÏÏου", 158 "settings.app.form.runInBackground" : "ΚÏατήστε το Franz στο παÏασκήνιο κατά το κλείσιμο του παÏαθÏÏου",
139 "settings.app.form.showDisabledServices" : "ΠÏοβολή καÏτελών των απενεÏγοποιημένων υπηÏεσιών", 159 "settings.app.form.showDisabledServices" : "ΠÏοβολή καÏτελών των απενεÏγοποιημένων υπηÏεσιών",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "ΠÏοβολή του εικονιδίου μη αναγνωσμένου μηνÏματος όταν οι ειδοποιήσεις είναι απενεÏγοποιημένες", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "ΠÏοβολή του εικονιδίου μη αναγνωσμένου μηνÏματος όταν οι ειδοποιήσεις είναι απενεÏγοποιημένες",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Ρυθμίσεις", 161 "settings.app.headline" : "Ρυθμίσεις",
143 "settings.app.headlineAdvanced" : "Για Ï€ÏοχωÏημένους", 162 "settings.app.headlineAdvanced" : "Για Ï€ÏοχωÏημένους",
144 "settings.app.headlineAppearance" : "Εμφάνιση", 163 "settings.app.headlineAppearance" : "Εμφάνιση",
145 "settings.app.headlineGeneral" : "Γενικά", 164 "settings.app.headlineGeneral" : "Γενικά",
146 "settings.app.headlineLanguage" : "Γλώσσα", 165 "settings.app.headlineLanguage" : "Γλώσσα",
147 "settings.app.headlineUpdates" : "ΕνημεÏώσεις", 166 "settings.app.headlineUpdates" : "ΕνημεÏώσεις",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Οι αλλαγές απαιτοÏν επανεκκίνηση", 168 "settings.app.restartRequired" : "Οι αλλαγές απαιτοÏν επανεκκίνηση",
149 "settings.app.subheadlineCache" : "Λανθάνουσα μνήμη", 169 "settings.app.subheadlineCache" : "Λανθάνουσα μνήμη",
150 "settings.app.translationHelp" : "Βοηθήστε μας να μεταφÏάσουμε το Franz στη δική σας γλώσσα.", 170 "settings.app.translationHelp" : "Βοηθήστε μας να μεταφÏάσουμε το Franz στη δική σας γλώσσα.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "ΠÏασκαλέστε Φίλους", 177 "settings.navigation.inviteFriends" : "ΠÏασκαλέστε Φίλους",
158 "settings.navigation.logout" : "ΑποσÏνδεση", 178 "settings.navigation.logout" : "ΑποσÏνδεση",
159 "settings.navigation.settings" : "Ρυθμίσεις", 179 "settings.navigation.settings" : "Ρυθμίσεις",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Οι υπηÏεσίες σας", 181 "settings.navigation.yourServices" : "Οι υπηÏεσίες σας",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Όλες οι υπηÏεσίες", 183 "settings.recipes.all" : "Όλες οι υπηÏεσίες",
162 "settings.recipes.dev" : "Ανάπτυξη", 184 "settings.recipes.dev" : "Ανάπτυξη",
163 "settings.recipes.headline" : "Διαθέσιμες υπηÏεσίες", 185 "settings.recipes.headline" : "Διαθέσιμες υπηÏεσίες",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "Αποθήκευση υπηÏεσίας", 225 "settings.service.form.saveButton" : "Αποθήκευση υπηÏεσίας",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Φιλοξενείται", 226 "settings.service.form.tabHosted" : "Φιλοξενείται",
207 "settings.service.form.tabOnPremise" : "Αυτο-φιλοξενείται â­ï¸", 227 "settings.service.form.tabOnPremise" : "Αυτο-φιλοξενείται â­ï¸",
208 "settings.service.form.team" : "Ομάδα", 228 "settings.service.form.team" : "Ομάδα",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "ΑνακαλÏψτε υπηÏεσίες", 232 "settings.services.discoverServices" : "ΑνακαλÏψτε υπηÏεσίες",
213 "settings.services.headline" : "Οι υπηÏεσίες σας", 233 "settings.services.headline" : "Οι υπηÏεσίες σας",
214 "settings.services.noServicesAdded" : "Δεν έχετε Ï€Ïοσθέσει ακόμα υπηÏεσίες.", 234 "settings.services.noServicesAdded" : "Δεν έχετε Ï€Ïοσθέσει ακόμα υπηÏεσίες.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Η υπηÏεσία είναι απενεÏγοποιημένη", 236 "settings.services.tooltip.isDisabled" : "Η υπηÏεσία είναι απενεÏγοποιημένη",
216 "settings.services.tooltip.isMuted" : "Όλοι οι ήχοι είναι απενεÏγοποιημένοι", 237 "settings.services.tooltip.isMuted" : "Όλοι οι ήχοι είναι απενεÏγοποιημένοι",
217 "settings.services.tooltip.notificationsDisabled" : "Οι ειδοποιήσεις είναι απενεÏγοποιημένες", 238 "settings.services.tooltip.notificationsDisabled" : "Οι ειδοποιήσεις είναι απενεÏγοποιημένες",
218 "settings.services.updatedInfo" : "Οι αλλαγές σας έχουν αποθηκευτεί", 239 "settings.services.updatedInfo" : "Οι αλλαγές σας έχουν αποθηκευτεί",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Ομάδα",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "ΕταιÏεία", 246 "settings.user.form.accountType.company" : "ΕταιÏεία",
220 "settings.user.form.accountType.individual" : "Ατομικός", 247 "settings.user.form.accountType.individual" : "Ατομικός",
221 "settings.user.form.accountType.label" : "ΤÏπος λογαÏιασμοÏ", 248 "settings.user.form.accountType.label" : "ΤÏπος λογαÏιασμοÏ",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Όνομα", 252 "settings.user.form.firstname" : "Όνομα",
226 "settings.user.form.lastname" : "Επίθετο", 253 "settings.user.form.lastname" : "Επίθετο",
227 "settings.user.form.newPassword" : "Îέος κωδικός Ï€Ïόσβασης", 254 "settings.user.form.newPassword" : "Îέος κωδικός Ï€Ïόσβασης",
255 "settings.workspace.add.form.name" : "Όνομα",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Όνομα",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Δοκιμάστε ξανά",
266 "settings.workspaces.updatedInfo" : "Οι αλλαγές σας έχουν αποθηκευτεί",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "ΠÏοσθήκη νέας υπηÏεσίας", 270 "sidebar.addNewService" : "ΠÏοσθήκη νέας υπηÏεσίας",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "ΑπενεÏγοποίηση ειδοποιήσεων & ήχου", 272 "sidebar.muteApp" : "ΑπενεÏγοποίηση ειδοποιήσεων & ήχου",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Ρυθμίσεις", 274 "sidebar.settings" : "Ρυθμίσεις",
231 "sidebar.unmuteApp" : "ΕνεÏγοποίηση ειδοποιήσεων & ήχου", 275 "sidebar.unmuteApp" : "ΕνεÏγοποίηση ειδοποιήσεων & ήχου",
232 "signup.company.label" : "ΕταιÏεία", 276 "signup.company.label" : "ΕταιÏεία",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Πολίτες Ε.Ε.: Στις τιμές δεν πεÏιλαμβάνονται τυχόν φόÏοι και άλλες τοπικές επιβαÏÏνσεις", 288 "subscription.euTaxInfo" : "Πολίτες Ε.Ε.: Στις τιμές δεν πεÏιλαμβάνονται τυχόν φόÏοι και άλλες τοπικές επιβαÏÏνσεις",
245 "subscription.features.ads" : "Τέλος στις διαφημίσεις", 289 "subscription.features.ads" : "Τέλος στις διαφημίσεις",
246 "subscription.features.comingSoon" : "σÏντομα", 290 "subscription.features.comingSoon" : "σÏντομα",
247 "subscription.features.encryptedSync" : "ΚÏυπτογÏαφημένος συγχÏονισμός πεÏιόδου σÏνδεσης",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Add on-premise \/ hosted services όπως το HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Ο Premium λογαÏιασμός υποστήÏιξης Franz πεÏιλαμβάνει", 296 "subscription.includedFeatures" : "Ο Premium λογαÏιασμός υποστήÏιξης Franz πεÏιλαμβάνει",
254 "subscription.paymentSessionError" : "Δεν ήταν δυνατή η Ï€Ïοετοιμασία της φόÏμας πληÏωμής", 297 "subscription.paymentSessionError" : "Δεν ήταν δυνατή η Ï€Ïοετοιμασία της φόÏμας πληÏωμής",
255 "subscription.submit.label" : "Θέλω να βοηθήσω στην ανάπτυξη του Franz", 298 "subscription.submit.label" : "Θέλω να βοηθήσω στην ανάπτυξη του Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "ΕπαναφόÏτωση", 312 "tabs.item.reload" : "ΕπαναφόÏτωση",
270 "validation.email" : "{field} δεν είναι έγκυÏο", 313 "validation.email" : "{field} δεν είναι έγκυÏο",
271 "validation.minLength" : "{field} Ï€Ïέπει να είναι τουλάχιστον {length} χαÏακτήÏες", 314 "validation.minLength" : "{field} Ï€Ïέπει να είναι τουλάχιστον {length} χαÏακτήÏες",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} είναι υποχÏεωτικό", 316 "validation.required" : "{field} είναι υποχÏεωτικό",
273 "validation.url" : "{field} δεν είναι έγκυÏος σÏνδεσμος URL", 317 "validation.url" : "{field} δεν είναι έγκυÏος σÏνδεσμος URL",
274 "welcome.loginButton" : "ΣÏνδεση στο λογαÏιασμό σας", 318 "welcome.loginButton" : "ΣÏνδεση στο λογαÏιασμό σας",
275 "welcome.signupButton" : "ΔημιουÏγία δωÏεάν λογαÏιασμοÏ", 319 "welcome.signupButton" : "ΔημιουÏγία δωÏεάν λογαÏιασμοÏ",
276 "welcome.slogan" : "Επικοινωνία που λειτουÏγεί για εσάς" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Όλες οι υπηÏεσίες",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index 99df6a0ca..6c2759dcc 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -1,277 +1,331 @@
1{ 1{
2 "app.errorHandler.action": "Reload",
3 "app.errorHandler.headline": "Something went wrong",
4 "feature.announcements.changelog.headline": "Changes in Franz {version}",
5 "feature.delayApp.action": "Get a Franz Supporter License",
6 "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting",
7 "feature.delayApp.text": "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email": "Send as email",
9 "feature.shareFranz.action.facebook": "Share on Facebook",
10 "feature.shareFranz.action.twitter": "Share on Twitter",
11 "feature.shareFranz.headline": "Franz is better together!",
12 "feature.shareFranz.shareText.email": "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter": "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger",
14 "feature.shareFranz.text": "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
2 "global.api.unhealthy": "Can't connect to Franz online services", 15 "global.api.unhealthy": "Can't connect to Franz online services",
3 "global.notConnectedToTheInternet": "You are not connected to the internet.", 16 "global.notConnectedToTheInternet": "You are not connected to the internet.",
4 "welcome.signupButton": "Create a free account", 17 "global.spellchecker.useDefault": "Use System Default ({default})",
5 "welcome.loginButton": "Login to your account", 18 "global.spellchecking.autodetect": "Detect language automatically",
6 "welcome.slogan": "Messaging that works for you", 19 "global.spellchecking.autodetect.short": "Automatic",
7 "login.headline": "Sign in", 20 "global.spellchecking.language": "Spell checking language",
21 "import.headline": "Import your Franz 4 services",
22 "import.notSupportedHeadline": "Services not yet supported in Franz 5",
23 "import.skip.label": "I want to add services manually",
24 "import.submit.label": "Import services",
25 "infobar.buttonChangelog": "What is new?",
26 "infobar.buttonInstallUpdate": "Restart & install update",
27 "infobar.buttonReloadServices": "Reload services",
28 "infobar.requiredRequestsFailed": "Could not load services and user information",
29 "infobar.servicesUpdated": "Your services have been updated.",
30 "infobar.updateAvailable": "A new update for Franz is available.",
31 "invite.email.label": "Email address",
32 "invite.headline.friends": "Invite 3 of your friends or colleagues",
33 "invite.name.label": "Name",
34 "invite.skip.label": "I want to do this later",
35 "invite.submit.label": "Send invites",
36 "invite.successInfo": "Invitations sent successfully",
8 "login.email.label": "Email address", 37 "login.email.label": "Email address",
38 "login.headline": "Sign in",
39 "login.invalidCredentials": "Email or password not valid",
40 "login.link.password": "Reset password",
41 "login.link.signup": "Create a free account",
9 "login.password.label": "Password", 42 "login.password.label": "Password",
43 "login.serverLogout": "Your session expired, please login again.",
10 "login.submit.label": "Sign in", 44 "login.submit.label": "Sign in",
11 "login.invalidCredentials": "Email or password not valid",
12 "login.tokenExpired": "Your session expired, please login again.", 45 "login.tokenExpired": "Your session expired, please login again.",
13 "login.serverLogout": "Your session expired, please login again.", 46 "menu.app.about": "About Franz",
14 "login.link.signup": "Create a free account", 47 "menu.app.announcement": "What's new?",
15 "login.link.password": "Reset password", 48 "menu.app.hide": "Hide",
16 "password.headline": "Reset password", 49 "menu.app.hideOthers": "Hide Others",
50 "menu.app.quit": "Quit",
51 "menu.app.settings": "Settings",
52 "menu.app.unhide": "Unhide",
53 "menu.edit": "Edit",
54 "menu.edit.copy": "Copy",
55 "menu.edit.cut": "Cut",
56 "menu.edit.delete": "Delete",
57 "menu.edit.emojiSymbols": "Emoji & Symbols",
58 "menu.edit.paste": "Paste",
59 "menu.edit.pasteAndMatchStyle": "Paste And Match Style",
60 "menu.edit.redo": "Redo",
61 "menu.edit.selectAll": "Select All",
62 "menu.edit.speech": "Speech",
63 "menu.edit.startDictation": "Start Dictation",
64 "menu.edit.startSpeaking": "Start Speaking",
65 "menu.edit.stopSpeaking": "Stop Speaking",
66 "menu.edit.undo": "Undo",
67 "menu.file": "File",
68 "menu.help": "Help",
69 "menu.help.changelog": "Changelog",
70 "menu.help.learnMore": "Learn More",
71 "menu.help.privacy": "Privacy Statement",
72 "menu.help.support": "Support",
73 "menu.help.tos": "Terms of Service",
74 "menu.services": "Services",
75 "menu.services.activatePreviousService": "Activate previous service",
76 "menu.services.addNewService": "Add New Service...",
77 "menu.services.setNextServiceActive": "Activate next service",
78 "menu.view": "View",
79 "menu.view.enterFullScreen": "Enter Full Screen",
80 "menu.view.exitFullScreen": "Exit Full Screen",
81 "menu.view.reloadFranz": "Reload Franz",
82 "menu.view.reloadService": "Reload Service",
83 "menu.view.resetZoom": "Actual Size",
84 "menu.view.toggleDevTools": "Toggle Developer Tools",
85 "menu.view.toggleFullScreen": "Toggle Full Screen",
86 "menu.view.toggleServiceDevTools": "Toggle Service Developer Tools",
87 "menu.view.zoomIn": "Zoom In",
88 "menu.view.zoomOut": "Zoom Out",
89 "menu.window": "Window",
90 "menu.window.close": "Close",
91 "menu.window.minimize": "Minimize",
92 "menu.workspaces": "Workspaces",
93 "menu.workspaces.addNewWorkspace": "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer": "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace": "All services",
96 "menu.workspaces.openWorkspaceDrawer": "Open workspace drawer",
17 "password.email.label": "Email address", 97 "password.email.label": "Email address",
18 "password.submit.label": "Submit", 98 "password.headline": "Reset password",
99 "password.link.login": "Sign in to your account",
100 "password.link.signup": "Create a free account",
19 "password.noUser": "No user with that email address was found", 101 "password.noUser": "No user with that email address was found",
102 "password.submit.label": "Submit",
20 "password.successInfo": "Please check your email", 103 "password.successInfo": "Please check your email",
21 "password.link.signup": "Create a free account", 104 "premiumFeature.button.upgradeAccount": "Upgrade account",
22 "password.link.login": "Sign in to your account",
23 "signup.headline": "Sign up",
24 "signup.firstname.label": "First Name",
25 "signup.lastname.label": "Last Name",
26 "signup.email.label": "Email address",
27 "signup.company.label": "Company",
28 "signup.password.label": "Password",
29 "signup.submit.label": "Create account",
30 "signup.link.login": "Already have an account, sign in?",
31 "signup.emailDuplicate": "A user with that email address already exists",
32 "signup.legal.info": "By creating a Franz account you accept the",
33 "signup.legal.terms": "Terms of service",
34 "signup.legal.privacy": "Privacy Statement",
35 "pricing.headline": "Support Franz", 105 "pricing.headline": "Support Franz",
36 "pricing.support.label": "Select your support plan",
37 "pricing.submit.label": "I want to support the development of Franz",
38 "pricing.link.skipPayment": "I don't want to support the development of Franz.", 106 "pricing.link.skipPayment": "I don't want to support the development of Franz.",
39 "import.headline": "Import your Franz 4 services", 107 "pricing.submit.label": "I want to support the development of Franz",
40 "import.notSupportedHeadline": "Services not yet supported in Franz 5", 108 "pricing.support.label": "Select your support plan",
41 "import.submit.label": "Import services", 109 "service.crashHandler.action": "Reload {name}",
42 "import.skip.label": "I want to add services manually", 110 "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds",
43 "invite.submit.label": "Send invites", 111 "service.crashHandler.headline": "Oh no!",
44 "invite.headline.friends": "Invite 3 of your friends or colleagues", 112 "service.crashHandler.text": "{name} has caused an error.",
45 "invite.name.label": "Name", 113 "service.disabledHandler.action": "Enable {name}",
46 "invite.email.label": "Email address", 114 "service.disabledHandler.headline": "{name} is disabled",
47 "invite.skip.label": "I want to do this later", 115 "service.errorHandler.action": "Reload {name}",
48 "invite.successInfo": "Invitations sent successfully", 116 "service.errorHandler.editAction": "Edit {name}",
49 "subscription.submit.label": "I want to support the development of Franz", 117 "service.errorHandler.headline": "Oh no!",
50 "subscription.paymentSessionError": "Could not initialize payment form", 118 "service.errorHandler.message": "Error",
51 "subscription.includedFeatures": "Paid Franz Premium Supporter Account includes", 119 "service.errorHandler.text": "{name} has failed to load.",
52 "subscription.features.onpremise": "Add on-premise/hosted services like HipChat", 120 "service.webviewLoader.loading": "Loading",
53 "subscription.features.onpremise.mattermost": "Add on-premise/hosted services like Mattermost",
54 "subscription.features.encryptedSync": "Encrypted session synchronization",
55 "subscription.features.proxy": "Proxy support for services",
56 "subscription.features.ads": "No ads, ever!",
57 "subscription.features.spellchecker": "Support for spellchecker",
58 "subscription.features.noInterruptions": "No app delays & nagging to upgrade license",
59 "subscription.features.comingSoon": "coming soon",
60 "infobar.servicesUpdated": "Your services have been updated.",
61 "infobar.updateAvailable": "A new update for Franz is available.",
62 "infobar.buttonReloadServices": "Reload services",
63 "infobar.buttonInstallUpdate": "Restart & install update",
64 "infobar.buttonChangelog": "What is new?",
65 "infobar.requiredRequestsFailed": "Could not load services and user information",
66 "sidebar.settings": "Settings",
67 "sidebar.addNewService": "Add new service",
68 "sidebar.muteApp": "Disable notifications & audio",
69 "sidebar.unmuteApp": "Enable notifications & audio",
70 "services.welcome": "Welcome to Franz",
71 "services.getStarted": "Get started", 121 "services.getStarted": "Get started",
72 "settings.searchService": "Search service", 122 "services.welcome": "Welcome to Franz",
73 "settings.account.headline": "Account", 123 "settings.account.account.editButton": "Edit account",
74 "settings.account.headlineSubscription": "Your subscription",
75 "settings.account.headlineUpgrade": "Upgrade your account & support Franz",
76 "settings.account.headlineInvoices": "Invoices",
77 "settings.account.headlineDangerZone": "Danger Zone",
78 "settings.account.manageSubscription.label": "Manage your subscription",
79 "settings.account.accountType.basic": "Basic Account", 124 "settings.account.accountType.basic": "Basic Account",
80 "settings.account.accountType.premium": "Premium Supporter Account", 125 "settings.account.accountType.premium": "Premium Supporter Account",
81 "settings.account.account.editButton": "Edit account",
82 "settings.account.invoiceDownload": "Download",
83 "settings.account.userInfoRequestFailed": "Could not load user information",
84 "settings.account.tryReloadUserInfoRequest": "Try again",
85 "settings.account.headlineProfile": "Update profile",
86 "settings.account.headlineAccount": "Account information",
87 "settings.account.headlinePassword": "Change password",
88 "settings.account.successInfo": "Your changes have been saved",
89 "settings.account.buttonSave": "Update profile", 126 "settings.account.buttonSave": "Update profile",
90 "settings.account.deleteAccount": "Delete account", 127 "settings.account.deleteAccount": "Delete account",
91 "settings.account.deleteInfo": "If you don't need your Franz account any longer, you can delete your account and all related data here.",
92 "settings.account.deleteEmailSent": "You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!", 128 "settings.account.deleteEmailSent": "You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
129 "settings.account.deleteInfo": "If you don't need your Franz account any longer, you can delete your account and all related data here.",
130 "settings.account.headline": "Account",
131 "settings.account.headlineAccount": "Account information",
132 "settings.account.headlineDangerZone": "Danger Zone",
133 "settings.account.headlineInvoices": "Invoices",
134 "settings.account.headlinePassword": "Change password",
135 "settings.account.headlineProfile": "Update profile",
136 "settings.account.headlineSubscription": "Your subscription",
137 "settings.account.headlineUpgrade": "Upgrade your account & support Franz",
138 "settings.account.invoiceDownload": "Download",
139 "settings.account.manageSubscription.label": "Manage your subscription",
140 "settings.account.successInfo": "Your changes have been saved",
141 "settings.account.tryReloadServices": "Try again",
142 "settings.account.tryReloadUserInfoRequest": "Try again",
143 "settings.account.userInfoRequestFailed": "Could not load user information",
144 "settings.app.buttonClearAllCache": "Clear cache",
145 "settings.app.buttonInstallUpdate": "Restart & install update",
146 "settings.app.buttonSearchForUpdate": "Check for updates",
147 "settings.app.cacheInfo": "Franz cache is currently using {size} of disk space.",
148 "settings.app.currentVersion": "Current version:",
149 "settings.app.form.autoLaunchInBackground": "Open in background",
150 "settings.app.form.autoLaunchOnStart": "Launch Franz on start",
151 "settings.app.form.beta": "Include beta versions",
152 "settings.app.form.darkMode": "Join the Dark Side",
153 "settings.app.form.enableGPUAcceleration": "Enable GPU Acceleration",
154 "settings.app.form.enableSpellchecking": "Enable spell checking",
155 "settings.app.form.enableSystemTray": "Show Franz in system tray",
156 "settings.app.form.language": "Language",
157 "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray",
158 "settings.app.form.runInBackground": "Keep Franz in background when closing the window",
159 "settings.app.form.showDisabledServices": "Display disabled services tabs",
160 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled",
161 "settings.app.headline": "Settings",
162 "settings.app.headlineAdvanced": "Advanced",
163 "settings.app.headlineAppearance": "Appearance",
164 "settings.app.headlineGeneral": "General",
165 "settings.app.headlineLanguage": "Language",
166 "settings.app.headlineUpdates": "Updates",
167 "settings.app.languageDisclaimer": "Official translations are English & German. All other languages are community based translations.",
168 "settings.app.restartRequired": "Changes require restart",
169 "settings.app.subheadlineCache": "Cache",
170 "settings.app.translationHelp": "Help us to translate Franz into your language.",
171 "settings.app.updateStatusAvailable": "Update available, downloading...",
172 "settings.app.updateStatusSearching": "Is searching for update",
173 "settings.app.updateStatusUpToDate": "You are using the latest version of Franz",
93 "settings.invite.headline": "Invite Friends", 174 "settings.invite.headline": "Invite Friends",
94 "settings.navigation.availableServices": "Available services",
95 "settings.navigation.yourServices": "Your services",
96 "settings.navigation.account": "Account", 175 "settings.navigation.account": "Account",
97 "settings.navigation.settings": "Settings", 176 "settings.navigation.availableServices": "Available services",
98 "settings.navigation.inviteFriends": "Invite Friends", 177 "settings.navigation.inviteFriends": "Invite Friends",
99 "settings.navigation.logout": "Logout", 178 "settings.navigation.logout": "Logout",
100 "settings.recipes.headline": "Available services", 179 "settings.navigation.settings": "Settings",
101 "settings.recipes.mostPopular": "Most popular", 180 "settings.navigation.team": "Manage Team",
181 "settings.navigation.yourServices": "Your services",
182 "settings.navigation.yourWorkspaces": "Your workspaces",
102 "settings.recipes.all": "All services", 183 "settings.recipes.all": "All services",
103 "settings.recipes.dev": "Development", 184 "settings.recipes.dev": "Development",
185 "settings.recipes.headline": "Available services",
186 "settings.recipes.missingService": "Missing a service?",
187 "settings.recipes.mostPopular": "Most popular",
104 "settings.recipes.nothingFound": "Sorry, but no service matched your search term.", 188 "settings.recipes.nothingFound": "Sorry, but no service matched your search term.",
105 "settings.recipes.servicesSuccessfulAddedInfo": "Service successfully added", 189 "settings.recipes.servicesSuccessfulAddedInfo": "Service successfully added",
106 "settings.recipes.missingService": "Missing a service?", 190 "settings.searchService": "Search service",
107 "settings.service.form.saveButton": "Save service", 191 "settings.service.error.goBack": "Back to services",
108 "settings.service.form.deleteButton": "Delete service", 192 "settings.service.error.headline": "Error",
109 "settings.service.form.availableServices": "Available services", 193 "settings.service.error.message": "Could not load service recipe.",
110 "settings.service.form.yourServices": "Your services",
111 "settings.service.form.addServiceHeadline": "Add {name}", 194 "settings.service.form.addServiceHeadline": "Add {name}",
112 "settings.service.form.editServiceHeadline": "Edit {name}", 195 "settings.service.form.availableServices": "Available services",
113 "settings.service.form.tabHosted": "Hosted", 196 "settings.service.form.customUrl": "Custom server",
114 "settings.service.form.tabOnPremise": "Self hosted â­ï¸",
115 "settings.service.form.useHostedService": "Use the hosted {name} service.",
116 "settings.service.form.customUrlValidationError": "Could not validate custom {name} server.",
117 "settings.service.form.customUrlPremiumInfo": "To add self hosted services, you need a Franz Premium Supporter Account.", 197 "settings.service.form.customUrlPremiumInfo": "To add self hosted services, you need a Franz Premium Supporter Account.",
118 "settings.service.form.customUrlUpgradeAccount": "Upgrade your account", 198 "settings.service.form.customUrlUpgradeAccount": "Upgrade your account",
119 "settings.service.form.indirectMessageInfo": "You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", 199 "settings.service.form.customUrlValidationError": "Could not validate custom {name} server.",
120 "settings.service.form.name": "Name", 200 "settings.service.form.deleteButton": "Delete service",
121 "settings.service.form.enableService": "Enable service", 201 "settings.service.form.editServiceHeadline": "Edit {name}",
122 "settings.service.form.enableNotification": "Enable notifications",
123 "settings.service.form.enableBadge": "Show unread message badges",
124 "settings.service.form.team": "Team",
125 "settings.service.form.customUrl": "Custom server",
126 "settings.service.form.indirectMessages": "Show message badge for all new messages",
127 "settings.service.form.enableAudio": "Enable audio", 202 "settings.service.form.enableAudio": "Enable audio",
128 "settings.service.form.isMutedInfo": "When disabled, all notification sounds and audio playback are muted", 203 "settings.service.form.enableBadge": "Show unread message badges",
129 "settings.service.form.headlineNotifications": "Notifications", 204 "settings.service.form.enableDarkMode": "Enable Dark Mode",
205 "settings.service.form.enableNotification": "Enable notifications",
206 "settings.service.form.enableService": "Enable service",
130 "settings.service.form.headlineBadges": "Unread message badges", 207 "settings.service.form.headlineBadges": "Unread message badges",
131 "settings.service.form.headlineGeneral": "General", 208 "settings.service.form.headlineGeneral": "General",
209 "settings.service.form.headlineNotifications": "Notifications",
132 "settings.service.form.icon": "Custom icon", 210 "settings.service.form.icon": "Custom icon",
133 "settings.service.form.iconDelete": "Delete", 211 "settings.service.form.iconDelete": "Delete",
134 "settings.service.form.iconUpload": "Drop your image, or click here", 212 "settings.service.form.iconUpload": "Drop your image, or click here",
135 "settings.service.form.enableDarkMode": "Enable Dark Mode", 213 "settings.service.form.indirectMessageInfo": "You will be notified about all new messages in a channel, not just @username, @channel, @here, ...",
214 "settings.service.form.indirectMessages": "Show message badge for all new messages",
215 "settings.service.form.isMutedInfo": "When disabled, all notification sounds and audio playback are muted",
216 "settings.service.form.name": "Name",
136 "settings.service.form.proxy.headline": "HTTP/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline": "HTTP/HTTPS Proxy Settings",
137 "settings.service.form.proxy.isEnabled": "Use Proxy",
138 "settings.service.form.proxy.host": "Proxy Host/IP", 218 "settings.service.form.proxy.host": "Proxy Host/IP",
139 "settings.service.form.proxy.port": "Port",
140 "settings.service.form.proxy.user": "User (optional)",
141 "settings.service.form.proxy.password": "Password (optional)",
142 "settings.service.form.proxy.info": "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info": "Proxy settings will not synced with the Franz servers.",
220 "settings.service.form.proxy.isEnabled": "Use Proxy",
221 "settings.service.form.proxy.password": "Password (optional)",
222 "settings.service.form.proxy.port": "Port",
143 "settings.service.form.proxy.restartInfo": "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo": "Please restart Franz after changing proxy Settings.",
144 "settings.service.form.spellcheckerLanguage": "Spell checking Language", 224 "settings.service.form.proxy.user": "User (optional)",
145 "settings.service.form.spellcheckerLanguage.default": "Use System Default ({default})", 225 "settings.service.form.saveButton": "Save service",
146 "settings.service.error.headline": "Error", 226 "settings.service.form.tabHosted": "Hosted",
147 "settings.service.error.goBack": "Back to services", 227 "settings.service.form.tabOnPremise": "Self hosted â­ï¸",
148 "settings.service.error.message": "Could not load service recipe.", 228 "settings.service.form.team": "Team",
149 "settings.services.tooltip.isDisabled": "Service is disabled", 229 "settings.service.form.useHostedService": "Use the hosted {name} service.",
150 "settings.services.tooltip.notificationsDisabled": "Notifications are disabled", 230 "settings.service.form.yourServices": "Your services",
151 "settings.services.tooltip.isMuted": "All sounds are muted", 231 "settings.services.deletedInfo": "Service has been deleted",
232 "settings.services.discoverServices": "Discover services",
152 "settings.services.headline": "Your services", 233 "settings.services.headline": "Your services",
153 "settings.services.noServicesAdded": "You haven't added any services yet.", 234 "settings.services.noServicesAdded": "You haven't added any services yet.",
154 "settings.services.discoverServices": "Discover services", 235 "settings.services.servicesRequestFailed": "Could not load your services",
236 "settings.services.tooltip.isDisabled": "Service is disabled",
237 "settings.services.tooltip.isMuted": "All sounds are muted",
238 "settings.services.tooltip.notificationsDisabled": "Notifications are disabled",
155 "settings.services.updatedInfo": "Your changes have been saved", 239 "settings.services.updatedInfo": "Your changes have been saved",
156 "settings.services.deletedInfo": "Service has been deleted", 240 "settings.team.contentHeadline": "Franz for Teams",
157 "settings.app.headline": "Settings", 241 "settings.team.copy": "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
158 "settings.app.headlineGeneral": "General", 242 "settings.team.headline": "Team",
159 "settings.app.headlineLanguage": "Language", 243 "settings.team.intro": "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
160 "settings.app.headlineUpdates": "Updates", 244 "settings.team.manageAction": "Manage your Team on meetfranz.com",
161 "settings.app.headlineAppearance": "Appearance", 245 "settings.team.upgradeAction": "Upgrade your Account",
162 "settings.app.headlineAdvanced": "Advanced", 246 "settings.user.form.accountType.company": "Company",
163 "settings.app.buttonSearchForUpdate": "Check for updates", 247 "settings.user.form.accountType.individual": "Individual",
164 "settings.app.buttonInstallUpdate": "Restart & install update", 248 "settings.user.form.accountType.label": "Account type",
165 "settings.app.updateStatusSearching": "Is searching for update", 249 "settings.user.form.accountType.non-profit": "Non-Profit",
166 "settings.app.updateStatusAvailable": "Update available, downloading...", 250 "settings.user.form.currentPassword": "Current password",
167 "settings.app.updateStatusUpToDate": "You are using the latest version of Franz", 251 "settings.user.form.email": "Email",
168 "settings.app.subheadlineCache": "Cache",
169 "settings.app.cacheInfo": "Franz cache is currently using {size} of disk space.",
170 "settings.app.buttonClearAllCache": "Clear cache",
171 "settings.app.form.autoLaunchOnStart": "Launch Franz on start",
172 "settings.app.form.autoLaunchInBackground": "Open in background",
173 "settings.app.form.enableSystemTray": "Show Franz in system tray",
174 "settings.app.form.darkMode": "Join the Dark Side",
175 "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray",
176 "settings.app.form.enableMenuBar": "Show Franz in Menu Bar",
177 "settings.app.form.hideDockIcon": "Hide Franz icon in Dock",
178 "settings.app.form.runInBackground": "Keep Franz in background when closing the window",
179 "settings.app.form.language": "Language",
180 "settings.app.form.enableSpellchecking": "Enable spell checking",
181 "settings.app.form.spellcheckerLanguage": "Spell checking language",
182 "settings.app.form.enableGPUAcceleration": "Enable GPU Acceleration",
183 "settings.app.form.showDisabledServices": "Display disabled services tabs",
184 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled",
185 "settings.app.form.beta": "Include beta versions",
186 "settings.app.translationHelp": "Help us to translate Franz into your language.",
187 "settings.app.currentVersion": "Current version:",
188 "settings.app.restartRequired": "Changes require restart",
189 "settings.user.form.firstname": "First Name", 252 "settings.user.form.firstname": "First Name",
190 "settings.user.form.lastname": "Last Name", 253 "settings.user.form.lastname": "Last Name",
191 "settings.user.form.email": "Email",
192 "settings.user.form.currentPassword": "Current password",
193 "settings.user.form.newPassword": "New password", 254 "settings.user.form.newPassword": "New password",
194 "settings.user.form.accountType.label": "Account type", 255 "settings.workspace.add.form.name": "Name",
195 "settings.user.form.accountType.individual": "Individual", 256 "settings.workspace.add.form.submitButton": "Create workspace",
196 "settings.user.form.accountType.non-profit": "Non-Profit", 257 "settings.workspace.form.buttonDelete": "Delete workspace",
197 "settings.user.form.accountType.company": "Company", 258 "settings.workspace.form.buttonSave": "Save workspace",
259 "settings.workspace.form.name": "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline": "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces": "Your workspaces",
262 "settings.workspaces.deletedInfo": "Workspace has been deleted",
263 "settings.workspaces.headline": "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded": "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces": "Try again",
266 "settings.workspaces.updatedInfo": "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline": "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo": "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed": "Could not load your workspaces",
270 "sidebar.addNewService": "Add new service",
271 "sidebar.closeWorkspaceDrawer": "Close workspace drawer",
272 "sidebar.muteApp": "Disable notifications & audio",
273 "sidebar.openWorkspaceDrawer": "Open workspace drawer",
274 "sidebar.settings": "Settings",
275 "sidebar.unmuteApp": "Enable notifications & audio",
276 "signup.company.label": "Company",
277 "signup.email.label": "Email address",
278 "signup.emailDuplicate": "A user with that email address already exists",
279 "signup.firstname.label": "First Name",
280 "signup.headline": "Sign up",
281 "signup.lastname.label": "Last Name",
282 "signup.legal.info": "By creating a Franz account you accept the",
283 "signup.legal.privacy": "Privacy Statement",
284 "signup.legal.terms": "Terms of service",
285 "signup.link.login": "Already have an account, sign in?",
286 "signup.password.label": "Password",
287 "signup.submit.label": "Create account",
288 "subscription.euTaxInfo": "EU residents: local sales tax may apply",
289 "subscription.features.ads": "No ads, ever!",
290 "subscription.features.comingSoon": "coming soon",
291 "subscription.features.noInterruptions": "No app delays & nagging to upgrade license",
292 "subscription.features.onpremise.mattermost": "Add on-premise/hosted services like Mattermost",
293 "subscription.features.proxy": "Proxy support for services",
294 "subscription.features.spellchecker": "Support for spellchecker",
295 "subscription.features.workspaces": "Organize your services in workspaces",
296 "subscription.includedFeatures": "Paid Franz Premium Supporter Account includes",
297 "subscription.paymentSessionError": "Could not initialize payment form",
298 "subscription.submit.label": "I want to support the development of Franz",
198 "subscription.type.free": "free", 299 "subscription.type.free": "free",
199 "subscription.type.month": "month", 300 "subscription.type.month": "month",
200 "subscription.type.year": "year", 301 "subscription.type.year": "year",
201 "subscription.euTaxInfo": "EU residents: local sales tax may apply",
202 "subscriptionPopup.buttonCancel": "Cancel", 302 "subscriptionPopup.buttonCancel": "Cancel",
203 "subscriptionPopup.buttonDone": "Done", 303 "subscriptionPopup.buttonDone": "Done",
204 "tabs.item.reload": "Reload", 304 "tabs.item.deleteService": "Delete service",
205 "tabs.item.edit": "Edit",
206 "tabs.item.disableNotifications": "Disable notifications",
207 "tabs.item.enableNotification": "Enable notifications",
208 "tabs.item.disableAudio": "Disable audio", 305 "tabs.item.disableAudio": "Disable audio",
209 "tabs.item.enableAudio": "Enable audio", 306 "tabs.item.disableNotifications": "Disable notifications",
210 "tabs.item.disableService": "Disable service", 307 "tabs.item.disableService": "Disable service",
308 "tabs.item.edit": "Edit",
309 "tabs.item.enableAudio": "Enable audio",
310 "tabs.item.enableNotification": "Enable notifications",
211 "tabs.item.enableService": "Enable service", 311 "tabs.item.enableService": "Enable service",
212 "tabs.item.deleteService": "Delete service", 312 "tabs.item.reload": "Reload",
213 "service.crashHandler.headline": "Oh no!",
214 "service.crashHandler.text": "{name} has caused an error.",
215 "service.crashHandler.action": "Reload {name}",
216 "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds",
217 "service.errorHandler.headline": "Oh no!",
218 "service.errorHandler.text": "{name} has failed to load.",
219 "service.errorHandler.message": "Error",
220 "service.errorHandler.action": "Reload {name}",
221 "service.errorHandler.editAction": "Edit {name}",
222 "service.disabledHandler.headline": "{name} is disabled",
223 "service.disabledHandler.action": "Enable {name}",
224 "menu.edit": "Edit",
225 "menu.edit.undo": "Undo",
226 "menu.edit.redo": "Redo",
227 "menu.edit.cut": "Cut",
228 "menu.edit.copy": "Copy",
229 "menu.edit.paste": "Paste",
230 "menu.edit.pasteAndMatchStyle": "Paste And Match Style",
231 "menu.edit.delete": "Delete",
232 "menu.edit.selectAll": "Select All",
233 "menu.edit.speech": "Speech",
234 "menu.edit.startSpeaking": "Start Speaking",
235 "menu.edit.stopSpeaking": "Stop Speaking",
236 "menu.edit.startDictation": "Start Dictation",
237 "menu.edit.emojiSymbols": "Emoji & Symbols",
238 "menu.view.resetZoom": "Actual Size",
239 "menu.view.zoomIn": "Zoom In",
240 "menu.view.zoomOut": "Zoom Out",
241 "menu.view.enterFullScreen": "Enter Full Screen",
242 "menu.view.exitFullScreen": "Exit Full Screen",
243 "menu.view.toggleFullScreen": "Toggle Full Screen",
244 "menu.view.toggleDevTools": "Toggle Developer Tools",
245 "menu.view.toggleServiceDevTools": "Toggle Service Developer Tools",
246 "menu.view.reloadService": "Reload Service",
247 "menu.view.reloadFranz": "Reload Franz",
248 "menu.window.minimize": "Minimize",
249 "menu.window.close": "Close",
250 "menu.help.learnMore": "Learn More",
251 "menu.help.changelog": "Changelog",
252 "menu.help.support": "Support",
253 "menu.help.tos": "Terms of Service",
254 "menu.help.privacy": "Privacy Statement",
255 "menu.file": "File",
256 "menu.view": "View",
257 "menu.services": "Services",
258 "menu.window": "Window",
259 "menu.help": "Help",
260 "menu.app.about": "About Franz",
261 "menu.app.settings": "Settings",
262 "menu.app.hide": "Hide",
263 "menu.app.hideOthers": "Hide Others",
264 "menu.app.unhide": "Unhide",
265 "menu.app.quit": "Quit",
266 "menu.services.addNewService": "Add New Service...",
267 "validation.required": "{field} is required",
268 "validation.email": "{field} is not valid", 313 "validation.email": "{field} is not valid",
269 "validation.url": "{field} is not a valid URL",
270 "validation.minLength": "{field} should be at least {length} characters long", 314 "validation.minLength": "{field} should be at least {length} characters long",
271 "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", 315 "validation.oneRequired": "At least one is required",
272 "feature.delayApp.action": "Get a Franz Supporter License", 316 "validation.required": "{field} is required",
273 "feature.delayApp.text": "Franz will continue in {seconds} seconds.", 317 "validation.url": "{field} is not a valid URL",
274 "premiumFeature.button.upgradeAccount": "Upgrade account", 318 "welcome.loginButton": "Login to your account",
275 "app.errorHandler.headline": "Something went wrong", 319 "welcome.signupButton": "Create a free account",
276 "app.errorHandler.action": "Reload" 320 "workspaceDrawer.addNewWorkspaceLabel": "Add new workspace",
277} 321 "workspaceDrawer.allServices": "All services",
322 "workspaceDrawer.headline": "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit": "edit",
324 "workspaceDrawer.item.noServicesAddedYet": "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel": "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge": "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel": "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo": "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>",
329 "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo": "Switching to"
331} \ No newline at end of file
diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json
index 669b4d2dd..4167a5c7d 100644
--- a/src/i18n/locales/es.json
+++ b/src/i18n/locales/es.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Recargar", 2 "app.errorHandler.action" : "Recargar",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Ha surgido un error",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Consigue una Licencia de Soporte de Franz", 5 "feature.delayApp.action" : "Consigue una Licencia de Soporte de Franz",
5 "feature.delayApp.headline" : "Por favor, compra una Licencia de Soporte de Franz para saltar la espera", 6 "feature.delayApp.headline" : "Por favor, compra una Licencia de Soporte de Franz para saltar la espera",
6 "feature.delayApp.text" : "Franz continuará en {seconds} segundos.", 7 "feature.delayApp.text" : "Franz continuará en {seconds} segundos.",
8 "feature.shareFranz.action.email" : "Envía como correo",
9 "feature.shareFranz.action.facebook" : "Compartir en Facebook",
10 "feature.shareFranz.action.twitter" : "Compartir en Twitter",
11 "feature.shareFranz.headline" : "¡Juntos mejoramos Franz!",
12 "feature.shareFranz.shareText.email" : "¡He añadido {count} servicios a Franz! Obtén la aplicación gratuita para WhatsApp, Messenger, Slack, Skype en www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Dile a tus amigos y colegas lo asombroso que es Franz y ayúdanos a correr la voz.",
7 "global.api.unhealthy" : "No es posible conectarse a los servicios en línea de Franz.", 15 "global.api.unhealthy" : "No es posible conectarse a los servicios en línea de Franz.",
8 "global.notConnectedToTheInternet" : "No estás conectado a Internet", 16 "global.notConnectedToTheInternet" : "No estás conectado a Internet",
17 "global.spellchecker.useDefault" : "Utilizar estándar del sistema ({default})",
18 "global.spellchecking.autodetect" : "Detectar el idioma automáticamente",
19 "global.spellchecking.autodetect.short" : "Automático",
20 "global.spellchecking.language" : "Corrector de ortografía",
9 "import.headline" : "Importa tus servicios de Franz 4", 21 "import.headline" : "Importa tus servicios de Franz 4",
10 "import.notSupportedHeadline" : "Servicios no admitidos aún en Franz 5", 22 "import.notSupportedHeadline" : "Servicios no admitidos aún en Franz 5",
11 "import.skip.label" : "Quiero agregar servicios manualmente", 23 "import.skip.label" : "Quiero agregar servicios manualmente",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Iniciar sesión", 44 "login.submit.label" : "Iniciar sesión",
33 "login.tokenExpired" : "Tu sesión ha expirado, por favor inicia sesión de nuevo.", 45 "login.tokenExpired" : "Tu sesión ha expirado, por favor inicia sesión de nuevo.",
34 "menu.app.about" : "Sobre Franz", 46 "menu.app.about" : "Sobre Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Ocultar", 48 "menu.app.hide" : "Ocultar",
36 "menu.app.hideOthers" : "Ocultar otros", 49 "menu.app.hideOthers" : "Ocultar otros",
37 "menu.app.quit" : "Salir", 50 "menu.app.quit" : "Salir",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Ayuda técnica", 72 "menu.help.support" : "Ayuda técnica",
60 "menu.help.tos" : "Términos del Servicio", 73 "menu.help.tos" : "Términos del Servicio",
61 "menu.services" : "Servicios", 74 "menu.services" : "Servicios",
75 "menu.services.activatePreviousService" : "Activa el servicio previo",
62 "menu.services.addNewService" : "Añadir Nuevo Servicio...", 76 "menu.services.addNewService" : "Añadir Nuevo Servicio...",
77 "menu.services.setNextServiceActive" : "Activa el siguiente servicio",
63 "menu.view" : "Mostrar", 78 "menu.view" : "Mostrar",
64 "menu.view.enterFullScreen" : "Pasar a pantalla completa", 79 "menu.view.enterFullScreen" : "Pasar a pantalla completa",
65 "menu.view.exitFullScreen" : "Salir de Pantalla Completa", 80 "menu.view.exitFullScreen" : "Salir de Pantalla Completa",
@@ -74,6 +89,11 @@
74 "menu.window" : "Ventana", 89 "menu.window" : "Ventana",
75 "menu.window.close" : "Cerrar", 90 "menu.window.close" : "Cerrar",
76 "menu.window.minimize" : "Minimizar", 91 "menu.window.minimize" : "Minimizar",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Todos los servicios",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Dirección de correo electrónico", 97 "password.email.label" : "Dirección de correo electrónico",
78 "password.headline" : "Restablecer contraseña", 98 "password.headline" : "Restablecer contraseña",
79 "password.link.login" : "Inicia sesión en tu cuenta", 99 "password.link.login" : "Inicia sesión en tu cuenta",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Editar {name}", 116 "service.errorHandler.editAction" : "Editar {name}",
97 "service.errorHandler.headline" : "¡Oh, no!", 117 "service.errorHandler.headline" : "¡Oh, no!",
98 "service.errorHandler.message" : "Error", 118 "service.errorHandler.message" : "Error",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} ha fallado la carga",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Primeros pasos", 121 "services.getStarted" : "Primeros pasos",
101 "services.welcome" : "Bienvenido a Franz", 122 "services.welcome" : "Bienvenido a Franz",
102 "settings.account.account.editButton" : "Editar cuenta", 123 "settings.account.account.editButton" : "Editar cuenta",
@@ -117,7 +138,8 @@
117 "settings.account.invoiceDownload" : "Descargar", 138 "settings.account.invoiceDownload" : "Descargar",
118 "settings.account.manageSubscription.label" : "Administra tu suscripción", 139 "settings.account.manageSubscription.label" : "Administra tu suscripción",
119 "settings.account.successInfo" : "Tus cambios han sido guardados", 140 "settings.account.successInfo" : "Tus cambios han sido guardados",
120 "settings.account.tryReloadUserInfoRequest" : "Intentar de nuevo", 141 "settings.account.tryReloadServices" : "Intentar de nuevo",
142 "settings.account.tryReloadUserInfoRequest" : "Intenta de nuevo",
121 "settings.account.userInfoRequestFailed" : "No se pudo cargar la información de usuario", 143 "settings.account.userInfoRequestFailed" : "No se pudo cargar la información de usuario",
122 "settings.app.buttonClearAllCache" : "Limpiar caché", 144 "settings.app.buttonClearAllCache" : "Limpiar caché",
123 "settings.app.buttonInstallUpdate" : "Reiniciar e instalar actualizaciones", 145 "settings.app.buttonInstallUpdate" : "Reiniciar e instalar actualizaciones",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Incluir versiones beta", 151 "settings.app.form.beta" : "Incluir versiones beta",
130 "settings.app.form.darkMode" : "Únete al Lado Oscuro", 152 "settings.app.form.darkMode" : "Únete al Lado Oscuro",
131 "settings.app.form.enableGPUAcceleration" : "Habilitar aceleración de GPU", 153 "settings.app.form.enableGPUAcceleration" : "Habilitar aceleración de GPU",
132 "settings.app.form.enableMenuBar" : "Mostrar a Franz en la barra de menús",
133 "settings.app.form.enableSpellchecking" : "Activar corrección ortográfica", 154 "settings.app.form.enableSpellchecking" : "Activar corrección ortográfica",
134 "settings.app.form.enableSystemTray" : "Mostrar Franz en la bandeja del sistema", 155 "settings.app.form.enableSystemTray" : "Mostrar Franz en la bandeja del sistema",
135 "settings.app.form.hideDockIcon" : "Ocultar Icono de Franz en barra de herramientas",
136 "settings.app.form.language" : "Idioma", 156 "settings.app.form.language" : "Idioma",
137 "settings.app.form.minimizeToSystemTray" : "Minimizar Franz a la bandeja del sistema", 157 "settings.app.form.minimizeToSystemTray" : "Minimizar Franz a la bandeja del sistema",
138 "settings.app.form.runInBackground" : "Mantener Franz en segundo plano al cerrar la ventana", 158 "settings.app.form.runInBackground" : "Mantener Franz en segundo plano al cerrar la ventana",
139 "settings.app.form.showDisabledServices" : "Mostrar pestañas de servicios desactivados", 159 "settings.app.form.showDisabledServices" : "Mostrar pestañas de servicios desactivados",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostrar la insignia de mensajes sin leer cuando las notificaciones están desactivadas", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostrar la insignia de mensajes sin leer cuando las notificaciones están desactivadas",
141 "settings.app.form.spellcheckerLanguage" : "Corrector de ortografía",
142 "settings.app.headline" : "Configuración", 161 "settings.app.headline" : "Configuración",
143 "settings.app.headlineAdvanced" : "Avanzado", 162 "settings.app.headlineAdvanced" : "Avanzado",
144 "settings.app.headlineAppearance" : "Apariencia", 163 "settings.app.headlineAppearance" : "Apariencia",
145 "settings.app.headlineGeneral" : "General", 164 "settings.app.headlineGeneral" : "General",
146 "settings.app.headlineLanguage" : "Idioma", 165 "settings.app.headlineLanguage" : "Idioma",
147 "settings.app.headlineUpdates" : "Actualizaciones", 166 "settings.app.headlineUpdates" : "Actualizaciones",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Los cambios requieren reiniciar", 168 "settings.app.restartRequired" : "Los cambios requieren reiniciar",
149 "settings.app.subheadlineCache" : "Caché", 169 "settings.app.subheadlineCache" : "Caché",
150 "settings.app.translationHelp" : "Ayúdanos a traducir Franz a tu idioma.", 170 "settings.app.translationHelp" : "Ayúdanos a traducir Franz a tu idioma.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Invita a tus amigos", 177 "settings.navigation.inviteFriends" : "Invita a tus amigos",
158 "settings.navigation.logout" : "Cerrar sesión", 178 "settings.navigation.logout" : "Cerrar sesión",
159 "settings.navigation.settings" : "Configuración", 179 "settings.navigation.settings" : "Configuración",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Tus servicios", 181 "settings.navigation.yourServices" : "Tus servicios",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Todos los servicios", 183 "settings.recipes.all" : "Todos los servicios",
162 "settings.recipes.dev" : "Desarrollo", 184 "settings.recipes.dev" : "Desarrollo",
163 "settings.recipes.headline" : "Servicios disponibles", 185 "settings.recipes.headline" : "Servicios disponibles",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Mostrar señal de notificación para todos los mensajes nuevos", 214 "settings.service.form.indirectMessages" : "Mostrar señal de notificación para todos los mensajes nuevos",
193 "settings.service.form.isMutedInfo" : "Cuando estén desactivados, todos los sonidos de notificación y la reproducción de audio serán silenciados", 215 "settings.service.form.isMutedInfo" : "Cuando estén desactivados, todos los sonidos de notificación y la reproducción de audio serán silenciados",
194 "settings.service.form.name" : "Nombre", 216 "settings.service.form.name" : "Nombre",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Ajustes Proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Las configuraciones de Proxy no se sincronizarán con los servidores de Franz.", 219 "settings.service.form.proxy.info" : "Las configuraciones de Proxy no se sincronizarán con los servidores de Franz.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Use Proxy",
199 "settings.service.form.proxy.password" : "Contraseña (opcional)", 221 "settings.service.form.proxy.password" : "Contraseña (opcional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Puerto",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Por favor reinicie Franz despues de modificar los ajustes proxy.",
202 "settings.service.form.proxy.user" : "Usuario (opcional)", 224 "settings.service.form.proxy.user" : "Usuario (opcional)",
203 "settings.service.form.saveButton" : "Guardar servicio", 225 "settings.service.form.saveButton" : "Guardar servicio",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Alojado", 226 "settings.service.form.tabHosted" : "Alojado",
207 "settings.service.form.tabOnPremise" : "Auto alojado â­ï¸", 227 "settings.service.form.tabOnPremise" : "Auto alojado â­ï¸",
208 "settings.service.form.team" : "Equipo", 228 "settings.service.form.team" : "Equipo",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Descubrir servicios", 232 "settings.services.discoverServices" : "Descubrir servicios",
213 "settings.services.headline" : "Tus servicios", 233 "settings.services.headline" : "Tus servicios",
214 "settings.services.noServicesAdded" : "No has añadido ningún servicio aún.", 234 "settings.services.noServicesAdded" : "No has añadido ningún servicio aún.",
235 "settings.services.servicesRequestFailed" : "No pudo cargar tus servicios",
215 "settings.services.tooltip.isDisabled" : "El servicio está desactivado", 236 "settings.services.tooltip.isDisabled" : "El servicio está desactivado",
216 "settings.services.tooltip.isMuted" : "Todos los sonidos están silenciados", 237 "settings.services.tooltip.isMuted" : "Todos los sonidos están silenciados",
217 "settings.services.tooltip.notificationsDisabled" : "Las notificaciones están desactivadas", 238 "settings.services.tooltip.notificationsDisabled" : "Las notificaciones están desactivadas",
218 "settings.services.updatedInfo" : "Tus cambios han sido guardados", 239 "settings.services.updatedInfo" : "Tus cambios han sido guardados",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Equipo",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Empresa", 246 "settings.user.form.accountType.company" : "Empresa",
220 "settings.user.form.accountType.individual" : "Individual", 247 "settings.user.form.accountType.individual" : "Individual",
221 "settings.user.form.accountType.label" : "Tipo de cuenta", 248 "settings.user.form.accountType.label" : "Tipo de cuenta",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Nombre", 252 "settings.user.form.firstname" : "Nombre",
226 "settings.user.form.lastname" : "Apellido", 253 "settings.user.form.lastname" : "Apellido",
227 "settings.user.form.newPassword" : "Nueva contraseña", 254 "settings.user.form.newPassword" : "Nueva contraseña",
255 "settings.workspace.add.form.name" : "Nombre",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Nombre",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Try again",
266 "settings.workspaces.updatedInfo" : "Tus cambios han sido guardados",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Añadir nuevo servicio", 270 "sidebar.addNewService" : "Añadir nuevo servicio",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Desactivar notificaciones y sonido", 272 "sidebar.muteApp" : "Desactivar notificaciones y sonido",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Configuración", 274 "sidebar.settings" : "Configuración",
231 "sidebar.unmuteApp" : "Activar notificaciones y sonido", 275 "sidebar.unmuteApp" : "Activar notificaciones y sonido",
232 "signup.company.label" : "Compañía", 276 "signup.company.label" : "Compañía",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Residentes de la UE: pueden aplicarse impuestos locales", 288 "subscription.euTaxInfo" : "Residentes de la UE: pueden aplicarse impuestos locales",
245 "subscription.features.ads" : "¡Sin publicidad, para siempre!", 289 "subscription.features.ads" : "¡Sin publicidad, para siempre!",
246 "subscription.features.comingSoon" : "próximamente", 290 "subscription.features.comingSoon" : "próximamente",
247 "subscription.features.encryptedSync" : "Sincronización de sesión encriptada",
248 "subscription.features.noInterruptions" : "Sin retrasos en la app ni molestas actualizaciones de licencias", 291 "subscription.features.noInterruptions" : "Sin retrasos en la app ni molestas actualizaciones de licencias",
249 "subscription.features.onpremise" : "Añade servicios locales\/autoalojados como HipChat",
250 "subscription.features.onpremise.mattermost" : "Agregar servicios de almacenamiento como Mattermost", 292 "subscription.features.onpremise.mattermost" : "Agregar servicios de almacenamiento como Mattermost",
251 "subscription.features.proxy" : "Soporte Proxy para servicios", 293 "subscription.features.proxy" : "Soporte Proxy para servicios",
252 "subscription.features.spellchecker" : "Soporte para corrector de ortografía", 294 "subscription.features.spellchecker" : "Soporte para corrector de ortografía",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "La Cuenta pagada de Colaborador Premium de Franz incluye", 296 "subscription.includedFeatures" : "La Cuenta pagada de Colaborador Premium de Franz incluye",
254 "subscription.paymentSessionError" : "No se pudo inicializar el formulario de pago", 297 "subscription.paymentSessionError" : "No se pudo inicializar el formulario de pago",
255 "subscription.submit.label" : "Quiero apoyar el desarrollo de Franz", 298 "subscription.submit.label" : "Quiero apoyar el desarrollo de Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Recargar", 312 "tabs.item.reload" : "Recargar",
270 "validation.email" : "{field} no es válido", 313 "validation.email" : "{field} no es válido",
271 "validation.minLength" : "{field} debería tener al menos {length} caracteres", 314 "validation.minLength" : "{field} debería tener al menos {length} caracteres",
315 "validation.oneRequired" : "Al menos uno es requerido",
272 "validation.required" : "{field} es obligatorio", 316 "validation.required" : "{field} es obligatorio",
273 "validation.url" : "{field} no es una URL válida", 317 "validation.url" : "{field} no es una URL válida",
274 "welcome.loginButton" : "Accede a tu cuenta", 318 "welcome.loginButton" : "Accede a tu cuenta",
275 "welcome.signupButton" : "Crear una cuenta gratuita", 319 "welcome.signupButton" : "Crear una cuenta gratuita",
276 "welcome.slogan" : "Mensajería que funciona para ti" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Todos los servicios",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json
index a83767f1e..2bd5326c0 100644
--- a/src/i18n/locales/fr.json
+++ b/src/i18n/locales/fr.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Recharger", 2 "app.errorHandler.action" : "Recharger",
3 "app.errorHandler.headline" : "Une erreur s'est produite.", 3 "app.errorHandler.headline" : "Une erreur s'est produite",
4 "feature.announcements.changelog.headline" : "Changements dans Franz {version}",
4 "feature.delayApp.action" : "Obtenez une licence de Supporter Franz", 5 "feature.delayApp.action" : "Obtenez une licence de Supporter Franz",
5 "feature.delayApp.headline" : "Veuillez acheter une licence de Supporter Franz pour sauter le temps d'attente", 6 "feature.delayApp.headline" : "Veuillez acheter une licence de Supporter Franz pour sauter le temps d'attente",
6 "feature.delayApp.text" : "Franz continuera dans {seconds} secondes.", 7 "feature.delayApp.text" : "Franz reprendra dans {seconds} secondes.",
8 "feature.shareFranz.action.email" : "Envoyer par mail",
9 "feature.shareFranz.action.facebook" : "Partager sur Facebook",
10 "feature.shareFranz.action.twitter" : "Partager sur Twitter",
11 "feature.shareFranz.headline" : "Franz est meilleur quand on est tous ensemble !",
12 "feature.shareFranz.shareText.email" : "J'ai ajouté {count} services à Franz ! Télécharger l'appli gratuite pour WhatsApp, Messenger, Skype et cie sur www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "J'ai ajouté {count} services à Franz! Télécharge l'application gratuite pour WhatsApp, Messenger, Slack, Skype et compagnie sur www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Dites à vos amis et collègues combien Franz est super et aidez nous à faire passer le mot.",
7 "global.api.unhealthy" : "Impossible de se connecter aux services en ligne de Franz", 15 "global.api.unhealthy" : "Impossible de se connecter aux services en ligne de Franz",
8 "global.notConnectedToTheInternet" : "Vous n'êtes pas connecté à Internet.", 16 "global.notConnectedToTheInternet" : "Vous n'êtes pas connecté à Internet.",
17 "global.spellchecker.useDefault" : "Par défaut ({default})",
18 "global.spellchecking.autodetect" : "Detecter automatiquement la langue",
19 "global.spellchecking.autodetect.short" : "Automatiquement",
20 "global.spellchecking.language" : "Langue de la vérification orthographique",
9 "import.headline" : "Importez vos services depuis la version 4 de Franz.", 21 "import.headline" : "Importez vos services depuis la version 4 de Franz.",
10 "import.notSupportedHeadline" : "Ces services ne sont pas encore supportés par Franz 5", 22 "import.notSupportedHeadline" : "Ces services ne sont pas encore supportés par Franz 5",
11 "import.skip.label" : "Je veux ajouter des services manuellement", 23 "import.skip.label" : "Je veux ajouter des services manuellement",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Se connecter", 44 "login.submit.label" : "Se connecter",
33 "login.tokenExpired" : "Votre session a expiré, veuillez vous reconnecter.", 45 "login.tokenExpired" : "Votre session a expiré, veuillez vous reconnecter.",
34 "menu.app.about" : "À propos de Franz", 46 "menu.app.about" : "À propos de Franz",
47 "menu.app.announcement" : "Quoi de neuf? ",
35 "menu.app.hide" : "Masquer", 48 "menu.app.hide" : "Masquer",
36 "menu.app.hideOthers" : "Masquer les autres", 49 "menu.app.hideOthers" : "Masquer les autres",
37 "menu.app.quit" : "Quitter", 50 "menu.app.quit" : "Quitter",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Support", 72 "menu.help.support" : "Support",
60 "menu.help.tos" : "Conditions d'utilisation", 73 "menu.help.tos" : "Conditions d'utilisation",
61 "menu.services" : "Services", 74 "menu.services" : "Services",
75 "menu.services.activatePreviousService" : "Activer le service précédent",
62 "menu.services.addNewService" : "Ajouter un nouveau service...", 76 "menu.services.addNewService" : "Ajouter un nouveau service...",
77 "menu.services.setNextServiceActive" : "Activer le service suivant",
63 "menu.view" : "Aperçu", 78 "menu.view" : "Aperçu",
64 "menu.view.enterFullScreen" : "Entrer en mode plein écran", 79 "menu.view.enterFullScreen" : "Entrer en mode plein écran",
65 "menu.view.exitFullScreen" : "Sortir du mode plein écran", 80 "menu.view.exitFullScreen" : "Sortir du mode plein écran",
@@ -74,13 +89,18 @@
74 "menu.window" : "Fenêtre", 89 "menu.window" : "Fenêtre",
75 "menu.window.close" : "Fermer", 90 "menu.window.close" : "Fermer",
76 "menu.window.minimize" : "Réduire", 91 "menu.window.minimize" : "Réduire",
77 "password.email.label" : "Adresse e-mail", 92 "menu.workspaces" : "Espace de travail",
93 "menu.workspaces.addNewWorkspace" : "Ajouter un nouvel espace de travail",
94 "menu.workspaces.closeWorkspaceDrawer" : "Ouvrir l'espace de travail",
95 "menu.workspaces.defaultWorkspace" : "Tous les services",
96 "menu.workspaces.openWorkspaceDrawer" : "Fermer l'espace de travail",
97 "password.email.label" : "Adresse email",
78 "password.headline" : "Réinitialiser le mot de passe", 98 "password.headline" : "Réinitialiser le mot de passe",
79 "password.link.login" : "Connectez-vous à votre compte", 99 "password.link.login" : "Connectez-vous à votre compte",
80 "password.link.signup" : "Créer un compte gratuit.", 100 "password.link.signup" : "Créer un compte gratuit.",
81 "password.noUser" : "Aucun utilisateur n'a été trouvé avec cette adresse e-mail", 101 "password.noUser" : "Aucun utilisateur n'a été trouvé avec cette adresse email",
82 "password.submit.label" : "Soumettre", 102 "password.submit.label" : "Soumettre",
83 "password.successInfo" : "Merci de consulter vos e-mails", 103 "password.successInfo" : "Merci de consulter vos emails",
84 "premiumFeature.button.upgradeAccount" : "Mettre à niveau mon compte", 104 "premiumFeature.button.upgradeAccount" : "Mettre à niveau mon compte",
85 "pricing.headline" : "Soutenez Franz", 105 "pricing.headline" : "Soutenez Franz",
86 "pricing.link.skipPayment" : "Je ne veux pas soutenir le développement de Franz.", 106 "pricing.link.skipPayment" : "Je ne veux pas soutenir le développement de Franz.",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "Oh non !", 117 "service.errorHandler.headline" : "Oh non !",
98 "service.errorHandler.message" : "Erreur", 118 "service.errorHandler.message" : "Erreur",
99 "service.errorHandler.text" : "Le chargement de {name} a échoué.", 119 "service.errorHandler.text" : "Le chargement de {name} a échoué.",
120 "service.webviewLoader.loading" : "Chargement (c'est l'heure du café...)",
100 "services.getStarted" : "Commencer", 121 "services.getStarted" : "Commencer",
101 "services.welcome" : "Bienvenue dans Franz", 122 "services.welcome" : "Bienvenue dans Franz",
102 "settings.account.account.editButton" : "Modifier le compte", 123 "settings.account.account.editButton" : "Modifier le compte",
@@ -108,7 +129,7 @@
108 "settings.account.deleteInfo" : "Si vous n'avez plus besoin de votre compte Franz, vous pouvez le supprimer avec toutes ses données associées.", 129 "settings.account.deleteInfo" : "Si vous n'avez plus besoin de votre compte Franz, vous pouvez le supprimer avec toutes ses données associées.",
109 "settings.account.headline" : "Compte", 130 "settings.account.headline" : "Compte",
110 "settings.account.headlineAccount" : "Informations sur le compte", 131 "settings.account.headlineAccount" : "Informations sur le compte",
111 "settings.account.headlineDangerZone" : "Zone Dangereuse !", 132 "settings.account.headlineDangerZone" : "Zone dangereuse !",
112 "settings.account.headlineInvoices" : "Factures", 133 "settings.account.headlineInvoices" : "Factures",
113 "settings.account.headlinePassword" : "Changer le mot de passe", 134 "settings.account.headlinePassword" : "Changer le mot de passe",
114 "settings.account.headlineProfile" : "Mettre à jour le profil", 135 "settings.account.headlineProfile" : "Mettre à jour le profil",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Télécharger", 138 "settings.account.invoiceDownload" : "Télécharger",
118 "settings.account.manageSubscription.label" : "Gérer votre abonnement", 139 "settings.account.manageSubscription.label" : "Gérer votre abonnement",
119 "settings.account.successInfo" : "Vos modifications ont été enregistrées", 140 "settings.account.successInfo" : "Vos modifications ont été enregistrées",
141 "settings.account.tryReloadServices" : "Réessayer",
120 "settings.account.tryReloadUserInfoRequest" : "Réessayer", 142 "settings.account.tryReloadUserInfoRequest" : "Réessayer",
121 "settings.account.userInfoRequestFailed" : "Impossible de charger les informations de l'utilisateur", 143 "settings.account.userInfoRequestFailed" : "Impossible de charger les informations de l'utilisateur",
122 "settings.app.buttonClearAllCache" : "Vider le cache", 144 "settings.app.buttonClearAllCache" : "Vider le cache",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Accepter les versions bêta", 151 "settings.app.form.beta" : "Accepter les versions bêta",
130 "settings.app.form.darkMode" : "Rejoins le côté obscur", 152 "settings.app.form.darkMode" : "Rejoins le côté obscur",
131 "settings.app.form.enableGPUAcceleration" : "Activer l'accélération GPU", 153 "settings.app.form.enableGPUAcceleration" : "Activer l'accélération GPU",
132 "settings.app.form.enableMenuBar" : "Afficher Franz dans la barre des menus",
133 "settings.app.form.enableSpellchecking" : "Activer la vérification orthographique", 154 "settings.app.form.enableSpellchecking" : "Activer la vérification orthographique",
134 "settings.app.form.enableSystemTray" : "Afficher Franz dans la barre d'état système", 155 "settings.app.form.enableSystemTray" : "Afficher Franz dans la barre d'état système",
135 "settings.app.form.hideDockIcon" : "Masquer Franz dans le Dock",
136 "settings.app.form.language" : "Langue", 156 "settings.app.form.language" : "Langue",
137 "settings.app.form.minimizeToSystemTray" : "Minimiser Franz dans la zone de notification", 157 "settings.app.form.minimizeToSystemTray" : "Minimiser Franz dans la zone de notification",
138 "settings.app.form.runInBackground" : "Garder Franz ouvert en arrière-plan à la fermeture de la fenêtre", 158 "settings.app.form.runInBackground" : "Garder Franz ouvert en arrière-plan à la fermeture de la fenêtre",
139 "settings.app.form.showDisabledServices" : "Afficher les onglets des services désactivés", 159 "settings.app.form.showDisabledServices" : "Afficher les onglets des services désactivés",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Afficher les badges de messages non lus quand les notifications sont désactivées.", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Afficher les badges de messages non lus quand les notifications sont désactivées.",
141 "settings.app.form.spellcheckerLanguage" : "Langue de la vérification orthographique",
142 "settings.app.headline" : "Paramètres", 161 "settings.app.headline" : "Paramètres",
143 "settings.app.headlineAdvanced" : "Paramètres avancés", 162 "settings.app.headlineAdvanced" : "Paramètres avancés",
144 "settings.app.headlineAppearance" : "Apparence", 163 "settings.app.headlineAppearance" : "Apparence",
145 "settings.app.headlineGeneral" : "Général", 164 "settings.app.headlineGeneral" : "Général",
146 "settings.app.headlineLanguage" : "Langue", 165 "settings.app.headlineLanguage" : "Langue",
147 "settings.app.headlineUpdates" : "Mises à jour", 166 "settings.app.headlineUpdates" : "Mises à jour",
167 "settings.app.languageDisclaimer" : "Les traductions officielles sont l'anglais et l'allemand. Toutes les autres langues sont des traductions faites par la communauté.",
148 "settings.app.restartRequired" : "Les modifications nécessitent un redémarrage", 168 "settings.app.restartRequired" : "Les modifications nécessitent un redémarrage",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Aidez-nous à traduire Franz dans votre langue.", 170 "settings.app.translationHelp" : "Aidez-nous à traduire Franz dans votre langue.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Inviter des amis", 177 "settings.navigation.inviteFriends" : "Inviter des amis",
158 "settings.navigation.logout" : "Se déconnecter", 178 "settings.navigation.logout" : "Se déconnecter",
159 "settings.navigation.settings" : "Paramètres", 179 "settings.navigation.settings" : "Paramètres",
180 "settings.navigation.team" : "Gérer l'équipe",
160 "settings.navigation.yourServices" : "Vos services", 181 "settings.navigation.yourServices" : "Vos services",
182 "settings.navigation.yourWorkspaces" : "Tes espaces de travail",
161 "settings.recipes.all" : "Tous les services", 183 "settings.recipes.all" : "Tous les services",
162 "settings.recipes.dev" : "Développement", 184 "settings.recipes.dev" : "Développement",
163 "settings.recipes.headline" : "Services disponibles", 185 "settings.recipes.headline" : "Services disponibles",
@@ -192,19 +214,17 @@
192 "settings.service.form.indirectMessages" : "Afficher le badge des messages pour tous les nouveaux messages", 214 "settings.service.form.indirectMessages" : "Afficher le badge des messages pour tous les nouveaux messages",
193 "settings.service.form.isMutedInfo" : "Lorsque désactivé, tous les sons de notifications ainsi que l'audio sont coupés", 215 "settings.service.form.isMutedInfo" : "Lorsque désactivé, tous les sons de notifications ainsi que l'audio sont coupés",
194 "settings.service.form.name" : "Nom", 216 "settings.service.form.name" : "Nom",
195 "settings.service.form.proxy.headline" : "Paramètres Proxy HTTP\/HTTPS", 217 "settings.service.form.proxy.headline" : "Paramètres proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Hôte\/IP du proxy", 218 "settings.service.form.proxy.host" : "Hôte\/IP du proxy",
197 "settings.service.form.proxy.info" : "Les paramètres de proxy ne seront pas synchronisés avec les serveurs de Franz.", 219 "settings.service.form.proxy.info" : "Les paramètres de proxy ne seront pas synchronisés avec les serveurs de Franz.",
198 "settings.service.form.proxy.isEnabled" : "Utiliser un proxy", 220 "settings.service.form.proxy.isEnabled" : "Utiliser un proxy",
199 "settings.service.form.proxy.password" : "Mot de passe (facultatif)", 221 "settings.service.form.proxy.password" : "Mot de passe (facultatif)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Veuillez redémarrer Franz après avoir modifier les paramètres proxy.", 223 "settings.service.form.proxy.restartInfo" : "Veuillez redémarrer Franz après avoir modifié les paramètres proxy.",
202 "settings.service.form.proxy.user" : "Utilisateur (facultatif)", 224 "settings.service.form.proxy.user" : "Utilisateur (facultatif)",
203 "settings.service.form.saveButton" : "Enregistrer le service", 225 "settings.service.form.saveButton" : "Enregistrer le service",
204 "settings.service.form.spellcheckerLanguage" : "Veuillez vérifier l'épellation Langage",
205 "settings.service.form.spellcheckerLanguage.default" : "Par défaut ({default})",
206 "settings.service.form.tabHosted" : "Hébergé", 226 "settings.service.form.tabHosted" : "Hébergé",
207 "settings.service.form.tabOnPremise" : "Auto-hébergé â­ï¸", 227 "settings.service.form.tabOnPremise" : "hébergé par soi-même â­ï¸",
208 "settings.service.form.team" : "Équipe", 228 "settings.service.form.team" : "Équipe",
209 "settings.service.form.useHostedService" : "Utilisez le service hébergé {name}.", 229 "settings.service.form.useHostedService" : "Utilisez le service hébergé {name}.",
210 "settings.service.form.yourServices" : "Vos services", 230 "settings.service.form.yourServices" : "Vos services",
@@ -212,26 +232,50 @@
212 "settings.services.discoverServices" : "Découvrir les services", 232 "settings.services.discoverServices" : "Découvrir les services",
213 "settings.services.headline" : "Vos services", 233 "settings.services.headline" : "Vos services",
214 "settings.services.noServicesAdded" : "Vous n'avez pas encore ajouté de services.", 234 "settings.services.noServicesAdded" : "Vous n'avez pas encore ajouté de services.",
235 "settings.services.servicesRequestFailed" : "Impossible de charger vos services",
215 "settings.services.tooltip.isDisabled" : "Ce service est désactivé", 236 "settings.services.tooltip.isDisabled" : "Ce service est désactivé",
216 "settings.services.tooltip.isMuted" : "Tous les sons sont coupés", 237 "settings.services.tooltip.isMuted" : "Tous les sons sont coupés",
217 "settings.services.tooltip.notificationsDisabled" : "Notifications désactivées.", 238 "settings.services.tooltip.notificationsDisabled" : "Notifications désactivées.",
218 "settings.services.updatedInfo" : "Vos modifications ont été enregistrées", 239 "settings.services.updatedInfo" : "Vos modifications ont été enregistrées",
240 "settings.team.contentHeadline" : "Franz pour les équipes",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Équipe de travail",
243 "settings.team.intro" : "Tu peux désormais gérer les abonnements Premium pour autant de collègues, amis ou membres de famille que tu souhaites, à partir d'un seul et même compte.",
244 "settings.team.manageAction" : "Gère ton équipe sur meetfranz.com",
245 "settings.team.upgradeAction" : "Mise à niveau du compte",
219 "settings.user.form.accountType.company" : "Entreprise", 246 "settings.user.form.accountType.company" : "Entreprise",
220 "settings.user.form.accountType.individual" : "Individuel", 247 "settings.user.form.accountType.individual" : "Individuel",
221 "settings.user.form.accountType.label" : "Type de compte", 248 "settings.user.form.accountType.label" : "Type de compte",
222 "settings.user.form.accountType.non-profit" : "Non-lucratif", 249 "settings.user.form.accountType.non-profit" : "Non-lucratif",
223 "settings.user.form.currentPassword" : "Mot de passe actuel", 250 "settings.user.form.currentPassword" : "Mot de passe actuel",
224 "settings.user.form.email" : "E-mail", 251 "settings.user.form.email" : "Email",
225 "settings.user.form.firstname" : "Prénom", 252 "settings.user.form.firstname" : "Prénom",
226 "settings.user.form.lastname" : "Nom", 253 "settings.user.form.lastname" : "Nom",
227 "settings.user.form.newPassword" : "Nouveau mot de passe", 254 "settings.user.form.newPassword" : "Nouveau mot de passe",
255 "settings.workspace.add.form.name" : "Nom",
256 "settings.workspace.add.form.submitButton" : "Créer un espace de travail",
257 "settings.workspace.form.buttonDelete" : "Effacer l'espace de travail",
258 "settings.workspace.form.buttonSave" : "Sauvegarder l'espace de travail",
259 "settings.workspace.form.name" : "Nom",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Tes espaces de travail",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Vos espaces de travails",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Réessayer",
266 "settings.workspaces.updatedInfo" : "Vos modifications ont été enregistrées",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Ajouter un nouveau service", 270 "sidebar.addNewService" : "Ajouter un nouveau service",
271 "sidebar.closeWorkspaceDrawer" : "Ouvrir l'espace de travail",
229 "sidebar.muteApp" : "Désactiver les notifications et les sons", 272 "sidebar.muteApp" : "Désactiver les notifications et les sons",
273 "sidebar.openWorkspaceDrawer" : "Fermer l'espace de travail",
230 "sidebar.settings" : "Paramètres", 274 "sidebar.settings" : "Paramètres",
231 "sidebar.unmuteApp" : "Activer les notifications et les sons", 275 "sidebar.unmuteApp" : "Activer les notifications et les sons",
232 "signup.company.label" : "Entreprise", 276 "signup.company.label" : "Entreprise",
233 "signup.email.label" : "Adresse e-mail", 277 "signup.email.label" : "Adresse email",
234 "signup.emailDuplicate" : "Cette adresse e-mail est déjà utilisée", 278 "signup.emailDuplicate" : "Cette adresse email est déjà utilisée",
235 "signup.firstname.label" : "Prénom", 279 "signup.firstname.label" : "Prénom",
236 "signup.headline" : "S'inscrire", 280 "signup.headline" : "S'inscrire",
237 "signup.lastname.label" : "Nom", 281 "signup.lastname.label" : "Nom",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Résidents de l'UE : une taxe locale peut s'appliquer", 288 "subscription.euTaxInfo" : "Résidents de l'UE : une taxe locale peut s'appliquer",
245 "subscription.features.ads" : "Plus de pubs !", 289 "subscription.features.ads" : "Plus de pubs !",
246 "subscription.features.comingSoon" : "Bientôt disponible", 290 "subscription.features.comingSoon" : "Bientôt disponible",
247 "subscription.features.encryptedSync" : "Synchronisation de session cryptée",
248 "subscription.features.noInterruptions" : "Aucun délai dans l'application ni de harcèlement pour mettre à niveau la licence", 291 "subscription.features.noInterruptions" : "Aucun délai dans l'application ni de harcèlement pour mettre à niveau la licence",
249 "subscription.features.onpremise" : "Ajouter des services locaux\/hébergés comme HipChat",
250 "subscription.features.onpremise.mattermost" : "Ajouter des services auto-hébergés comme Mattermost", 292 "subscription.features.onpremise.mattermost" : "Ajouter des services auto-hébergés comme Mattermost",
251 "subscription.features.proxy" : "Support proxy pour les services", 293 "subscription.features.proxy" : "Support proxy pour les services",
252 "subscription.features.spellchecker" : "Prise en charge du correcteur orthographique", 294 "subscription.features.spellchecker" : "Prise en charge du correcteur orthographique",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Le compte payant Supporter Premium Franz inclut", 296 "subscription.includedFeatures" : "Le compte payant Supporter Premium Franz inclut",
254 "subscription.paymentSessionError" : "Initialisation du paiement impossible", 297 "subscription.paymentSessionError" : "Initialisation du paiement impossible",
255 "subscription.submit.label" : "Je souhaite aider au développement de Franz", 298 "subscription.submit.label" : "Je souhaite aider au développement de Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Recharger", 312 "tabs.item.reload" : "Recharger",
270 "validation.email" : "{field} n'est pas valide", 313 "validation.email" : "{field} n'est pas valide",
271 "validation.minLength" : "{field} doit contenir au moins {length} caractère(s)", 314 "validation.minLength" : "{field} doit contenir au moins {length} caractère(s)",
315 "validation.oneRequired" : "Au moins un de ces champs est requis",
272 "validation.required" : "{field} est requis", 316 "validation.required" : "{field} est requis",
273 "validation.url" : "{field} n'est pas une URL valide", 317 "validation.url" : "{field} n'est pas une URL valide",
274 "welcome.loginButton" : "Se connecter sur son compte", 318 "welcome.loginButton" : "Se connecter sur son compte",
275 "welcome.signupButton" : "Créer un compte gratuit", 319 "welcome.signupButton" : "Créer un compte gratuit",
276 "welcome.slogan" : "Une messagerie qui fonctionne pour vous" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Tous les services",
322 "workspaceDrawer.headline" : "Espace de travail",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/ga.json b/src/i18n/locales/ga.json
index 0d3d8623e..3f1e827fb 100644
--- a/src/i18n/locales/ga.json
+++ b/src/i18n/locales/ga.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Athlódáil", 2 "app.errorHandler.action" : "Athlódáil",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Something went wrong",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Ní féidir nascadh le seirbhísí Franz ar líne", 15 "global.api.unhealthy" : "Ní féidir nascadh le seirbhísí Franz ar líne",
8 "global.notConnectedToTheInternet" : "Níl tú nasctha leis an Idirlíon.", 16 "global.notConnectedToTheInternet" : "Níl tú nasctha leis an Idirlíon.",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "Iompórtáil do sheirbhísí Franz 4", 21 "import.headline" : "Iompórtáil do sheirbhísí Franz 4",
10 "import.notSupportedHeadline" : "Níl na seirbhísí seo taca ag Franz 5 go fóill", 22 "import.notSupportedHeadline" : "Níl na seirbhísí seo taca ag Franz 5 go fóill",
11 "import.skip.label" : "Ba mhaith liom seirbhísí a chur de láimh", 23 "import.skip.label" : "Ba mhaith liom seirbhísí a chur de láimh",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Logáil isteach", 44 "login.submit.label" : "Logáil isteach",
33 "login.tokenExpired" : "D'éag do sheisiún, logáil isteach arís le do thoil.", 45 "login.tokenExpired" : "D'éag do sheisiún, logáil isteach arís le do thoil.",
34 "menu.app.about" : "Faoi Franz", 46 "menu.app.about" : "Faoi Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Cuir Franz i bhfolach", 48 "menu.app.hide" : "Cuir Franz i bhfolach",
36 "menu.app.hideOthers" : "Folaigh feidhmchláir eile", 49 "menu.app.hideOthers" : "Folaigh feidhmchláir eile",
37 "menu.app.quit" : "Scoir", 50 "menu.app.quit" : "Scoir",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Tacaíocht", 72 "menu.help.support" : "Tacaíocht",
60 "menu.help.tos" : "Téarmaí tagartha", 73 "menu.help.tos" : "Téarmaí tagartha",
61 "menu.services" : "Seirbhísí", 74 "menu.services" : "Seirbhísí",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Cuir seirbhís nua leis", 76 "menu.services.addNewService" : "Cuir seirbhís nua leis",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Amharc", 78 "menu.view" : "Amharc",
64 "menu.view.enterFullScreen" : "Cuir isteach mód lánscáileáin", 79 "menu.view.enterFullScreen" : "Cuir isteach mód lánscáileáin",
65 "menu.view.exitFullScreen" : "Scoir mód lánscáileáin", 80 "menu.view.exitFullScreen" : "Scoir mód lánscáileáin",
@@ -74,6 +89,11 @@
74 "menu.window" : "Fuinneog", 89 "menu.window" : "Fuinneog",
75 "menu.window.close" : "Dún", 90 "menu.window.close" : "Dún",
76 "menu.window.minimize" : "Ãoslaghdaigh", 91 "menu.window.minimize" : "Ãoslaghdaigh",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Gach seirbhís",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Seoladh ríomhphoist", 97 "password.email.label" : "Seoladh ríomhphoist",
78 "password.headline" : "Athshocraigh pasfhocal", 98 "password.headline" : "Athshocraigh pasfhocal",
79 "password.link.login" : "Logáil isteach i do chuntas", 99 "password.link.login" : "Logáil isteach i do chuntas",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "Oró, ní hea!", 117 "service.errorHandler.headline" : "Oró, ní hea!",
98 "service.errorHandler.message" : "Earráid", 118 "service.errorHandler.message" : "Earráid",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Cuir tús", 121 "services.getStarted" : "Cuir tús",
101 "services.welcome" : "Fáilte go Franz", 122 "services.welcome" : "Fáilte go Franz",
102 "settings.account.account.editButton" : "Cuir cuntas in eagar", 123 "settings.account.account.editButton" : "Cuir cuntas in eagar",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Ãoslódáil", 138 "settings.account.invoiceDownload" : "Ãoslódáil",
118 "settings.account.manageSubscription.label" : "Bainistigh do shíntiús", 139 "settings.account.manageSubscription.label" : "Bainistigh do shíntiús",
119 "settings.account.successInfo" : "Sábháladh do chuid athruithe", 140 "settings.account.successInfo" : "Sábháladh do chuid athruithe",
141 "settings.account.tryReloadServices" : "Atriail",
120 "settings.account.tryReloadUserInfoRequest" : "Atriail", 142 "settings.account.tryReloadUserInfoRequest" : "Atriail",
121 "settings.account.userInfoRequestFailed" : "Ní féidir eolas úsáideora a lódáil", 143 "settings.account.userInfoRequestFailed" : "Ní féidir eolas úsáideora a lódáil",
122 "settings.app.buttonClearAllCache" : "Glan taisce", 144 "settings.app.buttonClearAllCache" : "Glan taisce",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Cuir leagain béite san áireamh", 151 "settings.app.form.beta" : "Cuir leagain béite san áireamh",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "Cumasaigh luasghéarú APG", 153 "settings.app.form.enableGPUAcceleration" : "Cumasaigh luasghéarú APG",
132 "settings.app.form.enableMenuBar" : "Taispeáin Franz sa bharra roghchláir",
133 "settings.app.form.enableSpellchecking" : "Cumasaigh seiceáil litrithe", 154 "settings.app.form.enableSpellchecking" : "Cumasaigh seiceáil litrithe",
134 "settings.app.form.enableSystemTray" : "Taispeáin Franz i dtráidire an chórais", 155 "settings.app.form.enableSystemTray" : "Taispeáin Franz i dtráidire an chórais",
135 "settings.app.form.hideDockIcon" : "Cuir íocóin Franz i bhfolach ón leaba nasctha",
136 "settings.app.form.language" : "Teanga", 156 "settings.app.form.language" : "Teanga",
137 "settings.app.form.minimizeToSystemTray" : "Ãoslaghdaigh Franz chuig tráidire an chórais", 157 "settings.app.form.minimizeToSystemTray" : "Ãoslaghdaigh Franz chuig tráidire an chórais",
138 "settings.app.form.runInBackground" : "Coimeád Franz sa chúlra nuair a dhúntar an fhuinneog", 158 "settings.app.form.runInBackground" : "Coimeád Franz sa chúlra nuair a dhúntar an fhuinneog",
139 "settings.app.form.showDisabledServices" : "Taispeáin tabanna do sheirbhísí dhíchumasaithe", 159 "settings.app.form.showDisabledServices" : "Taispeáin tabanna do sheirbhísí dhíchumasaithe",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Taispeáin teachtaireachtaí neamhléite, nuair a dhíchumasaítear fógraí", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Taispeáin teachtaireachtaí neamhléite, nuair a dhíchumasaítear fógraí",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Socruithe", 161 "settings.app.headline" : "Socruithe",
143 "settings.app.headlineAdvanced" : "Casta", 162 "settings.app.headlineAdvanced" : "Casta",
144 "settings.app.headlineAppearance" : "Dealramh", 163 "settings.app.headlineAppearance" : "Dealramh",
145 "settings.app.headlineGeneral" : "Ginearálta", 164 "settings.app.headlineGeneral" : "Ginearálta",
146 "settings.app.headlineLanguage" : "Teanga", 165 "settings.app.headlineLanguage" : "Teanga",
147 "settings.app.headlineUpdates" : "Nuashonruithe", 166 "settings.app.headlineUpdates" : "Nuashonruithe",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Ní gá atosú chun athruithe a chur i bhfeidhm.", 168 "settings.app.restartRequired" : "Ní gá atosú chun athruithe a chur i bhfeidhm.",
149 "settings.app.subheadlineCache" : "Taisce", 169 "settings.app.subheadlineCache" : "Taisce",
150 "settings.app.translationHelp" : "Cabhraigh linn Franz a aistriú i do theanga.", 170 "settings.app.translationHelp" : "Cabhraigh linn Franz a aistriú i do theanga.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Tabhair cuireadh do chairde", 177 "settings.navigation.inviteFriends" : "Tabhair cuireadh do chairde",
158 "settings.navigation.logout" : "Logáil amach", 178 "settings.navigation.logout" : "Logáil amach",
159 "settings.navigation.settings" : "Socruithe", 179 "settings.navigation.settings" : "Socruithe",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Do sheirbhísí", 181 "settings.navigation.yourServices" : "Do sheirbhísí",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Gach seirbhís", 183 "settings.recipes.all" : "Gach seirbhís",
162 "settings.recipes.dev" : "Forbairt", 184 "settings.recipes.dev" : "Forbairt",
163 "settings.recipes.headline" : "Seirbhísí le fáil", 185 "settings.recipes.headline" : "Seirbhísí le fáil",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "Sábháil seirbhís", 225 "settings.service.form.saveButton" : "Sábháil seirbhís",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Óstáilte", 226 "settings.service.form.tabHosted" : "Óstáilte",
207 "settings.service.form.tabOnPremise" : "Féinóstáilte â­ï¸", 227 "settings.service.form.tabOnPremise" : "Féinóstáilte â­ï¸",
208 "settings.service.form.team" : "Foireann", 228 "settings.service.form.team" : "Foireann",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Aimsigh seirbhísí", 232 "settings.services.discoverServices" : "Aimsigh seirbhísí",
213 "settings.services.headline" : "Do sheirbhísí", 233 "settings.services.headline" : "Do sheirbhísí",
214 "settings.services.noServicesAdded" : "Níl aon seirbhís curtha agat go fóill.", 234 "settings.services.noServicesAdded" : "Níl aon seirbhís curtha agat go fóill.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Seirbhís díchumasaithe", 236 "settings.services.tooltip.isDisabled" : "Seirbhís díchumasaithe",
216 "settings.services.tooltip.isMuted" : "Tachtar gach fuaim", 237 "settings.services.tooltip.isMuted" : "Tachtar gach fuaim",
217 "settings.services.tooltip.notificationsDisabled" : "Fógraí dhíchumasaithe", 238 "settings.services.tooltip.notificationsDisabled" : "Fógraí dhíchumasaithe",
218 "settings.services.updatedInfo" : "Sábháiltear do chuid athruithe", 239 "settings.services.updatedInfo" : "Sábháiltear do chuid athruithe",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Foireann",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Comhlacht", 246 "settings.user.form.accountType.company" : "Comhlacht",
220 "settings.user.form.accountType.individual" : "Ar leith", 247 "settings.user.form.accountType.individual" : "Ar leith",
221 "settings.user.form.accountType.label" : "Cineál chuntais", 248 "settings.user.form.accountType.label" : "Cineál chuntais",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Céadainm", 252 "settings.user.form.firstname" : "Céadainm",
226 "settings.user.form.lastname" : "Sloinne", 253 "settings.user.form.lastname" : "Sloinne",
227 "settings.user.form.newPassword" : "Pasfhocal nua", 254 "settings.user.form.newPassword" : "Pasfhocal nua",
255 "settings.workspace.add.form.name" : "Ainm",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Ainm",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Atriail",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Cuir seirbhís nua leis", 270 "sidebar.addNewService" : "Cuir seirbhís nua leis",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Díchumasaigh fógraí ⊠fuaim", 272 "sidebar.muteApp" : "Díchumasaigh fógraí ⊠fuaim",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Socruithe", 274 "sidebar.settings" : "Socruithe",
231 "sidebar.unmuteApp" : "Cumasaigh fógraí ⊠fuaim", 275 "sidebar.unmuteApp" : "Cumasaigh fógraí ⊠fuaim",
232 "signup.company.label" : "Comhlacht", 276 "signup.company.label" : "Comhlacht",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Ãithritheoirí an tAÉ: is féidir cáin díolacháin áitiúla a chur i bhfeidhm", 288 "subscription.euTaxInfo" : "Ãithritheoirí an tAÉ: is féidir cáin díolacháin áitiúla a chur i bhfeidhm",
245 "subscription.features.ads" : "Fógraí ar bith, choíche!", 289 "subscription.features.ads" : "Fógraí ar bith, choíche!",
246 "subscription.features.comingSoon" : "ag teacht go luath", 290 "subscription.features.comingSoon" : "ag teacht go luath",
247 "subscription.features.encryptedSync" : "Sionchronú seisiúin chriptithe",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Cuir seirbhísí óstáilte ar nós HipChat leis",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Cuireann Cuntas Phŕeimhthacadóra Franz san áireamh", 296 "subscription.includedFeatures" : "Cuireann Cuntas Phŕeimhthacadóra Franz san áireamh",
254 "subscription.paymentSessionError" : "Ní féidir an bhfoirm íocaíochta a lódáil", 297 "subscription.paymentSessionError" : "Ní féidir an bhfoirm íocaíochta a lódáil",
255 "subscription.submit.label" : "Ba mhaith liom tacaíocht a thabhairt d'fhorbairt Franz", 298 "subscription.submit.label" : "Ba mhaith liom tacaíocht a thabhairt d'fhorbairt Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Athlódáil", 312 "tabs.item.reload" : "Athlódáil",
270 "validation.email" : "Níl {field} neamhbhailí", 313 "validation.email" : "Níl {field} neamhbhailí",
271 "validation.minLength" : "Ba cheart go mbeadh {field} ar a laghad {length} charactar fada", 314 "validation.minLength" : "Ba cheart go mbeadh {field} ar a laghad {length} charactar fada",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "Tá {field} de dhíth", 316 "validation.required" : "Tá {field} de dhíth",
273 "validation.url" : "Ní AAA bhailí é {field}", 317 "validation.url" : "Ní AAA bhailí é {field}",
274 "welcome.loginButton" : "Logáil isteach i do chuntas", 318 "welcome.loginButton" : "Logáil isteach i do chuntas",
275 "welcome.signupButton" : "Cruthaigh cuntas nua", 319 "welcome.signupButton" : "Cruthaigh cuntas nua",
276 "welcome.slogan" : "Teachtaireachtaí a oibríonn duitse" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Gach seirbhís",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/hr.json b/src/i18n/locales/hr.json
index 2ff69755d..468238166 100644
--- a/src/i18n/locales/hr.json
+++ b/src/i18n/locales/hr.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Ponovno uÄitavanje", 2 "app.errorHandler.action" : "Ponovno uÄitavanje",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Something went wrong",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Nije se moguće povezati na Francove on-line servise. ", 15 "global.api.unhealthy" : "Nije se moguće povezati na Francove on-line servise. ",
8 "global.notConnectedToTheInternet" : "Sada ste povezani s internetom. ", 16 "global.notConnectedToTheInternet" : "Sada ste povezani s internetom. ",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "Uvezite svoje Franc 4 servise. ", 21 "import.headline" : "Uvezite svoje Franc 4 servise. ",
10 "import.notSupportedHeadline" : "Franc 5 trenutno ne podržava taj servis", 22 "import.notSupportedHeadline" : "Franc 5 trenutno ne podržava taj servis",
11 "import.skip.label" : "Želim ruÄno dodati ove usluge", 23 "import.skip.label" : "Želim ruÄno dodati ove usluge",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Prijavite se", 44 "login.submit.label" : "Prijavite se",
33 "login.tokenExpired" : "Vaša sesija je istekla, prijavite se ponovo.", 45 "login.tokenExpired" : "Vaša sesija je istekla, prijavite se ponovo.",
34 "menu.app.about" : "O aplikaciji", 46 "menu.app.about" : "O aplikaciji",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Hide", 48 "menu.app.hide" : "Hide",
36 "menu.app.hideOthers" : "Hide Others", 49 "menu.app.hideOthers" : "Hide Others",
37 "menu.app.quit" : "Quit", 50 "menu.app.quit" : "Quit",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Support", 72 "menu.help.support" : "Support",
60 "menu.help.tos" : "Terms of Service", 73 "menu.help.tos" : "Terms of Service",
61 "menu.services" : "Services", 74 "menu.services" : "Services",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Add New Service...", 76 "menu.services.addNewService" : "Add New Service...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "View", 78 "menu.view" : "View",
64 "menu.view.enterFullScreen" : "Enter Full Screen", 79 "menu.view.enterFullScreen" : "Enter Full Screen",
65 "menu.view.exitFullScreen" : "Exit Full Screen", 80 "menu.view.exitFullScreen" : "Exit Full Screen",
@@ -74,6 +89,11 @@
74 "menu.window" : "Window", 89 "menu.window" : "Window",
75 "menu.window.close" : "Close", 90 "menu.window.close" : "Close",
76 "menu.window.minimize" : "Minimize", 91 "menu.window.minimize" : "Minimize",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Sve usluge",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Vaša e-adresa", 97 "password.email.label" : "Vaša e-adresa",
78 "password.headline" : "Stvorite novu zaporku", 98 "password.headline" : "Stvorite novu zaporku",
79 "password.link.login" : "Prijavite se na VaÅ¡ raÄun", 99 "password.link.login" : "Prijavite se na VaÅ¡ raÄun",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "O, ne! ", 117 "service.errorHandler.headline" : "O, ne! ",
98 "service.errorHandler.message" : "Greška", 118 "service.errorHandler.message" : "Greška",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "ZapoÄnimo!", 121 "services.getStarted" : "ZapoÄnimo!",
101 "services.welcome" : "Dobrodošli u Franz", 122 "services.welcome" : "Dobrodošli u Franz",
102 "settings.account.account.editButton" : "Uredi raÄun", 123 "settings.account.account.editButton" : "Uredi raÄun",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Preuzmite", 138 "settings.account.invoiceDownload" : "Preuzmite",
118 "settings.account.manageSubscription.label" : "Upravljajte pretplatama", 139 "settings.account.manageSubscription.label" : "Upravljajte pretplatama",
119 "settings.account.successInfo" : "Vaše promjene su spremljene", 140 "settings.account.successInfo" : "Vaše promjene su spremljene",
141 "settings.account.tryReloadServices" : "Pokušajte ponovno",
120 "settings.account.tryReloadUserInfoRequest" : "Pokušajte ponovno", 142 "settings.account.tryReloadUserInfoRequest" : "Pokušajte ponovno",
121 "settings.account.userInfoRequestFailed" : "Nije moguće uÄitati informacije o korisniku", 143 "settings.account.userInfoRequestFailed" : "Nije moguće uÄitati informacije o korisniku",
122 "settings.app.buttonClearAllCache" : "OÄisti memoriju", 144 "settings.app.buttonClearAllCache" : "OÄisti memoriju",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Obuhvati i beta verzije", 151 "settings.app.form.beta" : "Obuhvati i beta verzije",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "Enable GPU Acceleration", 153 "settings.app.form.enableGPUAcceleration" : "Enable GPU Acceleration",
132 "settings.app.form.enableMenuBar" : "Prikaži Franz u traci izbornika",
133 "settings.app.form.enableSpellchecking" : "Omogući provjeru pravopisa", 154 "settings.app.form.enableSpellchecking" : "Omogući provjeru pravopisa",
134 "settings.app.form.enableSystemTray" : "Prikaži aplikaciju u sustavskoj traci", 155 "settings.app.form.enableSystemTray" : "Prikaži aplikaciju u sustavskoj traci",
135 "settings.app.form.hideDockIcon" : "Sakrij ikonu Franz u prostoru za obavijesti",
136 "settings.app.form.language" : "Jezik", 156 "settings.app.form.language" : "Jezik",
137 "settings.app.form.minimizeToSystemTray" : "Smanji Franca u sustavsku traku", 157 "settings.app.form.minimizeToSystemTray" : "Smanji Franca u sustavsku traku",
138 "settings.app.form.runInBackground" : "Neka se Franc održava u pozadini i ako je prozor zatvoren", 158 "settings.app.form.runInBackground" : "Neka se Franc održava u pozadini i ako je prozor zatvoren",
139 "settings.app.form.showDisabledServices" : "Prikaži ploÄe s onemogućenim servisima", 159 "settings.app.form.showDisabledServices" : "Prikaži ploÄe s onemogućenim servisima",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Pokaži neproÄitane znaÄke poruka kad se obavjeÅ¡tenja onemoguće", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Pokaži neproÄitane znaÄke poruka kad se obavjeÅ¡tenja onemoguće",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Postavke", 161 "settings.app.headline" : "Postavke",
143 "settings.app.headlineAdvanced" : "Napredne alatke", 162 "settings.app.headlineAdvanced" : "Napredne alatke",
144 "settings.app.headlineAppearance" : "Izgled", 163 "settings.app.headlineAppearance" : "Izgled",
145 "settings.app.headlineGeneral" : "Općenito", 164 "settings.app.headlineGeneral" : "Općenito",
146 "settings.app.headlineLanguage" : "Jezik", 165 "settings.app.headlineLanguage" : "Jezik",
147 "settings.app.headlineUpdates" : "Nadogradnje", 166 "settings.app.headlineUpdates" : "Nadogradnje",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Promjene postavki zahtijevaju ponovni zagon", 168 "settings.app.restartRequired" : "Promjene postavki zahtijevaju ponovni zagon",
149 "settings.app.subheadlineCache" : "Predmemorija", 169 "settings.app.subheadlineCache" : "Predmemorija",
150 "settings.app.translationHelp" : "Pomozite nam prevesti aplikaciju na Vaš jezik. ", 170 "settings.app.translationHelp" : "Pomozite nam prevesti aplikaciju na Vaš jezik. ",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Pozovi prijatelje", 177 "settings.navigation.inviteFriends" : "Pozovi prijatelje",
158 "settings.navigation.logout" : "Odjava", 178 "settings.navigation.logout" : "Odjava",
159 "settings.navigation.settings" : "Postavke", 179 "settings.navigation.settings" : "Postavke",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Vaše usluge", 181 "settings.navigation.yourServices" : "Vaše usluge",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Sve usluge", 183 "settings.recipes.all" : "Sve usluge",
162 "settings.recipes.dev" : "Razvoj", 184 "settings.recipes.dev" : "Razvoj",
163 "settings.recipes.headline" : "Dostupne usluge", 185 "settings.recipes.headline" : "Dostupne usluge",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "SaÄuvaj uslugu\/e", 225 "settings.service.form.saveButton" : "SaÄuvaj uslugu\/e",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hostovano", 226 "settings.service.form.tabHosted" : "Hostovano",
207 "settings.service.form.tabOnPremise" : "Samo-hostovano â­ï¸", 227 "settings.service.form.tabOnPremise" : "Samo-hostovano â­ï¸",
208 "settings.service.form.team" : "Tim", 228 "settings.service.form.team" : "Tim",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Pronađite usluge", 232 "settings.services.discoverServices" : "Pronađite usluge",
213 "settings.services.headline" : "Vaše usluge", 233 "settings.services.headline" : "Vaše usluge",
214 "settings.services.noServicesAdded" : "Još uvijek niste unijeli niti jednu uslugu.", 234 "settings.services.noServicesAdded" : "Još uvijek niste unijeli niti jednu uslugu.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Usluga je onemogućena. ", 236 "settings.services.tooltip.isDisabled" : "Usluga je onemogućena. ",
216 "settings.services.tooltip.isMuted" : "Svi zvukovi su onemogućeni. ", 237 "settings.services.tooltip.isMuted" : "Svi zvukovi su onemogućeni. ",
217 "settings.services.tooltip.notificationsDisabled" : "Obavijesti su onemogućene.", 238 "settings.services.tooltip.notificationsDisabled" : "Obavijesti su onemogućene.",
218 "settings.services.updatedInfo" : "Vaše promjene su pohranjene. ", 239 "settings.services.updatedInfo" : "Vaše promjene su pohranjene. ",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Tim",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Tvrtka", 246 "settings.user.form.accountType.company" : "Tvrtka",
220 "settings.user.form.accountType.individual" : "Pojedinac", 247 "settings.user.form.accountType.individual" : "Pojedinac",
221 "settings.user.form.accountType.label" : "Tip raÄuna", 248 "settings.user.form.accountType.label" : "Tip raÄuna",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Ime", 252 "settings.user.form.firstname" : "Ime",
226 "settings.user.form.lastname" : "Prezime", 253 "settings.user.form.lastname" : "Prezime",
227 "settings.user.form.newPassword" : "Nova lozinka", 254 "settings.user.form.newPassword" : "Nova lozinka",
255 "settings.workspace.add.form.name" : "Ime",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Ime",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Pokušajte ponovno",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Dodajte novu uslugu", 270 "sidebar.addNewService" : "Dodajte novu uslugu",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Ugasi obavijesti i zvuk", 272 "sidebar.muteApp" : "Ugasi obavijesti i zvuk",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Postavke", 274 "sidebar.settings" : "Postavke",
231 "sidebar.unmuteApp" : "Omogući obavijesti i zvuk", 275 "sidebar.unmuteApp" : "Omogući obavijesti i zvuk",
232 "signup.company.label" : "Tvrtka", 276 "signup.company.label" : "Tvrtka",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "EU državljani, upozerenje: Moguće taksiranje ", 288 "subscription.euTaxInfo" : "EU državljani, upozerenje: Moguće taksiranje ",
245 "subscription.features.ads" : "Bez reklama, doživotno!", 289 "subscription.features.ads" : "Bez reklama, doživotno!",
246 "subscription.features.comingSoon" : "Dolazi uskoro", 290 "subscription.features.comingSoon" : "Dolazi uskoro",
247 "subscription.features.encryptedSync" : "Kodirano usklađivanje sesija.",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Dodajte pretpostavljeni\/hostirani servis kao Å¡to ima usluga HipChat ",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Plaćeni\/Premium raÄun ukljuÄuje sljedeće: ", 296 "subscription.includedFeatures" : "Plaćeni\/Premium raÄun ukljuÄuje sljedeće: ",
254 "subscription.paymentSessionError" : "Nemoguće inicijalizirati obrazac za uplatu", 297 "subscription.paymentSessionError" : "Nemoguće inicijalizirati obrazac za uplatu",
255 "subscription.submit.label" : "Želim da podržim razvoj Franca. ", 298 "subscription.submit.label" : "Želim da podržim razvoj Franca. ",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Ponovno uÄitavanje", 312 "tabs.item.reload" : "Ponovno uÄitavanje",
270 "validation.email" : "{field} is not valid", 313 "validation.email" : "{field} is not valid",
271 "validation.minLength" : "{field} should be at least {length} characters long", 314 "validation.minLength" : "{field} should be at least {length} characters long",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} is required", 316 "validation.required" : "{field} is required",
273 "validation.url" : "{field} is not a valid URL", 317 "validation.url" : "{field} is not a valid URL",
274 "welcome.loginButton" : "Prijavite se na raÄun", 318 "welcome.loginButton" : "Prijavite se na raÄun",
275 "welcome.signupButton" : "Stvorite novi korisniÄki raÄun", 319 "welcome.signupButton" : "Stvorite novi korisniÄki raÄun",
276 "welcome.slogan" : "Poruke koje su stvorene za tebe" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Sve usluge",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/hu.json b/src/i18n/locales/hu.json
index 0b396cf3b..b28dcb17a 100644
--- a/src/i18n/locales/hu.json
+++ b/src/i18n/locales/hu.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Újratöltés", 2 "app.errorHandler.action" : "Újratöltés",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Valami nem jött össze",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Szerezz egy Franz Támogatói Liszencet",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "Kérjük vásárolj egy Franc Támogatói Liszencet a várakozás átugrásához",
7 "feature.delayApp.text" : "A Franz továbblép {seconds} másodperc múlva.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Nem lehet csatlakozni a Franz online szolgáltatáshoz", 15 "global.api.unhealthy" : "Nem lehet csatlakozni a Franz online szolgáltatáshoz",
8 "global.notConnectedToTheInternet" : "Nincs hálózati kapcsolat.", 16 "global.notConnectedToTheInternet" : "Nincs hálózati kapcsolat.",
17 "global.spellchecker.useDefault" : "Rendszer alapbeállítás használata ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Helyesírás-ellenőrző nyelve",
9 "import.headline" : "Importáld szolgáltatásaidat a Franz 4-ből", 21 "import.headline" : "Importáld szolgáltatásaidat a Franz 4-ből",
10 "import.notSupportedHeadline" : "Még nem támogatott szolgáltatások a Franz 5-ben", 22 "import.notSupportedHeadline" : "Még nem támogatott szolgáltatások a Franz 5-ben",
11 "import.skip.label" : "Manuálisan szeretném hozzáadni a szolgáltatásokat", 23 "import.skip.label" : "Manuálisan szeretném hozzáadni a szolgáltatásokat",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Bejelentkezés", 44 "login.submit.label" : "Bejelentkezés",
33 "login.tokenExpired" : "A munkamenet lejárt, kérlek lépj be újra.", 45 "login.tokenExpired" : "A munkamenet lejárt, kérlek lépj be újra.",
34 "menu.app.about" : "Névjegy", 46 "menu.app.about" : "Névjegy",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Elrejt", 48 "menu.app.hide" : "Elrejt",
36 "menu.app.hideOthers" : "Többi elrejtése", 49 "menu.app.hideOthers" : "Többi elrejtése",
37 "menu.app.quit" : "Kilépés", 50 "menu.app.quit" : "Kilépés",
@@ -51,7 +64,7 @@
51 "menu.edit.startSpeaking" : "Beszélgetés kezdeményezése", 64 "menu.edit.startSpeaking" : "Beszélgetés kezdeményezése",
52 "menu.edit.stopSpeaking" : "Beszéd vége", 65 "menu.edit.stopSpeaking" : "Beszéd vége",
53 "menu.edit.undo" : "Visszavonás", 66 "menu.edit.undo" : "Visszavonás",
54 "menu.file" : "fájl", 67 "menu.file" : "Fájl",
55 "menu.help" : "Súgó", 68 "menu.help" : "Súgó",
56 "menu.help.changelog" : "Változások listája", 69 "menu.help.changelog" : "Változások listája",
57 "menu.help.learnMore" : "Tudjon meg többet", 70 "menu.help.learnMore" : "Tudjon meg többet",
@@ -59,21 +72,28 @@
59 "menu.help.support" : "Támogatás", 72 "menu.help.support" : "Támogatás",
60 "menu.help.tos" : "Felhasználói feltételek", 73 "menu.help.tos" : "Felhasználói feltételek",
61 "menu.services" : "Szolgáltatások", 74 "menu.services" : "Szolgáltatások",
62 "menu.services.addNewService" : "Új kiszolgáló hozzáadása", 75 "menu.services.activatePreviousService" : "Activate previous service",
76 "menu.services.addNewService" : "Új szolgáltatás hozzáadása...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Nézet", 78 "menu.view" : "Nézet",
64 "menu.view.enterFullScreen" : "Kilépés a teljes képernyős módból", 79 "menu.view.enterFullScreen" : "Kilépés a teljes képernyős módból",
65 "menu.view.exitFullScreen" : "Kilépés a teljes képernyős módból", 80 "menu.view.exitFullScreen" : "Kilépés a teljes képernyős módból",
66 "menu.view.reloadFranz" : "Franz újrainditása", 81 "menu.view.reloadFranz" : "Franz újrainditása",
67 "menu.view.reloadService" : "Kiszolgáló újraindítása", 82 "menu.view.reloadService" : "Szolgáltatás újraindítása",
68 "menu.view.resetZoom" : "Tényleges méret", 83 "menu.view.resetZoom" : "Tényleges méret",
69 "menu.view.toggleDevTools" : "fejlesztői eszközök bekapcsolása", 84 "menu.view.toggleDevTools" : "Fejlesztői eszközök ki\/bekapcsolása",
70 "menu.view.toggleFullScreen" : "Váltás Teljes képernyős módra", 85 "menu.view.toggleFullScreen" : "Teljes képernyős mód ki\/bekapcsolása",
71 "menu.view.toggleServiceDevTools" : "Kiszolgáló Fejlesztői Eszközök Bekapcsolása", 86 "menu.view.toggleServiceDevTools" : "Szolgáltatás Fejlesztői Eszközök ki\/bekapcsolása",
72 "menu.view.zoomIn" : "Nagyítás", 87 "menu.view.zoomIn" : "Nagyítás",
73 "menu.view.zoomOut" : "Kicsinyítés", 88 "menu.view.zoomOut" : "Kicsinyítés",
74 "menu.window" : "Ablak", 89 "menu.window" : "Ablak",
75 "menu.window.close" : "Bezárás", 90 "menu.window.close" : "Bezárás",
76 "menu.window.minimize" : "Tálcára", 91 "menu.window.minimize" : "Tálcára",
92 "menu.workspaces" : "Munkaterületek",
93 "menu.workspaces.addNewWorkspace" : "Új munkaterület...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Munkaterület panel bezárása",
95 "menu.workspaces.defaultWorkspace" : "Összes szolgáltatás",
96 "menu.workspaces.openWorkspaceDrawer" : "Munkaterület panel kinyitása",
77 "password.email.label" : "Email cím", 97 "password.email.label" : "Email cím",
78 "password.headline" : "Jelszó visszaállítása", 98 "password.headline" : "Jelszó visszaállítása",
79 "password.link.login" : "Jelentkezz be a fiókodba", 99 "password.link.login" : "Jelentkezz be a fiókodba",
@@ -81,13 +101,13 @@
81 "password.noUser" : "Nem található felhasználó a megadott email címmel", 101 "password.noUser" : "Nem található felhasználó a megadott email címmel",
82 "password.submit.label" : "Küldés", 102 "password.submit.label" : "Küldés",
83 "password.successInfo" : "Ellenőrizd az email fiókodat", 103 "password.successInfo" : "Ellenőrizd az email fiókodat",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Fiók frissítése",
85 "pricing.headline" : "Támogasd a Franz-ot", 105 "pricing.headline" : "Támogasd a Franz-ot",
86 "pricing.link.skipPayment" : "Nem szeretném támogatni a Franz fejlesztését.", 106 "pricing.link.skipPayment" : "Nem szeretném támogatni a Franz fejlesztését.",
87 "pricing.submit.label" : "Támogatni szeretném a Franz fejlesztését.", 107 "pricing.submit.label" : "Támogatni szeretném a Franz fejlesztését",
88 "pricing.support.label" : "Válaszd ki a támogatás módját", 108 "pricing.support.label" : "Válaszd ki a támogatás módját",
89 "service.crashHandler.action" : "{name} újratöltése", 109 "service.crashHandler.action" : "{name} újratöltése",
90 "service.crashHandler.autoReload" : "Megpróbáljuk automatikusan helyreállítani {name}-t {seconds} mp-en belül", 110 "service.crashHandler.autoReload" : "{name} automatikusan helyreállítása {seconds} másodpercen belül",
91 "service.crashHandler.headline" : "Jajj ne!", 111 "service.crashHandler.headline" : "Jajj ne!",
92 "service.crashHandler.text" : "{name} hibát okozott.", 112 "service.crashHandler.text" : "{name} hibát okozott.",
93 "service.disabledHandler.action" : "{name} engedélyezése", 113 "service.disabledHandler.action" : "{name} engedélyezése",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "{name} szerkesztése", 116 "service.errorHandler.editAction" : "{name} szerkesztése",
97 "service.errorHandler.headline" : "Jajj ne!", 117 "service.errorHandler.headline" : "Jajj ne!",
98 "service.errorHandler.message" : "Hiba", 118 "service.errorHandler.message" : "Hiba",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} nem tudott betöltődni.",
120 "service.webviewLoader.loading" : "Betöltés",
100 "services.getStarted" : "Kezdj hozzá", 121 "services.getStarted" : "Kezdj hozzá",
101 "services.welcome" : "Üdvözöl a Franz", 122 "services.welcome" : "Üdvözöl a Franz",
102 "settings.account.account.editButton" : "Fiók szerkesztése", 123 "settings.account.account.editButton" : "Fiók szerkesztése",
@@ -108,7 +129,7 @@
108 "settings.account.deleteInfo" : "Ha még nem szeretnéd fenntartani a Franz-fiókodat, akkor itt törölheted minden hozzá kapcsolódó adattal együtt.", 129 "settings.account.deleteInfo" : "Ha még nem szeretnéd fenntartani a Franz-fiókodat, akkor itt törölheted minden hozzá kapcsolódó adattal együtt.",
109 "settings.account.headline" : "Fiók", 130 "settings.account.headline" : "Fiók",
110 "settings.account.headlineAccount" : "Fiókinformációk", 131 "settings.account.headlineAccount" : "Fiókinformációk",
111 "settings.account.headlineDangerZone" : "Veszélyes terület, óvatosan!", 132 "settings.account.headlineDangerZone" : "Veszélyes terület",
112 "settings.account.headlineInvoices" : "Számlák", 133 "settings.account.headlineInvoices" : "Számlák",
113 "settings.account.headlinePassword" : "Jelszócsere", 134 "settings.account.headlinePassword" : "Jelszócsere",
114 "settings.account.headlineProfile" : "Profil frissítése", 135 "settings.account.headlineProfile" : "Profil frissítése",
@@ -117,54 +138,55 @@
117 "settings.account.invoiceDownload" : "Letöltés", 138 "settings.account.invoiceDownload" : "Letöltés",
118 "settings.account.manageSubscription.label" : "Előfizetés kezelése", 139 "settings.account.manageSubscription.label" : "Előfizetés kezelése",
119 "settings.account.successInfo" : "A módosításokat elmentettük", 140 "settings.account.successInfo" : "A módosításokat elmentettük",
141 "settings.account.tryReloadServices" : "Próbáld újra",
120 "settings.account.tryReloadUserInfoRequest" : "Próbáld újra", 142 "settings.account.tryReloadUserInfoRequest" : "Próbáld újra",
121 "settings.account.userInfoRequestFailed" : "A felhasználói adatok betöltése sikertelen", 143 "settings.account.userInfoRequestFailed" : "A felhasználói adatok betöltése sikertelen",
122 "settings.app.buttonClearAllCache" : "Gyorsítótár törlése", 144 "settings.app.buttonClearAllCache" : "Gyorsítótár törlése",
123 "settings.app.buttonInstallUpdate" : "Újraindítás és frissítések telepítése", 145 "settings.app.buttonInstallUpdate" : "Újraindítás és frissítések telepítése",
124 "settings.app.buttonSearchForUpdate" : "Frissítések keresése", 146 "settings.app.buttonSearchForUpdate" : "Frissítések keresése",
125 "settings.app.cacheInfo" : "A Franz gyorsítótár jelenleg {space} lemezterületet használ.", 147 "settings.app.cacheInfo" : "A Franz gyorsítótár jelenleg {size} lemezterületet használ.",
126 "settings.app.currentVersion" : "Aktuális verzió:", 148 "settings.app.currentVersion" : "Aktuális verzió:",
127 "settings.app.form.autoLaunchInBackground" : "Megnyitás háttérben", 149 "settings.app.form.autoLaunchInBackground" : "Megnyitás háttérben",
128 "settings.app.form.autoLaunchOnStart" : "Franz betöltése indításkor", 150 "settings.app.form.autoLaunchOnStart" : "Franz betöltése indításkor",
129 "settings.app.form.beta" : "Béta verziók keresése", 151 "settings.app.form.beta" : "Béta verziók keresése",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Csatlakozz a Sötét Oldalhoz",
131 "settings.app.form.enableGPUAcceleration" : "hardveres gyorsítás engedélyezése", 153 "settings.app.form.enableGPUAcceleration" : "Hardveres gyorsítás engedélyezése",
132 "settings.app.form.enableMenuBar" : "Franz megjelenítése a menüsorban",
133 "settings.app.form.enableSpellchecking" : "Helyesírás-ellenőrzés engedélyezése", 154 "settings.app.form.enableSpellchecking" : "Helyesírás-ellenőrzés engedélyezése",
134 "settings.app.form.enableSystemTray" : "Franz mutatása a tálcán", 155 "settings.app.form.enableSystemTray" : "Franz mutatása a tálcán",
135 "settings.app.form.hideDockIcon" : "Franz ikon elrejtése a Dock mögött",
136 "settings.app.form.language" : "Nyelv", 156 "settings.app.form.language" : "Nyelv",
137 "settings.app.form.minimizeToSystemTray" : "Franz kicsinyítése a tálcára", 157 "settings.app.form.minimizeToSystemTray" : "Franz kicsinyítése a tálcára",
138 "settings.app.form.runInBackground" : "Franz fusson a háttérben az ablak bezárásakor", 158 "settings.app.form.runInBackground" : "Franz fusson a háttérben az ablak bezárásakor",
139 "settings.app.form.showDisabledServices" : "Letiltott szolgáltatások megjelenítése", 159 "settings.app.form.showDisabledServices" : "Letiltott szolgáltatások megjelenítése",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Mutass az 'olvasatlan üzenet' jelzést amikor az értesítések le vannak tiltva.", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Mutassa az 'olvasatlan üzenet' jelzést, amikor az értesítések le vannak tiltva",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Beállítások", 161 "settings.app.headline" : "Beállítások",
143 "settings.app.headlineAdvanced" : "Haladó", 162 "settings.app.headlineAdvanced" : "Haladó",
144 "settings.app.headlineAppearance" : "Megjelenés", 163 "settings.app.headlineAppearance" : "Megjelenés",
145 "settings.app.headlineGeneral" : "Ãltalános", 164 "settings.app.headlineGeneral" : "Ãltalános",
146 "settings.app.headlineLanguage" : "Nyelv", 165 "settings.app.headlineLanguage" : "Nyelv",
147 "settings.app.headlineUpdates" : "Frissítések", 166 "settings.app.headlineUpdates" : "Frissítések",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Újraindítást igénylő módosítás", 168 "settings.app.restartRequired" : "Újraindítást igénylő módosítás",
149 "settings.app.subheadlineCache" : "Gyorsítótár", 169 "settings.app.subheadlineCache" : "Gyorsítótár",
150 "settings.app.translationHelp" : "Segíts nekünk a Franz-ot lefordítani a nyelvedre.", 170 "settings.app.translationHelp" : "Segíts nekünk a Franz-ot lefordítani a nyelvedre.",
151 "settings.app.updateStatusAvailable" : "Frissítés elérhető, letöltés folyamatban...", 171 "settings.app.updateStatusAvailable" : "Frissítés elérhető, letöltés folyamatban...",
152 "settings.app.updateStatusSearching" : "Frissítéseket keres", 172 "settings.app.updateStatusSearching" : "Frissítéseket keres",
153 "settings.app.updateStatusUpToDate" : "A Franz legfrissebb verzióját használod", 173 "settings.app.updateStatusUpToDate" : "A Franz legfrissebb verzióját használod",
154 "settings.invite.headline" : "Barát meghívása", 174 "settings.invite.headline" : "Barátok meghívása",
155 "settings.navigation.account" : "Fiók", 175 "settings.navigation.account" : "Fiók",
156 "settings.navigation.availableServices" : "Elérhető szolgáltatások", 176 "settings.navigation.availableServices" : "Elérhető szolgáltatások",
157 "settings.navigation.inviteFriends" : "Barát meghívása", 177 "settings.navigation.inviteFriends" : "Barát meghívása",
158 "settings.navigation.logout" : "Kijelentkezés", 178 "settings.navigation.logout" : "Kijelentkezés",
159 "settings.navigation.settings" : "Beállítások", 179 "settings.navigation.settings" : "Beállítások",
180 "settings.navigation.team" : "Csapat kezelése",
160 "settings.navigation.yourServices" : "Szolgáltatásaid", 181 "settings.navigation.yourServices" : "Szolgáltatásaid",
182 "settings.navigation.yourWorkspaces" : "Munkaterületeid",
161 "settings.recipes.all" : "Összes szolgáltatás", 183 "settings.recipes.all" : "Összes szolgáltatás",
162 "settings.recipes.dev" : "Fejlesztés", 184 "settings.recipes.dev" : "Fejlesztés",
163 "settings.recipes.headline" : "Elérhető szolgáltatások", 185 "settings.recipes.headline" : "Elérhető szolgáltatások",
164 "settings.recipes.missingService" : "Hiányzik egy szolgáltatás?", 186 "settings.recipes.missingService" : "Hiányzik egy szolgáltatás?",
165 "settings.recipes.mostPopular" : "Legnépszerűbb", 187 "settings.recipes.mostPopular" : "Legnépszerűbb",
166 "settings.recipes.nothingFound" : "Sajnáljuk, nincs egyezés a szolgáltatások között a keresett kifejezésre.", 188 "settings.recipes.nothingFound" : "Sajnáljuk, nincs egyezés a szolgáltatások között a keresett kifejezésre.",
167 "settings.recipes.servicesSuccessfulAddedInfo" : "Szolgáltatás sikeresen hozzáadva.", 189 "settings.recipes.servicesSuccessfulAddedInfo" : "Szolgáltatás sikeresen hozzáadva",
168 "settings.searchService" : "Szolgáltatások keresése", 190 "settings.searchService" : "Szolgáltatások keresése",
169 "settings.service.error.goBack" : "Vissza a szolgáltatásokhoz", 191 "settings.service.error.goBack" : "Vissza a szolgáltatásokhoz",
170 "settings.service.error.headline" : "Hiba", 192 "settings.service.error.headline" : "Hiba",
@@ -174,12 +196,12 @@
174 "settings.service.form.customUrl" : "Egyéni szerver", 196 "settings.service.form.customUrl" : "Egyéni szerver",
175 "settings.service.form.customUrlPremiumInfo" : "Egyénileg üzemeltetett szolgáltatások hozzáadásához Franz Prémium Támogató Fiók szükséges.", 197 "settings.service.form.customUrlPremiumInfo" : "Egyénileg üzemeltetett szolgáltatások hozzáadásához Franz Prémium Támogató Fiók szükséges.",
176 "settings.service.form.customUrlUpgradeAccount" : "Frissítsd fiókodat", 198 "settings.service.form.customUrlUpgradeAccount" : "Frissítsd fiókodat",
177 "settings.service.form.customUrlValidationError" : "Nem sikerült hitelesíteni az egyéni {name} szervert.", 199 "settings.service.form.customUrlValidationError" : "Nem sikerült érvényesíteni az egyéni {name} kiszolgálót.",
178 "settings.service.form.deleteButton" : "Szolgáltatás törlése", 200 "settings.service.form.deleteButton" : "Szolgáltatás törlése",
179 "settings.service.form.editServiceHeadline" : "{name} szerkesztése", 201 "settings.service.form.editServiceHeadline" : "{name} szerkesztése",
180 "settings.service.form.enableAudio" : "Hang engedélyezése", 202 "settings.service.form.enableAudio" : "Hang engedélyezése",
181 "settings.service.form.enableBadge" : "Mutasd az olvasatlan jelzéseket", 203 "settings.service.form.enableBadge" : "Mutasd az olvasatlan jelzéseket",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Sötét mód engedélyezése",
183 "settings.service.form.enableNotification" : "Értesítések engedélyezése", 205 "settings.service.form.enableNotification" : "Értesítések engedélyezése",
184 "settings.service.form.enableService" : "Szolgáltatás engedélyezése", 206 "settings.service.form.enableService" : "Szolgáltatás engedélyezése",
185 "settings.service.form.headlineBadges" : "Olvasatlan üzenet jelzések", 207 "settings.service.form.headlineBadges" : "Olvasatlan üzenet jelzések",
@@ -188,34 +210,39 @@
188 "settings.service.form.icon" : "Egyedi ikon", 210 "settings.service.form.icon" : "Egyedi ikon",
189 "settings.service.form.iconDelete" : "Törlés", 211 "settings.service.form.iconDelete" : "Törlés",
190 "settings.service.form.iconUpload" : "Húzd ide a képet, vagy kattints ide", 212 "settings.service.form.iconUpload" : "Húzd ide a képet, vagy kattints ide",
191 "settings.service.form.indirectMessageInfo" : "Értesítést kapsz minden üzenetről a csatornában, nem csak @felhasználónév, @csatorna @here és egyéb említések esetén", 213 "settings.service.form.indirectMessageInfo" : "Értesítést kapsz minden üzenetről a csatornában, nem csak @felhasználónév, @csatorna, @here és egyéb említések esetén",
192 "settings.service.form.indirectMessages" : "Üzenet kitűző megjelenítése minden üzenethez", 214 "settings.service.form.indirectMessages" : "Üzenet kitűző megjelenítése minden üzenethez",
193 "settings.service.form.isMutedInfo" : "Ha kikapcsolod, minden értesítési és lejátszott hang némításra kerül.", 215 "settings.service.form.isMutedInfo" : "Ha kikapcsolod, minden értesítési és lejátszott hang némításra kerül",
194 "settings.service.form.name" : "Név", 216 "settings.service.form.name" : "Név",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy beállítások",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "Proxy beállítások nem szinkronizálódnak a Franz kiszolgálókkal.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Proxy használata",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Jelszó (opcionális)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Kérjük indítsd újra a Franz-ot a proxy beállítások megváltoztatása után.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Felhasználó (opcionális)",
203 "settings.service.form.saveButton" : "Szolgáltatás mentése", 225 "settings.service.form.saveButton" : "Szolgáltatás mentése",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Ãœzemeltetett", 226 "settings.service.form.tabHosted" : "Ãœzemeltetett",
207 "settings.service.form.tabOnPremise" : "Egyénileg üzemeltetett", 227 "settings.service.form.tabOnPremise" : "Egyénileg üzemeltetett",
208 "settings.service.form.team" : "Csapat", 228 "settings.service.form.team" : "Csapat",
209 "settings.service.form.useHostedService" : "A távoli {name} szolgáltatás használata", 229 "settings.service.form.useHostedService" : "A távoli {name} szolgáltatás használata.",
210 "settings.service.form.yourServices" : "Szolgáltatásaid", 230 "settings.service.form.yourServices" : "Szolgáltatásaid",
211 "settings.services.deletedInfo" : "A szolgáltatás törlésre került", 231 "settings.services.deletedInfo" : "A szolgáltatás törlésre került",
212 "settings.services.discoverServices" : "Szolgáltatások felfedezése", 232 "settings.services.discoverServices" : "Szolgáltatások felfedezése",
213 "settings.services.headline" : "Szolgáltatásaid", 233 "settings.services.headline" : "Szolgáltatásaid",
214 "settings.services.noServicesAdded" : "Még nem adtál hozzá egyetlen szolgáltatást sem eddig.", 234 "settings.services.noServicesAdded" : "Még nem adtál hozzá egyetlen szolgáltatást sem eddig.",
215 "settings.services.tooltip.isDisabled" : "Ez a szolgáltatás le van tiltva.", 235 "settings.services.servicesRequestFailed" : "Could not load your services",
236 "settings.services.tooltip.isDisabled" : "A szolgáltatás le van tiltva",
216 "settings.services.tooltip.isMuted" : "Minden hang lenémítva", 237 "settings.services.tooltip.isMuted" : "Minden hang lenémítva",
217 "settings.services.tooltip.notificationsDisabled" : "Értesítések letiltva", 238 "settings.services.tooltip.notificationsDisabled" : "Értesítések letiltva",
218 "settings.services.updatedInfo" : "A módosításokat elmentettük", 239 "settings.services.updatedInfo" : "A módosításokat elmentettük",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Csapat",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Cég", 246 "settings.user.form.accountType.company" : "Cég",
220 "settings.user.form.accountType.individual" : "Egyén", 247 "settings.user.form.accountType.individual" : "Egyén",
221 "settings.user.form.accountType.label" : "Fiók típusa", 248 "settings.user.form.accountType.label" : "Fiók típusa",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Keresztnév", 252 "settings.user.form.firstname" : "Keresztnév",
226 "settings.user.form.lastname" : "Vezetéknév", 253 "settings.user.form.lastname" : "Vezetéknév",
227 "settings.user.form.newPassword" : "Új jelszó", 254 "settings.user.form.newPassword" : "Új jelszó",
255 "settings.workspace.add.form.name" : "Név",
256 "settings.workspace.add.form.submitButton" : "Új munkaterület",
257 "settings.workspace.form.buttonDelete" : "Munkaterület törlése",
258 "settings.workspace.form.buttonSave" : "Munkaterület mentése",
259 "settings.workspace.form.name" : "Név",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Szolgáltatások ezen a Munkaterületen",
261 "settings.workspace.form.yourWorkspaces" : "Munkaterületeid",
262 "settings.workspaces.deletedInfo" : "Munkaterület törölve",
263 "settings.workspaces.headline" : "Munkaterületeid",
264 "settings.workspaces.noWorkspacesAdded" : "Még nem hoztál létre munkaterületeket.",
265 "settings.workspaces.tryReloadWorkspaces" : "Próbáld újra",
266 "settings.workspaces.updatedInfo" : "A módosításokat elmentettük",
267 "settings.workspaces.workspaceFeatureHeadline" : "A kevesebb több: Bemutatjuk a Franz Munkaterületeket",
268 "settings.workspaces.workspaceFeatureInfo" : "A Franz Munkaterületek lehetÅ‘vé teszik, hogy összpontosíts a jelenleg fontos dolgokra. Ãllítsd be a különbözÅ‘ szolgáltatáskészleteket és könnyedén válthatsz közöttük bármikor. Te döntöd el, hogy mely szolgáltatásokra van szükséged, mikor és hol, így segíthetünk abban, hogy a teljesítményed csúcsán maradhass, vagy ha csak akarod, egyszerűen kikapcsold a munkával kapcsolatos dolgokat.",
269 "settings.workspaces.workspacesRequestFailed" : "Nem sikerült betölteni a munkaterületeket",
228 "sidebar.addNewService" : "Szolgáltatás hozzáadása", 270 "sidebar.addNewService" : "Szolgáltatás hozzáadása",
271 "sidebar.closeWorkspaceDrawer" : "Munkaterület panel bezárása",
229 "sidebar.muteApp" : "Értesítések és hangok letiltása", 272 "sidebar.muteApp" : "Értesítések és hangok letiltása",
273 "sidebar.openWorkspaceDrawer" : "Munkaterület panel megnyitása",
230 "sidebar.settings" : "Beállítások", 274 "sidebar.settings" : "Beállítások",
231 "sidebar.unmuteApp" : "Értesítések és hangok engedélyezése", 275 "sidebar.unmuteApp" : "Értesítések és hangok engedélyezése",
232 "signup.company.label" : "Cég", 276 "signup.company.label" : "Cég",
@@ -243,13 +287,12 @@
243 "signup.submit.label" : "Fiók létrehozása", 287 "signup.submit.label" : "Fiók létrehozása",
244 "subscription.euTaxInfo" : "EU állampolgárok: helyi vásárlás esetén adók kerülhetnek felszámolásra", 288 "subscription.euTaxInfo" : "EU állampolgárok: helyi vásárlás esetén adók kerülhetnek felszámolásra",
245 "subscription.features.ads" : "Hirdetésmentes, mindig!", 289 "subscription.features.ads" : "Hirdetésmentes, mindig!",
246 "subscription.features.comingSoon" : "Hamarosan!", 290 "subscription.features.comingSoon" : "hamarosan",
247 "subscription.features.encryptedSync" : "Titkosított munkamenet szinkronizálás", 291 "subscription.features.noInterruptions" : "Nincs több app késlekedés és liszencfrissítési piszkálás",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Saját kiszolgálós szolgáltatások hozzáadása, pl.: Mattermost",
249 "subscription.features.onpremise" : "Helyi\/üzemeltetett szolgáltatások használata, pl. HipChat", 293 "subscription.features.proxy" : "Proxy támogatás a szolgáltatásokhoz",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Támogatás a Helyesírás-ellenőrzőhöz",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Az előfizetett Franz Prémium Támogató Fiók tartalmazza", 296 "subscription.includedFeatures" : "Az előfizetett Franz Prémium Támogató Fiók tartalmazza",
254 "subscription.paymentSessionError" : "Nem sikerült a fizetési felületet betölteni", 297 "subscription.paymentSessionError" : "Nem sikerült a fizetési felületet betölteni",
255 "subscription.submit.label" : "Szeretném támogatni a Franz fejlesztését", 298 "subscription.submit.label" : "Szeretném támogatni a Franz fejlesztését",
@@ -268,10 +311,21 @@
268 "tabs.item.enableService" : "Szolgáltatás engedélyezése", 311 "tabs.item.enableService" : "Szolgáltatás engedélyezése",
269 "tabs.item.reload" : "Újratöltés", 312 "tabs.item.reload" : "Újratöltés",
270 "validation.email" : "{field} nem érvényes", 313 "validation.email" : "{field} nem érvényes",
271 "validation.minLength" : "{field} legalább {length} karakter hosszúnak kell lennie", 314 "validation.minLength" : "{field} mezőnek legalább {length} karakter hosszúnak kell lennie",
272 "validation.required" : "{field} Kitöltése kötelező", 315 "validation.oneRequired" : "At least one is required",
316 "validation.required" : "{field} kitöltése kötelező",
273 "validation.url" : "{field} nem érvényes URL", 317 "validation.url" : "{field} nem érvényes URL",
274 "welcome.loginButton" : "Jelentkezz be a fiókodba", 318 "welcome.loginButton" : "Jelentkezz be a fiókodba",
275 "welcome.signupButton" : "Új fiók létrehozása", 319 "welcome.signupButton" : "Új fiók létrehozása",
276 "welcome.slogan" : "Üzenetküldés okosan" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Összes szolgáltatás",
322 "workspaceDrawer.headline" : "Munkaterületek",
323 "workspaceDrawer.item.contextMenuEdit" : "szerkeszt",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Készítsd el az első munkaterületedet",
326 "workspaceDrawer.proFeatureBadge" : "Prémium funkció",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Prémium fiók reaktiválása",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Munkaterület beállítások szerkesztése",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/id.json b/src/i18n/locales/id.json
index 11596d142..e7a46e5e9 100644
--- a/src/i18n/locales/id.json
+++ b/src/i18n/locales/id.json
@@ -1,16 +1,28 @@
1{ 1{
2 "app.errorHandler.action" : "Muat Ulang", 2 "app.errorHandler.action" : "Muat Ulang",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Terjadi kesalahan",
4 "feature.delayApp.action" : "Dapatkan Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Perubahan dalam Franz {version}",
5 "feature.delayApp.headline" : "Beli Franz Supporter License agar tidak perlu menunggu", 5 "feature.delayApp.action" : "Dapatkan Lisensi Pendukung Franz",
6 "feature.delayApp.headline" : "Beli Lisensi Pendukung Franz agar tidak perlu menunggu",
6 "feature.delayApp.text" : "Franz akan melanjutkan dalam {seconds} detik.", 7 "feature.delayApp.text" : "Franz akan melanjutkan dalam {seconds} detik.",
8 "feature.shareFranz.action.email" : "Kirim sebagai email",
9 "feature.shareFranz.action.facebook" : "Bagikan di Facebook",
10 "feature.shareFranz.action.twitter" : "Bagikan di Twitter",
11 "feature.shareFranz.headline" : "Franz lebih baik bersama!",
12 "feature.shareFranz.shareText.email" : "Saya telah menambahkan layanan {count} ke Franz! Dapatkan aplikasi gratis untuk WhatsApp, Messenger, Slack, Skype dan co di www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Beri tahu teman dan kolega Anda betapa hebatnya Franz dan bantu kami menyebarkan berita.",
7 "global.api.unhealthy" : "Tidak dapat tersambung ke layanan Franz", 15 "global.api.unhealthy" : "Tidak dapat tersambung ke layanan Franz",
8 "global.notConnectedToTheInternet" : "Anda tidak tersambung ke internet.", 16 "global.notConnectedToTheInternet" : "Anda tidak tersambung ke internet.",
17 "global.spellchecker.useDefault" : "Gunakan Bawaan Sistem ({default})",
18 "global.spellchecking.autodetect" : "Deteksi bahasa secara otomatis",
19 "global.spellchecking.autodetect.short" : "Otomatis",
20 "global.spellchecking.language" : "Periksa ejaan",
9 "import.headline" : "Impor layanan Franz 4 Anda", 21 "import.headline" : "Impor layanan Franz 4 Anda",
10 "import.notSupportedHeadline" : "Layanan belum didukung di Franz 5", 22 "import.notSupportedHeadline" : "Layanan belum didukung di Franz 5",
11 "import.skip.label" : "Saya ingin menambahkan layanan secara manual", 23 "import.skip.label" : "Saya ingin menambahkan layanan secara manual",
12 "import.submit.label" : "Impor layanan", 24 "import.submit.label" : "Impor layanan",
13 "infobar.buttonChangelog" : "Apa yang baru?", 25 "infobar.buttonChangelog" : "Yang baru",
14 "infobar.buttonInstallUpdate" : "Mulai ulang & instal pembaruan", 26 "infobar.buttonInstallUpdate" : "Mulai ulang & instal pembaruan",
15 "infobar.buttonReloadServices" : "Muat ulang layanan", 27 "infobar.buttonReloadServices" : "Muat ulang layanan",
16 "infobar.requiredRequestsFailed" : "Gagal memuat layanan dan informasi pengguna", 28 "infobar.requiredRequestsFailed" : "Gagal memuat layanan dan informasi pengguna",
@@ -19,12 +31,12 @@
19 "invite.email.label" : "Alamat email", 31 "invite.email.label" : "Alamat email",
20 "invite.headline.friends" : "Undang 3 teman atau kolega Anda", 32 "invite.headline.friends" : "Undang 3 teman atau kolega Anda",
21 "invite.name.label" : "Nama", 33 "invite.name.label" : "Nama",
22 "invite.skip.label" : "Nanti saja", 34 "invite.skip.label" : "Saya ingin melakukan ini nanti",
23 "invite.submit.label" : "Kirim undangan", 35 "invite.submit.label" : "Kirim undangan",
24 "invite.successInfo" : "Undangan berhasil dikirim", 36 "invite.successInfo" : "Undangan berhasil dikirim",
25 "login.email.label" : "Alamat email", 37 "login.email.label" : "Alamat email",
26 "login.headline" : "Masuk", 38 "login.headline" : "Masuk",
27 "login.invalidCredentials" : "Email atau sandi salah", 39 "login.invalidCredentials" : "Email atau kata sandi tidak valid",
28 "login.link.password" : "Setel ulang sandi", 40 "login.link.password" : "Setel ulang sandi",
29 "login.link.signup" : "Buat akun gratis", 41 "login.link.signup" : "Buat akun gratis",
30 "login.password.label" : "Sandi", 42 "login.password.label" : "Sandi",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Masuk", 44 "login.submit.label" : "Masuk",
33 "login.tokenExpired" : "Sesi Anda telah kedaluwarsa, silakan masuk kembali.", 45 "login.tokenExpired" : "Sesi Anda telah kedaluwarsa, silakan masuk kembali.",
34 "menu.app.about" : "Tentang Franz", 46 "menu.app.about" : "Tentang Franz",
47 "menu.app.announcement" : "Yang baru",
35 "menu.app.hide" : "Sembunyikan", 48 "menu.app.hide" : "Sembunyikan",
36 "menu.app.hideOthers" : "Sembunyikan Lainnya", 49 "menu.app.hideOthers" : "Sembunyikan Lainnya",
37 "menu.app.quit" : "Keluar", 50 "menu.app.quit" : "Keluar",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Dukungan", 72 "menu.help.support" : "Dukungan",
60 "menu.help.tos" : "Ketentuan Layanan", 73 "menu.help.tos" : "Ketentuan Layanan",
61 "menu.services" : "Layanan", 74 "menu.services" : "Layanan",
75 "menu.services.activatePreviousService" : "Aktifkan layanan sebelumnya",
62 "menu.services.addNewService" : "Tambahkan Layanan Baru...", 76 "menu.services.addNewService" : "Tambahkan Layanan Baru...",
77 "menu.services.setNextServiceActive" : "Aktifkan layanan berikutnya",
63 "menu.view" : "Tampilan", 78 "menu.view" : "Tampilan",
64 "menu.view.enterFullScreen" : "Masuk ke Mode Layar Penuh", 79 "menu.view.enterFullScreen" : "Masuk ke Mode Layar Penuh",
65 "menu.view.exitFullScreen" : "Keluar dari Layar Penuh", 80 "menu.view.exitFullScreen" : "Keluar dari Layar Penuh",
@@ -74,6 +89,11 @@
74 "menu.window" : "Jendela", 89 "menu.window" : "Jendela",
75 "menu.window.close" : "Tutup", 90 "menu.window.close" : "Tutup",
76 "menu.window.minimize" : "Minimalkan", 91 "menu.window.minimize" : "Minimalkan",
92 "menu.workspaces" : "Ruang kerja",
93 "menu.workspaces.addNewWorkspace" : "Tambah Ruang Kerja Baru...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Tutup laci ruang kerja",
95 "menu.workspaces.defaultWorkspace" : "Semua layanan",
96 "menu.workspaces.openWorkspaceDrawer" : "Buka laci ruang kerja",
77 "password.email.label" : "Alamat email", 97 "password.email.label" : "Alamat email",
78 "password.headline" : "Setel ulang sandi", 98 "password.headline" : "Setel ulang sandi",
79 "password.link.login" : "Masuk ke akun Anda", 99 "password.link.login" : "Masuk ke akun Anda",
@@ -92,19 +112,20 @@
92 "service.crashHandler.text" : "{name} menyebabkan kesalahan.", 112 "service.crashHandler.text" : "{name} menyebabkan kesalahan.",
93 "service.disabledHandler.action" : "Aktifkan {name}", 113 "service.disabledHandler.action" : "Aktifkan {name}",
94 "service.disabledHandler.headline" : "{name} dinonaktifkan", 114 "service.disabledHandler.headline" : "{name} dinonaktifkan",
95 "service.errorHandler.action" : "Muat Ulang {name}", 115 "service.errorHandler.action" : "Muat ulang {name}",
96 "service.errorHandler.editAction" : "Edit {nama}", 116 "service.errorHandler.editAction" : "Edit {nama}",
97 "service.errorHandler.headline" : "Ya Ampun!", 117 "service.errorHandler.headline" : "Oh tidak!",
98 "service.errorHandler.message" : "Kesalahan", 118 "service.errorHandler.message" : "Kesalahan",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} gagal dimuat",
100 "services.getStarted" : "Ayo mulai!", 120 "service.webviewLoader.loading" : "Memuat",
121 "services.getStarted" : "Memulai",
101 "services.welcome" : "Selamat datang di Franz", 122 "services.welcome" : "Selamat datang di Franz",
102 "settings.account.account.editButton" : "Edit akun", 123 "settings.account.account.editButton" : "Edit akun",
103 "settings.account.accountType.basic" : "Akun Dasar", 124 "settings.account.accountType.basic" : "Akun Dasar",
104 "settings.account.accountType.premium" : "Akun Pendukung Premium", 125 "settings.account.accountType.premium" : "Akun Pendukung Premium",
105 "settings.account.buttonSave" : "Perbarui profil", 126 "settings.account.buttonSave" : "Perbarui profil",
106 "settings.account.deleteAccount" : "Hapus akun", 127 "settings.account.deleteAccount" : "Hapus akun",
107 "settings.account.deleteEmailSent" : "Anda akan menerima email yang berisi tautan untuk melakukan konfirmasi penghapusan akun. Akun dan data Anda tidak bisa dipulihkan!", 128 "settings.account.deleteEmailSent" : "Anda menerima email dengan tautan untuk mengonfirmasi penghapusan akun. Akun dan data Anda tidak bisa dipulihkan!",
108 "settings.account.deleteInfo" : "Jika Anda tidak membutuhkan akun Franz lagi, Anda bisa menghapus akun dan semua data terkait di sini.", 129 "settings.account.deleteInfo" : "Jika Anda tidak membutuhkan akun Franz lagi, Anda bisa menghapus akun dan semua data terkait di sini.",
109 "settings.account.headline" : "Akun", 130 "settings.account.headline" : "Akun",
110 "settings.account.headlineAccount" : "Informasi akun", 131 "settings.account.headlineAccount" : "Informasi akun",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Unduh", 138 "settings.account.invoiceDownload" : "Unduh",
118 "settings.account.manageSubscription.label" : "Kelola langganan Anda", 139 "settings.account.manageSubscription.label" : "Kelola langganan Anda",
119 "settings.account.successInfo" : "Perubahan Anda telah disimpan", 140 "settings.account.successInfo" : "Perubahan Anda telah disimpan",
141 "settings.account.tryReloadServices" : "Coba lagi",
120 "settings.account.tryReloadUserInfoRequest" : "Coba lagi", 142 "settings.account.tryReloadUserInfoRequest" : "Coba lagi",
121 "settings.account.userInfoRequestFailed" : "Gagal memuat informasi pengguna", 143 "settings.account.userInfoRequestFailed" : "Gagal memuat informasi pengguna",
122 "settings.app.buttonClearAllCache" : "Bersihkan singgahan", 144 "settings.app.buttonClearAllCache" : "Bersihkan singgahan",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Sertakan versi beta", 151 "settings.app.form.beta" : "Sertakan versi beta",
130 "settings.app.form.darkMode" : "Sisi Kelam menunggu Anda (Mode Gelap)", 152 "settings.app.form.darkMode" : "Sisi Kelam menunggu Anda (Mode Gelap)",
131 "settings.app.form.enableGPUAcceleration" : "Aktifkan Akselerasi GPU", 153 "settings.app.form.enableGPUAcceleration" : "Aktifkan Akselerasi GPU",
132 "settings.app.form.enableMenuBar" : "Tampilkan Franz di Bilah Menu",
133 "settings.app.form.enableSpellchecking" : "Aktifkan pemeriksaan ejaan", 154 "settings.app.form.enableSpellchecking" : "Aktifkan pemeriksaan ejaan",
134 "settings.app.form.enableSystemTray" : "Tampilkan Franz di baki sistem", 155 "settings.app.form.enableSystemTray" : "Tampilkan Franz di baki sistem",
135 "settings.app.form.hideDockIcon" : "Sembunyikan ikon Franz di Dock",
136 "settings.app.form.language" : "Bahasa", 156 "settings.app.form.language" : "Bahasa",
137 "settings.app.form.minimizeToSystemTray" : "Perkecil Franz ke baki sistem", 157 "settings.app.form.minimizeToSystemTray" : "Perkecil Franz ke baki sistem",
138 "settings.app.form.runInBackground" : "Tetap jalankan Franz di latar belakang saat menutup jendela", 158 "settings.app.form.runInBackground" : "Tetap jalankan Franz di latar belakang saat menutup jendela",
139 "settings.app.form.showDisabledServices" : "Tampilkan tab layanan yang dinonaktifkan", 159 "settings.app.form.showDisabledServices" : "Tampilkan tab layanan yang dinonaktifkan",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Tampilkan lencana pesan belum dibaca saat pemberitahuan dinonaktifkan", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Tampilkan lencana pesan belum dibaca saat pemberitahuan dinonaktifkan",
141 "settings.app.form.spellcheckerLanguage" : "Periksa ejaan",
142 "settings.app.headline" : "Pengaturan", 161 "settings.app.headline" : "Pengaturan",
143 "settings.app.headlineAdvanced" : "Tingkat Lanjut", 162 "settings.app.headlineAdvanced" : "Tingkat Lanjut",
144 "settings.app.headlineAppearance" : "Tampilan", 163 "settings.app.headlineAppearance" : "Tampilan",
145 "settings.app.headlineGeneral" : "Umum", 164 "settings.app.headlineGeneral" : "Umum",
146 "settings.app.headlineLanguage" : "Bahasa", 165 "settings.app.headlineLanguage" : "Bahasa",
147 "settings.app.headlineUpdates" : "Versi Baru", 166 "settings.app.headlineUpdates" : "Versi Baru",
167 "settings.app.languageDisclaimer" : "Penerjemahan resmi dilakukan untuk Bahasa Inggris dan Jerman. Bahasa lainnya merupakan penerjemahan oleh komunitas.",
148 "settings.app.restartRequired" : "Perubahan membutuhkan mulai ulang", 168 "settings.app.restartRequired" : "Perubahan membutuhkan mulai ulang",
149 "settings.app.subheadlineCache" : "Singgahan", 169 "settings.app.subheadlineCache" : "Singgahan",
150 "settings.app.translationHelp" : "Bantu kami menerjemahkan Franz ke bahasa Anda.", 170 "settings.app.translationHelp" : "Bantu kami menerjemahkan Franz ke bahasa Anda.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Undang Teman", 177 "settings.navigation.inviteFriends" : "Undang Teman",
158 "settings.navigation.logout" : "Keluar", 178 "settings.navigation.logout" : "Keluar",
159 "settings.navigation.settings" : "Pengaturan", 179 "settings.navigation.settings" : "Pengaturan",
180 "settings.navigation.team" : "Kelola Tim",
160 "settings.navigation.yourServices" : "Layanan Anda", 181 "settings.navigation.yourServices" : "Layanan Anda",
182 "settings.navigation.yourWorkspaces" : "Ruang kerja Anda",
161 "settings.recipes.all" : "Semua layanan", 183 "settings.recipes.all" : "Semua layanan",
162 "settings.recipes.dev" : "Pengembangan", 184 "settings.recipes.dev" : "Pengembangan",
163 "settings.recipes.headline" : "Layanan tersedia", 185 "settings.recipes.headline" : "Layanan tersedia",
@@ -167,7 +189,7 @@
167 "settings.recipes.servicesSuccessfulAddedInfo" : "Layanan berhasil ditambahkan", 189 "settings.recipes.servicesSuccessfulAddedInfo" : "Layanan berhasil ditambahkan",
168 "settings.searchService" : "Cari layanan", 190 "settings.searchService" : "Cari layanan",
169 "settings.service.error.goBack" : "Kembali ke layanan", 191 "settings.service.error.goBack" : "Kembali ke layanan",
170 "settings.service.error.headline" : "Kesalahan", 192 "settings.service.error.headline" : "Terjadi kesalahan",
171 "settings.service.error.message" : "Tidak dapat memuat konfigurasi layanan.", 193 "settings.service.error.message" : "Tidak dapat memuat konfigurasi layanan.",
172 "settings.service.form.addServiceHeadline" : "Tambahkan {name}", 194 "settings.service.form.addServiceHeadline" : "Tambahkan {name}",
173 "settings.service.form.availableServices" : "Layanan tersedia", 195 "settings.service.form.availableServices" : "Layanan tersedia",
@@ -176,7 +198,7 @@
176 "settings.service.form.customUrlUpgradeAccount" : "Tingkatkan akun Anda", 198 "settings.service.form.customUrlUpgradeAccount" : "Tingkatkan akun Anda",
177 "settings.service.form.customUrlValidationError" : "Gagal memvalidasi server {nama} khusus.", 199 "settings.service.form.customUrlValidationError" : "Gagal memvalidasi server {nama} khusus.",
178 "settings.service.form.deleteButton" : "Hapus layanan", 200 "settings.service.form.deleteButton" : "Hapus layanan",
179 "settings.service.form.editServiceHeadline" : "Edit {nama}", 201 "settings.service.form.editServiceHeadline" : "Edit {name}",
180 "settings.service.form.enableAudio" : "Aktifkan audio", 202 "settings.service.form.enableAudio" : "Aktifkan audio",
181 "settings.service.form.enableBadge" : "Tampilkan lencana pesan belum dibaca", 203 "settings.service.form.enableBadge" : "Tampilkan lencana pesan belum dibaca",
182 "settings.service.form.enableDarkMode" : "Aktifkan Mode Gelap", 204 "settings.service.form.enableDarkMode" : "Aktifkan Mode Gelap",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Tampilkan lencana pesan untuk semua pesan baru", 214 "settings.service.form.indirectMessages" : "Tampilkan lencana pesan untuk semua pesan baru",
193 "settings.service.form.isMutedInfo" : "Saat dinonaktifkan, semua suara pemberitahuan dan pemutaran audio akan dibisukan", 215 "settings.service.form.isMutedInfo" : "Saat dinonaktifkan, semua suara pemberitahuan dan pemutaran audio akan dibisukan",
194 "settings.service.form.name" : "Nama", 216 "settings.service.form.name" : "Nama",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Pengaturan Proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Host\/IP Proksi", 218 "settings.service.form.proxy.host" : "Host\/IP Proksi",
197 "settings.service.form.proxy.info" : "Pengaturan proksi tidak akan disinkronkan dengan server Franz.", 219 "settings.service.form.proxy.info" : "Pengaturan proksi tidak akan disinkronkan dengan server Franz.",
198 "settings.service.form.proxy.isEnabled" : "Gunakan Proksi", 220 "settings.service.form.proxy.isEnabled" : "Gunakan Proksi",
199 "settings.service.form.proxy.password" : "Sandi (opsional)", 221 "settings.service.form.proxy.password" : "Sandi (opsional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Silahkan mulai ulang Franz setelah mengubah Setelan proxy",
202 "settings.service.form.proxy.user" : "Pengguna (opsional)", 224 "settings.service.form.proxy.user" : "Pengguna (opsional)",
203 "settings.service.form.saveButton" : "Simpan layanan", 225 "settings.service.form.saveButton" : "Simpan layanan",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hosted", 226 "settings.service.form.tabHosted" : "Hosted",
207 "settings.service.form.tabOnPremise" : "Hosted mandiri", 227 "settings.service.form.tabOnPremise" : "Hosted mandiri",
208 "settings.service.form.team" : "Tim", 228 "settings.service.form.team" : "Tim",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Temukan layanan", 232 "settings.services.discoverServices" : "Temukan layanan",
213 "settings.services.headline" : "Layanan Anda", 233 "settings.services.headline" : "Layanan Anda",
214 "settings.services.noServicesAdded" : "Anda belum menambahkan layanan apa pun.", 234 "settings.services.noServicesAdded" : "Anda belum menambahkan layanan apa pun.",
235 "settings.services.servicesRequestFailed" : "Tidak dapat memuat layanan Anda",
215 "settings.services.tooltip.isDisabled" : "Layanan dinonaktifkan", 236 "settings.services.tooltip.isDisabled" : "Layanan dinonaktifkan",
216 "settings.services.tooltip.isMuted" : "Semua suara dibisukan", 237 "settings.services.tooltip.isMuted" : "Semua suara dibisukan",
217 "settings.services.tooltip.notificationsDisabled" : "Pemberitahuan dinonaktifkan", 238 "settings.services.tooltip.notificationsDisabled" : "Pemberitahuan dinonaktifkan",
218 "settings.services.updatedInfo" : "Perubahan telah disimpan", 239 "settings.services.updatedInfo" : "Perubahan telah disimpan",
240 "settings.team.contentHeadline" : "Franz untuk Tim",
241 "settings.team.copy" : "Franz untuk Tim menyediakan opsi untuk mengundang rekan kerja ke tim Anda dengan mengirimkan undangan email dan mengelola langganan mereka pada preferensi akun Anda. Jangan habiskan waktu Anda menyiapkan langganan bagi masing-masing anggota tim, lupakan berbagai faktur dan periode penagihan - satu tim untuk semua!",
242 "settings.team.headline" : "Tim",
243 "settings.team.intro" : "Anda dan tim Anda menggunakan Franz? Kini Anda bisa mengelola langganan Premium untuk semua rekan kerja, teman, atau anggota keluar sebanyak yang Anda inginkan, semuanya cukup dari satu akun.",
244 "settings.team.manageAction" : "Kelola Tim Anda di meetfranz.com",
245 "settings.team.upgradeAction" : "Tingkatkan Akun Anda",
219 "settings.user.form.accountType.company" : "Perusahaan", 246 "settings.user.form.accountType.company" : "Perusahaan",
220 "settings.user.form.accountType.individual" : "Pribadi", 247 "settings.user.form.accountType.individual" : "Pribadi",
221 "settings.user.form.accountType.label" : "Jenis akun", 248 "settings.user.form.accountType.label" : "Jenis akun",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Nama Depan", 252 "settings.user.form.firstname" : "Nama Depan",
226 "settings.user.form.lastname" : "Nama Belakang", 253 "settings.user.form.lastname" : "Nama Belakang",
227 "settings.user.form.newPassword" : "Sandi baru", 254 "settings.user.form.newPassword" : "Sandi baru",
255 "settings.workspace.add.form.name" : "Nama",
256 "settings.workspace.add.form.submitButton" : "Buat ruang kerja",
257 "settings.workspace.form.buttonDelete" : "Hapus ruang kerja",
258 "settings.workspace.form.buttonSave" : "Simpan ruang kerja",
259 "settings.workspace.form.name" : "Nama",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Layanan dalam Ruang Kerja ini",
261 "settings.workspace.form.yourWorkspaces" : "Ruang kerja Anda",
262 "settings.workspaces.deletedInfo" : "Ruang kerja telah dihapus",
263 "settings.workspaces.headline" : "Ruang kerja Anda",
264 "settings.workspaces.noWorkspacesAdded" : "Anda belum menambahkan ruang kerja.",
265 "settings.workspaces.tryReloadWorkspaces" : "Coba lagi",
266 "settings.workspaces.updatedInfo" : "Perubahan Anda telah disimpan",
267 "settings.workspaces.workspaceFeatureHeadline" : "Sedikit Namun Banyak: Memperkenalkan Ruang Kerja Franz",
268 "settings.workspaces.workspaceFeatureInfo" : "Ruang Kerja Franz dapat digunakan untuk tetap fokus pada hal penting saat ini. Siapkan sekelompok layanan yang berbeda dan dengan mudah beralih ke yang lain. Anda yang memutuskan layanan mana yang Anda perlukan dan kapan, agar kami bisa membantu Anda tetap berada di garis depan - atau dengan mudah mengakhiri hari kerja kapan saja Anda inginkan.",
269 "settings.workspaces.workspacesRequestFailed" : "Tidak dapat memuat ruang kerja Anda",
228 "sidebar.addNewService" : "Tambahkan layanan baru", 270 "sidebar.addNewService" : "Tambahkan layanan baru",
271 "sidebar.closeWorkspaceDrawer" : "Tutup laci ruang kerja",
229 "sidebar.muteApp" : "Nonaktifkan pemberitahuan & audio", 272 "sidebar.muteApp" : "Nonaktifkan pemberitahuan & audio",
273 "sidebar.openWorkspaceDrawer" : "Buka laci ruang kerja",
230 "sidebar.settings" : "Pengaturan", 274 "sidebar.settings" : "Pengaturan",
231 "sidebar.unmuteApp" : "Aktifkan pemberitahuan", 275 "sidebar.unmuteApp" : "Aktifkan pemberitahuan",
232 "signup.company.label" : "Perusahaan", 276 "signup.company.label" : "Perusahaan",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Warga UE: pajak penjualan lokal mungkin berlaku", 288 "subscription.euTaxInfo" : "Warga UE: pajak penjualan lokal mungkin berlaku",
245 "subscription.features.ads" : "Tanpa iklan, selamanya!", 289 "subscription.features.ads" : "Tanpa iklan, selamanya!",
246 "subscription.features.comingSoon" : "segera hadir", 290 "subscription.features.comingSoon" : "segera hadir",
247 "subscription.features.encryptedSync" : "Sinkronisasi sesi terenkripsi",
248 "subscription.features.noInterruptions" : "Tanpa menunggu dan ditanya untuk meningkatkan lisensi", 291 "subscription.features.noInterruptions" : "Tanpa menunggu dan ditanya untuk meningkatkan lisensi",
249 "subscription.features.onpremise" : "Integrasi layanan hosted, misalnya HipChat",
250 "subscription.features.onpremise.mattermost" : "Integrasi layanan hosted, misalnya Mattermost", 292 "subscription.features.onpremise.mattermost" : "Integrasi layanan hosted, misalnya Mattermost",
251 "subscription.features.proxy" : "Dukungan proksi untuk layanan", 293 "subscription.features.proxy" : "Dukungan proksi untuk layanan",
252 "subscription.features.spellchecker" : "Dukungan pengecek ejaan", 294 "subscription.features.spellchecker" : "Dukungan pengecek ejaan",
295 "subscription.features.workspaces" : "Kelola layanan Anda dalam ruang kerja",
253 "subscription.includedFeatures" : "Franz Premium Supporter Account berbayar menyertakan", 296 "subscription.includedFeatures" : "Franz Premium Supporter Account berbayar menyertakan",
254 "subscription.paymentSessionError" : "Tidak bisa menginisialisasi formulir pembayaran", 297 "subscription.paymentSessionError" : "Tidak bisa menginisialisasi formulir pembayaran",
255 "subscription.submit.label" : "Saya ingin mendukung pengembangan Franz", 298 "subscription.submit.label" : "Saya ingin mendukung pengembangan Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Muat Ulang", 312 "tabs.item.reload" : "Muat Ulang",
270 "validation.email" : "{field} tidak benar", 313 "validation.email" : "{field} tidak benar",
271 "validation.minLength" : "{field} setidaknya harus {length} karakter", 314 "validation.minLength" : "{field} setidaknya harus {length} karakter",
315 "validation.oneRequired" : "Setidaknya diperlukan satu",
272 "validation.required" : "{field} wajib diisi", 316 "validation.required" : "{field} wajib diisi",
273 "validation.url" : "{field} bukan URL yang benar", 317 "validation.url" : "{field} bukan URL yang benar",
274 "welcome.loginButton" : "Masuk ke akun Anda", 318 "welcome.loginButton" : "Masuk ke akun Anda",
275 "welcome.signupButton" : "Buat akun gratis", 319 "welcome.signupButton" : "Buat akun gratis",
276 "welcome.slogan" : "Perpesanan yang bekerja untuk Anda" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Tambah ruang kerja baru",
321 "workspaceDrawer.allServices" : "Semua layanan",
322 "workspaceDrawer.headline" : "Ruang kerja",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "Belum ada layanan yang ditambahkan",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Buat ruang kerja pertama Anda",
326 "workspaceDrawer.proFeatureBadge" : "Fitur premium",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Aktifkan ulang akun premium",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Ruang Kerja Franz dapat digunakan untuk tetap fokus pada hal penting saat ini. Siapkan sekelompok layanan yang berbeda dan dengan mudah beralih ke yang lain.<\/p><p>Anda yang memutuskan layanan mana yang Anda perlukan dan kapan, agar kami bisa membantu Anda tetap berada di garis depan - atau dengan mudah mengakhiri hari kerja kapan saja Anda inginkan.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit setelan ruang kerja",
330 "workspaces.switchingIndicator.switchingTo" : "Beralih ke"
277} 331}
diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json
index 47cbd8f1e..c12641e36 100644
--- a/src/i18n/locales/it.json
+++ b/src/i18n/locales/it.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Ricarica", 2 "app.errorHandler.action" : "Ricarica",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Qualcosa è andato storto",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Ricevi una Licenza Supporter di Franz", 5 "feature.delayApp.action" : "Ricevi una Licenza Supporter di Franz",
5 "feature.delayApp.headline" : "Per favore, compra una Licenza Supporter di Franz per saltare l'attesa", 6 "feature.delayApp.headline" : "Per favore, compra una Licenza Supporter di Franz per saltare l'attesa",
6 "feature.delayApp.text" : "Franz continuerà a funzionare tra {seconds} secondi.", 7 "feature.delayApp.text" : "Franz continuerà a funzionare tra {seconds} secondi.",
8 "feature.shareFranz.action.email" : "Manda come email",
9 "feature.shareFranz.action.facebook" : "Condividi su Facebook",
10 "feature.shareFranz.action.twitter" : "Condividi su Twitter",
11 "feature.shareFranz.headline" : "Franze è migliore insieme!",
12 "feature.shareFranz.shareText.email" : "Ho aggiunto {count} nuovi servizi a Franz! Scarica ora l'app gratuita per WhatsApp, Messenger, Slack, Skype e altri all'indirizzo www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Condividi con i tuoi amici e colleghi quanto Franz è fantastico e aiutaci a diffondere la parola.",
7 "global.api.unhealthy" : "Impossibile connettersi ai servizi online di Franz", 15 "global.api.unhealthy" : "Impossibile connettersi ai servizi online di Franz",
8 "global.notConnectedToTheInternet" : "Non sei connesso a Internet.", 16 "global.notConnectedToTheInternet" : "Non sei connesso a Internet.",
17 "global.spellchecker.useDefault" : "Usa le impostazioni predefinite di sistema ({default})",
18 "global.spellchecking.autodetect" : "Rileva automaticamente la lingua",
19 "global.spellchecking.autodetect.short" : "Automatico",
20 "global.spellchecking.language" : "Lingua per controllo ortografico",
9 "import.headline" : "Importa i servizi di Franz 4", 21 "import.headline" : "Importa i servizi di Franz 4",
10 "import.notSupportedHeadline" : "Servizi non ancora supportati in Franz 5", 22 "import.notSupportedHeadline" : "Servizi non ancora supportati in Franz 5",
11 "import.skip.label" : "Voglio aggiungere i servizi manualmente", 23 "import.skip.label" : "Voglio aggiungere i servizi manualmente",
@@ -32,8 +44,9 @@
32 "login.submit.label" : "Accedi", 44 "login.submit.label" : "Accedi",
33 "login.tokenExpired" : "La tua sessione è scaduta, per favore accedi di nuovo.", 45 "login.tokenExpired" : "La tua sessione è scaduta, per favore accedi di nuovo.",
34 "menu.app.about" : "Info su Franz", 46 "menu.app.about" : "Info su Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Nascondi", 48 "menu.app.hide" : "Nascondi",
36 "menu.app.hideOthers" : "Nascondi Altri", 49 "menu.app.hideOthers" : "Nascondi altri",
37 "menu.app.quit" : "Esci", 50 "menu.app.quit" : "Esci",
38 "menu.app.settings" : "Settings", 51 "menu.app.settings" : "Settings",
39 "menu.app.unhide" : "Mostra", 52 "menu.app.unhide" : "Mostra",
@@ -41,7 +54,7 @@
41 "menu.edit.copy" : "Copia", 54 "menu.edit.copy" : "Copia",
42 "menu.edit.cut" : "Taglia", 55 "menu.edit.cut" : "Taglia",
43 "menu.edit.delete" : "Elimina", 56 "menu.edit.delete" : "Elimina",
44 "menu.edit.emojiSymbols" : "Emoji e Simboli", 57 "menu.edit.emojiSymbols" : "Emoji e simboli",
45 "menu.edit.paste" : "Incolla", 58 "menu.edit.paste" : "Incolla",
46 "menu.edit.pasteAndMatchStyle" : "Incolla e Mantieni Stile", 59 "menu.edit.pasteAndMatchStyle" : "Incolla e Mantieni Stile",
47 "menu.edit.redo" : "Ripeti", 60 "menu.edit.redo" : "Ripeti",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Supporto", 72 "menu.help.support" : "Supporto",
60 "menu.help.tos" : "Termini di Servizio", 73 "menu.help.tos" : "Termini di Servizio",
61 "menu.services" : "Servizi", 74 "menu.services" : "Servizi",
75 "menu.services.activatePreviousService" : "Attiva servizio precedente",
62 "menu.services.addNewService" : "Aggiungi Nuovo Servizio...", 76 "menu.services.addNewService" : "Aggiungi Nuovo Servizio...",
77 "menu.services.setNextServiceActive" : "Attiva servizio seguente",
63 "menu.view" : "Visualizza", 78 "menu.view" : "Visualizza",
64 "menu.view.enterFullScreen" : "Visualizza a Schermo Intero", 79 "menu.view.enterFullScreen" : "Visualizza a Schermo Intero",
65 "menu.view.exitFullScreen" : "Esci da Schermo Intero", 80 "menu.view.exitFullScreen" : "Esci da Schermo Intero",
@@ -74,6 +89,11 @@
74 "menu.window" : "Finestra", 89 "menu.window" : "Finestra",
75 "menu.window.close" : "Chiudi", 90 "menu.window.close" : "Chiudi",
76 "menu.window.minimize" : "Minimizza", 91 "menu.window.minimize" : "Minimizza",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Tutti i servizi",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Indirizzo email", 97 "password.email.label" : "Indirizzo email",
78 "password.headline" : "Reimposta password", 98 "password.headline" : "Reimposta password",
79 "password.link.login" : "Accedi al tuo account", 99 "password.link.login" : "Accedi al tuo account",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Non è stato trovato nessun utente con questo indirizzo e-mail", 101 "password.noUser" : "Non è stato trovato nessun utente con questo indirizzo e-mail",
82 "password.submit.label" : "Invia", 102 "password.submit.label" : "Invia",
83 "password.successInfo" : "Per favore controlla la tua email", 103 "password.successInfo" : "Per favore controlla la tua email",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Effettua l'upgrade del tuo account",
85 "pricing.headline" : "Supporta Franz", 105 "pricing.headline" : "Supporta Franz",
86 "pricing.link.skipPayment" : "Non voglio supportare lo sviluppo di Franz", 106 "pricing.link.skipPayment" : "Non voglio supportare lo sviluppo di Franz",
87 "pricing.submit.label" : "Voglio supportare lo sviluppo di Franz", 107 "pricing.submit.label" : "Voglio supportare lo sviluppo di Franz",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Modifica {name}", 116 "service.errorHandler.editAction" : "Modifica {name}",
97 "service.errorHandler.headline" : "Oh no!", 117 "service.errorHandler.headline" : "Oh no!",
98 "service.errorHandler.message" : "Errore", 118 "service.errorHandler.message" : "Errore",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} non si è caricato correttamente.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Iniziamo", 121 "services.getStarted" : "Iniziamo",
101 "services.welcome" : "Benvenuto su Franz", 122 "services.welcome" : "Benvenuto su Franz",
102 "settings.account.account.editButton" : "Modifica account", 123 "settings.account.account.editButton" : "Modifica account",
@@ -117,7 +138,8 @@
117 "settings.account.invoiceDownload" : "Scarica", 138 "settings.account.invoiceDownload" : "Scarica",
118 "settings.account.manageSubscription.label" : "Gestisci il tuo abbonamento", 139 "settings.account.manageSubscription.label" : "Gestisci il tuo abbonamento",
119 "settings.account.successInfo" : "Le tue modifiche sono state salvate", 140 "settings.account.successInfo" : "Le tue modifiche sono state salvate",
120 "settings.account.tryReloadUserInfoRequest" : "Prova di nuovo", 141 "settings.account.tryReloadServices" : "Prova di nuovo",
142 "settings.account.tryReloadUserInfoRequest" : "Riprova",
121 "settings.account.userInfoRequestFailed" : "Impossibile caricare le informazioni dell'utente.", 143 "settings.account.userInfoRequestFailed" : "Impossibile caricare le informazioni dell'utente.",
122 "settings.app.buttonClearAllCache" : "Svuota la cache", 144 "settings.app.buttonClearAllCache" : "Svuota la cache",
123 "settings.app.buttonInstallUpdate" : "Riavvia e installa l'aggiornamento", 145 "settings.app.buttonInstallUpdate" : "Riavvia e installa l'aggiornamento",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Includi versioni beta", 151 "settings.app.form.beta" : "Includi versioni beta",
130 "settings.app.form.darkMode" : "Unisciti al Lato Oscuro.", 152 "settings.app.form.darkMode" : "Unisciti al Lato Oscuro.",
131 "settings.app.form.enableGPUAcceleration" : "Attiva Accelerazione GPU", 153 "settings.app.form.enableGPUAcceleration" : "Attiva Accelerazione GPU",
132 "settings.app.form.enableMenuBar" : "Mostra Franz nella Barra del Menu",
133 "settings.app.form.enableSpellchecking" : "Attiva controllo ortografico", 154 "settings.app.form.enableSpellchecking" : "Attiva controllo ortografico",
134 "settings.app.form.enableSystemTray" : "Mostra Franz nell'area di notifica", 155 "settings.app.form.enableSystemTray" : "Mostra Franz nell'area di notifica",
135 "settings.app.form.hideDockIcon" : "Nascondi l'icona Franz nel Dock",
136 "settings.app.form.language" : "Lingua", 156 "settings.app.form.language" : "Lingua",
137 "settings.app.form.minimizeToSystemTray" : "Minimizza Franz nell'area di notifica", 157 "settings.app.form.minimizeToSystemTray" : "Minimizza Franz nell'area di notifica",
138 "settings.app.form.runInBackground" : "Mantieni Franz in esecuzione quando chiudi la finestra", 158 "settings.app.form.runInBackground" : "Mantieni Franz in esecuzione quando chiudi la finestra",
139 "settings.app.form.showDisabledServices" : "Mostra schede servizi disattivati", 159 "settings.app.form.showDisabledServices" : "Mostra schede servizi disattivati",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostra l'etichetta dei messaggi non letti quando le notifiche sono disattivate", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostra l'etichetta dei messaggi non letti quando le notifiche sono disattivate",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Impostazioni", 161 "settings.app.headline" : "Impostazioni",
143 "settings.app.headlineAdvanced" : "Avanzate", 162 "settings.app.headlineAdvanced" : "Avanzate",
144 "settings.app.headlineAppearance" : "Aspetto", 163 "settings.app.headlineAppearance" : "Aspetto",
145 "settings.app.headlineGeneral" : "Generale", 164 "settings.app.headlineGeneral" : "Generale",
146 "settings.app.headlineLanguage" : "Lingua", 165 "settings.app.headlineLanguage" : "Lingua",
147 "settings.app.headlineUpdates" : "Aggiornamenti", 166 "settings.app.headlineUpdates" : "Aggiornamenti",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Le modifiche richiedono un riavvio", 168 "settings.app.restartRequired" : "Le modifiche richiedono un riavvio",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Aiutaci a tradurre Franz nella tua lingua.", 170 "settings.app.translationHelp" : "Aiutaci a tradurre Franz nella tua lingua.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Invita Amici", 177 "settings.navigation.inviteFriends" : "Invita Amici",
158 "settings.navigation.logout" : "Esci", 178 "settings.navigation.logout" : "Esci",
159 "settings.navigation.settings" : "Impostazioni", 179 "settings.navigation.settings" : "Impostazioni",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "I tuoi servizi", 181 "settings.navigation.yourServices" : "I tuoi servizi",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Tutti i servizi", 183 "settings.recipes.all" : "Tutti i servizi",
162 "settings.recipes.dev" : "Sviluppo", 184 "settings.recipes.dev" : "Sviluppo",
163 "settings.recipes.headline" : "Servizi disponibili", 185 "settings.recipes.headline" : "Servizi disponibili",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Mostra l'etichetta per tutti i nuovi messaggi", 214 "settings.service.form.indirectMessages" : "Mostra l'etichetta per tutti i nuovi messaggi",
193 "settings.service.form.isMutedInfo" : "Se disattivato, tutte le notifiche sonore e le riproduzioni audio saranno mutate", 215 "settings.service.form.isMutedInfo" : "Se disattivato, tutte le notifiche sonore e le riproduzioni audio saranno mutate",
194 "settings.service.form.name" : "Nome", 216 "settings.service.form.name" : "Nome",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Impostazioni Proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "Le impostazioni proxy non verranno sincronizzate con i server Franz",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Usa un Proxy",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Password (opzionale)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Porta",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Riavvia Franz dopo aver cambiato le impostazioni del proxy.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Utente (opzionale)",
203 "settings.service.form.saveButton" : "Salva servizio", 225 "settings.service.form.saveButton" : "Salva servizio",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hosted", 226 "settings.service.form.tabHosted" : "Hosted",
207 "settings.service.form.tabOnPremise" : "Self hosted â­ï¸", 227 "settings.service.form.tabOnPremise" : "Self hosted â­ï¸",
208 "settings.service.form.team" : "Gruppo", 228 "settings.service.form.team" : "Gruppo",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Scopri servizi", 232 "settings.services.discoverServices" : "Scopri servizi",
213 "settings.services.headline" : "I tuoi servizi", 233 "settings.services.headline" : "I tuoi servizi",
214 "settings.services.noServicesAdded" : "Non hai aggiunto ancora nessun servizio.", 234 "settings.services.noServicesAdded" : "Non hai aggiunto ancora nessun servizio.",
235 "settings.services.servicesRequestFailed" : "Impossibile caricare il servizio",
215 "settings.services.tooltip.isDisabled" : "Il servizio è disattivato", 236 "settings.services.tooltip.isDisabled" : "Il servizio è disattivato",
216 "settings.services.tooltip.isMuted" : "Tutti i suoni sono disattivati", 237 "settings.services.tooltip.isMuted" : "Tutti i suoni sono disattivati",
217 "settings.services.tooltip.notificationsDisabled" : "Le notifiche sono disattivate", 238 "settings.services.tooltip.notificationsDisabled" : "Le notifiche sono disattivate",
218 "settings.services.updatedInfo" : "Le tue modifiche sono state salvate", 239 "settings.services.updatedInfo" : "Le tue modifiche sono state salvate",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Gruppo",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Società", 246 "settings.user.form.accountType.company" : "Società",
220 "settings.user.form.accountType.individual" : "Individuale", 247 "settings.user.form.accountType.individual" : "Individuale",
221 "settings.user.form.accountType.label" : "Tipo di account", 248 "settings.user.form.accountType.label" : "Tipo di account",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Nome", 252 "settings.user.form.firstname" : "Nome",
226 "settings.user.form.lastname" : "Cognome", 253 "settings.user.form.lastname" : "Cognome",
227 "settings.user.form.newPassword" : "Nuova password", 254 "settings.user.form.newPassword" : "Nuova password",
255 "settings.workspace.add.form.name" : "Nome",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Nome",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Try again",
266 "settings.workspaces.updatedInfo" : "Le tue modifiche sono state salvate",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Aggiungi un nuovo servizio", 270 "sidebar.addNewService" : "Aggiungi un nuovo servizio",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Disattiva notifiche e audio", 272 "sidebar.muteApp" : "Disattiva notifiche e audio",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Impostazioni", 274 "sidebar.settings" : "Impostazioni",
231 "sidebar.unmuteApp" : "Attiva notifiche e audio", 275 "sidebar.unmuteApp" : "Attiva notifiche e audio",
232 "signup.company.label" : "Società", 276 "signup.company.label" : "Società",
@@ -235,7 +279,7 @@
235 "signup.firstname.label" : "Nome", 279 "signup.firstname.label" : "Nome",
236 "signup.headline" : "Iscriviti", 280 "signup.headline" : "Iscriviti",
237 "signup.lastname.label" : "Cognome", 281 "signup.lastname.label" : "Cognome",
238 "signup.legal.info" : "Creando un account di Franz accetti l' ", 282 "signup.legal.info" : "Creando un account di Franz stai accettando il ",
239 "signup.legal.privacy" : "Informativa sulla Privacy", 283 "signup.legal.privacy" : "Informativa sulla Privacy",
240 "signup.legal.terms" : "Termini di Servizio", 284 "signup.legal.terms" : "Termini di Servizio",
241 "signup.link.login" : "Hai già un account, vuoi accedere?", 285 "signup.link.login" : "Hai già un account, vuoi accedere?",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Per i residenti UE: possono essere applicate tasse locali", 288 "subscription.euTaxInfo" : "Per i residenti UE: possono essere applicate tasse locali",
245 "subscription.features.ads" : "Nessuna pubblicità, mai!", 289 "subscription.features.ads" : "Nessuna pubblicità, mai!",
246 "subscription.features.comingSoon" : "in arrivo", 290 "subscription.features.comingSoon" : "in arrivo",
247 "subscription.features.encryptedSync" : "Sincronizzazione sessione crittografata", 291 "subscription.features.noInterruptions" : "L'upgrade della licenza avrà impatti sull'utilizzo dell'App",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Aggiungi servizi on-premise\/hosted come \"Mattermost\"",
249 "subscription.features.onpremise" : "Aggiungi servizi on-premise\/hosted come HipChat", 293 "subscription.features.proxy" : "Supporto proxy per i servizi",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Supporto per il correttore ortografico",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "L'account a pagamento Franz Premium Supporter include", 296 "subscription.includedFeatures" : "L'account a pagamento Franz Premium Supporter include",
254 "subscription.paymentSessionError" : "Impossibile inizializzare il modulo per il pagamento", 297 "subscription.paymentSessionError" : "Impossibile inizializzare il modulo per il pagamento",
255 "subscription.submit.label" : "Voglio supportare lo sviluppo di Franz", 298 "subscription.submit.label" : "Voglio supportare lo sviluppo di Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Ricarica", 312 "tabs.item.reload" : "Ricarica",
270 "validation.email" : "{field} non valido", 313 "validation.email" : "{field} non valido",
271 "validation.minLength" : "{field} dovrebbe contenere almeno {length} caratteri", 314 "validation.minLength" : "{field} dovrebbe contenere almeno {length} caratteri",
315 "validation.oneRequired" : "Almeno un campo è richiesto",
272 "validation.required" : "{field} è necessario", 316 "validation.required" : "{field} è necessario",
273 "validation.url" : "{field} non è un URL valido", 317 "validation.url" : "{field} non è un URL valido",
274 "welcome.loginButton" : "Accedi al tuo account", 318 "welcome.loginButton" : "Accedi al tuo account",
275 "welcome.signupButton" : "Crea un account gratuito", 319 "welcome.signupButton" : "Crea un account gratuito",
276 "welcome.slogan" : "Un sistema di messaggistica che va bene per te" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Tutti i servizi",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json
index 6eea64c3a..cf7e9ab78 100644
--- a/src/i18n/locales/ja.json
+++ b/src/i18n/locales/ja.json
@@ -1,16 +1,28 @@
1{ 1{
2 "app.errorHandler.action" : "å†èª­ã¿è¾¼ã¿", 2 "app.errorHandler.action" : "å†èª­ã¿è¾¼ã¿",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "é–“é•ãˆã¦ã„る部分ãŒã‚ã‚Šã¾ã™",
4 "feature.delayApp.action" : "Franz サãƒãƒ¼ã‚¿ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã™ã‚‹", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Franz ã‚’ã™ãã«èµ·å‹•ã™ã‚‹ã«ã¯ã€Franz サãƒãƒ¼ã‚¿ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã—ã¦ãã ã•ã„。", 5 "feature.delayApp.action" : "Franzサãƒãƒ¼ã‚¿ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã™ã‚‹",
6 "feature.delayApp.text" : "Franz ã¯ã‚ã¨{seconds}秒後ã«èµ·å‹•ã—ã¾ã™ã€‚", 6 "feature.delayApp.headline" : "Franzã‚’ã™ãã«èµ·å‹•ã™ã‚‹ã«ã¯ã€Franz サãƒãƒ¼ã‚¿ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã—ã¦ãã ã•ã„。",
7 "feature.delayApp.text" : "Franzã¯ã‚ã¨{seconds}秒後ã«èµ·å‹•ã—ã¾ã™ã€‚",
8 "feature.shareFranz.action.email" : "メールã§é€ä¿¡",
9 "feature.shareFranz.action.facebook" : "Facebookã§ã‚·ã‚§ã‚¢",
10 "feature.shareFranz.action.twitter" : "Twitterã§ã‚·ã‚§ã‚¢",
11 "feature.shareFranz.headline" : "Franzã¯ã‚ãªãŸã¨ã¨ã‚‚ã«",
12 "feature.shareFranz.shareText.email" : "Franzã§{count}個ã®ã‚µãƒ¼ãƒ“スを使ã£ã¦ã„ã¾ã™ï¼ã‚ãªãŸã‚‚Gmail, Messenger, Slack, Skypeãªã©ã®ã‚µãƒ¼ãƒ“スをFranzã§ä¸€å…ƒç®¡ç†ã—ã¾ã—ょã†ï¼ www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "ã‚ãªãŸã®ãŠå‹é”ã«Franzã‚’æ•™ãˆã¦ã‚ã’ã¾ã—ょã†ã€‚",
7 "global.api.unhealthy" : "Franzã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã‚µãƒ¼ãƒ“スã«æŽ¥ç¶šã§ãã¾ã›ã‚“。", 15 "global.api.unhealthy" : "Franzã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã‚µãƒ¼ãƒ“スã«æŽ¥ç¶šã§ãã¾ã›ã‚“。",
8 "global.notConnectedToTheInternet" : "インターãƒãƒƒãƒˆã«æŽ¥ç¶šã•ã‚Œã¦ã„ã¾ã›ã‚“。", 16 "global.notConnectedToTheInternet" : "インターãƒãƒƒãƒˆã«æŽ¥ç¶šã•ã‚Œã¦ã„ã¾ã›ã‚“。",
17 "global.spellchecker.useDefault" : " {default}ã‚’åˆæœŸè¨­å®šã§ä½¿ç”¨ã—ã¦ãã ã•ã„",
18 "global.spellchecking.autodetect" : "言語を自動的ã«æ¤œå‡ºã™ã‚‹",
19 "global.spellchecking.autodetect.short" : "自動",
20 "global.spellchecking.language" : "スペルãƒã‚§ãƒƒã‚¯ã™ã‚‹è¨€èªž",
9 "import.headline" : "Franz 4ã®ã‚µãƒ¼ãƒ“スをインãƒãƒ¼ãƒˆã—ã¦ä¸‹ã•ã„", 21 "import.headline" : "Franz 4ã®ã‚µãƒ¼ãƒ“スをインãƒãƒ¼ãƒˆã—ã¦ä¸‹ã•ã„",
10 "import.notSupportedHeadline" : "Franz 5ã§ã¯ã“ã®ã‚µãƒ¼ãƒ“スã«ã¾ã å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“", 22 "import.notSupportedHeadline" : "Franz 5ã§ã¯ã“ã®ã‚µãƒ¼ãƒ“スã«ã¾ã å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“",
11 "import.skip.label" : "手動ã§ã‚µãƒ¼ãƒ“スを追加ã™ã‚‹", 23 "import.skip.label" : "手動ã§ã‚µãƒ¼ãƒ“スを追加ã™ã‚‹",
12 "import.submit.label" : "サービスをインãƒãƒ¼ãƒˆã—ã¦ä¸‹ã•ã„", 24 "import.submit.label" : "サービスをインãƒãƒ¼ãƒˆã—ã¦ä¸‹ã•ã„",
13 "infobar.buttonChangelog" : "最新ã®æƒ…å ±", 25 "infobar.buttonChangelog" : "更新履歴を見る",
14 "infobar.buttonInstallUpdate" : "å†èµ·å‹•ã—ã¦æ›´æ–°ã‚’インストールã™ã‚‹", 26 "infobar.buttonInstallUpdate" : "å†èµ·å‹•ã—ã¦æ›´æ–°ã‚’インストールã™ã‚‹",
15 "infobar.buttonReloadServices" : "サービスã®å†èª­ã¿è¾¼ã¿", 27 "infobar.buttonReloadServices" : "サービスã®å†èª­ã¿è¾¼ã¿",
16 "infobar.requiredRequestsFailed" : "サービスã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼æƒ…報を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ", 28 "infobar.requiredRequestsFailed" : "サービスã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼æƒ…報を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "サインイン", 44 "login.submit.label" : "サインイン",
33 "login.tokenExpired" : "セッションã®æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸã€‚ログインã—ç›´ã—ã¦ä¸‹ã•ã„。", 45 "login.tokenExpired" : "セッションã®æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸã€‚ログインã—ç›´ã—ã¦ä¸‹ã•ã„。",
34 "menu.app.about" : "ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±", 46 "menu.app.about" : "ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "éš ã™", 48 "menu.app.hide" : "éš ã™",
36 "menu.app.hideOthers" : "ä»–ã‚’éš ã™", 49 "menu.app.hideOthers" : "ä»–ã‚’éš ã™",
37 "menu.app.quit" : "終了", 50 "menu.app.quit" : "終了",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "サãƒãƒ¼ãƒˆ", 72 "menu.help.support" : "サãƒãƒ¼ãƒˆ",
60 "menu.help.tos" : "サービス利用è¦ç´„", 73 "menu.help.tos" : "サービス利用è¦ç´„",
61 "menu.services" : "サービス", 74 "menu.services" : "サービス",
75 "menu.services.activatePreviousService" : "å‰ã®ã‚µãƒ¼ãƒ“スを有効ã«ã™ã‚‹",
62 "menu.services.addNewService" : "サービスを追加", 76 "menu.services.addNewService" : "サービスを追加",
77 "menu.services.setNextServiceActive" : "次ã®ã‚µãƒ¼ãƒ“スを有効ã«ã™ã‚‹",
63 "menu.view" : "表示", 78 "menu.view" : "表示",
64 "menu.view.enterFullScreen" : "全画é¢è¡¨ç¤º", 79 "menu.view.enterFullScreen" : "全画é¢è¡¨ç¤º",
65 "menu.view.exitFullScreen" : "全画é¢è¡¨ç¤ºã‚’終了ã™ã‚‹", 80 "menu.view.exitFullScreen" : "全画é¢è¡¨ç¤ºã‚’終了ã™ã‚‹",
@@ -74,6 +89,11 @@
74 "menu.window" : "ウィンドウ", 89 "menu.window" : "ウィンドウ",
75 "menu.window.close" : "é–‰ã˜ã‚‹", 90 "menu.window.close" : "é–‰ã˜ã‚‹",
76 "menu.window.minimize" : "最å°åŒ–", 91 "menu.window.minimize" : "最å°åŒ–",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "ã™ã¹ã¦ã®ã‚µãƒ¼ãƒ“ス",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "メールアドレス", 97 "password.email.label" : "メールアドレス",
78 "password.headline" : "パスワードã®ãƒªã‚»ãƒƒãƒˆ", 98 "password.headline" : "パスワードã®ãƒªã‚»ãƒƒãƒˆ",
79 "password.link.login" : "サインイン", 99 "password.link.login" : "サインイン",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "{name}を編集", 116 "service.errorHandler.editAction" : "{name}を編集",
97 "service.errorHandler.headline" : "ã—ã¾ã£ãŸï¼", 117 "service.errorHandler.headline" : "ã—ã¾ã£ãŸï¼",
98 "service.errorHandler.message" : "エラー", 118 "service.errorHandler.message" : "エラー",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} ã¯ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "ã¯ã˜ã‚ã‚‹", 121 "services.getStarted" : "ã¯ã˜ã‚ã‚‹",
101 "services.welcome" : "Franzã«ã‚ˆã†ã“ã", 122 "services.welcome" : "Franzã«ã‚ˆã†ã“ã",
102 "settings.account.account.editButton" : "アカウントã®ç·¨é›†", 123 "settings.account.account.editButton" : "アカウントã®ç·¨é›†",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "ダウンロード", 138 "settings.account.invoiceDownload" : "ダウンロード",
118 "settings.account.manageSubscription.label" : "サブスクリプションã®ç®¡ç†", 139 "settings.account.manageSubscription.label" : "サブスクリプションã®ç®¡ç†",
119 "settings.account.successInfo" : "変更内容ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ", 140 "settings.account.successInfo" : "変更内容ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ",
141 "settings.account.tryReloadServices" : "ã‚‚ã†ä¸€åº¦è©¦ã™",
120 "settings.account.tryReloadUserInfoRequest" : "ã‚‚ã†ä¸€åº¦è©¦ã™", 142 "settings.account.tryReloadUserInfoRequest" : "ã‚‚ã†ä¸€åº¦è©¦ã™",
121 "settings.account.userInfoRequestFailed" : "ユーザ情報を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ", 143 "settings.account.userInfoRequestFailed" : "ユーザ情報を読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸ",
122 "settings.app.buttonClearAllCache" : "キャッシュを消去ã™ã‚‹", 144 "settings.app.buttonClearAllCache" : "キャッシュを消去ã™ã‚‹",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Betaãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å«ã‚ã‚‹", 151 "settings.app.form.beta" : "Betaãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å«ã‚ã‚‹",
130 "settings.app.form.darkMode" : "ダークモードを有効ã«ã™ã‚‹", 152 "settings.app.form.darkMode" : "ダークモードを有効ã«ã™ã‚‹",
131 "settings.app.form.enableGPUAcceleration" : "GPUアクセラレーションを有効ã«ã™ã‚‹", 153 "settings.app.form.enableGPUAcceleration" : "GPUアクセラレーションを有効ã«ã™ã‚‹",
132 "settings.app.form.enableMenuBar" : "メニューãƒãƒ¼ã«Franzを表示ã™ã‚‹",
133 "settings.app.form.enableSpellchecking" : "スペルãƒã‚§ãƒƒã‚¯ã‚’有効ã«ã™ã‚‹", 154 "settings.app.form.enableSpellchecking" : "スペルãƒã‚§ãƒƒã‚¯ã‚’有効ã«ã™ã‚‹",
134 "settings.app.form.enableSystemTray" : "Franzをシステムトレイã«è¡¨ç¤ºã™ã‚‹", 155 "settings.app.form.enableSystemTray" : "Franzをシステムトレイã«è¡¨ç¤ºã™ã‚‹",
135 "settings.app.form.hideDockIcon" : "Dockã‹ã‚‰Franzã‚’éš ã™",
136 "settings.app.form.language" : "言語", 156 "settings.app.form.language" : "言語",
137 "settings.app.form.minimizeToSystemTray" : "Franzをシステムトレイã«æœ€å°åŒ–ã™ã‚‹", 157 "settings.app.form.minimizeToSystemTray" : "Franzをシステムトレイã«æœ€å°åŒ–ã™ã‚‹",
138 "settings.app.form.runInBackground" : "ウインドウを閉ã˜ãŸéš›ã«Franzã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã•ã›ã¦ãŠã", 158 "settings.app.form.runInBackground" : "ウインドウを閉ã˜ãŸéš›ã«Franzã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã•ã›ã¦ãŠã",
139 "settings.app.form.showDisabledServices" : "無効化ã•ã‚ŒãŸã‚µãƒ¼ãƒ“スã®ã‚¿ãƒ–を表示ã™ã‚‹", 159 "settings.app.form.showDisabledServices" : "無効化ã•ã‚ŒãŸã‚µãƒ¼ãƒ“スã®ã‚¿ãƒ–を表示ã™ã‚‹",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "通知ã®ç„¡åŠ¹æ™‚ã«æœªèª­ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ä»¶æ•°ã‚’表示ã™ã‚‹", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "通知ã®ç„¡åŠ¹æ™‚ã«æœªèª­ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ä»¶æ•°ã‚’表示ã™ã‚‹",
141 "settings.app.form.spellcheckerLanguage" : "スペルãƒã‚§ãƒƒã‚¯ã™ã‚‹è¨€èªž",
142 "settings.app.headline" : "設定", 161 "settings.app.headline" : "設定",
143 "settings.app.headlineAdvanced" : "詳細", 162 "settings.app.headlineAdvanced" : "詳細",
144 "settings.app.headlineAppearance" : "表示スタイル", 163 "settings.app.headlineAppearance" : "表示スタイル",
145 "settings.app.headlineGeneral" : "一般", 164 "settings.app.headlineGeneral" : "一般",
146 "settings.app.headlineLanguage" : "言語", 165 "settings.app.headlineLanguage" : "言語",
147 "settings.app.headlineUpdates" : "æ›´æ–°", 166 "settings.app.headlineUpdates" : "æ›´æ–°",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "変更ã«ã¯å†èµ·å‹•ãŒå¿…è¦ã§ã™", 168 "settings.app.restartRequired" : "変更ã«ã¯å†èµ·å‹•ãŒå¿…è¦ã§ã™",
149 "settings.app.subheadlineCache" : "キャッシュ", 169 "settings.app.subheadlineCache" : "キャッシュ",
150 "settings.app.translationHelp" : "Franzã®ç¿»è¨³ä½œæ¥­ã«ã”å”力をãŠé¡˜ã„ã—ã¾ã™ã€‚", 170 "settings.app.translationHelp" : "Franzã®ç¿»è¨³ä½œæ¥­ã«ã”å”力をãŠé¡˜ã„ã—ã¾ã™ã€‚",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "知りåˆã„を招待ã™ã‚‹", 177 "settings.navigation.inviteFriends" : "知りåˆã„を招待ã™ã‚‹",
158 "settings.navigation.logout" : "ログアウト", 178 "settings.navigation.logout" : "ログアウト",
159 "settings.navigation.settings" : "設定", 179 "settings.navigation.settings" : "設定",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "利用中ã®ã‚µãƒ¼ãƒ“ス", 181 "settings.navigation.yourServices" : "利用中ã®ã‚µãƒ¼ãƒ“ス",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "ã™ã¹ã¦ã®ã‚µãƒ¼ãƒ“ス", 183 "settings.recipes.all" : "ã™ã¹ã¦ã®ã‚µãƒ¼ãƒ“ス",
162 "settings.recipes.dev" : "開発版", 184 "settings.recipes.dev" : "開発版",
163 "settings.recipes.headline" : "利用å¯èƒ½ãªã‚µãƒ¼ãƒ“ス", 185 "settings.recipes.headline" : "利用å¯èƒ½ãªã‚µãƒ¼ãƒ“ス",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "ã™ã¹ã¦ã®æ–°è¦ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã«ã¤ã„ã¦ãƒãƒƒã‚¸ã‚’表示ã™ã‚‹", 214 "settings.service.form.indirectMessages" : "ã™ã¹ã¦ã®æ–°è¦ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã«ã¤ã„ã¦ãƒãƒƒã‚¸ã‚’表示ã™ã‚‹",
193 "settings.service.form.isMutedInfo" : "無効化ã•ã‚Œã¦ã„ã‚‹å ´åˆã€å…¨ã¦ã®é€šçŸ¥éŸ³ã‚„オーディオå†ç”Ÿã¯ç„¡éŸ³ã«ãªã‚Šã¾ã™", 215 "settings.service.form.isMutedInfo" : "無効化ã•ã‚Œã¦ã„ã‚‹å ´åˆã€å…¨ã¦ã®é€šçŸ¥éŸ³ã‚„オーディオå†ç”Ÿã¯ç„¡éŸ³ã«ãªã‚Šã¾ã™",
194 "settings.service.form.name" : "サービスå", 216 "settings.service.form.name" : "サービスå",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPSã®ãƒ—ロキシ設定",
196 "settings.service.form.proxy.host" : "プロキシサーãƒãƒ¼\/IP", 218 "settings.service.form.proxy.host" : "プロキシサーãƒãƒ¼\/IP",
197 "settings.service.form.proxy.info" : "プロキシ設定ã¯Franz アカウントã§åŒæœŸã•ã‚Œã¾ã›ã‚“。", 219 "settings.service.form.proxy.info" : "プロキシ設定ã¯Franz アカウントã§åŒæœŸã•ã‚Œã¾ã›ã‚“。",
198 "settings.service.form.proxy.isEnabled" : "プロキシ設定を有効ã«ã™ã‚‹", 220 "settings.service.form.proxy.isEnabled" : "プロキシ設定を有効ã«ã™ã‚‹",
199 "settings.service.form.proxy.password" : "パスワード(任æ„)", 221 "settings.service.form.proxy.password" : "パスワード(任æ„)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "ãƒãƒ¼ãƒˆ",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "プロキシ設定を変更ã—ã¦ã‹ã‚‰ã€Franzã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„",
202 "settings.service.form.proxy.user" : "ユーザーå(任æ„)", 224 "settings.service.form.proxy.user" : "ユーザーå(任æ„)",
203 "settings.service.form.saveButton" : "サービスã®ä¿å­˜", 225 "settings.service.form.saveButton" : "サービスã®ä¿å­˜",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "ホスト", 226 "settings.service.form.tabHosted" : "ホスト",
207 "settings.service.form.tabOnPremise" : "セルフホスト â­ï¸", 227 "settings.service.form.tabOnPremise" : "セルフホスト â­ï¸",
208 "settings.service.form.team" : "ãƒãƒ¼ãƒ ", 228 "settings.service.form.team" : "ãƒãƒ¼ãƒ ",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "サービスを探ã™", 232 "settings.services.discoverServices" : "サービスを探ã™",
213 "settings.services.headline" : "利用中ã®ã‚µãƒ¼ãƒ“ス", 233 "settings.services.headline" : "利用中ã®ã‚µãƒ¼ãƒ“ス",
214 "settings.services.noServicesAdded" : "ã¾ã ã€ã©ã®ã‚µãƒ¼ãƒ“スも追加ã•ã‚Œã¦ã„ã¾ã›ã‚“。", 234 "settings.services.noServicesAdded" : "ã¾ã ã€ã©ã®ã‚µãƒ¼ãƒ“スも追加ã•ã‚Œã¦ã„ã¾ã›ã‚“。",
235 "settings.services.servicesRequestFailed" : "サービスを読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸ",
215 "settings.services.tooltip.isDisabled" : "サービスãŒç„¡åŠ¹ã§ã™", 236 "settings.services.tooltip.isDisabled" : "サービスãŒç„¡åŠ¹ã§ã™",
216 "settings.services.tooltip.isMuted" : "無音ã¨ãªã£ã¦ã„ã¾ã™", 237 "settings.services.tooltip.isMuted" : "無音ã¨ãªã£ã¦ã„ã¾ã™",
217 "settings.services.tooltip.notificationsDisabled" : "通知ã¯ç„¡åŠ¹ã§ã™", 238 "settings.services.tooltip.notificationsDisabled" : "通知ã¯ç„¡åŠ¹ã§ã™",
218 "settings.services.updatedInfo" : "変更内容ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ", 239 "settings.services.updatedInfo" : "変更内容ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "ãƒãƒ¼ãƒ ",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "法人", 246 "settings.user.form.accountType.company" : "法人",
220 "settings.user.form.accountType.individual" : "個人", 247 "settings.user.form.accountType.individual" : "個人",
221 "settings.user.form.accountType.label" : "アカウントã®ç¨®é¡ž", 248 "settings.user.form.accountType.label" : "アカウントã®ç¨®é¡ž",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "å", 252 "settings.user.form.firstname" : "å",
226 "settings.user.form.lastname" : "姓", 253 "settings.user.form.lastname" : "姓",
227 "settings.user.form.newPassword" : "æ–°ã—ã„パスワード", 254 "settings.user.form.newPassword" : "æ–°ã—ã„パスワード",
255 "settings.workspace.add.form.name" : "Name",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "ã‚‚ã†ä¸€åº¦è©¦ã™",
266 "settings.workspaces.updatedInfo" : "変更内容ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "サービスを追加", 270 "sidebar.addNewService" : "サービスを追加",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "通知ã¨ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚’無効化", 272 "sidebar.muteApp" : "通知ã¨ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚’無効化",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "設定", 274 "sidebar.settings" : "設定",
231 "sidebar.unmuteApp" : "通知ã¨ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚’有効化", 275 "sidebar.unmuteApp" : "通知ã¨ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚’有効化",
232 "signup.company.label" : "法人", 276 "signup.company.label" : "法人",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "EU在ä½è€… : 地域ã®æ¶ˆè²»ç¨ŽãŒé©ç”¨ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™", 288 "subscription.euTaxInfo" : "EU在ä½è€… : 地域ã®æ¶ˆè²»ç¨ŽãŒé©ç”¨ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™",
245 "subscription.features.ads" : "広告ã¯ä¸€åˆ‡ã‚ã‚Šã¾ã›ã‚“!", 289 "subscription.features.ads" : "広告ã¯ä¸€åˆ‡ã‚ã‚Šã¾ã›ã‚“!",
246 "subscription.features.comingSoon" : "ã¾ã‚‚ãªã登場", 290 "subscription.features.comingSoon" : "ã¾ã‚‚ãªã登場",
247 "subscription.features.encryptedSync" : "æš—å·åŒ–ã•ã‚ŒãŸã‚»ãƒƒã‚·ãƒ§ãƒ³ã®åŒæœŸ",
248 "subscription.features.noInterruptions" : "å¾…ã¡æ™‚é–“ãªã—ã§Franz ã‚’ãŠä½¿ã„ã„ãŸã ã‘ã¾ã™", 291 "subscription.features.noInterruptions" : "å¾…ã¡æ™‚é–“ãªã—ã§Franz ã‚’ãŠä½¿ã„ã„ãŸã ã‘ã¾ã™",
249 "subscription.features.onpremise" : "HipChatã®ã‚ˆã†ãªã‚ªãƒ³ãƒ—レミス\/ホスト型サービスã®è¿½åŠ ",
250 "subscription.features.onpremise.mattermost" : "Mattermost ã®ã‚ˆã†ãªã‚ªãƒ³ãƒ—レミス(自社é‹ç”¨ï¼‰åž‹ã®ã‚µãƒ¼ãƒ“スを追加ã§ãるよã†ã«ãªã‚Šã¾ã™", 292 "subscription.features.onpremise.mattermost" : "Mattermost ã®ã‚ˆã†ãªã‚ªãƒ³ãƒ—レミス(自社é‹ç”¨ï¼‰åž‹ã®ã‚µãƒ¼ãƒ“スを追加ã§ãるよã†ã«ãªã‚Šã¾ã™",
251 "subscription.features.proxy" : "プロキシ設定ãŒåˆ©ç”¨å¯èƒ½", 293 "subscription.features.proxy" : "プロキシ設定ãŒåˆ©ç”¨å¯èƒ½",
252 "subscription.features.spellchecker" : "スペルãƒã‚§ãƒƒã‚¯æ©Ÿèƒ½ã‚’ãŠä½¿ã„ã„ãŸã ã‘ã¾ã™", 294 "subscription.features.spellchecker" : "スペルãƒã‚§ãƒƒã‚¯æ©Ÿèƒ½ã‚’ãŠä½¿ã„ã„ãŸã ã‘ã¾ã™",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Franz Premium Supporter有料アカウントã«ã¯ä»¥ä¸‹ãŒå«ã¾ã‚Œã¾ã™", 296 "subscription.includedFeatures" : "Franz Premium Supporter有料アカウントã«ã¯ä»¥ä¸‹ãŒå«ã¾ã‚Œã¾ã™",
254 "subscription.paymentSessionError" : "支払ã„フォームをåˆæœŸåŒ–出æ¥ã¾ã›ã‚“", 297 "subscription.paymentSessionError" : "支払ã„フォームをåˆæœŸåŒ–出æ¥ã¾ã›ã‚“",
255 "subscription.submit.label" : "Franzã®é–‹ç™ºã‚’支æ´ã—ãŸã„", 298 "subscription.submit.label" : "Franzã®é–‹ç™ºã‚’支æ´ã—ãŸã„",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "å†èª­ã¿è¾¼ã¿", 312 "tabs.item.reload" : "å†èª­ã¿è¾¼ã¿",
270 "validation.email" : "{field}ã¯æ­£ã—ãã‚ã‚Šã¾ã›ã‚“", 313 "validation.email" : "{field}ã¯æ­£ã—ãã‚ã‚Šã¾ã›ã‚“",
271 "validation.minLength" : "{field}ã¯å°‘ãªãã¨ã‚‚{length}文字以上ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“", 314 "validation.minLength" : "{field}ã¯å°‘ãªãã¨ã‚‚{length}文字以上ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“",
315 "validation.oneRequired" : "å°‘ãªãã¨ã‚‚1ã¤ã¯å¿…è¦ã§ã™",
272 "validation.required" : "{field}ã¯å¿…é ˆã§ã™", 316 "validation.required" : "{field}ã¯å¿…é ˆã§ã™",
273 "validation.url" : "{field}ã¯æ­£ã—ã„URLã§ã¯ã‚ã‚Šã¾ã›ã‚“", 317 "validation.url" : "{field}ã¯æ­£ã—ã„URLã§ã¯ã‚ã‚Šã¾ã›ã‚“",
274 "welcome.loginButton" : "アカウントã«ãƒ­ã‚°ã‚¤ãƒ³", 318 "welcome.loginButton" : "アカウントã«ãƒ­ã‚°ã‚¤ãƒ³",
275 "welcome.signupButton" : "無料アカウントを作æˆ", 319 "welcome.signupButton" : "無料アカウントを作æˆ",
276 "welcome.slogan" : "Messaging that works for you" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "ã™ã¹ã¦ã®ã‚µãƒ¼ãƒ“ス",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/ka.json b/src/i18n/locales/ka.json
index 632ca618e..af224c115 100644
--- a/src/i18n/locales/ka.json
+++ b/src/i18n/locales/ka.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ", 2 "app.errorHandler.action" : "ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Something went wrong",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Franz-ის áƒáƒœáƒšáƒáƒ˜áƒœ სერვისთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბრვერ მáƒáƒ®áƒ”რხდáƒ", 15 "global.api.unhealthy" : "Franz-ის áƒáƒœáƒšáƒáƒ˜áƒœ სერვისთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბრვერ მáƒáƒ®áƒ”რხდáƒ",
8 "global.notConnectedToTheInternet" : "თქვენ áƒáƒ  ხáƒáƒ áƒ— ინტერნეტთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბული.", 16 "global.notConnectedToTheInternet" : "თქვენ áƒáƒ  ხáƒáƒ áƒ— ინტერნეტთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბული.",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "შემáƒáƒ˜áƒ¢áƒáƒœáƒ” Franz 4-ის სერვისები", 21 "import.headline" : "შემáƒáƒ˜áƒ¢áƒáƒœáƒ” Franz 4-ის სერვისები",
10 "import.notSupportedHeadline" : "სერვისები ჯერ áƒáƒ  áƒáƒ áƒ˜áƒ¡ მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი Franz 5-ში", 22 "import.notSupportedHeadline" : "სერვისები ჯერ áƒáƒ  áƒáƒ áƒ˜áƒ¡ მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი Franz 5-ში",
11 "import.skip.label" : "I want to add services manually", 23 "import.skip.label" : "I want to add services manually",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "შესვლáƒ", 44 "login.submit.label" : "შესვლáƒ",
33 "login.tokenExpired" : "თქვენს სესიáƒáƒ¡ ვáƒáƒ“რგáƒáƒ£áƒ•áƒ˜áƒ“áƒ, შედით áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ ხელáƒáƒ®áƒšáƒ.", 45 "login.tokenExpired" : "თქვენს სესიáƒáƒ¡ ვáƒáƒ“რგáƒáƒ£áƒ•áƒ˜áƒ“áƒ, შედით áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ ხელáƒáƒ®áƒšáƒ.",
34 "menu.app.about" : "Franz-ის შესáƒáƒ®áƒ”ბ", 46 "menu.app.about" : "Franz-ის შესáƒáƒ®áƒ”ბ",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Hide", 48 "menu.app.hide" : "Hide",
36 "menu.app.hideOthers" : "სხვების დáƒáƒ›áƒáƒšáƒ•áƒ", 49 "menu.app.hideOthers" : "სხვების დáƒáƒ›áƒáƒšáƒ•áƒ",
37 "menu.app.quit" : "გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ", 50 "menu.app.quit" : "გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Support", 72 "menu.help.support" : "Support",
60 "menu.help.tos" : "Terms of Service", 73 "menu.help.tos" : "Terms of Service",
61 "menu.services" : "Services", 74 "menu.services" : "Services",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Add New Service...", 76 "menu.services.addNewService" : "Add New Service...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "View", 78 "menu.view" : "View",
64 "menu.view.enterFullScreen" : "Enter Full Screen", 79 "menu.view.enterFullScreen" : "Enter Full Screen",
65 "menu.view.exitFullScreen" : "Exit Full Screen", 80 "menu.view.exitFullScreen" : "Exit Full Screen",
@@ -74,6 +89,11 @@
74 "menu.window" : "Window", 89 "menu.window" : "Window",
75 "menu.window.close" : "Close", 90 "menu.window.close" : "Close",
76 "menu.window.minimize" : "Minimize", 91 "menu.window.minimize" : "Minimize",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "ყველრსერვისი",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "მეილი", 97 "password.email.label" : "მეილი",
78 "password.headline" : "პáƒáƒ áƒáƒšáƒ˜áƒ¡ áƒáƒ¦áƒ“გენáƒ", 98 "password.headline" : "პáƒáƒ áƒáƒšáƒ˜áƒ¡ áƒáƒ¦áƒ“გენáƒ",
79 "password.link.login" : "შედით თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜", 99 "password.link.login" : "შედით თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "Oh no!", 117 "service.errorHandler.headline" : "Oh no!",
98 "service.errorHandler.message" : "შეცდáƒáƒ›áƒ", 118 "service.errorHandler.message" : "შეცდáƒáƒ›áƒ",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "დáƒáƒ¬áƒ§áƒ”ბáƒ", 121 "services.getStarted" : "დáƒáƒ¬áƒ§áƒ”ბáƒ",
101 "services.welcome" : "მáƒáƒ’ესáƒáƒšáƒ›áƒ”ბით Franz-ზე", 122 "services.welcome" : "მáƒáƒ’ესáƒáƒšáƒ›áƒ”ბით Franz-ზე",
102 "settings.account.account.editButton" : "áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ მáƒáƒ áƒ—ვáƒ", 123 "settings.account.account.editButton" : "áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ მáƒáƒ áƒ—ვáƒ",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "გáƒáƒ“მáƒáƒ¬áƒ”რáƒ", 138 "settings.account.invoiceDownload" : "გáƒáƒ“მáƒáƒ¬áƒ”რáƒ",
118 "settings.account.manageSubscription.label" : "თქვენი გáƒáƒ›áƒáƒ¬áƒ”რის მáƒáƒ áƒ—ვáƒ", 139 "settings.account.manageSubscription.label" : "თქვენი გáƒáƒ›áƒáƒ¬áƒ”რის მáƒáƒ áƒ—ვáƒ",
119 "settings.account.successInfo" : "თქვენი ცვლილებები შენáƒáƒ®áƒ£áƒšáƒ˜áƒ", 140 "settings.account.successInfo" : "თქვენი ცვლილებები შენáƒáƒ®áƒ£áƒšáƒ˜áƒ",
141 "settings.account.tryReloadServices" : "სცáƒáƒ“ეთ ხელáƒáƒ®áƒšáƒ",
120 "settings.account.tryReloadUserInfoRequest" : "სცáƒáƒ“ეთ ხელáƒáƒ®áƒšáƒ", 142 "settings.account.tryReloadUserInfoRequest" : "სცáƒáƒ“ეთ ხელáƒáƒ®áƒšáƒ",
121 "settings.account.userInfoRequestFailed" : "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვრვერ მáƒáƒ®áƒ”რხდáƒ", 143 "settings.account.userInfoRequestFailed" : "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვრვერ მáƒáƒ®áƒ”რხდáƒ",
122 "settings.app.buttonClearAllCache" : "Clear cache", 144 "settings.app.buttonClearAllCache" : "Clear cache",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "ჩáƒáƒ áƒ—ეთ ბეტრვერსიები", 151 "settings.app.form.beta" : "ჩáƒáƒ áƒ—ეთ ბეტრვერსიები",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "Enable GPU Acceleration", 153 "settings.app.form.enableGPUAcceleration" : "Enable GPU Acceleration",
132 "settings.app.form.enableMenuBar" : "Show Franz in Menu Bar",
133 "settings.app.form.enableSpellchecking" : "Enable spell checking", 154 "settings.app.form.enableSpellchecking" : "Enable spell checking",
134 "settings.app.form.enableSystemTray" : "áƒáƒ©áƒ•áƒ”ნეთ Franz სისტემის უჯრáƒáƒ¨áƒ˜", 155 "settings.app.form.enableSystemTray" : "áƒáƒ©áƒ•áƒ”ნეთ Franz სისტემის უჯრáƒáƒ¨áƒ˜",
135 "settings.app.form.hideDockIcon" : "Hide Franz icon in Dock",
136 "settings.app.form.language" : "ენáƒ", 156 "settings.app.form.language" : "ენáƒ",
137 "settings.app.form.minimizeToSystemTray" : "ჩáƒáƒ™áƒ”ცეთ Franz სისტემის უჯრáƒáƒ¨áƒ˜", 157 "settings.app.form.minimizeToSystemTray" : "ჩáƒáƒ™áƒ”ცეთ Franz სისტემის უჯრáƒáƒ¨áƒ˜",
138 "settings.app.form.runInBackground" : "დáƒáƒ¢áƒáƒ•áƒ”თ Franz გáƒáƒ¨áƒ•áƒ”ბული რáƒáƒ“ესáƒáƒª ფáƒáƒœáƒ¯áƒáƒ áƒ დáƒáƒ˜áƒ®áƒ£áƒ áƒ”ბáƒ", 158 "settings.app.form.runInBackground" : "დáƒáƒ¢áƒáƒ•áƒ”თ Franz გáƒáƒ¨áƒ•áƒ”ბული რáƒáƒ“ესáƒáƒª ფáƒáƒœáƒ¯áƒáƒ áƒ დáƒáƒ˜áƒ®áƒ£áƒ áƒ”ბáƒ",
139 "settings.app.form.showDisabledServices" : "Display disabled services tabs", 159 "settings.app.form.showDisabledServices" : "Display disabled services tabs",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Show unread message badge when notifications are disabled", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Show unread message badge when notifications are disabled",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "პáƒáƒ áƒáƒ›áƒ”ტრები", 161 "settings.app.headline" : "პáƒáƒ áƒáƒ›áƒ”ტრები",
143 "settings.app.headlineAdvanced" : "Advanced", 162 "settings.app.headlineAdvanced" : "Advanced",
144 "settings.app.headlineAppearance" : "Appearance", 163 "settings.app.headlineAppearance" : "Appearance",
145 "settings.app.headlineGeneral" : "მთáƒáƒ•áƒáƒ áƒ˜", 164 "settings.app.headlineGeneral" : "მთáƒáƒ•áƒáƒ áƒ˜",
146 "settings.app.headlineLanguage" : "ენáƒ", 165 "settings.app.headlineLanguage" : "ენáƒ",
147 "settings.app.headlineUpdates" : "გáƒáƒœáƒáƒ®áƒšáƒ”ბები", 166 "settings.app.headlineUpdates" : "გáƒáƒœáƒáƒ®áƒšáƒ”ბები",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Changes require restart", 168 "settings.app.restartRequired" : "Changes require restart",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Help us to translate Franz into your language.", 170 "settings.app.translationHelp" : "Help us to translate Franz into your language.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Invite Friends", 177 "settings.navigation.inviteFriends" : "Invite Friends",
158 "settings.navigation.logout" : "გáƒáƒ¡áƒ•áƒšáƒ", 178 "settings.navigation.logout" : "გáƒáƒ¡áƒ•áƒšáƒ",
159 "settings.navigation.settings" : "პáƒáƒ áƒáƒ›áƒ”ტრები", 179 "settings.navigation.settings" : "პáƒáƒ áƒáƒ›áƒ”ტრები",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "თქვენი სერვისები", 181 "settings.navigation.yourServices" : "თქვენი სერვისები",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "ყველრსერვისი", 183 "settings.recipes.all" : "ყველრსერვისი",
162 "settings.recipes.dev" : "გáƒáƒœáƒ•áƒ˜áƒ—áƒáƒ áƒ”ბáƒ", 184 "settings.recipes.dev" : "გáƒáƒœáƒ•áƒ˜áƒ—áƒáƒ áƒ”ბáƒ",
163 "settings.recipes.headline" : "ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜ სერვისები", 185 "settings.recipes.headline" : "ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜ სერვისები",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "სერვისის შენáƒáƒ®áƒ•áƒ", 225 "settings.service.form.saveButton" : "სერვისის შენáƒáƒ®áƒ•áƒ",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "დáƒáƒ°áƒáƒ¡áƒ¢áƒ˜áƒšáƒ˜", 226 "settings.service.form.tabHosted" : "დáƒáƒ°áƒáƒ¡áƒ¢áƒ˜áƒšáƒ˜",
207 "settings.service.form.tabOnPremise" : "თვით დáƒáƒ°áƒáƒ¡áƒ¢áƒ˜áƒšáƒ˜ â­ï¸", 227 "settings.service.form.tabOnPremise" : "თვით დáƒáƒ°áƒáƒ¡áƒ¢áƒ˜áƒšáƒ˜ â­ï¸",
208 "settings.service.form.team" : "გუნდი", 228 "settings.service.form.team" : "გუნდი",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "áƒáƒ¦áƒ›áƒáƒáƒ©áƒ˜áƒœáƒ”თ სერვისები", 232 "settings.services.discoverServices" : "áƒáƒ¦áƒ›áƒáƒáƒ©áƒ˜áƒœáƒ”თ სერვისები",
213 "settings.services.headline" : "თქვენი სერვისები", 233 "settings.services.headline" : "თქვენი სერვისები",
214 "settings.services.noServicesAdded" : "თქვენ ჯერ áƒáƒ  გáƒáƒ¥áƒ•áƒ— სერვისები დáƒáƒ›áƒáƒ¢áƒ”ბული.", 234 "settings.services.noServicesAdded" : "თქვენ ჯერ áƒáƒ  გáƒáƒ¥áƒ•áƒ— სერვისები დáƒáƒ›áƒáƒ¢áƒ”ბული.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "სერვისი გáƒáƒ—იშულიáƒ", 236 "settings.services.tooltip.isDisabled" : "სერვისი გáƒáƒ—იშულიáƒ",
216 "settings.services.tooltip.isMuted" : "All sounds are muted", 237 "settings.services.tooltip.isMuted" : "All sounds are muted",
217 "settings.services.tooltip.notificationsDisabled" : "შეტყáƒáƒ‘ინებები გáƒáƒ—იშულიáƒ", 238 "settings.services.tooltip.notificationsDisabled" : "შეტყáƒáƒ‘ინებები გáƒáƒ—იშულიáƒ",
218 "settings.services.updatedInfo" : "ცვლილებები შენáƒáƒ®áƒ£áƒšáƒ˜áƒ", 239 "settings.services.updatedInfo" : "ცვლილებები შენáƒáƒ®áƒ£áƒšáƒ˜áƒ",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "გუნდი",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "კáƒáƒ›áƒžáƒáƒœáƒ˜áƒ", 246 "settings.user.form.accountType.company" : "კáƒáƒ›áƒžáƒáƒœáƒ˜áƒ",
220 "settings.user.form.accountType.individual" : "ინდივიდუáƒáƒšáƒ£áƒ áƒ˜", 247 "settings.user.form.accountType.individual" : "ინდივიდუáƒáƒšáƒ£áƒ áƒ˜",
221 "settings.user.form.accountType.label" : "áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ ტიპი", 248 "settings.user.form.accountType.label" : "áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ ტიპი",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "First Name", 252 "settings.user.form.firstname" : "First Name",
226 "settings.user.form.lastname" : "Last Name", 253 "settings.user.form.lastname" : "Last Name",
227 "settings.user.form.newPassword" : "áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜", 254 "settings.user.form.newPassword" : "áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜",
255 "settings.workspace.add.form.name" : "Name",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "სცáƒáƒ“ეთ ხელáƒáƒ®áƒšáƒ",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Add new service", 270 "sidebar.addNewService" : "Add new service",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Disable notifications & audio", 272 "sidebar.muteApp" : "Disable notifications & audio",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "პáƒáƒ áƒáƒ›áƒ”ტრები", 274 "sidebar.settings" : "პáƒáƒ áƒáƒ›áƒ”ტრები",
231 "sidebar.unmuteApp" : "Enable notifications & audio", 275 "sidebar.unmuteApp" : "Enable notifications & audio",
232 "signup.company.label" : "კáƒáƒ›áƒžáƒáƒœáƒ˜áƒ", 276 "signup.company.label" : "კáƒáƒ›áƒžáƒáƒœáƒ˜áƒ",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "EU residents: local sales tax may apply", 288 "subscription.euTaxInfo" : "EU residents: local sales tax may apply",
245 "subscription.features.ads" : "áƒáƒ áƒáƒœáƒáƒ˜áƒ áƒ˜ რეკლáƒáƒ›áƒ”ბი, áƒáƒ áƒáƒ¡áƒ“რáƒáƒ¡!", 289 "subscription.features.ads" : "áƒáƒ áƒáƒœáƒáƒ˜áƒ áƒ˜ რეკლáƒáƒ›áƒ”ბი, áƒáƒ áƒáƒ¡áƒ“რáƒáƒ¡!",
246 "subscription.features.comingSoon" : "მáƒáƒšáƒ”", 290 "subscription.features.comingSoon" : "მáƒáƒšáƒ”",
247 "subscription.features.encryptedSync" : "დáƒáƒ¨áƒ˜áƒ¤áƒ áƒ£áƒšáƒ˜ სესიის სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "on-premise\/hosted სერვისების დáƒáƒ›áƒáƒ¢áƒ”ბáƒ, რáƒáƒ’áƒáƒ áƒ˜áƒªáƒáƒ HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "ფáƒáƒ¡áƒ˜áƒáƒœáƒ˜ Franz-ის პრემიუმ მხáƒáƒ áƒ›áƒ“áƒáƒ›áƒ­áƒ”რი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜", 296 "subscription.includedFeatures" : "ფáƒáƒ¡áƒ˜áƒáƒœáƒ˜ Franz-ის პრემიუმ მხáƒáƒ áƒ›áƒ“áƒáƒ›áƒ­áƒ”რი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜",
254 "subscription.paymentSessionError" : "გáƒáƒ“áƒáƒ®áƒ“ის ფáƒáƒ áƒ›áƒáƒ¢áƒ˜áƒ¡ ინიციáƒáƒšáƒ˜áƒ–áƒáƒªáƒ˜áƒ ვერ მáƒáƒ®áƒ”რხდáƒ", 297 "subscription.paymentSessionError" : "გáƒáƒ“áƒáƒ®áƒ“ის ფáƒáƒ áƒ›áƒáƒ¢áƒ˜áƒ¡ ინიციáƒáƒšáƒ˜áƒ–áƒáƒªáƒ˜áƒ ვერ მáƒáƒ®áƒ”რხდáƒ",
255 "subscription.submit.label" : "მინდრხელი შევუწყრFranz-ის გáƒáƒœáƒ•áƒ˜áƒ—áƒáƒ áƒ”ბáƒáƒ¡", 298 "subscription.submit.label" : "მინდრხელი შევუწყრFranz-ის გáƒáƒœáƒ•áƒ˜áƒ—áƒáƒ áƒ”ბáƒáƒ¡",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ", 312 "tabs.item.reload" : "ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ",
270 "validation.email" : "{field} is not valid", 313 "validation.email" : "{field} is not valid",
271 "validation.minLength" : "{field} should be at least {length} characters long", 314 "validation.minLength" : "{field} should be at least {length} characters long",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} is required", 316 "validation.required" : "{field} is required",
273 "validation.url" : "{field} is not a valid URL", 317 "validation.url" : "{field} is not a valid URL",
274 "welcome.loginButton" : "შედით თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜", 318 "welcome.loginButton" : "შედით თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜",
275 "welcome.signupButton" : "შექმენი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜, ეს უფáƒáƒ¡áƒáƒ", 319 "welcome.signupButton" : "შექმენი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜, ეს უფáƒáƒ¡áƒáƒ",
276 "welcome.slogan" : "შეტყáƒáƒ‘ინების áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ, რáƒáƒ›áƒ”ლიც მუშáƒáƒáƒ‘ს შენთვის" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "ყველრსერვისი",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/nl-BE.json b/src/i18n/locales/nl-BE.json
index c38a7f024..2854fcb09 100644
--- a/src/i18n/locales/nl-BE.json
+++ b/src/i18n/locales/nl-BE.json
@@ -1,124 +1,146 @@
1{ 1{
2 "app.errorHandler.action" : "Herladen", 2 "app.errorHandler.action" : "Herladen",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Er ging iets mis",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Neem een Franz Supporter Licentie ",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "Neem een Franz Supporter Licentie om niet meer te hoeven wachten",
7 "feature.delayApp.text" : "Franz gaat over {seconds} seconden verder.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Kan geen verbinding maken met de Franz services", 15 "global.api.unhealthy" : "Kan geen verbinding maken met de Franz services",
8 "global.notConnectedToTheInternet" : "Je hebt geen internet verbinding.", 16 "global.notConnectedToTheInternet" : "Je hebt geen internet verbinding.",
17 "global.spellchecker.useDefault" : "Gebruik Systeemstandaard ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Taal spellingscontrole",
9 "import.headline" : "Importeer je Franz 4 services", 21 "import.headline" : "Importeer je Franz 4 services",
10 "import.notSupportedHeadline" : "De volgende services worden nog niet ondersteund in Franz 5", 22 "import.notSupportedHeadline" : "De volgende services worden nog niet ondersteund in Franz 5",
11 "import.skip.label" : "Ik wens services manueel toe te voegen", 23 "import.skip.label" : "Ik wil services handmatig toevoegen",
12 "import.submit.label" : "Importeer services", 24 "import.submit.label" : "Importeer services",
13 "infobar.buttonChangelog" : "Wat is er nieuw?", 25 "infobar.buttonChangelog" : "Wat is er nieuw?",
14 "infobar.buttonInstallUpdate" : "Start opnieuw op & installeer de update", 26 "infobar.buttonInstallUpdate" : "Opnieuw opstarten & update installeren",
15 "infobar.buttonReloadServices" : "Herlaad de services", 27 "infobar.buttonReloadServices" : "Services opnieuw laden",
16 "infobar.requiredRequestsFailed" : "Kan de services en gebruikers informatie niet laden", 28 "infobar.requiredRequestsFailed" : "Kan de services en gebruikersinformatie niet laden",
17 "infobar.servicesUpdated" : "Je services zijn geüpdatet.", 29 "infobar.servicesUpdated" : "Je services zijn bijgewerkt.",
18 "infobar.updateAvailable" : "Een nieuwe update voor Franz is beschikbaar.", 30 "infobar.updateAvailable" : "Er is een nieuwe update voor Franz beschikbaar.",
19 "invite.email.label" : "E-mailadres", 31 "invite.email.label" : "E-mailadres",
20 "invite.headline.friends" : "Nodig 3 van je vrienden of collega's uit", 32 "invite.headline.friends" : "Nodig 3 van je vrienden of collega's uit",
21 "invite.name.label" : "Naam", 33 "invite.name.label" : "Naam",
22 "invite.skip.label" : "Ik wil dit later doen", 34 "invite.skip.label" : "Ik wil dit later doen",
23 "invite.submit.label" : "Verzend uitnodigingen", 35 "invite.submit.label" : "Uitnodigingen verzenden",
24 "invite.successInfo" : "Uitnodiging met succes verzonden", 36 "invite.successInfo" : "Uitnodiging met succes verzonden",
25 "login.email.label" : "E-mailadres", 37 "login.email.label" : "E-mailadres",
26 "login.headline" : "Inloggen", 38 "login.headline" : "Inloggen",
27 "login.invalidCredentials" : "E-mailadres of wachtwoord ongeldig", 39 "login.invalidCredentials" : "E-mailadres of wachtwoord ongeldig",
28 "login.link.password" : "Wachtwoord resetten", 40 "login.link.password" : "Wachtwoord resetten",
29 "login.link.signup" : "Maak een gratis account", 41 "login.link.signup" : "Maak een gratis account aan",
30 "login.password.label" : "Wachtwoord", 42 "login.password.label" : "Wachtwoord",
31 "login.serverLogout" : "De sessie is verlopen, log opnieuw in alsjeblieft.", 43 "login.serverLogout" : "De sessie is verlopen, log opnieuw in alsjeblieft.",
32 "login.submit.label" : "Log in", 44 "login.submit.label" : "Inloggen",
33 "login.tokenExpired" : "De sessie is verlopen, log opnieuw in alsjeblieft.", 45 "login.tokenExpired" : "De sessie is verlopen, log opnieuw in alsjeblieft.",
34 "menu.app.about" : "Over Franz", 46 "menu.app.about" : "Over Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Verbergen", 48 "menu.app.hide" : "Verbergen",
36 "menu.app.hideOthers" : "Andere verbergen", 49 "menu.app.hideOthers" : "Andere Verbergen",
37 "menu.app.quit" : "Afsluiten", 50 "menu.app.quit" : "Afsluiten",
38 "menu.app.settings" : "Instellingen", 51 "menu.app.settings" : "Instellingen",
39 "menu.app.unhide" : "Zichtbaar maken", 52 "menu.app.unhide" : "Tonen",
40 "menu.edit" : "Aanpassen", 53 "menu.edit" : "Bewerken",
41 "menu.edit.copy" : "Kopiëren", 54 "menu.edit.copy" : "Kopiëren",
42 "menu.edit.cut" : "Knippen", 55 "menu.edit.cut" : "Knippen",
43 "menu.edit.delete" : "Verwijderen", 56 "menu.edit.delete" : "Verwijderen",
44 "menu.edit.emojiSymbols" : "Emoji & Symbolen", 57 "menu.edit.emojiSymbols" : "Emoji & Symbolen",
45 "menu.edit.paste" : "Plakken", 58 "menu.edit.paste" : "Plakken",
46 "menu.edit.pasteAndMatchStyle" : "Plakken en stijl overeen laten komen", 59 "menu.edit.pasteAndMatchStyle" : "Plakken en stijl overeen laten komen",
47 "menu.edit.redo" : "Opnieuw uitvoeren", 60 "menu.edit.redo" : "Opnieuw doen",
48 "menu.edit.selectAll" : "Selecteer alles", 61 "menu.edit.selectAll" : "Selecteer Alles",
49 "menu.edit.speech" : "Spraakuitvoer", 62 "menu.edit.speech" : "Spraakuitvoer",
50 "menu.edit.startDictation" : "Beginnen met dicteren", 63 "menu.edit.startDictation" : "Beginnen met dicteren",
51 "menu.edit.startSpeaking" : "Begin met spreken", 64 "menu.edit.startSpeaking" : "Begin met Spreken",
52 "menu.edit.stopSpeaking" : "Stoppen met spreken", 65 "menu.edit.stopSpeaking" : "Stoppen met Spreken",
53 "menu.edit.undo" : "Ongedaan maken", 66 "menu.edit.undo" : "Ongedaan maken",
54 "menu.file" : "Bestand", 67 "menu.file" : "Bestand",
55 "menu.help" : "Help", 68 "menu.help" : "Help",
56 "menu.help.changelog" : "Logboek", 69 "menu.help.changelog" : "Logboek",
57 "menu.help.learnMore" : "Meer weten", 70 "menu.help.learnMore" : "Meer Weten",
58 "menu.help.privacy" : "Privacyverklaring", 71 "menu.help.privacy" : "Privacyverklaring",
59 "menu.help.support" : "Ondersteuning", 72 "menu.help.support" : "Ondersteuning",
60 "menu.help.tos" : "Servicevoorwaarden", 73 "menu.help.tos" : "Servicevoorwaarden",
61 "menu.services" : "Diensten", 74 "menu.services" : "Services",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Nieuwe service toevoegen...", 76 "menu.services.addNewService" : "Nieuwe service toevoegen...",
63 "menu.view" : "Beeld", 77 "menu.services.setNextServiceActive" : "Activate next service",
78 "menu.view" : "Weergave",
64 "menu.view.enterFullScreen" : "Volledig scherm openen", 79 "menu.view.enterFullScreen" : "Volledig scherm openen",
65 "menu.view.exitFullScreen" : "Volledig scherm verlaten", 80 "menu.view.exitFullScreen" : "Volledig scherm verlaten",
66 "menu.view.reloadFranz" : "Franz Herladen", 81 "menu.view.reloadFranz" : "Franz Herladen",
67 "menu.view.reloadService" : "Service herladen", 82 "menu.view.reloadService" : "Service Herladen",
68 "menu.view.resetZoom" : "Werkelijke grootte", 83 "menu.view.resetZoom" : "Werkelijke Grootte",
69 "menu.view.toggleDevTools" : "Toggle Developer Tools", 84 "menu.view.toggleDevTools" : "Ontwikkelaarstools Aan\/Uit",
70 "menu.view.toggleFullScreen" : "Volledig scherm aan\/uit", 85 "menu.view.toggleFullScreen" : "Volledig Scherm Aan\/Uit",
71 "menu.view.toggleServiceDevTools" : "Toggle Service Developer Tools", 86 "menu.view.toggleServiceDevTools" : "Service Ontwikkelaarstools Aan\/Uit",
72 "menu.view.zoomIn" : "Inzoomen", 87 "menu.view.zoomIn" : "Inzoomen",
73 "menu.view.zoomOut" : "Uitzoomen", 88 "menu.view.zoomOut" : "Uitzoomen",
74 "menu.window" : "Venster", 89 "menu.window" : "Venster",
75 "menu.window.close" : "Sluiten", 90 "menu.window.close" : "Sluiten",
76 "menu.window.minimize" : "Minimaliseren", 91 "menu.window.minimize" : "Minimaliseren",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Alle services",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-mailadres", 97 "password.email.label" : "E-mailadres",
78 "password.headline" : "Wachtwoord resetten", 98 "password.headline" : "Wachtwoord resetten",
79 "password.link.login" : "Log in op je account", 99 "password.link.login" : "Log in op je account",
80 "password.link.signup" : "Maak een gratis account", 100 "password.link.signup" : "Maak een gratis account",
81 "password.noUser" : "Geen gebruiker bekend met dat e-mailadres", 101 "password.noUser" : "Geen gebruiker gevonden met dat e-mailadres",
82 "password.submit.label" : "Doorgaan", 102 "password.submit.label" : "Verzenden",
83 "password.successInfo" : "Controleer alsjeblieft je e-mail", 103 "password.successInfo" : "Controleer alsjeblieft je e-mail",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Upgrade account",
85 "pricing.headline" : "Ondersteun Franz", 105 "pricing.headline" : "Steun Franz",
86 "pricing.link.skipPayment" : "Ik wil de ontwikkeling van Franz niet ondersteunen.", 106 "pricing.link.skipPayment" : "Ik wil de ontwikkeling van Franz niet ondersteunen.",
87 "pricing.submit.label" : "Ik wil de ontwikkeling van Franz ondersteunen", 107 "pricing.submit.label" : "Ik wil de ontwikkeling van Franz ondersteunen",
88 "pricing.support.label" : "Selecteer je ondersteuningsplan", 108 "pricing.support.label" : "Selecteer je ondersteuningsplan",
89 "service.crashHandler.action" : "{naam} herladen", 109 "service.crashHandler.action" : "{naam} herladen",
90 "service.crashHandler.autoReload" : "Automatisch herstellen {name} proberen in {seconds} seconden", 110 "service.crashHandler.autoReload" : "Ga proberen om {name} te herstellen over {seconds} seconden",
91 "service.crashHandler.headline" : "Oh nee!", 111 "service.crashHandler.headline" : "Oh nee!",
92 "service.crashHandler.text" : "{name} heeft een probleem veroorzaakt.", 112 "service.crashHandler.text" : "{name} heeft een probleem veroorzaakt.",
93 "service.disabledHandler.action" : "Activeer {name}", 113 "service.disabledHandler.action" : "Activeer {name}",
94 "service.disabledHandler.headline" : "{name} is uitgeschakeld", 114 "service.disabledHandler.headline" : "{name} is uitgeschakeld",
95 "service.errorHandler.action" : "{naam} herladen", 115 "service.errorHandler.action" : "{naam} herladen",
96 "service.errorHandler.editAction" : "{name} aanpassen", 116 "service.errorHandler.editAction" : "Bewerk {name}",
97 "service.errorHandler.headline" : "Oh nee!", 117 "service.errorHandler.headline" : "Oh nee!",
98 "service.errorHandler.message" : "Fout", 118 "service.errorHandler.message" : "Fout",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} kon niet geladen worden.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Beginnen", 121 "services.getStarted" : "Beginnen",
101 "services.welcome" : "Welkom bij Franz", 122 "services.welcome" : "Welkom bij Franz",
102 "settings.account.account.editButton" : "Bewerk account", 123 "settings.account.account.editButton" : "Account bewerken",
103 "settings.account.accountType.basic" : "Basis Account", 124 "settings.account.accountType.basic" : "Basis Account",
104 "settings.account.accountType.premium" : "Premium Supporter Account", 125 "settings.account.accountType.premium" : "Premium Supporter Account",
105 "settings.account.buttonSave" : "Profiel aanpassen", 126 "settings.account.buttonSave" : "Profiel bijwerken",
106 "settings.account.deleteAccount" : "Account verwijderen", 127 "settings.account.deleteAccount" : "Account verwijderen",
107 "settings.account.deleteEmailSent" : "U heeft een email ontvangen met een bevestiginslink om uw account te verwijderen. Uw account en de bijhorende gegevens kunnen niet meer worden herstel na deze actie!", 128 "settings.account.deleteEmailSent" : "U heeft een email ontvangen met een bevestiginslink om uw account te verwijderen. Uw account en de bijhorende gegevens kunnen niet meer worden herstel na deze actie!",
108 "settings.account.deleteInfo" : "Indien u uw Franz account nietmeer nodig heeft, kan u hier uw account en de gerelateerde gegegevens verwijderen.", 129 "settings.account.deleteInfo" : "Indien u uw Franz account niet meer nodig heeft, kan u hier uw account en alle gerelateerde gegevens verwijderen.",
109 "settings.account.headline" : "Account", 130 "settings.account.headline" : "Account",
110 "settings.account.headlineAccount" : "Account informatie", 131 "settings.account.headlineAccount" : "Account informatie",
111 "settings.account.headlineDangerZone" : "Gevaren Zone", 132 "settings.account.headlineDangerZone" : "Gevarenzone",
112 "settings.account.headlineInvoices" : "Facturen", 133 "settings.account.headlineInvoices" : "Facturen",
113 "settings.account.headlinePassword" : "Wijzig wachtwoord", 134 "settings.account.headlinePassword" : "Wijzig wachtwoord",
114 "settings.account.headlineProfile" : "Profiel aanpassen", 135 "settings.account.headlineProfile" : "Profiel bijwerken",
115 "settings.account.headlineSubscription" : "Je abonnement", 136 "settings.account.headlineSubscription" : "Je abonnement",
116 "settings.account.headlineUpgrade" : "Upgrade je account & ondersteun Franz", 137 "settings.account.headlineUpgrade" : "Upgrade je account & ondersteun Franz",
117 "settings.account.invoiceDownload" : "Download", 138 "settings.account.invoiceDownload" : "Download",
118 "settings.account.manageSubscription.label" : "Beheer je abonnement", 139 "settings.account.manageSubscription.label" : "Beheer je abonnement",
119 "settings.account.successInfo" : "Je wijzigingen zijn opgeslagen", 140 "settings.account.successInfo" : "Je wijzigingen zijn opgeslagen",
141 "settings.account.tryReloadServices" : "Probeer opnieuw",
120 "settings.account.tryReloadUserInfoRequest" : "Probeer opnieuw", 142 "settings.account.tryReloadUserInfoRequest" : "Probeer opnieuw",
121 "settings.account.userInfoRequestFailed" : "Kon gebruikerinformatie niet laden", 143 "settings.account.userInfoRequestFailed" : "Kon gebruikersinformatie niet laden",
122 "settings.app.buttonClearAllCache" : "Cache wissen", 144 "settings.app.buttonClearAllCache" : "Cache wissen",
123 "settings.app.buttonInstallUpdate" : "Herstart & installeer update", 145 "settings.app.buttonInstallUpdate" : "Herstart & installeer update",
124 "settings.app.buttonSearchForUpdate" : "Controleer op updates", 146 "settings.app.buttonSearchForUpdate" : "Controleer op updates",
@@ -126,47 +148,47 @@
126 "settings.app.currentVersion" : "Huidige versie:", 148 "settings.app.currentVersion" : "Huidige versie:",
127 "settings.app.form.autoLaunchInBackground" : "Open op de achtergrond", 149 "settings.app.form.autoLaunchInBackground" : "Open op de achtergrond",
128 "settings.app.form.autoLaunchOnStart" : "Lanceer Franz bij opstarten", 150 "settings.app.form.autoLaunchOnStart" : "Lanceer Franz bij opstarten",
129 "settings.app.form.beta" : "Inclusief bèta versies", 151 "settings.app.form.beta" : "Inclusief beta versies",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Word lid van de Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "GPU Acceleratie Activeren", 153 "settings.app.form.enableGPUAcceleration" : "GPU Acceleratie Activeren",
132 "settings.app.form.enableMenuBar" : "Toon Franz in Menu Bar",
133 "settings.app.form.enableSpellchecking" : "Spellingcontrole inschakelen", 154 "settings.app.form.enableSpellchecking" : "Spellingcontrole inschakelen",
134 "settings.app.form.enableSystemTray" : "Toon Franz in de systeembalk", 155 "settings.app.form.enableSystemTray" : "Toon Franz in de systeembalk",
135 "settings.app.form.hideDockIcon" : "Hide Franz icon in Dock",
136 "settings.app.form.language" : "Taal", 156 "settings.app.form.language" : "Taal",
137 "settings.app.form.minimizeToSystemTray" : "Minimaliseer Franz naar de systeembalk", 157 "settings.app.form.minimizeToSystemTray" : "Minimaliseer Franz naar de systeembalk",
138 "settings.app.form.runInBackground" : "Houd Franz op de achtergrond wanneer het venster gesloten wordt", 158 "settings.app.form.runInBackground" : "Houd Franz op de achtergrond wanneer het venster gesloten wordt",
139 "settings.app.form.showDisabledServices" : "Display disabled services tabs", 159 "settings.app.form.showDisabledServices" : "Toon uitgeschakelde services",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Show unread message badge when notifications are disabled", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Toon badge met ongelezen berichten wanneer meldingen zijn uitgeschakeld",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Instellingen", 161 "settings.app.headline" : "Instellingen",
143 "settings.app.headlineAdvanced" : "Advanced", 162 "settings.app.headlineAdvanced" : "Geavanceerd",
144 "settings.app.headlineAppearance" : "Appearance", 163 "settings.app.headlineAppearance" : "Weergave",
145 "settings.app.headlineGeneral" : "Algemeen", 164 "settings.app.headlineGeneral" : "Algemeen",
146 "settings.app.headlineLanguage" : "Taal", 165 "settings.app.headlineLanguage" : "Taal",
147 "settings.app.headlineUpdates" : "Updates", 166 "settings.app.headlineUpdates" : "Updates",
148 "settings.app.restartRequired" : "Changes require restart", 167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
168 "settings.app.restartRequired" : "Deze wijziging heeft een herstart nodig",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Help us to translate Franz into your language.", 170 "settings.app.translationHelp" : "Help ons om Franz te vertalen naar uw taal.",
151 "settings.app.updateStatusAvailable" : "Update beschikbaar, downloaden...", 171 "settings.app.updateStatusAvailable" : "Update beschikbaar, downloaden...",
152 "settings.app.updateStatusSearching" : "Zoekt naar updates", 172 "settings.app.updateStatusSearching" : "Zoekt naar updates",
153 "settings.app.updateStatusUpToDate" : "Je gebruikt de laatste versie van Franz", 173 "settings.app.updateStatusUpToDate" : "Je gebruikt de laatste versie van Franz",
154 "settings.invite.headline" : "Invite Friends", 174 "settings.invite.headline" : "Nodig vrienden uit",
155 "settings.navigation.account" : "Account", 175 "settings.navigation.account" : "Account",
156 "settings.navigation.availableServices" : "Beschikbare services", 176 "settings.navigation.availableServices" : "Beschikbare services",
157 "settings.navigation.inviteFriends" : "Invite Friends", 177 "settings.navigation.inviteFriends" : "Nodig vrienden uit",
158 "settings.navigation.logout" : "Uitloggen", 178 "settings.navigation.logout" : "Uitloggen",
159 "settings.navigation.settings" : "Instellingen", 179 "settings.navigation.settings" : "Instellingen",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Jouw services", 181 "settings.navigation.yourServices" : "Jouw services",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Alle services", 183 "settings.recipes.all" : "Alle services",
162 "settings.recipes.dev" : "Ontwikkeling", 184 "settings.recipes.dev" : "Ontwikkeling",
163 "settings.recipes.headline" : "Beschikbare services", 185 "settings.recipes.headline" : "Beschikbare services",
164 "settings.recipes.missingService" : "Missing a service?", 186 "settings.recipes.missingService" : "Mist er een service?",
165 "settings.recipes.mostPopular" : "Meest populair", 187 "settings.recipes.mostPopular" : "Meest populair",
166 "settings.recipes.nothingFound" : "Sorry, maar geen enkele service kwam overeen met je zoekterm.", 188 "settings.recipes.nothingFound" : "Sorry, maar geen enkele service kwam overeen met je zoekterm.",
167 "settings.recipes.servicesSuccessfulAddedInfo" : "Service succesvol toegevoegd", 189 "settings.recipes.servicesSuccessfulAddedInfo" : "Service succesvol toegevoegd",
168 "settings.searchService" : "Search service", 190 "settings.searchService" : "Service zoeken",
169 "settings.service.error.goBack" : "Terug naar de services", 191 "settings.service.error.goBack" : "Terug naar services",
170 "settings.service.error.headline" : "Fout", 192 "settings.service.error.headline" : "Fout",
171 "settings.service.error.message" : "Kon het service-recept niet laden.", 193 "settings.service.error.message" : "Kon het service-recept niet laden.",
172 "settings.service.form.addServiceHeadline" : "{name} toevoegen", 194 "settings.service.form.addServiceHeadline" : "{name} toevoegen",
@@ -177,62 +199,84 @@
177 "settings.service.form.customUrlValidationError" : "Kon de custom {name} server niet valideren.", 199 "settings.service.form.customUrlValidationError" : "Kon de custom {name} server niet valideren.",
178 "settings.service.form.deleteButton" : "Service verwijderen", 200 "settings.service.form.deleteButton" : "Service verwijderen",
179 "settings.service.form.editServiceHeadline" : "{name} aanpassen", 201 "settings.service.form.editServiceHeadline" : "{name} aanpassen",
180 "settings.service.form.enableAudio" : "Enable audio", 202 "settings.service.form.enableAudio" : "Audio inschakelen",
181 "settings.service.form.enableBadge" : "Show unread message badges", 203 "settings.service.form.enableBadge" : "Toon badges met ongelezen berichten",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Dark Mode aanzetten",
183 "settings.service.form.enableNotification" : "Notificaties aanzetten", 205 "settings.service.form.enableNotification" : "Notificaties aanzetten",
184 "settings.service.form.enableService" : "Service aanzetten", 206 "settings.service.form.enableService" : "Service aanzetten",
185 "settings.service.form.headlineBadges" : "Unread message badges", 207 "settings.service.form.headlineBadges" : "Ongelezen berichten badges",
186 "settings.service.form.headlineGeneral" : "Algemeen", 208 "settings.service.form.headlineGeneral" : "Algemeen",
187 "settings.service.form.headlineNotifications" : "Notifications", 209 "settings.service.form.headlineNotifications" : "Meldingen",
188 "settings.service.form.icon" : "Custom icon", 210 "settings.service.form.icon" : "Aangepast icoon",
189 "settings.service.form.iconDelete" : "Verwijderen", 211 "settings.service.form.iconDelete" : "Verwijderen",
190 "settings.service.form.iconUpload" : "Drop your image, or click here", 212 "settings.service.form.iconUpload" : "Sleep en drop je afbeelding, of klik hier",
191 "settings.service.form.indirectMessageInfo" : "Je wordt verwittigd over alle nieuwe berichten in een kanaal, niet alleen @username, @channel, @here, ...", 213 "settings.service.form.indirectMessageInfo" : "Je wordt verwittigd over alle nieuwe berichten in een kanaal, niet alleen @username, @channel, @here, ...",
192 "settings.service.form.indirectMessages" : "Toon berichten-badge voor alle nieuwe berichten", 214 "settings.service.form.indirectMessages" : "Toon berichten-badge voor alle nieuwe berichten",
193 "settings.service.form.isMutedInfo" : "When disabled, all notification sounds and audio playback are muted", 215 "settings.service.form.isMutedInfo" : "Indien uitgeschakeld zullen alle meldingsgeluiden en afgespeelde audio uitgeschakeld zijn",
194 "settings.service.form.name" : "Naam", 216 "settings.service.form.name" : "Naam",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Instellingen",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "Proxy instellingen worden niet gesynchroniseerd met de Franz servers.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Proxy gebruiken",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Wachtwoord (optioneel)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Poort",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Start Franz opnieuw op na het aanpassen van proxy Instellingen.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Gebruiker (optioneel)",
203 "settings.service.form.saveButton" : "Service bewaren", 225 "settings.service.form.saveButton" : "Service opslaan",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Gehost", 226 "settings.service.form.tabHosted" : "Gehost",
207 "settings.service.form.tabOnPremise" : "Intern gehost â­ï¸", 227 "settings.service.form.tabOnPremise" : "Intern gehost â­ï¸",
208 "settings.service.form.team" : "Team", 228 "settings.service.form.team" : "Team",
209 "settings.service.form.useHostedService" : "Use the hosted {name} service.", 229 "settings.service.form.useHostedService" : "Gebruik de gehoste {name} service.",
210 "settings.service.form.yourServices" : "Jouw services", 230 "settings.service.form.yourServices" : "Jouw services",
211 "settings.services.deletedInfo" : "Service werd verwijderd", 231 "settings.services.deletedInfo" : "Service werd verwijderd",
212 "settings.services.discoverServices" : "Services ontdekken", 232 "settings.services.discoverServices" : "Services ontdekken",
213 "settings.services.headline" : "Jouw services", 233 "settings.services.headline" : "Jouw services",
214 "settings.services.noServicesAdded" : "Je hebt nog geen services toegevoegd.", 234 "settings.services.noServicesAdded" : "Je hebt nog geen services toegevoegd.",
215 "settings.services.tooltip.isDisabled" : "Service staat uit", 235 "settings.services.servicesRequestFailed" : "Could not load your services",
216 "settings.services.tooltip.isMuted" : "All sounds are muted", 236 "settings.services.tooltip.isDisabled" : "Service is uitgeschakeld",
237 "settings.services.tooltip.isMuted" : "Alle geluiden zijn uitgeschakeld",
217 "settings.services.tooltip.notificationsDisabled" : "Notificaties staan uit", 238 "settings.services.tooltip.notificationsDisabled" : "Notificaties staan uit",
218 "settings.services.updatedInfo" : "Je wijzigingen werden bewaard", 239 "settings.services.updatedInfo" : "Je wijzigingen zijn opgeslagen",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Team",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Bedrijf", 246 "settings.user.form.accountType.company" : "Bedrijf",
220 "settings.user.form.accountType.individual" : "Particulier", 247 "settings.user.form.accountType.individual" : "Particulier",
221 "settings.user.form.accountType.label" : "Account type", 248 "settings.user.form.accountType.label" : "Account type",
222 "settings.user.form.accountType.non-profit" : "Non-Profit", 249 "settings.user.form.accountType.non-profit" : "Non-Profit",
223 "settings.user.form.currentPassword" : "Huidig wachtwoord", 250 "settings.user.form.currentPassword" : "Huidig wachtwoord",
224 "settings.user.form.email" : "Email", 251 "settings.user.form.email" : "Email",
225 "settings.user.form.firstname" : "Naam", 252 "settings.user.form.firstname" : "Voornaam",
226 "settings.user.form.lastname" : "Achternaam", 253 "settings.user.form.lastname" : "Achternaam",
227 "settings.user.form.newPassword" : "Nieuw wachtwoord", 254 "settings.user.form.newPassword" : "Nieuw wachtwoord",
228 "sidebar.addNewService" : "!!!Add new service", 255 "settings.workspace.add.form.name" : "Naam",
229 "sidebar.muteApp" : "Disable notifications & audio", 256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Naam",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Probeer opnieuw",
266 "settings.workspaces.updatedInfo" : "Je wijzigingen zijn opgeslagen",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
270 "sidebar.addNewService" : "Nieuw service toevoegen",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
272 "sidebar.muteApp" : "Berichten & geluid uitschakelen",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Instellingen", 274 "sidebar.settings" : "Instellingen",
231 "sidebar.unmuteApp" : "Enable notifications & audio", 275 "sidebar.unmuteApp" : "Berichten & geluid inschakelen",
232 "signup.company.label" : "Bedrijf", 276 "signup.company.label" : "Bedrijf",
233 "signup.email.label" : "E-mailadres", 277 "signup.email.label" : "E-mailadres",
234 "signup.emailDuplicate" : "Er bestaat reeds een gebruiker met dat e-mailadres", 278 "signup.emailDuplicate" : "Er bestaat al een gebruiker met dat e-mailadres",
235 "signup.firstname.label" : "Naam", 279 "signup.firstname.label" : "Voornaam",
236 "signup.headline" : "Registreren", 280 "signup.headline" : "Registreren",
237 "signup.lastname.label" : "Achternaam", 281 "signup.lastname.label" : "Achternaam",
238 "signup.legal.info" : "Door een account aan te maken aanvaard je de", 282 "signup.legal.info" : "Door een account aan te maken aanvaard je de",
@@ -241,15 +285,14 @@
241 "signup.link.login" : "Al een account, inloggen?", 285 "signup.link.login" : "Al een account, inloggen?",
242 "signup.password.label" : "Wachtwoord", 286 "signup.password.label" : "Wachtwoord",
243 "signup.submit.label" : "Account aanmaken", 287 "signup.submit.label" : "Account aanmaken",
244 "subscription.euTaxInfo" : "EU residents: local sales tax may apply", 288 "subscription.euTaxInfo" : "Bewoners binnen EU: lokale belasting kan van toepassing zijn",
245 "subscription.features.ads" : "Geen reclame, nooit!", 289 "subscription.features.ads" : "Geen reclame, nooit!",
246 "subscription.features.comingSoon" : "komt binnenkort", 290 "subscription.features.comingSoon" : "komt binnenkort",
247 "subscription.features.encryptedSync" : "Synchronisatie van geëncrypteerde sessies", 291 "subscription.features.noInterruptions" : "Geen haperingen & pop ups over upgrades",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Voeg op-locatie\/gehoste diensten zoals Mattermost toe",
249 "subscription.features.onpremise" : "Intern gehoste services zoals HipChat", 293 "subscription.features.proxy" : "Proxy ondersteuning voor services",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Ondersteuning voor spellingscheck",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Een betalend account voor Franz omvat", 296 "subscription.includedFeatures" : "Een betalend account voor Franz omvat",
254 "subscription.paymentSessionError" : "Betalingsformulier kon niet geladen worden", 297 "subscription.paymentSessionError" : "Betalingsformulier kon niet geladen worden",
255 "subscription.submit.label" : "Ik wil de ontwikkeling van Franz steunen", 298 "subscription.submit.label" : "Ik wil de ontwikkeling van Franz steunen",
@@ -259,19 +302,30 @@
259 "subscriptionPopup.buttonCancel" : "Annuleren", 302 "subscriptionPopup.buttonCancel" : "Annuleren",
260 "subscriptionPopup.buttonDone" : "Klaar", 303 "subscriptionPopup.buttonDone" : "Klaar",
261 "tabs.item.deleteService" : "Service verwijderen", 304 "tabs.item.deleteService" : "Service verwijderen",
262 "tabs.item.disableAudio" : "Disable audio", 305 "tabs.item.disableAudio" : "Audio uitschakelen",
263 "tabs.item.disableNotifications" : "Notificaties uitschakelen", 306 "tabs.item.disableNotifications" : "Notificaties uitschakelen",
264 "tabs.item.disableService" : "Service uitschakelen", 307 "tabs.item.disableService" : "Service uitschakelen",
265 "tabs.item.edit" : "Aanpassen", 308 "tabs.item.edit" : "Aanpassen",
266 "tabs.item.enableAudio" : "Enable audio", 309 "tabs.item.enableAudio" : "Audio inschakelen",
267 "tabs.item.enableNotification" : "Notificaties inschakelen", 310 "tabs.item.enableNotification" : "Notificaties inschakelen",
268 "tabs.item.enableService" : "Service aanzetten", 311 "tabs.item.enableService" : "Service inschakelen",
269 "tabs.item.reload" : "Herladen", 312 "tabs.item.reload" : "Herladen",
270 "validation.email" : "{field} is not valid", 313 "validation.email" : "{field} is niet geldig",
271 "validation.minLength" : "{field} should be at least {length} characters long", 314 "validation.minLength" : "{field} moet minimaal {length} karakters lang zijn",
272 "validation.required" : "{field} is required", 315 "validation.oneRequired" : "At least one is required",
273 "validation.url" : "{field} is not a valid URL", 316 "validation.required" : "{field} is vereist",
317 "validation.url" : "{field} is niet een geldige URL",
274 "welcome.loginButton" : "Inloggen op je account", 318 "welcome.loginButton" : "Inloggen op je account",
275 "welcome.signupButton" : "Maak een gratis account aan", 319 "welcome.signupButton" : "Maak een gratis account aan",
276 "welcome.slogan" : "Messaging that works for you" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Alle services",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/nl.json b/src/i18n/locales/nl.json
index 940f24b0b..03d4474c1 100644
--- a/src/i18n/locales/nl.json
+++ b/src/i18n/locales/nl.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Laad opnieuw", 2 "app.errorHandler.action" : "Herladen",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Er ging iets mis",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Sponsor Franz", 5 "feature.delayApp.action" : "Sponsor Franz",
5 "feature.delayApp.headline" : "Sponsor Franz om wachten over te slaan", 6 "feature.delayApp.headline" : "Sponsor Franz om wachten over te slaan",
6 "feature.delayApp.text" : "Franz gaat over {seconds} seconden verder.", 7 "feature.delayApp.text" : "Franz gaat over {seconds} seconden verder.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Kan geen verbinding maken met de Franz-services", 15 "global.api.unhealthy" : "Kan geen verbinding maken met de Franz-services",
8 "global.notConnectedToTheInternet" : "U bent niet verbonden met het internet.", 16 "global.notConnectedToTheInternet" : "U bent niet verbonden met het internet.",
17 "global.spellchecker.useDefault" : "Gebruik systeemstandaard ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spelling checken",
9 "import.headline" : "Importeer uw Franz 4-services", 21 "import.headline" : "Importeer uw Franz 4-services",
10 "import.notSupportedHeadline" : "Services die nog niet ondersteund worden in Franz 5", 22 "import.notSupportedHeadline" : "Services die nog niet ondersteund worden in Franz 5",
11 "import.skip.label" : "Ik wil services handmatig toevoegen", 23 "import.skip.label" : "Ik wil services handmatig toevoegen",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Inloggen", 44 "login.submit.label" : "Inloggen",
33 "login.tokenExpired" : "De sessie is verlopen, log opnieuw in alsjeblieft.", 45 "login.tokenExpired" : "De sessie is verlopen, log opnieuw in alsjeblieft.",
34 "menu.app.about" : "Over Franz", 46 "menu.app.about" : "Over Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Verbergen", 48 "menu.app.hide" : "Verbergen",
36 "menu.app.hideOthers" : "Andere verbergen", 49 "menu.app.hideOthers" : "Andere verbergen",
37 "menu.app.quit" : "Afsluiten", 50 "menu.app.quit" : "Afsluiten",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Ondersteuning", 72 "menu.help.support" : "Ondersteuning",
60 "menu.help.tos" : "Servicevoorwaarden", 73 "menu.help.tos" : "Servicevoorwaarden",
61 "menu.services" : "Diensten", 74 "menu.services" : "Diensten",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Nieuwe dienst toevoegen", 76 "menu.services.addNewService" : "Nieuwe dienst toevoegen",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Weergave", 78 "menu.view" : "Weergave",
64 "menu.view.enterFullScreen" : "Gebruik volledig scherm", 79 "menu.view.enterFullScreen" : "Gebruik volledig scherm",
65 "menu.view.exitFullScreen" : "Volledig scherm verlaten", 80 "menu.view.exitFullScreen" : "Volledig scherm verlaten",
@@ -74,6 +89,11 @@
74 "menu.window" : "Venster", 89 "menu.window" : "Venster",
75 "menu.window.close" : "Sluiten", 90 "menu.window.close" : "Sluiten",
76 "menu.window.minimize" : "Minimaliseren", 91 "menu.window.minimize" : "Minimaliseren",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Alle services",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-mailadres", 97 "password.email.label" : "E-mailadres",
78 "password.headline" : "Wachtwoord vergeten", 98 "password.headline" : "Wachtwoord vergeten",
79 "password.link.login" : "Log in op je account", 99 "password.link.login" : "Log in op je account",
@@ -92,11 +112,12 @@
92 "service.crashHandler.text" : "{name} heeft een fout veroorzaakt.", 112 "service.crashHandler.text" : "{name} heeft een fout veroorzaakt.",
93 "service.disabledHandler.action" : "Activeer {name}", 113 "service.disabledHandler.action" : "Activeer {name}",
94 "service.disabledHandler.headline" : "{name} is uitgeschakeld", 114 "service.disabledHandler.headline" : "{name} is uitgeschakeld",
95 "service.errorHandler.action" : "Laad {name} opnieuw", 115 "service.errorHandler.action" : "{name} herladen",
96 "service.errorHandler.editAction" : "Bewerk {name}", 116 "service.errorHandler.editAction" : "Bewerk {name}",
97 "service.errorHandler.headline" : "Oh nee!", 117 "service.errorHandler.headline" : "Oh nee!",
98 "service.errorHandler.message" : "Fout", 118 "service.errorHandler.message" : "Fout",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} kon niet geladen worden.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Begin", 121 "services.getStarted" : "Begin",
101 "services.welcome" : "Welkom bij Franz", 122 "services.welcome" : "Welkom bij Franz",
102 "settings.account.account.editButton" : "Bewerk account", 123 "settings.account.account.editButton" : "Bewerk account",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Download", 138 "settings.account.invoiceDownload" : "Download",
118 "settings.account.manageSubscription.label" : "Beheer je abonnement", 139 "settings.account.manageSubscription.label" : "Beheer je abonnement",
119 "settings.account.successInfo" : "Je wijzigingen zijn opgeslagen", 140 "settings.account.successInfo" : "Je wijzigingen zijn opgeslagen",
141 "settings.account.tryReloadServices" : "Probeer opnieuw",
120 "settings.account.tryReloadUserInfoRequest" : "Probeer opnieuw", 142 "settings.account.tryReloadUserInfoRequest" : "Probeer opnieuw",
121 "settings.account.userInfoRequestFailed" : "Kon gebruikersinformatie niet laden", 143 "settings.account.userInfoRequestFailed" : "Kon gebruikersinformatie niet laden",
122 "settings.app.buttonClearAllCache" : "Cache legen", 144 "settings.app.buttonClearAllCache" : "Cache legen",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Inclusief bètaversies", 151 "settings.app.form.beta" : "Inclusief bètaversies",
130 "settings.app.form.darkMode" : "Stap over naar de donkere kant", 152 "settings.app.form.darkMode" : "Stap over naar de donkere kant",
131 "settings.app.form.enableGPUAcceleration" : "Schakel videokaart acceleratie in ", 153 "settings.app.form.enableGPUAcceleration" : "Schakel videokaart acceleratie in ",
132 "settings.app.form.enableMenuBar" : "Toon Franz in menubalk",
133 "settings.app.form.enableSpellchecking" : "Zet spellingcontrole aan", 154 "settings.app.form.enableSpellchecking" : "Zet spellingcontrole aan",
134 "settings.app.form.enableSystemTray" : "Toon Franz in de systeembalk", 155 "settings.app.form.enableSystemTray" : "Toon Franz in de systeembalk",
135 "settings.app.form.hideDockIcon" : "Verberg Franz in Dock",
136 "settings.app.form.language" : "Taal", 156 "settings.app.form.language" : "Taal",
137 "settings.app.form.minimizeToSystemTray" : "Minimaliseer Franz naar de systeembalk", 157 "settings.app.form.minimizeToSystemTray" : "Minimaliseer Franz naar de systeembalk",
138 "settings.app.form.runInBackground" : "Houd Franz op de achtergrond wanneer het venster gesloten wordt", 158 "settings.app.form.runInBackground" : "Houd Franz op de achtergrond wanneer het venster gesloten wordt",
139 "settings.app.form.showDisabledServices" : "Toon uitgeschakelde services", 159 "settings.app.form.showDisabledServices" : "Toon uitgeschakelde services",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Toon badge met ongelezen berichten wanneer meldingen zijn uitgeschakeld", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Toon badge met ongelezen berichten wanneer meldingen zijn uitgeschakeld",
141 "settings.app.form.spellcheckerLanguage" : "Spelling checken",
142 "settings.app.headline" : "Instellingen", 161 "settings.app.headline" : "Instellingen",
143 "settings.app.headlineAdvanced" : "Geavanceerd", 162 "settings.app.headlineAdvanced" : "Geavanceerd",
144 "settings.app.headlineAppearance" : "Weergave", 163 "settings.app.headlineAppearance" : "Weergave",
145 "settings.app.headlineGeneral" : "Algemeen", 164 "settings.app.headlineGeneral" : "Algemeen",
146 "settings.app.headlineLanguage" : "Taal", 165 "settings.app.headlineLanguage" : "Taal",
147 "settings.app.headlineUpdates" : "Updates", 166 "settings.app.headlineUpdates" : "Updates",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Deze wijziging heeft een herstart nodig", 168 "settings.app.restartRequired" : "Deze wijziging heeft een herstart nodig",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Help ons om Franz te vertalen naar uw taal.", 170 "settings.app.translationHelp" : "Help ons om Franz te vertalen naar uw taal.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Nodig vrienden uit", 177 "settings.navigation.inviteFriends" : "Nodig vrienden uit",
158 "settings.navigation.logout" : "Uitloggen", 178 "settings.navigation.logout" : "Uitloggen",
159 "settings.navigation.settings" : "Instellingen", 179 "settings.navigation.settings" : "Instellingen",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Jouw services", 181 "settings.navigation.yourServices" : "Jouw services",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Alle services", 183 "settings.recipes.all" : "Alle services",
162 "settings.recipes.dev" : "Ontwikkeling", 184 "settings.recipes.dev" : "Ontwikkeling",
163 "settings.recipes.headline" : "Beschikbare services", 185 "settings.recipes.headline" : "Beschikbare services",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Toon berichtenbadge voor alle nieuwe berichten", 214 "settings.service.form.indirectMessages" : "Toon berichtenbadge voor alle nieuwe berichten",
193 "settings.service.form.isMutedInfo" : "Indien uitgeschakeld zullen alle meldinggeluiden en afgespeelde audio uitgeschakeld zijn", 215 "settings.service.form.isMutedInfo" : "Indien uitgeschakeld zullen alle meldinggeluiden en afgespeelde audio uitgeschakeld zijn",
194 "settings.service.form.name" : "Naam", 216 "settings.service.form.name" : "Naam",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy instellingen",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy instellingen worden niet gesynchroniseerd met de Franz servers", 219 "settings.service.form.proxy.info" : "Proxy instellingen worden niet gesynchroniseerd met de Franz servers",
198 "settings.service.form.proxy.isEnabled" : "Proxy gebruiken", 220 "settings.service.form.proxy.isEnabled" : "Proxy gebruiken",
199 "settings.service.form.proxy.password" : "Wachtwoord (optioneel)", 221 "settings.service.form.proxy.password" : "Wachtwoord (optioneel)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Poort",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Start Franz opnieuw na het aanpassen van proxy instellingen.",
202 "settings.service.form.proxy.user" : "Gebruiker (optioneel)", 224 "settings.service.form.proxy.user" : "Gebruiker (optioneel)",
203 "settings.service.form.saveButton" : "Service opslaan", 225 "settings.service.form.saveButton" : "Service opslaan",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Gehost", 226 "settings.service.form.tabHosted" : "Gehost",
207 "settings.service.form.tabOnPremise" : "Zelf-gehost â­ï¸", 227 "settings.service.form.tabOnPremise" : "Zelf-gehost â­ï¸",
208 "settings.service.form.team" : "Team", 228 "settings.service.form.team" : "Team",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Ontdek services", 232 "settings.services.discoverServices" : "Ontdek services",
213 "settings.services.headline" : "Jouw services", 233 "settings.services.headline" : "Jouw services",
214 "settings.services.noServicesAdded" : "Je hebt nog geen services toegevoegd.", 234 "settings.services.noServicesAdded" : "Je hebt nog geen services toegevoegd.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Service is uitgeschakeld", 236 "settings.services.tooltip.isDisabled" : "Service is uitgeschakeld",
216 "settings.services.tooltip.isMuted" : "Alle geluiden zijn uitgeschakeld", 237 "settings.services.tooltip.isMuted" : "Alle geluiden zijn uitgeschakeld",
217 "settings.services.tooltip.notificationsDisabled" : "Meldingen zijn uitgeschakeld", 238 "settings.services.tooltip.notificationsDisabled" : "Meldingen zijn uitgeschakeld",
218 "settings.services.updatedInfo" : "Je wijzigingen zijn opgeslagen", 239 "settings.services.updatedInfo" : "Je wijzigingen zijn opgeslagen",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Team",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Bedrijf", 246 "settings.user.form.accountType.company" : "Bedrijf",
220 "settings.user.form.accountType.individual" : "Individueel", 247 "settings.user.form.accountType.individual" : "Individueel",
221 "settings.user.form.accountType.label" : "Accounttype", 248 "settings.user.form.accountType.label" : "Accounttype",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Voornaam", 252 "settings.user.form.firstname" : "Voornaam",
226 "settings.user.form.lastname" : "Achternaam", 253 "settings.user.form.lastname" : "Achternaam",
227 "settings.user.form.newPassword" : "Nieuw wachtwoord", 254 "settings.user.form.newPassword" : "Nieuw wachtwoord",
255 "settings.workspace.add.form.name" : "Naam",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Naam",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Probeer opnieuw",
266 "settings.workspaces.updatedInfo" : "Je wijzigingen zijn opgeslagen",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Voeg service toe", 270 "sidebar.addNewService" : "Voeg service toe",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Schakel berichten & geluid uit", 272 "sidebar.muteApp" : "Schakel berichten & geluid uit",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Instellingen", 274 "sidebar.settings" : "Instellingen",
231 "sidebar.unmuteApp" : "Berichten & geluid inschakelen", 275 "sidebar.unmuteApp" : "Berichten & geluid inschakelen",
232 "signup.company.label" : "Bedrijf", 276 "signup.company.label" : "Bedrijf",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Bewoners binnen EU: lokale belasting kan van toepassing zijn", 288 "subscription.euTaxInfo" : "Bewoners binnen EU: lokale belasting kan van toepassing zijn",
245 "subscription.features.ads" : "Geen advertenties, nooit!", 289 "subscription.features.ads" : "Geen advertenties, nooit!",
246 "subscription.features.comingSoon" : "komt binnenkort", 290 "subscription.features.comingSoon" : "komt binnenkort",
247 "subscription.features.encryptedSync" : "Beveiligde sessie synchronisatie",
248 "subscription.features.noInterruptions" : "Geen haperingen & pop ups over upgrades", 291 "subscription.features.noInterruptions" : "Geen haperingen & pop ups over upgrades",
249 "subscription.features.onpremise" : "Add on-geschikt\/gehoste services zoals HipChat", 292 "subscription.features.onpremise.mattermost" : "Voeg op-locatie\/gehoste diensten zoals Mattermost toe",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy understeuning voor diensten", 293 "subscription.features.proxy" : "Proxy understeuning voor diensten",
252 "subscription.features.spellchecker" : "Ondersteuning voor spellingscheck", 294 "subscription.features.spellchecker" : "Ondersteuning voor spellingscheck",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Betaald Franz Premium Supporter Account bevat", 296 "subscription.includedFeatures" : "Betaald Franz Premium Supporter Account bevat",
254 "subscription.paymentSessionError" : "Kan betaalformulier niet initialiseren", 297 "subscription.paymentSessionError" : "Kan betaalformulier niet initialiseren",
255 "subscription.submit.label" : "Ik wil de ontwikkeling van Franz ondersteunen", 298 "subscription.submit.label" : "Ik wil de ontwikkeling van Franz ondersteunen",
@@ -266,12 +309,23 @@
266 "tabs.item.enableAudio" : "Audio inschakelen", 309 "tabs.item.enableAudio" : "Audio inschakelen",
267 "tabs.item.enableNotification" : "Meldingen inschakelen", 310 "tabs.item.enableNotification" : "Meldingen inschakelen",
268 "tabs.item.enableService" : "Service inschakelen", 311 "tabs.item.enableService" : "Service inschakelen",
269 "tabs.item.reload" : "Laad opnieuw", 312 "tabs.item.reload" : "Herladen",
270 "validation.email" : "{field} is niet geldig", 313 "validation.email" : "{field} is niet geldig",
271 "validation.minLength" : "{field} moet minimaal {length} karakters lang zijn", 314 "validation.minLength" : "{field} moet minimaal {length} karakters lang zijn",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} is vereist", 316 "validation.required" : "{field} is vereist",
273 "validation.url" : "{field} is niet een geldige URL", 317 "validation.url" : "{field} is niet een geldige URL",
274 "welcome.loginButton" : "Log in op je account", 318 "welcome.loginButton" : "Log in op je account",
275 "welcome.signupButton" : "Maak een gratis account", 319 "welcome.signupButton" : "Maak een gratis account",
276 "welcome.slogan" : "Messaging die voor jou werkt" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Alle services",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/pl.json b/src/i18n/locales/pl.json
index d45e5ce24..591b13145 100644
--- a/src/i18n/locales/pl.json
+++ b/src/i18n/locales/pl.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Przeładuj", 2 "app.errorHandler.action" : "Przeładuj",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Coś poszło nie tak",
4 "feature.announcements.changelog.headline" : "Zmiany we Franzie {version}",
4 "feature.delayApp.action" : "Uzyskaj licencjÄ™ Franz Supporter", 5 "feature.delayApp.action" : "Uzyskaj licencjÄ™ Franz Supporter",
5 "feature.delayApp.headline" : "Kup licencję Franz Supporter , aby nie czekać", 6 "feature.delayApp.headline" : "Aby nie czekać kup licencję Franz Supporter",
6 "feature.delayApp.text" : "Franz będzie kontynuował za {seconds} sekund.", 7 "feature.delayApp.text" : "Franz będzie kontynuował za {seconds} sekund.",
8 "feature.shareFranz.action.email" : "Wyślij nam maila",
9 "feature.shareFranz.action.facebook" : "Udostępnij na Facebooku",
10 "feature.shareFranz.action.twitter" : "Udostępnij na Twitterze",
11 "feature.shareFranz.headline" : "Franz jest lepszy, gdy tworzymy go razem!",
12 "feature.shareFranz.shareText.email" : "Dodałem {count} serwisów do Franza! Pobierz darmową aplikacją WhatsApp, Messenger, Slack, Skype i inne na www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "Dodałem {count} serwisów do Franza! Pobierz darmową aplikacją WhatsApp, Messenger, Slack, Skype i inne na www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Powiedz znajomym i kolegom o tym, jak odlotowy jest Franz i pomóż nam go spopularyzować.",
7 "global.api.unhealthy" : "Nie można połączyć się z usługami Franz online", 15 "global.api.unhealthy" : "Nie można połączyć się z usługami Franz online",
8 "global.notConnectedToTheInternet" : "Nie masz połączenia z Internetem.", 16 "global.notConnectedToTheInternet" : "Nie masz połączenia z Internetem.",
17 "global.spellchecker.useDefault" : "Użyj domyślnego dla systemu ({default})",
18 "global.spellchecking.autodetect" : "Automatycznie wykryj język",
19 "global.spellchecking.autodetect.short" : "Automatycznie",
20 "global.spellchecking.language" : "Język słownika",
9 "import.headline" : "Importuj usługi Franz 4", 21 "import.headline" : "Importuj usługi Franz 4",
10 "import.notSupportedHeadline" : "Usługi, które nie są jeszcze obsługiwane w Franz 5", 22 "import.notSupportedHeadline" : "Usługi, które nie są jeszcze obsługiwane w Franz 5",
11 "import.skip.label" : "Chcę dodać usługi samodzielnie", 23 "import.skip.label" : "Chcę dodać usługi samodzielnie",
@@ -25,18 +37,19 @@
25 "login.email.label" : "Adres email", 37 "login.email.label" : "Adres email",
26 "login.headline" : "Zaloguj siÄ™", 38 "login.headline" : "Zaloguj siÄ™",
27 "login.invalidCredentials" : "Adres email lub hasło są błędne", 39 "login.invalidCredentials" : "Adres email lub hasło są błędne",
28 "login.link.password" : "Wyzeruj hasło", 40 "login.link.password" : "Przypomnij hasło",
29 "login.link.signup" : "Załóż darmowe konto", 41 "login.link.signup" : "Załóż darmowe konto",
30 "login.password.label" : "Hasło", 42 "login.password.label" : "Hasło",
31 "login.serverLogout" : "Twoja sesja wygasła, zaloguj się ponownie.", 43 "login.serverLogout" : "Twoja sesja wygasła, zaloguj się ponownie.",
32 "login.submit.label" : "Zaloguj siÄ™", 44 "login.submit.label" : "Zaloguj siÄ™",
33 "login.tokenExpired" : "Twoja sesja wygasła, zaloguj się ponownie.", 45 "login.tokenExpired" : "Twoja sesja wygasła, zaloguj się ponownie.",
34 "menu.app.about" : "O Franz", 46 "menu.app.about" : "O Franz",
47 "menu.app.announcement" : "Co słychać?",
35 "menu.app.hide" : "Ukryj", 48 "menu.app.hide" : "Ukryj",
36 "menu.app.hideOthers" : "Ukryj pozostałe", 49 "menu.app.hideOthers" : "Ukryj pozostałe",
37 "menu.app.quit" : "Zakończ", 50 "menu.app.quit" : "Zakończ",
38 "menu.app.settings" : "Ustawienia", 51 "menu.app.settings" : "Ustawienia",
39 "menu.app.unhide" : "Pokaż", 52 "menu.app.unhide" : "Pokaż więcej",
40 "menu.edit" : "Edytuj", 53 "menu.edit" : "Edytuj",
41 "menu.edit.copy" : "Skopiuj", 54 "menu.edit.copy" : "Skopiuj",
42 "menu.edit.cut" : "Wytnij", 55 "menu.edit.cut" : "Wytnij",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Wsparcie", 72 "menu.help.support" : "Wsparcie",
60 "menu.help.tos" : "Warunki świadczenia usług", 73 "menu.help.tos" : "Warunki świadczenia usług",
61 "menu.services" : "Usługi", 74 "menu.services" : "Usługi",
75 "menu.services.activatePreviousService" : "WÅ‚Ä…cz poprzedni serwis",
62 "menu.services.addNewService" : "Dodaj nową usługę...", 76 "menu.services.addNewService" : "Dodaj nową usługę...",
77 "menu.services.setNextServiceActive" : "WÅ‚Ä…cz kolejny serwis",
63 "menu.view" : "Widok", 78 "menu.view" : "Widok",
64 "menu.view.enterFullScreen" : "Włącz tryb pełnoekranowy", 79 "menu.view.enterFullScreen" : "Włącz tryb pełnoekranowy",
65 "menu.view.exitFullScreen" : "Zakończ tryb pełnoekranowy", 80 "menu.view.exitFullScreen" : "Zakończ tryb pełnoekranowy",
@@ -68,20 +83,25 @@
68 "menu.view.resetZoom" : "Domyślny rozmiar", 83 "menu.view.resetZoom" : "Domyślny rozmiar",
69 "menu.view.toggleDevTools" : "Pokaż narzędzia developerskie", 84 "menu.view.toggleDevTools" : "Pokaż narzędzia developerskie",
70 "menu.view.toggleFullScreen" : "Przełącz tryb pełnoekranowy", 85 "menu.view.toggleFullScreen" : "Przełącz tryb pełnoekranowy",
71 "menu.view.toggleServiceDevTools" : "Włącz narzędzia developerskie serwisu", 86 "menu.view.toggleServiceDevTools" : "Włącz narzędzia developerskie usługi",
72 "menu.view.zoomIn" : "Powiększ", 87 "menu.view.zoomIn" : "Powiększ",
73 "menu.view.zoomOut" : "Pomniejsz", 88 "menu.view.zoomOut" : "Pomniejsz",
74 "menu.window" : "Okno", 89 "menu.window" : "Okno",
75 "menu.window.close" : "Zamknij", 90 "menu.window.close" : "Zamknij",
76 "menu.window.minimize" : "Zminimalizuj", 91 "menu.window.minimize" : "Zminimalizuj",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Wszystkie usługi",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Adres email", 97 "password.email.label" : "Adres email",
78 "password.headline" : "Wyzeruj hasło", 98 "password.headline" : "Przypomnij hasło",
79 "password.link.login" : "Zaloguj siÄ™ na swoje konto", 99 "password.link.login" : "Zaloguj siÄ™ na swoje konto",
80 "password.link.signup" : "Stwórz darmowe konto", 100 "password.link.signup" : "Stwórz darmowe konto",
81 "password.noUser" : "Nie znaleziono użytkownika z takim adresem email", 101 "password.noUser" : "Nie znaleziono użytkownika z takim adresem email",
82 "password.submit.label" : "Wyślij", 102 "password.submit.label" : "Wyślij",
83 "password.successInfo" : "Proszę sprawdzić swój email", 103 "password.successInfo" : "Proszę sprawdzić swój email",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Ulepsz swoje konto",
85 "pricing.headline" : "Wspieraj Franz", 105 "pricing.headline" : "Wspieraj Franz",
86 "pricing.link.skipPayment" : "Nie chcę wspierać rozwoju aplikacji Franz.", 106 "pricing.link.skipPayment" : "Nie chcę wspierać rozwoju aplikacji Franz.",
87 "pricing.submit.label" : "Chcę wspierać rozwój aplikacji Franz", 107 "pricing.submit.label" : "Chcę wspierać rozwój aplikacji Franz",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Edytuj {name}", 116 "service.errorHandler.editAction" : "Edytuj {name}",
97 "service.errorHandler.headline" : "O nie!", 117 "service.errorHandler.headline" : "O nie!",
98 "service.errorHandler.message" : "BÅ‚Ä…d", 118 "service.errorHandler.message" : "BÅ‚Ä…d",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "Nie udało się załadować {name}.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Zacznij", 121 "services.getStarted" : "Zacznij",
101 "services.welcome" : "Witaj w programie Franz", 122 "services.welcome" : "Witaj w programie Franz",
102 "settings.account.account.editButton" : "Modyfikuj konta", 123 "settings.account.account.editButton" : "Modyfikuj konta",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Pobierz", 138 "settings.account.invoiceDownload" : "Pobierz",
118 "settings.account.manageSubscription.label" : "ZarzÄ…dzaj swoimi subskrypcjami", 139 "settings.account.manageSubscription.label" : "ZarzÄ…dzaj swoimi subskrypcjami",
119 "settings.account.successInfo" : "Twoje zmiany zostały zapisane", 140 "settings.account.successInfo" : "Twoje zmiany zostały zapisane",
141 "settings.account.tryReloadServices" : "Spróbuj ponownie",
120 "settings.account.tryReloadUserInfoRequest" : "Spróbuj ponownie", 142 "settings.account.tryReloadUserInfoRequest" : "Spróbuj ponownie",
121 "settings.account.userInfoRequestFailed" : "Nie można wczytać informacji o użytkowniku", 143 "settings.account.userInfoRequestFailed" : "Nie można wczytać informacji o użytkowniku",
122 "settings.app.buttonClearAllCache" : "Wyczyść pamięć podręczną (cache)", 144 "settings.app.buttonClearAllCache" : "Wyczyść pamięć podręczną (cache)",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Uwzględnij wersje beta", 151 "settings.app.form.beta" : "Uwzględnij wersje beta",
130 "settings.app.form.darkMode" : "Przejdź na Ciemną Stronę", 152 "settings.app.form.darkMode" : "Przejdź na Ciemną Stronę",
131 "settings.app.form.enableGPUAcceleration" : "WÅ‚Ä…cz akceleracjÄ™ GPU", 153 "settings.app.form.enableGPUAcceleration" : "WÅ‚Ä…cz akceleracjÄ™ GPU",
132 "settings.app.form.enableMenuBar" : "Pokaż Franz na pasku menu",
133 "settings.app.form.enableSpellchecking" : "WÅ‚Ä…cz sprawdzanie pisowni", 154 "settings.app.form.enableSpellchecking" : "WÅ‚Ä…cz sprawdzanie pisowni",
134 "settings.app.form.enableSystemTray" : "Pokaż Franza w obszarze powiadomień", 155 "settings.app.form.enableSystemTray" : "Pokaż Franza w obszarze powiadomień",
135 "settings.app.form.hideDockIcon" : "Ukrywaj ikonÄ™ Franz w zasobniku systemowym",
136 "settings.app.form.language" : "Język", 156 "settings.app.form.language" : "Język",
137 "settings.app.form.minimizeToSystemTray" : "Zminimalizuj aplikacjÄ™ Franz", 157 "settings.app.form.minimizeToSystemTray" : "Zminimalizuj aplikacjÄ™ Franz",
138 "settings.app.form.runInBackground" : "Zachowaj aplikację Franz w tle po zamknięciu okna", 158 "settings.app.form.runInBackground" : "Zachowaj aplikację Franz w tle po zamknięciu okna",
139 "settings.app.form.showDisabledServices" : "Wyłącz wyświetlanie zakładek z usługami", 159 "settings.app.form.showDisabledServices" : "Wyłącz wyświetlanie zakładek z usługami",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Pokaż licznik nieprzeczytanych wiadomości gdy powiadomienia są wyłączone", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Pokaż licznik nieprzeczytanych wiadomości gdy powiadomienia są wyłączone",
141 "settings.app.form.spellcheckerLanguage" : "Język słownika",
142 "settings.app.headline" : "Ustawienia", 161 "settings.app.headline" : "Ustawienia",
143 "settings.app.headlineAdvanced" : "Zaawansowane", 162 "settings.app.headlineAdvanced" : "Zaawansowane",
144 "settings.app.headlineAppearance" : "WyglÄ…d", 163 "settings.app.headlineAppearance" : "WyglÄ…d",
145 "settings.app.headlineGeneral" : "Ogólne", 164 "settings.app.headlineGeneral" : "Ogólne",
146 "settings.app.headlineLanguage" : "Język", 165 "settings.app.headlineLanguage" : "Język",
147 "settings.app.headlineUpdates" : "Aktualizacje", 166 "settings.app.headlineUpdates" : "Aktualizacje",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Zmiany. wymagajÄ… ponownego uruchomienia", 168 "settings.app.restartRequired" : "Zmiany. wymagajÄ… ponownego uruchomienia",
149 "settings.app.subheadlineCache" : "Pamięć podręczna", 169 "settings.app.subheadlineCache" : "Pamięć podręczna",
150 "settings.app.translationHelp" : "Pomóż nam tłumaczyć Franz na Twój język.", 170 "settings.app.translationHelp" : "Pomóż nam tłumaczyć Franz na Twój język.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "ZaproÅ› znajomych", 177 "settings.navigation.inviteFriends" : "ZaproÅ› znajomych",
158 "settings.navigation.logout" : "Wyloguj", 178 "settings.navigation.logout" : "Wyloguj",
159 "settings.navigation.settings" : "Ustawienia", 179 "settings.navigation.settings" : "Ustawienia",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Twoje usługi", 181 "settings.navigation.yourServices" : "Twoje usługi",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Wszystkie usługi", 183 "settings.recipes.all" : "Wszystkie usługi",
162 "settings.recipes.dev" : "Rozwojowe", 184 "settings.recipes.dev" : "Rozwojowe",
163 "settings.recipes.headline" : "Dostępne usługi", 185 "settings.recipes.headline" : "Dostępne usługi",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Pokaż ikonę wiadomości dla wszystkich nowych wiadomości", 214 "settings.service.form.indirectMessages" : "Pokaż ikonę wiadomości dla wszystkich nowych wiadomości",
193 "settings.service.form.isMutedInfo" : "Kiedy nieaktywne, wszystkie dźwięki powiadomień są wyciszone", 215 "settings.service.form.isMutedInfo" : "Kiedy nieaktywne, wszystkie dźwięki powiadomień są wyciszone",
194 "settings.service.form.name" : "Nazwa", 216 "settings.service.form.name" : "Nazwa",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Ustawienia Proxy HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Host Proxy\/IP", 218 "settings.service.form.proxy.host" : "Host Proxy\/IP",
197 "settings.service.form.proxy.info" : "Ustawienia proxy nie będą zsynchronizowane z serwerami Franza.", 219 "settings.service.form.proxy.info" : "Ustawienia proxy nie będą zsynchronizowane z serwerami Franza.",
198 "settings.service.form.proxy.isEnabled" : "Użyj Proxy", 220 "settings.service.form.proxy.isEnabled" : "Użyj Proxy",
199 "settings.service.form.proxy.password" : "Hasło (opcjonalnie)", 221 "settings.service.form.proxy.password" : "Hasło (opcjonalnie)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Uruchom ponownie Franz po zmianie ustawień proxy.",
202 "settings.service.form.proxy.user" : "Użytkownik (opcjonalnie)", 224 "settings.service.form.proxy.user" : "Użytkownik (opcjonalnie)",
203 "settings.service.form.saveButton" : "Zapisz usługę", 225 "settings.service.form.saveButton" : "Zapisz usługę",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hostowane", 226 "settings.service.form.tabHosted" : "Hostowane",
207 "settings.service.form.tabOnPremise" : "Hostowane lokalnie â­ï¸", 227 "settings.service.form.tabOnPremise" : "Hostowane lokalnie â­ï¸",
208 "settings.service.form.team" : "Zespół", 228 "settings.service.form.team" : "Zespół",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Przeglądaj usługi", 232 "settings.services.discoverServices" : "Przeglądaj usługi",
213 "settings.services.headline" : "Twoje usługi", 233 "settings.services.headline" : "Twoje usługi",
214 "settings.services.noServicesAdded" : "Nie dodałeś jeszcze żadnych usług.", 234 "settings.services.noServicesAdded" : "Nie dodałeś jeszcze żadnych usług.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Usługa jest nieaktywna", 236 "settings.services.tooltip.isDisabled" : "Usługa jest nieaktywna",
216 "settings.services.tooltip.isMuted" : "Wszystkie dźwięki są wyciszone", 237 "settings.services.tooltip.isMuted" : "Wszystkie dźwięki są wyciszone",
217 "settings.services.tooltip.notificationsDisabled" : "Powiadomienia sÄ… nieaktywne", 238 "settings.services.tooltip.notificationsDisabled" : "Powiadomienia sÄ… nieaktywne",
218 "settings.services.updatedInfo" : "Zmiany zostały zapisane", 239 "settings.services.updatedInfo" : "Zmiany zostały zapisane",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Zespół",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Firma", 246 "settings.user.form.accountType.company" : "Firma",
220 "settings.user.form.accountType.individual" : "Prywatne", 247 "settings.user.form.accountType.individual" : "Prywatne",
221 "settings.user.form.accountType.label" : "Typ konta", 248 "settings.user.form.accountType.label" : "Typ konta",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "ImiÄ™", 252 "settings.user.form.firstname" : "ImiÄ™",
226 "settings.user.form.lastname" : "Nazwisko", 253 "settings.user.form.lastname" : "Nazwisko",
227 "settings.user.form.newPassword" : "Nowe hasło", 254 "settings.user.form.newPassword" : "Nowe hasło",
255 "settings.workspace.add.form.name" : "Name",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Spróbuj ponownie",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Dodaj kolejną usługę", 270 "sidebar.addNewService" : "Dodaj kolejną usługę",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Wyłącz powiadomienia i dźwięki", 272 "sidebar.muteApp" : "Wyłącz powiadomienia i dźwięki",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Ustawienia", 274 "sidebar.settings" : "Ustawienia",
231 "sidebar.unmuteApp" : "Włącz powiadomienia i dźwięki", 275 "sidebar.unmuteApp" : "Włącz powiadomienia i dźwięki",
232 "signup.company.label" : "Firma", 276 "signup.company.label" : "Firma",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Rezydenci UE: lokalne stawki VAT mogą zostać zaaplikowane", 288 "subscription.euTaxInfo" : "Rezydenci UE: lokalne stawki VAT mogą zostać zaaplikowane",
245 "subscription.features.ads" : "Brak reklam, na zawsze!", 289 "subscription.features.ads" : "Brak reklam, na zawsze!",
246 "subscription.features.comingSoon" : "wkrótce dostępne", 290 "subscription.features.comingSoon" : "wkrótce dostępne",
247 "subscription.features.encryptedSync" : "Szyfrowana synchronizacja sesji", 291 "subscription.features.noInterruptions" : "Bez opóźnień i przypominania o ulepszeniu licencji",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Dodaj prywatnie hostowane usługi takie jak Mattermost",
249 "subscription.features.onpremise" : "Dodawanie lokalnych\/hostowanych usług takich jak HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Obsługa proxy dla usług", 293 "subscription.features.proxy" : "Obsługa proxy dla usług",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Wsparcie dla sprawdzania pisowni",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "PÅ‚atne konto Franz Premium obejmuje", 296 "subscription.includedFeatures" : "PÅ‚atne konto Franz Premium obejmuje",
254 "subscription.paymentSessionError" : "Nie można wczytać formularza płatności\"", 297 "subscription.paymentSessionError" : "Nie można wczytać formularza płatności\"",
255 "subscription.submit.label" : "Chcę wspierać rozwój aplikacji Franz", 298 "subscription.submit.label" : "Chcę wspierać rozwój aplikacji Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Przeładuj", 312 "tabs.item.reload" : "Przeładuj",
270 "validation.email" : "Pole {field} nie jest poprawne", 313 "validation.email" : "Pole {field} nie jest poprawne",
271 "validation.minLength" : "Pole {field} powinno składać się z co najmniej {length} znaków", 314 "validation.minLength" : "Pole {field} powinno składać się z co najmniej {length} znaków",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "Pole {field} jest wymagane", 316 "validation.required" : "Pole {field} jest wymagane",
273 "validation.url" : "Pole {field} nie jest poprawnym ciÄ…giem URL.", 317 "validation.url" : "Pole {field} nie jest poprawnym ciÄ…giem URL.",
274 "welcome.loginButton" : "Zaloguj siÄ™ na swoje konto", 318 "welcome.loginButton" : "Zaloguj siÄ™ na swoje konto",
275 "welcome.signupButton" : "Stwórz darmowe konto", 319 "welcome.signupButton" : "Stwórz darmowe konto",
276 "welcome.slogan" : "Komunikator który działa" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Wszystkie usługi",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/pt-BR.json b/src/i18n/locales/pt-BR.json
index c0cf0039f..4ad2fac08 100644
--- a/src/i18n/locales/pt-BR.json
+++ b/src/i18n/locales/pt-BR.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Recarregar", 2 "app.errorHandler.action" : "Recarregar",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Alguma coisa deu errado",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Adquira uma licença Franz Supporter", 5 "feature.delayApp.action" : "Adquira uma licença Franz Supporter",
5 "feature.delayApp.headline" : "Por favor, adquira uma licença Franz Supporter para pular o tempo de espera", 6 "feature.delayApp.headline" : "Por favor, adquira uma licença Franz Supporter para pular o tempo de espera",
6 "feature.delayApp.text" : "Franz continuará em {seconds} segundos.", 7 "feature.delayApp.text" : "Franz continuará em {seconds} segundos.",
8 "feature.shareFranz.action.email" : "Enviar como e-mail",
9 "feature.shareFranz.action.facebook" : "Compartilhar no Facebook",
10 "feature.shareFranz.action.twitter" : "Compartilhar no Twitter",
11 "feature.shareFranz.headline" : "Franz é melhor em grupo!",
12 "feature.shareFranz.shareText.email" : "Eu adicionei {count} serviços ao Franz! Adquira o aplicativo gratuito para WhatsApp, Messenger, Slack, Skype e mais em www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Conte aos seus amigos e colegas o quão incrível Franz é e nos ajude a espalhar a mensagem. ",
7 "global.api.unhealthy" : "Não foi possível conectar-se aos serviços on-line do Franz.", 15 "global.api.unhealthy" : "Não foi possível conectar-se aos serviços on-line do Franz.",
8 "global.notConnectedToTheInternet" : "Você não está conectado à internet", 16 "global.notConnectedToTheInternet" : "Você não está conectado à internet",
17 "global.spellchecker.useDefault" : "Use o padrão do sistema ({default})",
18 "global.spellchecking.autodetect" : "Detectar linguagem automaticamente.",
19 "global.spellchecking.autodetect.short" : "Automático",
20 "global.spellchecking.language" : "Idioma de verificação ortográfica",
9 "import.headline" : "Importe seus serviços do Franz 4 ", 21 "import.headline" : "Importe seus serviços do Franz 4 ",
10 "import.notSupportedHeadline" : "Serviços ainda não suportados pelo Franz 5 ", 22 "import.notSupportedHeadline" : "Serviços ainda não suportados pelo Franz 5 ",
11 "import.skip.label" : "Quero adicionar serviços manualmente", 23 "import.skip.label" : "Quero adicionar serviços manualmente",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Entrar", 44 "login.submit.label" : "Entrar",
33 "login.tokenExpired" : "Sua sessão expirou, faça o login novamente.", 45 "login.tokenExpired" : "Sua sessão expirou, faça o login novamente.",
34 "menu.app.about" : "Sobre Franz", 46 "menu.app.about" : "Sobre Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Ocultar", 48 "menu.app.hide" : "Ocultar",
36 "menu.app.hideOthers" : "Ocultar Outros", 49 "menu.app.hideOthers" : "Ocultar Outros",
37 "menu.app.quit" : "Sair", 50 "menu.app.quit" : "Sair",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Suporte", 72 "menu.help.support" : "Suporte",
60 "menu.help.tos" : "Termos de Serviço", 73 "menu.help.tos" : "Termos de Serviço",
61 "menu.services" : "Serviços", 74 "menu.services" : "Serviços",
75 "menu.services.activatePreviousService" : "Pular para serviço anterior",
62 "menu.services.addNewService" : "Adicionar Novo Serviço", 76 "menu.services.addNewService" : "Adicionar Novo Serviço",
77 "menu.services.setNextServiceActive" : "Pular para próximo serviço",
63 "menu.view" : "Visualizar ", 78 "menu.view" : "Visualizar ",
64 "menu.view.enterFullScreen" : "Modo Tela Cheia", 79 "menu.view.enterFullScreen" : "Modo Tela Cheia",
65 "menu.view.exitFullScreen" : "Sair da Tela Cheia", 80 "menu.view.exitFullScreen" : "Sair da Tela Cheia",
@@ -74,6 +89,11 @@
74 "menu.window" : "Modo Janela", 89 "menu.window" : "Modo Janela",
75 "menu.window.close" : "Fechar", 90 "menu.window.close" : "Fechar",
76 "menu.window.minimize" : "Minimizar", 91 "menu.window.minimize" : "Minimizar",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Todos os serviços",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-mail", 97 "password.email.label" : "E-mail",
78 "password.headline" : "Trocar senha", 98 "password.headline" : "Trocar senha",
79 "password.link.login" : "Fazer login na sua conta", 99 "password.link.login" : "Fazer login na sua conta",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Editar {name}", 116 "service.errorHandler.editAction" : "Editar {name}",
97 "service.errorHandler.headline" : "Ah, não!", 117 "service.errorHandler.headline" : "Ah, não!",
98 "service.errorHandler.message" : "Erro", 118 "service.errorHandler.message" : "Erro",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} não pôde ser carregado.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Iniciar", 121 "services.getStarted" : "Iniciar",
101 "services.welcome" : "Bem-vindo ao Franz!", 122 "services.welcome" : "Bem-vindo ao Franz!",
102 "settings.account.account.editButton" : "Editar conta", 123 "settings.account.account.editButton" : "Editar conta",
@@ -117,7 +138,8 @@
117 "settings.account.invoiceDownload" : "Baixar", 138 "settings.account.invoiceDownload" : "Baixar",
118 "settings.account.manageSubscription.label" : "Gerencie a sua assinatura", 139 "settings.account.manageSubscription.label" : "Gerencie a sua assinatura",
119 "settings.account.successInfo" : "Suas alterações foram gravadas", 140 "settings.account.successInfo" : "Suas alterações foram gravadas",
120 "settings.account.tryReloadUserInfoRequest" : "Tente novamente", 141 "settings.account.tryReloadServices" : "Tente novamente",
142 "settings.account.tryReloadUserInfoRequest" : "Tentar novamente",
121 "settings.account.userInfoRequestFailed" : "Não foi possível carregar as informações do usuário", 143 "settings.account.userInfoRequestFailed" : "Não foi possível carregar as informações do usuário",
122 "settings.app.buttonClearAllCache" : "Limpar cache", 144 "settings.app.buttonClearAllCache" : "Limpar cache",
123 "settings.app.buttonInstallUpdate" : "Reiniciar e instalar atualização", 145 "settings.app.buttonInstallUpdate" : "Reiniciar e instalar atualização",
@@ -129,24 +151,22 @@
129 "settings.app.form.beta" : "Incluir versões beta", 151 "settings.app.form.beta" : "Incluir versões beta",
130 "settings.app.form.darkMode" : "Venha para o Lado Negro da força", 152 "settings.app.form.darkMode" : "Venha para o Lado Negro da força",
131 "settings.app.form.enableGPUAcceleration" : "Ativar Aceleração de GPU", 153 "settings.app.form.enableGPUAcceleration" : "Ativar Aceleração de GPU",
132 "settings.app.form.enableMenuBar" : "Mostrar Franz na Barra de Menu",
133 "settings.app.form.enableSpellchecking" : "Ativar correção ortográfica", 154 "settings.app.form.enableSpellchecking" : "Ativar correção ortográfica",
134 "settings.app.form.enableSystemTray" : "Exibir o Franz na barra de sistema", 155 "settings.app.form.enableSystemTray" : "Exibir o Franz na barra de sistema",
135 "settings.app.form.hideDockIcon" : "Ocultar ícone do Franz no Dock",
136 "settings.app.form.language" : "Idioma", 156 "settings.app.form.language" : "Idioma",
137 "settings.app.form.minimizeToSystemTray" : "Minimizar o Franz para a área de sistema", 157 "settings.app.form.minimizeToSystemTray" : "Minimizar o Franz para a área de sistema",
138 "settings.app.form.runInBackground" : "Manter o Franz no fundo quando fechar a janela", 158 "settings.app.form.runInBackground" : "Manter o Franz no fundo quando fechar a janela",
139 "settings.app.form.showDisabledServices" : "Mostrar abas de serviços desativados", 159 "settings.app.form.showDisabledServices" : "Mostrar abas de serviços desativados",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostrar ícone de mensagem não lida quando as notificações estiverem desativadas", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Mostrar ícone de mensagem não lida quando as notificações estiverem desativadas",
141 "settings.app.form.spellcheckerLanguage" : "Idioma de verificação ortográfica",
142 "settings.app.headline" : "Configurações", 161 "settings.app.headline" : "Configurações",
143 "settings.app.headlineAdvanced" : "Avançado", 162 "settings.app.headlineAdvanced" : "Avançado",
144 "settings.app.headlineAppearance" : "Aparência", 163 "settings.app.headlineAppearance" : "Aparência",
145 "settings.app.headlineGeneral" : "Geral", 164 "settings.app.headlineGeneral" : "Geral",
146 "settings.app.headlineLanguage" : "Idioma", 165 "settings.app.headlineLanguage" : "Idioma",
147 "settings.app.headlineUpdates" : "Atualizações", 166 "settings.app.headlineUpdates" : "Atualizações",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "As atualizações exigem reiniciar o sistema", 168 "settings.app.restartRequired" : "As atualizações exigem reiniciar o sistema",
149 "settings.app.subheadlineCache" : "Cachê", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Ajude-nos a traduzir o Franz para seu idioma.", 170 "settings.app.translationHelp" : "Ajude-nos a traduzir o Franz para seu idioma.",
151 "settings.app.updateStatusAvailable" : "Atualização disponível, baixando...", 171 "settings.app.updateStatusAvailable" : "Atualização disponível, baixando...",
152 "settings.app.updateStatusSearching" : "Buscando atualizações", 172 "settings.app.updateStatusSearching" : "Buscando atualizações",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Convidar Amigos", 177 "settings.navigation.inviteFriends" : "Convidar Amigos",
158 "settings.navigation.logout" : "Sair", 178 "settings.navigation.logout" : "Sair",
159 "settings.navigation.settings" : "Ajustes", 179 "settings.navigation.settings" : "Ajustes",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Seus serviços", 181 "settings.navigation.yourServices" : "Seus serviços",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Todos os serviços", 183 "settings.recipes.all" : "Todos os serviços",
162 "settings.recipes.dev" : "Desenvolvimento", 184 "settings.recipes.dev" : "Desenvolvimento",
163 "settings.recipes.headline" : "Serviços disponíveis", 185 "settings.recipes.headline" : "Serviços disponíveis",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Mostrar avisos para todas as mensagens", 214 "settings.service.form.indirectMessages" : "Mostrar avisos para todas as mensagens",
193 "settings.service.form.isMutedInfo" : "Quando desativado, as notificações sonoras e áudios ficarão em silêncio", 215 "settings.service.form.isMutedInfo" : "Quando desativado, as notificações sonoras e áudios ficarão em silêncio",
194 "settings.service.form.name" : "Nome", 216 "settings.service.form.name" : "Nome",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Configurações de HTTP\/HTTPS Proxy",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Host\/IP",
197 "settings.service.form.proxy.info" : "As configurações de proxy não serão sincronizadas com os servidores do Franz.", 219 "settings.service.form.proxy.info" : "As configurações de proxy não serão sincronizadas com os servidores do Franz.",
198 "settings.service.form.proxy.isEnabled" : "Usar o Proxy", 220 "settings.service.form.proxy.isEnabled" : "Usar o Proxy",
199 "settings.service.form.proxy.password" : "Senha (opcional)", 221 "settings.service.form.proxy.password" : "Senha (opcional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Porta",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Por favor, reinicie o Franz após alterar as configurações de proxy.",
202 "settings.service.form.proxy.user" : "Usuário (opcional)", 224 "settings.service.form.proxy.user" : "Usuário (opcional)",
203 "settings.service.form.saveButton" : "Salvar serviço", 225 "settings.service.form.saveButton" : "Salvar serviço",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hospedado", 226 "settings.service.form.tabHosted" : "Hospedado",
207 "settings.service.form.tabOnPremise" : "Auto-hospedado â­ï¸", 227 "settings.service.form.tabOnPremise" : "Auto-hospedado â­ï¸",
208 "settings.service.form.team" : "Equipe", 228 "settings.service.form.team" : "Equipe",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Descobrir serviços", 232 "settings.services.discoverServices" : "Descobrir serviços",
213 "settings.services.headline" : "Seus serviços", 233 "settings.services.headline" : "Seus serviços",
214 "settings.services.noServicesAdded" : "Você ainda não adicionou nenhum serviço.", 234 "settings.services.noServicesAdded" : "Você ainda não adicionou nenhum serviço.",
235 "settings.services.servicesRequestFailed" : "Não foi possível carregar os seus serviços",
215 "settings.services.tooltip.isDisabled" : "O serviço está desativado", 236 "settings.services.tooltip.isDisabled" : "O serviço está desativado",
216 "settings.services.tooltip.isMuted" : "Sem som", 237 "settings.services.tooltip.isMuted" : "Sem som",
217 "settings.services.tooltip.notificationsDisabled" : "Notificações desativadas", 238 "settings.services.tooltip.notificationsDisabled" : "Notificações desativadas",
218 "settings.services.updatedInfo" : "Suas mudanças foram gravadas", 239 "settings.services.updatedInfo" : "Suas mudanças foram gravadas",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Equipe",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Empresa", 246 "settings.user.form.accountType.company" : "Empresa",
220 "settings.user.form.accountType.individual" : "Pessoal", 247 "settings.user.form.accountType.individual" : "Pessoal",
221 "settings.user.form.accountType.label" : "Tipo de conta", 248 "settings.user.form.accountType.label" : "Tipo de conta",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Nome", 252 "settings.user.form.firstname" : "Nome",
226 "settings.user.form.lastname" : "Sobrenome", 253 "settings.user.form.lastname" : "Sobrenome",
227 "settings.user.form.newPassword" : "Nova senha", 254 "settings.user.form.newPassword" : "Nova senha",
255 "settings.workspace.add.form.name" : "Nome",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Nome",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Try again",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Adicionar novo serviço", 270 "sidebar.addNewService" : "Adicionar novo serviço",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Desativar notificações e áudio", 272 "sidebar.muteApp" : "Desativar notificações e áudio",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Ajustes", 274 "sidebar.settings" : "Ajustes",
231 "sidebar.unmuteApp" : "Ativar notificações e áudio", 275 "sidebar.unmuteApp" : "Ativar notificações e áudio",
232 "signup.company.label" : "Empresa", 276 "signup.company.label" : "Empresa",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Residentes na União Europeia: taxas locais serão aplicadas", 288 "subscription.euTaxInfo" : "Residentes na União Europeia: taxas locais serão aplicadas",
245 "subscription.features.ads" : "Sem anúncios, pra sempre!", 289 "subscription.features.ads" : "Sem anúncios, pra sempre!",
246 "subscription.features.comingSoon" : "em breve", 290 "subscription.features.comingSoon" : "em breve",
247 "subscription.features.encryptedSync" : "Sincronização encriptada das sessões", 291 "subscription.features.noInterruptions" : "Sem demora e sem chateação para comprar uma licença. ",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Adicionar serviços locais\/hospedados como o Mattermost",
249 "subscription.features.onpremise" : "Adicionar serviços locais\/hospedados como o HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Suporte de proxy para serviços", 293 "subscription.features.proxy" : "Suporte de proxy para serviços",
252 "subscription.features.spellchecker" : "Suporte para corretor ortográfico", 294 "subscription.features.spellchecker" : "Suporte para corretor ortográfico",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "A conta Apoiador Franz Premium inclui", 296 "subscription.includedFeatures" : "A conta Apoiador Franz Premium inclui",
254 "subscription.paymentSessionError" : "Não foi possível abrir o formulário de pagamento", 297 "subscription.paymentSessionError" : "Não foi possível abrir o formulário de pagamento",
255 "subscription.submit.label" : "Eu quero apoiar o desenvolvimento do Franz", 298 "subscription.submit.label" : "Eu quero apoiar o desenvolvimento do Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Recarregar", 312 "tabs.item.reload" : "Recarregar",
270 "validation.email" : "inválido", 313 "validation.email" : "inválido",
271 "validation.minLength" : "{campo} deve ter pelo menos {comprimento} mais caracteres ", 314 "validation.minLength" : "{campo} deve ter pelo menos {comprimento} mais caracteres ",
315 "validation.oneRequired" : "Necessário pelo menos um",
272 "validation.required" : "{campo} obrigatório", 316 "validation.required" : "{campo} obrigatório",
273 "validation.url" : "{campo} essa URL não é válida", 317 "validation.url" : "{campo} essa URL não é válida",
274 "welcome.loginButton" : "Entrar na sua conta", 318 "welcome.loginButton" : "Entrar na sua conta",
275 "welcome.signupButton" : "Criar uma conta grátis", 319 "welcome.signupButton" : "Criar uma conta grátis",
276 "welcome.slogan" : "Mensagens que funcionam para você" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Todos os serviços",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/pt.json b/src/i18n/locales/pt.json
index 80e8094f5..302284ab8 100644
--- a/src/i18n/locales/pt.json
+++ b/src/i18n/locales/pt.json
@@ -1,14 +1,26 @@
1{ 1{
2 "app.errorHandler.action" : "Recarregar", 2 "app.errorHandler.action" : "Recarregar",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Alguma coisa correu mal",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Faz parte do grupo de apoio do Franz",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "Por favor compre uma licença Franz Supporter para saltar a fila de espera",
7 "feature.delayApp.text" : "Franz irá continuar em {seconds} segundos.",
8 "feature.shareFranz.action.email" : "Enviar por e-mail",
9 "feature.shareFranz.action.facebook" : "Compartilahr no Facebook",
10 "feature.shareFranz.action.twitter" : "Compartilhar no Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Não foi possível estabelecer ligação aos serviços do Franz", 15 "global.api.unhealthy" : "Não foi possível estabelecer ligação aos serviços do Franz",
8 "global.notConnectedToTheInternet" : "Não existe ligação à Internet", 16 "global.notConnectedToTheInternet" : "Não estás ligado à Internet",
9 "import.headline" : "Importe os seus serviços do Franz 4", 17 "global.spellchecker.useDefault" : "Utilizar o Sistema por Omissão ({default})",
10 "import.notSupportedHeadline" : "Serviços ainda não suportados pelo Franz 5", 18 "global.spellchecking.autodetect" : "Detect language automatically",
11 "import.skip.label" : "Pretendo adicionar serviços manualmente", 19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Linguagem para correção ortográfica",
21 "import.headline" : "Importa os teus serviços do Franz",
22 "import.notSupportedHeadline" : "Estes serviços ainda não são suportados pelo Franz 5",
23 "import.skip.label" : "Eu quero adicionar serviços manualmente",
12 "import.submit.label" : "Importar serviços", 24 "import.submit.label" : "Importar serviços",
13 "infobar.buttonChangelog" : "O que há de novo?", 25 "infobar.buttonChangelog" : "O que há de novo?",
14 "infobar.buttonInstallUpdate" : "Reiniciar e instalar atualizações", 26 "infobar.buttonInstallUpdate" : "Reiniciar e instalar atualizações",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Iniciar sessão", 44 "login.submit.label" : "Iniciar sessão",
33 "login.tokenExpired" : "A sua sessão expirou, inicie sessão novamente.", 45 "login.tokenExpired" : "A sua sessão expirou, inicie sessão novamente.",
34 "menu.app.about" : "Sobre o Franz", 46 "menu.app.about" : "Sobre o Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Ocultar", 48 "menu.app.hide" : "Ocultar",
36 "menu.app.hideOthers" : "Ocultar Outros", 49 "menu.app.hideOthers" : "Ocultar Outros",
37 "menu.app.quit" : "Sair", 50 "menu.app.quit" : "Sair",
@@ -59,14 +72,16 @@
59 "menu.help.support" : "Suporte", 72 "menu.help.support" : "Suporte",
60 "menu.help.tos" : "Termos do Serviço", 73 "menu.help.tos" : "Termos do Serviço",
61 "menu.services" : "Serviços", 74 "menu.services" : "Serviços",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Adicionar Novo Serviço...", 76 "menu.services.addNewService" : "Adicionar Novo Serviço...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Ver", 78 "menu.view" : "Ver",
64 "menu.view.enterFullScreen" : "Ativar Modo de Ecrã Completo", 79 "menu.view.enterFullScreen" : "Ativar Modo de Ecrã Completo",
65 "menu.view.exitFullScreen" : "Sair do Modo de Ecrã Completo", 80 "menu.view.exitFullScreen" : "Sair do Modo de Ecrã Completo",
66 "menu.view.reloadFranz" : "Recarregar Franz", 81 "menu.view.reloadFranz" : "Recarregar Franz",
67 "menu.view.reloadService" : "Recarregar serviço", 82 "menu.view.reloadService" : "Recarregar serviço",
68 "menu.view.resetZoom" : "Tamanho Real", 83 "menu.view.resetZoom" : "Tamanho Real",
69 "menu.view.toggleDevTools" : "Activar\/Desativar Ferramentas de Desenvolvimento", 84 "menu.view.toggleDevTools" : "Ativar\/Desativar Ferramentas de Desenvolvimento",
70 "menu.view.toggleFullScreen" : "Ativar\/Desativar Ecrã Completo", 85 "menu.view.toggleFullScreen" : "Ativar\/Desativar Ecrã Completo",
71 "menu.view.toggleServiceDevTools" : "Ativar\/Desativar Ferramentas de Desenvolvimento de Serviços", 86 "menu.view.toggleServiceDevTools" : "Ativar\/Desativar Ferramentas de Desenvolvimento de Serviços",
72 "menu.view.zoomIn" : "Aumentar", 87 "menu.view.zoomIn" : "Aumentar",
@@ -74,6 +89,11 @@
74 "menu.window" : "Janela", 89 "menu.window" : "Janela",
75 "menu.window.close" : "Fechar", 90 "menu.window.close" : "Fechar",
76 "menu.window.minimize" : "Minimizar", 91 "menu.window.minimize" : "Minimizar",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Todos os serviços",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Endereço de e-mail", 97 "password.email.label" : "Endereço de e-mail",
78 "password.headline" : "Repor a minha palavra-passe", 98 "password.headline" : "Repor a minha palavra-passe",
79 "password.link.login" : "Iniciar sessão", 99 "password.link.login" : "Iniciar sessão",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Não existe nenhuma conta associada a esse endereço de e-mail", 101 "password.noUser" : "Não existe nenhuma conta associada a esse endereço de e-mail",
82 "password.submit.label" : "Submeter", 102 "password.submit.label" : "Submeter",
83 "password.successInfo" : "Por favor verifique o seu endereço de e-mail", 103 "password.successInfo" : "Por favor verifique o seu endereço de e-mail",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Atualiza a tua conta",
85 "pricing.headline" : "Apoie o Franz", 105 "pricing.headline" : "Apoie o Franz",
86 "pricing.link.skipPayment" : "Não pretendo patrocinar o desenvolvimento do Franz", 106 "pricing.link.skipPayment" : "Não pretendo patrocinar o desenvolvimento do Franz",
87 "pricing.submit.label" : "Pretendo patrocinar o desenvolvimento do Franz", 107 "pricing.submit.label" : "Pretendo patrocinar o desenvolvimento do Franz",
@@ -96,11 +116,12 @@
96 "service.errorHandler.editAction" : "Editar {name}", 116 "service.errorHandler.editAction" : "Editar {name}",
97 "service.errorHandler.headline" : "Oh não!", 117 "service.errorHandler.headline" : "Oh não!",
98 "service.errorHandler.message" : "Erro", 118 "service.errorHandler.message" : "Erro",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} falhou o carregamento",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Vamos começar", 121 "services.getStarted" : "Vamos começar",
101 "services.welcome" : "Bem-vindo ao Franz", 122 "services.welcome" : "Bem-vindo ao Franz",
102 "settings.account.account.editButton" : "Editar conta", 123 "settings.account.account.editButton" : "Editar conta",
103 "settings.account.accountType.basic" : "Conta básica", 124 "settings.account.accountType.basic" : "Conta Básica",
104 "settings.account.accountType.premium" : "Conta Premium", 125 "settings.account.accountType.premium" : "Conta Premium",
105 "settings.account.buttonSave" : "Atualizar o perfil", 126 "settings.account.buttonSave" : "Atualizar o perfil",
106 "settings.account.deleteAccount" : "Apagar conta", 127 "settings.account.deleteAccount" : "Apagar conta",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Transferir", 138 "settings.account.invoiceDownload" : "Transferir",
118 "settings.account.manageSubscription.label" : "Gerir as minhas subscrições", 139 "settings.account.manageSubscription.label" : "Gerir as minhas subscrições",
119 "settings.account.successInfo" : "As suas alterações foram efetuadas com sucesso", 140 "settings.account.successInfo" : "As suas alterações foram efetuadas com sucesso",
141 "settings.account.tryReloadServices" : "Tentar novamente",
120 "settings.account.tryReloadUserInfoRequest" : "Tentar novamente", 142 "settings.account.tryReloadUserInfoRequest" : "Tentar novamente",
121 "settings.account.userInfoRequestFailed" : "Não é possível carregar a informação do utilizador", 143 "settings.account.userInfoRequestFailed" : "Não é possível carregar a informação do utilizador",
122 "settings.app.buttonClearAllCache" : "Limpar cache", 144 "settings.app.buttonClearAllCache" : "Limpar cache",
@@ -127,45 +149,45 @@
127 "settings.app.form.autoLaunchInBackground" : "Abrir em segundo plano", 149 "settings.app.form.autoLaunchInBackground" : "Abrir em segundo plano",
128 "settings.app.form.autoLaunchOnStart" : "Iniciar o Franz após iniciar o computador", 150 "settings.app.form.autoLaunchOnStart" : "Iniciar o Franz após iniciar o computador",
129 "settings.app.form.beta" : "Incluir versões instáveis (beta)", 151 "settings.app.form.beta" : "Incluir versões instáveis (beta)",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Junta-te ao Lado Negro",
131 "settings.app.form.enableGPUAcceleration" : "Activar Aceleração de GPU", 153 "settings.app.form.enableGPUAcceleration" : "Activar Aceleração de GPU",
132 "settings.app.form.enableMenuBar" : "Mostrar Franz na Barra de Menu",
133 "settings.app.form.enableSpellchecking" : "Ativar verificação ortográfica", 154 "settings.app.form.enableSpellchecking" : "Ativar verificação ortográfica",
134 "settings.app.form.enableSystemTray" : "Mostrar o Franz na barra do sistema", 155 "settings.app.form.enableSystemTray" : "Mostrar o Franz na barra do sistema",
135 "settings.app.form.hideDockIcon" : "Esconder ícone na Dock",
136 "settings.app.form.language" : "Idioma", 156 "settings.app.form.language" : "Idioma",
137 "settings.app.form.minimizeToSystemTray" : "Minimizar o Franz para a barra do sistema", 157 "settings.app.form.minimizeToSystemTray" : "Minimizar o Franz para a barra do sistema",
138 "settings.app.form.runInBackground" : "Manter o Franz em segundo plano ao fechar a janela", 158 "settings.app.form.runInBackground" : "Manter o Franz em segundo plano ao fechar a janela",
139 "settings.app.form.showDisabledServices" : "Apresentar separadores de serviços desativados", 159 "settings.app.form.showDisabledServices" : "Apresentar separadores de serviços desativados",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Apresentar emblema com o número de mensagens não lidas quando as notificações estão desativadas", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Apresentar emblema com o número de mensagens não lidas quando as notificações estão desativadas",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Definições", 161 "settings.app.headline" : "Definições",
143 "settings.app.headlineAdvanced" : "Avançado", 162 "settings.app.headlineAdvanced" : "Avançado",
144 "settings.app.headlineAppearance" : "Aparência", 163 "settings.app.headlineAppearance" : "Aparência",
145 "settings.app.headlineGeneral" : "Geral", 164 "settings.app.headlineGeneral" : "Geral",
146 "settings.app.headlineLanguage" : "Idioma", 165 "settings.app.headlineLanguage" : "Idioma",
147 "settings.app.headlineUpdates" : "Atualizações", 166 "settings.app.headlineUpdates" : "Atualizações",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Alterações requerem reinício", 168 "settings.app.restartRequired" : "Alterações requerem reinício",
149 "settings.app.subheadlineCache" : "Cache", 169 "settings.app.subheadlineCache" : "Cache",
150 "settings.app.translationHelp" : "Ajude-nos a traduzir a Franz para a sua língua.", 170 "settings.app.translationHelp" : "Ajude-nos a traduzir a Franz para a sua língua.",
151 "settings.app.updateStatusAvailable" : "Atualização disponivel, a transferir...", 171 "settings.app.updateStatusAvailable" : "Atualização disponivel, a transferir...",
152 "settings.app.updateStatusSearching" : "A procurar atualizações", 172 "settings.app.updateStatusSearching" : "A procurar atualizações",
153 "settings.app.updateStatusUpToDate" : "Está a usar a versão mais recente do Franz", 173 "settings.app.updateStatusUpToDate" : "Está a usar a versão mais recente do Franz",
154 "settings.invite.headline" : "Convide amigos", 174 "settings.invite.headline" : "Convide Amigos",
155 "settings.navigation.account" : "Conta", 175 "settings.navigation.account" : "Conta",
156 "settings.navigation.availableServices" : "Serviços disponíveis", 176 "settings.navigation.availableServices" : "Serviços disponíveis",
157 "settings.navigation.inviteFriends" : "Convide amigos", 177 "settings.navigation.inviteFriends" : "Convide Amigos",
158 "settings.navigation.logout" : "Terminar sessão", 178 "settings.navigation.logout" : "Terminar sessão",
159 "settings.navigation.settings" : "Definições", 179 "settings.navigation.settings" : "Definições",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Os seus serviços", 181 "settings.navigation.yourServices" : "Os seus serviços",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Todos os serviços", 183 "settings.recipes.all" : "Todos os serviços",
162 "settings.recipes.dev" : "Desenvolvimento", 184 "settings.recipes.dev" : "Desenvolvimento",
163 "settings.recipes.headline" : "Serviços disponíveis", 185 "settings.recipes.headline" : "Serviços disponíveis",
164 "settings.recipes.missingService" : "Falta um serviço?", 186 "settings.recipes.missingService" : "Falta um serviço?",
165 "settings.recipes.mostPopular" : "Os mais populares", 187 "settings.recipes.mostPopular" : "Os mais populares",
166 "settings.recipes.nothingFound" : "Lamentamos, nenhum serviço corresponde ao pesquisado.", 188 "settings.recipes.nothingFound" : "Lamentamos, nenhum serviço corresponde ao termo pesquisado.",
167 "settings.recipes.servicesSuccessfulAddedInfo" : "Serviço adicionado", 189 "settings.recipes.servicesSuccessfulAddedInfo" : "Serviço adicionado com sucesso",
168 "settings.searchService" : "Pesquisa de serviço", 190 "settings.searchService" : "Pesquisar erviço",
169 "settings.service.error.goBack" : "Voltar aos serviços", 191 "settings.service.error.goBack" : "Voltar aos serviços",
170 "settings.service.error.headline" : "Erro", 192 "settings.service.error.headline" : "Erro",
171 "settings.service.error.message" : "Não foi possível carregar a receita do serviço.", 193 "settings.service.error.message" : "Não foi possível carregar a receita do serviço.",
@@ -179,30 +201,28 @@
179 "settings.service.form.editServiceHeadline" : "Editar {name}", 201 "settings.service.form.editServiceHeadline" : "Editar {name}",
180 "settings.service.form.enableAudio" : "Ativar áudio", 202 "settings.service.form.enableAudio" : "Ativar áudio",
181 "settings.service.form.enableBadge" : "Mostrar emblemas de mensagens não lidas", 203 "settings.service.form.enableBadge" : "Mostrar emblemas de mensagens não lidas",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Ativar o Tema Escuro",
183 "settings.service.form.enableNotification" : "Ativar notificações", 205 "settings.service.form.enableNotification" : "Ativar notificações",
184 "settings.service.form.enableService" : "Ativar serviço", 206 "settings.service.form.enableService" : "Ativar serviço",
185 "settings.service.form.headlineBadges" : "Emblema de mensagem não lida", 207 "settings.service.form.headlineBadges" : "Emblema de mensagem não lida",
186 "settings.service.form.headlineGeneral" : "Geral", 208 "settings.service.form.headlineGeneral" : "Geral",
187 "settings.service.form.headlineNotifications" : "Notificações", 209 "settings.service.form.headlineNotifications" : "Notificações",
188 "settings.service.form.icon" : "Personalizar ícone", 210 "settings.service.form.icon" : "Ãcone personalizado",
189 "settings.service.form.iconDelete" : "Apagar", 211 "settings.service.form.iconDelete" : "Apagar",
190 "settings.service.form.iconUpload" : "Arraste a sua imagem, ou clique aqui", 212 "settings.service.form.iconUpload" : "Arraste a sua imagem, ou clique aqui",
191 "settings.service.form.indirectMessageInfo" : "Será notificado sobre todas as novas mensagens num canal, não apenas @username, @channel, @here, ...", 213 "settings.service.form.indirectMessageInfo" : "Será notificado sobre todas as novas mensagens num canal, não apenas @username, @channel, @here, ...",
192 "settings.service.form.indirectMessages" : "Mostrar o emblema da mensagem para todas as novas mensagens", 214 "settings.service.form.indirectMessages" : "Mostrar o emblema da mensagem para todas as novas mensagens",
193 "settings.service.form.isMutedInfo" : "Quando desativado, todos sons e reproduções de áudio serão silenciados", 215 "settings.service.form.isMutedInfo" : "Quando desativado, todos sons e reproduções de áudio serão silenciados",
194 "settings.service.form.name" : "Nome", 216 "settings.service.form.name" : "Nome",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "Definições HTTP\/HTTPS Proxy",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Host\/IP proxy",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "As definições do proxy não serão guardadas nos servidores do Franz.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Usar Proxy",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Palavra-chave (opcional)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Porta",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Reinicie, por favor, após atualizar as definições do Franz",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Utilizador (opcional)",
203 "settings.service.form.saveButton" : "Guardar serviço", 225 "settings.service.form.saveButton" : "Guardar serviço",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Com domínio", 226 "settings.service.form.tabHosted" : "Com domínio",
207 "settings.service.form.tabOnPremise" : "Com domínio próprio â­ï¸", 227 "settings.service.form.tabOnPremise" : "Com domínio próprio â­ï¸",
208 "settings.service.form.team" : "Equipa", 228 "settings.service.form.team" : "Equipa",
@@ -211,11 +231,18 @@
211 "settings.services.deletedInfo" : "O serviço foi apagado", 231 "settings.services.deletedInfo" : "O serviço foi apagado",
212 "settings.services.discoverServices" : "Descobrir serviços", 232 "settings.services.discoverServices" : "Descobrir serviços",
213 "settings.services.headline" : "Os seus serviços", 233 "settings.services.headline" : "Os seus serviços",
214 "settings.services.noServicesAdded" : "Ainda não adicionou um serviço.", 234 "settings.services.noServicesAdded" : "Ainda não adicionou nenhum serviço.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "O serviço está desativado", 236 "settings.services.tooltip.isDisabled" : "O serviço está desativado",
216 "settings.services.tooltip.isMuted" : "Todos os sons estão silenciados", 237 "settings.services.tooltip.isMuted" : "Todos os sons estão silenciados",
217 "settings.services.tooltip.notificationsDisabled" : "As notificações estão desativadas", 238 "settings.services.tooltip.notificationsDisabled" : "As notificações estão desativadas",
218 "settings.services.updatedInfo" : "As alterações foram guardadas", 239 "settings.services.updatedInfo" : "As alterações foram guardadas",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Equipa",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Empresa", 246 "settings.user.form.accountType.company" : "Empresa",
220 "settings.user.form.accountType.individual" : "Indivíduo", 247 "settings.user.form.accountType.individual" : "Indivíduo",
221 "settings.user.form.accountType.label" : "Tipo de conta", 248 "settings.user.form.accountType.label" : "Tipo de conta",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Primeiro Nome", 252 "settings.user.form.firstname" : "Primeiro Nome",
226 "settings.user.form.lastname" : "Último Nome", 253 "settings.user.form.lastname" : "Último Nome",
227 "settings.user.form.newPassword" : "Nova palavra-passe", 254 "settings.user.form.newPassword" : "Nova palavra-passe",
255 "settings.workspace.add.form.name" : "Nome",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Nome",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Tentar novamente",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Adicionar um novo serviço", 270 "sidebar.addNewService" : "Adicionar um novo serviço",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Desativar notificações e áudio", 272 "sidebar.muteApp" : "Desativar notificações e áudio",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Definições", 274 "sidebar.settings" : "Definições",
231 "sidebar.unmuteApp" : "Ativar notificações e áudio", 275 "sidebar.unmuteApp" : "Ativar notificações e áudio",
232 "signup.company.label" : "Empresa", 276 "signup.company.label" : "Empresa",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Residentes EU: Taxas locais podem ser aplicadas", 288 "subscription.euTaxInfo" : "Residentes EU: Taxas locais podem ser aplicadas",
245 "subscription.features.ads" : "Sem anúncios, para sempre!", 289 "subscription.features.ads" : "Sem anúncios, para sempre!",
246 "subscription.features.comingSoon" : "em breve", 290 "subscription.features.comingSoon" : "em breve",
247 "subscription.features.encryptedSync" : "Sincronização encriptada de sessão", 291 "subscription.features.noInterruptions" : "Sem atrasos na aplicação nem mensagens para comprar uma licença",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Adicione serviços como Mattermost no local ou online",
249 "subscription.features.onpremise" : "Adicionar serviços 'on-premise'\/hosted como o HipChat", 293 "subscription.features.proxy" : "Suporte Proxy para os serviços",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Suporte para correção ortográfica",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Ao subscrever uma Conta Premium, tem acesso a", 296 "subscription.includedFeatures" : "Ao subscrever uma Conta Premium, tem acesso a",
254 "subscription.paymentSessionError" : "Erro no serviço de pagamento", 297 "subscription.paymentSessionError" : "Erro no serviço de pagamento",
255 "subscription.submit.label" : "Pretendo ajudar o desenvolvimento do Franz", 298 "subscription.submit.label" : "Pretendo ajudar o desenvolvimento do Franz",
@@ -268,10 +311,21 @@
268 "tabs.item.enableService" : "Ativar serviço", 311 "tabs.item.enableService" : "Ativar serviço",
269 "tabs.item.reload" : "Recarregar", 312 "tabs.item.reload" : "Recarregar",
270 "validation.email" : "{field} não é válido", 313 "validation.email" : "{field} não é válido",
271 "validation.minLength" : "{field} deveria ter pelo menos {comprimento} caracteres", 314 "validation.minLength" : "{field} deveria ter pelo menos {length} caracteres",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} é obrigatório", 316 "validation.required" : "{field} é obrigatório",
273 "validation.url" : "{field} não é uma hiperligação válida", 317 "validation.url" : "{field} não é uma hiperligação válida",
274 "welcome.loginButton" : "Iniciar sessão", 318 "welcome.loginButton" : "Iniciar sessão",
275 "welcome.signupButton" : "Criar uma conta gratuita", 319 "welcome.signupButton" : "Criar uma conta gratuita",
276 "welcome.slogan" : "Sistema de mensagens feito para si" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Todos os serviços",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json
index b605afc4d..97ad98361 100644
--- a/src/i18n/locales/ru.json
+++ b/src/i18n/locales/ru.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Перезагрузить", 2 "app.errorHandler.action" : "Перезагрузить",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Что-то пошло не так",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² верÑии Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Получите лицензию Franz Supporter",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "ПожалуйÑта приобретите лицензию Franz Supporter чтобы убрать ожидание",
7 "feature.delayApp.text" : "Franz продолжит работу через {seconds} Ñекунд.",
8 "feature.shareFranz.action.email" : "Отправить email",
9 "feature.shareFranz.action.facebook" : "ПоделитьÑÑ Ð½Ð° Facebook",
10 "feature.shareFranz.action.twitter" : "ПоделитьÑÑ Ð² Twitter",
11 "feature.shareFranz.headline" : "Сделаем Franz лучше вмеÑте!",
12 "feature.shareFranz.shareText.email" : "Я добавил {count} ÑервиÑов во Franz! Теперь доÑтупны такие меÑÑенджеры как WhatsApp, Messenger, Slack, Skype и другие. Полый ÑпиÑок вы найдете на www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "Я добавил {count} ÑервиÑ(ов) в Franz! Скачай беÑплатную аппку Ð´Ð»Ñ WhatsApp, Messenger, Slack, Skype и иже на www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "РаÑÑкажи Ñвоим друзьÑм и коллегам наÑколько прелеÑтен Franz и помоги нам развитьÑÑ",
7 "global.api.unhealthy" : "Ðевозможно подключитьÑÑ Ðº онлайн-ÑервиÑам Franz", 15 "global.api.unhealthy" : "Ðевозможно подключитьÑÑ Ðº онлайн-ÑервиÑам Franz",
8 "global.notConnectedToTheInternet" : "Ð’Ñ‹ не подключены к Ñети Интернет", 16 "global.notConnectedToTheInternet" : "Ð’Ñ‹ не подключены к Ñети Интернет",
17 "global.spellchecker.useDefault" : "ИÑпользовать ÑиÑтемные параметры по умолчанию ({default})",
18 "global.spellchecking.autodetect" : "Ðайти Ñзык автоматичеÑки",
19 "global.spellchecking.autodetect.short" : "Ðвто",
20 "global.spellchecking.language" : "Проверка правопиÑаниÑ",
9 "import.headline" : "Импортировать ваши ÑервиÑÑ‹ из Franz 4", 21 "import.headline" : "Импортировать ваши ÑервиÑÑ‹ из Franz 4",
10 "import.notSupportedHeadline" : "СервиÑÑ‹ пока ещё не поддерживаютÑÑ Ð² Franz 5", 22 "import.notSupportedHeadline" : "СервиÑÑ‹ пока ещё не поддерживаютÑÑ Ð² Franz 5",
11 "import.skip.label" : "Я хочу добавить ÑервиÑÑ‹ вручную", 23 "import.skip.label" : "Я хочу добавить ÑервиÑÑ‹ вручную",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Вход", 44 "login.submit.label" : "Вход",
33 "login.tokenExpired" : "СеÑÑÐ¸Ñ ÑƒÑтарела, пожалуйÑта, войдите Ñнова.", 45 "login.tokenExpired" : "СеÑÑÐ¸Ñ ÑƒÑтарела, пожалуйÑта, войдите Ñнова.",
34 "menu.app.about" : "О Franz", 46 "menu.app.about" : "О Franz",
47 "menu.app.announcement" : "Что нового?",
35 "menu.app.hide" : "Скрыть", 48 "menu.app.hide" : "Скрыть",
36 "menu.app.hideOthers" : "Скрыть оÑтальные", 49 "menu.app.hideOthers" : "Скрыть оÑтальные",
37 "menu.app.quit" : "Выйти", 50 "menu.app.quit" : "Выйти",
@@ -58,8 +71,10 @@
58 "menu.help.privacy" : "Политика конфиденциальноÑти", 71 "menu.help.privacy" : "Политика конфиденциальноÑти",
59 "menu.help.support" : "Поддержка", 72 "menu.help.support" : "Поддержка",
60 "menu.help.tos" : "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑпользованиÑ", 73 "menu.help.tos" : "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑпользованиÑ",
61 "menu.services" : "Службы", 74 "menu.services" : "СервиÑ",
75 "menu.services.activatePreviousService" : "Ðктивировать предыдущий Ñервич",
62 "menu.services.addNewService" : "Добавить новый ÑервиÑ...", 76 "menu.services.addNewService" : "Добавить новый ÑервиÑ...",
77 "menu.services.setNextServiceActive" : "Ðктивировать Ñледующий ÑервиÑ",
63 "menu.view" : "Вид", 78 "menu.view" : "Вид",
64 "menu.view.enterFullScreen" : "Ðа веÑÑŒ Ñкран", 79 "menu.view.enterFullScreen" : "Ðа веÑÑŒ Ñкран",
65 "menu.view.exitFullScreen" : "В окне", 80 "menu.view.exitFullScreen" : "В окне",
@@ -74,6 +89,11 @@
74 "menu.window" : "Окно", 89 "menu.window" : "Окно",
75 "menu.window.close" : "Закрыть", 90 "menu.window.close" : "Закрыть",
76 "menu.window.minimize" : "Свернуть", 91 "menu.window.minimize" : "Свернуть",
92 "menu.workspaces" : "Окружение",
93 "menu.workspaces.addNewWorkspace" : "Добавить Ðовое Окружение...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Закрыть меню окружений",
95 "menu.workspaces.defaultWorkspace" : "Ð’Ñе ÑервиÑÑ‹",
96 "menu.workspaces.openWorkspaceDrawer" : "Открыть меню окружений",
77 "password.email.label" : "ÐÐ´Ñ€ÐµÑ Ñлектронной почты", 97 "password.email.label" : "ÐÐ´Ñ€ÐµÑ Ñлектронной почты",
78 "password.headline" : "СброÑить пароль", 98 "password.headline" : "СброÑить пароль",
79 "password.link.login" : "Вход", 99 "password.link.login" : "Вход",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Ðе найдено Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ñ‚Ð°ÐºÐ¸Ð¼ адреÑом Ñлектронной почты", 101 "password.noUser" : "Ðе найдено Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ñ‚Ð°ÐºÐ¸Ð¼ адреÑом Ñлектронной почты",
82 "password.submit.label" : "ПринÑÑ‚ÑŒ", 102 "password.submit.label" : "ПринÑÑ‚ÑŒ",
83 "password.successInfo" : "Проверьте вашу Ñлектронную почту", 103 "password.successInfo" : "Проверьте вашу Ñлектронную почту",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Перейти на платную подпиÑку",
85 "pricing.headline" : "Поддержать Franz", 105 "pricing.headline" : "Поддержать Franz",
86 "pricing.link.skipPayment" : "Я не хочу поддерживать разработку Franz.", 106 "pricing.link.skipPayment" : "Я не хочу поддерживать разработку Franz.",
87 "pricing.submit.label" : "Я хочу поддержать разработку Franz", 107 "pricing.submit.label" : "Я хочу поддержать разработку Franz",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Редактирование {name}", 116 "service.errorHandler.editAction" : "Редактирование {name}",
97 "service.errorHandler.headline" : "О, нет!", 117 "service.errorHandler.headline" : "О, нет!",
98 "service.errorHandler.message" : "Ошибка", 118 "service.errorHandler.message" : "Ошибка",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} не Ñмог загрузитьÑÑ.",
120 "service.webviewLoader.loading" : "Загрузка",
100 "services.getStarted" : "Ðачать работу", 121 "services.getStarted" : "Ðачать работу",
101 "services.welcome" : "Добро пожаловать во Franz", 122 "services.welcome" : "Добро пожаловать во Franz",
102 "settings.account.account.editButton" : "Редактировать аккаунт", 123 "settings.account.account.editButton" : "Редактировать аккаунт",
@@ -108,7 +129,7 @@
108 "settings.account.deleteInfo" : "ЕÑли вам больше не нужна ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в Franz, вы можете удалить аккаунт и вÑÑŽ ÑвÑзанную Ñ Ð½ÐµÐ¹ информацию.", 129 "settings.account.deleteInfo" : "ЕÑли вам больше не нужна ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в Franz, вы можете удалить аккаунт и вÑÑŽ ÑвÑзанную Ñ Ð½ÐµÐ¹ информацию.",
109 "settings.account.headline" : "Ðккаунт", 130 "settings.account.headline" : "Ðккаунт",
110 "settings.account.headlineAccount" : "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°", 131 "settings.account.headlineAccount" : "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°",
111 "settings.account.headlineDangerZone" : "ОпаÑÐ½Ð°Ñ Ð—Ð¾Ð½Ð°", 132 "settings.account.headlineDangerZone" : "ÐапреÑÐ½Ð°Ñ Ð—Ð¾Ð½Ð°",
112 "settings.account.headlineInvoices" : "Счета", 133 "settings.account.headlineInvoices" : "Счета",
113 "settings.account.headlinePassword" : "Сменить пароль", 134 "settings.account.headlinePassword" : "Сменить пароль",
114 "settings.account.headlineProfile" : "Обновить профиль", 135 "settings.account.headlineProfile" : "Обновить профиль",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Скачать", 138 "settings.account.invoiceDownload" : "Скачать",
118 "settings.account.manageSubscription.label" : "Управление вашей подпиÑкой", 139 "settings.account.manageSubscription.label" : "Управление вашей подпиÑкой",
119 "settings.account.successInfo" : "Ваши Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ Ñохранены", 140 "settings.account.successInfo" : "Ваши Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ Ñохранены",
141 "settings.account.tryReloadServices" : "Попробовать Ñнова",
120 "settings.account.tryReloadUserInfoRequest" : "Попробовать Ñнова", 142 "settings.account.tryReloadUserInfoRequest" : "Попробовать Ñнова",
121 "settings.account.userInfoRequestFailed" : "Ðевозможно загрузить информацию пользователÑ", 143 "settings.account.userInfoRequestFailed" : "Ðевозможно загрузить информацию пользователÑ",
122 "settings.app.buttonClearAllCache" : "ОчиÑтить кÑш", 144 "settings.app.buttonClearAllCache" : "ОчиÑтить кÑш",
@@ -127,24 +149,22 @@
127 "settings.app.form.autoLaunchInBackground" : "Открывать в фоне", 149 "settings.app.form.autoLaunchInBackground" : "Открывать в фоне",
128 "settings.app.form.autoLaunchOnStart" : "ЗапуÑкать Franz при Ñтарте", 150 "settings.app.form.autoLaunchOnStart" : "ЗапуÑкать Franz при Ñтарте",
129 "settings.app.form.beta" : "Ð’ÐºÐ»ÑŽÑ‡Ð°Ñ Ð±ÐµÑ‚Ð° верÑии", 151 "settings.app.form.beta" : "Ð’ÐºÐ»ÑŽÑ‡Ð°Ñ Ð±ÐµÑ‚Ð° верÑии",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Перейти на Тёмную Ñторону",
131 "settings.app.form.enableGPUAcceleration" : "Включить уÑкорение GPU", 153 "settings.app.form.enableGPUAcceleration" : "Включить уÑкорение GPU",
132 "settings.app.form.enableMenuBar" : "Показывать Franz на панели меню",
133 "settings.app.form.enableSpellchecking" : "Включить проверку правопиÑаниÑ", 154 "settings.app.form.enableSpellchecking" : "Включить проверку правопиÑаниÑ",
134 "settings.app.form.enableSystemTray" : "Показывать Franz в ÑиÑтемном трее", 155 "settings.app.form.enableSystemTray" : "Показывать Franz в ÑиÑтемном трее",
135 "settings.app.form.hideDockIcon" : "СпрÑтать иконку Franz на панели",
136 "settings.app.form.language" : "Язык", 156 "settings.app.form.language" : "Язык",
137 "settings.app.form.minimizeToSystemTray" : "Сворачивать Franz в ÑиÑтемный трей", 157 "settings.app.form.minimizeToSystemTray" : "Сворачивать Franz в ÑиÑтемный трей",
138 "settings.app.form.runInBackground" : "ОÑтавлÑÑ‚ÑŒ Franz в фоне при закрытии окна", 158 "settings.app.form.runInBackground" : "ОÑтавлÑÑ‚ÑŒ Franz в фоне при закрытии окна",
139 "settings.app.form.showDisabledServices" : "Показывать вкладки отключённых Ñлужб", 159 "settings.app.form.showDisabledServices" : "Показывать вкладки отключённых Ñлужб",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Показывать значок непрочитанного ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ отключённых уведомлениÑÑ…", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Показывать значок непрочитанного ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ отключённых уведомлениÑÑ…",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "ÐаÑтройки", 161 "settings.app.headline" : "ÐаÑтройки",
143 "settings.app.headlineAdvanced" : "Дополнительно", 162 "settings.app.headlineAdvanced" : "Дополнительно",
144 "settings.app.headlineAppearance" : "Внешний вид", 163 "settings.app.headlineAppearance" : "Внешний вид",
145 "settings.app.headlineGeneral" : "Общие", 164 "settings.app.headlineGeneral" : "Общие",
146 "settings.app.headlineLanguage" : "Язык", 165 "settings.app.headlineLanguage" : "Язык",
147 "settings.app.headlineUpdates" : "ОбновлениÑ", 166 "settings.app.headlineUpdates" : "ОбновлениÑ",
167 "settings.app.languageDisclaimer" : "ÐžÑ„Ð¸Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ° только Ð´Ð»Ñ Ð°Ð½Ð³Ð»Ð¸Ð¹Ñкого и немецкого Ñзыков. ОÑтальные Ñзыки переведены ÑообщеÑтвом.",
148 "settings.app.restartRequired" : "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ перезагрузки приложениÑ", 168 "settings.app.restartRequired" : "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ перезагрузки приложениÑ",
149 "settings.app.subheadlineCache" : "КÑш", 169 "settings.app.subheadlineCache" : "КÑш",
150 "settings.app.translationHelp" : "Помогите нам перевеÑти Franz на ваш Ñзык.", 170 "settings.app.translationHelp" : "Помогите нам перевеÑти Franz на ваш Ñзык.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "ПриглаÑить друзей", 177 "settings.navigation.inviteFriends" : "ПриглаÑить друзей",
158 "settings.navigation.logout" : "Выход", 178 "settings.navigation.logout" : "Выход",
159 "settings.navigation.settings" : "ÐаÑтройки", 179 "settings.navigation.settings" : "ÐаÑтройки",
180 "settings.navigation.team" : "Управление Командой",
160 "settings.navigation.yourServices" : "Ваши ÑервиÑÑ‹", 181 "settings.navigation.yourServices" : "Ваши ÑервиÑÑ‹",
182 "settings.navigation.yourWorkspaces" : "Ваши окружениÑ",
161 "settings.recipes.all" : "Ð’Ñе ÑервиÑÑ‹", 183 "settings.recipes.all" : "Ð’Ñе ÑервиÑÑ‹",
162 "settings.recipes.dev" : "Разработка", 184 "settings.recipes.dev" : "Разработка",
163 "settings.recipes.headline" : "ДоÑтупные ÑервиÑÑ‹", 185 "settings.recipes.headline" : "ДоÑтупные ÑервиÑÑ‹",
@@ -176,10 +198,10 @@
176 "settings.service.form.customUrlUpgradeAccount" : "Улучшить ваш аккаунт", 198 "settings.service.form.customUrlUpgradeAccount" : "Улучшить ваш аккаунт",
177 "settings.service.form.customUrlValidationError" : "Ðевозможно проверить Ñервер {name}.", 199 "settings.service.form.customUrlValidationError" : "Ðевозможно проверить Ñервер {name}.",
178 "settings.service.form.deleteButton" : "Удалить ÑервиÑ", 200 "settings.service.form.deleteButton" : "Удалить ÑервиÑ",
179 "settings.service.form.editServiceHeadline" : "Редактирование {name}", 201 "settings.service.form.editServiceHeadline" : "Редактировать {name}",
180 "settings.service.form.enableAudio" : "Включить звук", 202 "settings.service.form.enableAudio" : "Включить звук",
181 "settings.service.form.enableBadge" : "Показывать иконку непрочитанных Ñообщений", 203 "settings.service.form.enableBadge" : "Показывать иконку непрочитанных Ñообщений",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Включить Тёмный режим",
183 "settings.service.form.enableNotification" : "Включить уведомлениÑ", 205 "settings.service.form.enableNotification" : "Включить уведомлениÑ",
184 "settings.service.form.enableService" : "Включить ÑервиÑ", 206 "settings.service.form.enableService" : "Включить ÑервиÑ",
185 "settings.service.form.headlineBadges" : "Значки непрочитанных Ñообщений", 207 "settings.service.form.headlineBadges" : "Значки непрочитанных Ñообщений",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Показывать значок уведомлений Ð´Ð»Ñ Ð²Ñех новых Ñообщений", 214 "settings.service.form.indirectMessages" : "Показывать значок уведомлений Ð´Ð»Ñ Ð²Ñех новых Ñообщений",
193 "settings.service.form.isMutedInfo" : "Когда выключено, вÑе звуковые ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ отключены", 215 "settings.service.form.isMutedInfo" : "Когда выключено, вÑе звуковые ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ отключены",
194 "settings.service.form.name" : "Ðазвание", 216 "settings.service.form.name" : "Ðазвание",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "ÐаÑтройки ПрокÑи HTTP\/HTTPS",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "ПрокÑи Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "ÐаÑтройки прокÑи не будут Ñинхронизированны Ñ Ñерверами Franz",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "ИÑпользовать прокÑи",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Пароль (опционально)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Порт",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "ПожалуйÑта перезапуÑтите Franz поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек прокÑи.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Пользователь (опционально)",
203 "settings.service.form.saveButton" : "Сохранить ÑервиÑ", 225 "settings.service.form.saveButton" : "Сохранить ÑервиÑ",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Размещено", 226 "settings.service.form.tabHosted" : "Размещено",
207 "settings.service.form.tabOnPremise" : "Свой хоÑтинг â­ï¸", 227 "settings.service.form.tabOnPremise" : "Свой хоÑтинг â­ï¸",
208 "settings.service.form.team" : "Команда", 228 "settings.service.form.team" : "Команда",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Ðайти ÑервиÑÑ‹", 232 "settings.services.discoverServices" : "Ðайти ÑервиÑÑ‹",
213 "settings.services.headline" : "Ваши ÑервиÑÑ‹", 233 "settings.services.headline" : "Ваши ÑервиÑÑ‹",
214 "settings.services.noServicesAdded" : "Ð’Ñ‹ пока не добавили никаких ÑервиÑов.", 234 "settings.services.noServicesAdded" : "Ð’Ñ‹ пока не добавили никаких ÑервиÑов.",
235 "settings.services.servicesRequestFailed" : "Ошибка загрузки ÑервиÑов",
215 "settings.services.tooltip.isDisabled" : "Ð¡ÐµÑ€Ð²Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½", 236 "settings.services.tooltip.isDisabled" : "Ð¡ÐµÑ€Ð²Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½",
216 "settings.services.tooltip.isMuted" : "Ð’Ñе звуки отключены", 237 "settings.services.tooltip.isMuted" : "Ð’Ñе звуки отключены",
217 "settings.services.tooltip.notificationsDisabled" : "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ‹", 238 "settings.services.tooltip.notificationsDisabled" : "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ‹",
218 "settings.services.updatedInfo" : "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñохранены", 239 "settings.services.updatedInfo" : "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñохранены",
240 "settings.team.contentHeadline" : "Franz Ð´Ð»Ñ ÐšÐ¾Ð¼Ð°Ð½Ð´",
241 "settings.team.copy" : "Franz Ð´Ð»Ñ ÐšÐ¾Ð¼Ð°Ð½Ð´ позволÑет приглаÑить коллег в вашу команду, отправив им емайл Ñ Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸ÐµÐ¼, а также управлÑÑ‚ÑŒ их подпиÑками в наÑтройках вашего аккаунта. Ðе тратьте Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° наÑтройку подпиÑок Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ члена команды индивидуально, забудьте о многочиÑленных платежках и разных циклах оплаты - одна команда Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñеми!",
242 "settings.team.headline" : "Команда",
243 "settings.team.intro" : "Ð’Ñ‹ и ваша команда иÑпльзуете Franz? Ð’Ñ‹ теперь можете управлÑÑ‚ÑŒ Премиум подпиÑками любого количеÑтва коллег, друзей и членов Ñемьи, из одного и того же аккаунта.",
244 "settings.team.manageAction" : "УправлÑйте вашей Командой на meetfranz.com",
245 "settings.team.upgradeAction" : "Улучшить ваш аккаунт",
219 "settings.user.form.accountType.company" : "КомпаниÑ", 246 "settings.user.form.accountType.company" : "КомпаниÑ",
220 "settings.user.form.accountType.individual" : "Индивидуальный", 247 "settings.user.form.accountType.individual" : "Индивидуальный",
221 "settings.user.form.accountType.label" : "Тип аккаунта", 248 "settings.user.form.accountType.label" : "Тип аккаунта",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "ИмÑ", 252 "settings.user.form.firstname" : "ИмÑ",
226 "settings.user.form.lastname" : "ФамилиÑ", 253 "settings.user.form.lastname" : "ФамилиÑ",
227 "settings.user.form.newPassword" : "Ðовый пароль", 254 "settings.user.form.newPassword" : "Ðовый пароль",
255 "settings.workspace.add.form.name" : "ИмÑ",
256 "settings.workspace.add.form.submitButton" : "Создать окружение",
257 "settings.workspace.form.buttonDelete" : "Удалить окружение",
258 "settings.workspace.form.buttonSave" : "Сохранить окружение",
259 "settings.workspace.form.name" : "ИмÑ",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Ваши окружениÑ",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Ваши окружениÑ",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Попробовать Ñнова",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Добавить новый ÑервиÑ", 270 "sidebar.addNewService" : "Добавить новый ÑервиÑ",
271 "sidebar.closeWorkspaceDrawer" : "Закрыть меню окружений",
229 "sidebar.muteApp" : "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ звук", 272 "sidebar.muteApp" : "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ звук",
273 "sidebar.openWorkspaceDrawer" : "Открыть меню окружений",
230 "sidebar.settings" : "ÐаÑтройки", 274 "sidebar.settings" : "ÐаÑтройки",
231 "sidebar.unmuteApp" : "Включить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ звук", 275 "sidebar.unmuteApp" : "Включить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ звук",
232 "signup.company.label" : "ОрганизациÑ", 276 "signup.company.label" : "ОрганизациÑ",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Резидентам ЕвроСоюза: могут применÑÑ‚ÑŒÑÑ Ð¼ÐµÑтные налоги", 288 "subscription.euTaxInfo" : "Резидентам ЕвроСоюза: могут применÑÑ‚ÑŒÑÑ Ð¼ÐµÑтные налоги",
245 "subscription.features.ads" : "Без рекламы, навÑегда!", 289 "subscription.features.ads" : "Без рекламы, навÑегда!",
246 "subscription.features.comingSoon" : "Ñкоро", 290 "subscription.features.comingSoon" : "Ñкоро",
247 "subscription.features.encryptedSync" : "Зашифрованные ÑеÑÑии Ñинхронизации", 291 "subscription.features.noInterruptions" : "Ðикаких задержек и предложений перейти на платную верÑию",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Локальные\/размещенные на хоÑтинге ÑервиÑÑ‹, такие как Mattermost",
249 "subscription.features.onpremise" : "Добавление облачных Ñлужб или Ñлужб на Ñвоём хоÑтинге типа HipChat", 293 "subscription.features.proxy" : "Подержка прокÑи Ð´Ð»Ñ ÑервиÑов",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Поддержка проверки правопиÑаниÑ",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Платный премиум аккаунт Franz включает", 296 "subscription.includedFeatures" : "Платный премиум аккаунт Franz включает",
254 "subscription.paymentSessionError" : "Ðевозможно загрузить форму оплаты", 297 "subscription.paymentSessionError" : "Ðевозможно загрузить форму оплаты",
255 "subscription.submit.label" : "Я хочу поддержать разработку Franz", 298 "subscription.submit.label" : "Я хочу поддержать разработку Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Перезагрузить", 312 "tabs.item.reload" : "Перезагрузить",
270 "validation.email" : "{field} недейÑтвительно", 313 "validation.email" : "{field} недейÑтвительно",
271 "validation.minLength" : "{field} должно быть не менее {length} Ñимволов", 314 "validation.minLength" : "{field} должно быть не менее {length} Ñимволов",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} обÑзательно", 316 "validation.required" : "{field} обÑзательно",
273 "validation.url" : "{field} ÑвлÑетÑÑ Ð½ÐµÐ´ÐµÐ¹Ñтвительной ÑÑылкой", 317 "validation.url" : "{field} ÑвлÑетÑÑ Ð½ÐµÐ´ÐµÐ¹Ñтвительной ÑÑылкой",
274 "welcome.loginButton" : "Вход", 318 "welcome.loginButton" : "Вход",
275 "welcome.signupButton" : "Создать беÑплатный аккаунт", 319 "welcome.signupButton" : "Создать беÑплатный аккаунт",
276 "welcome.slogan" : "Общение, которое работает Ð´Ð»Ñ Ð²Ð°Ñ" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Ð’Ñе ÑервиÑÑ‹",
322 "workspaceDrawer.headline" : "Окружение",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "ВоÑÑтановить премиум аккаунт",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/sk.json b/src/i18n/locales/sk.json
index ca7335fe9..7af29ef1c 100644
--- a/src/i18n/locales/sk.json
+++ b/src/i18n/locales/sk.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Obnoviť", 2 "app.errorHandler.action" : "Obnoviť",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Something went wrong",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Nedá sa pripojiť k online službám Franz", 15 "global.api.unhealthy" : "Nedá sa pripojiť k online službám Franz",
8 "global.notConnectedToTheInternet" : "Nie ste pripojení k internetu.", 16 "global.notConnectedToTheInternet" : "Nie ste pripojení k internetu.",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "Importovať vaše služby z Franz 4", 21 "import.headline" : "Importovať vaše služby z Franz 4",
10 "import.notSupportedHeadline" : "Služby zatiaľ nie sú podporované vo verzii Franz 5", 22 "import.notSupportedHeadline" : "Služby zatiaľ nie sú podporované vo verzii Franz 5",
11 "import.skip.label" : "Chcem pridaÅ¥ služby ruÄne", 23 "import.skip.label" : "Chcem pridaÅ¥ služby ruÄne",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Prihlásiť sa", 44 "login.submit.label" : "Prihlásiť sa",
33 "login.tokenExpired" : "Vaša relácia vypršala, prihláste sa prosím znovu.", 45 "login.tokenExpired" : "Vaša relácia vypršala, prihláste sa prosím znovu.",
34 "menu.app.about" : "O aplikácii", 46 "menu.app.about" : "O aplikácii",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Skryť", 48 "menu.app.hide" : "Skryť",
36 "menu.app.hideOthers" : "Skryť ostatné", 49 "menu.app.hideOthers" : "Skryť ostatné",
37 "menu.app.quit" : "UkonÄiÅ¥", 50 "menu.app.quit" : "UkonÄiÅ¥",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Podpora", 72 "menu.help.support" : "Podpora",
60 "menu.help.tos" : "Podmienky použitia", 73 "menu.help.tos" : "Podmienky použitia",
61 "menu.services" : "Služby", 74 "menu.services" : "Služby",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Pridať novú službu...", 76 "menu.services.addNewService" : "Pridať novú službu...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Zobraziť", 78 "menu.view" : "Zobraziť",
64 "menu.view.enterFullScreen" : "Na celú obrazovku", 79 "menu.view.enterFullScreen" : "Na celú obrazovku",
65 "menu.view.exitFullScreen" : "UkonÄiÅ¥ režim na celú obrazovku", 80 "menu.view.exitFullScreen" : "UkonÄiÅ¥ režim na celú obrazovku",
@@ -74,6 +89,11 @@
74 "menu.window" : "Okno", 89 "menu.window" : "Okno",
75 "menu.window.close" : "Zatvoriť", 90 "menu.window.close" : "Zatvoriť",
76 "menu.window.minimize" : "Minimalizovať", 91 "menu.window.minimize" : "Minimalizovať",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Všetky služby",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-mailová adresa", 97 "password.email.label" : "E-mailová adresa",
78 "password.headline" : "Obnoviť heslo", 98 "password.headline" : "Obnoviť heslo",
79 "password.link.login" : "PrihlásiÅ¥ sa do vášho úÄtu", 99 "password.link.login" : "PrihlásiÅ¥ sa do vášho úÄtu",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "Ale nie!", 117 "service.errorHandler.headline" : "Ale nie!",
98 "service.errorHandler.message" : "Chyba", 118 "service.errorHandler.message" : "Chyba",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "ZaÄíname", 121 "services.getStarted" : "ZaÄíname",
101 "services.welcome" : "Vítajte v aplikácii Franz", 122 "services.welcome" : "Vítajte v aplikácii Franz",
102 "settings.account.account.editButton" : "UpraviÅ¥ úÄet", 123 "settings.account.account.editButton" : "UpraviÅ¥ úÄet",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Prevziať", 138 "settings.account.invoiceDownload" : "Prevziať",
118 "settings.account.manageSubscription.label" : "Spravovať vaše odoberanie", 139 "settings.account.manageSubscription.label" : "Spravovať vaše odoberanie",
119 "settings.account.successInfo" : "Vaše zmeny boli uložené", 140 "settings.account.successInfo" : "Vaše zmeny boli uložené",
141 "settings.account.tryReloadServices" : "Skúsiť znova",
120 "settings.account.tryReloadUserInfoRequest" : "Skúsiť znova", 142 "settings.account.tryReloadUserInfoRequest" : "Skúsiť znova",
121 "settings.account.userInfoRequestFailed" : "Nebolo možné naÄítaÅ¥ informácie o používateľovi", 143 "settings.account.userInfoRequestFailed" : "Nebolo možné naÄítaÅ¥ informácie o používateľovi",
122 "settings.app.buttonClearAllCache" : "VyÄistiÅ¥ vyrovnávaciu pamäť", 144 "settings.app.buttonClearAllCache" : "VyÄistiÅ¥ vyrovnávaciu pamäť",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Vrátane beta verzií", 151 "settings.app.form.beta" : "Vrátane beta verzií",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "Zapnúť GPU zrýchlenie", 153 "settings.app.form.enableGPUAcceleration" : "Zapnúť GPU zrýchlenie",
132 "settings.app.form.enableMenuBar" : "Zobraziť Franz v ponuke menu",
133 "settings.app.form.enableSpellchecking" : "Zapnúť kontrolu pravopisu", 154 "settings.app.form.enableSpellchecking" : "Zapnúť kontrolu pravopisu",
134 "settings.app.form.enableSystemTray" : "Zobrazovať Franz v systémovej lište", 155 "settings.app.form.enableSystemTray" : "Zobrazovať Franz v systémovej lište",
135 "settings.app.form.hideDockIcon" : "Skryť ikonu Franz v doku",
136 "settings.app.form.language" : "Jazyk", 156 "settings.app.form.language" : "Jazyk",
137 "settings.app.form.minimizeToSystemTray" : "Minimalizovať Franz do systémovej lišty", 157 "settings.app.form.minimizeToSystemTray" : "Minimalizovať Franz do systémovej lišty",
138 "settings.app.form.runInBackground" : "Po zatvorení okna ponechať Franz spustený na pozadí", 158 "settings.app.form.runInBackground" : "Po zatvorení okna ponechať Franz spustený na pozadí",
139 "settings.app.form.showDisabledServices" : "Zobraziť záložky vypnutých služieb", 159 "settings.app.form.showDisabledServices" : "Zobraziť záložky vypnutých služieb",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "ZobraziÅ¥ symbol pre nepreÄítané správy, keÄ sú vypnuté upozornenia", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "ZobraziÅ¥ symbol pre nepreÄítané správy, keÄ sú vypnuté upozornenia",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Nastavenia", 161 "settings.app.headline" : "Nastavenia",
143 "settings.app.headlineAdvanced" : "PokroÄilé", 162 "settings.app.headlineAdvanced" : "PokroÄilé",
144 "settings.app.headlineAppearance" : "Vzhľad", 163 "settings.app.headlineAppearance" : "Vzhľad",
145 "settings.app.headlineGeneral" : "Všeobecné", 164 "settings.app.headlineGeneral" : "Všeobecné",
146 "settings.app.headlineLanguage" : "Jazyk", 165 "settings.app.headlineLanguage" : "Jazyk",
147 "settings.app.headlineUpdates" : "Aktualizácie", 166 "settings.app.headlineUpdates" : "Aktualizácie",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Zmeny vyžadujú reštart", 168 "settings.app.restartRequired" : "Zmeny vyžadujú reštart",
149 "settings.app.subheadlineCache" : "Vyrovnávacia pamäť", 169 "settings.app.subheadlineCache" : "Vyrovnávacia pamäť",
150 "settings.app.translationHelp" : "Pomôžte nám preložiť Franz do svojho jazyka.", 170 "settings.app.translationHelp" : "Pomôžte nám preložiť Franz do svojho jazyka.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Pozvať priateľov", 177 "settings.navigation.inviteFriends" : "Pozvať priateľov",
158 "settings.navigation.logout" : "Odhlásiť sa", 178 "settings.navigation.logout" : "Odhlásiť sa",
159 "settings.navigation.settings" : "Nastavenia", 179 "settings.navigation.settings" : "Nastavenia",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Vaše služby", 181 "settings.navigation.yourServices" : "Vaše služby",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Všetky služby", 183 "settings.recipes.all" : "Všetky služby",
162 "settings.recipes.dev" : "Vývoj", 184 "settings.recipes.dev" : "Vývoj",
163 "settings.recipes.headline" : "Dostupné služby", 185 "settings.recipes.headline" : "Dostupné služby",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "Uložiť službu", 225 "settings.service.form.saveButton" : "Uložiť službu",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hostované", 226 "settings.service.form.tabHosted" : "Hostované",
207 "settings.service.form.tabOnPremise" : "Vlastné hostovanie â­ï¸", 227 "settings.service.form.tabOnPremise" : "Vlastné hostovanie â­ï¸",
208 "settings.service.form.team" : "Tím", 228 "settings.service.form.team" : "Tím",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Preskúmať služby", 232 "settings.services.discoverServices" : "Preskúmať služby",
213 "settings.services.headline" : "Vaše služby", 233 "settings.services.headline" : "Vaše služby",
214 "settings.services.noServicesAdded" : "Doposiaľ ste nepridali žiadne služby.", 234 "settings.services.noServicesAdded" : "Doposiaľ ste nepridali žiadne služby.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Služba je vypnutá", 236 "settings.services.tooltip.isDisabled" : "Služba je vypnutá",
216 "settings.services.tooltip.isMuted" : "Všetky zvuky sú stíšené", 237 "settings.services.tooltip.isMuted" : "Všetky zvuky sú stíšené",
217 "settings.services.tooltip.notificationsDisabled" : "Oznámenia sú vypnuté", 238 "settings.services.tooltip.notificationsDisabled" : "Oznámenia sú vypnuté",
218 "settings.services.updatedInfo" : "Vaše zmeny boli uložené", 239 "settings.services.updatedInfo" : "Vaše zmeny boli uložené",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Tím",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "SpoloÄnosÅ¥", 246 "settings.user.form.accountType.company" : "SpoloÄnosÅ¥",
220 "settings.user.form.accountType.individual" : "Osoba", 247 "settings.user.form.accountType.individual" : "Osoba",
221 "settings.user.form.accountType.label" : "Typ úÄtu", 248 "settings.user.form.accountType.label" : "Typ úÄtu",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Krstné meno", 252 "settings.user.form.firstname" : "Krstné meno",
226 "settings.user.form.lastname" : "Priezvisko", 253 "settings.user.form.lastname" : "Priezvisko",
227 "settings.user.form.newPassword" : "Nové heslo", 254 "settings.user.form.newPassword" : "Nové heslo",
255 "settings.workspace.add.form.name" : "Meno",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Meno",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Skúsiť znova",
266 "settings.workspaces.updatedInfo" : "Vaše zmeny boli uložené",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Pridať novú službu", 270 "sidebar.addNewService" : "Pridať novú službu",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Vypnúť upozornenia a zvuky", 272 "sidebar.muteApp" : "Vypnúť upozornenia a zvuky",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Nastavenia", 274 "sidebar.settings" : "Nastavenia",
231 "sidebar.unmuteApp" : "Povoliť oznámenia a zvuky", 275 "sidebar.unmuteApp" : "Povoliť oznámenia a zvuky",
232 "signup.company.label" : "SpoloÄnosÅ¥", 276 "signup.company.label" : "SpoloÄnosÅ¥",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Pre obyvateľov EÚ: môže byť aplikovaná miestna daň", 288 "subscription.euTaxInfo" : "Pre obyvateľov EÚ: môže byť aplikovaná miestna daň",
245 "subscription.features.ads" : "Žiadne reklamy, nikdy!", 289 "subscription.features.ads" : "Žiadne reklamy, nikdy!",
246 "subscription.features.comingSoon" : "už Äoskoro", 290 "subscription.features.comingSoon" : "už Äoskoro",
247 "subscription.features.encryptedSync" : "Šifrovaná synchronizácia relácie",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Pridať lokálne hostované služby, ako napr. HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Platený úÄet Premium Supporter Franz zahŕňa", 296 "subscription.includedFeatures" : "Platený úÄet Premium Supporter Franz zahŕňa",
254 "subscription.paymentSessionError" : "Nepodarilo sa inicializovať platbu od", 297 "subscription.paymentSessionError" : "Nepodarilo sa inicializovať platbu od",
255 "subscription.submit.label" : "Chcem podporiť vývoj aplikácie Franz", 298 "subscription.submit.label" : "Chcem podporiť vývoj aplikácie Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Obnoviť", 312 "tabs.item.reload" : "Obnoviť",
270 "validation.email" : "{field} je neplatný", 313 "validation.email" : "{field} je neplatný",
271 "validation.minLength" : "{field} by malo byť dlhé aspoň {length} znakov", 314 "validation.minLength" : "{field} by malo byť dlhé aspoň {length} znakov",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} je povinné", 316 "validation.required" : "{field} je povinné",
273 "validation.url" : "{field} nie je platné URL", 317 "validation.url" : "{field} nie je platné URL",
274 "welcome.loginButton" : "PrihlásiÅ¥ sa do vášho úÄtu", 318 "welcome.loginButton" : "PrihlásiÅ¥ sa do vášho úÄtu",
275 "welcome.signupButton" : "VytvoriÅ¥ úÄet zdarma", 319 "welcome.signupButton" : "VytvoriÅ¥ úÄet zdarma",
276 "welcome.slogan" : "Správy, ktoré pracujú pre vás" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Všetky služby",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/sr.json b/src/i18n/locales/sr.json
index df0b849c4..e5962566b 100644
--- a/src/i18n/locales/sr.json
+++ b/src/i18n/locales/sr.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "Ponovno uÄitavanje", 2 "app.errorHandler.action" : "Ponovno uÄitavanje",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Something went wrong",
4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 5 "feature.delayApp.action" : "Get a Franz Supporter License",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 6 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 7 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
7 "global.api.unhealthy" : "Nije moguće pristupiti Franz-ovim on-line servisima. ", 15 "global.api.unhealthy" : "Nije moguće pristupiti Franz-ovim on-line servisima. ",
8 "global.notConnectedToTheInternet" : "Niste povezani sa serverom.", 16 "global.notConnectedToTheInternet" : "Niste povezani sa serverom.",
17 "global.spellchecker.useDefault" : "Use System Default ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Spell checking language",
9 "import.headline" : "Uvezite svoje Franz 4 servise", 21 "import.headline" : "Uvezite svoje Franz 4 servise",
10 "import.notSupportedHeadline" : "Servis trenutno nije podržan u Franz 5", 22 "import.notSupportedHeadline" : "Servis trenutno nije podržan u Franz 5",
11 "import.skip.label" : "Желим да додам уÑлуге ручно", 23 "import.skip.label" : "Желим да додам уÑлуге ручно",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Prijavite se", 44 "login.submit.label" : "Prijavite se",
33 "login.tokenExpired" : "Vaša sesija je istekla, prijavite se ponovo.", 45 "login.tokenExpired" : "Vaša sesija je istekla, prijavite se ponovo.",
34 "menu.app.about" : "O Francu", 46 "menu.app.about" : "O Francu",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Sakrij", 48 "menu.app.hide" : "Sakrij",
36 "menu.app.hideOthers" : "Sakrij ostale", 49 "menu.app.hideOthers" : "Sakrij ostale",
37 "menu.app.quit" : "Izađi", 50 "menu.app.quit" : "Izađi",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Подршка", 72 "menu.help.support" : "Подршка",
60 "menu.help.tos" : "УÑлови коришћења уÑлуге", 73 "menu.help.tos" : "УÑлови коришћења уÑлуге",
61 "menu.services" : "Usluge", 74 "menu.services" : "Usluge",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Додај нову уÑлугу", 76 "menu.services.addNewService" : "Додај нову уÑлугу",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Преглед", 78 "menu.view" : "Преглед",
64 "menu.view.enterFullScreen" : "Отвори у целом екрану", 79 "menu.view.enterFullScreen" : "Отвори у целом екрану",
65 "menu.view.exitFullScreen" : "ÐапуÑти цео екран", 80 "menu.view.exitFullScreen" : "ÐапуÑти цео екран",
@@ -74,6 +89,11 @@
74 "menu.window" : "У прозору", 89 "menu.window" : "У прозору",
75 "menu.window.close" : "Затвори", 90 "menu.window.close" : "Затвори",
76 "menu.window.minimize" : "Умањи", 91 "menu.window.minimize" : "Умањи",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Sve usluge",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Vaša e-adresa", 97 "password.email.label" : "Vaša e-adresa",
78 "password.headline" : "Stvorite novu zaporku", 98 "password.headline" : "Stvorite novu zaporku",
79 "password.link.login" : "Prijavite se na VaÅ¡ raÄun", 99 "password.link.login" : "Prijavite se na VaÅ¡ raÄun",
@@ -97,6 +117,7 @@
97 "service.errorHandler.headline" : "O, ne! ", 117 "service.errorHandler.headline" : "O, ne! ",
98 "service.errorHandler.message" : "Greška ", 118 "service.errorHandler.message" : "Greška ",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} has failed to load.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "ZapoÄnimo! ", 121 "services.getStarted" : "ZapoÄnimo! ",
101 "services.welcome" : "Dobrodošli u Franz", 122 "services.welcome" : "Dobrodošli u Franz",
102 "settings.account.account.editButton" : "Uredi raÄun", 123 "settings.account.account.editButton" : "Uredi raÄun",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Preuzmite", 138 "settings.account.invoiceDownload" : "Preuzmite",
118 "settings.account.manageSubscription.label" : "Upravljajte pretplatama", 139 "settings.account.manageSubscription.label" : "Upravljajte pretplatama",
119 "settings.account.successInfo" : "Vaše promjene su spremljene", 140 "settings.account.successInfo" : "Vaše promjene su spremljene",
141 "settings.account.tryReloadServices" : "Pokušajte ponovno",
120 "settings.account.tryReloadUserInfoRequest" : "Pokušajte ponovno", 142 "settings.account.tryReloadUserInfoRequest" : "Pokušajte ponovno",
121 "settings.account.userInfoRequestFailed" : "Nije moguće uÄitati informacije o korisniku", 143 "settings.account.userInfoRequestFailed" : "Nije moguće uÄitati informacije o korisniku",
122 "settings.app.buttonClearAllCache" : "ОчиÑти кеш", 144 "settings.app.buttonClearAllCache" : "ОчиÑти кеш",
@@ -129,22 +151,20 @@
129 "settings.app.form.beta" : "Obuhvati i beta verzije", 151 "settings.app.form.beta" : "Obuhvati i beta verzije",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Join the Dark Side",
131 "settings.app.form.enableGPUAcceleration" : "Омогући убрзање графичке јединице", 153 "settings.app.form.enableGPUAcceleration" : "Омогући убрзање графичке јединице",
132 "settings.app.form.enableMenuBar" : "Покажи Франз у менију",
133 "settings.app.form.enableSpellchecking" : "Omogući provjeru pravopisa", 154 "settings.app.form.enableSpellchecking" : "Omogući provjeru pravopisa",
134 "settings.app.form.enableSystemTray" : "Prikaži aplikaciju u sustavskoj traci", 155 "settings.app.form.enableSystemTray" : "Prikaži aplikaciju u sustavskoj traci",
135 "settings.app.form.hideDockIcon" : "Сакриј Франз иконицу у доку",
136 "settings.app.form.language" : "Jezik", 156 "settings.app.form.language" : "Jezik",
137 "settings.app.form.minimizeToSystemTray" : "Smanji Franca u sustavsku traku", 157 "settings.app.form.minimizeToSystemTray" : "Smanji Franca u sustavsku traku",
138 "settings.app.form.runInBackground" : "Neka se Franc održava u pozadini i ako je prozor zatvoren", 158 "settings.app.form.runInBackground" : "Neka se Franc održava u pozadini i ako je prozor zatvoren",
139 "settings.app.form.showDisabledServices" : "Prikaži ploÄe s onemogućenim servisima", 159 "settings.app.form.showDisabledServices" : "Prikaži ploÄe s onemogućenim servisima",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Покажи беџ за непрочитане поруке када Ñу обавештења онемогућена", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Покажи беџ за непрочитане поруке када Ñу обавештења онемогућена",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Подешавања", 161 "settings.app.headline" : "Подешавања",
143 "settings.app.headlineAdvanced" : "Napredne alatke", 162 "settings.app.headlineAdvanced" : "Napredne alatke",
144 "settings.app.headlineAppearance" : "Izgled", 163 "settings.app.headlineAppearance" : "Izgled",
145 "settings.app.headlineGeneral" : "Općenito", 164 "settings.app.headlineGeneral" : "Općenito",
146 "settings.app.headlineLanguage" : "Jezik", 165 "settings.app.headlineLanguage" : "Jezik",
147 "settings.app.headlineUpdates" : "Nadogradnje", 166 "settings.app.headlineUpdates" : "Nadogradnje",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Promjene postavki zahtijevaju ponovni pogon", 168 "settings.app.restartRequired" : "Promjene postavki zahtijevaju ponovni pogon",
149 "settings.app.subheadlineCache" : "Кеш", 169 "settings.app.subheadlineCache" : "Кеш",
150 "settings.app.translationHelp" : "Pomozite nam prevesti aplikaciju na Vaš jezik. ", 170 "settings.app.translationHelp" : "Pomozite nam prevesti aplikaciju na Vaš jezik. ",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Позови пријатеље", 177 "settings.navigation.inviteFriends" : "Позови пријатеље",
158 "settings.navigation.logout" : "Odjava", 178 "settings.navigation.logout" : "Odjava",
159 "settings.navigation.settings" : "Postavke", 179 "settings.navigation.settings" : "Postavke",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Vaše usluge", 181 "settings.navigation.yourServices" : "Vaše usluge",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Sve usluge", 183 "settings.recipes.all" : "Sve usluge",
162 "settings.recipes.dev" : "Razvoj", 184 "settings.recipes.dev" : "Razvoj",
163 "settings.recipes.headline" : "Dostupne usluge", 185 "settings.recipes.headline" : "Dostupne usluge",
@@ -201,8 +223,6 @@
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "User (optional)",
203 "settings.service.form.saveButton" : "SaÄuvaj uslugu\/e", 225 "settings.service.form.saveButton" : "SaÄuvaj uslugu\/e",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Hostovano", 226 "settings.service.form.tabHosted" : "Hostovano",
207 "settings.service.form.tabOnPremise" : "Samo-hostovano â­ï¸", 227 "settings.service.form.tabOnPremise" : "Samo-hostovano â­ï¸",
208 "settings.service.form.team" : "Tim", 228 "settings.service.form.team" : "Tim",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Pronađite usluge", 232 "settings.services.discoverServices" : "Pronađite usluge",
213 "settings.services.headline" : "Vaše usluge", 233 "settings.services.headline" : "Vaše usluge",
214 "settings.services.noServicesAdded" : "Još uvijek niste unijeli niti jednu uslugu.", 234 "settings.services.noServicesAdded" : "Još uvijek niste unijeli niti jednu uslugu.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Usluga je onemogućena.", 236 "settings.services.tooltip.isDisabled" : "Usluga je onemogućena.",
216 "settings.services.tooltip.isMuted" : "Svi zvukovi su onemogućeni.", 237 "settings.services.tooltip.isMuted" : "Svi zvukovi su onemogućeni.",
217 "settings.services.tooltip.notificationsDisabled" : "Obavijesti su onemogućene.", 238 "settings.services.tooltip.notificationsDisabled" : "Obavijesti su onemogućene.",
218 "settings.services.updatedInfo" : "Vaše promjene su pohranjene.", 239 "settings.services.updatedInfo" : "Vaše promjene su pohranjene.",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Tim",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Tvrtka", 246 "settings.user.form.accountType.company" : "Tvrtka",
220 "settings.user.form.accountType.individual" : "Pojedinac", 247 "settings.user.form.accountType.individual" : "Pojedinac",
221 "settings.user.form.accountType.label" : "Tip raÄuna", 248 "settings.user.form.accountType.label" : "Tip raÄuna",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Ime", 252 "settings.user.form.firstname" : "Ime",
226 "settings.user.form.lastname" : "Prezime", 253 "settings.user.form.lastname" : "Prezime",
227 "settings.user.form.newPassword" : "Nova lozinka", 254 "settings.user.form.newPassword" : "Nova lozinka",
255 "settings.workspace.add.form.name" : "Ime",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Ime",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Pokušajte ponovno",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Dodajte novu uslugu", 270 "sidebar.addNewService" : "Dodajte novu uslugu",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Онемогући обавештења и звукове", 272 "sidebar.muteApp" : "Онемогући обавештења и звукове",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Postavke", 274 "sidebar.settings" : "Postavke",
231 "sidebar.unmuteApp" : "ИÑкључи обавештења и звукове", 275 "sidebar.unmuteApp" : "ИÑкључи обавештења и звукове",
232 "signup.company.label" : "Tvrtka", 276 "signup.company.label" : "Tvrtka",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "EU državljani, upozerenje: Moguće taksiranje", 288 "subscription.euTaxInfo" : "EU državljani, upozerenje: Moguće taksiranje",
245 "subscription.features.ads" : "Bez reklama, doživotno!", 289 "subscription.features.ads" : "Bez reklama, doživotno!",
246 "subscription.features.comingSoon" : "Dolazi uskoro", 290 "subscription.features.comingSoon" : "Dolazi uskoro",
247 "subscription.features.encryptedSync" : "Kodirano usklađivanje sesija.",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 291 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license",
249 "subscription.features.onpremise" : "Dodajte pretpostavljeni\/hostirani servis kao Å¡to ima usluga HipChat",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 292 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services", 293 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "Support for spellchecker", 294 "subscription.features.spellchecker" : "Support for spellchecker",
295 "subscription.features.workspaces" : "Organize your services in workspaces",
253 "subscription.includedFeatures" : "Plaćeni\/Premium raÄun ukljuÄuje sljedeće:", 296 "subscription.includedFeatures" : "Plaćeni\/Premium raÄun ukljuÄuje sljedeće:",
254 "subscription.paymentSessionError" : "Nemoguće inicijalizirati obrazac za uplatu", 297 "subscription.paymentSessionError" : "Nemoguće inicijalizirati obrazac za uplatu",
255 "subscription.submit.label" : "Želim da podržim razvoj Franca.", 298 "subscription.submit.label" : "Želim da podržim razvoj Franca.",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Ponovno uÄitavanje", 312 "tabs.item.reload" : "Ponovno uÄitavanje",
270 "validation.email" : "{поље} није валидно", 313 "validation.email" : "{поље} није валидно",
271 "validation.minLength" : "{поље} треба да буде најмање {дужина} карактера дугачко", 314 "validation.minLength" : "{поље} треба да буде најмање {дужина} карактера дугачко",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{поље} је неопходно", 316 "validation.required" : "{поље} је неопходно",
273 "validation.url" : "{field} није валидан УРЛ", 317 "validation.url" : "{field} није валидан УРЛ",
274 "welcome.loginButton" : "Prijavite se na raÄun", 318 "welcome.loginButton" : "Prijavite se na raÄun",
275 "welcome.signupButton" : "Stvorite novi korisniÄki raÄun", 319 "welcome.signupButton" : "Stvorite novi korisniÄki raÄun",
276 "welcome.slogan" : "Poruke koje su stvorene za tebe" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Sve usluge",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/tr.json b/src/i18n/locales/tr.json
index 9e7619454..69c5ede37 100644
--- a/src/i18n/locales/tr.json
+++ b/src/i18n/locales/tr.json
@@ -1,13 +1,25 @@
1{ 1{
2 "app.errorHandler.action" : "Yeniden Yükle", 2 "app.errorHandler.action" : "Tekrar Yükle",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "Bir terslik çıktı",
4 "feature.delayApp.action" : "Franz Destek Lisansı'nı alın.", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Beklememek için Franz Destek Lisansı'nı satın alın.", 5 "feature.delayApp.action" : "Franz Destek Lisansı'nı alın",
6 "feature.delayApp.headline" : "Beklememek için Franz Destek Lisansı'nı satın alın",
6 "feature.delayApp.text" : "Franz {seconds} saniye sonra devam edecek.", 7 "feature.delayApp.text" : "Franz {seconds} saniye sonra devam edecek.",
7 "global.api.unhealthy" : "Franz hizmetlerine şu anda erişilemiyor.", 8 "feature.shareFranz.action.email" : "Mail olarak gönder",
9 "feature.shareFranz.action.facebook" : "Facebook'ta PaylaÅŸ",
10 "feature.shareFranz.action.twitter" : "Twitter'da PaylaÅŸ",
11 "feature.shareFranz.headline" : "Franz birlikte daha iyi!",
12 "feature.shareFranz.shareText.email" : "Franz'a {count} tane servis ekledim! WhatsApp, Messenger, Slack ve fazlasını içeren ücretsiz uygulamayı www.meetfranz.com adresinden edinin.",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Arkadaşlarına ve meslektaşlarına Franz'ın ne kadar harika olduğunu söyle ve bize bu kelimeyi yaymamızda yardım et.",
15 "global.api.unhealthy" : "Franz hizmetlerine ÅŸu anda eriÅŸilemiyor",
8 "global.notConnectedToTheInternet" : "İnternete bağlı değilsiniz.", 16 "global.notConnectedToTheInternet" : "İnternete bağlı değilsiniz.",
9 "import.headline" : "Franz 4 servislerinizi ekleyin.", 17 "global.spellchecker.useDefault" : "Sistem Dilini Kullan ({default})",
10 "import.notSupportedHeadline" : "Servisler henüz Franz 5'te desteklenmiyor.", 18 "global.spellchecking.autodetect" : "Dili otomatik tespit et",
19 "global.spellchecking.autodetect.short" : "Otomatik",
20 "global.spellchecking.language" : "Ä°mla kontrol dili",
21 "import.headline" : "Franz 4 servislerinizi içeri aktarın",
22 "import.notSupportedHeadline" : "Henüz Franz 5'te desteklenmeyen servisler",
11 "import.skip.label" : "Servisleri kendim eklemek istiyorum", 23 "import.skip.label" : "Servisleri kendim eklemek istiyorum",
12 "import.submit.label" : "Servisleri içe aktar", 24 "import.submit.label" : "Servisleri içe aktar",
13 "infobar.buttonChangelog" : "Yeni ne var?", 25 "infobar.buttonChangelog" : "Yeni ne var?",
@@ -15,7 +27,7 @@
15 "infobar.buttonReloadServices" : "Hizmetleri yeniden yükle", 27 "infobar.buttonReloadServices" : "Hizmetleri yeniden yükle",
16 "infobar.requiredRequestsFailed" : "Hizmetler ve kullanıcı bilgileri yüklenemedi", 28 "infobar.requiredRequestsFailed" : "Hizmetler ve kullanıcı bilgileri yüklenemedi",
17 "infobar.servicesUpdated" : "Hizmetleriniz güncellendi.", 29 "infobar.servicesUpdated" : "Hizmetleriniz güncellendi.",
18 "infobar.updateAvailable" : "Yeni Franz güncellemesi mevcut", 30 "infobar.updateAvailable" : "Yeni Franz güncellemesi mevcut.",
19 "invite.email.label" : "E-posta adresi", 31 "invite.email.label" : "E-posta adresi",
20 "invite.headline.friends" : "3 arkadaşını ya da çalışma arkadaşını davet et", 32 "invite.headline.friends" : "3 arkadaşını ya da çalışma arkadaşını davet et",
21 "invite.name.label" : "Ad", 33 "invite.name.label" : "Ad",
@@ -32,6 +44,7 @@
32 "login.submit.label" : "Oturum Aç", 44 "login.submit.label" : "Oturum Aç",
33 "login.tokenExpired" : "Oturum zaman aşımına uğradı, lütfen tekrar giriş yapın.", 45 "login.tokenExpired" : "Oturum zaman aşımına uğradı, lütfen tekrar giriş yapın.",
34 "menu.app.about" : "Franz Hakkında", 46 "menu.app.about" : "Franz Hakkında",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Gizle", 48 "menu.app.hide" : "Gizle",
36 "menu.app.hideOthers" : "DiÄŸerlerini Gizle", 49 "menu.app.hideOthers" : "DiÄŸerlerini Gizle",
37 "menu.app.quit" : "Çıkış", 50 "menu.app.quit" : "Çıkış",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Destek", 72 "menu.help.support" : "Destek",
60 "menu.help.tos" : "Kullanım Şartları", 73 "menu.help.tos" : "Kullanım Şartları",
61 "menu.services" : "Hizmetler", 74 "menu.services" : "Hizmetler",
62 "menu.services.addNewService" : "Yeni Servis Ekle", 75 "menu.services.activatePreviousService" : "Activate previous service",
76 "menu.services.addNewService" : "Yeni servis ekle...",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "Görünüm", 78 "menu.view" : "Görünüm",
64 "menu.view.enterFullScreen" : "Tam Ekrana Geç", 79 "menu.view.enterFullScreen" : "Tam Ekrana Geç",
65 "menu.view.exitFullScreen" : "Tam Ekrandan Çık", 80 "menu.view.exitFullScreen" : "Tam Ekrandan Çık",
@@ -74,6 +89,11 @@
74 "menu.window" : "Pencere", 89 "menu.window" : "Pencere",
75 "menu.window.close" : "Kapat", 90 "menu.window.close" : "Kapat",
76 "menu.window.minimize" : "Simge Durumuna Küçült", 91 "menu.window.minimize" : "Simge Durumuna Küçült",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Tüm servisler",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "E-posta adresi", 97 "password.email.label" : "E-posta adresi",
78 "password.headline" : "Parola sıfırla", 98 "password.headline" : "Parola sıfırla",
79 "password.link.login" : "Hesabına giriş yap", 99 "password.link.login" : "Hesabına giriş yap",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Bu e-posta adresinde bir kullanıcı bulunamadı", 101 "password.noUser" : "Bu e-posta adresinde bir kullanıcı bulunamadı",
82 "password.submit.label" : "Gönder", 102 "password.submit.label" : "Gönder",
83 "password.successInfo" : "E-postanızı kontrol ediniz", 103 "password.successInfo" : "E-postanızı kontrol ediniz",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Hesabı Yükselt",
85 "pricing.headline" : "Franz'ı Destekle", 105 "pricing.headline" : "Franz'ı Destekle",
86 "pricing.link.skipPayment" : "Franz'ın gelişimini desteklemek istemiyorum.", 106 "pricing.link.skipPayment" : "Franz'ın gelişimini desteklemek istemiyorum.",
87 "pricing.submit.label" : "Franz'ın gelişimini desteklemek istiyorum", 107 "pricing.submit.label" : "Franz'ın gelişimini desteklemek istiyorum",
@@ -92,11 +112,12 @@
92 "service.crashHandler.text" : "{name} bir hataya neden oldu.", 112 "service.crashHandler.text" : "{name} bir hataya neden oldu.",
93 "service.disabledHandler.action" : "{name} aktif", 113 "service.disabledHandler.action" : "{name} aktif",
94 "service.disabledHandler.headline" : "{name} devredışı", 114 "service.disabledHandler.headline" : "{name} devredışı",
95 "service.errorHandler.action" : "{name} yeniden yükle", 115 "service.errorHandler.action" : "{İsim} Yeniden Yükle",
96 "service.errorHandler.editAction" : "{name} düzenle", 116 "service.errorHandler.editAction" : "{name} düzenle",
97 "service.errorHandler.headline" : "Aman Tanrım hayır!", 117 "service.errorHandler.headline" : "Hayııırrr!",
98 "service.errorHandler.message" : "Hata", 118 "service.errorHandler.message" : "Hata",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} yüklenemedi.",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Haydi başlayalım", 121 "services.getStarted" : "Haydi başlayalım",
101 "services.welcome" : "Franz'a HoÅŸgeldiniz", 122 "services.welcome" : "Franz'a HoÅŸgeldiniz",
102 "settings.account.account.editButton" : "Hesabı düzenle", 123 "settings.account.account.editButton" : "Hesabı düzenle",
@@ -117,8 +138,9 @@
117 "settings.account.invoiceDownload" : "Ä°ndir", 138 "settings.account.invoiceDownload" : "Ä°ndir",
118 "settings.account.manageSubscription.label" : "Aboneliğini yönet", 139 "settings.account.manageSubscription.label" : "Aboneliğini yönet",
119 "settings.account.successInfo" : "DeÄŸiÅŸikliklerin kaydedildi", 140 "settings.account.successInfo" : "DeÄŸiÅŸikliklerin kaydedildi",
141 "settings.account.tryReloadServices" : "Tekrar deneyin",
120 "settings.account.tryReloadUserInfoRequest" : "Tekrar deneyin", 142 "settings.account.tryReloadUserInfoRequest" : "Tekrar deneyin",
121 "settings.account.userInfoRequestFailed" : "Kullanıcı bilgisi yüklenemedi.", 143 "settings.account.userInfoRequestFailed" : "Kullanıcı bilgisi yüklenemedi",
122 "settings.app.buttonClearAllCache" : "Önbelleği temizle", 144 "settings.app.buttonClearAllCache" : "Önbelleği temizle",
123 "settings.app.buttonInstallUpdate" : "Yeniden Başlat ve Güncelleştirmeleri Kur", 145 "settings.app.buttonInstallUpdate" : "Yeniden Başlat ve Güncelleştirmeleri Kur",
124 "settings.app.buttonSearchForUpdate" : "Güncellemeleri kontrol et", 146 "settings.app.buttonSearchForUpdate" : "Güncellemeleri kontrol et",
@@ -127,24 +149,22 @@
127 "settings.app.form.autoLaunchInBackground" : "Arka planda aç", 149 "settings.app.form.autoLaunchInBackground" : "Arka planda aç",
128 "settings.app.form.autoLaunchOnStart" : "Franz'ı başlangıçta aç", 150 "settings.app.form.autoLaunchOnStart" : "Franz'ı başlangıçta aç",
129 "settings.app.form.beta" : "Beta versiyonları dahil et", 151 "settings.app.form.beta" : "Beta versiyonları dahil et",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Karanlık tarafa katıl",
131 "settings.app.form.enableGPUAcceleration" : "Grafik İşlemci Ünitesi (GPU) Hızlandırıcısını Aktif et", 153 "settings.app.form.enableGPUAcceleration" : "Grafik İşlemci Ünitesi (GPU) Hızlandırıcısını Aktif et",
132 "settings.app.form.enableMenuBar" : "Menü çubuğunda Franz'ı göster",
133 "settings.app.form.enableSpellchecking" : "Yazım denetimini etkinleştir", 154 "settings.app.form.enableSpellchecking" : "Yazım denetimini etkinleştir",
134 "settings.app.form.enableSystemTray" : "Franz'ı sistem tepsisinde göster", 155 "settings.app.form.enableSystemTray" : "Franz'ı sistem tepsisinde göster",
135 "settings.app.form.hideDockIcon" : "Franz Simgesini Gösterme",
136 "settings.app.form.language" : "Dil", 156 "settings.app.form.language" : "Dil",
137 "settings.app.form.minimizeToSystemTray" : "Franz'ı sistem tepsisine küçült", 157 "settings.app.form.minimizeToSystemTray" : "Franz'ı sistem tepsisine küçült",
138 "settings.app.form.runInBackground" : "Pencereyi kapatırken Franz'ı arka planda tut", 158 "settings.app.form.runInBackground" : "Pencereyi kapatırken Franz'ı arka planda tut",
139 "settings.app.form.showDisabledServices" : "Devre dışı bırakılan servis sekmelerini göster", 159 "settings.app.form.showDisabledServices" : "Devre dışı bırakılan servis sekmelerini göster",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Bildirimler kapalı iken okunmamış mesaj sayısını göster", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Bildirimler kapalı iken okunmamış mesaj sayısını göster",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "Ayarlar", 161 "settings.app.headline" : "Ayarlar",
143 "settings.app.headlineAdvanced" : "GeliÅŸmiÅŸ", 162 "settings.app.headlineAdvanced" : "GeliÅŸmiÅŸ",
144 "settings.app.headlineAppearance" : "Görünüm", 163 "settings.app.headlineAppearance" : "Görünüm",
145 "settings.app.headlineGeneral" : "Genel", 164 "settings.app.headlineGeneral" : "Genel",
146 "settings.app.headlineLanguage" : "Dil", 165 "settings.app.headlineLanguage" : "Dil",
147 "settings.app.headlineUpdates" : "Güncellemeler", 166 "settings.app.headlineUpdates" : "Güncellemeler",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Değişiklikler yeniden başlatmayı gerektiriyor", 168 "settings.app.restartRequired" : "Değişiklikler yeniden başlatmayı gerektiriyor",
149 "settings.app.subheadlineCache" : "Önbellek", 169 "settings.app.subheadlineCache" : "Önbellek",
150 "settings.app.translationHelp" : "Franz'ı senin diline tercüme etmemiz için yardım et.", 170 "settings.app.translationHelp" : "Franz'ı senin diline tercüme etmemiz için yardım et.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "Arkadaşlarını Davet Et", 177 "settings.navigation.inviteFriends" : "Arkadaşlarını Davet Et",
158 "settings.navigation.logout" : "Çıkış", 178 "settings.navigation.logout" : "Çıkış",
159 "settings.navigation.settings" : "Ayarlar", 179 "settings.navigation.settings" : "Ayarlar",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Servislerin", 181 "settings.navigation.yourServices" : "Servislerin",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Tüm servisler", 183 "settings.recipes.all" : "Tüm servisler",
162 "settings.recipes.dev" : "GeliÅŸtirme", 184 "settings.recipes.dev" : "GeliÅŸtirme",
163 "settings.recipes.headline" : "Mevcut servisler", 185 "settings.recipes.headline" : "Mevcut servisler",
@@ -168,7 +190,7 @@
168 "settings.searchService" : "Hizmeti ara", 190 "settings.searchService" : "Hizmeti ara",
169 "settings.service.error.goBack" : "Servislere geri dön", 191 "settings.service.error.goBack" : "Servislere geri dön",
170 "settings.service.error.headline" : "Hata", 192 "settings.service.error.headline" : "Hata",
171 "settings.service.error.message" : "Servis tarifi yüklenemedi", 193 "settings.service.error.message" : "Servis tarifi yüklenemedi.",
172 "settings.service.form.addServiceHeadline" : "{name} Ekle", 194 "settings.service.form.addServiceHeadline" : "{name} Ekle",
173 "settings.service.form.availableServices" : "Mevcut servisler", 195 "settings.service.form.availableServices" : "Mevcut servisler",
174 "settings.service.form.customUrl" : "Özel sunucu", 196 "settings.service.form.customUrl" : "Özel sunucu",
@@ -176,10 +198,10 @@
176 "settings.service.form.customUrlUpgradeAccount" : "Hesabını yükselt", 198 "settings.service.form.customUrlUpgradeAccount" : "Hesabını yükselt",
177 "settings.service.form.customUrlValidationError" : "{name} özel sunucu doğrulanamadı.", 199 "settings.service.form.customUrlValidationError" : "{name} özel sunucu doğrulanamadı.",
178 "settings.service.form.deleteButton" : "Servisi sil", 200 "settings.service.form.deleteButton" : "Servisi sil",
179 "settings.service.form.editServiceHeadline" : "{name} düzenle", 201 "settings.service.form.editServiceHeadline" : "{İsim} Düzenle",
180 "settings.service.form.enableAudio" : "Sesi etkinleÅŸtirin", 202 "settings.service.form.enableAudio" : "Sesi etkinleÅŸtirin",
181 "settings.service.form.enableBadge" : "Okunmamış mesajları göster", 203 "settings.service.form.enableBadge" : "Okunmamış mesajları göster",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Karanlık modu aç",
183 "settings.service.form.enableNotification" : "Bildirimleri etkinleÅŸtir", 205 "settings.service.form.enableNotification" : "Bildirimleri etkinleÅŸtir",
184 "settings.service.form.enableService" : "Servisi etkinleÅŸtir", 206 "settings.service.form.enableService" : "Servisi etkinleÅŸtir",
185 "settings.service.form.headlineBadges" : "Okunmamış mesajlar", 207 "settings.service.form.headlineBadges" : "Okunmamış mesajlar",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Mesaj rozetini tüm yeni mesajlar için göster", 214 "settings.service.form.indirectMessages" : "Mesaj rozetini tüm yeni mesajlar için göster",
193 "settings.service.form.isMutedInfo" : "Devre dışı bırakıldığında, tüm bildirim sesleri sessize alınır", 215 "settings.service.form.isMutedInfo" : "Devre dışı bırakıldığında, tüm bildirim sesleri sessize alınır",
194 "settings.service.form.name" : "Ä°sim", 216 "settings.service.form.name" : "Ä°sim",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Ayarları",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "Proxy Sunucusu\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "Proxy ayarları Franz serverlarına yüklenmeyecektir.",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "Proxy Kullan",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Parola (opsiyonel)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Port",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Proxy ayarlarını değiştirdikten sonra Franz'ı yeniden başlatınız.",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "Kullanıcı (opsiyonel)",
203 "settings.service.form.saveButton" : "Servisi kaydet", 225 "settings.service.form.saveButton" : "Servisi kaydet",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Barındırılan", 226 "settings.service.form.tabHosted" : "Barındırılan",
207 "settings.service.form.tabOnPremise" : "Kendi barındırılan", 227 "settings.service.form.tabOnPremise" : "Kendi barındırılan",
208 "settings.service.form.team" : "Takım", 228 "settings.service.form.team" : "Takım",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Servisleri keÅŸfet", 232 "settings.services.discoverServices" : "Servisleri keÅŸfet",
213 "settings.services.headline" : "Servislerin", 233 "settings.services.headline" : "Servislerin",
214 "settings.services.noServicesAdded" : "Henüz hiç servis eklemedin.", 234 "settings.services.noServicesAdded" : "Henüz hiç servis eklemedin.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Servis devre dışı", 236 "settings.services.tooltip.isDisabled" : "Servis devre dışı",
216 "settings.services.tooltip.isMuted" : "Tüm sesler kapalı", 237 "settings.services.tooltip.isMuted" : "Tüm sesler kapalı",
217 "settings.services.tooltip.notificationsDisabled" : "Bildirimler devre dışı", 238 "settings.services.tooltip.notificationsDisabled" : "Bildirimler devre dışı",
218 "settings.services.updatedInfo" : "DeÄŸiÅŸikliklerin kaydedildi", 239 "settings.services.updatedInfo" : "DeÄŸiÅŸikliklerin kaydedildi",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Takım",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "Kurum", 246 "settings.user.form.accountType.company" : "Kurum",
220 "settings.user.form.accountType.individual" : "Bireysel", 247 "settings.user.form.accountType.individual" : "Bireysel",
221 "settings.user.form.accountType.label" : "Hesap tipi", 248 "settings.user.form.accountType.label" : "Hesap tipi",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Ad", 252 "settings.user.form.firstname" : "Ad",
226 "settings.user.form.lastname" : "Soyad", 253 "settings.user.form.lastname" : "Soyad",
227 "settings.user.form.newPassword" : "Yeni ÅŸifre", 254 "settings.user.form.newPassword" : "Yeni ÅŸifre",
255 "settings.workspace.add.form.name" : "Name",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Name",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Tekrar deneyin",
266 "settings.workspaces.updatedInfo" : "DeÄŸiÅŸikliklerin kaydedildi",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Yeni servis ekle", 270 "sidebar.addNewService" : "Yeni servis ekle",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Bildirimleri ve sesli uyarıları kapat", 272 "sidebar.muteApp" : "Bildirimleri ve sesli uyarıları kapat",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "Ayarlar", 274 "sidebar.settings" : "Ayarlar",
231 "sidebar.unmuteApp" : "Bildirimleri ve sesli uyarıları etkinleştir", 275 "sidebar.unmuteApp" : "Bildirimleri ve sesli uyarıları etkinleştir",
232 "signup.company.label" : "Kurum", 276 "signup.company.label" : "Kurum",
@@ -238,18 +282,17 @@
238 "signup.legal.info" : "Franz'ı hesabı oluşturark kabul ediyorsun", 282 "signup.legal.info" : "Franz'ı hesabı oluşturark kabul ediyorsun",
239 "signup.legal.privacy" : "Gizlilik Sözleşmesi", 283 "signup.legal.privacy" : "Gizlilik Sözleşmesi",
240 "signup.legal.terms" : "Kullanım Koşulları", 284 "signup.legal.terms" : "Kullanım Koşulları",
241 "signup.link.login" : "Mevcut hesabınla giriş yap.", 285 "signup.link.login" : "Hali hazırda hesabınız varsa giriş yapmak ister misiniz?",
242 "signup.password.label" : "Åžifre", 286 "signup.password.label" : "Åžifre",
243 "signup.submit.label" : "Hesap oluÅŸtur", 287 "signup.submit.label" : "Hesap oluÅŸtur",
244 "subscription.euTaxInfo" : "AB vatandaşları: yerel satış vergileri uygulanabilir", 288 "subscription.euTaxInfo" : "AB vatandaşları: yerel satış vergileri uygulanabilir",
245 "subscription.features.ads" : "Reklam yok, asla!", 289 "subscription.features.ads" : "Reklam yok, asla!",
246 "subscription.features.comingSoon" : "yakında geliyor", 290 "subscription.features.comingSoon" : "yakında geliyor",
247 "subscription.features.encryptedSync" : "Şifreli oturum senkronizasyonu", 291 "subscription.features.noInterruptions" : "Uygulama gecikmeleri & yükseltme lisanları için dırdır yok",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "Mattermost gibi şirket-içi\/barındırılan servisler ekleyin",
249 "subscription.features.onpremise" : "HipChat gibi kurum içi\/barındırılan hizmetler ekle", 293 "subscription.features.proxy" : "Servisler için proxy desteği",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Yazım denetleyicisi desteği",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Ücretli Franz Premium Destekçi Hesabına dahil", 296 "subscription.includedFeatures" : "Ücretli Franz Premium Destekçi Hesabına dahil",
254 "subscription.paymentSessionError" : "Ödeme formu başlatılamadı", 297 "subscription.paymentSessionError" : "Ödeme formu başlatılamadı",
255 "subscription.submit.label" : "Franz'ın gelişimini desteklemek istiyorum", 298 "subscription.submit.label" : "Franz'ın gelişimini desteklemek istiyorum",
@@ -266,12 +309,23 @@
266 "tabs.item.enableAudio" : "Sesi etkinleÅŸtir", 309 "tabs.item.enableAudio" : "Sesi etkinleÅŸtir",
267 "tabs.item.enableNotification" : "Bildirimleri etkinleÅŸtir", 310 "tabs.item.enableNotification" : "Bildirimleri etkinleÅŸtir",
268 "tabs.item.enableService" : "Servisi etkinleÅŸtir", 311 "tabs.item.enableService" : "Servisi etkinleÅŸtir",
269 "tabs.item.reload" : "Yeniden Yükle", 312 "tabs.item.reload" : "Tekrar yükle",
270 "validation.email" : "{alan} geçerli değil", 313 "validation.email" : "{alan} geçerli değil",
271 "validation.minLength" : "{field} en az {length} karakter uzunluğunda olmalı", 314 "validation.minLength" : "{field} en az {length} karakter uzunluğunda olmalı",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} gereklidir", 316 "validation.required" : "{field} gereklidir",
273 "validation.url" : "{field} geçerli bir URL değil", 317 "validation.url" : "{field} geçerli bir URL değil",
274 "welcome.loginButton" : "Hesabına giriş yap", 318 "welcome.loginButton" : "Hesabına giriş yap",
275 "welcome.signupButton" : "Ãœcretsiz hesap oluÅŸtur", 319 "welcome.signupButton" : "Ãœcretsiz hesap oluÅŸtur",
276 "welcome.slogan" : "Sizin için çalışan mesajlaşma" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Tüm servisler",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/uk.json b/src/i18n/locales/uk.json
index 7d51b380e..113665f5f 100644
--- a/src/i18n/locales/uk.json
+++ b/src/i18n/locales/uk.json
@@ -1,13 +1,25 @@
1{ 1{
2 "app.errorHandler.action" : "Перезавантажити", 2 "app.errorHandler.action" : "Перезавантажити",
3 "app.errorHandler.headline" : "Something went wrong", 3 "app.errorHandler.headline" : "ЩоÑÑŒ пішло не так",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "Отримати ліцензію Franz Supporter ",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "Будь лаÑка, придбайте ліцензію Franz Supporter аби пропуÑтити очікуваннÑ",
7 "global.api.unhealthy" : "Ðе можна підключитиÑÑŒ до онлайн ÑервіÑів Franz", 7 "feature.delayApp.text" : "Franz відновить роботу за {seconds} Ñекунд",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
15 "global.api.unhealthy" : "Ðе можливо підключитиÑÑŒ до онлайн ÑервіÑів Franz",
8 "global.notConnectedToTheInternet" : "Ви не підключені до Інтернету.", 16 "global.notConnectedToTheInternet" : "Ви не підключені до Інтернету.",
17 "global.spellchecker.useDefault" : "ВикориÑтовувати ÑиÑтемні параметри за змовчуваннÑм ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "Мова перевірки правопиÑу",
9 "import.headline" : "Імпортувати ваші ÑервіÑи з Franz 4", 21 "import.headline" : "Імпортувати ваші ÑервіÑи з Franz 4",
10 "import.notSupportedHeadline" : "СервіÑи ще не підтримуютьÑÑ Ð² Franz 5", 22 "import.notSupportedHeadline" : "Ðаразі ÑервіÑи не підтримуютьÑÑ Ñƒ Franz 5",
11 "import.skip.label" : "Я бажаю додати ÑÐµÑ€Ð²Ñ–Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ", 23 "import.skip.label" : "Я бажаю додати ÑÐµÑ€Ð²Ñ–Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ",
12 "import.submit.label" : "Імпортувати ÑервіÑи", 24 "import.submit.label" : "Імпортувати ÑервіÑи",
13 "infobar.buttonChangelog" : "Що нового?", 25 "infobar.buttonChangelog" : "Що нового?",
@@ -17,21 +29,22 @@
17 "infobar.servicesUpdated" : "Ваші ÑервіÑи було оновлено.", 29 "infobar.servicesUpdated" : "Ваші ÑервіÑи було оновлено.",
18 "infobar.updateAvailable" : "Ðове Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Franz доÑтупне.", 30 "infobar.updateAvailable" : "Ðове Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Franz доÑтупне.",
19 "invite.email.label" : "Email адреÑа", 31 "invite.email.label" : "Email адреÑа",
20 "invite.headline.friends" : "ЗапроÑÑ–Ñ‚ÑŒ 3 ваших друзів або колег", 32 "invite.headline.friends" : "ЗапроÑÑ–Ñ‚ÑŒ 3-Ñ… ваших друзів або колег",
21 "invite.name.label" : "Ім'Ñ", 33 "invite.name.label" : "Ім'Ñ",
22 "invite.skip.label" : "Я хочу зробити це пізніше", 34 "invite.skip.label" : "Я хочу зробити це пізніше",
23 "invite.submit.label" : "Відправити запрошеннÑ", 35 "invite.submit.label" : "Відправити запрошеннÑ",
24 "invite.successInfo" : "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно відоÑлані", 36 "invite.successInfo" : "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно надіÑлані",
25 "login.email.label" : "Email адреÑа", 37 "login.email.label" : "Email адреÑа",
26 "login.headline" : "Увійти", 38 "login.headline" : "Увійти",
27 "login.invalidCredentials" : "Email або пароль некоректні", 39 "login.invalidCredentials" : "Email або пароль некоректні",
28 "login.link.password" : "Скинути пароль", 40 "login.link.password" : "Скинути пароль",
29 "login.link.signup" : "Створити безплатний акаунт", 41 "login.link.signup" : "Створити безплатний акаунт",
30 "login.password.label" : "Пароль", 42 "login.password.label" : "Пароль",
31 "login.serverLogout" : "Ваша ÑеÑÑ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ, будь лаÑка, зайдіть знову.", 43 "login.serverLogout" : "Ваша ÑеÑÑ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ, будь лаÑка, увійдіть знову.",
32 "login.submit.label" : "Увійти", 44 "login.submit.label" : "Увійти",
33 "login.tokenExpired" : "Ваша ÑеÑÑ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ, будь лаÑка, зайдіть знову.", 45 "login.tokenExpired" : "Ваша ÑеÑÑ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ, будь лаÑка, увійдіть знову.",
34 "menu.app.about" : "Про Franz", 46 "menu.app.about" : "Про Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "Приховати", 48 "menu.app.hide" : "Приховати",
36 "menu.app.hideOthers" : "Приховати інші", 49 "menu.app.hideOthers" : "Приховати інші",
37 "menu.app.quit" : "Вийти", 50 "menu.app.quit" : "Вийти",
@@ -59,7 +72,9 @@
59 "menu.help.support" : "Підтримка", 72 "menu.help.support" : "Підтримка",
60 "menu.help.tos" : "Умови викориÑтаннÑ", 73 "menu.help.tos" : "Умови викориÑтаннÑ",
61 "menu.services" : "Служби", 74 "menu.services" : "Служби",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "Додати ÑервіÑ", 76 "menu.services.addNewService" : "Додати ÑервіÑ",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "ВиглÑд", 78 "menu.view" : "ВиглÑд",
64 "menu.view.enterFullScreen" : "Вікно на повний екран", 79 "menu.view.enterFullScreen" : "Вікно на повний екран",
65 "menu.view.exitFullScreen" : "Вийти з повного екрану", 80 "menu.view.exitFullScreen" : "Вийти з повного екрану",
@@ -74,6 +89,11 @@
74 "menu.window" : "Вікно", 89 "menu.window" : "Вікно",
75 "menu.window.close" : "Закрити", 90 "menu.window.close" : "Закрити",
76 "menu.window.minimize" : "Згорнути", 91 "menu.window.minimize" : "Згорнути",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "Ð’ÑÑ– ÑервіÑи",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "Email адреÑа", 97 "password.email.label" : "Email адреÑа",
78 "password.headline" : "Скинути пароль", 98 "password.headline" : "Скинути пароль",
79 "password.link.login" : "Увійти до вашого акаунту", 99 "password.link.login" : "Увійти до вашого акаунту",
@@ -81,7 +101,7 @@
81 "password.noUser" : "Ðе знайдено жодного кориÑтувача з цією email адреÑою", 101 "password.noUser" : "Ðе знайдено жодного кориÑтувача з цією email адреÑою",
82 "password.submit.label" : "Подати", 102 "password.submit.label" : "Подати",
83 "password.successInfo" : "Будь лаÑка, перевірте ваш email", 103 "password.successInfo" : "Будь лаÑка, перевірте ваш email",
84 "premiumFeature.button.upgradeAccount" : "Upgrade account", 104 "premiumFeature.button.upgradeAccount" : "Преміум акаунт",
85 "pricing.headline" : "Підтримайте Franz", 105 "pricing.headline" : "Підтримайте Franz",
86 "pricing.link.skipPayment" : "Я не хочу підтримувати розробку Franz.", 106 "pricing.link.skipPayment" : "Я не хочу підтримувати розробку Franz.",
87 "pricing.submit.label" : "Я хочу підтримати розробку Franz", 107 "pricing.submit.label" : "Я хочу підтримати розробку Franz",
@@ -96,7 +116,8 @@
96 "service.errorHandler.editAction" : "Редагувати {name}", 116 "service.errorHandler.editAction" : "Редагувати {name}",
97 "service.errorHandler.headline" : "О, ні!", 117 "service.errorHandler.headline" : "О, ні!",
98 "service.errorHandler.message" : "Помилка", 118 "service.errorHandler.message" : "Помилка",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} не завантажено",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "Почати", 121 "services.getStarted" : "Почати",
101 "services.welcome" : "ЛаÑкаво проÑимо в Franz", 122 "services.welcome" : "ЛаÑкаво проÑимо в Franz",
102 "settings.account.account.editButton" : "Редагувати акаунт", 123 "settings.account.account.editButton" : "Редагувати акаунт",
@@ -117,6 +138,7 @@
117 "settings.account.invoiceDownload" : "Завантажити", 138 "settings.account.invoiceDownload" : "Завантажити",
118 "settings.account.manageSubscription.label" : "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾ÑŽ підпиÑкою", 139 "settings.account.manageSubscription.label" : "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾ÑŽ підпиÑкою",
119 "settings.account.successInfo" : "Ваші зміни були збережені", 140 "settings.account.successInfo" : "Ваші зміни були збережені",
141 "settings.account.tryReloadServices" : "Спробуйте ще раз",
120 "settings.account.tryReloadUserInfoRequest" : "Спробуйте ще раз", 142 "settings.account.tryReloadUserInfoRequest" : "Спробуйте ще раз",
121 "settings.account.userInfoRequestFailed" : "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ інформацію кориÑтувача", 143 "settings.account.userInfoRequestFailed" : "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ інформацію кориÑтувача",
122 "settings.app.buttonClearAllCache" : "ОчиÑтити кеш", 144 "settings.app.buttonClearAllCache" : "ОчиÑтити кеш",
@@ -127,24 +149,22 @@
127 "settings.app.form.autoLaunchInBackground" : "Відкрити у фоновому режимі", 149 "settings.app.form.autoLaunchInBackground" : "Відкрити у фоновому режимі",
128 "settings.app.form.autoLaunchOnStart" : "ЗапуÑкати Franz на початку", 150 "settings.app.form.autoLaunchOnStart" : "ЗапуÑкати Franz на початку",
129 "settings.app.form.beta" : "Включити бета-верÑÑ–Ñ—", 151 "settings.app.form.beta" : "Включити бета-верÑÑ–Ñ—",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "Переходь на Темну Сторону",
131 "settings.app.form.enableGPUAcceleration" : "Ввімкнути приÑÐºÐ¾Ñ€ÐµÐ½Ð½Ñ GPU", 153 "settings.app.form.enableGPUAcceleration" : "Ввімкнути приÑÐºÐ¾Ñ€ÐµÐ½Ð½Ñ GPU",
132 "settings.app.form.enableMenuBar" : "Відображати Franz в панелі головного меню",
133 "settings.app.form.enableSpellchecking" : "Увімкнути перевірку орфографії", 154 "settings.app.form.enableSpellchecking" : "Увімкнути перевірку орфографії",
134 "settings.app.form.enableSystemTray" : "Показувати Franz у ÑиÑтемному лотку", 155 "settings.app.form.enableSystemTray" : "Показувати Franz у ÑиÑтемному лотку",
135 "settings.app.form.hideDockIcon" : "Сховати значок Franz в Dock",
136 "settings.app.form.language" : "Мова", 156 "settings.app.form.language" : "Мова",
137 "settings.app.form.minimizeToSystemTray" : "Мінімізувати Franz до ÑиÑтемного лотка", 157 "settings.app.form.minimizeToSystemTray" : "Мінімізувати Franz до ÑиÑтемного лотка",
138 "settings.app.form.runInBackground" : "Тримати Franz в фоні при закритті вікна", 158 "settings.app.form.runInBackground" : "Тримати Franz в фоні при закритті вікна",
139 "settings.app.form.showDisabledServices" : "Показати вкладку вимкнених ÑервіÑів", 159 "settings.app.form.showDisabledServices" : "Показати вкладку вимкнених ÑервіÑів",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "Показувати значок непрочитаних повідомлень коли ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ñ–", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "Показувати значок непрочитаних повідомлень коли ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ñ–",
141 "settings.app.form.spellcheckerLanguage" : "Spell checking language",
142 "settings.app.headline" : "ÐалаштуваннÑ", 161 "settings.app.headline" : "ÐалаштуваннÑ",
143 "settings.app.headlineAdvanced" : "Додаткові налаштуваннÑ", 162 "settings.app.headlineAdvanced" : "Додаткові налаштуваннÑ",
144 "settings.app.headlineAppearance" : "ВиглÑд", 163 "settings.app.headlineAppearance" : "ВиглÑд",
145 "settings.app.headlineGeneral" : "Загальні", 164 "settings.app.headlineGeneral" : "Загальні",
146 "settings.app.headlineLanguage" : "Мова", 165 "settings.app.headlineLanguage" : "Мова",
147 "settings.app.headlineUpdates" : "ОновленнÑ", 166 "settings.app.headlineUpdates" : "ОновленнÑ",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "Зміни потребують перезапуÑку", 168 "settings.app.restartRequired" : "Зміни потребують перезапуÑку",
149 "settings.app.subheadlineCache" : "Кеш", 169 "settings.app.subheadlineCache" : "Кеш",
150 "settings.app.translationHelp" : "Допоможіть переклаÑти Franz на Вашу мову.", 170 "settings.app.translationHelp" : "Допоможіть переклаÑти Franz на Вашу мову.",
@@ -157,7 +177,9 @@
157 "settings.navigation.inviteFriends" : "ЗапроÑити друзів", 177 "settings.navigation.inviteFriends" : "ЗапроÑити друзів",
158 "settings.navigation.logout" : "Вийти", 178 "settings.navigation.logout" : "Вийти",
159 "settings.navigation.settings" : "ÐалаштуваннÑ", 179 "settings.navigation.settings" : "ÐалаштуваннÑ",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "Ваші ÑервіÑи", 181 "settings.navigation.yourServices" : "Ваші ÑервіÑи",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "Ð’ÑÑ– ÑервіÑи", 183 "settings.recipes.all" : "Ð’ÑÑ– ÑервіÑи",
162 "settings.recipes.dev" : "Розробка", 184 "settings.recipes.dev" : "Розробка",
163 "settings.recipes.headline" : "ДоÑтупні ÑервіÑи", 185 "settings.recipes.headline" : "ДоÑтупні ÑервіÑи",
@@ -179,7 +201,7 @@
179 "settings.service.form.editServiceHeadline" : "Редагувати {name}", 201 "settings.service.form.editServiceHeadline" : "Редагувати {name}",
180 "settings.service.form.enableAudio" : "Увімкнути звук", 202 "settings.service.form.enableAudio" : "Увімкнути звук",
181 "settings.service.form.enableBadge" : "Показувати непрочитані повідомленнÑ", 203 "settings.service.form.enableBadge" : "Показувати непрочитані повідомленнÑ",
182 "settings.service.form.enableDarkMode" : "Enable Dark Mode", 204 "settings.service.form.enableDarkMode" : "Переходь на Темну Сторону",
183 "settings.service.form.enableNotification" : "Увімкнути ÑповіщеннÑ", 205 "settings.service.form.enableNotification" : "Увімкнути ÑповіщеннÑ",
184 "settings.service.form.enableService" : "Увімкнути ÑервіÑ", 206 "settings.service.form.enableService" : "Увімкнути ÑервіÑ",
185 "settings.service.form.headlineBadges" : "Значки непрочитаних повідомлень", 207 "settings.service.form.headlineBadges" : "Значки непрочитаних повідомлень",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "Показувати значок Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… нових повідомлень", 214 "settings.service.form.indirectMessages" : "Показувати значок Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… нових повідомлень",
193 "settings.service.form.isMutedInfo" : "Коли вимкнено, вÑÑ– ÑÐ¿Ð¾Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ–Ð³Ð½Ð¾Ñ€ÑƒÑŽÑ‚ÑŒÑÑ", 215 "settings.service.form.isMutedInfo" : "Коли вимкнено, вÑÑ– ÑÐ¿Ð¾Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ–Ð³Ð½Ð¾Ñ€ÑƒÑŽÑ‚ÑŒÑÑ",
194 "settings.service.form.name" : "Ім'Ñ", 216 "settings.service.form.name" : "Ім'Ñ",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ HTTP\/HTTPS прокÑÑ– ",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "ПрокÑÑ– Host\/IP",
197 "settings.service.form.proxy.info" : "Proxy settings will not synced with the Franz servers.", 219 "settings.service.form.proxy.info" : "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐºÑÑ– не будуть Ñинхронізовані із Ñерверами Franz",
198 "settings.service.form.proxy.isEnabled" : "Use Proxy", 220 "settings.service.form.proxy.isEnabled" : "ВикориÑтовувати прокÑÑ–",
199 "settings.service.form.proxy.password" : "Password (optional)", 221 "settings.service.form.proxy.password" : "Пароль (опційно)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "Порт",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "Будь лаÑка, перезапуÑÑ‚Ñ–Ñ‚ÑŒ Franz піÑÐ»Ñ Ð·Ð¼Ñ–Ð½Ð¸ налуштувань прокÑÑ–",
202 "settings.service.form.proxy.user" : "User (optional)", 224 "settings.service.form.proxy.user" : "КориÑтувач (опційно)",
203 "settings.service.form.saveButton" : "Зберегти ÑервіÑ", 225 "settings.service.form.saveButton" : "Зберегти ÑервіÑ",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "Розміщений", 226 "settings.service.form.tabHosted" : "Розміщений",
207 "settings.service.form.tabOnPremise" : "СамоÑтійно розміщений â­ï¸", 227 "settings.service.form.tabOnPremise" : "СамоÑтійно розміщений â­ï¸",
208 "settings.service.form.team" : "Команда", 228 "settings.service.form.team" : "Команда",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "Відкрийте Ð´Ð»Ñ Ñебе ÑервіÑи", 232 "settings.services.discoverServices" : "Відкрийте Ð´Ð»Ñ Ñебе ÑервіÑи",
213 "settings.services.headline" : "Ваші ÑервіÑи", 233 "settings.services.headline" : "Ваші ÑервіÑи",
214 "settings.services.noServicesAdded" : "Ви ще не додавали жодних ÑервіÑів.", 234 "settings.services.noServicesAdded" : "Ви ще не додавали жодних ÑервіÑів.",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ð¹", 236 "settings.services.tooltip.isDisabled" : "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ð¹",
216 "settings.services.tooltip.isMuted" : "Ð’ÑÑ– звуки вимкнено", 237 "settings.services.tooltip.isMuted" : "Ð’ÑÑ– звуки вимкнено",
217 "settings.services.tooltip.notificationsDisabled" : "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ–", 238 "settings.services.tooltip.notificationsDisabled" : "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ–",
218 "settings.services.updatedInfo" : "Ваші зміни були збережені", 239 "settings.services.updatedInfo" : "Ваші зміни були збережені",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "Команда",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "КомпаніÑ", 246 "settings.user.form.accountType.company" : "КомпаніÑ",
220 "settings.user.form.accountType.individual" : "Індивідуальний", 247 "settings.user.form.accountType.individual" : "Індивідуальний",
221 "settings.user.form.accountType.label" : "Тип акаунту", 248 "settings.user.form.accountType.label" : "Тип акаунту",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "Ім`Ñ", 252 "settings.user.form.firstname" : "Ім`Ñ",
226 "settings.user.form.lastname" : "Прізвище", 253 "settings.user.form.lastname" : "Прізвище",
227 "settings.user.form.newPassword" : "Ðовий пароль", 254 "settings.user.form.newPassword" : "Ðовий пароль",
255 "settings.workspace.add.form.name" : "Ім'Ñ",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "Ім'Ñ",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "Спробуйте ще раз",
266 "settings.workspaces.updatedInfo" : "Ваші зміни були збережені",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "Додати новий ÑервіÑ", 270 "sidebar.addNewService" : "Додати новий ÑервіÑ",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "Вимкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° звуки", 272 "sidebar.muteApp" : "Вимкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° звуки",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "ÐалаштуваннÑ", 274 "sidebar.settings" : "ÐалаштуваннÑ",
231 "sidebar.unmuteApp" : "Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° звуки", 275 "sidebar.unmuteApp" : "Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° звуки",
232 "signup.company.label" : "КомпаніÑ", 276 "signup.company.label" : "КомпаніÑ",
@@ -244,12 +288,11 @@
244 "subscription.euTaxInfo" : "Ð”Ð»Ñ Ð¶Ð¸Ñ‚ÐµÐ»Ñ–Ð² ЄС: можуть заÑтоÑовуватиÑÑ Ð¿Ð¾Ð´Ð°Ñ‚ÐºÐ¸", 288 "subscription.euTaxInfo" : "Ð”Ð»Ñ Ð¶Ð¸Ñ‚ÐµÐ»Ñ–Ð² ЄС: можуть заÑтоÑовуватиÑÑ Ð¿Ð¾Ð´Ð°Ñ‚ÐºÐ¸",
245 "subscription.features.ads" : "Жодної реклами!", 289 "subscription.features.ads" : "Жодної реклами!",
246 "subscription.features.comingSoon" : "очікуйте незабаром", 290 "subscription.features.comingSoon" : "очікуйте незабаром",
247 "subscription.features.encryptedSync" : "Шифрована ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ ÑеанÑу", 291 "subscription.features.noInterruptions" : "ÐÑ–Ñких затримок та набридливих пропозицій з платних підпиÑок",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "СервіÑи, що виконуютьÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾\/вимагають хоÑтингу, приміром Mattermost",
249 "subscription.features.onpremise" : "Додайте on-premise \/ hosted ÑервіÑи, такі Ñк Hipchat", 293 "subscription.features.proxy" : "Підтримка прокÑÑ– ",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost", 294 "subscription.features.spellchecker" : "Підтримка перевірки правопиÑу",
251 "subscription.features.proxy" : "Proxy support for services", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
252 "subscription.features.spellchecker" : "Support for spellchecker",
253 "subscription.includedFeatures" : "Платний Преміальний Ðкаунт Прихильника Franz включає", 296 "subscription.includedFeatures" : "Платний Преміальний Ðкаунт Прихильника Franz включає",
254 "subscription.paymentSessionError" : "Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ форму платежу", 297 "subscription.paymentSessionError" : "Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ форму платежу",
255 "subscription.submit.label" : "Я хочу підтримати розробку Franz", 298 "subscription.submit.label" : "Я хочу підтримати розробку Franz",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "Перезавантажити", 312 "tabs.item.reload" : "Перезавантажити",
270 "validation.email" : "{field} не валідне", 313 "validation.email" : "{field} не валідне",
271 "validation.minLength" : "КількіÑÑ‚ÑŒ Ñимволів в {field} повина бути не меньше {length} ", 314 "validation.minLength" : "КількіÑÑ‚ÑŒ Ñимволів в {field} повина бути не меньше {length} ",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field} обов'Ñзвоке", 316 "validation.required" : "{field} обов'Ñзвоке",
273 "validation.url" : "{field} не валідний URL", 317 "validation.url" : "{field} не валідний URL",
274 "welcome.loginButton" : "Увійдіть до Ñвого акаунту", 318 "welcome.loginButton" : "Увійдіть до Ñвого акаунту",
275 "welcome.signupButton" : "Створити безплатний акаунт", 319 "welcome.signupButton" : "Створити безплатний акаунт",
276 "welcome.slogan" : "Обмін повідомленнÑми, Ñкий працює Ð´Ð»Ñ Ð²Ð°Ñ" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "Ð’ÑÑ– ÑервіÑи",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/locales/whitelist_en-US.json b/src/i18n/locales/whitelist_en-US.json
new file mode 100644
index 000000000..32960f8ce
--- /dev/null
+++ b/src/i18n/locales/whitelist_en-US.json
@@ -0,0 +1,2 @@
1[
2] \ No newline at end of file
diff --git a/src/i18n/locales/zh-TW.json b/src/i18n/locales/zh-TW.json
index cfb1d3dce..34bd2158c 100644
--- a/src/i18n/locales/zh-TW.json
+++ b/src/i18n/locales/zh-TW.json
@@ -1,11 +1,23 @@
1{ 1{
2 "app.errorHandler.action" : "é‡æ–°è¼‰å…¥", 2 "app.errorHandler.action" : "é‡æ–°è¼‰å…¥",
3 "app.errorHandler.headline" : "有些æ±è¥¿å‡ºéŒ¯äº†", 3 "app.errorHandler.headline" : "有些æ±è¥¿å‡ºéŒ¯äº†",
4 "feature.delayApp.action" : "Get a Franz Supporter License", 4 "feature.announcements.changelog.headline" : "Changes in Franz {version}",
5 "feature.delayApp.headline" : "Please purchase a Franz Supporter License to skip waiting", 5 "feature.delayApp.action" : "å–å¾— Franz 支æ´æŽˆæ¬Š",
6 "feature.delayApp.text" : "Franz will continue in {seconds} seconds.", 6 "feature.delayApp.headline" : "請購買 Franz 支æ´æŽˆæ¬Šä»¥è·³éŽç­‰å€™",
7 "global.api.unhealthy" : "無法連線至Franz的伺æœå™¨ã€‚", 7 "feature.delayApp.text" : "Franz 會在 {seconds} 秒後繼續。",
8 "feature.shareFranz.action.email" : "Send as email",
9 "feature.shareFranz.action.facebook" : "Share on Facebook",
10 "feature.shareFranz.action.twitter" : "Share on Twitter",
11 "feature.shareFranz.headline" : "Franz is better together!",
12 "feature.shareFranz.shareText.email" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
13 "feature.shareFranz.shareText.twitter" : "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com \/cc @FranzMessenger",
14 "feature.shareFranz.text" : "Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
15 "global.api.unhealthy" : "無法連線至 Franz 的伺æœå™¨",
8 "global.notConnectedToTheInternet" : "你沒有連上網路。", 16 "global.notConnectedToTheInternet" : "你沒有連上網路。",
17 "global.spellchecker.useDefault" : "使用系統é è¨­ ({default})",
18 "global.spellchecking.autodetect" : "Detect language automatically",
19 "global.spellchecking.autodetect.short" : "Automatic",
20 "global.spellchecking.language" : "拼字檢查語言",
9 "import.headline" : "匯入 Franz 4 çš„æœå‹™", 21 "import.headline" : "匯入 Franz 4 çš„æœå‹™",
10 "import.notSupportedHeadline" : "Franz 5 尚未支æ´æ­¤æœå‹™", 22 "import.notSupportedHeadline" : "Franz 5 尚未支æ´æ­¤æœå‹™",
11 "import.skip.label" : "手動添加æœå‹™", 23 "import.skip.label" : "手動添加æœå‹™",
@@ -14,10 +26,10 @@
14 "infobar.buttonInstallUpdate" : "é‡æ–°å•Ÿå‹•ä¸¦å®‰è£æ›´æ–°", 26 "infobar.buttonInstallUpdate" : "é‡æ–°å•Ÿå‹•ä¸¦å®‰è£æ›´æ–°",
15 "infobar.buttonReloadServices" : "é‡æ–°è¼‰å…¥æœå‹™", 27 "infobar.buttonReloadServices" : "é‡æ–°è¼‰å…¥æœå‹™",
16 "infobar.requiredRequestsFailed" : "無法載入æœå‹™å’Œä½¿ç”¨è€…資訊", 28 "infobar.requiredRequestsFailed" : "無法載入æœå‹™å’Œä½¿ç”¨è€…資訊",
17 "infobar.servicesUpdated" : "ä½ çš„æœå‹™å·²ç¶“被更新", 29 "infobar.servicesUpdated" : "已經更新你的æœå‹™",
18 "infobar.updateAvailable" : "Franz有å¯ç”¨çš„æ›´æ–°", 30 "infobar.updateAvailable" : "Franz 有å¯ç”¨çš„æ›´æ–°",
19 "invite.email.label" : "é›»å­éƒµä»¶åœ°å€", 31 "invite.email.label" : "é›»å­éƒµä»¶åœ°å€",
20 "invite.headline.friends" : "邀請3ä½ä½ çš„朋å‹æˆ–åŒäº‹", 32 "invite.headline.friends" : "邀請 3 ä½æœ‹å‹æˆ–åŒäº‹",
21 "invite.name.label" : "å稱", 33 "invite.name.label" : "å稱",
22 "invite.skip.label" : "我想ç¨å¾Œå†åš", 34 "invite.skip.label" : "我想ç¨å¾Œå†åš",
23 "invite.submit.label" : "é€å‡ºé‚€è«‹", 35 "invite.submit.label" : "é€å‡ºé‚€è«‹",
@@ -31,7 +43,8 @@
31 "login.serverLogout" : "您的登入期間已éŽæœŸï¼Œè«‹é‡æ–°ç™»éŒ„", 43 "login.serverLogout" : "您的登入期間已éŽæœŸï¼Œè«‹é‡æ–°ç™»éŒ„",
32 "login.submit.label" : "登入", 44 "login.submit.label" : "登入",
33 "login.tokenExpired" : "您的登入已éŽæœŸï¼Œè«‹é‡æ–°ç™»å…¥ã€‚", 45 "login.tokenExpired" : "您的登入已éŽæœŸï¼Œè«‹é‡æ–°ç™»å…¥ã€‚",
34 "menu.app.about" : "關於Franz", 46 "menu.app.about" : "關於 Franz",
47 "menu.app.announcement" : "What's new?",
35 "menu.app.hide" : "éš±è—", 48 "menu.app.hide" : "éš±è—",
36 "menu.app.hideOthers" : "éš±è—其他", 49 "menu.app.hideOthers" : "éš±è—其他",
37 "menu.app.quit" : "çµæŸ", 50 "menu.app.quit" : "çµæŸ",
@@ -59,11 +72,13 @@
59 "menu.help.support" : "支æ´", 72 "menu.help.support" : "支æ´",
60 "menu.help.tos" : "æœå‹™æ¢æ¬¾", 73 "menu.help.tos" : "æœå‹™æ¢æ¬¾",
61 "menu.services" : "æœå‹™", 74 "menu.services" : "æœå‹™",
75 "menu.services.activatePreviousService" : "Activate previous service",
62 "menu.services.addNewService" : "新增æœå‹™", 76 "menu.services.addNewService" : "新增æœå‹™",
77 "menu.services.setNextServiceActive" : "Activate next service",
63 "menu.view" : "檢視", 78 "menu.view" : "檢視",
64 "menu.view.enterFullScreen" : "進入全螢幕模å¼", 79 "menu.view.enterFullScreen" : "進入全螢幕模å¼",
65 "menu.view.exitFullScreen" : "離開全螢幕模å¼", 80 "menu.view.exitFullScreen" : "離開全螢幕模å¼",
66 "menu.view.reloadFranz" : "é‡æ–°è¼‰å…¥Franz", 81 "menu.view.reloadFranz" : "é‡æ–°è¼‰å…¥ Franz",
67 "menu.view.reloadService" : "é‡æ–°è¼‰å…¥æœå‹™", 82 "menu.view.reloadService" : "é‡æ–°è¼‰å…¥æœå‹™",
68 "menu.view.resetZoom" : "實際大å°", 83 "menu.view.resetZoom" : "實際大å°",
69 "menu.view.toggleDevTools" : "切æ›é–‹ç™¼è€…工具", 84 "menu.view.toggleDevTools" : "切æ›é–‹ç™¼è€…工具",
@@ -74,6 +89,11 @@
74 "menu.window" : "視窗", 89 "menu.window" : "視窗",
75 "menu.window.close" : "關閉", 90 "menu.window.close" : "關閉",
76 "menu.window.minimize" : "最å°åŒ–", 91 "menu.window.minimize" : "最å°åŒ–",
92 "menu.workspaces" : "Workspaces",
93 "menu.workspaces.addNewWorkspace" : "Add New Workspace...",
94 "menu.workspaces.closeWorkspaceDrawer" : "Close workspace drawer",
95 "menu.workspaces.defaultWorkspace" : "所有æœå‹™",
96 "menu.workspaces.openWorkspaceDrawer" : "Open workspace drawer",
77 "password.email.label" : "é›»å­éƒµä»¶åœ°å€", 97 "password.email.label" : "é›»å­éƒµä»¶åœ°å€",
78 "password.headline" : "é‡è¨­å¯†ç¢¼", 98 "password.headline" : "é‡è¨­å¯†ç¢¼",
79 "password.link.login" : "登入您的帳號", 99 "password.link.login" : "登入您的帳號",
@@ -82,9 +102,9 @@
82 "password.submit.label" : "é€å‡º", 102 "password.submit.label" : "é€å‡º",
83 "password.successInfo" : "請檢查您的電å­éƒµä»¶", 103 "password.successInfo" : "請檢查您的電å­éƒµä»¶",
84 "premiumFeature.button.upgradeAccount" : "å‡ç´šå¸³è™Ÿ", 104 "premiumFeature.button.upgradeAccount" : "å‡ç´šå¸³è™Ÿ",
85 "pricing.headline" : "支æŒFranz", 105 "pricing.headline" : "æ”¯æŒ Franz",
86 "pricing.link.skipPayment" : "我ä¸æƒ³æ”¯æŒFranz的開發。", 106 "pricing.link.skipPayment" : "我ä¸æƒ³æ”¯æŒ Franz 的開發。",
87 "pricing.submit.label" : "我想支æŒFranz的開發。", 107 "pricing.submit.label" : "æˆ‘æƒ³æ”¯æŒ Franz 的開發。",
88 "pricing.support.label" : "é¸æ“‡æ‚¨æ”¯æŒçš„計畫", 108 "pricing.support.label" : "é¸æ“‡æ‚¨æ”¯æŒçš„計畫",
89 "service.crashHandler.action" : "é‡æ–°è¼‰å…¥{name}", 109 "service.crashHandler.action" : "é‡æ–°è¼‰å…¥{name}",
90 "service.crashHandler.autoReload" : "嘗試在{seconds}秒內自動æ¢å¾©{name}", 110 "service.crashHandler.autoReload" : "嘗試在{seconds}秒內自動æ¢å¾©{name}",
@@ -92,20 +112,21 @@
92 "service.crashHandler.text" : "{name}導致了一個錯誤。", 112 "service.crashHandler.text" : "{name}導致了一個錯誤。",
93 "service.disabledHandler.action" : "啟用{name}", 113 "service.disabledHandler.action" : "啟用{name}",
94 "service.disabledHandler.headline" : "{name}å·²åœç”¨", 114 "service.disabledHandler.headline" : "{name}å·²åœç”¨",
95 "service.errorHandler.action" : "é‡æ–°è¼‰å…¥{name}", 115 "service.errorHandler.action" : "é‡æ–°è¼‰å…¥ {name}",
96 "service.errorHandler.editAction" : "編輯{å稱}", 116 "service.errorHandler.editAction" : "編輯{å稱}",
97 "service.errorHandler.headline" : "噢ä¸!", 117 "service.errorHandler.headline" : "噢ä¸ï¼",
98 "service.errorHandler.message" : "錯誤", 118 "service.errorHandler.message" : "錯誤",
99 "service.errorHandler.text" : "{name} has failed to load.", 119 "service.errorHandler.text" : "{name} 載入失敗。",
120 "service.webviewLoader.loading" : "Loading",
100 "services.getStarted" : "開始", 121 "services.getStarted" : "開始",
101 "services.welcome" : "歡迎使用Franz", 122 "services.welcome" : "歡迎使用 Franz",
102 "settings.account.account.editButton" : "編輯帳號", 123 "settings.account.account.editButton" : "編輯帳號",
103 "settings.account.accountType.basic" : "基礎帳號", 124 "settings.account.accountType.basic" : "基礎帳號",
104 "settings.account.accountType.premium" : "高級支æŒè€…帳戶", 125 "settings.account.accountType.premium" : "高級支æ´å¸³æˆ¶",
105 "settings.account.buttonSave" : "更新簡介", 126 "settings.account.buttonSave" : "更新簡介",
106 "settings.account.deleteAccount" : "移除帳號", 127 "settings.account.deleteAccount" : "移除帳號",
107 "settings.account.deleteEmailSent" : "移除帳號之確èªé›»éƒµå·²é€å‡ºã€‚你的帳號åŠç›¸é—œè³‡æ–™å°‡ç„¡æ³•æ¢å¾©ï¼", 128 "settings.account.deleteEmailSent" : "移除帳號之確èªé›»éƒµå·²é€å‡ºã€‚你的帳號åŠç›¸é—œè³‡æ–™å°‡ç„¡æ³•æ¢å¾©ï¼",
108 "settings.account.deleteInfo" : "如果ä¸å†éœ€è¦ä½ çš„帳號了,你å¯ä»¥åœ¨é€™è£¡åˆªé™¤å¸³è™Ÿå’Œç›¸é—œè³‡æ–™", 129 "settings.account.deleteInfo" : "如果ä¸å†éœ€è¦ä½ çš„帳號,你å¯ä»¥åœ¨é€™è£¡åˆªé™¤å¸³è™Ÿå’Œæ‰€æœ‰ç›¸é—œè³‡æ–™ã€‚",
109 "settings.account.headline" : "帳號", 130 "settings.account.headline" : "帳號",
110 "settings.account.headlineAccount" : "帳戶資訊", 131 "settings.account.headlineAccount" : "帳戶資訊",
111 "settings.account.headlineDangerZone" : "å±éšªåœ°å¸¶", 132 "settings.account.headlineDangerZone" : "å±éšªåœ°å¸¶",
@@ -113,51 +134,52 @@
113 "settings.account.headlinePassword" : "變更密碼", 134 "settings.account.headlinePassword" : "變更密碼",
114 "settings.account.headlineProfile" : "更新簡介", 135 "settings.account.headlineProfile" : "更新簡介",
115 "settings.account.headlineSubscription" : "您的訂閱", 136 "settings.account.headlineSubscription" : "您的訂閱",
116 "settings.account.headlineUpgrade" : "å‡ç´šæ‚¨çš„帳戶&支æŒFranz", 137 "settings.account.headlineUpgrade" : "å‡ç´šæ‚¨çš„å¸³æˆ¶ä¸¦æ”¯æŒ Franz",
117 "settings.account.invoiceDownload" : "下載", 138 "settings.account.invoiceDownload" : "下載",
118 "settings.account.manageSubscription.label" : "管ç†æ‚¨çš„訂閱", 139 "settings.account.manageSubscription.label" : "管ç†æ‚¨çš„訂閱",
119 "settings.account.successInfo" : "您的更變已經被儲存", 140 "settings.account.successInfo" : "您的更變已經被儲存",
141 "settings.account.tryReloadServices" : "å†è©¦ä¸€æ¬¡",
120 "settings.account.tryReloadUserInfoRequest" : "å†è©¦ä¸€æ¬¡", 142 "settings.account.tryReloadUserInfoRequest" : "å†è©¦ä¸€æ¬¡",
121 "settings.account.userInfoRequestFailed" : "無法載入使用者資訊。", 143 "settings.account.userInfoRequestFailed" : "無法載入使用者資訊。",
122 "settings.app.buttonClearAllCache" : "清除快å–", 144 "settings.app.buttonClearAllCache" : "清除快å–",
123 "settings.app.buttonInstallUpdate" : "é‡æ–°å•Ÿå‹•ä¸¦å®‰è£æ›´æ–°", 145 "settings.app.buttonInstallUpdate" : "é‡æ–°å•Ÿå‹•ä¸¦å®‰è£æ›´æ–°",
124 "settings.app.buttonSearchForUpdate" : "檢查更新", 146 "settings.app.buttonSearchForUpdate" : "檢查更新",
125 "settings.app.cacheInfo" : "Franzå¿«å–ç›®å‰å ç”¨ç£ç¢Ÿç©ºé–“{大å°}。", 147 "settings.app.cacheInfo" : "Franz å¿«å–ç›®å‰å ç”¨ {size} çš„ç£ç¢Ÿç©ºé–“。",
126 "settings.app.currentVersion" : "ç›®å‰çš„版本", 148 "settings.app.currentVersion" : "ç›®å‰çš„版本",
127 "settings.app.form.autoLaunchInBackground" : "在背景開啟", 149 "settings.app.form.autoLaunchInBackground" : "在背景開啟",
128 "settings.app.form.autoLaunchOnStart" : "開機時啟動Franz", 150 "settings.app.form.autoLaunchOnStart" : "開機時啟動 Franz",
129 "settings.app.form.beta" : "包å«æ¸¬è©¦ç‰ˆ", 151 "settings.app.form.beta" : "包å«æ¸¬è©¦ç‰ˆ",
130 "settings.app.form.darkMode" : "Join the Dark Side", 152 "settings.app.form.darkMode" : "加入黑暗é¢",
131 "settings.app.form.enableGPUAcceleration" : "啟用GPU加速", 153 "settings.app.form.enableGPUAcceleration" : "啟用 GPU 加速",
132 "settings.app.form.enableMenuBar" : "顯示Franz在é¸å–®åˆ—",
133 "settings.app.form.enableSpellchecking" : "啟用拼字檢查", 154 "settings.app.form.enableSpellchecking" : "啟用拼字檢查",
134 "settings.app.form.enableSystemTray" : "顯示Franz在系統列", 155 "settings.app.form.enableSystemTray" : "在系統列顯示 Franz",
135 "settings.app.form.hideDockIcon" : "在工作列中隱è—Franz圖示",
136 "settings.app.form.language" : "語言", 156 "settings.app.form.language" : "語言",
137 "settings.app.form.minimizeToSystemTray" : "最å°åŒ–Franz到系統列", 157 "settings.app.form.minimizeToSystemTray" : "最å°åŒ– Franz 到系統列",
138 "settings.app.form.runInBackground" : "當關閉視窗時ä¿æŒFranz在背景é‹ä½œ", 158 "settings.app.form.runInBackground" : "當關閉視窗時,ä¿æŒ Franz 在背景é‹ä½œ",
139 "settings.app.form.showDisabledServices" : "顯示åœç”¨çš„æœå‹™æ¨™ç±¤", 159 "settings.app.form.showDisabledServices" : "顯示åœç”¨çš„æœå‹™æ¨™ç±¤",
140 "settings.app.form.showMessagesBadgesWhenMuted" : "當通知關閉時,標記未讀的訊æ¯", 160 "settings.app.form.showMessagesBadgesWhenMuted" : "當通知關閉時,標記未讀的訊æ¯",
141 "settings.app.form.spellcheckerLanguage" : "拼字檢查語言",
142 "settings.app.headline" : "設定", 161 "settings.app.headline" : "設定",
143 "settings.app.headlineAdvanced" : "進階", 162 "settings.app.headlineAdvanced" : "進階",
144 "settings.app.headlineAppearance" : "外觀", 163 "settings.app.headlineAppearance" : "外觀",
145 "settings.app.headlineGeneral" : "一般", 164 "settings.app.headlineGeneral" : "一般",
146 "settings.app.headlineLanguage" : "語言", 165 "settings.app.headlineLanguage" : "語言",
147 "settings.app.headlineUpdates" : "æ›´æ–°", 166 "settings.app.headlineUpdates" : "æ›´æ–°",
167 "settings.app.languageDisclaimer" : "Official translations are English & German. All other languages are community based translations.",
148 "settings.app.restartRequired" : "需è¦é‡å•Ÿä»¥æ›´è®Š", 168 "settings.app.restartRequired" : "需è¦é‡å•Ÿä»¥æ›´è®Š",
149 "settings.app.subheadlineCache" : "å¿«å–", 169 "settings.app.subheadlineCache" : "å¿«å–",
150 "settings.app.translationHelp" : "幫助我們將Franz翻譯æˆæ‚¨çš„語言。", 170 "settings.app.translationHelp" : "幫助我們將 Franz 翻譯æˆæ‚¨çš„語言。",
151 "settings.app.updateStatusAvailable" : "有å¯ç”¨æ›´æ–°ï¼Œä¸‹è¼‰ä¸­...", 171 "settings.app.updateStatusAvailable" : "有å¯ç”¨æ›´æ–°ï¼Œä¸‹è¼‰ä¸­...",
152 "settings.app.updateStatusSearching" : "正在æœå°‹æ›´æ–°", 172 "settings.app.updateStatusSearching" : "正在æœå°‹æ›´æ–°",
153 "settings.app.updateStatusUpToDate" : "您正在使用最新版本的Franz", 173 "settings.app.updateStatusUpToDate" : "您正在使用最新版本的 Franz",
154 "settings.invite.headline" : "邀請朋å‹", 174 "settings.invite.headline" : "邀請朋å‹",
155 "settings.navigation.account" : "帳號", 175 "settings.navigation.account" : "帳號",
156 "settings.navigation.availableServices" : "å¯ä½¿ç”¨çš„æœå‹™", 176 "settings.navigation.availableServices" : "å¯ä½¿ç”¨çš„æœå‹™",
157 "settings.navigation.inviteFriends" : "邀請朋å‹", 177 "settings.navigation.inviteFriends" : "邀請朋å‹",
158 "settings.navigation.logout" : "登出", 178 "settings.navigation.logout" : "登出",
159 "settings.navigation.settings" : "設定", 179 "settings.navigation.settings" : "設定",
180 "settings.navigation.team" : "Manage Team",
160 "settings.navigation.yourServices" : "您的æœå‹™", 181 "settings.navigation.yourServices" : "您的æœå‹™",
182 "settings.navigation.yourWorkspaces" : "Your workspaces",
161 "settings.recipes.all" : "所有æœå‹™", 183 "settings.recipes.all" : "所有æœå‹™",
162 "settings.recipes.dev" : "開發", 184 "settings.recipes.dev" : "開發",
163 "settings.recipes.headline" : "å¯ä½¿ç”¨çš„æœå‹™", 185 "settings.recipes.headline" : "å¯ä½¿ç”¨çš„æœå‹™",
@@ -172,11 +194,11 @@
172 "settings.service.form.addServiceHeadline" : "新增{name}", 194 "settings.service.form.addServiceHeadline" : "新增{name}",
173 "settings.service.form.availableServices" : "å¯ä½¿ç”¨çš„æœå‹™", 195 "settings.service.form.availableServices" : "å¯ä½¿ç”¨çš„æœå‹™",
174 "settings.service.form.customUrl" : "自訂伺æœå™¨", 196 "settings.service.form.customUrl" : "自訂伺æœå™¨",
175 "settings.service.form.customUrlPremiumInfo" : "è¦æ·»åŠ è‡ªå·±è¨—管的æœå‹™ï¼Œæ‚¨éœ€è¦ä¸€å€‹Franz é¡å¤–支æŒè€…帳戶。", 197 "settings.service.form.customUrlPremiumInfo" : "è¦æ·»åŠ è‡ªè¡Œè¨—管的æœå‹™ï¼Œæ‚¨éœ€è¦æ“有 Franz 高級支æ´å¸³æˆ¶ã€‚",
176 "settings.service.form.customUrlUpgradeAccount" : "å‡ç´šæ‚¨çš„帳戶", 198 "settings.service.form.customUrlUpgradeAccount" : "å‡ç´šæ‚¨çš„帳戶",
177 "settings.service.form.customUrlValidationError" : "無法驗證自定義{name}æœå‹™å™¨ã€‚", 199 "settings.service.form.customUrlValidationError" : "無法驗證自定義{name}æœå‹™å™¨ã€‚",
178 "settings.service.form.deleteButton" : "刪除æœå‹™", 200 "settings.service.form.deleteButton" : "刪除æœå‹™",
179 "settings.service.form.editServiceHeadline" : "編輯{å稱}", 201 "settings.service.form.editServiceHeadline" : "編輯 {å稱}",
180 "settings.service.form.enableAudio" : "啟用音訊", 202 "settings.service.form.enableAudio" : "啟用音訊",
181 "settings.service.form.enableBadge" : "顯示未讀訊æ¯åœ–示", 203 "settings.service.form.enableBadge" : "顯示未讀訊æ¯åœ–示",
182 "settings.service.form.enableDarkMode" : "開啟深色模å¼", 204 "settings.service.form.enableDarkMode" : "開啟深色模å¼",
@@ -192,17 +214,15 @@
192 "settings.service.form.indirectMessages" : "顯示所有新消æ¯çš„消æ¯æ¨™èªŒ", 214 "settings.service.form.indirectMessages" : "顯示所有新消æ¯çš„消æ¯æ¨™èªŒ",
193 "settings.service.form.isMutedInfo" : "åœç”¨æ™‚,所有通知è²å’Œè²éŸ³æ’­æ”¾éƒ½å°‡éœéŸ³", 215 "settings.service.form.isMutedInfo" : "åœç”¨æ™‚,所有通知è²å’Œè²éŸ³æ’­æ”¾éƒ½å°‡éœéŸ³",
194 "settings.service.form.name" : "å稱", 216 "settings.service.form.name" : "å稱",
195 "settings.service.form.proxy.headline" : "HTTP\/HTTPS Proxy Settings", 217 "settings.service.form.proxy.headline" : "HTTP\/HTTPS 代ç†ä¼ºæœå™¨è¨­å®š",
196 "settings.service.form.proxy.host" : "Proxy Host\/IP", 218 "settings.service.form.proxy.host" : "代ç†ä¼ºæœå™¨ç¶²åŸŸ \/ IP",
197 "settings.service.form.proxy.info" : "Proxy 設定ä¸æœƒèˆ‡ Franz 伺æœå™¨åŒæ­¥", 219 "settings.service.form.proxy.info" : "Proxy 設定ä¸æœƒèˆ‡ Franz 伺æœå™¨åŒæ­¥",
198 "settings.service.form.proxy.isEnabled" : "使用 Proxy", 220 "settings.service.form.proxy.isEnabled" : "使用 Proxy",
199 "settings.service.form.proxy.password" : "密碼 (é¸å¡«)", 221 "settings.service.form.proxy.password" : "密碼 (é¸å¡«)",
200 "settings.service.form.proxy.port" : "Port", 222 "settings.service.form.proxy.port" : "通訊阜",
201 "settings.service.form.proxy.restartInfo" : "Please restart Franz after changing proxy Settings.", 223 "settings.service.form.proxy.restartInfo" : "在變更 Proxy 設定後,請é‡æ–°å•Ÿå‹• Franz",
202 "settings.service.form.proxy.user" : "使用者 (é¸å¡«)", 224 "settings.service.form.proxy.user" : "使用者 (é¸å¡«)",
203 "settings.service.form.saveButton" : "ä¿å­˜æœå‹™", 225 "settings.service.form.saveButton" : "ä¿å­˜æœå‹™",
204 "settings.service.form.spellcheckerLanguage" : "Spell checking Language",
205 "settings.service.form.spellcheckerLanguage.default" : "Use System Default ({default})",
206 "settings.service.form.tabHosted" : "託管", 226 "settings.service.form.tabHosted" : "託管",
207 "settings.service.form.tabOnPremise" : "自我託管â­ï¸", 227 "settings.service.form.tabOnPremise" : "自我託管â­ï¸",
208 "settings.service.form.team" : "團隊", 228 "settings.service.form.team" : "團隊",
@@ -212,10 +232,17 @@
212 "settings.services.discoverServices" : "發ç¾æœå‹™", 232 "settings.services.discoverServices" : "發ç¾æœå‹™",
213 "settings.services.headline" : "您的æœå‹™", 233 "settings.services.headline" : "您的æœå‹™",
214 "settings.services.noServicesAdded" : "你尚未新增任何æœå‹™", 234 "settings.services.noServicesAdded" : "你尚未新增任何æœå‹™",
235 "settings.services.servicesRequestFailed" : "Could not load your services",
215 "settings.services.tooltip.isDisabled" : "æœå‹™å·²åœç”¨", 236 "settings.services.tooltip.isDisabled" : "æœå‹™å·²åœç”¨",
216 "settings.services.tooltip.isMuted" : "所有的è²éŸ³éƒ½æ˜¯éœéŸ³", 237 "settings.services.tooltip.isMuted" : "所有的è²éŸ³éƒ½æ˜¯éœéŸ³",
217 "settings.services.tooltip.notificationsDisabled" : "通知已åœç”¨", 238 "settings.services.tooltip.notificationsDisabled" : "通知已åœç”¨",
218 "settings.services.updatedInfo" : "你的更變已經儲存", 239 "settings.services.updatedInfo" : "已儲存你的變更",
240 "settings.team.contentHeadline" : "Franz for Teams",
241 "settings.team.copy" : "Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
242 "settings.team.headline" : "團隊",
243 "settings.team.intro" : "You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
244 "settings.team.manageAction" : "Manage your Team on meetfranz.com",
245 "settings.team.upgradeAction" : "Upgrade your Account",
219 "settings.user.form.accountType.company" : "å…¬å¸", 246 "settings.user.form.accountType.company" : "å…¬å¸",
220 "settings.user.form.accountType.individual" : "個人", 247 "settings.user.form.accountType.individual" : "個人",
221 "settings.user.form.accountType.label" : "帳戶類型", 248 "settings.user.form.accountType.label" : "帳戶類型",
@@ -225,8 +252,25 @@
225 "settings.user.form.firstname" : "å", 252 "settings.user.form.firstname" : "å",
226 "settings.user.form.lastname" : "姓", 253 "settings.user.form.lastname" : "姓",
227 "settings.user.form.newPassword" : "新密碼", 254 "settings.user.form.newPassword" : "新密碼",
255 "settings.workspace.add.form.name" : "å稱",
256 "settings.workspace.add.form.submitButton" : "Create workspace",
257 "settings.workspace.form.buttonDelete" : "Delete workspace",
258 "settings.workspace.form.buttonSave" : "Save workspace",
259 "settings.workspace.form.name" : "å稱",
260 "settings.workspace.form.servicesInWorkspaceHeadline" : "Services in this Workspace",
261 "settings.workspace.form.yourWorkspaces" : "Your workspaces",
262 "settings.workspaces.deletedInfo" : "Workspace has been deleted",
263 "settings.workspaces.headline" : "Your workspaces",
264 "settings.workspaces.noWorkspacesAdded" : "You haven't added any workspaces yet.",
265 "settings.workspaces.tryReloadWorkspaces" : "å†è©¦ä¸€æ¬¡",
266 "settings.workspaces.updatedInfo" : "Your changes have been saved",
267 "settings.workspaces.workspaceFeatureHeadline" : "Less is More: Introducing Franz Workspaces",
268 "settings.workspaces.workspaceFeatureInfo" : "Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.",
269 "settings.workspaces.workspacesRequestFailed" : "Could not load your workspaces",
228 "sidebar.addNewService" : "新增新的æœå‹™", 270 "sidebar.addNewService" : "新增新的æœå‹™",
271 "sidebar.closeWorkspaceDrawer" : "Close workspace drawer",
229 "sidebar.muteApp" : "關閉通知和通知音效", 272 "sidebar.muteApp" : "關閉通知和通知音效",
273 "sidebar.openWorkspaceDrawer" : "Open workspace drawer",
230 "sidebar.settings" : "設定", 274 "sidebar.settings" : "設定",
231 "sidebar.unmuteApp" : "開啟通知和通知音效", 275 "sidebar.unmuteApp" : "開啟通知和通知音效",
232 "signup.company.label" : "å…¬å¸", 276 "signup.company.label" : "å…¬å¸",
@@ -235,7 +279,7 @@
235 "signup.firstname.label" : "å", 279 "signup.firstname.label" : "å",
236 "signup.headline" : "註冊", 280 "signup.headline" : "註冊",
237 "signup.lastname.label" : "姓", 281 "signup.lastname.label" : "姓",
238 "signup.legal.info" : "你接å—é€éŽå‰µå»ºä¸€å€‹Franz帳戶", 282 "signup.legal.info" : "é€éŽå‰µå»ºä¸€å€‹ Franz 帳戶,你åŒæ„",
239 "signup.legal.privacy" : "éš±ç§è²æ˜Ž", 283 "signup.legal.privacy" : "éš±ç§è²æ˜Ž",
240 "signup.legal.terms" : "æœå‹™æ¢æ¬¾", 284 "signup.legal.terms" : "æœå‹™æ¢æ¬¾",
241 "signup.link.login" : "已經有一個帳戶,登入?", 285 "signup.link.login" : "已經有一個帳戶,登入?",
@@ -244,15 +288,14 @@
244 "subscription.euTaxInfo" : "æ­ç›Ÿå±…民:å¯èƒ½æŽ¡ç”¨ç•¶åœ°éŠ·å”®ç¨…", 288 "subscription.euTaxInfo" : "æ­ç›Ÿå±…民:å¯èƒ½æŽ¡ç”¨ç•¶åœ°éŠ·å”®ç¨…",
245 "subscription.features.ads" : "無廣告,永é !", 289 "subscription.features.ads" : "無廣告,永é !",
246 "subscription.features.comingSoon" : "å³å°‡æŽ¨å‡º", 290 "subscription.features.comingSoon" : "å³å°‡æŽ¨å‡º",
247 "subscription.features.encryptedSync" : "加密的會話åŒæ­¥", 291 "subscription.features.noInterruptions" : "å‡ç´šæŽˆæ¬Šæ²’有延é²èˆ‡æ‰“盹",
248 "subscription.features.noInterruptions" : "No app delays & nagging to upgrade license", 292 "subscription.features.onpremise.mattermost" : "加入如 Mattermost 等已é å®š \/ 託管的æœå‹™",
249 "subscription.features.onpremise" : "添加本地\/託管æœå‹™å¦‚HipChat", 293 "subscription.features.proxy" : "æœå‹™çš„代ç†ä¼ºæœå™¨æ”¯æ´",
250 "subscription.features.onpremise.mattermost" : "Add on-premise\/hosted services like Mattermost",
251 "subscription.features.proxy" : "Proxy support for services",
252 "subscription.features.spellchecker" : "支æ´æ‹¼å­—檢查", 294 "subscription.features.spellchecker" : "支æ´æ‹¼å­—檢查",
253 "subscription.includedFeatures" : "包å«é«˜ç´šFranz付費帳戶", 295 "subscription.features.workspaces" : "Organize your services in workspaces",
296 "subscription.includedFeatures" : "Franz 高級支æ´å¸³æˆ¶åŒ…å«",
254 "subscription.paymentSessionError" : "無法åˆå§‹åŒ–付款表單", 297 "subscription.paymentSessionError" : "無法åˆå§‹åŒ–付款表單",
255 "subscription.submit.label" : "我想支æŒFranz的開發", 298 "subscription.submit.label" : "æˆ‘æƒ³æ”¯æŒ Franz 開發",
256 "subscription.type.free" : "自由", 299 "subscription.type.free" : "自由",
257 "subscription.type.month" : "月", 300 "subscription.type.month" : "月",
258 "subscription.type.year" : "å¹´", 301 "subscription.type.year" : "å¹´",
@@ -269,9 +312,20 @@
269 "tabs.item.reload" : "é‡æ–°è¼‰å…¥", 312 "tabs.item.reload" : "é‡æ–°è¼‰å…¥",
270 "validation.email" : "{field}無效", 313 "validation.email" : "{field}無效",
271 "validation.minLength" : "{field}長度至少應為{length}個字", 314 "validation.minLength" : "{field}長度至少應為{length}個字",
315 "validation.oneRequired" : "At least one is required",
272 "validation.required" : "{field}為必填", 316 "validation.required" : "{field}為必填",
273 "validation.url" : "{field}ä¸æ˜¯å€‹æœ‰æ•ˆçš„網å€", 317 "validation.url" : "{field}ä¸æ˜¯å€‹æœ‰æ•ˆçš„網å€",
274 "welcome.loginButton" : "登入您的帳戶", 318 "welcome.loginButton" : "登入您的帳戶",
275 "welcome.signupButton" : "建立å…費帳號", 319 "welcome.signupButton" : "建立å…費帳號",
276 "welcome.slogan" : "為你通信" 320 "workspaceDrawer.addNewWorkspaceLabel" : "Add new workspace",
321 "workspaceDrawer.allServices" : "所有æœå‹™",
322 "workspaceDrawer.headline" : "Workspaces",
323 "workspaceDrawer.item.contextMenuEdit" : "edit",
324 "workspaceDrawer.item.noServicesAddedYet" : "No services added yet",
325 "workspaceDrawer.premiumCtaButtonLabel" : "Create your first workspace",
326 "workspaceDrawer.proFeatureBadge" : "Premium feature",
327 "workspaceDrawer.reactivatePremiumAccountLabel" : "Reactivate premium account",
328 "workspaceDrawer.workspaceFeatureInfo" : "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.<\/p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.<\/p>",
329 "workspaceDrawer.workspacesSettingsTooltip" : "Edit workspaces settings",
330 "workspaces.switchingIndicator.switchingTo" : "Switching to"
277} 331}
diff --git a/src/i18n/manage-translations.js b/src/i18n/manage-translations.js
new file mode 100644
index 000000000..ee64c9c09
--- /dev/null
+++ b/src/i18n/manage-translations.js
@@ -0,0 +1,9 @@
1require('@babel/register');
2const manageTranslations = require('react-intl-translations-manager').default;
3
4manageTranslations({
5 messagesDirectory: 'src/i18n/messages',
6 translationsDirectory: 'src/i18n/locales',
7 singleMessagesFile: true,
8 languages: ['en-US'],
9});
diff --git a/src/i18n/messages/src/components/auth/Import.json b/src/i18n/messages/src/components/auth/Import.json
new file mode 100644
index 000000000..264fc729b
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Import.json
@@ -0,0 +1,54 @@
1[
2 {
3 "id": "import.headline",
4 "defaultMessage": "!!!Import your Franz 4 services",
5 "file": "src/components/auth/Import.js",
6 "start": {
7 "line": 13,
8 "column": 12
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "import.notSupportedHeadline",
17 "defaultMessage": "!!!Services not yet supported in Franz 5",
18 "file": "src/components/auth/Import.js",
19 "start": {
20 "line": 17,
21 "column": 24
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "import.submit.label",
30 "defaultMessage": "!!!Import {count} services",
31 "file": "src/components/auth/Import.js",
32 "start": {
33 "line": 21,
34 "column": 21
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "import.skip.label",
43 "defaultMessage": "!!!I want to add services manually",
44 "file": "src/components/auth/Import.js",
45 "start": {
46 "line": 25,
47 "column": 19
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Invite.json b/src/i18n/messages/src/components/auth/Invite.json
new file mode 100644
index 000000000..57c9bddcf
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Invite.json
@@ -0,0 +1,93 @@
1[
2 {
3 "id": "settings.invite.headline",
4 "defaultMessage": "!!!Invite Friends",
5 "file": "src/components/auth/Invite.js",
6 "start": {
7 "line": 16,
8 "column": 20
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "invite.headline.friends",
17 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
18 "file": "src/components/auth/Invite.js",
19 "start": {
20 "line": 20,
21 "column": 12
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "invite.name.label",
30 "defaultMessage": "!!!Name",
31 "file": "src/components/auth/Invite.js",
32 "start": {
33 "line": 24,
34 "column": 13
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "invite.email.label",
43 "defaultMessage": "!!!Email address",
44 "file": "src/components/auth/Invite.js",
45 "start": {
46 "line": 28,
47 "column": 14
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "invite.submit.label",
56 "defaultMessage": "!!!Send invites",
57 "file": "src/components/auth/Invite.js",
58 "start": {
59 "line": 32,
60 "column": 21
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "invite.skip.label",
69 "defaultMessage": "!!!I want to do this later",
70 "file": "src/components/auth/Invite.js",
71 "start": {
72 "line": 36,
73 "column": 19
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "invite.successInfo",
82 "defaultMessage": "!!!Invitations sent successfully",
83 "file": "src/components/auth/Invite.js",
84 "start": {
85 "line": 40,
86 "column": 21
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Login.json b/src/i18n/messages/src/components/auth/Login.json
new file mode 100644
index 000000000..177f6000b
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Login.json
@@ -0,0 +1,119 @@
1[
2 {
3 "id": "login.headline",
4 "defaultMessage": "!!!Sign in",
5 "file": "src/components/auth/Login.js",
6 "start": {
7 "line": 17,
8 "column": 12
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "login.email.label",
17 "defaultMessage": "!!!Email address",
18 "file": "src/components/auth/Login.js",
19 "start": {
20 "line": 21,
21 "column": 14
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "login.password.label",
30 "defaultMessage": "!!!Password",
31 "file": "src/components/auth/Login.js",
32 "start": {
33 "line": 25,
34 "column": 17
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 },
41 {
42 "id": "login.submit.label",
43 "defaultMessage": "!!!Sign in",
44 "file": "src/components/auth/Login.js",
45 "start": {
46 "line": 29,
47 "column": 21
48 },
49 "end": {
50 "line": 32,
51 "column": 3
52 }
53 },
54 {
55 "id": "login.invalidCredentials",
56 "defaultMessage": "!!!Email or password not valid",
57 "file": "src/components/auth/Login.js",
58 "start": {
59 "line": 33,
60 "column": 22
61 },
62 "end": {
63 "line": 36,
64 "column": 3
65 }
66 },
67 {
68 "id": "login.tokenExpired",
69 "defaultMessage": "!!!Your session expired, please login again.",
70 "file": "src/components/auth/Login.js",
71 "start": {
72 "line": 37,
73 "column": 16
74 },
75 "end": {
76 "line": 40,
77 "column": 3
78 }
79 },
80 {
81 "id": "login.serverLogout",
82 "defaultMessage": "!!!Your session expired, please login again.",
83 "file": "src/components/auth/Login.js",
84 "start": {
85 "line": 41,
86 "column": 16
87 },
88 "end": {
89 "line": 44,
90 "column": 3
91 }
92 },
93 {
94 "id": "login.link.signup",
95 "defaultMessage": "!!!Create a free account",
96 "file": "src/components/auth/Login.js",
97 "start": {
98 "line": 45,
99 "column": 14
100 },
101 "end": {
102 "line": 48,
103 "column": 3
104 }
105 },
106 {
107 "id": "login.link.password",
108 "defaultMessage": "!!!Forgot password",
109 "file": "src/components/auth/Login.js",
110 "start": {
111 "line": 49,
112 "column": 16
113 },
114 "end": {
115 "line": 52,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Password.json b/src/i18n/messages/src/components/auth/Password.json
new file mode 100644
index 000000000..f335b3acb
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Password.json
@@ -0,0 +1,93 @@
1[
2 {
3 "id": "password.headline",
4 "defaultMessage": "!!!Forgot password",
5 "file": "src/components/auth/Password.js",
6 "start": {
7 "line": 14,
8 "column": 12
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "password.email.label",
17 "defaultMessage": "!!!Email address",
18 "file": "src/components/auth/Password.js",
19 "start": {
20 "line": 18,
21 "column": 14
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "password.submit.label",
30 "defaultMessage": "!!!Submit",
31 "file": "src/components/auth/Password.js",
32 "start": {
33 "line": 22,
34 "column": 21
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "password.successInfo",
43 "defaultMessage": "!!!Your new password was sent to your email address",
44 "file": "src/components/auth/Password.js",
45 "start": {
46 "line": 26,
47 "column": 15
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "password.noUser",
56 "defaultMessage": "!!!No user affiliated with that email address",
57 "file": "src/components/auth/Password.js",
58 "start": {
59 "line": 30,
60 "column": 10
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "password.link.signup",
69 "defaultMessage": "!!!Create a free account",
70 "file": "src/components/auth/Password.js",
71 "start": {
72 "line": 34,
73 "column": 14
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "password.link.login",
82 "defaultMessage": "!!!Sign in to your account",
83 "file": "src/components/auth/Password.js",
84 "start": {
85 "line": 38,
86 "column": 13
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Pricing.json b/src/i18n/messages/src/components/auth/Pricing.json
new file mode 100644
index 000000000..f711a55b4
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Pricing.json
@@ -0,0 +1,54 @@
1[
2 {
3 "id": "pricing.headline",
4 "defaultMessage": "!!!Support Franz",
5 "file": "src/components/auth/Pricing.js",
6 "start": {
7 "line": 13,
8 "column": 12
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "pricing.support.label",
17 "defaultMessage": "!!!Select your support plan",
18 "file": "src/components/auth/Pricing.js",
19 "start": {
20 "line": 17,
21 "column": 23
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "pricing.submit.label",
30 "defaultMessage": "!!!Support the development of Franz",
31 "file": "src/components/auth/Pricing.js",
32 "start": {
33 "line": 21,
34 "column": 21
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "pricing.link.skipPayment",
43 "defaultMessage": "!!!I don't want to support the development of Franz.",
44 "file": "src/components/auth/Pricing.js",
45 "start": {
46 "line": 25,
47 "column": 15
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Signup.json b/src/i18n/messages/src/components/auth/Signup.json
new file mode 100644
index 000000000..a09745048
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Signup.json
@@ -0,0 +1,158 @@
1[
2 {
3 "id": "signup.headline",
4 "defaultMessage": "!!!Sign up",
5 "file": "src/components/auth/Signup.js",
6 "start": {
7 "line": 18,
8 "column": 12
9 },
10 "end": {
11 "line": 21,
12 "column": 3
13 }
14 },
15 {
16 "id": "signup.firstname.label",
17 "defaultMessage": "!!!Firstname",
18 "file": "src/components/auth/Signup.js",
19 "start": {
20 "line": 22,
21 "column": 18
22 },
23 "end": {
24 "line": 25,
25 "column": 3
26 }
27 },
28 {
29 "id": "signup.lastname.label",
30 "defaultMessage": "!!!Lastname",
31 "file": "src/components/auth/Signup.js",
32 "start": {
33 "line": 26,
34 "column": 17
35 },
36 "end": {
37 "line": 29,
38 "column": 3
39 }
40 },
41 {
42 "id": "signup.email.label",
43 "defaultMessage": "!!!Email address",
44 "file": "src/components/auth/Signup.js",
45 "start": {
46 "line": 30,
47 "column": 14
48 },
49 "end": {
50 "line": 33,
51 "column": 3
52 }
53 },
54 {
55 "id": "signup.company.label",
56 "defaultMessage": "!!!Company",
57 "file": "src/components/auth/Signup.js",
58 "start": {
59 "line": 34,
60 "column": 16
61 },
62 "end": {
63 "line": 37,
64 "column": 3
65 }
66 },
67 {
68 "id": "signup.password.label",
69 "defaultMessage": "!!!Password",
70 "file": "src/components/auth/Signup.js",
71 "start": {
72 "line": 38,
73 "column": 17
74 },
75 "end": {
76 "line": 41,
77 "column": 3
78 }
79 },
80 {
81 "id": "signup.legal.info",
82 "defaultMessage": "!!!By creating a Franz account you accept the",
83 "file": "src/components/auth/Signup.js",
84 "start": {
85 "line": 42,
86 "column": 13
87 },
88 "end": {
89 "line": 45,
90 "column": 3
91 }
92 },
93 {
94 "id": "signup.legal.terms",
95 "defaultMessage": "!!!Terms of service",
96 "file": "src/components/auth/Signup.js",
97 "start": {
98 "line": 46,
99 "column": 9
100 },
101 "end": {
102 "line": 49,
103 "column": 3
104 }
105 },
106 {
107 "id": "signup.legal.privacy",
108 "defaultMessage": "!!!Privacy Statement",
109 "file": "src/components/auth/Signup.js",
110 "start": {
111 "line": 50,
112 "column": 11
113 },
114 "end": {
115 "line": 53,
116 "column": 3
117 }
118 },
119 {
120 "id": "signup.submit.label",
121 "defaultMessage": "!!!Create account",
122 "file": "src/components/auth/Signup.js",
123 "start": {
124 "line": 54,
125 "column": 21
126 },
127 "end": {
128 "line": 57,
129 "column": 3
130 }
131 },
132 {
133 "id": "signup.link.login",
134 "defaultMessage": "!!!Already have an account, sign in?",
135 "file": "src/components/auth/Signup.js",
136 "start": {
137 "line": 58,
138 "column": 13
139 },
140 "end": {
141 "line": 61,
142 "column": 3
143 }
144 },
145 {
146 "id": "signup.emailDuplicate",
147 "defaultMessage": "!!!A user with that email address already exists",
148 "file": "src/components/auth/Signup.js",
149 "start": {
150 "line": 62,
151 "column": 18
152 },
153 "end": {
154 "line": 65,
155 "column": 3
156 }
157 }
158] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Welcome.json b/src/i18n/messages/src/components/auth/Welcome.json
new file mode 100644
index 000000000..b4d2ce689
--- /dev/null
+++ b/src/i18n/messages/src/components/auth/Welcome.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "welcome.signupButton",
4 "defaultMessage": "!!!Create a free account",
5 "file": "src/components/auth/Welcome.js",
6 "start": {
7 "line": 9,
8 "column": 16
9 },
10 "end": {
11 "line": 12,
12 "column": 3
13 }
14 },
15 {
16 "id": "welcome.loginButton",
17 "defaultMessage": "!!!Login to your account",
18 "file": "src/components/auth/Welcome.js",
19 "start": {
20 "line": 13,
21 "column": 15
22 },
23 "end": {
24 "line": 16,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/layout/AppLayout.json b/src/i18n/messages/src/components/layout/AppLayout.json
new file mode 100644
index 000000000..26b8ce040
--- /dev/null
+++ b/src/i18n/messages/src/components/layout/AppLayout.json
@@ -0,0 +1,80 @@
1[
2 {
3 "id": "infobar.servicesUpdated",
4 "defaultMessage": "!!!Your services have been updated.",
5 "file": "src/components/layout/AppLayout.js",
6 "start": {
7 "line": 27,
8 "column": 19
9 },
10 "end": {
11 "line": 30,
12 "column": 3
13 }
14 },
15 {
16 "id": "infobar.updateAvailable",
17 "defaultMessage": "!!!A new update for Franz is available.",
18 "file": "src/components/layout/AppLayout.js",
19 "start": {
20 "line": 31,
21 "column": 19
22 },
23 "end": {
24 "line": 34,
25 "column": 3
26 }
27 },
28 {
29 "id": "infobar.buttonReloadServices",
30 "defaultMessage": "!!!Reload services",
31 "file": "src/components/layout/AppLayout.js",
32 "start": {
33 "line": 35,
34 "column": 24
35 },
36 "end": {
37 "line": 38,
38 "column": 3
39 }
40 },
41 {
42 "id": "infobar.buttonChangelog",
43 "defaultMessage": "!!!Changelog",
44 "file": "src/components/layout/AppLayout.js",
45 "start": {
46 "line": 39,
47 "column": 13
48 },
49 "end": {
50 "line": 42,
51 "column": 3
52 }
53 },
54 {
55 "id": "infobar.buttonInstallUpdate",
56 "defaultMessage": "!!!Restart & install update",
57 "file": "src/components/layout/AppLayout.js",
58 "start": {
59 "line": 43,
60 "column": 23
61 },
62 "end": {
63 "line": 46,
64 "column": 3
65 }
66 },
67 {
68 "id": "infobar.requiredRequestsFailed",
69 "defaultMessage": "!!!Could not load services and user information",
70 "file": "src/components/layout/AppLayout.js",
71 "start": {
72 "line": 47,
73 "column": 26
74 },
75 "end": {
76 "line": 50,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/layout/Sidebar.json b/src/i18n/messages/src/components/layout/Sidebar.json
new file mode 100644
index 000000000..d67adc96e
--- /dev/null
+++ b/src/i18n/messages/src/components/layout/Sidebar.json
@@ -0,0 +1,80 @@
1[
2 {
3 "id": "sidebar.settings",
4 "defaultMessage": "!!!Settings",
5 "file": "src/components/layout/Sidebar.js",
6 "start": {
7 "line": 13,
8 "column": 12
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "sidebar.addNewService",
17 "defaultMessage": "!!!Add new service",
18 "file": "src/components/layout/Sidebar.js",
19 "start": {
20 "line": 17,
21 "column": 17
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "sidebar.muteApp",
30 "defaultMessage": "!!!Disable notifications & audio",
31 "file": "src/components/layout/Sidebar.js",
32 "start": {
33 "line": 21,
34 "column": 8
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "sidebar.unmuteApp",
43 "defaultMessage": "!!!Enable notifications & audio",
44 "file": "src/components/layout/Sidebar.js",
45 "start": {
46 "line": 25,
47 "column": 10
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "sidebar.openWorkspaceDrawer",
56 "defaultMessage": "!!!Open workspace drawer",
57 "file": "src/components/layout/Sidebar.js",
58 "start": {
59 "line": 29,
60 "column": 23
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 },
67 {
68 "id": "sidebar.closeWorkspaceDrawer",
69 "defaultMessage": "!!!Close workspace drawer",
70 "file": "src/components/layout/Sidebar.js",
71 "start": {
72 "line": 33,
73 "column": 24
74 },
75 "end": {
76 "line": 36,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json b/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json
new file mode 100644
index 000000000..c8fe802df
--- /dev/null
+++ b/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json
@@ -0,0 +1,67 @@
1[
2 {
3 "id": "service.errorHandler.headline",
4 "defaultMessage": "!!!Oh no!",
5 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
6 "start": {
7 "line": 12,
8 "column": 12
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.errorHandler.text",
17 "defaultMessage": "!!!{name} has failed to load.",
18 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
19 "start": {
20 "line": 16,
21 "column": 8
22 },
23 "end": {
24 "line": 19,
25 "column": 3
26 }
27 },
28 {
29 "id": "service.errorHandler.action",
30 "defaultMessage": "!!!Reload {name}",
31 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
32 "start": {
33 "line": 20,
34 "column": 10
35 },
36 "end": {
37 "line": 23,
38 "column": 3
39 }
40 },
41 {
42 "id": "service.errorHandler.editAction",
43 "defaultMessage": "!!!Edit {name}",
44 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
45 "start": {
46 "line": 24,
47 "column": 14
48 },
49 "end": {
50 "line": 27,
51 "column": 3
52 }
53 },
54 {
55 "id": "service.errorHandler.message",
56 "defaultMessage": "!!!Error:",
57 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
58 "start": {
59 "line": 28,
60 "column": 16
61 },
62 "end": {
63 "line": 31,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ServiceDisabled.json b/src/i18n/messages/src/components/services/content/ServiceDisabled.json
new file mode 100644
index 000000000..8bfad28c7
--- /dev/null
+++ b/src/i18n/messages/src/components/services/content/ServiceDisabled.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "service.disabledHandler.headline",
4 "defaultMessage": "!!!{name} is disabled",
5 "file": "src/components/services/content/ServiceDisabled.js",
6 "start": {
7 "line": 9,
8 "column": 12
9 },
10 "end": {
11 "line": 12,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.disabledHandler.action",
17 "defaultMessage": "!!!Enable {name}",
18 "file": "src/components/services/content/ServiceDisabled.js",
19 "start": {
20 "line": 13,
21 "column": 10
22 },
23 "end": {
24 "line": 16,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/Services.json b/src/i18n/messages/src/components/services/content/Services.json
new file mode 100644
index 000000000..884ab0c90
--- /dev/null
+++ b/src/i18n/messages/src/components/services/content/Services.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "services.welcome",
4 "defaultMessage": "!!!Welcome to Franz",
5 "file": "src/components/services/content/Services.js",
6 "start": {
7 "line": 11,
8 "column": 11
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "services.getStarted",
17 "defaultMessage": "!!!Get started",
18 "file": "src/components/services/content/Services.js",
19 "start": {
20 "line": 15,
21 "column": 14
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json b/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json
new file mode 100644
index 000000000..c3d6c41a5
--- /dev/null
+++ b/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json
@@ -0,0 +1,54 @@
1[
2 {
3 "id": "service.crashHandler.headline",
4 "defaultMessage": "!!!Oh no!",
5 "file": "src/components/services/content/WebviewCrashHandler.js",
6 "start": {
7 "line": 10,
8 "column": 12
9 },
10 "end": {
11 "line": 13,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.crashHandler.text",
17 "defaultMessage": "!!!{name} has caused an error.",
18 "file": "src/components/services/content/WebviewCrashHandler.js",
19 "start": {
20 "line": 14,
21 "column": 8
22 },
23 "end": {
24 "line": 17,
25 "column": 3
26 }
27 },
28 {
29 "id": "service.crashHandler.action",
30 "defaultMessage": "!!!Reload {name}",
31 "file": "src/components/services/content/WebviewCrashHandler.js",
32 "start": {
33 "line": 18,
34 "column": 10
35 },
36 "end": {
37 "line": 21,
38 "column": 3
39 }
40 },
41 {
42 "id": "service.crashHandler.autoReload",
43 "defaultMessage": "!!!Trying to automatically restore {name} in {seconds} seconds",
44 "file": "src/components/services/content/WebviewCrashHandler.js",
45 "start": {
46 "line": 22,
47 "column": 14
48 },
49 "end": {
50 "line": 25,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/tabs/TabItem.json b/src/i18n/messages/src/components/services/tabs/TabItem.json
new file mode 100644
index 000000000..08a07845c
--- /dev/null
+++ b/src/i18n/messages/src/components/services/tabs/TabItem.json
@@ -0,0 +1,119 @@
1[
2 {
3 "id": "tabs.item.reload",
4 "defaultMessage": "!!!Reload",
5 "file": "src/components/services/tabs/TabItem.js",
6 "start": {
7 "line": 15,
8 "column": 10
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "tabs.item.edit",
17 "defaultMessage": "!!!Edit",
18 "file": "src/components/services/tabs/TabItem.js",
19 "start": {
20 "line": 19,
21 "column": 8
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "tabs.item.disableNotifications",
30 "defaultMessage": "!!!Disable notifications",
31 "file": "src/components/services/tabs/TabItem.js",
32 "start": {
33 "line": 23,
34 "column": 24
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "tabs.item.enableNotification",
43 "defaultMessage": "!!!Enable notifications",
44 "file": "src/components/services/tabs/TabItem.js",
45 "start": {
46 "line": 27,
47 "column": 23
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "tabs.item.disableAudio",
56 "defaultMessage": "!!!Disable audio",
57 "file": "src/components/services/tabs/TabItem.js",
58 "start": {
59 "line": 31,
60 "column": 16
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "tabs.item.enableAudio",
69 "defaultMessage": "!!!Enable audio",
70 "file": "src/components/services/tabs/TabItem.js",
71 "start": {
72 "line": 35,
73 "column": 15
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "tabs.item.disableService",
82 "defaultMessage": "!!!Disable Service",
83 "file": "src/components/services/tabs/TabItem.js",
84 "start": {
85 "line": 39,
86 "column": 18
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 },
93 {
94 "id": "tabs.item.enableService",
95 "defaultMessage": "!!!Enable Service",
96 "file": "src/components/services/tabs/TabItem.js",
97 "start": {
98 "line": 43,
99 "column": 17
100 },
101 "end": {
102 "line": 46,
103 "column": 3
104 }
105 },
106 {
107 "id": "tabs.item.deleteService",
108 "defaultMessage": "!!!Delete Service",
109 "file": "src/components/services/tabs/TabItem.js",
110 "start": {
111 "line": 47,
112 "column": 17
113 },
114 "end": {
115 "line": 50,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/account/AccountDashboard.json b/src/i18n/messages/src/components/settings/account/AccountDashboard.json
new file mode 100644
index 000000000..4969db910
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/account/AccountDashboard.json
@@ -0,0 +1,197 @@
1[
2 {
3 "id": "settings.account.headline",
4 "defaultMessage": "!!!Account",
5 "file": "src/components/settings/account/AccountDashboard.js",
6 "start": {
7 "line": 14,
8 "column": 12
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.account.headlineSubscription",
17 "defaultMessage": "!!!Your Subscription",
18 "file": "src/components/settings/account/AccountDashboard.js",
19 "start": {
20 "line": 18,
21 "column": 24
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.account.headlineUpgrade",
30 "defaultMessage": "!!!Upgrade your Account",
31 "file": "src/components/settings/account/AccountDashboard.js",
32 "start": {
33 "line": 22,
34 "column": 19
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.account.headlineDangerZone",
43 "defaultMessage": "!!Danger Zone",
44 "file": "src/components/settings/account/AccountDashboard.js",
45 "start": {
46 "line": 26,
47 "column": 22
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.account.manageSubscription.label",
56 "defaultMessage": "!!!Manage your subscription",
57 "file": "src/components/settings/account/AccountDashboard.js",
58 "start": {
59 "line": 30,
60 "column": 33
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.account.accountType.basic",
69 "defaultMessage": "!!!Basic Account",
70 "file": "src/components/settings/account/AccountDashboard.js",
71 "start": {
72 "line": 34,
73 "column": 20
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.account.accountType.premium",
82 "defaultMessage": "!!!Premium Supporter Account",
83 "file": "src/components/settings/account/AccountDashboard.js",
84 "start": {
85 "line": 38,
86 "column": 22
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.account.account.editButton",
95 "defaultMessage": "!!!Edit Account",
96 "file": "src/components/settings/account/AccountDashboard.js",
97 "start": {
98 "line": 42,
99 "column": 21
100 },
101 "end": {
102 "line": 45,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.account.headlineInvoices",
108 "defaultMessage": "!!Invoices",
109 "file": "src/components/settings/account/AccountDashboard.js",
110 "start": {
111 "line": 46,
112 "column": 18
113 },
114 "end": {
115 "line": 49,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.account.invoiceDownload",
121 "defaultMessage": "!!!Download",
122 "file": "src/components/settings/account/AccountDashboard.js",
123 "start": {
124 "line": 50,
125 "column": 19
126 },
127 "end": {
128 "line": 53,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.account.userInfoRequestFailed",
134 "defaultMessage": "!!!Could not load user information",
135 "file": "src/components/settings/account/AccountDashboard.js",
136 "start": {
137 "line": 54,
138 "column": 25
139 },
140 "end": {
141 "line": 57,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.account.tryReloadUserInfoRequest",
147 "defaultMessage": "!!!Try again",
148 "file": "src/components/settings/account/AccountDashboard.js",
149 "start": {
150 "line": 58,
151 "column": 28
152 },
153 "end": {
154 "line": 61,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.account.deleteAccount",
160 "defaultMessage": "!!!Delete account",
161 "file": "src/components/settings/account/AccountDashboard.js",
162 "start": {
163 "line": 62,
164 "column": 17
165 },
166 "end": {
167 "line": 65,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.account.deleteInfo",
173 "defaultMessage": "!!!If you don't need your Franz account any longer, you can delete your account and all related data here.",
174 "file": "src/components/settings/account/AccountDashboard.js",
175 "start": {
176 "line": 66,
177 "column": 14
178 },
179 "end": {
180 "line": 69,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.account.deleteEmailSent",
186 "defaultMessage": "!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
187 "file": "src/components/settings/account/AccountDashboard.js",
188 "start": {
189 "line": 70,
190 "column": 19
191 },
192 "end": {
193 "line": 73,
194 "column": 3
195 }
196 }
197] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
new file mode 100644
index 000000000..70a989211
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
@@ -0,0 +1,106 @@
1[
2 {
3 "id": "settings.navigation.availableServices",
4 "defaultMessage": "!!!Available services",
5 "file": "src/components/settings/navigation/SettingsNavigation.js",
6 "start": {
7 "line": 13,
8 "column": 21
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.navigation.yourServices",
17 "defaultMessage": "!!!Your services",
18 "file": "src/components/settings/navigation/SettingsNavigation.js",
19 "start": {
20 "line": 17,
21 "column": 16
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.navigation.yourWorkspaces",
30 "defaultMessage": "!!!Your workspaces",
31 "file": "src/components/settings/navigation/SettingsNavigation.js",
32 "start": {
33 "line": 21,
34 "column": 18
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.navigation.account",
43 "defaultMessage": "!!!Account",
44 "file": "src/components/settings/navigation/SettingsNavigation.js",
45 "start": {
46 "line": 25,
47 "column": 11
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.navigation.team",
56 "defaultMessage": "!!!Manage Team",
57 "file": "src/components/settings/navigation/SettingsNavigation.js",
58 "start": {
59 "line": 29,
60 "column": 8
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.navigation.settings",
69 "defaultMessage": "!!!Settings",
70 "file": "src/components/settings/navigation/SettingsNavigation.js",
71 "start": {
72 "line": 33,
73 "column": 12
74 },
75 "end": {
76 "line": 36,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.navigation.inviteFriends",
82 "defaultMessage": "!!!Invite Friends",
83 "file": "src/components/settings/navigation/SettingsNavigation.js",
84 "start": {
85 "line": 37,
86 "column": 17
87 },
88 "end": {
89 "line": 40,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.navigation.logout",
95 "defaultMessage": "!!!Logout",
96 "file": "src/components/settings/navigation/SettingsNavigation.js",
97 "start": {
98 "line": 41,
99 "column": 10
100 },
101 "end": {
102 "line": 44,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json b/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json
new file mode 100644
index 000000000..7d9ed3283
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json
@@ -0,0 +1,106 @@
1[
2 {
3 "id": "settings.recipes.headline",
4 "defaultMessage": "!!!Available Services",
5 "file": "src/components/settings/recipes/RecipesDashboard.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.searchService",
17 "defaultMessage": "!!!Search service",
18 "file": "src/components/settings/recipes/RecipesDashboard.js",
19 "start": {
20 "line": 19,
21 "column": 17
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.recipes.mostPopular",
30 "defaultMessage": "!!!Most popular",
31 "file": "src/components/settings/recipes/RecipesDashboard.js",
32 "start": {
33 "line": 23,
34 "column": 22
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.recipes.all",
43 "defaultMessage": "!!!All services",
44 "file": "src/components/settings/recipes/RecipesDashboard.js",
45 "start": {
46 "line": 27,
47 "column": 14
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.recipes.dev",
56 "defaultMessage": "!!!Development",
57 "file": "src/components/settings/recipes/RecipesDashboard.js",
58 "start": {
59 "line": 31,
60 "column": 14
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.recipes.nothingFound",
69 "defaultMessage": "!!!Sorry, but no service matched your search term.",
70 "file": "src/components/settings/recipes/RecipesDashboard.js",
71 "start": {
72 "line": 35,
73 "column": 16
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.recipes.servicesSuccessfulAddedInfo",
82 "defaultMessage": "!!!Service successfully added",
83 "file": "src/components/settings/recipes/RecipesDashboard.js",
84 "start": {
85 "line": 39,
86 "column": 31
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.recipes.missingService",
95 "defaultMessage": "!!!Missing a service?",
96 "file": "src/components/settings/recipes/RecipesDashboard.js",
97 "start": {
98 "line": 43,
99 "column": 18
100 },
101 "end": {
102 "line": 46,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/EditServiceForm.json b/src/i18n/messages/src/components/settings/services/EditServiceForm.json
new file mode 100644
index 000000000..42b741b7a
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/services/EditServiceForm.json
@@ -0,0 +1,288 @@
1[
2 {
3 "id": "settings.service.form.saveButton",
4 "defaultMessage": "!!!Save service",
5 "file": "src/components/settings/services/EditServiceForm.js",
6 "start": {
7 "line": 22,
8 "column": 15
9 },
10 "end": {
11 "line": 25,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.form.deleteButton",
17 "defaultMessage": "!!!Delete Service",
18 "file": "src/components/settings/services/EditServiceForm.js",
19 "start": {
20 "line": 26,
21 "column": 17
22 },
23 "end": {
24 "line": 29,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.availableServices",
30 "defaultMessage": "!!!Available services",
31 "file": "src/components/settings/services/EditServiceForm.js",
32 "start": {
33 "line": 30,
34 "column": 21
35 },
36 "end": {
37 "line": 33,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.form.yourServices",
43 "defaultMessage": "!!!Your services",
44 "file": "src/components/settings/services/EditServiceForm.js",
45 "start": {
46 "line": 34,
47 "column": 16
48 },
49 "end": {
50 "line": 37,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.service.form.addServiceHeadline",
56 "defaultMessage": "!!!Add {name}",
57 "file": "src/components/settings/services/EditServiceForm.js",
58 "start": {
59 "line": 38,
60 "column": 22
61 },
62 "end": {
63 "line": 41,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.service.form.editServiceHeadline",
69 "defaultMessage": "!!!Edit {name}",
70 "file": "src/components/settings/services/EditServiceForm.js",
71 "start": {
72 "line": 42,
73 "column": 23
74 },
75 "end": {
76 "line": 45,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.service.form.tabHosted",
82 "defaultMessage": "!!!Hosted",
83 "file": "src/components/settings/services/EditServiceForm.js",
84 "start": {
85 "line": 46,
86 "column": 13
87 },
88 "end": {
89 "line": 49,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.service.form.tabOnPremise",
95 "defaultMessage": "!!!Self hosted â­ï¸",
96 "file": "src/components/settings/services/EditServiceForm.js",
97 "start": {
98 "line": 50,
99 "column": 16
100 },
101 "end": {
102 "line": 53,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.service.form.useHostedService",
108 "defaultMessage": "!!!Use the hosted {name} service.",
109 "file": "src/components/settings/services/EditServiceForm.js",
110 "start": {
111 "line": 54,
112 "column": 20
113 },
114 "end": {
115 "line": 57,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.service.form.customUrlValidationError",
121 "defaultMessage": "!!!Could not validate custom {name} server.",
122 "file": "src/components/settings/services/EditServiceForm.js",
123 "start": {
124 "line": 58,
125 "column": 28
126 },
127 "end": {
128 "line": 61,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.service.form.customUrlPremiumInfo",
134 "defaultMessage": "!!!To add self hosted services, you need a Franz Premium Supporter Account.",
135 "file": "src/components/settings/services/EditServiceForm.js",
136 "start": {
137 "line": 62,
138 "column": 24
139 },
140 "end": {
141 "line": 65,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.service.form.customUrlUpgradeAccount",
147 "defaultMessage": "!!!Upgrade your account",
148 "file": "src/components/settings/services/EditServiceForm.js",
149 "start": {
150 "line": 66,
151 "column": 27
152 },
153 "end": {
154 "line": 69,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.service.form.indirectMessageInfo",
160 "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...",
161 "file": "src/components/settings/services/EditServiceForm.js",
162 "start": {
163 "line": 70,
164 "column": 23
165 },
166 "end": {
167 "line": 73,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.service.form.isMutedInfo",
173 "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted",
174 "file": "src/components/settings/services/EditServiceForm.js",
175 "start": {
176 "line": 74,
177 "column": 15
178 },
179 "end": {
180 "line": 77,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.service.form.headlineNotifications",
186 "defaultMessage": "!!!Notifications",
187 "file": "src/components/settings/services/EditServiceForm.js",
188 "start": {
189 "line": 78,
190 "column": 25
191 },
192 "end": {
193 "line": 81,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.service.form.headlineBadges",
199 "defaultMessage": "!!!Unread message badges",
200 "file": "src/components/settings/services/EditServiceForm.js",
201 "start": {
202 "line": 82,
203 "column": 18
204 },
205 "end": {
206 "line": 85,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.service.form.headlineGeneral",
212 "defaultMessage": "!!!General",
213 "file": "src/components/settings/services/EditServiceForm.js",
214 "start": {
215 "line": 86,
216 "column": 19
217 },
218 "end": {
219 "line": 89,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.service.form.iconDelete",
225 "defaultMessage": "!!!Delete",
226 "file": "src/components/settings/services/EditServiceForm.js",
227 "start": {
228 "line": 90,
229 "column": 14
230 },
231 "end": {
232 "line": 93,
233 "column": 3
234 }
235 },
236 {
237 "id": "settings.service.form.iconUpload",
238 "defaultMessage": "!!!Drop your image, or click here",
239 "file": "src/components/settings/services/EditServiceForm.js",
240 "start": {
241 "line": 94,
242 "column": 14
243 },
244 "end": {
245 "line": 97,
246 "column": 3
247 }
248 },
249 {
250 "id": "settings.service.form.proxy.headline",
251 "defaultMessage": "!!!HTTP/HTTPS Proxy Settings",
252 "file": "src/components/settings/services/EditServiceForm.js",
253 "start": {
254 "line": 98,
255 "column": 17
256 },
257 "end": {
258 "line": 101,
259 "column": 3
260 }
261 },
262 {
263 "id": "settings.service.form.proxy.restartInfo",
264 "defaultMessage": "!!!Please restart Franz after changing proxy Settings.",
265 "file": "src/components/settings/services/EditServiceForm.js",
266 "start": {
267 "line": 102,
268 "column": 20
269 },
270 "end": {
271 "line": 105,
272 "column": 3
273 }
274 },
275 {
276 "id": "settings.service.form.proxy.info",
277 "defaultMessage": "!!!Proxy settings will not be synchronized with the Franz servers.",
278 "file": "src/components/settings/services/EditServiceForm.js",
279 "start": {
280 "line": 106,
281 "column": 13
282 },
283 "end": {
284 "line": 109,
285 "column": 3
286 }
287 }
288] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServiceError.json b/src/i18n/messages/src/components/settings/services/ServiceError.json
new file mode 100644
index 000000000..648fc5b3e
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/services/ServiceError.json
@@ -0,0 +1,54 @@
1[
2 {
3 "id": "settings.service.error.headline",
4 "defaultMessage": "!!!Error",
5 "file": "src/components/settings/services/ServiceError.js",
6 "start": {
7 "line": 10,
8 "column": 12
9 },
10 "end": {
11 "line": 13,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.error.goBack",
17 "defaultMessage": "!!!Back to services",
18 "file": "src/components/settings/services/ServiceError.js",
19 "start": {
20 "line": 14,
21 "column": 10
22 },
23 "end": {
24 "line": 17,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.availableServices",
30 "defaultMessage": "!!!Available services",
31 "file": "src/components/settings/services/ServiceError.js",
32 "start": {
33 "line": 18,
34 "column": 21
35 },
36 "end": {
37 "line": 21,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.error.message",
43 "defaultMessage": "!!!Could not load service recipe.",
44 "file": "src/components/settings/services/ServiceError.js",
45 "start": {
46 "line": 22,
47 "column": 16
48 },
49 "end": {
50 "line": 25,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServiceItem.json b/src/i18n/messages/src/components/settings/services/ServiceItem.json
new file mode 100644
index 000000000..ffea8b9e1
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/services/ServiceItem.json
@@ -0,0 +1,41 @@
1[
2 {
3 "id": "settings.services.tooltip.isDisabled",
4 "defaultMessage": "!!!Service is disabled",
5 "file": "src/components/settings/services/ServiceItem.js",
6 "start": {
7 "line": 11,
8 "column": 21
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.services.tooltip.notificationsDisabled",
17 "defaultMessage": "!!!Notifications are disabled",
18 "file": "src/components/settings/services/ServiceItem.js",
19 "start": {
20 "line": 15,
21 "column": 32
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.services.tooltip.isMuted",
30 "defaultMessage": "!!!All sounds are muted",
31 "file": "src/components/settings/services/ServiceItem.js",
32 "start": {
33 "line": 19,
34 "column": 18
35 },
36 "end": {
37 "line": 22,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServicesDashboard.json b/src/i18n/messages/src/components/settings/services/ServicesDashboard.json
new file mode 100644
index 000000000..3803c6512
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/services/ServicesDashboard.json
@@ -0,0 +1,119 @@
1[
2 {
3 "id": "settings.services.headline",
4 "defaultMessage": "!!!Your services",
5 "file": "src/components/settings/services/ServicesDashboard.js",
6 "start": {
7 "line": 14,
8 "column": 12
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.searchService",
17 "defaultMessage": "!!!Search service",
18 "file": "src/components/settings/services/ServicesDashboard.js",
19 "start": {
20 "line": 18,
21 "column": 17
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.services.noServicesAdded",
30 "defaultMessage": "!!!You haven't added any services yet.",
31 "file": "src/components/settings/services/ServicesDashboard.js",
32 "start": {
33 "line": 22,
34 "column": 19
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.recipes.nothingFound",
43 "defaultMessage": "!!!Sorry, but no service matched your search term.",
44 "file": "src/components/settings/services/ServicesDashboard.js",
45 "start": {
46 "line": 26,
47 "column": 18
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.services.discoverServices",
56 "defaultMessage": "!!!Discover services",
57 "file": "src/components/settings/services/ServicesDashboard.js",
58 "start": {
59 "line": 30,
60 "column": 20
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.services.servicesRequestFailed",
69 "defaultMessage": "!!!Could not load your services",
70 "file": "src/components/settings/services/ServicesDashboard.js",
71 "start": {
72 "line": 34,
73 "column": 25
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.account.tryReloadServices",
82 "defaultMessage": "!!!Try again",
83 "file": "src/components/settings/services/ServicesDashboard.js",
84 "start": {
85 "line": 38,
86 "column": 21
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.services.updatedInfo",
95 "defaultMessage": "!!!Your changes have been saved",
96 "file": "src/components/settings/services/ServicesDashboard.js",
97 "start": {
98 "line": 42,
99 "column": 15
100 },
101 "end": {
102 "line": 45,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.services.deletedInfo",
108 "defaultMessage": "!!!Service has been deleted",
109 "file": "src/components/settings/services/ServicesDashboard.js",
110 "start": {
111 "line": 46,
112 "column": 15
113 },
114 "end": {
115 "line": 49,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
new file mode 100644
index 000000000..fa21db10a
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
@@ -0,0 +1,236 @@
1[
2 {
3 "id": "settings.app.headline",
4 "defaultMessage": "!!!Settings",
5 "file": "src/components/settings/settings/EditSettingsForm.js",
6 "start": {
7 "line": 16,
8 "column": 12
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.app.headlineGeneral",
17 "defaultMessage": "!!!General",
18 "file": "src/components/settings/settings/EditSettingsForm.js",
19 "start": {
20 "line": 20,
21 "column": 19
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.app.headlineLanguage",
30 "defaultMessage": "!!!Language",
31 "file": "src/components/settings/settings/EditSettingsForm.js",
32 "start": {
33 "line": 24,
34 "column": 20
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.app.headlineUpdates",
43 "defaultMessage": "!!!Updates",
44 "file": "src/components/settings/settings/EditSettingsForm.js",
45 "start": {
46 "line": 28,
47 "column": 19
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.app.headlineAppearance",
56 "defaultMessage": "!!!Appearance",
57 "file": "src/components/settings/settings/EditSettingsForm.js",
58 "start": {
59 "line": 32,
60 "column": 22
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.app.headlineAdvanced",
69 "defaultMessage": "!!!Advanced",
70 "file": "src/components/settings/settings/EditSettingsForm.js",
71 "start": {
72 "line": 36,
73 "column": 20
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.app.translationHelp",
82 "defaultMessage": "!!!Help us to translate Franz into your language.",
83 "file": "src/components/settings/settings/EditSettingsForm.js",
84 "start": {
85 "line": 40,
86 "column": 19
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.app.subheadlineCache",
95 "defaultMessage": "!!!Cache",
96 "file": "src/components/settings/settings/EditSettingsForm.js",
97 "start": {
98 "line": 44,
99 "column": 20
100 },
101 "end": {
102 "line": 47,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.app.cacheInfo",
108 "defaultMessage": "!!!Franz cache is currently using {size} of disk space.",
109 "file": "src/components/settings/settings/EditSettingsForm.js",
110 "start": {
111 "line": 48,
112 "column": 13
113 },
114 "end": {
115 "line": 51,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.app.buttonClearAllCache",
121 "defaultMessage": "!!!Clear cache",
122 "file": "src/components/settings/settings/EditSettingsForm.js",
123 "start": {
124 "line": 52,
125 "column": 23
126 },
127 "end": {
128 "line": 55,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.app.buttonSearchForUpdate",
134 "defaultMessage": "!!!Check for updates",
135 "file": "src/components/settings/settings/EditSettingsForm.js",
136 "start": {
137 "line": 56,
138 "column": 25
139 },
140 "end": {
141 "line": 59,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.app.buttonInstallUpdate",
147 "defaultMessage": "!!!Restart & install update",
148 "file": "src/components/settings/settings/EditSettingsForm.js",
149 "start": {
150 "line": 60,
151 "column": 23
152 },
153 "end": {
154 "line": 63,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.app.updateStatusSearching",
160 "defaultMessage": "!!!Is searching for update",
161 "file": "src/components/settings/settings/EditSettingsForm.js",
162 "start": {
163 "line": 64,
164 "column": 25
165 },
166 "end": {
167 "line": 67,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.app.updateStatusAvailable",
173 "defaultMessage": "!!!Update available, downloading...",
174 "file": "src/components/settings/settings/EditSettingsForm.js",
175 "start": {
176 "line": 68,
177 "column": 25
178 },
179 "end": {
180 "line": 71,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.app.updateStatusUpToDate",
186 "defaultMessage": "!!!You are using the latest version of Franz",
187 "file": "src/components/settings/settings/EditSettingsForm.js",
188 "start": {
189 "line": 72,
190 "column": 24
191 },
192 "end": {
193 "line": 75,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.app.currentVersion",
199 "defaultMessage": "!!!Current version:",
200 "file": "src/components/settings/settings/EditSettingsForm.js",
201 "start": {
202 "line": 76,
203 "column": 18
204 },
205 "end": {
206 "line": 79,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.app.restartRequired",
212 "defaultMessage": "!!!Changes require restart",
213 "file": "src/components/settings/settings/EditSettingsForm.js",
214 "start": {
215 "line": 80,
216 "column": 29
217 },
218 "end": {
219 "line": 83,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.app.languageDisclaimer",
225 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
226 "file": "src/components/settings/settings/EditSettingsForm.js",
227 "start": {
228 "line": 84,
229 "column": 22
230 },
231 "end": {
232 "line": 87,
233 "column": 3
234 }
235 }
236] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/team/TeamDashboard.json b/src/i18n/messages/src/components/settings/team/TeamDashboard.json
new file mode 100644
index 000000000..6bccc25ff
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/team/TeamDashboard.json
@@ -0,0 +1,80 @@
1[
2 {
3 "id": "settings.team.headline",
4 "defaultMessage": "!!!Team",
5 "file": "src/components/settings/team/TeamDashboard.js",
6 "start": {
7 "line": 14,
8 "column": 12
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.team.contentHeadline",
17 "defaultMessage": "!!!Franz for Teams",
18 "file": "src/components/settings/team/TeamDashboard.js",
19 "start": {
20 "line": 18,
21 "column": 19
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.team.intro",
30 "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.",
31 "file": "src/components/settings/team/TeamDashboard.js",
32 "start": {
33 "line": 22,
34 "column": 9
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.team.copy",
43 "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!",
44 "file": "src/components/settings/team/TeamDashboard.js",
45 "start": {
46 "line": 26,
47 "column": 8
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.team.manageAction",
56 "defaultMessage": "!!!Manage your Team on meetfranz.com",
57 "file": "src/components/settings/team/TeamDashboard.js",
58 "start": {
59 "line": 30,
60 "column": 16
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.team.upgradeAction",
69 "defaultMessage": "!!!Upgrade your Account",
70 "file": "src/components/settings/team/TeamDashboard.js",
71 "start": {
72 "line": 34,
73 "column": 17
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/user/EditUserForm.json b/src/i18n/messages/src/components/settings/user/EditUserForm.json
new file mode 100644
index 000000000..3a59f8681
--- /dev/null
+++ b/src/i18n/messages/src/components/settings/user/EditUserForm.json
@@ -0,0 +1,80 @@
1[
2 {
3 "id": "settings.account.headline",
4 "defaultMessage": "!!!Account",
5 "file": "src/components/settings/user/EditUserForm.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.account.headlineProfile",
17 "defaultMessage": "!!!Update Profile",
18 "file": "src/components/settings/user/EditUserForm.js",
19 "start": {
20 "line": 19,
21 "column": 19
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.account.headlineAccount",
30 "defaultMessage": "!!!Account Information",
31 "file": "src/components/settings/user/EditUserForm.js",
32 "start": {
33 "line": 23,
34 "column": 19
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.account.headlinePassword",
43 "defaultMessage": "!!!Change Password",
44 "file": "src/components/settings/user/EditUserForm.js",
45 "start": {
46 "line": 27,
47 "column": 20
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.account.successInfo",
56 "defaultMessage": "!!!Your changes have been saved",
57 "file": "src/components/settings/user/EditUserForm.js",
58 "start": {
59 "line": 31,
60 "column": 15
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.account.buttonSave",
69 "defaultMessage": "!!!Update profile",
70 "file": "src/components/settings/user/EditUserForm.js",
71 "start": {
72 "line": 35,
73 "column": 14
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/subscription/SubscriptionForm.json b/src/i18n/messages/src/components/subscription/SubscriptionForm.json
new file mode 100644
index 000000000..f98eb986f
--- /dev/null
+++ b/src/i18n/messages/src/components/subscription/SubscriptionForm.json
@@ -0,0 +1,184 @@
1[
2 {
3 "id": "subscription.submit.label",
4 "defaultMessage": "!!!Support the development of Franz",
5 "file": "src/components/subscription/SubscriptionForm.js",
6 "start": {
7 "line": 14,
8 "column": 21
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "subscription.paymentSessionError",
17 "defaultMessage": "!!!Could not initialize payment form",
18 "file": "src/components/subscription/SubscriptionForm.js",
19 "start": {
20 "line": 18,
21 "column": 23
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "subscription.type.free",
30 "defaultMessage": "!!!free",
31 "file": "src/components/subscription/SubscriptionForm.js",
32 "start": {
33 "line": 22,
34 "column": 12
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "subscription.type.month",
43 "defaultMessage": "!!!month",
44 "file": "src/components/subscription/SubscriptionForm.js",
45 "start": {
46 "line": 26,
47 "column": 15
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "subscription.type.year",
56 "defaultMessage": "!!!year",
57 "file": "src/components/subscription/SubscriptionForm.js",
58 "start": {
59 "line": 30,
60 "column": 14
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "subscription.includedFeatures",
69 "defaultMessage": "!!!The Franz Premium Supporter Account includes",
70 "file": "src/components/subscription/SubscriptionForm.js",
71 "start": {
72 "line": 34,
73 "column": 20
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "subscription.features.onpremise.mattermost",
82 "defaultMessage": "!!!Add on-premise/hosted services like Mattermost",
83 "file": "src/components/subscription/SubscriptionForm.js",
84 "start": {
85 "line": 38,
86 "column": 13
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "subscription.features.noInterruptions",
95 "defaultMessage": "!!!No app delays & nagging to upgrade license",
96 "file": "src/components/subscription/SubscriptionForm.js",
97 "start": {
98 "line": 42,
99 "column": 19
100 },
101 "end": {
102 "line": 45,
103 "column": 3
104 }
105 },
106 {
107 "id": "subscription.features.proxy",
108 "defaultMessage": "!!!Proxy support for services",
109 "file": "src/components/subscription/SubscriptionForm.js",
110 "start": {
111 "line": 46,
112 "column": 9
113 },
114 "end": {
115 "line": 49,
116 "column": 3
117 }
118 },
119 {
120 "id": "subscription.features.spellchecker",
121 "defaultMessage": "!!!Support for Spellchecker",
122 "file": "src/components/subscription/SubscriptionForm.js",
123 "start": {
124 "line": 50,
125 "column": 16
126 },
127 "end": {
128 "line": 53,
129 "column": 3
130 }
131 },
132 {
133 "id": "subscription.features.workspaces",
134 "defaultMessage": "!!!Organize your services in workspaces",
135 "file": "src/components/subscription/SubscriptionForm.js",
136 "start": {
137 "line": 54,
138 "column": 14
139 },
140 "end": {
141 "line": 57,
142 "column": 3
143 }
144 },
145 {
146 "id": "subscription.features.ads",
147 "defaultMessage": "!!!No ads, ever!",
148 "file": "src/components/subscription/SubscriptionForm.js",
149 "start": {
150 "line": 58,
151 "column": 7
152 },
153 "end": {
154 "line": 61,
155 "column": 3
156 }
157 },
158 {
159 "id": "subscription.features.comingSoon",
160 "defaultMessage": "!!!coming soon",
161 "file": "src/components/subscription/SubscriptionForm.js",
162 "start": {
163 "line": 62,
164 "column": 14
165 },
166 "end": {
167 "line": 65,
168 "column": 3
169 }
170 },
171 {
172 "id": "subscription.euTaxInfo",
173 "defaultMessage": "!!!EU residents: local sales tax may apply",
174 "file": "src/components/subscription/SubscriptionForm.js",
175 "start": {
176 "line": 66,
177 "column": 13
178 },
179 "end": {
180 "line": 69,
181 "column": 3
182 }
183 }
184] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/subscription/SubscriptionPopup.json b/src/i18n/messages/src/components/subscription/SubscriptionPopup.json
new file mode 100644
index 000000000..c06da7531
--- /dev/null
+++ b/src/i18n/messages/src/components/subscription/SubscriptionPopup.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "subscriptionPopup.buttonCancel",
4 "defaultMessage": "!!!Cancel",
5 "file": "src/components/subscription/SubscriptionPopup.js",
6 "start": {
7 "line": 11,
8 "column": 16
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "subscriptionPopup.buttonDone",
17 "defaultMessage": "!!!Done",
18 "file": "src/components/subscription/SubscriptionPopup.js",
19 "start": {
20 "line": 15,
21 "column": 14
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json
new file mode 100644
index 000000000..320d3ca3e
--- /dev/null
+++ b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json
@@ -0,0 +1,15 @@
1[
2 {
3 "id": "premiumFeature.button.upgradeAccount",
4 "defaultMessage": "!!!Upgrade account",
5 "file": "src/components/ui/PremiumFeatureContainer/index.js",
6 "start": {
7 "line": 15,
8 "column": 10
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/WebviewLoader/index.json b/src/i18n/messages/src/components/ui/WebviewLoader/index.json
new file mode 100644
index 000000000..ef3e4b593
--- /dev/null
+++ b/src/i18n/messages/src/components/ui/WebviewLoader/index.json
@@ -0,0 +1,15 @@
1[
2 {
3 "id": "service.webviewLoader.loading",
4 "defaultMessage": "!!!Loading",
5 "file": "src/components/ui/WebviewLoader/index.js",
6 "start": {
7 "line": 11,
8 "column": 11
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/util/ErrorBoundary/index.json b/src/i18n/messages/src/components/util/ErrorBoundary/index.json
new file mode 100644
index 000000000..43c323031
--- /dev/null
+++ b/src/i18n/messages/src/components/util/ErrorBoundary/index.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "app.errorHandler.headline",
4 "defaultMessage": "!!!Something went wrong.",
5 "file": "src/components/util/ErrorBoundary/index.js",
6 "start": {
7 "line": 11,
8 "column": 12
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "app.errorHandler.action",
17 "defaultMessage": "!!!Reload",
18 "file": "src/components/util/ErrorBoundary/index.js",
19 "start": {
20 "line": 15,
21 "column": 10
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditServiceScreen.json b/src/i18n/messages/src/containers/settings/EditServiceScreen.json
new file mode 100644
index 000000000..42ca42125
--- /dev/null
+++ b/src/i18n/messages/src/containers/settings/EditServiceScreen.json
@@ -0,0 +1,197 @@
1[
2 {
3 "id": "settings.service.form.name",
4 "defaultMessage": "!!!Name",
5 "file": "src/containers/settings/EditServiceScreen.js",
6 "start": {
7 "line": 28,
8 "column": 8
9 },
10 "end": {
11 "line": 31,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.form.enableService",
17 "defaultMessage": "!!!Enable service",
18 "file": "src/containers/settings/EditServiceScreen.js",
19 "start": {
20 "line": 32,
21 "column": 17
22 },
23 "end": {
24 "line": 35,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.enableNotification",
30 "defaultMessage": "!!!Enable Notifications",
31 "file": "src/containers/settings/EditServiceScreen.js",
32 "start": {
33 "line": 36,
34 "column": 22
35 },
36 "end": {
37 "line": 39,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.form.enableBadge",
43 "defaultMessage": "!!!Show unread message badges",
44 "file": "src/containers/settings/EditServiceScreen.js",
45 "start": {
46 "line": 40,
47 "column": 15
48 },
49 "end": {
50 "line": 43,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.service.form.enableAudio",
56 "defaultMessage": "!!!Enable audio",
57 "file": "src/containers/settings/EditServiceScreen.js",
58 "start": {
59 "line": 44,
60 "column": 15
61 },
62 "end": {
63 "line": 47,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.service.form.team",
69 "defaultMessage": "!!!Team",
70 "file": "src/containers/settings/EditServiceScreen.js",
71 "start": {
72 "line": 48,
73 "column": 8
74 },
75 "end": {
76 "line": 51,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.service.form.customUrl",
82 "defaultMessage": "!!!Custom server",
83 "file": "src/containers/settings/EditServiceScreen.js",
84 "start": {
85 "line": 52,
86 "column": 13
87 },
88 "end": {
89 "line": 55,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.service.form.indirectMessages",
95 "defaultMessage": "!!!Show message badge for all new messages",
96 "file": "src/containers/settings/EditServiceScreen.js",
97 "start": {
98 "line": 56,
99 "column": 20
100 },
101 "end": {
102 "line": 59,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.service.form.icon",
108 "defaultMessage": "!!!Custom icon",
109 "file": "src/containers/settings/EditServiceScreen.js",
110 "start": {
111 "line": 60,
112 "column": 8
113 },
114 "end": {
115 "line": 63,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.service.form.enableDarkMode",
121 "defaultMessage": "!!!Enable Dark Mode",
122 "file": "src/containers/settings/EditServiceScreen.js",
123 "start": {
124 "line": 64,
125 "column": 18
126 },
127 "end": {
128 "line": 67,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.service.form.proxy.isEnabled",
134 "defaultMessage": "!!!Use Proxy",
135 "file": "src/containers/settings/EditServiceScreen.js",
136 "start": {
137 "line": 68,
138 "column": 15
139 },
140 "end": {
141 "line": 71,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.service.form.proxy.host",
147 "defaultMessage": "!!!Proxy Host/IP",
148 "file": "src/containers/settings/EditServiceScreen.js",
149 "start": {
150 "line": 72,
151 "column": 13
152 },
153 "end": {
154 "line": 75,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.service.form.proxy.port",
160 "defaultMessage": "!!!Port",
161 "file": "src/containers/settings/EditServiceScreen.js",
162 "start": {
163 "line": 76,
164 "column": 13
165 },
166 "end": {
167 "line": 79,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.service.form.proxy.user",
173 "defaultMessage": "!!!User",
174 "file": "src/containers/settings/EditServiceScreen.js",
175 "start": {
176 "line": 80,
177 "column": 13
178 },
179 "end": {
180 "line": 83,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.service.form.proxy.password",
186 "defaultMessage": "!!!Password",
187 "file": "src/containers/settings/EditServiceScreen.js",
188 "start": {
189 "line": 84,
190 "column": 17
191 },
192 "end": {
193 "line": 87,
194 "column": 3
195 }
196 }
197] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditSettingsScreen.json b/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
new file mode 100644
index 000000000..d3b413540
--- /dev/null
+++ b/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
@@ -0,0 +1,158 @@
1[
2 {
3 "id": "settings.app.form.autoLaunchOnStart",
4 "defaultMessage": "!!!Launch Franz on start",
5 "file": "src/containers/settings/EditSettingsScreen.js",
6 "start": {
7 "line": 22,
8 "column": 21
9 },
10 "end": {
11 "line": 25,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.app.form.autoLaunchInBackground",
17 "defaultMessage": "!!!Open in background",
18 "file": "src/containers/settings/EditSettingsScreen.js",
19 "start": {
20 "line": 26,
21 "column": 26
22 },
23 "end": {
24 "line": 29,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.app.form.runInBackground",
30 "defaultMessage": "!!!Keep Franz in background when closing the window",
31 "file": "src/containers/settings/EditSettingsScreen.js",
32 "start": {
33 "line": 30,
34 "column": 19
35 },
36 "end": {
37 "line": 33,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.app.form.enableSystemTray",
43 "defaultMessage": "!!!Show Franz in system tray",
44 "file": "src/containers/settings/EditSettingsScreen.js",
45 "start": {
46 "line": 34,
47 "column": 20
48 },
49 "end": {
50 "line": 37,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.app.form.minimizeToSystemTray",
56 "defaultMessage": "!!!Minimize Franz to system tray",
57 "file": "src/containers/settings/EditSettingsScreen.js",
58 "start": {
59 "line": 38,
60 "column": 24
61 },
62 "end": {
63 "line": 41,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.app.form.language",
69 "defaultMessage": "!!!Language",
70 "file": "src/containers/settings/EditSettingsScreen.js",
71 "start": {
72 "line": 42,
73 "column": 12
74 },
75 "end": {
76 "line": 45,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.app.form.darkMode",
82 "defaultMessage": "!!!Dark Mode",
83 "file": "src/containers/settings/EditSettingsScreen.js",
84 "start": {
85 "line": 46,
86 "column": 12
87 },
88 "end": {
89 "line": 49,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.app.form.showDisabledServices",
95 "defaultMessage": "!!!Display disabled services tabs",
96 "file": "src/containers/settings/EditSettingsScreen.js",
97 "start": {
98 "line": 50,
99 "column": 24
100 },
101 "end": {
102 "line": 53,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.app.form.showMessagesBadgesWhenMuted",
108 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
109 "file": "src/containers/settings/EditSettingsScreen.js",
110 "start": {
111 "line": 54,
112 "column": 29
113 },
114 "end": {
115 "line": 57,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.app.form.enableSpellchecking",
121 "defaultMessage": "!!!Enable spell checking",
122 "file": "src/containers/settings/EditSettingsScreen.js",
123 "start": {
124 "line": 58,
125 "column": 23
126 },
127 "end": {
128 "line": 61,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.app.form.enableGPUAcceleration",
134 "defaultMessage": "!!!Enable GPU Acceleration",
135 "file": "src/containers/settings/EditSettingsScreen.js",
136 "start": {
137 "line": 62,
138 "column": 25
139 },
140 "end": {
141 "line": 65,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.app.form.beta",
147 "defaultMessage": "!!!Include beta versions",
148 "file": "src/containers/settings/EditSettingsScreen.js",
149 "start": {
150 "line": 66,
151 "column": 8
152 },
153 "end": {
154 "line": 69,
155 "column": 3
156 }
157 }
158] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditUserScreen.json b/src/i18n/messages/src/containers/settings/EditUserScreen.json
new file mode 100644
index 000000000..70ff29945
--- /dev/null
+++ b/src/i18n/messages/src/containers/settings/EditUserScreen.json
@@ -0,0 +1,119 @@
1[
2 {
3 "id": "settings.user.form.firstname",
4 "defaultMessage": "!!!Firstname",
5 "file": "src/containers/settings/EditUserScreen.js",
6 "start": {
7 "line": 14,
8 "column": 13
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.user.form.lastname",
17 "defaultMessage": "!!!Lastname",
18 "file": "src/containers/settings/EditUserScreen.js",
19 "start": {
20 "line": 18,
21 "column": 12
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.user.form.email",
30 "defaultMessage": "!!!Email",
31 "file": "src/containers/settings/EditUserScreen.js",
32 "start": {
33 "line": 22,
34 "column": 9
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.user.form.accountType.label",
43 "defaultMessage": "!!!Account type",
44 "file": "src/containers/settings/EditUserScreen.js",
45 "start": {
46 "line": 26,
47 "column": 20
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.user.form.accountType.individual",
56 "defaultMessage": "!!!Individual",
57 "file": "src/containers/settings/EditUserScreen.js",
58 "start": {
59 "line": 30,
60 "column": 25
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.user.form.accountType.non-profit",
69 "defaultMessage": "!!!Non-Profit",
70 "file": "src/containers/settings/EditUserScreen.js",
71 "start": {
72 "line": 34,
73 "column": 24
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.user.form.accountType.company",
82 "defaultMessage": "!!!Company",
83 "file": "src/containers/settings/EditUserScreen.js",
84 "start": {
85 "line": 38,
86 "column": 22
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.user.form.currentPassword",
95 "defaultMessage": "!!!Current password",
96 "file": "src/containers/settings/EditUserScreen.js",
97 "start": {
98 "line": 42,
99 "column": 19
100 },
101 "end": {
102 "line": 45,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.user.form.newPassword",
108 "defaultMessage": "!!!New password",
109 "file": "src/containers/settings/EditUserScreen.js",
110 "start": {
111 "line": 46,
112 "column": 15
113 },
114 "end": {
115 "line": 49,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json
new file mode 100644
index 000000000..eb1b66916
--- /dev/null
+++ b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json
@@ -0,0 +1,15 @@
1[
2 {
3 "id": "feature.announcements.changelog.headline",
4 "defaultMessage": "!!!Changes in Franz {version}",
5 "file": "src/features/announcements/components/AnnouncementScreen.js",
6 "start": {
7 "line": 20,
8 "column": 12
9 },
10 "end": {
11 "line": 23,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/delayApp/Component.json b/src/i18n/messages/src/features/delayApp/Component.json
new file mode 100644
index 000000000..bacd9444a
--- /dev/null
+++ b/src/i18n/messages/src/features/delayApp/Component.json
@@ -0,0 +1,41 @@
1[
2 {
3 "id": "feature.delayApp.headline",
4 "defaultMessage": "!!!Please purchase license to skip waiting",
5 "file": "src/features/delayApp/Component.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "feature.delayApp.action",
17 "defaultMessage": "!!!Get a Franz Supporter License",
18 "file": "src/features/delayApp/Component.js",
19 "start": {
20 "line": 19,
21 "column": 10
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "feature.delayApp.text",
30 "defaultMessage": "!!!Franz will continue in {seconds} seconds.",
31 "file": "src/features/delayApp/Component.js",
32 "start": {
33 "line": 23,
34 "column": 8
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/shareFranz/Component.json b/src/i18n/messages/src/features/shareFranz/Component.json
new file mode 100644
index 000000000..34a43d5a0
--- /dev/null
+++ b/src/i18n/messages/src/features/shareFranz/Component.json
@@ -0,0 +1,93 @@
1[
2 {
3 "id": "feature.shareFranz.headline",
4 "defaultMessage": "!!!Franz is better together!",
5 "file": "src/features/shareFranz/Component.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "feature.shareFranz.text",
17 "defaultMessage": "!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.",
18 "file": "src/features/shareFranz/Component.js",
19 "start": {
20 "line": 19,
21 "column": 8
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "feature.shareFranz.action.email",
30 "defaultMessage": "!!!Share as email",
31 "file": "src/features/shareFranz/Component.js",
32 "start": {
33 "line": 23,
34 "column": 16
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "feature.shareFranz.action.facebook",
43 "defaultMessage": "!!!Share on Facebook",
44 "file": "src/features/shareFranz/Component.js",
45 "start": {
46 "line": 27,
47 "column": 19
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "feature.shareFranz.action.twitter",
56 "defaultMessage": "!!!Share on Twitter",
57 "file": "src/features/shareFranz/Component.js",
58 "start": {
59 "line": 31,
60 "column": 18
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "feature.shareFranz.shareText.email",
69 "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com",
70 "file": "src/features/shareFranz/Component.js",
71 "start": {
72 "line": 35,
73 "column": 18
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "feature.shareFranz.shareText.twitter",
82 "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger",
83 "file": "src/features/shareFranz/Component.js",
84 "start": {
85 "line": 39,
86 "column": 20
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json
new file mode 100644
index 000000000..f62bac42c
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "settings.workspace.add.form.submitButton",
4 "defaultMessage": "!!!Create workspace",
5 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
6 "start": {
7 "line": 13,
8 "column": 16
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspace.add.form.name",
17 "defaultMessage": "!!!Name",
18 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
19 "start": {
20 "line": 17,
21 "column": 8
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json
new file mode 100644
index 000000000..20ed99f8d
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json
@@ -0,0 +1,93 @@
1[
2 {
3 "id": "settings.workspace.form.buttonDelete",
4 "defaultMessage": "!!!Delete workspace",
5 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
6 "start": {
7 "line": 19,
8 "column": 16
9 },
10 "end": {
11 "line": 22,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspace.form.buttonSave",
17 "defaultMessage": "!!!Save workspace",
18 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
19 "start": {
20 "line": 23,
21 "column": 14
22 },
23 "end": {
24 "line": 26,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.workspace.form.name",
30 "defaultMessage": "!!!Name",
31 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
32 "start": {
33 "line": 27,
34 "column": 8
35 },
36 "end": {
37 "line": 30,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.workspace.form.yourWorkspaces",
43 "defaultMessage": "!!!Your workspaces",
44 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
45 "start": {
46 "line": 31,
47 "column": 18
48 },
49 "end": {
50 "line": 34,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.workspace.form.servicesInWorkspaceHeadline",
56 "defaultMessage": "!!!Services in this Workspace",
57 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
58 "start": {
59 "line": 35,
60 "column": 31
61 },
62 "end": {
63 "line": 38,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.services.noServicesAdded",
69 "defaultMessage": "!!!You haven't added any services yet.",
70 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
71 "start": {
72 "line": 39,
73 "column": 19
74 },
75 "end": {
76 "line": 42,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.services.discoverServices",
82 "defaultMessage": "!!!Discover services",
83 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
84 "start": {
85 "line": 43,
86 "column": 20
87 },
88 "end": {
89 "line": 46,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json
new file mode 100644
index 000000000..9f0935620
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json
@@ -0,0 +1,106 @@
1[
2 {
3 "id": "workspaceDrawer.headline",
4 "defaultMessage": "!!!Workspaces",
5 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
6 "start": {
7 "line": 16,
8 "column": 12
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "workspaceDrawer.allServices",
17 "defaultMessage": "!!!All services",
18 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
19 "start": {
20 "line": 20,
21 "column": 15
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "workspaceDrawer.workspacesSettingsTooltip",
30 "defaultMessage": "!!!Workspaces settings",
31 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
32 "start": {
33 "line": 24,
34 "column": 29
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "workspaceDrawer.workspaceFeatureInfo",
43 "defaultMessage": "!!!Info about workspace feature",
44 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
45 "start": {
46 "line": 28,
47 "column": 24
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "workspaceDrawer.premiumCtaButtonLabel",
56 "defaultMessage": "!!!Create your first workspace",
57 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
58 "start": {
59 "line": 32,
60 "column": 25
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "workspaceDrawer.reactivatePremiumAccountLabel",
69 "defaultMessage": "!!!Reactivate premium account",
70 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
71 "start": {
72 "line": 36,
73 "column": 28
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "workspaceDrawer.addNewWorkspaceLabel",
82 "defaultMessage": "!!!add new workspace",
83 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
84 "start": {
85 "line": 40,
86 "column": 24
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 },
93 {
94 "id": "workspaceDrawer.proFeatureBadge",
95 "defaultMessage": "!!!Premium feature",
96 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
97 "start": {
98 "line": 44,
99 "column": 23
100 },
101 "end": {
102 "line": 47,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json
new file mode 100644
index 000000000..4ff190606
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json
@@ -0,0 +1,28 @@
1[
2 {
3 "id": "workspaceDrawer.item.noServicesAddedYet",
4 "defaultMessage": "!!!No services added yet",
5 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
6 "start": {
7 "line": 12,
8 "column": 22
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 },
15 {
16 "id": "workspaceDrawer.item.contextMenuEdit",
17 "defaultMessage": "!!!edit",
18 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
19 "start": {
20 "line": 16,
21 "column": 19
22 },
23 "end": {
24 "line": 19,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json
new file mode 100644
index 000000000..4f3e6d55c
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json
@@ -0,0 +1,15 @@
1[
2 {
3 "id": "workspaces.switchingIndicator.switchingTo",
4 "defaultMessage": "!!!Switching to",
5 "file": "src/features/workspaces/components/WorkspaceSwitchingIndicator.js",
6 "start": {
7 "line": 12,
8 "column": 15
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json
new file mode 100644
index 000000000..ef8f1bebc
--- /dev/null
+++ b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json
@@ -0,0 +1,106 @@
1[
2 {
3 "id": "settings.workspaces.headline",
4 "defaultMessage": "!!!Your workspaces",
5 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
6 "start": {
7 "line": 17,
8 "column": 12
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspaces.noWorkspacesAdded",
17 "defaultMessage": "!!!You haven't added any workspaces yet.",
18 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
19 "start": {
20 "line": 21,
21 "column": 19
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.workspaces.workspacesRequestFailed",
30 "defaultMessage": "!!!Could not load your workspaces",
31 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
32 "start": {
33 "line": 25,
34 "column": 27
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.workspaces.tryReloadWorkspaces",
43 "defaultMessage": "!!!Try again",
44 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
45 "start": {
46 "line": 29,
47 "column": 23
48 },
49 "end": {
50 "line": 32,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.workspaces.updatedInfo",
56 "defaultMessage": "!!!Your changes have been saved",
57 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
58 "start": {
59 "line": 33,
60 "column": 15
61 },
62 "end": {
63 "line": 36,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.workspaces.deletedInfo",
69 "defaultMessage": "!!!Workspace has been deleted",
70 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
71 "start": {
72 "line": 37,
73 "column": 15
74 },
75 "end": {
76 "line": 40,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.workspaces.workspaceFeatureInfo",
82 "defaultMessage": "!!!Info about workspace feature",
83 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
84 "start": {
85 "line": 41,
86 "column": 24
87 },
88 "end": {
89 "line": 44,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.workspaces.workspaceFeatureHeadline",
95 "defaultMessage": "!!!Less is More: Introducing Franz Workspaces",
96 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
97 "start": {
98 "line": 45,
99 "column": 28
100 },
101 "end": {
102 "line": 48,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/helpers/validation-helpers.json b/src/i18n/messages/src/helpers/validation-helpers.json
new file mode 100644
index 000000000..86bfe1500
--- /dev/null
+++ b/src/i18n/messages/src/helpers/validation-helpers.json
@@ -0,0 +1,67 @@
1[
2 {
3 "id": "validation.required",
4 "defaultMessage": "!!!Field is required",
5 "file": "src/helpers/validation-helpers.js",
6 "start": {
7 "line": 4,
8 "column": 12
9 },
10 "end": {
11 "line": 7,
12 "column": 3
13 }
14 },
15 {
16 "id": "validation.email",
17 "defaultMessage": "!!!Email not valid",
18 "file": "src/helpers/validation-helpers.js",
19 "start": {
20 "line": 8,
21 "column": 9
22 },
23 "end": {
24 "line": 11,
25 "column": 3
26 }
27 },
28 {
29 "id": "validation.url",
30 "defaultMessage": "!!!Not a valid URL",
31 "file": "src/helpers/validation-helpers.js",
32 "start": {
33 "line": 12,
34 "column": 7
35 },
36 "end": {
37 "line": 15,
38 "column": 3
39 }
40 },
41 {
42 "id": "validation.minLength",
43 "defaultMessage": "!!!Too few characters",
44 "file": "src/helpers/validation-helpers.js",
45 "start": {
46 "line": 16,
47 "column": 13
48 },
49 "end": {
50 "line": 19,
51 "column": 3
52 }
53 },
54 {
55 "id": "validation.oneRequired",
56 "defaultMessage": "!!!At least one is required",
57 "file": "src/helpers/validation-helpers.js",
58 "start": {
59 "line": 20,
60 "column": 15
61 },
62 "end": {
63 "line": 23,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/i18n/globalMessages.json b/src/i18n/messages/src/i18n/globalMessages.json
new file mode 100644
index 000000000..28001614f
--- /dev/null
+++ b/src/i18n/messages/src/i18n/globalMessages.json
@@ -0,0 +1,80 @@
1[
2 {
3 "id": "global.api.unhealthy",
4 "defaultMessage": "!!!Can't connect to Franz Online Services",
5 "file": "src/i18n/globalMessages.js",
6 "start": {
7 "line": 4,
8 "column": 16
9 },
10 "end": {
11 "line": 7,
12 "column": 3
13 }
14 },
15 {
16 "id": "global.notConnectedToTheInternet",
17 "defaultMessage": "!!!You are not connected to the internet.",
18 "file": "src/i18n/globalMessages.js",
19 "start": {
20 "line": 8,
21 "column": 29
22 },
23 "end": {
24 "line": 11,
25 "column": 3
26 }
27 },
28 {
29 "id": "global.spellchecking.language",
30 "defaultMessage": "!!!Spell checking language",
31 "file": "src/i18n/globalMessages.js",
32 "start": {
33 "line": 12,
34 "column": 24
35 },
36 "end": {
37 "line": 15,
38 "column": 3
39 }
40 },
41 {
42 "id": "global.spellchecker.useDefault",
43 "defaultMessage": "!!!Use System Default ({default})",
44 "file": "src/i18n/globalMessages.js",
45 "start": {
46 "line": 16,
47 "column": 29
48 },
49 "end": {
50 "line": 19,
51 "column": 3
52 }
53 },
54 {
55 "id": "global.spellchecking.autodetect",
56 "defaultMessage": "!!!Detect language automatically",
57 "file": "src/i18n/globalMessages.js",
58 "start": {
59 "line": 20,
60 "column": 34
61 },
62 "end": {
63 "line": 23,
64 "column": 3
65 }
66 },
67 {
68 "id": "global.spellchecking.autodetect.short",
69 "defaultMessage": "!!!Automatic",
70 "file": "src/i18n/globalMessages.js",
71 "start": {
72 "line": 24,
73 "column": 39
74 },
75 "end": {
76 "line": 27,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json
new file mode 100644
index 000000000..2adf5b787
--- /dev/null
+++ b/src/i18n/messages/src/lib/Menu.json
@@ -0,0 +1,691 @@
1[
2 {
3 "id": "menu.edit",
4 "defaultMessage": "!!!Edit",
5 "file": "src/lib/Menu.js",
6 "start": {
7 "line": 15,
8 "column": 8
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "menu.edit.undo",
17 "defaultMessage": "!!!Undo",
18 "file": "src/lib/Menu.js",
19 "start": {
20 "line": 19,
21 "column": 8
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "menu.edit.redo",
30 "defaultMessage": "!!!Redo",
31 "file": "src/lib/Menu.js",
32 "start": {
33 "line": 23,
34 "column": 8
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "menu.edit.cut",
43 "defaultMessage": "!!!Cut",
44 "file": "src/lib/Menu.js",
45 "start": {
46 "line": 27,
47 "column": 7
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "menu.edit.copy",
56 "defaultMessage": "!!!Copy",
57 "file": "src/lib/Menu.js",
58 "start": {
59 "line": 31,
60 "column": 8
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "menu.edit.paste",
69 "defaultMessage": "!!!Paste",
70 "file": "src/lib/Menu.js",
71 "start": {
72 "line": 35,
73 "column": 9
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "menu.edit.pasteAndMatchStyle",
82 "defaultMessage": "!!!Paste And Match Style",
83 "file": "src/lib/Menu.js",
84 "start": {
85 "line": 39,
86 "column": 22
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 },
93 {
94 "id": "menu.edit.delete",
95 "defaultMessage": "!!!Delete",
96 "file": "src/lib/Menu.js",
97 "start": {
98 "line": 43,
99 "column": 10
100 },
101 "end": {
102 "line": 46,
103 "column": 3
104 }
105 },
106 {
107 "id": "menu.edit.selectAll",
108 "defaultMessage": "!!!Select All",
109 "file": "src/lib/Menu.js",
110 "start": {
111 "line": 47,
112 "column": 13
113 },
114 "end": {
115 "line": 50,
116 "column": 3
117 }
118 },
119 {
120 "id": "menu.edit.speech",
121 "defaultMessage": "!!!Speech",
122 "file": "src/lib/Menu.js",
123 "start": {
124 "line": 51,
125 "column": 10
126 },
127 "end": {
128 "line": 54,
129 "column": 3
130 }
131 },
132 {
133 "id": "menu.edit.startSpeaking",
134 "defaultMessage": "!!!Start Speaking",
135 "file": "src/lib/Menu.js",
136 "start": {
137 "line": 55,
138 "column": 17
139 },
140 "end": {
141 "line": 58,
142 "column": 3
143 }
144 },
145 {
146 "id": "menu.edit.stopSpeaking",
147 "defaultMessage": "!!!Stop Speaking",
148 "file": "src/lib/Menu.js",
149 "start": {
150 "line": 59,
151 "column": 16
152 },
153 "end": {
154 "line": 62,
155 "column": 3
156 }
157 },
158 {
159 "id": "menu.edit.startDictation",
160 "defaultMessage": "!!!Start Dictation",
161 "file": "src/lib/Menu.js",
162 "start": {
163 "line": 63,
164 "column": 18
165 },
166 "end": {
167 "line": 66,
168 "column": 3
169 }
170 },
171 {
172 "id": "menu.edit.emojiSymbols",
173 "defaultMessage": "!!!Emoji & Symbols",
174 "file": "src/lib/Menu.js",
175 "start": {
176 "line": 67,
177 "column": 16
178 },
179 "end": {
180 "line": 70,
181 "column": 3
182 }
183 },
184 {
185 "id": "menu.view.resetZoom",
186 "defaultMessage": "!!!Actual Size",
187 "file": "src/lib/Menu.js",
188 "start": {
189 "line": 71,
190 "column": 13
191 },
192 "end": {
193 "line": 74,
194 "column": 3
195 }
196 },
197 {
198 "id": "menu.view.zoomIn",
199 "defaultMessage": "!!!Zoom In",
200 "file": "src/lib/Menu.js",
201 "start": {
202 "line": 75,
203 "column": 10
204 },
205 "end": {
206 "line": 78,
207 "column": 3
208 }
209 },
210 {
211 "id": "menu.view.zoomOut",
212 "defaultMessage": "!!!Zoom Out",
213 "file": "src/lib/Menu.js",
214 "start": {
215 "line": 79,
216 "column": 11
217 },
218 "end": {
219 "line": 82,
220 "column": 3
221 }
222 },
223 {
224 "id": "menu.view.enterFullScreen",
225 "defaultMessage": "!!!Enter Full Screen",
226 "file": "src/lib/Menu.js",
227 "start": {
228 "line": 83,
229 "column": 19
230 },
231 "end": {
232 "line": 86,
233 "column": 3
234 }
235 },
236 {
237 "id": "menu.view.exitFullScreen",
238 "defaultMessage": "!!!Exit Full Screen",
239 "file": "src/lib/Menu.js",
240 "start": {
241 "line": 87,
242 "column": 18
243 },
244 "end": {
245 "line": 90,
246 "column": 3
247 }
248 },
249 {
250 "id": "menu.view.toggleFullScreen",
251 "defaultMessage": "!!!Toggle Full Screen",
252 "file": "src/lib/Menu.js",
253 "start": {
254 "line": 91,
255 "column": 20
256 },
257 "end": {
258 "line": 94,
259 "column": 3
260 }
261 },
262 {
263 "id": "menu.view.toggleDevTools",
264 "defaultMessage": "!!!Toggle Developer Tools",
265 "file": "src/lib/Menu.js",
266 "start": {
267 "line": 95,
268 "column": 18
269 },
270 "end": {
271 "line": 98,
272 "column": 3
273 }
274 },
275 {
276 "id": "menu.view.toggleServiceDevTools",
277 "defaultMessage": "!!!Toggle Service Developer Tools",
278 "file": "src/lib/Menu.js",
279 "start": {
280 "line": 99,
281 "column": 25
282 },
283 "end": {
284 "line": 102,
285 "column": 3
286 }
287 },
288 {
289 "id": "menu.view.reloadService",
290 "defaultMessage": "!!!Reload Service",
291 "file": "src/lib/Menu.js",
292 "start": {
293 "line": 103,
294 "column": 17
295 },
296 "end": {
297 "line": 106,
298 "column": 3
299 }
300 },
301 {
302 "id": "menu.view.reloadFranz",
303 "defaultMessage": "!!!Reload Franz",
304 "file": "src/lib/Menu.js",
305 "start": {
306 "line": 107,
307 "column": 15
308 },
309 "end": {
310 "line": 110,
311 "column": 3
312 }
313 },
314 {
315 "id": "menu.window.minimize",
316 "defaultMessage": "!!!Minimize",
317 "file": "src/lib/Menu.js",
318 "start": {
319 "line": 111,
320 "column": 12
321 },
322 "end": {
323 "line": 114,
324 "column": 3
325 }
326 },
327 {
328 "id": "menu.window.close",
329 "defaultMessage": "!!!Close",
330 "file": "src/lib/Menu.js",
331 "start": {
332 "line": 115,
333 "column": 9
334 },
335 "end": {
336 "line": 118,
337 "column": 3
338 }
339 },
340 {
341 "id": "menu.help.learnMore",
342 "defaultMessage": "!!!Learn More",
343 "file": "src/lib/Menu.js",
344 "start": {
345 "line": 119,
346 "column": 13
347 },
348 "end": {
349 "line": 122,
350 "column": 3
351 }
352 },
353 {
354 "id": "menu.help.changelog",
355 "defaultMessage": "!!!Changelog",
356 "file": "src/lib/Menu.js",
357 "start": {
358 "line": 123,
359 "column": 13
360 },
361 "end": {
362 "line": 126,
363 "column": 3
364 }
365 },
366 {
367 "id": "menu.help.support",
368 "defaultMessage": "!!!Support",
369 "file": "src/lib/Menu.js",
370 "start": {
371 "line": 127,
372 "column": 11
373 },
374 "end": {
375 "line": 130,
376 "column": 3
377 }
378 },
379 {
380 "id": "menu.help.tos",
381 "defaultMessage": "!!!Terms of Service",
382 "file": "src/lib/Menu.js",
383 "start": {
384 "line": 131,
385 "column": 7
386 },
387 "end": {
388 "line": 134,
389 "column": 3
390 }
391 },
392 {
393 "id": "menu.help.privacy",
394 "defaultMessage": "!!!Privacy Statement",
395 "file": "src/lib/Menu.js",
396 "start": {
397 "line": 135,
398 "column": 11
399 },
400 "end": {
401 "line": 138,
402 "column": 3
403 }
404 },
405 {
406 "id": "menu.file",
407 "defaultMessage": "!!!File",
408 "file": "src/lib/Menu.js",
409 "start": {
410 "line": 139,
411 "column": 8
412 },
413 "end": {
414 "line": 142,
415 "column": 3
416 }
417 },
418 {
419 "id": "menu.view",
420 "defaultMessage": "!!!View",
421 "file": "src/lib/Menu.js",
422 "start": {
423 "line": 143,
424 "column": 8
425 },
426 "end": {
427 "line": 146,
428 "column": 3
429 }
430 },
431 {
432 "id": "menu.services",
433 "defaultMessage": "!!!Services",
434 "file": "src/lib/Menu.js",
435 "start": {
436 "line": 147,
437 "column": 12
438 },
439 "end": {
440 "line": 150,
441 "column": 3
442 }
443 },
444 {
445 "id": "menu.window",
446 "defaultMessage": "!!!Window",
447 "file": "src/lib/Menu.js",
448 "start": {
449 "line": 151,
450 "column": 10
451 },
452 "end": {
453 "line": 154,
454 "column": 3
455 }
456 },
457 {
458 "id": "menu.help",
459 "defaultMessage": "!!!Help",
460 "file": "src/lib/Menu.js",
461 "start": {
462 "line": 155,
463 "column": 8
464 },
465 "end": {
466 "line": 158,
467 "column": 3
468 }
469 },
470 {
471 "id": "menu.app.about",
472 "defaultMessage": "!!!About Franz",
473 "file": "src/lib/Menu.js",
474 "start": {
475 "line": 159,
476 "column": 9
477 },
478 "end": {
479 "line": 162,
480 "column": 3
481 }
482 },
483 {
484 "id": "menu.app.announcement",
485 "defaultMessage": "!!!What's new?",
486 "file": "src/lib/Menu.js",
487 "start": {
488 "line": 163,
489 "column": 16
490 },
491 "end": {
492 "line": 166,
493 "column": 3
494 }
495 },
496 {
497 "id": "menu.app.settings",
498 "defaultMessage": "!!!Settings",
499 "file": "src/lib/Menu.js",
500 "start": {
501 "line": 167,
502 "column": 12
503 },
504 "end": {
505 "line": 170,
506 "column": 3
507 }
508 },
509 {
510 "id": "menu.app.hide",
511 "defaultMessage": "!!!Hide",
512 "file": "src/lib/Menu.js",
513 "start": {
514 "line": 171,
515 "column": 8
516 },
517 "end": {
518 "line": 174,
519 "column": 3
520 }
521 },
522 {
523 "id": "menu.app.hideOthers",
524 "defaultMessage": "!!!Hide Others",
525 "file": "src/lib/Menu.js",
526 "start": {
527 "line": 175,
528 "column": 14
529 },
530 "end": {
531 "line": 178,
532 "column": 3
533 }
534 },
535 {
536 "id": "menu.app.unhide",
537 "defaultMessage": "!!!Unhide",
538 "file": "src/lib/Menu.js",
539 "start": {
540 "line": 179,
541 "column": 10
542 },
543 "end": {
544 "line": 182,
545 "column": 3
546 }
547 },
548 {
549 "id": "menu.app.quit",
550 "defaultMessage": "!!!Quit",
551 "file": "src/lib/Menu.js",
552 "start": {
553 "line": 183,
554 "column": 8
555 },
556 "end": {
557 "line": 186,
558 "column": 3
559 }
560 },
561 {
562 "id": "menu.services.addNewService",
563 "defaultMessage": "!!!Add New Service...",
564 "file": "src/lib/Menu.js",
565 "start": {
566 "line": 187,
567 "column": 17
568 },
569 "end": {
570 "line": 190,
571 "column": 3
572 }
573 },
574 {
575 "id": "menu.workspaces.addNewWorkspace",
576 "defaultMessage": "!!!Add New Workspace...",
577 "file": "src/lib/Menu.js",
578 "start": {
579 "line": 191,
580 "column": 19
581 },
582 "end": {
583 "line": 194,
584 "column": 3
585 }
586 },
587 {
588 "id": "menu.workspaces.openWorkspaceDrawer",
589 "defaultMessage": "!!!Open workspace drawer",
590 "file": "src/lib/Menu.js",
591 "start": {
592 "line": 195,
593 "column": 23
594 },
595 "end": {
596 "line": 198,
597 "column": 3
598 }
599 },
600 {
601 "id": "menu.workspaces.closeWorkspaceDrawer",
602 "defaultMessage": "!!!Close workspace drawer",
603 "file": "src/lib/Menu.js",
604 "start": {
605 "line": 199,
606 "column": 24
607 },
608 "end": {
609 "line": 202,
610 "column": 3
611 }
612 },
613 {
614 "id": "menu.services.setNextServiceActive",
615 "defaultMessage": "!!!Activate next service...",
616 "file": "src/lib/Menu.js",
617 "start": {
618 "line": 203,
619 "column": 23
620 },
621 "end": {
622 "line": 206,
623 "column": 3
624 }
625 },
626 {
627 "id": "menu.services.activatePreviousService",
628 "defaultMessage": "!!!Activate previous service...",
629 "file": "src/lib/Menu.js",
630 "start": {
631 "line": 207,
632 "column": 27
633 },
634 "end": {
635 "line": 210,
636 "column": 3
637 }
638 },
639 {
640 "id": "sidebar.muteApp",
641 "defaultMessage": "!!!Disable notifications & audio",
642 "file": "src/lib/Menu.js",
643 "start": {
644 "line": 211,
645 "column": 11
646 },
647 "end": {
648 "line": 214,
649 "column": 3
650 }
651 },
652 {
653 "id": "sidebar.unmuteApp",
654 "defaultMessage": "!!!Enable notifications & audio",
655 "file": "src/lib/Menu.js",
656 "start": {
657 "line": 215,
658 "column": 13
659 },
660 "end": {
661 "line": 218,
662 "column": 3
663 }
664 },
665 {
666 "id": "menu.workspaces",
667 "defaultMessage": "!!!Workspaces",
668 "file": "src/lib/Menu.js",
669 "start": {
670 "line": 219,
671 "column": 14
672 },
673 "end": {
674 "line": 222,
675 "column": 3
676 }
677 },
678 {
679 "id": "menu.workspaces.defaultWorkspace",
680 "defaultMessage": "!!!Default",
681 "file": "src/lib/Menu.js",
682 "start": {
683 "line": 223,
684 "column": 20
685 },
686 "end": {
687 "line": 226,
688 "column": 3
689 }
690 }
691] \ No newline at end of file
diff --git a/src/index.js b/src/index.js
index f34df8c17..3fe996aa7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -4,25 +4,23 @@ import {
4 shell, 4 shell,
5 ipcMain, 5 ipcMain,
6} from 'electron'; 6} from 'electron';
7 7import isDevMode from 'electron-is-dev';
8import fs from 'fs-extra'; 8import fs from 'fs-extra';
9import path from 'path'; 9import path from 'path';
10import windowStateKeeper from 'electron-window-state'; 10import windowStateKeeper from 'electron-window-state';
11 11
12// Set app directory before loading user modules
13if (isDevMode) {
14 app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev'));
15}
16
17/* eslint-disable import/first */
12import { 18import {
13 isDevMode,
14 isMac, 19 isMac,
15 isWindows, 20 isWindows,
16 isLinux, 21 isLinux,
17} from './environment'; 22} from './environment';
18
19import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; 23import { mainIpcHandler as basicAuthHandler } from './features/basicAuth';
20
21// DEV MODE: Save user data into FranzDev
22if (isDevMode) {
23 app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev'));
24}
25/* eslint-disable import/first */
26import ipcApi from './electron/ipc-api'; 24import ipcApi from './electron/ipc-api';
27import Tray from './lib/Tray'; 25import Tray from './lib/Tray';
28import Settings from './electron/Settings'; 26import Settings from './electron/Settings';
@@ -35,6 +33,8 @@ import {
35 DEFAULT_APP_SETTINGS, 33 DEFAULT_APP_SETTINGS,
36 DEFAULT_WINDOW_OPTIONS, 34 DEFAULT_WINDOW_OPTIONS,
37} from './config'; 35} from './config';
36import { asarPath } from './helpers/asar-helpers';
37import { isValidExternalURL } from './helpers/url-helpers';
38/* eslint-enable import/first */ 38/* eslint-enable import/first */
39 39
40const debug = require('debug')('Franz:App'); 40const debug = require('debug')('Franz:App');
@@ -44,6 +44,17 @@ const debug = require('debug')('Franz:App');
44let mainWindow; 44let mainWindow;
45let willQuitApp = false; 45let willQuitApp = false;
46 46
47// Register methods to be called once the window has been loaded.
48let onDidLoadFns = [];
49
50function onDidLoad(fn) {
51 if (onDidLoadFns) {
52 onDidLoadFns.push(fn);
53 } else if (mainWindow) {
54 fn(mainWindow);
55 }
56}
57
47// Ensure that the recipe directory exists 58// Ensure that the recipe directory exists
48fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); 59fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp'));
49fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json')); 60fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json'));
@@ -61,32 +72,38 @@ if (!gotTheLock) {
61 app.on('second-instance', (event, argv) => { 72 app.on('second-instance', (event, argv) => {
62 // Someone tried to run a second instance, we should focus our window. 73 // Someone tried to run a second instance, we should focus our window.
63 if (mainWindow) { 74 if (mainWindow) {
64 if (mainWindow.isMinimized()) mainWindow.restore(); 75 mainWindow.show();
76 if (mainWindow.isMinimized()) {
77 mainWindow.restore();
78 }
65 mainWindow.focus(); 79 mainWindow.focus();
66 80
67 if (isWindows) { 81 if (isWindows) {
68 // Keep only command line / deep linked arguments 82 onDidLoad((window) => {
69 const url = argv.slice(1); 83 // Keep only command line / deep linked arguments
70 84 const url = argv.slice(1);
71 if (url) { 85 if (url) {
72 handleDeepLink(mainWindow, url.toString()); 86 handleDeepLink(window, url.toString());
73 } 87 }
74 } 88
75 89 if (argv.includes('--reset-window')) {
76 if (argv.includes('--reset-window')) { 90 // Needs to be delayed to not interfere with mainWindow.restore();
77 // Needs to be delayed to not interfere with mainWindow.restore(); 91 setTimeout(() => {
78 setTimeout(() => { 92 debug('Resetting windows via Task');
79 debug('Resetting windows via Task'); 93 window.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100);
80 mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100); 94 window.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height);
81 mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height); 95 }, 1);
82 }, 1); 96 } else if (argv.includes('--quit')) {
97 // Needs to be delayed to not interfere with mainWindow.restore();
98 setTimeout(() => {
99 debug('Quitting Franz via Task');
100 app.quit();
101 }, 1);
102 }
103 });
83 } 104 }
84 } 105 }
85 }); 106 });
86
87 // Create myWindow, load the rest of the app, etc...
88 app.on('ready', () => {
89 });
90} 107}
91// const isSecondInstance = app.makeSingleInstance((argv) => { 108// const isSecondInstance = app.makeSingleInstance((argv) => {
92// if (mainWindow) { 109// if (mainWindow) {
@@ -166,6 +183,14 @@ const createWindow = () => {
166 }, 183 },
167 }); 184 });
168 185
186 mainWindow.webContents.on('did-finish-load', () => {
187 const fns = onDidLoadFns;
188 onDidLoadFns = null;
189 for (const fn of fns) {
190 fn(mainWindow);
191 }
192 });
193
169 // Initialize System Tray 194 // Initialize System Tray
170 const trayIcon = new Tray(); 195 const trayIcon = new Tray();
171 196
@@ -190,22 +215,36 @@ const createWindow = () => {
190 mainWindow.webContents.openDevTools(); 215 mainWindow.webContents.openDevTools();
191 } 216 }
192 217
218 // Windows deep linking handling on app launch
219 if (isWindows) {
220 onDidLoad((window) => {
221 const url = process.argv.slice(1);
222 if (url) {
223 handleDeepLink(window, url.toString());
224 }
225 });
226 }
227
193 // Emitted when the window is closed. 228 // Emitted when the window is closed.
194 mainWindow.on('close', (e) => { 229 mainWindow.on('close', (e) => {
230 debug('Window: close window');
195 // Dereference the window object, usually you would store windows 231 // Dereference the window object, usually you would store windows
196 // in an array if your app supports multi windows, this is the time 232 // in an array if your app supports multi windows, this is the time
197 // when you should delete the corresponding element. 233 // when you should delete the corresponding element.
198 if (!willQuitApp && (settings.get('runInBackground') === undefined || settings.get('runInBackground'))) { 234 if (!willQuitApp && (settings.get('runInBackground') === undefined || settings.get('runInBackground'))) {
199 e.preventDefault(); 235 e.preventDefault();
200 if (isWindows) { 236 if (isWindows) {
237 debug('Window: minimize');
201 mainWindow.minimize(); 238 mainWindow.minimize();
239
240 if (settings.get('minimizeToSystemTray')) {
241 debug('Skip taskbar: true');
242 mainWindow.setSkipTaskbar(true);
243 }
202 } else { 244 } else {
245 debug('Window: hide');
203 mainWindow.hide(); 246 mainWindow.hide();
204 } 247 }
205
206 if (isWindows) {
207 mainWindow.setSkipTaskbar(true);
208 }
209 } else { 248 } else {
210 app.quit(); 249 app.quit();
211 } 250 }
@@ -217,32 +256,39 @@ const createWindow = () => {
217 app.wasMaximized = app.isMaximized; 256 app.wasMaximized = app.isMaximized;
218 257
219 if (settings.get('minimizeToSystemTray')) { 258 if (settings.get('minimizeToSystemTray')) {
259 debug('Skip taskbar: true');
220 mainWindow.setSkipTaskbar(true); 260 mainWindow.setSkipTaskbar(true);
221 trayIcon.show(); 261 trayIcon.show();
222 } 262 }
223 }); 263 });
224 264
225 mainWindow.on('maximize', () => { 265 mainWindow.on('maximize', () => {
266 debug('Window: maximize');
226 app.isMaximized = true; 267 app.isMaximized = true;
227 }); 268 });
228 269
229 mainWindow.on('unmaximize', () => { 270 mainWindow.on('unmaximize', () => {
271 debug('Window: unmaximize');
230 app.isMaximized = false; 272 app.isMaximized = false;
231 }); 273 });
232 274
233 mainWindow.on('restore', () => { 275 mainWindow.on('restore', () => {
276 debug('Window: restore');
234 mainWindow.setSkipTaskbar(false); 277 mainWindow.setSkipTaskbar(false);
235 278
236 if (app.wasMaximized) { 279 if (app.wasMaximized) {
280 debug('Window: was maximized before, maximize window');
237 mainWindow.maximize(); 281 mainWindow.maximize();
238 } 282 }
239 283
240 if (!settings.get('enableSystemTray')) { 284 if (!settings.get('enableSystemTray')) {
285 debug('Tray: hiding tray icon');
241 trayIcon.hide(); 286 trayIcon.hide();
242 } 287 }
243 }); 288 });
244 289
245 mainWindow.on('show', () => { 290 mainWindow.on('show', () => {
291 debug('Skip taskbar: false');
246 mainWindow.setSkipTaskbar(false); 292 mainWindow.setSkipTaskbar(false);
247 }); 293 });
248 294
@@ -250,23 +296,53 @@ const createWindow = () => {
250 app.isMaximized = mainWindow.isMaximized(); 296 app.isMaximized = mainWindow.isMaximized();
251 297
252 mainWindow.webContents.on('new-window', (e, url) => { 298 mainWindow.webContents.on('new-window', (e, url) => {
299 debug('Open url', url);
253 e.preventDefault(); 300 e.preventDefault();
254 shell.openExternal(url); 301
302 if (isValidExternalURL(url)) {
303 shell.openExternal(url);
304 }
255 }); 305 });
256}; 306};
257 307
308// Allow passing command line parameters/switches to electron
309// https://electronjs.org/docs/api/chrome-command-line-switches
310// used for Kerberos support
311// Usage e.g. MACOS
312// $ Franz.app/Contents/MacOS/Franz --auth-server-whitelist *.mydomain.com --auth-negotiate-delegate-whitelist *.mydomain.com
313const argv = require('minimist')(process.argv.slice(1));
314
315if (argv['auth-server-whitelist']) {
316 app.commandLine.appendSwitch('auth-server-whitelist', argv['auth-server-whitelist']);
317}
318if (argv['auth-negotiate-delegate-whitelist']) {
319 app.commandLine.appendSwitch('auth-negotiate-delegate-whitelist', argv['auth-negotiate-delegate-whitelist']);
320}
321
258// This method will be called when Electron has finished 322// This method will be called when Electron has finished
259// initialization and is ready to create browser windows. 323// initialization and is ready to create browser windows.
260// Some APIs can only be used after this event occurs. 324// Some APIs can only be used after this event occurs.
261app.on('ready', () => { 325app.on('ready', () => {
326 // Register App URL
327 app.setAsDefaultProtocolClient('franz');
328
329 if (isDevMode) {
330 app.setAsDefaultProtocolClient('franz-dev');
331 }
332
262 if (process.platform === 'win32') { 333 if (process.platform === 'win32') {
263 app.setUserTasks([{ 334 app.setUserTasks([{
264 program: process.execPath, 335 program: process.execPath,
265 arguments: `${isDevMode ? `${__dirname} ` : ''}--reset-window`, 336 arguments: `${isDevMode ? `${__dirname} ` : ''}--reset-window`,
266 iconPath: path.join(`${__dirname}`, '../src/assets/images/taskbar/win32/display.ico'), 337 iconPath: asarPath(path.join(isDevMode ? `${__dirname}../src/` : __dirname, 'assets/images/taskbar/win32/display.ico')),
267 iconIndex: 0, 338 iconIndex: 0,
268 title: 'Move Franz to Current Display', 339 title: 'Move Franz to Current Display',
269 description: 'Restore the position and size of Franz', 340 description: 'Restore the position and size of Franz',
341 }, {
342 program: process.execPath,
343 arguments: `${isDevMode ? `${__dirname} ` : ''}--quit`,
344 iconIndex: 0,
345 title: 'Quit Franz',
270 }]); 346 }]);
271 } 347 }
272 348
@@ -317,7 +393,10 @@ app.on('window-all-closed', () => {
317 // to stay active until the user quits explicitly with Cmd + Q 393 // to stay active until the user quits explicitly with Cmd + Q
318 if (settings.get('runInBackground') === undefined 394 if (settings.get('runInBackground') === undefined
319 || settings.get('runInBackground')) { 395 || settings.get('runInBackground')) {
396 debug('Window: all windows closed, quit app');
320 app.quit(); 397 app.quit();
398 } else {
399 debug('Window: don\'t quit app');
321 } 400 }
322}); 401});
323 402
@@ -336,13 +415,13 @@ app.on('activate', () => {
336}); 415});
337 416
338app.on('will-finish-launching', () => { 417app.on('will-finish-launching', () => {
339 // Protocol handler for osx 418 // Protocol handler for macOS
340 app.on('open-url', (event, url) => { 419 app.on('open-url', (event, url) => {
341 event.preventDefault(); 420 event.preventDefault();
342 console.log(`open-url event: ${url}`); 421
343 handleDeepLink(mainWindow, url); 422 onDidLoad((window) => {
423 debug('open-url event', url);
424 handleDeepLink(window, url);
425 });
344 }); 426 });
345}); 427});
346
347// Register App URL
348app.setAsDefaultProtocolClient('franz');
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index c378619ad..da2540274 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -1,8 +1,13 @@
1import { remote, shell } from 'electron'; 1import { remote, shell } from 'electron';
2import { observable, autorun, computed } from 'mobx'; 2import { observable, autorun } from 'mobx';
3import { defineMessages } from 'react-intl'; 3import { defineMessages } from 'react-intl';
4 4
5import { isMac, ctrlKey, cmdKey } from '../environment'; 5import { isMac, ctrlKey, cmdKey } from '../environment';
6import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../features/workspaces/index';
7import { workspaceActions } from '../features/workspaces/actions';
8import { gaEvent } from './analytics';
9import { announcementActions } from '../features/announcements/actions';
10import { announcementsStore } from '../features/announcements';
6 11
7const { app, Menu, dialog } = remote; 12const { app, Menu, dialog } = remote;
8 13
@@ -155,6 +160,10 @@ const menuItems = defineMessages({
155 id: 'menu.app.about', 160 id: 'menu.app.about',
156 defaultMessage: '!!!About Franz', 161 defaultMessage: '!!!About Franz',
157 }, 162 },
163 announcement: {
164 id: 'menu.app.announcement',
165 defaultMessage: '!!!What\'s new?',
166 },
158 settings: { 167 settings: {
159 id: 'menu.app.settings', 168 id: 'menu.app.settings',
160 defaultMessage: '!!!Settings', 169 defaultMessage: '!!!Settings',
@@ -179,6 +188,42 @@ const menuItems = defineMessages({
179 id: 'menu.services.addNewService', 188 id: 'menu.services.addNewService',
180 defaultMessage: '!!!Add New Service...', 189 defaultMessage: '!!!Add New Service...',
181 }, 190 },
191 addNewWorkspace: {
192 id: 'menu.workspaces.addNewWorkspace',
193 defaultMessage: '!!!Add New Workspace...',
194 },
195 openWorkspaceDrawer: {
196 id: 'menu.workspaces.openWorkspaceDrawer',
197 defaultMessage: '!!!Open workspace drawer',
198 },
199 closeWorkspaceDrawer: {
200 id: 'menu.workspaces.closeWorkspaceDrawer',
201 defaultMessage: '!!!Close workspace drawer',
202 },
203 activateNextService: {
204 id: 'menu.services.setNextServiceActive',
205 defaultMessage: '!!!Activate next service...',
206 },
207 activatePreviousService: {
208 id: 'menu.services.activatePreviousService',
209 defaultMessage: '!!!Activate previous service...',
210 },
211 muteApp: {
212 id: 'sidebar.muteApp',
213 defaultMessage: '!!!Disable notifications & audio',
214 },
215 unmuteApp: {
216 id: 'sidebar.unmuteApp',
217 defaultMessage: '!!!Enable notifications & audio',
218 },
219 workspaces: {
220 id: 'menu.workspaces',
221 defaultMessage: '!!!Workspaces',
222 },
223 defaultWorkspace: {
224 id: 'menu.workspaces.defaultWorkspace',
225 defaultMessage: '!!!Default',
226 },
182}); 227});
183 228
184function getActiveWebview() { 229function getActiveWebview() {
@@ -239,16 +284,32 @@ const _templateFactory = intl => [
239 }, 284 },
240 { 285 {
241 label: intl.formatMessage(menuItems.resetZoom), 286 label: intl.formatMessage(menuItems.resetZoom),
242 role: 'resetzoom', 287 accelerator: 'Cmd+0',
288 click() {
289 getActiveWebview().setZoomLevel(0);
290 },
243 }, 291 },
244 { 292 {
245 label: intl.formatMessage(menuItems.zoomIn), 293 label: intl.formatMessage(menuItems.zoomIn),
246 // accelerator: 'Cmd+=', 294 accelerator: 'Cmd+plus',
247 role: 'zoomin', 295 click() {
296 const activeService = getActiveWebview();
297 activeService.getZoomLevel((level) => {
298 // level 9 =~ +300% and setZoomLevel wouldnt zoom in further
299 if (level < 9) activeService.setZoomLevel(level + 1);
300 });
301 },
248 }, 302 },
249 { 303 {
250 label: intl.formatMessage(menuItems.zoomOut), 304 label: intl.formatMessage(menuItems.zoomOut),
251 role: 'zoomout', 305 accelerator: 'Cmd+-',
306 click() {
307 const activeService = getActiveWebview();
308 activeService.getZoomLevel((level) => {
309 // level -9 =~ -50% and setZoomLevel wouldnt zoom out further
310 if (level > -9) activeService.setZoomLevel(level - 1);
311 });
312 },
252 }, 313 },
253 { 314 {
254 type: 'separator', 315 type: 'separator',
@@ -266,6 +327,11 @@ const _templateFactory = intl => [
266 submenu: [], 327 submenu: [],
267 }, 328 },
268 { 329 {
330 label: intl.formatMessage(menuItems.workspaces),
331 submenu: [],
332 visible: workspaceStore.isFeatureEnabled,
333 },
334 {
269 label: intl.formatMessage(menuItems.window), 335 label: intl.formatMessage(menuItems.window),
270 role: 'window', 336 role: 'window',
271 submenu: [ 337 submenu: [
@@ -288,8 +354,11 @@ const _templateFactory = intl => [
288 click() { shell.openExternal('https://meetfranz.com'); }, 354 click() { shell.openExternal('https://meetfranz.com'); },
289 }, 355 },
290 { 356 {
291 label: intl.formatMessage(menuItems.changelog), 357 label: intl.formatMessage(menuItems.announcement),
292 click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); }, 358 click: () => {
359 announcementActions.show();
360 },
361 visible: window.franz.stores.user.isLoggedIn && announcementsStore.areNewsAvailable,
293 }, 362 },
294 { 363 {
295 type: 'separator', 364 type: 'separator',
@@ -392,10 +461,12 @@ const _titleBarTemplateFactory = intl => [
392 }, 461 },
393 { 462 {
394 label: intl.formatMessage(menuItems.zoomIn), 463 label: intl.formatMessage(menuItems.zoomIn),
395 accelerator: `${ctrlKey}+Plus`, 464 accelerator: `${ctrlKey}+=`,
396 click() { 465 click() {
397 getActiveWebview().getZoomLevel((zoomLevel) => { 466 const activeService = getActiveWebview();
398 getActiveWebview().setZoomLevel(zoomLevel === 5 ? zoomLevel : zoomLevel + 1); 467 activeService.getZoomLevel((level) => {
468 // level 9 =~ +300% and setZoomLevel wouldnt zoom in further
469 if (level < 9) activeService.setZoomLevel(level + 1);
399 }); 470 });
400 }, 471 },
401 }, 472 },
@@ -403,8 +474,10 @@ const _titleBarTemplateFactory = intl => [
403 label: intl.formatMessage(menuItems.zoomOut), 474 label: intl.formatMessage(menuItems.zoomOut),
404 accelerator: `${ctrlKey}+-`, 475 accelerator: `${ctrlKey}+-`,
405 click() { 476 click() {
406 getActiveWebview().getZoomLevel((zoomLevel) => { 477 const activeService = getActiveWebview();
407 getActiveWebview().setZoomLevel(zoomLevel === -5 ? zoomLevel : zoomLevel - 1); 478 activeService.getZoomLevel((level) => {
479 // level -9 =~ -50% and setZoomLevel wouldnt zoom out further
480 if (level > -9) activeService.setZoomLevel(level - 1);
408 }); 481 });
409 }, 482 },
410 }, 483 },
@@ -499,13 +572,14 @@ export default class FranzMenu {
499 } 572 }
500 573
501 _build() { 574 _build() {
502 const serviceTpl = Object.assign([], this.serviceTpl); // need to clone object so we don't modify computed (cached) object 575 // need to clone object so we don't modify computed (cached) object
576 const serviceTpl = Object.assign([], this.serviceTpl());
503 577
504 if (window.franz === undefined) { 578 if (window.franz === undefined) {
505 return; 579 return;
506 } 580 }
507 581
508 const intl = window.franz.intl; 582 const { intl } = window.franz;
509 const tpl = isMac ? _templateFactory(intl) : _titleBarTemplateFactory(intl); 583 const tpl = isMac ? _templateFactory(intl) : _titleBarTemplateFactory(intl);
510 584
511 tpl[1].submenu.push({ 585 tpl[1].submenu.push({
@@ -632,7 +706,7 @@ export default class FranzMenu {
632 }, 706 },
633 ); 707 );
634 708
635 tpl[4].submenu.unshift(about, { 709 tpl[5].submenu.unshift(about, {
636 type: 'separator', 710 type: 'separator',
637 }); 711 });
638 } else { 712 } else {
@@ -663,42 +737,122 @@ export default class FranzMenu {
663 }, about); 737 }, about);
664 } 738 }
665 739
666 serviceTpl.unshift({ 740 if (serviceTpl.length > 0) {
741 tpl[3].submenu = serviceTpl;
742 }
743
744 if (workspaceStore.isFeatureEnabled) {
745 tpl[4].submenu = this.workspacesMenu();
746 }
747
748 this.currentTemplate = tpl;
749 const menu = Menu.buildFromTemplate(tpl);
750 Menu.setApplicationMenu(menu);
751 }
752
753 serviceTpl() {
754 const { intl } = window.franz;
755 const { user, services, settings } = this.stores;
756 if (!user.isLoggedIn) return [];
757 const menu = [];
758
759 menu.push({
667 label: intl.formatMessage(menuItems.addNewService), 760 label: intl.formatMessage(menuItems.addNewService),
668 accelerator: `${cmdKey}+N`, 761 accelerator: `${cmdKey}+N`,
669 click: () => { 762 click: () => {
670 this.actions.ui.openSettings({ path: 'recipes' }); 763 this.actions.ui.openSettings({ path: 'recipes' });
671 }, 764 },
672 enabled: this.stores.user.isLoggedIn, 765 }, {
766 type: 'separator',
767 }, {
768 label: intl.formatMessage(menuItems.activateNextService),
769 accelerator: `${cmdKey}+alt+right`,
770 click: () => this.actions.service.setActiveNext(),
771 }, {
772 label: intl.formatMessage(menuItems.activatePreviousService),
773 accelerator: `${cmdKey}+alt+left`,
774 click: () => this.actions.service.setActivePrev(),
775 }, {
776 label: intl.formatMessage(
777 settings.all.app.isAppMuted ? menuItems.unmuteApp : menuItems.muteApp,
778 ).replace('&', '&&'),
779 accelerator: `${cmdKey}+shift+m`,
780 click: () => this.actions.app.toggleMuteApp(),
673 }, { 781 }, {
674 type: 'separator', 782 type: 'separator',
675 }); 783 });
676 784
677 if (serviceTpl.length > 0) { 785 services.allDisplayed.forEach((service, i) => (menu.push({
678 tpl[3].submenu = serviceTpl; 786 label: this._getServiceName(service),
679 } 787 accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null,
788 type: 'radio',
789 checked: service.isActive,
790 click: () => {
791 this.actions.service.setActive({ serviceId: service.id });
792 },
793 })));
680 794
681 this.currentTemplate = tpl; 795 return menu;
682 const menu = Menu.buildFromTemplate(tpl);
683 Menu.setApplicationMenu(menu);
684 } 796 }
685 797
686 @computed get serviceTpl() { 798 workspacesMenu() {
687 const services = this.stores.services.allDisplayed; 799 const { workspaces, activeWorkspace, isWorkspaceDrawerOpen } = workspaceStore;
800 const { intl } = window.franz;
801 const menu = [];
802
803 // Add new workspace item:
804 menu.push({
805 label: intl.formatMessage(menuItems.addNewWorkspace),
806 accelerator: `${cmdKey}+Shift+N`,
807 click: () => {
808 workspaceActions.openWorkspaceSettings();
809 },
810 enabled: this.stores.user.isLoggedIn,
811 });
812
813 // Open workspace drawer:
814 const drawerLabel = (
815 isWorkspaceDrawerOpen ? menuItems.closeWorkspaceDrawer : menuItems.openWorkspaceDrawer
816 );
817 menu.push({
818 label: intl.formatMessage(drawerLabel),
819 accelerator: `${cmdKey}+D`,
820 click: () => {
821 workspaceActions.toggleWorkspaceDrawer();
822 gaEvent(GA_CATEGORY_WORKSPACES, 'toggleDrawer', 'menu');
823 },
824 enabled: this.stores.user.isLoggedIn,
825 }, {
826 type: 'separator',
827 });
828
829 // Default workspace
830 menu.push({
831 label: intl.formatMessage(menuItems.defaultWorkspace),
832 accelerator: `${cmdKey}+Alt+0`,
833 type: 'radio',
834 checked: !activeWorkspace,
835 click: () => {
836 workspaceActions.deactivate();
837 gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'menu');
838 },
839 });
688 840
689 if (this.stores.user.isLoggedIn) { 841 // Workspace items
690 return services.map((service, i) => ({ 842 if (this.stores.user.isPremium) {
691 label: this._getServiceName(service), 843 workspaces.forEach((workspace, i) => menu.push({
692 accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, 844 label: workspace.name,
845 accelerator: i < 9 ? `${cmdKey}+Alt+${i + 1}` : null,
693 type: 'radio', 846 type: 'radio',
694 checked: service.isActive, 847 checked: activeWorkspace ? workspace.id === activeWorkspace.id : false,
695 click: () => { 848 click: () => {
696 this.actions.service.setActive({ serviceId: service.id }); 849 workspaceActions.activate({ workspace });
850 gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'menu');
697 }, 851 },
698 })); 852 }));
699 } 853 }
700 854
701 return []; 855 return menu;
702 } 856 }
703 857
704 _getServiceName(service) { 858 _getServiceName(service) {
diff --git a/src/lib/Tray.js b/src/lib/Tray.js
index 669b02709..192e24796 100644
--- a/src/lib/Tray.js
+++ b/src/lib/Tray.js
@@ -22,7 +22,11 @@ export default class TrayIcon {
22 { 22 {
23 label: 'Show Franz', 23 label: 'Show Franz',
24 click() { 24 click() {
25 if (app.mainWindow.isMinimized()) {
26 app.mainWindow.restore();
27 }
25 app.mainWindow.show(); 28 app.mainWindow.show();
29 app.mainWindow.focus();
26 }, 30 },
27 }, { 31 }, {
28 label: 'Quit Franz', 32 label: 'Quit Franz',
@@ -36,7 +40,11 @@ export default class TrayIcon {
36 this.trayIcon.setContextMenu(trayMenu); 40 this.trayIcon.setContextMenu(trayMenu);
37 41
38 this.trayIcon.on('click', () => { 42 this.trayIcon.on('click', () => {
43 if (app.mainWindow.isMinimized()) {
44 app.mainWindow.restore();
45 }
39 app.mainWindow.show(); 46 app.mainWindow.show();
47 app.mainWindow.focus();
40 }); 48 });
41 49
42 if (process.platform === 'darwin') { 50 if (process.platform === 'darwin') {
diff --git a/src/lib/analytics.js b/src/lib/analytics.js
index 7044e5bb7..c305fdb00 100644
--- a/src/lib/analytics.js
+++ b/src/lib/analytics.js
@@ -1,5 +1,8 @@
1import { remote } from 'electron'; 1import { remote } from 'electron';
2import { GA_ID } from '../config'; 2import querystring from 'querystring';
3
4import { GA_ID, STATS_API } from '../config';
5import { isDevMode } from '../environment';
3 6
4const debug = require('debug')('Franz:Analytics'); 7const debug = require('debug')('Franz:Analytics');
5 8
@@ -28,16 +31,25 @@ ga('send', 'App');
28 31
29export function gaPage(page) { 32export function gaPage(page) {
30 ga('send', 'pageview', page); 33 ga('send', 'pageview', page);
31
32 debug('GA track page', page); 34 debug('GA track page', page);
33} 35}
34 36
35export function gaEvent(category, action, label) { 37export function gaEvent(category, action, label) {
36 ga('send', 'event', category, action, label); 38 ga('send', 'event', category, action, label);
37 39 debug('GA track event', category, action, label);
38 debug('GA track event', category, action);
39} 40}
40 41
41setTimeout(() => { 42export function statsEvent(key, value) {
42 ga('send', 'Ping'); 43 const params = {
43}, 1000 * 60 * 10); // Ping GA every 10 Minutes 44 key,
45 value: value || key,
46 platform: process.platform,
47 version: remote.app.getVersion(),
48 };
49
50 debug('Send Franz stats event', params);
51
52 if (!isDevMode) {
53 window.fetch(`${STATS_API}/event/?${querystring.stringify(params)}`);
54 }
55}
diff --git a/src/models/Service.js b/src/models/Service.js
index eee8df8ca..8a2a8d3d8 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -202,7 +202,7 @@ export default class Service {
202 202
203 this.webview.addEventListener('did-fail-load', (event) => { 203 this.webview.addEventListener('did-fail-load', (event) => {
204 debug('Service failed to load', this.name, event); 204 debug('Service failed to load', this.name, event);
205 if (event.isMainFrame && event.errorCode !== -27 && event.errorCode !== -3) { 205 if (event.isMainFrame && event.errorCode !== -21 && event.errorCode !== -3) {
206 this.isError = true; 206 this.isError = true;
207 this.errorMessage = event.errorDescription; 207 this.errorMessage = event.errorDescription;
208 this.isLoading = false; 208 this.isLoading = false;
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index dd4642d70..72c4b4d0b 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -1,21 +1,25 @@
1import { remote, ipcRenderer, shell } from 'electron'; 1import { remote, ipcRenderer, shell } from 'electron';
2import { action, computed, observable } from 'mobx'; 2import {
3 action, computed, observable, reaction,
4} from 'mobx';
3import moment from 'moment'; 5import moment from 'moment';
4import key from 'keymaster';
5import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; 6import { getDoNotDisturb } from '@meetfranz/electron-notification-state';
6import AutoLaunch from 'auto-launch'; 7import AutoLaunch from 'auto-launch';
7import prettyBytes from 'pretty-bytes'; 8import prettyBytes from 'pretty-bytes';
9import ms from 'ms';
10import { URL } from 'url';
8 11
9import Store from './lib/Store'; 12import Store from './lib/Store';
10import Request from './lib/Request'; 13import Request from './lib/Request';
11import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; 14import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config';
12import { isMac, isLinux, isWindows } from '../environment'; 15import { isMac } from '../environment';
13import locales from '../i18n/translations'; 16import locales from '../i18n/translations';
14import { gaEvent } from '../lib/analytics'; 17import { gaEvent, gaPage, statsEvent } from '../lib/analytics';
15import { onVisibilityChange } from '../helpers/visibility-helper'; 18import { onVisibilityChange } from '../helpers/visibility-helper';
16import { getLocale } from '../helpers/i18n-helpers'; 19import { getLocale } from '../helpers/i18n-helpers';
17 20
18import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; 21import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js';
22import { isValidExternalURL } from '../helpers/url-helpers';
19 23
20const debug = require('debug')('Franz:AppStore'); 24const debug = require('debug')('Franz:AppStore');
21 25
@@ -63,6 +67,8 @@ export default class AppStore extends Store {
63 67
64 @observable isFocused = true; 68 @observable isFocused = true;
65 69
70 @observable nextAppReleaseVersion = null;
71
66 dictionaries = []; 72 dictionaries = [];
67 73
68 constructor(...args) { 74 constructor(...args) {
@@ -110,16 +116,16 @@ export default class AppStore extends Store {
110 // Check if system is muted 116 // Check if system is muted
111 // There are no events to subscribe so we need to poll everey 5s 117 // There are no events to subscribe so we need to poll everey 5s
112 this._systemDND(); 118 this._systemDND();
113 setInterval(() => this._systemDND(), 5000); 119 setInterval(() => this._systemDND(), ms('5s'));
114 120
115 // Check for updates once every 4 hours 121 // Check for updates once every 4 hours
116 setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); 122 setInterval(() => this._checkForUpdates(), CHECK_INTERVAL);
117 // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) 123 // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues)
118 setTimeout(() => this._checkForUpdates(), 30000); 124 setTimeout(() => this._checkForUpdates(), ms('30s'));
119 ipcRenderer.on('autoUpdate', (event, data) => { 125 ipcRenderer.on('autoUpdate', (event, data) => {
120 if (data.available) { 126 if (data.available) {
121 this.updateStatus = this.updateStatusTypes.AVAILABLE; 127 this.updateStatus = this.updateStatusTypes.AVAILABLE;
122 128 this.nextAppReleaseVersion = data.version;
123 if (isMac) { 129 if (isMac) {
124 app.dock.bounce(); 130 app.dock.bounce();
125 } 131 }
@@ -143,32 +149,14 @@ export default class AppStore extends Store {
143 149
144 // Handle deep linking (franz://) 150 // Handle deep linking (franz://)
145 ipcRenderer.on('navigateFromDeepLink', (event, data) => { 151 ipcRenderer.on('navigateFromDeepLink', (event, data) => {
146 const { url } = data; 152 debug('Navigate from deep link', data);
153 let { url } = data;
147 if (!url) return; 154 if (!url) return;
148 155
149 this.stores.router.push(data.url); 156 url = url.replace(/\/$/, '');
150 });
151
152 // Set active the next service
153 key(
154 '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => {
155 this.actions.service.setActiveNext();
156 },
157 );
158 157
159 // Set active the prev service 158 this.stores.router.push(url);
160 key( 159 });
161 '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => {
162 this.actions.service.setActivePrev();
163 },
164 );
165
166 // Global Mute
167 key(
168 '⌘+shift+m ctrl+shift+m', () => {
169 this.actions.app.toggleMuteApp();
170 },
171 );
172 160
173 this.locale = this._getDefaultLocale(); 161 this.locale = this._getDefaultLocale();
174 162
@@ -181,6 +169,13 @@ export default class AppStore extends Store {
181 169
182 debug('Window is visible/focused', isVisible); 170 debug('Window is visible/focused', isVisible);
183 }); 171 });
172
173 // analytics autorun
174 reaction(() => this.stores.router.location.pathname, (pathname) => {
175 gaPage(pathname);
176 });
177
178 statsEvent('app-start');
184 } 179 }
185 180
186 @computed get cacheSize() { 181 @computed get cacheSize() {
@@ -193,7 +188,15 @@ export default class AppStore extends Store {
193 }) { 188 }) {
194 if (this.stores.settings.all.app.isAppMuted) return; 189 if (this.stores.settings.all.app.isAppMuted) return;
195 190
191 // TODO: is there a simple way to use blobs for notifications without storing them on disk?
192 if (options.icon.startsWith('blob:')) {
193 delete options.icon;
194 }
195
196 const notification = new window.Notification(title, options); 196 const notification = new window.Notification(title, options);
197
198 debug('New notification', title, options);
199
197 notification.onclick = (e) => { 200 notification.onclick = (e) => {
198 if (serviceId) { 201 if (serviceId) {
199 this.actions.service.sendIPCMessage({ 202 this.actions.service.sendIPCMessage({
@@ -203,12 +206,13 @@ export default class AppStore extends Store {
203 }); 206 });
204 207
205 this.actions.service.setActive({ serviceId }); 208 this.actions.service.setActive({ serviceId });
206 209 mainWindow.show();
207 if (isWindows) { 210 if (app.mainWindow.isMinimized()) {
208 mainWindow.restore(); 211 mainWindow.restore();
209 } else if (isLinux) {
210 mainWindow.show();
211 } 212 }
213 mainWindow.focus();
214
215 debug('Notification click handler');
212 } 216 }
213 }; 217 };
214 } 218 }
@@ -244,7 +248,14 @@ export default class AppStore extends Store {
244 } 248 }
245 249
246 @action _openExternalUrl({ url }) { 250 @action _openExternalUrl({ url }) {
247 shell.openExternal(url); 251 const parsedUrl = new URL(url);
252 debug('open external url', parsedUrl);
253
254 if (isValidExternalURL(url)) {
255 shell.openExternal(url);
256 }
257
258 gaEvent('External URL', 'open', parsedUrl.host);
248 } 259 }
249 260
250 @action _checkForUpdates() { 261 @action _checkForUpdates() {
@@ -268,7 +279,6 @@ export default class AppStore extends Store {
268 279
269 @action _muteApp({ isMuted, overrideSystemMute = true }) { 280 @action _muteApp({ isMuted, overrideSystemMute = true }) {
270 this.isSystemMuteOverridden = overrideSystemMute; 281 this.isSystemMuteOverridden = overrideSystemMute;
271
272 this.actions.settings.update({ 282 this.actions.settings.update({
273 type: 'app', 283 type: 'app',
274 data: { 284 data: {
@@ -305,7 +315,7 @@ export default class AppStore extends Store {
305 } else { 315 } else {
306 const deltaTime = moment().diff(this.timeOfflineStart); 316 const deltaTime = moment().diff(this.timeOfflineStart);
307 317
308 if (deltaTime > 30 * 60 * 1000) { 318 if (deltaTime > ms('30m')) {
309 this.actions.service.reloadAll(); 319 this.actions.service.reloadAll();
310 } 320 }
311 } 321 }
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
index 0adee6adf..e7832088b 100644
--- a/src/stores/FeaturesStore.js
+++ b/src/stores/FeaturesStore.js
@@ -1,4 +1,9 @@
1import { computed, observable, reaction } from 'mobx'; 1import {
2 computed,
3 observable,
4 reaction,
5 runInAction,
6} from 'mobx';
2 7
3import Store from './lib/Store'; 8import Store from './lib/Store';
4import CachedRequest from './lib/CachedRequest'; 9import CachedRequest from './lib/CachedRequest';
@@ -7,6 +12,10 @@ import delayApp from '../features/delayApp';
7import spellchecker from '../features/spellchecker'; 12import spellchecker from '../features/spellchecker';
8import serviceProxy from '../features/serviceProxy'; 13import serviceProxy from '../features/serviceProxy';
9import basicAuth from '../features/basicAuth'; 14import basicAuth from '../features/basicAuth';
15import workspaces from '../features/workspaces';
16import shareFranz from '../features/shareFranz';
17import announcements from '../features/announcements';
18import settingsWS from '../features/settingsWS';
10 19
11import { DEFAULT_FEATURES_CONFIG } from '../config'; 20import { DEFAULT_FEATURES_CONFIG } from '../config';
12 21
@@ -15,13 +24,16 @@ export default class FeaturesStore extends Store {
15 24
16 @observable featuresRequest = new CachedRequest(this.api.features, 'features'); 25 @observable featuresRequest = new CachedRequest(this.api.features, 'features');
17 26
27 @observable features = Object.assign({}, DEFAULT_FEATURES_CONFIG);
28
18 async setup() { 29 async setup() {
19 this.registerReactions([ 30 this.registerReactions([
31 this._updateFeatures,
20 this._monitorLoginStatus.bind(this), 32 this._monitorLoginStatus.bind(this),
21 ]); 33 ]);
22 34
23 await this.featuresRequest._promise; 35 await this.featuresRequest._promise;
24 setTimeout(this._enableFeatures.bind(this), 1); 36 setTimeout(this._setupFeatures.bind(this), 1);
25 37
26 // single key reaction 38 // single key reaction
27 reaction(() => this.stores.user.data.isPremium, () => { 39 reaction(() => this.stores.user.data.isPremium, () => {
@@ -35,13 +47,16 @@ export default class FeaturesStore extends Store {
35 return this.defaultFeaturesRequest.execute().result || DEFAULT_FEATURES_CONFIG; 47 return this.defaultFeaturesRequest.execute().result || DEFAULT_FEATURES_CONFIG;
36 } 48 }
37 49
38 @computed get features() { 50 _updateFeatures = () => {
51 const features = Object.assign({}, DEFAULT_FEATURES_CONFIG);
39 if (this.stores.user.isLoggedIn) { 52 if (this.stores.user.isLoggedIn) {
40 return this.featuresRequest.execute().result || DEFAULT_FEATURES_CONFIG; 53 const requestResult = this.featuresRequest.execute().result;
54 Object.assign(features, requestResult);
41 } 55 }
42 56 runInAction('FeaturesStore::_updateFeatures', () => {
43 return DEFAULT_FEATURES_CONFIG; 57 this.features = features;
44 } 58 });
59 };
45 60
46 _monitorLoginStatus() { 61 _monitorLoginStatus() {
47 if (this.stores.user.isLoggedIn) { 62 if (this.stores.user.isLoggedIn) {
@@ -51,10 +66,14 @@ export default class FeaturesStore extends Store {
51 } 66 }
52 } 67 }
53 68
54 _enableFeatures() { 69 _setupFeatures() {
55 delayApp(this.stores, this.actions); 70 delayApp(this.stores, this.actions);
56 spellchecker(this.stores, this.actions); 71 spellchecker(this.stores, this.actions);
57 serviceProxy(this.stores, this.actions); 72 serviceProxy(this.stores, this.actions);
58 basicAuth(this.stores, this.actions); 73 basicAuth(this.stores, this.actions);
74 workspaces(this.stores, this.actions);
75 shareFranz(this.stores, this.actions);
76 announcements(this.stores, this.actions);
77 settingsWS(this.stores, this.actions);
59 } 78 }
60} 79}
diff --git a/src/stores/PaymentStore.js b/src/stores/PaymentStore.js
index 4cabee194..d4de476c8 100644
--- a/src/stores/PaymentStore.js
+++ b/src/stores/PaymentStore.js
@@ -10,15 +10,10 @@ export default class PaymentStore extends Store {
10 10
11 @observable createHostedPageRequest = new Request(this.api.payment, 'getHostedPage'); 11 @observable createHostedPageRequest = new Request(this.api.payment, 'getHostedPage');
12 12
13 @observable createDashboardUrlRequest = new Request(this.api.payment, 'getDashboardUrl');
14
15 @observable ordersDataRequest = new CachedRequest(this.api.payment, 'getOrders');
16
17 constructor(...args) { 13 constructor(...args) {
18 super(...args); 14 super(...args);
19 15
20 this.actions.payment.createHostedPage.listen(this._createHostedPage.bind(this)); 16 this.actions.payment.createHostedPage.listen(this._createHostedPage.bind(this));
21 this.actions.payment.createDashboardUrl.listen(this._createDashboardUrl.bind(this));
22 } 17 }
23 18
24 @computed get plan() { 19 @computed get plan() {
@@ -28,10 +23,6 @@ export default class PaymentStore extends Store {
28 return this.plansRequest.execute().result || {}; 23 return this.plansRequest.execute().result || {};
29 } 24 }
30 25
31 @computed get orders() {
32 return this.ordersDataRequest.execute().result || [];
33 }
34
35 @action _createHostedPage({ planId }) { 26 @action _createHostedPage({ planId }) {
36 const request = this.createHostedPageRequest.execute(planId); 27 const request = this.createHostedPageRequest.execute(planId);
37 28
@@ -39,12 +30,4 @@ export default class PaymentStore extends Store {
39 30
40 return request; 31 return request;
41 } 32 }
42
43 @action _createDashboardUrl() {
44 const request = this.createDashboardUrlRequest.execute();
45
46 gaEvent('Payment', 'createDashboardUrl');
47
48 return request;
49 }
50} 33}
diff --git a/src/stores/RecipePreviewsStore.js b/src/stores/RecipePreviewsStore.js
index 10b2928e3..382820d58 100644
--- a/src/stores/RecipePreviewsStore.js
+++ b/src/stores/RecipePreviewsStore.js
@@ -1,5 +1,6 @@
1import { action, computed, observable } from 'mobx'; 1import { action, computed, observable } from 'mobx';
2import { debounce } from 'lodash'; 2import { debounce } from 'lodash';
3import ms from 'ms';
3 4
4import Store from './lib/Store'; 5import Store from './lib/Store';
5import CachedRequest from './lib/CachedRequest'; 6import CachedRequest from './lib/CachedRequest';
@@ -48,5 +49,5 @@ export default class RecipePreviewsStore extends Store {
48 // Helper 49 // Helper
49 _analyticsSearch = debounce((needle) => { 50 _analyticsSearch = debounce((needle) => {
50 gaEvent('Recipe', 'search', needle); 51 gaEvent('Recipe', 'search', needle);
51 }, 3000); 52 }, ms('3s'));
52} 53}
diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js
index 2629e0a38..9254e3223 100644
--- a/src/stores/RequestStore.js
+++ b/src/stores/RequestStore.js
@@ -1,4 +1,5 @@
1import { action, computed, observable } from 'mobx'; 1import { action, computed, observable } from 'mobx';
2import ms from 'ms';
2 3
3import Store from './lib/Store'; 4import Store from './lib/Store';
4 5
@@ -13,7 +14,7 @@ export default class RequestStore extends Store {
13 14
14 retries = 0; 15 retries = 0;
15 16
16 retryDelay = 2000; 17 retryDelay = ms('2s');
17 18
18 constructor(...args) { 19 constructor(...args) {
19 super(...args); 20 super(...args);
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index efd57a09d..13f929c2f 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -5,12 +5,14 @@ import {
5 observable, 5 observable,
6} from 'mobx'; 6} from 'mobx';
7import { debounce, remove } from 'lodash'; 7import { debounce, remove } from 'lodash';
8import ms from 'ms';
8 9
9import Store from './lib/Store'; 10import Store from './lib/Store';
10import Request from './lib/Request'; 11import Request from './lib/Request';
11import CachedRequest from './lib/CachedRequest'; 12import CachedRequest from './lib/CachedRequest';
12import { matchRoute } from '../helpers/routing-helpers'; 13import { matchRoute } from '../helpers/routing-helpers';
13import { gaEvent } from '../lib/analytics'; 14import { gaEvent, statsEvent } from '../lib/analytics';
15import { workspaceStore } from '../features/workspaces';
14 16
15const debug = require('debug')('Franz:ServiceStore'); 17const debug = require('debug')('Franz:ServiceStore');
16 18
@@ -34,6 +36,7 @@ export default class ServicesStore extends Store {
34 36
35 // Register action handlers 37 // Register action handlers
36 this.actions.service.setActive.listen(this._setActive.bind(this)); 38 this.actions.service.setActive.listen(this._setActive.bind(this));
39 this.actions.service.blurActive.listen(this._blurActive.bind(this));
37 this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); 40 this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this));
38 this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); 41 this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this));
39 this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); 42 this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this));
@@ -43,6 +46,7 @@ export default class ServicesStore extends Store {
43 this.actions.service.deleteService.listen(this._deleteService.bind(this)); 46 this.actions.service.deleteService.listen(this._deleteService.bind(this));
44 this.actions.service.clearCache.listen(this._clearCache.bind(this)); 47 this.actions.service.clearCache.listen(this._clearCache.bind(this));
45 this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this)); 48 this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this));
49 this.actions.service.detachService.listen(this._detachService.bind(this));
46 this.actions.service.focusService.listen(this._focusService.bind(this)); 50 this.actions.service.focusService.listen(this._focusService.bind(this));
47 this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this)); 51 this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this));
48 this.actions.service.toggleService.listen(this._toggleService.bind(this)); 52 this.actions.service.toggleService.listen(this._toggleService.bind(this));
@@ -97,7 +101,6 @@ export default class ServicesStore extends Store {
97 return observable(services.slice().slice().sort((a, b) => a.order - b.order)); 101 return observable(services.slice().slice().sort((a, b) => a.order - b.order));
98 } 102 }
99 } 103 }
100
101 return []; 104 return [];
102 } 105 }
103 106
@@ -106,13 +109,16 @@ export default class ServicesStore extends Store {
106 } 109 }
107 110
108 @computed get allDisplayed() { 111 @computed get allDisplayed() {
109 return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled; 112 const services = this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled;
113 return workspaceStore.filterServicesByActiveWorkspace(services);
110 } 114 }
111 115
112 // This is just used to avoid unnecessary rerendering of resource-heavy webviews 116 // This is just used to avoid unnecessary rerendering of resource-heavy webviews
113 @computed get allDisplayedUnordered() { 117 @computed get allDisplayedUnordered() {
118 const { showDisabledServices } = this.stores.settings.all.app;
114 const services = this.allServicesRequest.execute().result || []; 119 const services = this.allServicesRequest.execute().result || [];
115 return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled); 120 const filteredServices = showDisabledServices ? services : services.filter(service => service.isEnabled);
121 return workspaceStore.filterServicesByActiveWorkspace(filteredServices);
116 } 122 }
117 123
118 @computed get filtered() { 124 @computed get filtered() {
@@ -293,9 +299,16 @@ export default class ServicesStore extends Store {
293 }); 299 });
294 service.isActive = true; 300 service.isActive = true;
295 301
302 statsEvent('activate-service', service.recipe.id);
303
296 this._focusActiveService(); 304 this._focusActiveService();
297 } 305 }
298 306
307 @action _blurActive() {
308 if (!this.active) return;
309 this.active.isActive = false;
310 }
311
299 @action _setActiveNext() { 312 @action _setActiveNext() {
300 const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); 313 const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length);
301 314
@@ -340,6 +353,11 @@ export default class ServicesStore extends Store {
340 service.isAttached = true; 353 service.isAttached = true;
341 } 354 }
342 355
356 @action _detachService({ service }) {
357 service.webview = null;
358 service.isAttached = false;
359 }
360
343 @action _focusService({ serviceId }) { 361 @action _focusService({ serviceId }) {
344 const service = this.one(serviceId); 362 const service = this.one(serviceId);
345 363
@@ -679,7 +697,7 @@ export default class ServicesStore extends Store {
679 _initRecipePolling(serviceId) { 697 _initRecipePolling(serviceId) {
680 const service = this.one(serviceId); 698 const service = this.one(serviceId);
681 699
682 const delay = 2000; 700 const delay = ms('2s');
683 701
684 if (service) { 702 if (service) {
685 if (service.timer !== null) { 703 if (service.timer !== null) {
@@ -700,7 +718,7 @@ export default class ServicesStore extends Store {
700 718
701 _reorderAnalytics = debounce(() => { 719 _reorderAnalytics = debounce(() => {
702 gaEvent('Service', 'order'); 720 gaEvent('Service', 'order');
703 }, 5000); 721 }, ms('5s'));
704 722
705 _wrapIndex(index, delta, size) { 723 _wrapIndex(index, delta, size) {
706 return (((index + delta) % size) + size) % size; 724 return (((index + delta) % size) + size) % size;
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index d37ebe4c7..a95a8e1e0 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -1,8 +1,7 @@
1import { action, observable, computed } from 'mobx'; 1import { action, observable, computed } from 'mobx';
2import { theme } from '@meetfranz/theme';
2 3
3import Store from './lib/Store'; 4import Store from './lib/Store';
4import * as themeDefault from '../theme/default';
5import * as themeDark from '../theme/dark';
6 5
7export default class UIStore extends Store { 6export default class UIStore extends Store {
8 @observable showServicesUpdatedInfoBar = false; 7 @observable showServicesUpdatedInfoBar = false;
@@ -22,12 +21,13 @@ export default class UIStore extends Store {
22 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted; 21 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted;
23 } 22 }
24 23
25 @computed get theme() { 24 @computed get isDarkThemeActive() {
26 if (this.stores.settings.all.app.darkMode) { 25 return this.stores.settings.all.app.darkMode;
27 return Object.assign({}, themeDefault, themeDark); 26 }
28 }
29 27
30 return themeDefault; 28 @computed get theme() {
29 if (this.isDarkThemeActive) return theme('dark');
30 return theme('default');
31 } 31 }
32 32
33 // Actions 33 // Actions
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 7addb5760..31555dd5c 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -129,10 +129,6 @@ export default class UserStore extends Store {
129 return Boolean(localStorage.getItem('authToken')); 129 return Boolean(localStorage.getItem('authToken'));
130 } 130 }
131 131
132 // @computed get isTokenValid() {
133 // return this.authToken !== null && moment(this.tokenExpiry).isAfter(moment());
134 // }
135
136 @computed get isTokenExpired() { 132 @computed get isTokenExpired() {
137 if (!this.authToken) return false; 133 if (!this.authToken) return false;
138 134
@@ -146,6 +142,10 @@ export default class UserStore extends Store {
146 return this.getUserInfoRequest.execute().result || {}; 142 return this.getUserInfoRequest.execute().result || {};
147 } 143 }
148 144
145 @computed get isPremium() {
146 return !!this.data.isPremium;
147 }
148
149 @computed get legacyServices() { 149 @computed get legacyServices() {
150 return this.getLegacyServicesRequest.execute() || {}; 150 return this.getLegacyServicesRequest.execute() || {};
151 } 151 }
@@ -160,6 +160,14 @@ export default class UserStore extends Store {
160 gaEvent('User', 'login'); 160 gaEvent('User', 'login');
161 } 161 }
162 162
163 @action _tokenLogin(authToken) {
164 this._setUserData(authToken);
165
166 this.stores.router.push('/');
167
168 gaEvent('User', 'tokenLogin');
169 }
170
163 @action async _signup({ 171 @action async _signup({
164 firstname, lastname, email, password, accountType, company, 172 firstname, lastname, email, password, accountType, company,
165 }) { 173 }) {
@@ -170,6 +178,7 @@ export default class UserStore extends Store {
170 password, 178 password,
171 accountType, 179 accountType,
172 company, 180 company,
181 locale: this.stores.app.locale,
173 }); 182 });
174 183
175 this.hasCompletedSignup = false; 184 this.hasCompletedSignup = false;
@@ -206,6 +215,8 @@ export default class UserStore extends Store {
206 } 215 }
207 216
208 @action async _update({ userData }) { 217 @action async _update({ userData }) {
218 if (!this.isLoggedIn) return;
219
209 const response = await this.updateUserInfoRequest.execute(userData)._promise; 220 const response = await this.updateUserInfoRequest.execute(userData)._promise;
210 221
211 this.getUserInfoRequest.patch(() => response.data); 222 this.getUserInfoRequest.patch(() => response.data);
@@ -222,6 +233,7 @@ export default class UserStore extends Store {
222 // workaround mobx issue 233 // workaround mobx issue
223 localStorage.removeItem('authToken'); 234 localStorage.removeItem('authToken');
224 window.localStorage.removeItem('authToken'); 235 window.localStorage.removeItem('authToken');
236
225 this.getUserInfoRequest.invalidate().reset(); 237 this.getUserInfoRequest.invalidate().reset();
226 this.authToken = null; 238 this.authToken = null;
227 } 239 }
@@ -262,6 +274,18 @@ export default class UserStore extends Store {
262 const { router } = this.stores; 274 const { router } = this.stores;
263 const currentRoute = router.location.pathname; 275 const currentRoute = router.location.pathname;
264 if (!this.isLoggedIn 276 if (!this.isLoggedIn
277 && currentRoute.includes('token=')) {
278 router.push(this.WELCOME_ROUTE);
279 const token = currentRoute.split('=')[1];
280
281 const data = this._parseToken(token);
282 if (data) {
283 // Give this some time to sink
284 setTimeout(() => {
285 this._tokenLogin(token);
286 }, 1000);
287 }
288 } else if (!this.isLoggedIn
265 && !currentRoute.includes(this.BASE_ROUTE)) { 289 && !currentRoute.includes(this.BASE_ROUTE)) {
266 router.push(this.WELCOME_ROUTE); 290 router.push(this.WELCOME_ROUTE);
267 } else if (this.isLoggedIn 291 } else if (this.isLoggedIn
diff --git a/src/stores/index.js b/src/stores/index.js
index 96b844c95..1912418a2 100644
--- a/src/stores/index.js
+++ b/src/stores/index.js
@@ -10,6 +10,8 @@ import PaymentStore from './PaymentStore';
10import NewsStore from './NewsStore'; 10import NewsStore from './NewsStore';
11import RequestStore from './RequestStore'; 11import RequestStore from './RequestStore';
12import GlobalErrorStore from './GlobalErrorStore'; 12import GlobalErrorStore from './GlobalErrorStore';
13import { workspaceStore } from '../features/workspaces';
14import { announcementsStore } from '../features/announcements';
13 15
14export default (api, actions, router) => { 16export default (api, actions, router) => {
15 const stores = {}; 17 const stores = {};
@@ -27,6 +29,8 @@ export default (api, actions, router) => {
27 news: new NewsStore(stores, api, actions), 29 news: new NewsStore(stores, api, actions),
28 requests: new RequestStore(stores, api, actions), 30 requests: new RequestStore(stores, api, actions),
29 globalError: new GlobalErrorStore(stores, api, actions), 31 globalError: new GlobalErrorStore(stores, api, actions),
32 workspaces: workspaceStore,
33 announcements: announcementsStore,
30 }); 34 });
31 // Initialize all stores 35 // Initialize all stores
32 Object.keys(stores).forEach((name) => { 36 Object.keys(stores).forEach((name) => {
diff --git a/src/stores/lib/Reaction.js b/src/stores/lib/Reaction.js
index 46aa4dae6..f2642908f 100644
--- a/src/stores/lib/Reaction.js
+++ b/src/stores/lib/Reaction.js
@@ -1,24 +1,31 @@
1// @flow
2import { autorun } from 'mobx'; 1import { autorun } from 'mobx';
3 2
4export default class Reaction { 3export default class Reaction {
5 reaction; 4 reaction;
6 5
7 hasBeenStarted; 6 isRunning = false;
8 7
9 dispose; 8 dispose;
10 9
11 constructor(reaction) { 10 constructor(reaction) {
12 this.reaction = reaction; 11 this.reaction = reaction;
13 this.hasBeenStarted = false;
14 } 12 }
15 13
16 start() { 14 start() {
17 this.dispose = autorun(() => this.reaction()); 15 if (!this.isRunning) {
18 this.hasBeenStarted = true; 16 this.dispose = autorun(() => this.reaction());
17 this.isActive = true;
18 }
19 } 19 }
20 20
21 stop() { 21 stop() {
22 if (this.hasBeenStarted) this.dispose(); 22 if (this.isRunning) {
23 this.dispose();
24 this.isActive = false;
25 }
23 } 26 }
24} 27}
28
29export const createReactions = reactions => (
30 reactions.map(r => new Reaction(r))
31);
diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.js
index 04f528156..486de8a49 100644
--- a/src/stores/lib/Request.js
+++ b/src/stores/lib/Request.js
@@ -85,6 +85,8 @@ export default class Request {
85 return this.execute(...this._currentApiCall.args); 85 return this.execute(...this._currentApiCall.args);
86 } 86 }
87 87
88 retry = () => this.reload();
89
88 isExecutingWithArgs(...args) { 90 isExecutingWithArgs(...args) {
89 return this.isExecuting && this._currentApiCall && isEqual(this._currentApiCall.args, args); 91 return this.isExecuting && this._currentApiCall && isEqual(this._currentApiCall.args, args);
90 } 92 }
@@ -107,7 +109,7 @@ export default class Request {
107 Request._hooks.forEach(hook => hook(this)); 109 Request._hooks.forEach(hook => hook(this));
108 } 110 }
109 111
110 reset() { 112 reset = () => {
111 this.result = null; 113 this.result = null;
112 this.isExecuting = false; 114 this.isExecuting = false;
113 this.isError = false; 115 this.isError = false;
@@ -116,5 +118,5 @@ export default class Request {
116 this._promise = Promise; 118 this._promise = Promise;
117 119
118 return this; 120 return this;
119 } 121 };
120} 122}
diff --git a/src/styles/auth.scss b/src/styles/auth.scss
index 817801982..0a075036a 100644
--- a/src/styles/auth.scss
+++ b/src/styles/auth.scss
@@ -107,7 +107,7 @@
107 &__scroll-container { 107 &__scroll-container {
108 max-height: 100vh; 108 max-height: 100vh;
109 padding: 80px 0; 109 padding: 80px 0;
110 overflow: scroll; 110 overflow: auto;
111 width: 100%; 111 width: 100%;
112 } 112 }
113 113
diff --git a/src/styles/badge.scss b/src/styles/badge.scss
index f9fac039a..69879de31 100644
--- a/src/styles/badge.scss
+++ b/src/styles/badge.scss
@@ -8,7 +8,7 @@
8 &.badge--primary, 8 &.badge--primary,
9 &.badge--premium { 9 &.badge--premium {
10 background: $theme-brand-primary; 10 background: $theme-brand-primary;
11 color: $dark-theme-gray-smoke; 11 color: $dark-theme-gray-lightest;
12 } 12 }
13} 13}
14 14
@@ -19,6 +19,7 @@
19 display: inline-block; 19 display: inline-block;
20 font-size: 14px; 20 font-size: 14px;
21 padding: 5px 10px; 21 padding: 5px 10px;
22 letter-spacing: 0;
22 23
23 &.badge--primary, 24 &.badge--primary,
24 &.badge--premium { 25 &.badge--premium {
diff --git a/src/styles/info-bar.scss b/src/styles/info-bar.scss
index fb4917358..d3010942f 100644
--- a/src/styles/info-bar.scss
+++ b/src/styles/info-bar.scss
@@ -43,6 +43,10 @@
43 } 43 }
44 } 44 }
45 45
46 .info-bar__inline-button {
47 color: white;
48 }
49
46 &.info-bar--bottom { order: 10; } 50 &.info-bar--bottom { order: 10; }
47 51
48 &.info-bar--primary { 52 &.info-bar--primary {
diff --git a/src/styles/layout.scss b/src/styles/layout.scss
index 8b7cc512a..e858b7904 100644
--- a/src/styles/layout.scss
+++ b/src/styles/layout.scss
@@ -18,8 +18,14 @@ html { overflow: hidden; }
18 font-size: 22px; 18 font-size: 22px;
19 19
20 &:hover, 20 &:hover,
21 &:active { color: $dark-theme-gray-smoke; } 21 &:active {
22 &.is-muted { color: $theme-brand-primary; } 22 color: $dark-theme-gray-smoke;
23 }
24
25 &.is-muted,
26 &.is-active {
27 color: $theme-brand-primary;
28 }
23 } 29 }
24 } 30 }
25 31
@@ -33,6 +39,7 @@ html { overflow: hidden; }
33 .app__content { display: flex; } 39 .app__content { display: flex; }
34 40
35 .app__service { 41 .app__service {
42 position: relative;
36 display: flex; 43 display: flex;
37 flex: 1; 44 flex: 1;
38 flex-direction: column; 45 flex-direction: column;
@@ -84,7 +91,7 @@ html { overflow: hidden; }
84 91
85 &:hover, 92 &:hover,
86 &:active { color: lighten($theme-gray-light, 10%); } 93 &:active { color: lighten($theme-gray-light, 10%); }
87 &.is-muted { color: $theme-brand-primary; } 94 &.is-muted, &.is-active { color: $theme-brand-primary; }
88 &--new-service { padding-bottom: 6px; } 95 &--new-service { padding-bottom: 6px; }
89 } 96 }
90 97
@@ -124,15 +131,14 @@ html { overflow: hidden; }
124 background: $theme-brand-warning; 131 background: $theme-brand-warning;
125 color: #FFF; 132 color: #FFF;
126 display: block; 133 display: block;
127 font-size: 10px; 134 font-size: 8px;
128 height: auto; 135 height: auto;
129 padding: 4px; 136 padding: 4px;
130 position: fixed; 137 position: fixed;
131 right: 5px; 138 left: 9px;
132 top: 5px; 139 bottom: 0px;
133 transition: opacity .5s ease; 140 transition: opacity .5s ease;
134 width: auto; 141 width: auto;
135 z-index: 999999999; 142 z-index: 999999999;
136 143 pointer-events: none;
137 &:hover { opacity: 0; }
138} 144}
diff --git a/src/styles/settings.scss b/src/styles/settings.scss
index 750b6bedd..1baff8b54 100644
--- a/src/styles/settings.scss
+++ b/src/styles/settings.scss
@@ -61,14 +61,9 @@
61 61
62 .account { 62 .account {
63 .account__box { background: $dark-theme-gray-darker; } 63 .account__box { background: $dark-theme-gray-darker; }
64
65 .invoices {
66 td { border-bottom: 1px solid $dark-theme-gray-darker; }
67 .invoices__action button { color: $theme-brand-primary; }
68 }
69 } 64 }
70 65
71 .premium-info { 66 .premium-info {
72 background: $dark-theme-gray-darker; 67 background: $dark-theme-gray-darker;
73 border: 2px solid $theme-brand-primary; 68 border: 2px solid $theme-brand-primary;
74 } 69 }
@@ -329,15 +324,6 @@
329 .account__avatar { 324 .account__avatar {
330 margin-right: 20px; 325 margin-right: 20px;
331 position: relative; 326 position: relative;
332
333 .emoji img { width: 30px; }
334 }
335
336 .account__avatar-premium {
337 font-size: 26px;
338 position: absolute;
339 right: 2px;
340 top: 2px;
341 } 327 }
342 328
343 .account__info { 329 .account__info {
@@ -345,6 +331,7 @@
345 331
346 h2 { margin-bottom: 5px; } 332 h2 { margin-bottom: 5px; }
347 .badge { margin-top: 5px; } 333 .badge { margin-top: 5px; }
334 .username { margin-right: 10 }
348 } 335 }
349 336
350 .account__subscription { 337 .account__subscription {
@@ -354,6 +341,22 @@
354 .badge { margin-left: 10px; } 341 .badge { margin-left: 10px; }
355 } 342 }
356 343
344 .badge--premium {
345 margin-left: 1px;
346 position: relative;
347 top: -3px;
348 padding-top: 4px;
349 color: #FFF;
350 border-radius: 3px;
351 }
352
353
354 .manage-user-links {
355 margin-top: 20px;
356 display: flex;
357 justify-content: space-between;
358 }
359
357 .account__subscription-button { margin-left: auto; } 360 .account__subscription-button { margin-left: auto; }
358 .franz-form__button { white-space: nowrap; } 361 .franz-form__button { white-space: nowrap; }
359 div { height: auto; } 362 div { height: auto; }
@@ -414,6 +417,7 @@
414 417
415 .settings-navigation__link { 418 .settings-navigation__link {
416 align-items: center; 419 align-items: center;
420 justify-content: space-between;
417 color: $theme-text-color; 421 color: $theme-text-color;
418 display: flex; 422 display: flex;
419 flex-shrink: 0; 423 flex-shrink: 0;
@@ -425,7 +429,9 @@
425 &:hover { 429 &:hover {
426 background: darken($theme-gray-lightest, 5%); 430 background: darken($theme-gray-lightest, 5%);
427 431
428 .badge { background: #FFF; } 432 .badge {
433 background: #FFF;
434 }
429 } 435 }
430 436
431 &.is-active { 437 &.is-active {
@@ -442,8 +448,8 @@
442 .settings-navigation__expander { flex: 1; } 448 .settings-navigation__expander { flex: 1; }
443 449
444 .badge { 450 .badge {
451
445 display: initial; 452 display: initial;
446 margin-left: 5px;
447 transition: background $theme-transition-time, color $theme-transition-time; 453 transition: background $theme-transition-time, color $theme-transition-time;
448 } 454 }
449 455
diff --git a/src/styles/toggle.scss b/src/styles/toggle.scss
index 0ce0c3379..52675ceed 100644
--- a/src/styles/toggle.scss
+++ b/src/styles/toggle.scss
@@ -41,7 +41,7 @@ $toggle-button-size: 22px;
41 41
42 &.is-active .franz-form__toggle-button { 42 &.is-active .franz-form__toggle-button {
43 background: $theme-brand-primary; 43 background: $theme-brand-primary;
44 left: $toggle-width - $toggle-size - 3;; 44 left: $toggle-width - $toggle-size - 3;
45 } 45 }
46 46
47 input { display: none; } 47 input { display: none; }
diff --git a/src/theme/dark/index.js b/src/theme/dark/index.js
deleted file mode 100644
index 8fdb321f3..000000000
--- a/src/theme/dark/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
1import hexToRgba from 'hex-to-rgba';
2
3import * as legacyStyles from '../default/legacy';
4
5export const colorBackground = legacyStyles.darkThemeGrayDarkest;
6export const colorBackgroundSubscriptionContainer = legacyStyles.themeBrandInfo;
7
8export const colorHeadline = legacyStyles.darkThemeTextColor;
9export const colorText = legacyStyles.darkThemeTextColor;
10
11// Error Handler
12export const colorWebviewErrorHandlerBackground = legacyStyles.darkThemeGrayDarkest;
13
14// Loader
15export const colorFullscreenLoaderSpinner = '#FFF';
16export const colorWebviewLoaderBackground = hexToRgba(legacyStyles.darkThemeGrayDarkest, 0.5);
17
18// Modal
19export const colorModalOverlayBackground = hexToRgba(legacyStyles.darkThemeGrayDarkest, 0.8);
diff --git a/src/theme/default/index.js b/src/theme/default/index.js
deleted file mode 100644
index 61410073d..000000000
--- a/src/theme/default/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
1import hexToRgba from 'hex-to-rgba';
2
3import * as legacyStyles from './legacy';
4
5export const brandPrimary = '#3498db';
6export const brandSuccess = '#5cb85c';
7export const brandInfo = '#5bc0de';
8export const brandWarning = '#FF9F00';
9export const brandDanger = '#d9534f';
10
11export const borderRadius = legacyStyles.themeBorderRadius;
12export const borderRadiusSmall = legacyStyles.themeBorderRadiusSmall;
13
14export const colorBackground = legacyStyles.themeGrayLighter;
15export const colorHeadline = legacyStyles.themeGrayDark;
16
17export const colorText = legacyStyles.themeTextColor;
18
19// Subscription Container Component
20export const colorSubscriptionContainerBackground = 'none';
21export const colorSubscriptionContainerBorder = [1, 'solid', brandPrimary];
22export const colorSubscriptionContainerTitle = brandPrimary;
23export const colorSubscriptionContainerActionButtonBackground = brandPrimary;
24export const colorSubscriptionContainerActionButtonColor = '#FFF';
25
26// Error Handler
27export const colorWebviewErrorHandlerBackground = legacyStyles.themeGrayLighter;
28
29// Loader
30export const colorAppLoaderSpinner = '#FFF';
31export const colorFullscreenLoaderSpinner = legacyStyles.themeGrayDark;
32export const colorWebviewLoaderBackground = hexToRgba(legacyStyles.themeGrayLighter, 0.8);
33
34// Modal
35export const colorModalOverlayBackground = hexToRgba(legacyStyles.themeGrayLighter, 0.8);
diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js
index a76c03e5a..a4a6ab899 100644
--- a/src/webview/contextMenu.js
+++ b/src/webview/contextMenu.js
@@ -33,6 +33,8 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
33 const canGoBack = webContents.canGoBack(); 33 const canGoBack = webContents.canGoBack();
34 const canGoForward = webContents.canGoForward(); 34 const canGoForward = webContents.canGoForward();
35 35
36 // @adlk: we can't use roles here due to a bug with electron where electron.remote.webContents.getFocusedWebContents() returns the first webview in DOM instead of the focused one
37 // Github issue creation is pending
36 let menuTpl = [ 38 let menuTpl = [
37 { 39 {
38 type: 'separator', 40 type: 'separator',
@@ -48,19 +50,32 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
48 type: 'separator', 50 type: 'separator',
49 }, { 51 }, {
50 id: 'cut', 52 id: 'cut',
51 role: can('Cut') ? 'cut' : '', 53 label: 'Cut',
54 click() {
55 if (can('Cut')) {
56 webContents.cut();
57 }
58 },
52 enabled: can('Cut'), 59 enabled: can('Cut'),
53 visible: hasText && props.isEditable, 60 visible: hasText && props.isEditable,
54 }, { 61 }, {
55 id: 'copy', 62 id: 'copy',
56 label: 'Copy', 63 label: 'Copy',
57 role: can('Copy') ? 'copy' : '', 64 click() {
65 if (can('Copy')) {
66 webContents.copy();
67 }
68 },
58 enabled: can('Copy'), 69 enabled: can('Copy'),
59 visible: props.isEditable || hasText, 70 visible: props.isEditable || hasText,
60 }, { 71 }, {
61 id: 'paste', 72 id: 'paste',
62 label: 'Paste', 73 label: 'Paste',
63 role: editFlags.canPaste ? 'paste' : '', 74 click() {
75 if (editFlags.canPaste) {
76 webContents.paste();
77 }
78 },
64 enabled: editFlags.canPaste, 79 enabled: editFlags.canPaste,
65 visible: props.isEditable, 80 visible: props.isEditable,
66 }, { 81 }, {
@@ -207,8 +222,6 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
207 }); 222 });
208 }); 223 });
209 224
210 console.log('isSpellcheckEnabled', isSpellcheckEnabled);
211
212 menuTpl.push({ 225 menuTpl.push({
213 type: 'separator', 226 type: 'separator',
214 }, { 227 }, {
@@ -234,6 +247,16 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
234 }, 247 },
235 }, 248 },
236 { 249 {
250 id: 'automaticDetection',
251 label: 'Automatic language detection',
252 type: 'radio',
253 checked: spellcheckerLanguage === 'automatic',
254 click() {
255 debug('Detect language automatically');
256 ipcRenderer.sendToHost('set-service-spellchecker-language', 'automatic');
257 },
258 },
259 {
237 type: 'separator', 260 type: 'separator',
238 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage, 261 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage,
239 }, 262 },
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index c718b348e..1e5d74b1f 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -1,10 +1,12 @@
1import { ipcRenderer } from 'electron'; 1import { ipcRenderer } from 'electron';
2import path from 'path'; 2import path from 'path';
3import { autorun, computed, observable } from 'mobx'; 3import { autorun, computed, observable } from 'mobx';
4import { loadModule } from 'cld3-asm';
5import { debounce } from 'lodash';
4 6
5import RecipeWebview from './lib/RecipeWebview'; 7import RecipeWebview from './lib/RecipeWebview';
6 8
7import spellchecker, { switchDict, disable as disableSpellchecker } from './spellchecker'; 9import spellchecker, { switchDict, disable as disableSpellchecker, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker';
8import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; 10import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode';
9import contextMenu from './contextMenu'; 11import contextMenu from './contextMenu';
10import './notifications'; 12import './notifications';
@@ -40,6 +42,8 @@ class RecipeController {
40 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage; 42 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage;
41 } 43 }
42 44
45 cldIdentifier = null;
46
43 async initialize() { 47 async initialize() {
44 Object.keys(this.ipcEvents).forEach((channel) => { 48 Object.keys(this.ipcEvents).forEach((channel) => {
45 ipcRenderer.on(channel, (...args) => { 49 ipcRenderer.on(channel, (...args) => {
@@ -87,10 +91,22 @@ class RecipeController {
87 91
88 if (this.settings.app.enableSpellchecking) { 92 if (this.settings.app.enableSpellchecking) {
89 debug('Setting spellchecker language to', this.spellcheckerLanguage); 93 debug('Setting spellchecker language to', this.spellcheckerLanguage);
90 switchDict(this.spellcheckerLanguage); 94 let { spellcheckerLanguage } = this;
95 if (spellcheckerLanguage === 'automatic') {
96 this.automaticLanguageDetection();
97 debug('Found `automatic` locale, falling back to user locale until detected', this.settings.app.locale);
98 spellcheckerLanguage = this.settings.app.locale;
99 } else if (this.cldIdentifier) {
100 this.cldIdentifier.destroy();
101 }
102 switchDict(spellcheckerLanguage);
91 } else { 103 } else {
92 debug('Disable spellchecker'); 104 debug('Disable spellchecker');
93 disableSpellchecker(); 105 disableSpellchecker();
106
107 if (this.cldIdentifier) {
108 this.cldIdentifier.destroy();
109 }
94 } 110 }
95 111
96 if (this.settings.service.isDarkModeEnabled) { 112 if (this.settings.service.isDarkModeEnabled) {
@@ -113,6 +129,42 @@ class RecipeController {
113 serviceIdEcho(event) { 129 serviceIdEcho(event) {
114 event.sender.send('service-id', this.settings.service.id); 130 event.sender.send('service-id', this.settings.service.id);
115 } 131 }
132
133 async automaticLanguageDetection() {
134 const cldFactory = await loadModule();
135 this.cldIdentifier = cldFactory.create(0, 1000);
136
137 window.addEventListener('keyup', debounce((e) => {
138 const element = e.target;
139
140 console.log(element);
141
142 if (!element) return;
143
144 let value = '';
145 if (element.isContentEditable) {
146 value = element.textContent;
147 } else if (element.value) {
148 value = element.value;
149 }
150
151 // Force a minimum length to get better detection results
152 if (value.length < 30) return;
153
154 debug('Detecting language for', value);
155 const findResult = this.cldIdentifier.findLanguage(value);
156
157 debug('Language detection result', findResult);
158
159 if (findResult.is_reliable) {
160 const spellcheckerLocale = getSpellcheckerLocaleByFuzzyIdentifier(findResult.language);
161 debug('Language detected reliably, setting spellchecker language to', spellcheckerLocale);
162 if (spellcheckerLocale) {
163 switchDict(spellcheckerLocale);
164 }
165 }
166 }, 225));
167 }
116} 168}
117 169
118/* eslint-disable no-new */ 170/* eslint-disable no-new */
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index becaed449..9158b3b94 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -3,6 +3,7 @@ import { SpellCheckerProvider } from 'electron-hunspell';
3import path from 'path'; 3import path from 'path';
4 4
5import { DICTIONARY_PATH } from '../config'; 5import { DICTIONARY_PATH } from '../config';
6import { SPELLCHECKER_LOCALES } from '../i18n/languages';
6 7
7const debug = require('debug')('Franz:spellchecker'); 8const debug = require('debug')('Franz:spellchecker');
8 9
@@ -82,3 +83,13 @@ export function disable() {
82 currentDict = null; 83 currentDict = null;
83 } 84 }
84} 85}
86
87export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) {
88 const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase());
89
90 if (locales.length >= 1) {
91 return locales[0];
92 }
93
94 return null;
95}