Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35ad6fbad0 | ||
|
|
97f8fe71af | ||
|
|
a9d59b3dcd | ||
|
|
b7240e1c40 | ||
|
|
62aa849657 | ||
|
|
c302ebe282 | ||
|
|
6404bed519 | ||
|
|
8d4d168988 | ||
|
|
d4d3805be8 | ||
|
|
e853af40c4 | ||
|
|
941200cf3b | ||
|
|
cf1f659ebf | ||
|
|
eb381a87bc | ||
|
|
68bc0ae4a0 | ||
|
|
178bc7f401 | ||
|
|
0f1245b975 | ||
|
|
960312a932 | ||
|
|
0e00f3bbce | ||
|
|
ec205f68a6 | ||
|
|
5fe5989710 | ||
|
|
69141b5395 | ||
|
|
8d66f05924 | ||
|
|
e7330dbff8 | ||
|
|
67fa9cca8c | ||
|
|
a90bf1af08 | ||
|
|
cb145acc73 | ||
|
|
099e10673c | ||
|
|
4b3608fc1e | ||
|
|
6128c0e12a | ||
|
|
14a1f5d3e1 | ||
|
|
9cf26f4890 | ||
|
|
397a7381b8 | ||
|
|
24b28f9ded | ||
|
|
9ceabe02d5 | ||
|
|
b207ee57de | ||
|
|
cf9d0c8aa2 | ||
|
|
e97ab2e6dd | ||
|
|
6a7f26d7e8 | ||
|
|
b6e11f623a | ||
|
|
1c60c335fd | ||
|
|
c9249b1724 | ||
|
|
9e957ba704 | ||
|
|
6c37e30233 | ||
|
|
addfe2e414 | ||
|
|
bda0dd29df | ||
|
|
01926e1234 | ||
|
|
9138bbfaf2 | ||
|
|
596561b731 | ||
|
|
5943c21814 | ||
|
|
2456bba5ae | ||
|
|
0fff6336c7 | ||
|
|
4261874e29 | ||
|
|
f976270d33 | ||
|
|
4782f1cfd3 | ||
|
|
2f70621255 | ||
|
|
b6f4e2b83c | ||
|
|
25f4c3aba8 | ||
|
|
1b23468375 | ||
|
|
5d775405d9 | ||
|
|
7f13d9162a | ||
|
|
e0013c22ff | ||
|
|
5c41afdccd | ||
|
|
99a3530238 | ||
|
|
a5ceffc856 | ||
|
|
f55570f2f5 | ||
|
|
4f890c0316 | ||
|
|
bf651dece0 | ||
|
|
1babd8da42 | ||
|
|
bfd146f2d9 | ||
|
|
3126510245 | ||
|
|
d661895545 | ||
|
|
ca9ab6168e | ||
|
|
bbdf2c6017 | ||
|
|
109a9bbd10 | ||
|
|
22d7ef5615 |
8
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,8 +0,0 @@
|
||||
---
|
||||
<!-- Please Include: -->
|
||||
- **Operating System**:
|
||||
- [ ] Windows
|
||||
- [ ] Linux/Ubuntu
|
||||
- [ ] macOS
|
||||
- **Clear steps to reproduce the issue**:
|
||||
- **Relevant error messages and/or screenshots**:
|
||||
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
<!-- Clear steps to reproduce the issue. -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- Operating System:
|
||||
<!-- (Platform and Version) e.g. macOS 10.13.6 / Windows 10 (1803) / Ubuntu 18.04 x64 -->
|
||||
- Zulip Desktop Version:
|
||||
<!-- e.g. 5.2.0 -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context about the problem here. -->
|
||||
6
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
name: Custom issue template
|
||||
about: Describe this issue template's purpose here.
|
||||
---
|
||||
|
||||
|
||||
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
---
|
||||
|
||||
**Problem Description**
|
||||
<!-- Please add a clear and concise description of what the problem is. -->
|
||||
|
||||
**Proposed Solution**
|
||||
<!-- Describe the solution you'd like in a clear and concise manner -->
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
3
.gitignore
vendored
@@ -4,6 +4,9 @@
|
||||
# npm cache directory
|
||||
.npm
|
||||
|
||||
# transifexrc - if user prefers it to be in working tree
|
||||
.transifexrc
|
||||
|
||||
# Compiled binary build directory
|
||||
dist/
|
||||
|
||||
|
||||
5
.mailmap
Normal file
@@ -0,0 +1,5 @@
|
||||
Anders Kaseorg <anders@zulip.com> <anders@zulipchat.com>
|
||||
Rishi Gupta <rishig@zulip.com> <rishig@zulipchat.com>
|
||||
Rishi Gupta <rishig@zulip.com> <rishig@users.noreply.github.com>
|
||||
Tim Abbott <tabbott@zulip.com> <tabbott@zulipchat.com>
|
||||
Tim Abbott <tabbott@zulip.com> <tabbott@mit.edu>
|
||||
9
.tx/config
Normal file
@@ -0,0 +1,9 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[zulip.desktopjson]
|
||||
file_filter = app/translations/<lang>.json
|
||||
minimum_perc = 0
|
||||
source_file = app/translations/en.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
Desktop client for Zulip. Available for Mac, Linux, and Windows.
|
||||
|
||||
<img src="http://i.imgur.com/ChzTq4F.png"/>
|
||||
<img src="https://i.imgur.com/s1o6TRA.png"/>
|
||||
<img src="https://i.imgur.com/vekKnW4.png"/>
|
||||
|
||||
# Download
|
||||
Please see the [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
|
||||
Please see the [installation guide](https://zulip.com/help/desktop-app-install-guide).
|
||||
|
||||
# Features
|
||||
* Sign in to multiple organizations
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
import {app, dialog} from 'electron';
|
||||
import {UpdateDownloadedEvent, UpdateInfo, autoUpdater} from 'electron-updater';
|
||||
import {linuxUpdateNotification} from './linuxupdater'; // Required only in case of linux
|
||||
import {app, dialog, session} from 'electron';
|
||||
import util from 'util';
|
||||
|
||||
import log from 'electron-log';
|
||||
import isDev from 'electron-is-dev';
|
||||
import log from 'electron-log';
|
||||
import {UpdateDownloadedEvent, UpdateInfo, autoUpdater} from 'electron-updater';
|
||||
|
||||
import * as ConfigUtil from '../renderer/js/utils/config-util';
|
||||
import * as LinkUtil from '../renderer/js/utils/link-util';
|
||||
|
||||
export function appUpdater(updateFromMenu = false): void {
|
||||
import {linuxUpdateNotification} from './linuxupdater'; // Required only in case of linux
|
||||
|
||||
const sleep = util.promisify(setTimeout);
|
||||
|
||||
export async function appUpdater(updateFromMenu = false): Promise<void> {
|
||||
// Don't initiate auto-updates in development
|
||||
if (isDev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.platform === 'linux' && !process.env.APPIMAGE) {
|
||||
linuxUpdateNotification();
|
||||
const ses = session.fromPartition('persist:webviewsession');
|
||||
await linuxUpdateNotification(ses);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,11 +80,11 @@ export function appUpdater(updateFromMenu = false): void {
|
||||
type: 'error',
|
||||
buttons: ['Manual Download', 'Cancel'],
|
||||
message: messageText,
|
||||
detail: `Error: ${error.message}\n\nThe latest version of Zulip Desktop is available at -\nhttps://zulipchat.com/apps/.\n
|
||||
detail: `Error: ${error.message}\n\nThe latest version of Zulip Desktop is available at -\nhttps://zulip.com/apps/.\n
|
||||
Current Version: ${app.getVersion()}`
|
||||
});
|
||||
if (response === 0) {
|
||||
await LinkUtil.openBrowser(new URL('https://zulipchat.com/apps/'));
|
||||
await LinkUtil.openBrowser(new URL('https://zulip.com/apps/'));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -94,13 +100,12 @@ export function appUpdater(updateFromMenu = false): void {
|
||||
detail: 'It will be installed the next time you restart the application'
|
||||
});
|
||||
if (response === 0) {
|
||||
setTimeout(() => {
|
||||
autoUpdater.quitAndInstall();
|
||||
// Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app.
|
||||
app.quit();
|
||||
}, 1000);
|
||||
await sleep(1000);
|
||||
autoUpdater.quitAndInstall();
|
||||
// Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app.
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
// Init for updates
|
||||
(async () => autoUpdater.checkForUpdates())();
|
||||
await autoUpdater.checkForUpdates();
|
||||
}
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import {sentryInit} from '../renderer/js/utils/sentry-util';
|
||||
import {appUpdater} from './autoupdater';
|
||||
import {setAutoLaunch} from './startup';
|
||||
|
||||
import electron, {app, dialog, ipcMain, session} from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import windowStateKeeper from 'electron-window-state';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import electron, {app, dialog, ipcMain, session} from 'electron';
|
||||
|
||||
import * as AppMenu from './menu';
|
||||
import * as BadgeSettings from '../renderer/js/pages/preference/badge-settings';
|
||||
import * as CertificateUtil from '../renderer/js/utils/certificate-util';
|
||||
import * as ConfigUtil from '../renderer/js/utils/config-util';
|
||||
import * as ProxyUtil from '../renderer/js/utils/proxy-util';
|
||||
import {sentryInit} from '../renderer/js/utils/sentry-util';
|
||||
|
||||
interface PatchedGlobal extends NodeJS.Global {
|
||||
mainWindowState: windowStateKeeper.State;
|
||||
}
|
||||
import {appUpdater} from './autoupdater';
|
||||
import * as AppMenu from './menu';
|
||||
import {_getServerSettings, _saveServerIcon, _isOnline} from './request';
|
||||
import {setAutoLaunch} from './startup';
|
||||
|
||||
const globalPatched = global as PatchedGlobal;
|
||||
let mainWindowState: windowStateKeeper.State;
|
||||
|
||||
// Prevent window being garbage collected
|
||||
let mainWindow: Electron.BrowserWindow;
|
||||
@@ -58,9 +57,7 @@ function makeRendererCallback(callback: (...args: any[]) => void): number {
|
||||
|
||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
||||
|
||||
const iconPath = (): string => {
|
||||
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
||||
};
|
||||
const iconPath = (): string => APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
||||
|
||||
// Toggle the app window
|
||||
const toggleApp = (): void => {
|
||||
@@ -79,9 +76,6 @@ function createMainWindow(): Electron.BrowserWindow {
|
||||
path: `${app.getPath('userData')}/config`
|
||||
});
|
||||
|
||||
// Let's keep the window position global so that we can access it in other process
|
||||
globalPatched.mainWindowState = mainWindowState;
|
||||
|
||||
const win = new electron.BrowserWindow({
|
||||
// This settings needs to be saved in config
|
||||
title: 'Zulip',
|
||||
@@ -90,7 +84,7 @@ function createMainWindow(): Electron.BrowserWindow {
|
||||
y: mainWindowState.y,
|
||||
width: mainWindowState.width,
|
||||
height: mainWindowState.height,
|
||||
minWidth: 300,
|
||||
minWidth: 500,
|
||||
minHeight: 400,
|
||||
webPreferences: {
|
||||
plugins: true,
|
||||
@@ -170,6 +164,9 @@ app.on('ready', () => {
|
||||
const ses = session.fromPartition('persist:webviewsession');
|
||||
ses.setUserAgent(`ZulipElectron/${app.getVersion()} ${ses.getUserAgent()}`);
|
||||
|
||||
ipcMain.on('set-spellcheck-langs', () => {
|
||||
ses.setSpellCheckerLanguages(ConfigUtil.getConfigItem('spellcheckerLanguages'));
|
||||
});
|
||||
AppMenu.setMenu({
|
||||
tabs: []
|
||||
});
|
||||
@@ -208,27 +205,36 @@ app.on('ready', () => {
|
||||
event.returnValue = session.fromPartition('persist:webviewsession').getUserAgent();
|
||||
});
|
||||
|
||||
page.once('did-frame-finish-load', () => {
|
||||
ipcMain.handle('get-server-settings', async (event, domain: string) => _getServerSettings(domain, ses));
|
||||
|
||||
ipcMain.handle('save-server-icon', async (event, url: string) => _saveServerIcon(url, ses));
|
||||
|
||||
ipcMain.handle('is-online', async (event, url: string) => _isOnline(url, ses));
|
||||
|
||||
page.once('did-frame-finish-load', async () => {
|
||||
// Initiate auto-updates on MacOS and Windows
|
||||
if (ConfigUtil.getConfigItem('autoUpdate')) {
|
||||
appUpdater();
|
||||
await appUpdater();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('certificate-error', (
|
||||
event: Event,
|
||||
webContents: Electron.WebContents,
|
||||
url: string,
|
||||
urlString: string,
|
||||
error: string,
|
||||
certificate: Electron.Certificate,
|
||||
callback: (isTrusted: boolean) => void
|
||||
) /* eslint-disable-line max-params */ => {
|
||||
// TODO: The entire concept of selectively ignoring certificate errors
|
||||
// is ill-conceived, and this handler needs to be deleted.
|
||||
event.preventDefault();
|
||||
|
||||
const {origin} = new URL(url);
|
||||
const filename = CertificateUtil.getCertificate(encodeURIComponent(origin));
|
||||
const url = new URL(urlString);
|
||||
if (url.protocol === 'wss:') {
|
||||
url.protocol = 'https:';
|
||||
}
|
||||
|
||||
const filename = CertificateUtil.getCertificate(encodeURIComponent(url.origin));
|
||||
if (filename !== undefined) {
|
||||
try {
|
||||
const savedCertificate = fs.readFileSync(
|
||||
@@ -237,6 +243,7 @@ app.on('ready', () => {
|
||||
);
|
||||
if (certificate.data.replace(/[\r\n]/g, '') ===
|
||||
savedCertificate.replace(/[\r\n]/g, '')) {
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
@@ -245,20 +252,11 @@ app.on('ready', () => {
|
||||
}
|
||||
}
|
||||
|
||||
page.send(
|
||||
'certificate-error',
|
||||
webContents.id === mainWindow.webContents.id ? null : webContents.id,
|
||||
makeRendererCallback(ignore => {
|
||||
callback(ignore);
|
||||
if (!ignore) {
|
||||
dialog.showErrorBox(
|
||||
'Certificate error',
|
||||
`The server presented an invalid certificate for ${origin}:
|
||||
dialog.showErrorBox(
|
||||
'Certificate error',
|
||||
`The server presented an invalid certificate for ${url.origin}:
|
||||
|
||||
${error}`
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -320,7 +318,7 @@ ${error}`
|
||||
});
|
||||
|
||||
ipcMain.on('clear-app-settings', () => {
|
||||
globalPatched.mainWindowState.unmanage();
|
||||
mainWindowState.unmanage();
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
});
|
||||
@@ -357,7 +355,7 @@ ${error}`
|
||||
AppMenu.setMenu(props);
|
||||
const activeTab = props.tabs[props.activeTabIndex];
|
||||
if (activeTab) {
|
||||
mainWindow.setTitle(`Zulip - ${activeTab.webview.props.name}`);
|
||||
mainWindow.setTitle(`Zulip - ${activeTab.webviewName}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -369,7 +367,7 @@ ${error}`
|
||||
page.downloadURL(url);
|
||||
page.session.once('will-download', async (_event: Event, item) => {
|
||||
if (ConfigUtil.getConfigItem('promptDownload', false)) {
|
||||
const showDialogOptions: object = {
|
||||
const showDialogOptions: electron.SaveDialogOptions = {
|
||||
defaultPath: path.join(downloadPath, item.getFilename())
|
||||
};
|
||||
item.setSaveDialogOptions(showDialogOptions);
|
||||
|
||||
@@ -1,52 +1,45 @@
|
||||
import {app, Notification} from 'electron';
|
||||
import {app, Notification, net} from 'electron';
|
||||
|
||||
import request from 'request';
|
||||
import getStream from 'get-stream';
|
||||
import semver from 'semver';
|
||||
|
||||
import * as ConfigUtil from '../renderer/js/utils/config-util';
|
||||
import * as ProxyUtil from '../renderer/js/utils/proxy-util';
|
||||
import * as LinuxUpdateUtil from '../renderer/js/utils/linux-update-util';
|
||||
import Logger from '../renderer/js/utils/logger-util';
|
||||
|
||||
import {fetchResponse} from './request';
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'linux-update-util.log',
|
||||
timestamp: true
|
||||
});
|
||||
|
||||
export function linuxUpdateNotification(): void {
|
||||
export async function linuxUpdateNotification(session: Electron.session): Promise<void> {
|
||||
let url = 'https://api.github.com/repos/zulip/zulip-desktop/releases';
|
||||
url = ConfigUtil.getConfigItem('betaUpdate') ? url : url + '/latest';
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
|
||||
const options = {
|
||||
url,
|
||||
headers: {'User-Agent': 'request'},
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(url) : '',
|
||||
ecdhCurve: 'auto'
|
||||
};
|
||||
|
||||
request(options, (error, response: request.Response, body: string) => {
|
||||
if (error) {
|
||||
logger.error('Linux update error.');
|
||||
logger.error(error);
|
||||
try {
|
||||
const response = await fetchResponse(net.request({url, session}));
|
||||
if (response.statusCode !== 200) {
|
||||
logger.log('Linux update response status: ', response.statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode < 400) {
|
||||
const data = JSON.parse(body);
|
||||
const latestVersion = ConfigUtil.getConfigItem('betaUpdate') ? data[0].tag_name : data.tag_name;
|
||||
if (typeof latestVersion !== 'string') {
|
||||
throw new TypeError('Expected string for tag_name');
|
||||
}
|
||||
|
||||
if (semver.gt(latestVersion, app.getVersion())) {
|
||||
const notified = LinuxUpdateUtil.getUpdateItem(latestVersion);
|
||||
if (notified === null) {
|
||||
new Notification({title: 'Zulip Update', body: `A new version ${latestVersion} is available. Please update using your package manager.`}).show();
|
||||
LinuxUpdateUtil.setUpdateItem(latestVersion, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.log('Linux update response status: ', response.statusCode);
|
||||
const data = JSON.parse(await getStream(response));
|
||||
const latestVersion = ConfigUtil.getConfigItem('betaUpdate') ? data[0].tag_name : data.tag_name;
|
||||
if (typeof latestVersion !== 'string') {
|
||||
throw new TypeError('Expected string for tag_name');
|
||||
}
|
||||
});
|
||||
|
||||
if (semver.gt(latestVersion, app.getVersion())) {
|
||||
const notified = LinuxUpdateUtil.getUpdateItem(latestVersion);
|
||||
if (notified === null) {
|
||||
new Notification({title: 'Zulip Update', body: `A new version ${latestVersion} is available. Please update using your package manager.`}).show();
|
||||
LinuxUpdateUtil.setUpdateItem(latestVersion, true);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Linux update error.');
|
||||
logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
import {app, shell, BrowserWindow, Menu, dialog} from 'electron';
|
||||
import {appUpdater} from './autoupdater';
|
||||
import {app, shell, BrowserWindow, Menu} from 'electron';
|
||||
|
||||
import AdmZip from 'adm-zip';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import * as DNDUtil from '../renderer/js/utils/dnd-util';
|
||||
import Logger from '../renderer/js/utils/logger-util';
|
||||
|
||||
import type {TabData} from '../renderer/js/main';
|
||||
import * as ConfigUtil from '../renderer/js/utils/config-util';
|
||||
import * as DNDUtil from '../renderer/js/utils/dnd-util';
|
||||
import * as LinkUtil from '../renderer/js/utils/link-util';
|
||||
import * as t from '../renderer/js/utils/translation-util';
|
||||
import type {ServerOrFunctionalTab} from '../renderer/js/main';
|
||||
|
||||
import {appUpdater} from './autoupdater';
|
||||
|
||||
export interface MenuProps {
|
||||
tabs: ServerOrFunctionalTab[];
|
||||
tabs: TabData[];
|
||||
activeTabIndex?: number;
|
||||
enableMenu?: boolean;
|
||||
}
|
||||
|
||||
const appName = app.name;
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'errors.log',
|
||||
timestamp: true
|
||||
});
|
||||
|
||||
function getHistorySubmenu(enableMenu: boolean): Electron.MenuItemConstructorOptions[] {
|
||||
return [{
|
||||
label: t.__('Back'),
|
||||
@@ -49,8 +43,8 @@ function getHistorySubmenu(enableMenu: boolean): Electron.MenuItemConstructorOpt
|
||||
function getToolsSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
return [{
|
||||
label: t.__('Check for Updates'),
|
||||
click() {
|
||||
checkForUpdate();
|
||||
async click() {
|
||||
await checkForUpdate();
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -62,13 +56,6 @@ function getToolsSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: t.__('Factory Reset'),
|
||||
accelerator: process.platform === 'darwin' ? 'Command+Shift+D' : 'Ctrl+Shift+D',
|
||||
async click() {
|
||||
await resetAppSettings();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t.__('Download App Logs'),
|
||||
click() {
|
||||
@@ -135,7 +122,7 @@ function getViewSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
role: 'togglefullscreen'
|
||||
}, {
|
||||
label: t.__('Zoom In'),
|
||||
role: 'zoomIn',
|
||||
accelerator: 'CommandOrControl+=',
|
||||
click(_item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('zoomIn');
|
||||
@@ -143,7 +130,6 @@ function getViewSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
}
|
||||
}, {
|
||||
label: t.__('Zoom Out'),
|
||||
role: 'zoomOut',
|
||||
accelerator: 'CommandOrControl+-',
|
||||
click(_item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
@@ -152,7 +138,6 @@ function getViewSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
}
|
||||
}, {
|
||||
label: t.__('Actual Size'),
|
||||
role: 'resetZoom',
|
||||
accelerator: 'CommandOrControl+0',
|
||||
click(_item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
@@ -230,7 +215,7 @@ function getHelpSubmenu(): Electron.MenuItemConstructorOptions[] {
|
||||
];
|
||||
}
|
||||
|
||||
function getWindowSubmenu(tabs: ServerOrFunctionalTab[], activeTabIndex: number): Electron.MenuItemConstructorOptions[] {
|
||||
function getWindowSubmenu(tabs: TabData[], activeTabIndex: number): Electron.MenuItemConstructorOptions[] {
|
||||
const initialSubmenu: Electron.MenuItemConstructorOptions[] = [{
|
||||
label: t.__('Minimize'),
|
||||
role: 'minimize'
|
||||
@@ -246,17 +231,17 @@ function getWindowSubmenu(tabs: ServerOrFunctionalTab[], activeTabIndex: number)
|
||||
});
|
||||
tabs.forEach(tab => {
|
||||
// Do not add functional tab settings to list of windows in menu bar
|
||||
if (tab.props.role === 'function' && tab.props.name === 'Settings') {
|
||||
if (tab.role === 'function' && tab.name === 'Settings') {
|
||||
return;
|
||||
}
|
||||
|
||||
initialSubmenu.push({
|
||||
label: tab.props.name,
|
||||
accelerator: tab.props.role === 'function' ? '' : `${ShortcutKey} + ${tab.props.index + 1}`,
|
||||
checked: tab.props.index === activeTabIndex,
|
||||
label: tab.name,
|
||||
accelerator: tab.role === 'function' ? '' : `${ShortcutKey} + ${tab.index + 1}`,
|
||||
checked: tab.index === activeTabIndex,
|
||||
click(_item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('switch-server-tab', tab.props.index);
|
||||
sendAction('switch-server-tab', tab.index);
|
||||
}
|
||||
},
|
||||
type: 'checkbox'
|
||||
@@ -558,58 +543,28 @@ function sendAction(action: string, ...parameters: unknown[]): void {
|
||||
win.webContents.send(action, ...parameters);
|
||||
}
|
||||
|
||||
function checkForUpdate(): void {
|
||||
appUpdater(true);
|
||||
async function checkForUpdate(): Promise<void> {
|
||||
await appUpdater(true);
|
||||
}
|
||||
|
||||
function getNextServer(tabs: ServerOrFunctionalTab[], activeTabIndex: number): number {
|
||||
function getNextServer(tabs: TabData[], activeTabIndex: number): number {
|
||||
do {
|
||||
activeTabIndex = (activeTabIndex + 1) % tabs.length;
|
||||
}
|
||||
while (tabs[activeTabIndex].props.role !== 'server');
|
||||
while (tabs[activeTabIndex].role !== 'server');
|
||||
|
||||
return activeTabIndex;
|
||||
}
|
||||
|
||||
function getPreviousServer(tabs: ServerOrFunctionalTab[], activeTabIndex: number): number {
|
||||
function getPreviousServer(tabs: TabData[], activeTabIndex: number): number {
|
||||
do {
|
||||
activeTabIndex = (activeTabIndex - 1 + tabs.length) % tabs.length;
|
||||
}
|
||||
while (tabs[activeTabIndex].props.role !== 'server');
|
||||
while (tabs[activeTabIndex].role !== 'server');
|
||||
|
||||
return activeTabIndex;
|
||||
}
|
||||
|
||||
async function resetAppSettings(): Promise<void> {
|
||||
const resetAppSettingsMessage = 'By proceeding you will be removing all connected organizations and preferences from Zulip.';
|
||||
|
||||
// We save App's settings/configurations in following files
|
||||
const settingFiles = ['config/window-state.json', 'config/domain.json', 'config/settings.json', 'config/certificates.json'];
|
||||
|
||||
const {response} = await dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['YES', 'NO'],
|
||||
defaultId: 0,
|
||||
message: 'Are you sure?',
|
||||
detail: resetAppSettingsMessage
|
||||
});
|
||||
if (response === 0) {
|
||||
settingFiles.forEach(settingFileName => {
|
||||
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
||||
fs.access(getSettingFilesPath, (error: NodeJS.ErrnoException) => {
|
||||
if (error) {
|
||||
logger.error('Error while resetting app settings.');
|
||||
logger.error(error);
|
||||
} else {
|
||||
fs.unlink(getSettingFilesPath, () => {
|
||||
sendAction('clear-app-data');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function setMenu(props: MenuProps): void {
|
||||
const tpl = process.platform === 'darwin' ? getDarwinTpl(props) : getOtherTpl(props);
|
||||
const menu = Menu.buildFromTemplate(tpl);
|
||||
|
||||
112
app/main/request.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import {ClientRequest, IncomingMessage, app, net} from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import stream from 'stream';
|
||||
import util from 'util';
|
||||
|
||||
import getStream from 'get-stream';
|
||||
|
||||
import {ServerConf} from '../renderer/js/utils/domain-util';
|
||||
import Logger from '../renderer/js/utils/logger-util';
|
||||
import * as Messages from '../resources/messages';
|
||||
|
||||
export async function fetchResponse(request: ClientRequest): Promise<IncomingMessage> {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.on('response', resolve);
|
||||
request.on('abort', () => reject(new Error('Request aborted')));
|
||||
request.on('error', reject);
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
const pipeline = util.promisify(stream.pipeline);
|
||||
|
||||
/* Request: domain-util */
|
||||
|
||||
const defaultIconUrl = '../renderer/img/icon.png';
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'domain-util.log',
|
||||
timestamp: true
|
||||
});
|
||||
|
||||
const generateFilePath = (url: string): string => {
|
||||
const dir = `${app.getPath('userData')}/server-icons`;
|
||||
const extension = path.extname(url).split('?')[0];
|
||||
|
||||
let hash = 5381;
|
||||
let {length} = url;
|
||||
|
||||
while (length) {
|
||||
hash = (hash * 33) ^ url.charCodeAt(--length);
|
||||
}
|
||||
|
||||
// Create 'server-icons' directory if not existed
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
return `${dir}/${hash >>> 0}${extension}`;
|
||||
};
|
||||
|
||||
export const _getServerSettings = async (domain: string, session: Electron.session): Promise<ServerConf> => {
|
||||
const response = await fetchResponse(net.request({
|
||||
url: domain + '/api/v1/server_settings',
|
||||
session
|
||||
}));
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error(Messages.invalidZulipServerError(domain));
|
||||
}
|
||||
|
||||
const {realm_name, realm_uri, realm_icon} = JSON.parse(await getStream(response));
|
||||
if (
|
||||
typeof realm_name !== 'string' ||
|
||||
typeof realm_uri !== 'string' ||
|
||||
typeof realm_icon !== 'string'
|
||||
) {
|
||||
throw new TypeError(Messages.noOrgsError(domain));
|
||||
}
|
||||
|
||||
return {
|
||||
// Some Zulip Servers use absolute URL for server icon whereas others use relative URL
|
||||
// Following check handles both the cases
|
||||
icon: realm_icon.startsWith('/') ? realm_uri + realm_icon : realm_icon,
|
||||
url: realm_uri,
|
||||
alias: realm_name
|
||||
};
|
||||
};
|
||||
|
||||
export const _saveServerIcon = async (url: string, session: Electron.session): Promise<string> => {
|
||||
try {
|
||||
const response = await fetchResponse(net.request({url, session}));
|
||||
if (response.statusCode !== 200) {
|
||||
logger.log('Could not get server icon.');
|
||||
return defaultIconUrl;
|
||||
}
|
||||
|
||||
const filePath = generateFilePath(url);
|
||||
await pipeline(response, fs.createWriteStream(filePath));
|
||||
return filePath;
|
||||
} catch (error) {
|
||||
logger.log('Could not get server icon.');
|
||||
logger.log(error);
|
||||
logger.reportSentry(error);
|
||||
return defaultIconUrl;
|
||||
}
|
||||
};
|
||||
|
||||
/* Request: reconnect-util */
|
||||
|
||||
export const _isOnline = async (url: string, session: Electron.session): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetchResponse(net.request({
|
||||
url: `${url}/static/favicon.ico`,
|
||||
session
|
||||
}));
|
||||
const isValidResponse = response.statusCode >= 200 && response.statusCode < 400;
|
||||
return isValidResponse;
|
||||
} catch (error) {
|
||||
logger.log(error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -2,6 +2,7 @@ import {app} from 'electron';
|
||||
|
||||
import AutoLaunch from 'auto-launch';
|
||||
import isDev from 'electron-is-dev';
|
||||
|
||||
import * as ConfigUtil from '../renderer/js/utils/config-util';
|
||||
|
||||
export const setAutoLaunch = async (AutoLaunchValue: boolean): Promise<void> => {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="maintenance-info">
|
||||
<p class="detail maintainer">
|
||||
Maintained by
|
||||
<a href="https://zulipchat.com" target="_blank" rel="noopener noreferrer">Zulip</a>
|
||||
<a href="https://zulip.com" target="_blank" rel="noopener noreferrer">Zulip</a>
|
||||
</p>
|
||||
<p class="detail license">
|
||||
Available under the
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
const { app } = require('electron').remote;
|
||||
const version_tag = document.querySelector('#version');
|
||||
version_tag.innerHTML = 'v' + app.getVersion();
|
||||
version_tag.textContent = 'v' + app.getVersion();
|
||||
</script>
|
||||
<script>require('./js/shared/preventdrag.js')</script>
|
||||
</body>
|
||||
|
||||
19
app/renderer/css/feedback.css
Normal file
@@ -0,0 +1,19 @@
|
||||
:host {
|
||||
--button-color: rgb(69, 166, 149);
|
||||
}
|
||||
|
||||
button:hover,
|
||||
button:focus {
|
||||
border-color: var(--button-color);
|
||||
color: var(--button-color);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: rgb(241, 241, 241);
|
||||
color: var(--button-color);
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: var(--button-color);
|
||||
border-color: var(--button-color);
|
||||
}
|
||||
@@ -389,6 +389,10 @@ img.server-info-icon {
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
#note {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
}
|
||||
@@ -663,6 +667,26 @@ i.open-network-button {
|
||||
}
|
||||
|
||||
/* responsive grid */
|
||||
@media (min-width: 500px) and (max-width: 720px) {
|
||||
#new-server-container {
|
||||
padding-left: 0px;
|
||||
width: 60vw;
|
||||
padding-right: 4vh;
|
||||
}
|
||||
.page-title {
|
||||
width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
#new-server-container {
|
||||
padding-left: 0px;
|
||||
width: 54%;
|
||||
}
|
||||
.page-title {
|
||||
width: 54%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 650px) {
|
||||
.selected-css-path,
|
||||
@@ -695,9 +719,6 @@ i.open-network-button {
|
||||
margin-right: 6px;
|
||||
width: 43%;
|
||||
}
|
||||
#new-server-container {
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 14 KiB |
@@ -1,5 +1,5 @@
|
||||
import {clipboard} from 'electron';
|
||||
import crypto from 'crypto';
|
||||
import {clipboard} from 'electron';
|
||||
|
||||
// This helper is exposed via electron_bridge for use in the social
|
||||
// login flow.
|
||||
@@ -59,7 +59,7 @@ export class ClipboardDecrypterImpl implements ClipboardDecrypter {
|
||||
plaintext =
|
||||
decipher.update(ciphertext, undefined, 'utf8') +
|
||||
decipher.final('utf8');
|
||||
} catch (_) {
|
||||
} catch {
|
||||
// If the parsing or decryption failed in any way,
|
||||
// the correct token hasn’t been copied yet; try
|
||||
// again next time.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export default class BaseComponent {
|
||||
generateNodeFromTemplate(template: string): Element | null {
|
||||
generateNodeFromHTML(html: string): Element | null {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = template;
|
||||
wrapper.innerHTML = html;
|
||||
return wrapper.firstElementChild;
|
||||
}
|
||||
}
|
||||
|
||||
115
app/renderer/js/components/context-menu.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import {remote, ContextMenuParams} from 'electron';
|
||||
|
||||
import * as t from '../utils/translation-util';
|
||||
|
||||
const {clipboard, Menu} = remote;
|
||||
|
||||
export const contextMenu = (webContents: Electron.WebContents, event: Event, props: ContextMenuParams) => {
|
||||
const isText = props.selectionText !== '';
|
||||
const isLink = props.linkURL !== '';
|
||||
const linkURL = isLink ? new URL(props.linkURL) : undefined;
|
||||
const isEmailAddress = isLink ? linkURL.protocol === 'mailto:' : undefined;
|
||||
|
||||
const makeSuggestion = (suggestion: string) => ({
|
||||
label: suggestion,
|
||||
visible: true,
|
||||
async click() {
|
||||
await webContents.insertText(suggestion);
|
||||
}
|
||||
});
|
||||
|
||||
let menuTemplate: Electron.MenuItemConstructorOptions[] = [{
|
||||
label: t.__('Add to Dictionary'),
|
||||
visible: props.isEditable && isText && props.misspelledWord.length !== 0,
|
||||
click(_item) {
|
||||
webContents.session.addWordToSpellCheckerDictionary(props.misspelledWord);
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
visible: props.isEditable && isText && props.misspelledWord.length !== 0
|
||||
}, {
|
||||
label: `${t.__('Look Up')} "${props.selectionText}"`,
|
||||
visible: process.platform === 'darwin' && isText,
|
||||
click(_item) {
|
||||
webContents.showDefinitionForSelection();
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
visible: process.platform === 'darwin' && isText
|
||||
}, {
|
||||
label: t.__('Cut'),
|
||||
visible: isText,
|
||||
enabled: props.isEditable,
|
||||
accelerator: 'CommandOrControl+X',
|
||||
click(_item) {
|
||||
webContents.cut();
|
||||
}
|
||||
}, {
|
||||
label: t.__('Copy'),
|
||||
accelerator: 'CommandOrControl+C',
|
||||
enabled: props.editFlags.canCopy,
|
||||
click(_item) {
|
||||
webContents.copy();
|
||||
}
|
||||
}, {
|
||||
label: t.__('Paste'), // Bug: Paste replaces text
|
||||
accelerator: 'CommandOrControl+V',
|
||||
enabled: props.isEditable,
|
||||
click() {
|
||||
webContents.paste();
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: isEmailAddress ? t.__('Copy Email Address') : t.__('Copy Link'),
|
||||
visible: isLink,
|
||||
click(_item) {
|
||||
clipboard.write({
|
||||
bookmark: props.linkText,
|
||||
text: isEmailAddress ? linkURL.pathname : props.linkURL
|
||||
});
|
||||
}
|
||||
}, {
|
||||
label: t.__('Copy Image'),
|
||||
visible: props.mediaType === 'image',
|
||||
click(_item) {
|
||||
webContents.copyImageAt(props.x, props.y);
|
||||
}
|
||||
}, {
|
||||
label: t.__('Copy Image URL'),
|
||||
visible: props.mediaType === 'image',
|
||||
click(_item) {
|
||||
clipboard.write({
|
||||
bookmark: props.srcURL,
|
||||
text: props.srcURL
|
||||
});
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
visible: isLink || props.mediaType === 'image'
|
||||
}, {
|
||||
label: t.__('Services'),
|
||||
visible: process.platform === 'darwin',
|
||||
role: 'services'
|
||||
}];
|
||||
|
||||
if (props.misspelledWord) {
|
||||
if (props.dictionarySuggestions.length > 0) {
|
||||
const suggestions: Electron.MenuItemConstructorOptions[] = props.dictionarySuggestions.map((suggestion: string) => makeSuggestion(suggestion));
|
||||
menuTemplate = suggestions.concat(menuTemplate);
|
||||
} else {
|
||||
menuTemplate.unshift({
|
||||
label: t.__('No Suggestion Found'),
|
||||
enabled: false
|
||||
});
|
||||
}
|
||||
}
|
||||
// Hide the invisible separators on Linux and Windows
|
||||
// Electron has a bug which ignores visible: false parameter for separator menuitems. So we remove them here.
|
||||
// https://github.com/electron/electron/issues/5869
|
||||
// https://github.com/electron/electron/issues/6906
|
||||
|
||||
const filteredMenuTemplate = menuTemplate.filter(menuItem => menuItem.visible ?? true);
|
||||
const menu = Menu.buildFromTemplate(filteredMenuTemplate);
|
||||
menu.popup();
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import Tab, {TabProps} from './tab';
|
||||
|
||||
export default class FunctionalTab extends Tab {
|
||||
@@ -8,19 +10,21 @@ export default class FunctionalTab extends Tab {
|
||||
this.init();
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `<div class="tab functional-tab" data-tab-id="${this.props.tabIndex}">
|
||||
<div class="server-tab-badge close-button">
|
||||
<i class="material-icons">close</i>
|
||||
</div>
|
||||
<div class="server-tab">
|
||||
<i class="material-icons">${this.props.materialIcon}</i>
|
||||
</div>
|
||||
</div>`;
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="tab functional-tab" data-tab-id="${this.props.tabIndex}">
|
||||
<div class="server-tab-badge close-button">
|
||||
<i class="material-icons">close</i>
|
||||
</div>
|
||||
<div class="server-tab">
|
||||
<i class="material-icons">${this.props.materialIcon}</i>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.$el = this.generateNodeFromHTML(this.templateHTML());
|
||||
if (this.props.name !== 'Settings') {
|
||||
this.props.$root.append(this.$el);
|
||||
this.$closeButton = this.$el.querySelectorAll('.server-tab-badge')[0];
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {ipcRenderer, remote} from 'electron';
|
||||
|
||||
import * as LinkUtil from '../utils/link-util';
|
||||
import * as ConfigUtil from '../utils/config-util';
|
||||
import * as LinkUtil from '../utils/link-util';
|
||||
|
||||
import type WebView from './webview';
|
||||
|
||||
const {shell, app} = remote;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import Tab, {TabProps} from './tab';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as SystemUtil from '../utils/system-util';
|
||||
|
||||
import Tab, {TabProps} from './tab';
|
||||
|
||||
export default class ServerTab extends Tab {
|
||||
$badge: Element;
|
||||
|
||||
@@ -11,19 +14,21 @@ export default class ServerTab extends Tab {
|
||||
this.init();
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `<div class="tab" data-tab-id="${this.props.tabIndex}">
|
||||
<div class="server-tooltip" style="display:none">${this.props.name}</div>
|
||||
<div class="server-tab-badge"></div>
|
||||
<div class="server-tab">
|
||||
<img class="server-icons" src='${this.props.icon}'/>
|
||||
</div>
|
||||
<div class="server-tab-shortcut">${this.generateShortcutText()}</div>
|
||||
</div>`;
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="tab" data-tab-id="${this.props.tabIndex}">
|
||||
<div class="server-tooltip" style="display:none">${this.props.name}</div>
|
||||
<div class="server-tab-badge"></div>
|
||||
<div class="server-tab">
|
||||
<img class="server-icons" src="${this.props.icon}"/>
|
||||
</div>
|
||||
<div class="server-tab-shortcut">${this.generateShortcutText()}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.$el = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.props.$root.append(this.$el);
|
||||
this.registerListeners();
|
||||
this.$badge = this.$el.querySelectorAll('.server-tab-badge')[0];
|
||||
@@ -32,7 +37,7 @@ export default class ServerTab extends Tab {
|
||||
updateBadge(count: number): void {
|
||||
if (count > 0) {
|
||||
const formattedCount = count > 999 ? '1K+' : count.toString();
|
||||
this.$badge.innerHTML = formattedCount;
|
||||
this.$badge.textContent = formattedCount;
|
||||
this.$badge.classList.add('active');
|
||||
} else {
|
||||
this.$badge.classList.remove('active');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import WebView from './webview';
|
||||
import BaseComponent from './base';
|
||||
import WebView from './webview';
|
||||
|
||||
export interface TabProps {
|
||||
role: string;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import {ipcRenderer, remote} from 'electron';
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as ConfigUtil from '../utils/config-util';
|
||||
import * as SystemUtil from '../utils/system-util';
|
||||
|
||||
import BaseComponent from './base';
|
||||
import {contextMenu} from './context-menu';
|
||||
import handleExternalLink from './handle-external-link';
|
||||
|
||||
const {app, dialog} = remote;
|
||||
@@ -24,7 +28,6 @@ interface WebViewProps {
|
||||
nodeIntegration: boolean;
|
||||
preload: boolean;
|
||||
onTitleChange: () => void;
|
||||
ignoreCerts?: boolean;
|
||||
hasPermission?: (origin: string, permission: string) => boolean;
|
||||
}
|
||||
|
||||
@@ -49,21 +52,27 @@ export default class WebView extends BaseComponent {
|
||||
this.$webviewsContainer = document.querySelector('#webviews-container').classList;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `<webview
|
||||
class="disabled"
|
||||
data-tab-id="${this.props.tabIndex}"
|
||||
src="${this.props.url}"
|
||||
${this.props.nodeIntegration ? 'nodeIntegration' : ''}
|
||||
${this.props.preload ? 'preload="js/preload.js"' : ''}
|
||||
partition="persist:webviewsession"
|
||||
name="${this.props.name}"
|
||||
webpreferences="${this.props.nodeIntegration ? '' : 'contextIsolation, '}javascript=yes">
|
||||
</webview>`;
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<webview
|
||||
class="disabled"
|
||||
data-tab-id="${this.props.tabIndex}"
|
||||
src="${this.props.url}"
|
||||
` + (this.props.nodeIntegration ? 'nodeIntegration' : '') + htmlEscape`
|
||||
` + (this.props.preload ? 'preload="js/preload.js"' : '') + htmlEscape`
|
||||
partition="persist:webviewsession"
|
||||
name="${this.props.name}"
|
||||
webpreferences="
|
||||
${this.props.nodeIntegration ? '' : 'contextIsolation,'}
|
||||
${ConfigUtil.getConfigItem('enableSpellchecker') ? 'spellcheck,' : ''}
|
||||
javascript
|
||||
">
|
||||
</webview>
|
||||
`;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$el = this.generateNodeFromTemplate(this.template()) as Electron.WebviewTag;
|
||||
this.$el = this.generateNodeFromHTML(this.templateHTML()) as Electron.WebviewTag;
|
||||
this.domReady = new Promise(resolve => {
|
||||
this.$el.addEventListener('dom-ready', () => resolve(), true);
|
||||
});
|
||||
@@ -118,6 +127,11 @@ export default class WebView extends BaseComponent {
|
||||
});
|
||||
|
||||
this.$el.addEventListener('dom-ready', () => {
|
||||
const webContents = remote.webContents.fromId(this.$el.getWebContentsId());
|
||||
webContents.addListener('context-menu', (event, menuParameters) => {
|
||||
contextMenu(webContents, event, menuParameters);
|
||||
});
|
||||
|
||||
if (this.props.role === 'server') {
|
||||
this.$el.classList.add('onload');
|
||||
}
|
||||
@@ -207,7 +221,7 @@ export default class WebView extends BaseComponent {
|
||||
|
||||
focus(): void {
|
||||
// Focus Webview and it's contents when Window regain focus.
|
||||
const webContents = this.$el.getWebContents();
|
||||
const webContents = remote.webContents.fromId(this.$el.getWebContentsId());
|
||||
// HACK: webContents.isFocused() seems to be true even without the element
|
||||
// being in focus. So, we check against `document.activeElement`.
|
||||
if (webContents && this.$el !== document.activeElement) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import {EventEmitter} from 'events';
|
||||
|
||||
import {ClipboardDecrypterImpl} from './clipboard-decrypter';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {remote} from 'electron';
|
||||
import SendFeedback from '@electron-elements/send-feedback';
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import SendFeedback from '@electron-elements/send-feedback';
|
||||
|
||||
const {app} = remote;
|
||||
|
||||
@@ -11,48 +11,20 @@ export const sendFeedback: SendFeedback = document.querySelector('send-feedback'
|
||||
export const feedbackHolder = sendFeedback.parentElement;
|
||||
|
||||
// Make the button color match zulip app's theme
|
||||
sendFeedback.customStyles = `
|
||||
button:hover, button:focus {
|
||||
border-color: #4EBFAC;
|
||||
color: #4EBFAC;
|
||||
}
|
||||
sendFeedback.customStylesheet = 'css/feedback.css';
|
||||
|
||||
button:active {
|
||||
background-color: #f1f1f1;
|
||||
color: #4EBFAC;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #4EBFAC;
|
||||
border-color: #4EBFAC;
|
||||
}
|
||||
`;
|
||||
|
||||
/* eslint-disable no-multi-str */
|
||||
|
||||
// customize the fields of custom elements
|
||||
// Customize the fields of custom elements
|
||||
sendFeedback.title = 'Report Issue';
|
||||
sendFeedback.titleLabel = 'Issue title:';
|
||||
sendFeedback.titlePlaceholder = 'Enter issue title';
|
||||
sendFeedback.textareaLabel = 'Describe the issue:';
|
||||
sendFeedback.textareaPlaceholder = 'Succinctly describe your issue and steps to reproduce it...\n\n\
|
||||
---\n\
|
||||
<!-- Please Include: -->\n\
|
||||
- **Operating System**:\n\
|
||||
- [ ] Windows\n\
|
||||
- [ ] Linux/Ubuntu\n\
|
||||
- [ ] macOS\n\
|
||||
- **Clear steps to reproduce the issue**:\n\
|
||||
- **Relevant error messages and/or screenshots**:\n\
|
||||
';
|
||||
|
||||
/* eslint-enable no-multi-str */
|
||||
sendFeedback.textareaPlaceholder = 'Succinctly describe your issue and steps to reproduce it...';
|
||||
|
||||
sendFeedback.buttonLabel = 'Report Issue';
|
||||
sendFeedback.loaderSuccessText = '';
|
||||
|
||||
sendFeedback.useReporter('emailReporter', {
|
||||
email: 'akash@zulipchat.com'
|
||||
email: 'support@zulip.com'
|
||||
});
|
||||
|
||||
feedbackHolder.addEventListener('click', (event: Event) => {
|
||||
@@ -69,6 +41,10 @@ sendFeedback.addEventListener('feedback-submitted', () => {
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
sendFeedback.addEventListener('feedback-cancelled', () => {
|
||||
feedbackHolder.classList.remove('show');
|
||||
});
|
||||
|
||||
const dataDir = app.getPath('userData');
|
||||
const logsDir = path.join(dataDir, '/Logs');
|
||||
sendFeedback.logs.push(...fs.readdirSync(logsDir).map(file => path.join(logsDir, file)));
|
||||
|
||||
@@ -52,9 +52,7 @@ interface CompatElectronBridge extends ElectronBridge {
|
||||
|
||||
const {page_params} = zulipWindow;
|
||||
if (page_params) {
|
||||
electron_bridge.send_event('zulip-loaded', {
|
||||
serverLanguage: page_params.default_language
|
||||
});
|
||||
electron_bridge.send_event('zulip-loaded');
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import {ipcRenderer, remote, clipboard} from 'electron';
|
||||
import {feedbackHolder} from './feedback';
|
||||
|
||||
import path from 'path';
|
||||
import escape from 'escape-html';
|
||||
|
||||
import isDev from 'electron-is-dev';
|
||||
const {session, app, Menu, dialog} = remote;
|
||||
|
||||
import * as Messages from '../../resources/messages';
|
||||
|
||||
import FunctionalTab from './components/functional-tab';
|
||||
import ServerTab from './components/server-tab';
|
||||
import WebView from './components/webview';
|
||||
import {feedbackHolder} from './feedback';
|
||||
import * as ConfigUtil from './utils/config-util';
|
||||
import * as DNDUtil from './utils/dnd-util';
|
||||
import type {DNDSettings} from './utils/dnd-util';
|
||||
import * as DomainUtil from './utils/domain-util';
|
||||
import * as EnterpriseUtil from './utils/enterprise-util';
|
||||
import * as LinkUtil from './utils/link-util';
|
||||
import Logger from './utils/logger-util';
|
||||
import ReconnectUtil from './utils/reconnect-util';
|
||||
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
import './tray';
|
||||
|
||||
import * as DomainUtil from './utils/domain-util';
|
||||
import WebView from './components/webview';
|
||||
import ServerTab from './components/server-tab';
|
||||
import FunctionalTab from './components/functional-tab';
|
||||
import * as ConfigUtil from './utils/config-util';
|
||||
import * as DNDUtil from './utils/dnd-util';
|
||||
import ReconnectUtil from './utils/reconnect-util';
|
||||
import Logger from './utils/logger-util';
|
||||
import * as CommonUtil from './utils/common-util';
|
||||
import * as EnterpriseUtil from './utils/enterprise-util';
|
||||
import * as LinkUtil from './utils/link-util';
|
||||
import * as Messages from '../../resources/messages';
|
||||
import type {DNDSettings} from './utils/dnd-util';
|
||||
const {session, app, Menu, dialog} = remote;
|
||||
|
||||
interface FunctionalTabProps {
|
||||
name: string;
|
||||
@@ -50,6 +50,7 @@ interface SettingsOptions extends DNDSettings {
|
||||
quitOnClose: boolean;
|
||||
promptDownload: boolean;
|
||||
dockBouncing?: boolean;
|
||||
spellcheckerLanguages?: string[];
|
||||
}
|
||||
|
||||
const logger = new Logger({
|
||||
@@ -58,7 +59,14 @@ const logger = new Logger({
|
||||
});
|
||||
|
||||
const rendererDirectory = path.resolve(__dirname, '..');
|
||||
export type ServerOrFunctionalTab = ServerTab | FunctionalTab;
|
||||
type ServerOrFunctionalTab = ServerTab | FunctionalTab;
|
||||
|
||||
export interface TabData {
|
||||
role: string;
|
||||
name: string;
|
||||
index: number;
|
||||
webviewName: string;
|
||||
}
|
||||
|
||||
class ServerManagerView {
|
||||
$addServerButton: HTMLButtonElement;
|
||||
@@ -115,7 +123,7 @@ class ServerManagerView {
|
||||
|
||||
this.$fullscreenPopup = document.querySelector('#fullscreen-popup');
|
||||
this.$fullscreenEscapeKey = process.platform === 'darwin' ? '^⌘F' : 'F11';
|
||||
this.$fullscreenPopup.innerHTML = `Press ${this.$fullscreenEscapeKey} to exit full screen`;
|
||||
this.$fullscreenPopup.textContent = `Press ${this.$fullscreenEscapeKey} to exit full screen`;
|
||||
|
||||
this.loading = new Set();
|
||||
this.activeTabIndex = -1;
|
||||
@@ -137,6 +145,7 @@ class ServerManagerView {
|
||||
await this.initTabs();
|
||||
this.initActions();
|
||||
this.registerIpcs();
|
||||
ipcRenderer.send('set-spellcheck-langs');
|
||||
}
|
||||
|
||||
async loadProxy(): Promise<void> {
|
||||
@@ -179,7 +188,7 @@ class ServerManagerView {
|
||||
useSystemProxy: false,
|
||||
showSidebar: true,
|
||||
badgeOption: true,
|
||||
startAtLogin: true,
|
||||
startAtLogin: false,
|
||||
startMinimized: false,
|
||||
enableSpellchecker: true,
|
||||
showNotification: true,
|
||||
@@ -214,6 +223,7 @@ class ServerManagerView {
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
settingOptions.autoHideMenubar = false;
|
||||
settingOptions.spellcheckerLanguages = ['en-US'];
|
||||
}
|
||||
|
||||
for (const [setting, value] of Object.entries(settingOptions)) {
|
||||
@@ -346,7 +356,7 @@ class ServerManagerView {
|
||||
this.tabs.push(new ServerTab({
|
||||
role: 'server',
|
||||
icon: server.icon,
|
||||
name: CommonUtil.decodeString(server.alias),
|
||||
name: server.alias,
|
||||
$root: this.$tabsContainer,
|
||||
onClick: this.activateLastTab.bind(this, index),
|
||||
index,
|
||||
@@ -359,13 +369,10 @@ class ServerManagerView {
|
||||
tabIndex,
|
||||
url: server.url,
|
||||
role: 'server',
|
||||
name: CommonUtil.decodeString(server.alias),
|
||||
ignoreCerts: server.ignoreCerts,
|
||||
name: server.alias,
|
||||
hasPermission: (origin: string, permission: string) =>
|
||||
origin === server.url && permission === 'notifications',
|
||||
isActive: () => {
|
||||
return index === this.activeTabIndex;
|
||||
},
|
||||
isActive: () => index === this.activeTabIndex,
|
||||
switchLoading: (loading: boolean, url: string) => {
|
||||
if (loading) {
|
||||
this.loading.add(url);
|
||||
@@ -454,7 +461,7 @@ class ServerManagerView {
|
||||
const $parent = $img.parentElement;
|
||||
const $container = $parent.parentElement;
|
||||
const webviewId = $container.dataset.tabId;
|
||||
const $webview = document.querySelector(`webview[data-tab-id="${webviewId}"]`);
|
||||
const $webview = document.querySelector(`webview[data-tab-id="${CSS.escape(webviewId)}"]`);
|
||||
const realmName = $webview.getAttribute('name');
|
||||
|
||||
if (realmName === null) {
|
||||
@@ -490,7 +497,7 @@ class ServerManagerView {
|
||||
}
|
||||
|
||||
onHover(index: number): void {
|
||||
// `this.$serverIconTooltip[index].innerHTML` already has realm name, so we are just
|
||||
// `this.$serverIconTooltip[index].textContent` already has realm name, so we are just
|
||||
// removing the style.
|
||||
this.$serverIconTooltip[index].removeAttribute('style');
|
||||
// To handle position of servers' tooltip due to scrolling of list of organizations
|
||||
@@ -530,9 +537,7 @@ class ServerManagerView {
|
||||
url: tabProps.url,
|
||||
role: 'function',
|
||||
name: tabProps.name,
|
||||
isActive: () => {
|
||||
return this.functionalTabs.get(tabProps.name) === this.activeTabIndex;
|
||||
},
|
||||
isActive: () => this.functionalTabs.get(tabProps.name) === this.activeTabIndex,
|
||||
switchLoading: (loading: boolean, url: string) => {
|
||||
if (loading) {
|
||||
this.loading.add(url);
|
||||
@@ -592,19 +597,13 @@ class ServerManagerView {
|
||||
// not crash app when this.tabs is passed into
|
||||
// ipcRenderer. Something about webview, and props.webview
|
||||
// properties in ServerTab causes the app to crash.
|
||||
get tabsForIpc(): ServerOrFunctionalTab[] {
|
||||
const tabs: ServerOrFunctionalTab[] = [];
|
||||
this.tabs.forEach((tab: ServerOrFunctionalTab) => {
|
||||
const proto = Object.create(Object.getPrototypeOf(tab));
|
||||
const tabClone = Object.assign(proto, tab);
|
||||
|
||||
tabClone.webview = {props: {}};
|
||||
tabClone.webview.props.name = tab.webview.props.name;
|
||||
delete tabClone.props.webview;
|
||||
tabs.push(tabClone);
|
||||
});
|
||||
|
||||
return tabs;
|
||||
get tabsForIpc(): TabData[] {
|
||||
return this.tabs.map(tab => ({
|
||||
role: tab.props.role,
|
||||
name: tab.props.name,
|
||||
index: tab.props.index,
|
||||
webviewName: tab.webview.props.name
|
||||
}));
|
||||
}
|
||||
|
||||
activateTab(index: number, hideOldTab = true): void {
|
||||
@@ -629,7 +628,7 @@ class ServerManagerView {
|
||||
|
||||
try {
|
||||
this.tabs[index].webview.canGoBackButton();
|
||||
} catch (_) {
|
||||
} catch {
|
||||
}
|
||||
|
||||
this.activeTabIndex = index;
|
||||
@@ -683,8 +682,8 @@ class ServerManagerView {
|
||||
this.functionalTabs.clear();
|
||||
|
||||
// Clear DOM elements
|
||||
this.$tabsContainer.innerHTML = '';
|
||||
this.$webviewsContainer.innerHTML = '';
|
||||
this.$tabsContainer.textContent = '';
|
||||
this.$webviewsContainer.textContent = '';
|
||||
}
|
||||
|
||||
async reloadView(): Promise<void> {
|
||||
@@ -719,7 +718,7 @@ class ServerManagerView {
|
||||
|
||||
updateGeneralSettings(setting: string, value: unknown): void {
|
||||
if (this.getActiveWebview()) {
|
||||
const webContents = this.getActiveWebview().getWebContents();
|
||||
const webContents = remote.webContents.fromId(this.getActiveWebview().getWebContentsId());
|
||||
webContents.send(setting, value);
|
||||
}
|
||||
}
|
||||
@@ -816,21 +815,6 @@ class ServerManagerView {
|
||||
});
|
||||
}
|
||||
|
||||
ipcRenderer.on('certificate-error', (
|
||||
event: Event,
|
||||
webContentsId: number | null,
|
||||
rendererCallbackId: number
|
||||
) => {
|
||||
const ignore = webContentsId !== null &&
|
||||
this.tabs.some(
|
||||
({webview}) =>
|
||||
!webview.loading &&
|
||||
webview.$el.getWebContentsId() === webContentsId &&
|
||||
webview.props.ignoreCerts
|
||||
);
|
||||
ipcRenderer.send('renderer-callback', rendererCallbackId, ignore);
|
||||
});
|
||||
|
||||
ipcRenderer.on('permission-request', (
|
||||
event: Event,
|
||||
{webContentsId, origin, permission}: {
|
||||
@@ -846,7 +830,7 @@ class ServerManagerView {
|
||||
({webview}) =>
|
||||
!webview.loading &&
|
||||
webview.$el.getWebContentsId() === webContentsId &&
|
||||
webview.props.hasPermission?.(origin, permission)
|
||||
webview.props.hasPermission?.(origin, permission)
|
||||
);
|
||||
console.log(
|
||||
grant ? 'Granted' : 'Denied', 'permissions request for',
|
||||
@@ -867,7 +851,7 @@ class ServerManagerView {
|
||||
|
||||
ipcRenderer.on('open-help', async () => {
|
||||
// Open help page of current active server
|
||||
await LinkUtil.openBrowser(new URL('https://zulipchat.com/help/'));
|
||||
await LinkUtil.openBrowser(new URL('https://zulip.com/help/'));
|
||||
});
|
||||
|
||||
ipcRenderer.on('reload-viewer', this.reloadView.bind(this, this.tabs[this.activeTabIndex].props.index));
|
||||
@@ -878,10 +862,6 @@ class ServerManagerView {
|
||||
ipcRenderer.send('reload-full-app');
|
||||
});
|
||||
|
||||
ipcRenderer.on('clear-app-data', () => {
|
||||
ipcRenderer.send('clear-app-settings');
|
||||
});
|
||||
|
||||
ipcRenderer.on('switch-server-tab', (event: Event, index: number) => {
|
||||
this.activateLastTab(index);
|
||||
});
|
||||
@@ -914,7 +894,7 @@ class ServerManagerView {
|
||||
webviews.forEach(webview => {
|
||||
try {
|
||||
webview.setAudioMuted(state);
|
||||
} catch (_) {
|
||||
} catch {
|
||||
// Webview is not ready yet
|
||||
webview.addEventListener('dom-ready', () => {
|
||||
webview.setAudioMuted(state);
|
||||
@@ -938,7 +918,7 @@ class ServerManagerView {
|
||||
ipcRenderer.on('toggle-dnd', (event: Event, state: boolean, newSettings: DNDSettings) => {
|
||||
this.toggleDNDButton(state);
|
||||
ipcRenderer.send('forward-message', 'toggle-silent', newSettings.silent);
|
||||
const webContents = this.getActiveWebview().getWebContents();
|
||||
const webContents = remote.webContents.fromId(this.getActiveWebview().getWebContentsId());
|
||||
webContents.send('toggle-dnd', state, newSettings);
|
||||
});
|
||||
|
||||
@@ -947,11 +927,11 @@ class ServerManagerView {
|
||||
if (domain.url.includes(serverURL)) {
|
||||
const serverTooltipSelector = '.tab .server-tooltip';
|
||||
const serverTooltips = document.querySelectorAll(serverTooltipSelector);
|
||||
serverTooltips[index].innerHTML = escape(realmName);
|
||||
this.tabs[index].props.name = escape(realmName);
|
||||
serverTooltips[index].textContent = realmName;
|
||||
this.tabs[index].props.name = realmName;
|
||||
this.tabs[index].webview.props.name = realmName;
|
||||
|
||||
domain.alias = escape(realmName);
|
||||
domain.alias = realmName;
|
||||
DomainUtil.updateDomain(index, domain);
|
||||
// Update the realm name also on the Window menu
|
||||
ipcRenderer.send('update-menu', {
|
||||
@@ -990,9 +970,9 @@ class ServerManagerView {
|
||||
ipcRenderer.on('focus-webview-with-id', (event: Event, webviewId: number) => {
|
||||
const webviews: NodeListOf<Electron.WebviewTag> = document.querySelectorAll('webview');
|
||||
webviews.forEach(webview => {
|
||||
const currentId = webview.getWebContents().id;
|
||||
const currentId = webview.getWebContentsId();
|
||||
const tabId = webview.getAttribute('data-tab-id');
|
||||
const concurrentTab: HTMLButtonElement = document.querySelector(`div[data-tab-id="${tabId}"]`);
|
||||
const concurrentTab: HTMLButtonElement = document.querySelector(`div[data-tab-id="${CSS.escape(tabId)}"]`);
|
||||
if (currentId === webviewId) {
|
||||
concurrentTab.click();
|
||||
}
|
||||
@@ -1043,13 +1023,9 @@ class ServerManagerView {
|
||||
});
|
||||
|
||||
// Redo and undo functionality since the default API doesn't work on macOS
|
||||
ipcRenderer.on('undo', () => {
|
||||
return this.getActiveWebview().undo();
|
||||
});
|
||||
ipcRenderer.on('undo', () => this.getActiveWebview().undo());
|
||||
|
||||
ipcRenderer.on('redo', () => {
|
||||
return this.getActiveWebview().redo();
|
||||
});
|
||||
ipcRenderer.on('redo', () => this.getActiveWebview().redo());
|
||||
|
||||
ipcRenderer.on('set-active', async () => {
|
||||
const webviews: NodeListOf<Electron.WebviewTag> = document.querySelectorAll('webview');
|
||||
@@ -1069,15 +1045,14 @@ class ServerManagerView {
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
// Only start electron-connect (auto reload on change) when its ran
|
||||
// from `npm run dev` or `gulp dev` and not from `npm start` when
|
||||
// app is started `npm start` main process's proces.argv will have
|
||||
// `--no-electron-connect`
|
||||
if (isDev && !remote.getGlobal('process').argv.includes('--no-electron-connect')) {
|
||||
require('electron-connect').client.create();
|
||||
// from `npm run dev` or `gulp dev` and not from `npm start`
|
||||
if (isDev && remote.getGlobal('process').argv.includes('--electron-connect')) {
|
||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
||||
(await import('electron-connect')).client.create();
|
||||
}
|
||||
|
||||
const serverManagerView = new ServerManagerView();
|
||||
await serverManagerView.init();
|
||||
});
|
||||
|
||||
export {};
|
||||
export { };
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import MacNotifier from 'node-mac-notifier';
|
||||
|
||||
import electron_bridge from '../electron-bridge';
|
||||
import * as ConfigUtil from '../utils/config-util';
|
||||
|
||||
import {
|
||||
appId, customReply, focusCurrentServer, parseReply
|
||||
} from './helpers';
|
||||
|
||||
import MacNotifier from 'node-mac-notifier';
|
||||
import * as ConfigUtil from '../utils/config-util';
|
||||
import electron_bridge from '../electron-bridge';
|
||||
|
||||
type ReplyHandler = (response: string) => void;
|
||||
type ClickHandler = () => void;
|
||||
let replyHandler: ReplyHandler;
|
||||
@@ -47,7 +49,7 @@ class DarwinNotification {
|
||||
}
|
||||
|
||||
static requestPermission(): void {
|
||||
return; // eslint-disable-line no-useless-return
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// Override default Notification permission
|
||||
@@ -104,7 +106,7 @@ class DarwinNotification {
|
||||
// Method specific to notification api
|
||||
// used by zulip
|
||||
close(): void {
|
||||
return; // eslint-disable-line no-useless-return
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
import {focusCurrentServer} from './helpers';
|
||||
|
||||
import * as ConfigUtil from '../utils/config-util';
|
||||
|
||||
import {focusCurrentServer} from './helpers';
|
||||
|
||||
const NativeNotification = window.Notification;
|
||||
export default class BaseNotification extends NativeNotification {
|
||||
constructor(title: string, options: NotificationOptions) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {remote} from 'electron';
|
||||
import electron_bridge from '../electron-bridge';
|
||||
import {appId, loadBots} from './helpers';
|
||||
|
||||
import DefaultNotification from './default-notification';
|
||||
import {appId} from './helpers';
|
||||
|
||||
const {app} = remote;
|
||||
|
||||
// From https://github.com/felixrieseberg/electron-windows-notifications#appusermodelid
|
||||
@@ -67,7 +67,3 @@ export function newNotification(
|
||||
actions: notification.actions
|
||||
};
|
||||
}
|
||||
|
||||
electron_bridge.once('zulip-loaded', async () => {
|
||||
await loadBots();
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use-strict';
|
||||
|
||||
import {remote, OpenDialogOptions} from 'electron';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
import * as CertificateUtil from '../../utils/certificate-util';
|
||||
import * as DomainUtil from '../../utils/domain-util';
|
||||
@@ -26,8 +26,8 @@ export default class AddCertificate extends BaseComponent {
|
||||
this._certFile = '';
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-card certificates-card">
|
||||
<div class="certificate-input">
|
||||
<div>${t.__('Organization URL')}</div>
|
||||
@@ -42,7 +42,7 @@ export default class AddCertificate extends BaseComponent {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$addCertificate = this.generateNodeFromTemplate(this.template());
|
||||
this.$addCertificate = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.props.$root.append(this.$addCertificate);
|
||||
this.addCertificateButton = this.$addCertificate.querySelector('#add-certificate-button');
|
||||
this.serverUrl = this.$addCertificate.querySelectorAll('input.setting-input-value')[0] as HTMLInputElement;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
import escape from 'escape-html';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
|
||||
@@ -14,9 +15,9 @@ export default class BaseSection extends BaseComponent {
|
||||
generateSettingOption(props: BaseSectionProps): void {
|
||||
const {$element, disabled, value, clickHandler} = props;
|
||||
|
||||
$element.innerHTML = '';
|
||||
$element.textContent = '';
|
||||
|
||||
const $optionControl = this.generateNodeFromTemplate(this.generateOptionTemplate(value, disabled));
|
||||
const $optionControl = this.generateNodeFromHTML(this.generateOptionHTML(value, disabled));
|
||||
$element.append($optionControl);
|
||||
|
||||
if (!disabled) {
|
||||
@@ -24,39 +25,39 @@ export default class BaseSection extends BaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
generateOptionTemplate(settingOption: boolean, disabled?: boolean): string {
|
||||
const label = disabled ? '<label class="disallowed" title="Setting locked by system administrator."/>' : '<label/>';
|
||||
generateOptionHTML(settingOption: boolean, disabled?: boolean): string {
|
||||
const labelHTML = disabled ? '<label class="disallowed" title="Setting locked by system administrator."></label>' : '<label></label>';
|
||||
if (settingOption) {
|
||||
return `
|
||||
return htmlEscape`
|
||||
<div class="action">
|
||||
<div class="switch">
|
||||
<input class="toggle toggle-round" type="checkbox" checked disabled>
|
||||
${label}
|
||||
<input class="toggle toggle-round" type="checkbox" checked disabled>
|
||||
` + labelHTML + htmlEscape`
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="action">
|
||||
<div class="switch">
|
||||
<input class="toggle toggle-round" type="checkbox">
|
||||
${label}
|
||||
</div>
|
||||
return htmlEscape`
|
||||
<div class="action">
|
||||
<div class="switch">
|
||||
<input class="toggle toggle-round" type="checkbox">
|
||||
` + labelHTML + htmlEscape`
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* A method that in future can be used to create dropdown menus using <select> <option> tags.
|
||||
it needs an object which has ``key: value`` pairs and will return a string that can be appended to HTML
|
||||
*/
|
||||
generateSelectTemplate(options: {[key: string]: string}, className?: string, idName?: string): string {
|
||||
let select = `<select class="${escape(className)}" id="${escape(idName)}">\n`;
|
||||
generateSelectHTML(options: {[key: string]: string}, className?: string, idName?: string): string {
|
||||
let html = htmlEscape`<select class="${className}" id="${idName}">\n`;
|
||||
Object.keys(options).forEach(key => {
|
||||
select += `<option name="${escape(key)}" value="${escape(key)}">${escape(options[key])}</option>\n`;
|
||||
html += htmlEscape`<option name="${key}" value="${key}">${options[key]}</option>\n`;
|
||||
});
|
||||
select += '</select>';
|
||||
return select;
|
||||
html += '</select>';
|
||||
return html;
|
||||
}
|
||||
|
||||
reloadApp(): void {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as DomainUtil from '../../utils/domain-util';
|
||||
import ServerInfoForm from './server-info-form';
|
||||
import AddCertificate from './add-certificate';
|
||||
import FindAccounts from './find-accounts';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
import AddCertificate from './add-certificate';
|
||||
import BaseSection from './base-section';
|
||||
import FindAccounts from './find-accounts';
|
||||
import ServerInfoForm from './server-info-form';
|
||||
|
||||
interface ConnectedOrgSectionProps {
|
||||
$root: Element;
|
||||
}
|
||||
@@ -23,8 +26,8 @@ export default class ConnectedOrgSection extends BaseSection {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-pane" id="server-settings-pane">
|
||||
<div class="page-title">${t.__('Connected organizations')}</div>
|
||||
<div class="title" id="existing-servers">${t.__('All the connected orgnizations will appear here.')}</div>
|
||||
@@ -43,10 +46,10 @@ export default class ConnectedOrgSection extends BaseSection {
|
||||
}
|
||||
|
||||
initServers(): void {
|
||||
this.props.$root.innerHTML = '';
|
||||
this.props.$root.textContent = '';
|
||||
|
||||
const servers = DomainUtil.getDomains();
|
||||
this.props.$root.innerHTML = this.template();
|
||||
this.props.$root.innerHTML = this.templateHTML();
|
||||
|
||||
this.$serverInfoContainer = document.querySelector('#server-info-container');
|
||||
this.$existingServers = document.querySelector('#existing-servers');
|
||||
@@ -56,7 +59,7 @@ export default class ConnectedOrgSection extends BaseSection {
|
||||
|
||||
const noServerText = t.__('All the connected orgnizations will appear here');
|
||||
// Show noServerText if no servers are there otherwise hide it
|
||||
this.$existingServers.innerHTML = servers.length === 0 ? noServerText : '';
|
||||
this.$existingServers.textContent = servers.length === 0 ? noServerText : '';
|
||||
|
||||
for (const [i, server] of servers.entries()) {
|
||||
new ServerInfoForm({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use-strict';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
import * as LinkUtil from '../../utils/link-util';
|
||||
@@ -18,8 +18,8 @@ export default class FindAccounts extends BaseComponent {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-card certificate-card">
|
||||
<div class="certificate-input">
|
||||
<div>${t.__('Organization URL')}</div>
|
||||
@@ -33,7 +33,7 @@ export default class FindAccounts extends BaseComponent {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$findAccounts = this.generateNodeFromTemplate(this.template());
|
||||
this.$findAccounts = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.props.$root.append(this.$findAccounts);
|
||||
this.$findAccountsButton = this.$findAccounts.querySelector('#find-accounts-button');
|
||||
this.$serverUrlField = this.$findAccounts.querySelectorAll('input.setting-input-value')[0] as HTMLInputElement;
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import {ipcRenderer, remote, OpenDialogOptions} from 'electron';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import Tagify from '@yaireo/tagify';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
import fs from 'fs-extra';
|
||||
import ISO6391 from 'iso-639-1';
|
||||
|
||||
const {app, dialog} = remote;
|
||||
const currentBrowserWindow = remote.getCurrentWindow();
|
||||
|
||||
import BaseSection from './base-section';
|
||||
import supportedLocales from '../../../../translations/supported-locales.json';
|
||||
import * as ConfigUtil from '../../utils/config-util';
|
||||
import * as EnterpriseUtil from '../../utils/enterprise-util';
|
||||
import * as t from '../../utils/translation-util';
|
||||
import supportedLocales from '../../../../translations/supported-locales.json';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
|
||||
const {app, dialog, session} = remote;
|
||||
const currentBrowserWindow = remote.getCurrentWindow();
|
||||
|
||||
interface GeneralSectionProps {
|
||||
$root: Element;
|
||||
@@ -23,8 +27,8 @@ export default class GeneralSection extends BaseSection {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-pane">
|
||||
<div class="title">${t.__('Appearance')}</div>
|
||||
<div id="appearance-option-settings" class="settings-card">
|
||||
@@ -93,7 +97,10 @@ export default class GeneralSection extends BaseSection {
|
||||
<div class="setting-description">${t.__('Enable spellchecker (requires restart)')}</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="spellcheck-langs" style= "display:${process.platform === 'darwin' ? 'none' : ''}"></div>
|
||||
<div class="setting-row" id="note"></div>
|
||||
</div>
|
||||
|
||||
<div class="title">${t.__('Advanced')}</div>
|
||||
<div class="settings-card">
|
||||
|
||||
@@ -138,12 +145,12 @@ export default class GeneralSection extends BaseSection {
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">${t.__('Reset Application Data')}</div>
|
||||
<div class="title">${t.__('Factory Reset Data')}</div>
|
||||
<div class="settings-card">
|
||||
<div class="setting-row" id="resetdata-option">
|
||||
<div class="setting-description">${t.__('This will delete all application data including all added accounts and preferences')}
|
||||
<div class="setting-row" id="factory-reset-option">
|
||||
<div class="setting-description">${t.__('Reset the application, thus deleting all the connected organizations, accounts, and certificates.')}
|
||||
</div>
|
||||
<button class="reset-data-button red w-150">${t.__('Reset App Data')}</button>
|
||||
<button class="factory-reset-button red w-150">${t.__('Factory Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -151,7 +158,7 @@ export default class GeneralSection extends BaseSection {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.props.$root.innerHTML = this.template();
|
||||
this.props.$root.innerHTML = this.templateHTML();
|
||||
this.updateTrayOption();
|
||||
this.updateBadgeOption();
|
||||
this.updateSilentOption();
|
||||
@@ -159,7 +166,7 @@ export default class GeneralSection extends BaseSection {
|
||||
this.betaUpdateOption();
|
||||
this.updateSidebarOption();
|
||||
this.updateStartAtLoginOption();
|
||||
this.updateResetDataOption();
|
||||
this.factoryReset();
|
||||
this.showDesktopNotification();
|
||||
this.enableSpellchecker();
|
||||
this.minimizeOnStart();
|
||||
@@ -171,6 +178,7 @@ export default class GeneralSection extends BaseSection {
|
||||
this.updatePromptDownloadOption();
|
||||
this.enableErrorReporting();
|
||||
this.setLocale();
|
||||
this.initSpellChecker();
|
||||
|
||||
// Platform specific settings
|
||||
|
||||
@@ -356,6 +364,10 @@ export default class GeneralSection extends BaseSection {
|
||||
const newValue = !ConfigUtil.getConfigItem('enableSpellchecker');
|
||||
ConfigUtil.setConfigItem('enableSpellchecker', newValue);
|
||||
this.enableSpellchecker();
|
||||
const spellcheckerLanguageInput: HTMLElement = document.querySelector('#spellcheck-langs');
|
||||
const spellcheckerNote: HTMLElement = document.querySelector('#note');
|
||||
spellcheckerLanguageInput.style.display = spellcheckerLanguageInput.style.display === 'none' ? '' : 'none';
|
||||
spellcheckerNote.style.display = spellcheckerNote.style.display === 'none' ? '' : 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -372,23 +384,6 @@ export default class GeneralSection extends BaseSection {
|
||||
});
|
||||
}
|
||||
|
||||
async clearAppDataDialog(): Promise<void> {
|
||||
const clearAppDataMessage = 'By clicking proceed you will be removing all added accounts and preferences from Zulip. When the application restarts, it will be as if you are starting Zulip for the first time.';
|
||||
const getAppPath = path.join(app.getPath('appData'), app.name);
|
||||
|
||||
const {response} = await dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['YES', 'NO'],
|
||||
defaultId: 0,
|
||||
message: 'Are you sure',
|
||||
detail: clearAppDataMessage
|
||||
});
|
||||
if (response === 0) {
|
||||
await fs.remove(getAppPath);
|
||||
ipcRenderer.send('forward-message', 'hard-reload');
|
||||
}
|
||||
}
|
||||
|
||||
async customCssDialog(): Promise<void> {
|
||||
const showDialogOptions: OpenDialogOptions = {
|
||||
title: 'Select file',
|
||||
@@ -403,24 +398,16 @@ export default class GeneralSection extends BaseSection {
|
||||
}
|
||||
}
|
||||
|
||||
updateResetDataOption(): void {
|
||||
const resetDataButton = document.querySelector('#resetdata-option .reset-data-button');
|
||||
resetDataButton.addEventListener('click', async () => {
|
||||
await this.clearAppDataDialog();
|
||||
});
|
||||
}
|
||||
|
||||
setLocale(): void {
|
||||
const langDiv: HTMLSelectElement = document.querySelector('.lang-div');
|
||||
// This path is for the JSON file that stores key: value pairs for supported locales
|
||||
const langList = this.generateSelectTemplate(supportedLocales, 'lang-menu');
|
||||
langDiv.innerHTML += langList;
|
||||
const langListHTML = this.generateSelectHTML(supportedLocales, 'lang-menu');
|
||||
langDiv.innerHTML += langListHTML;
|
||||
// `langMenu` is the select-option dropdown menu formed after executing the previous command
|
||||
const langMenu: HTMLSelectElement = document.querySelector('.lang-menu');
|
||||
|
||||
// The next three lines set the selected language visible on the dropdown button
|
||||
let language = ConfigUtil.getConfigItem('appLanguage');
|
||||
language = language && langMenu.options.namedItem(language) ? language : 'en-US';
|
||||
language = language && langMenu.options.namedItem(language) ? language : 'en';
|
||||
langMenu.options.namedItem(language).selected = true;
|
||||
|
||||
langMenu.addEventListener('change', (event: Event) => {
|
||||
@@ -494,4 +481,103 @@ export default class GeneralSection extends BaseSection {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async factoryResetSettings(): Promise<void> {
|
||||
const clearAppDataMessage = 'When the application restarts, it will be as if you have just downloaded Zulip app.';
|
||||
const getAppPath = path.join(app.getPath('appData'), app.name);
|
||||
|
||||
const {response} = await dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['YES', 'NO'],
|
||||
defaultId: 0,
|
||||
message: 'Are you sure?',
|
||||
detail: clearAppDataMessage
|
||||
});
|
||||
if (response === 0) {
|
||||
await fs.remove(getAppPath);
|
||||
setTimeout(() => ipcRenderer.send('clear-app-settings'), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
factoryReset(): void {
|
||||
const factoryResetButton = document.querySelector('#factory-reset-option .factory-reset-button');
|
||||
factoryResetButton.addEventListener('click', async () => {
|
||||
await this.factoryResetSettings();
|
||||
});
|
||||
}
|
||||
|
||||
initSpellChecker(): void {
|
||||
// The elctron API is a no-op on macOS and macOS default spellchecker is used.
|
||||
if (process.platform === 'darwin') {
|
||||
const note: HTMLElement = document.querySelector('#note');
|
||||
note.append(t.__('On macOS, the OS spellchecker is used.'));
|
||||
note.append(document.createElement('br'));
|
||||
note.append(t.__('Change the language from System Preferences → Keyboard → Text → Spelling.'));
|
||||
} else {
|
||||
const note: HTMLElement = document.querySelector('#note');
|
||||
note.append(t.__('You can select a maximum of 3 languages for spellchecking.'));
|
||||
const spellDiv: HTMLElement = document.querySelector('#spellcheck-langs');
|
||||
spellDiv.innerHTML += htmlEscape`
|
||||
<div class="setting-description">${t.__('Spellchecker Languages')}</div>
|
||||
<input name='spellcheck' placeholder='Enter Languages'>`;
|
||||
|
||||
const availableLanguages = session.fromPartition('persist:webviewsession').availableSpellCheckerLanguages;
|
||||
let languagePairs: Map<string, string> = new Map();
|
||||
availableLanguages.forEach((l: string) => {
|
||||
if (ISO6391.validate(l)) {
|
||||
languagePairs.set(ISO6391.getName(l), l);
|
||||
}
|
||||
});
|
||||
|
||||
// Manually set names for languages not available in ISO6391
|
||||
languagePairs.set('English (AU)', 'en-AU');
|
||||
languagePairs.set('English (CA)', 'en-CA');
|
||||
languagePairs.set('English (GB)', 'en-GB');
|
||||
languagePairs.set('English (US)', 'en-US');
|
||||
languagePairs.set('Spanish (Latin America)', 'es-419');
|
||||
languagePairs.set('Spanish (Argentina)', 'es-AR');
|
||||
languagePairs.set('Spanish (Mexico)', 'es-MX');
|
||||
languagePairs.set('Spanish (US)', 'es-US');
|
||||
languagePairs.set('Portuguese (Brazil)', 'pt-BR');
|
||||
languagePairs.set('Portuguese (Portugal)', 'pt-PT');
|
||||
languagePairs.set('Serbo-Croatian', 'sh');
|
||||
|
||||
languagePairs = new Map([...languagePairs].sort((a, b) => ((a[0] < b[0]) ? -1 : 1)));
|
||||
|
||||
const tagField: HTMLElement = document.querySelector('input[name=spellcheck]');
|
||||
const tagify = new Tagify(tagField, {
|
||||
whitelist: [...languagePairs.keys()],
|
||||
enforceWhitelist: true,
|
||||
maxTags: 3,
|
||||
dropdown: {
|
||||
enabled: 0,
|
||||
maxItems: Infinity,
|
||||
closeOnSelect: false,
|
||||
highlightFirst: true
|
||||
}
|
||||
});
|
||||
|
||||
const configuredLanguages: string[] = ConfigUtil.getConfigItem('spellcheckerLanguages').map((code: string) => [...languagePairs].find(pair => (pair[1] === code))[0]);
|
||||
tagify.addTags(configuredLanguages);
|
||||
|
||||
tagField.addEventListener('change', event => {
|
||||
if ((event.target as HTMLInputElement).value.length === 0) {
|
||||
ConfigUtil.setConfigItem('spellcheckerLanguages', []);
|
||||
ipcRenderer.send('set-spellcheck-langs');
|
||||
} else {
|
||||
const spellLangs: string[] = [...JSON.parse((event.target as HTMLInputElement).value).values()].map(elt => languagePairs.get(elt.value));
|
||||
ConfigUtil.setConfigItem('spellcheckerLanguages', spellLangs);
|
||||
ipcRenderer.send('set-spellcheck-langs');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Do not display the spellchecker input and note if it is disabled
|
||||
if (!ConfigUtil.getConfigItem('enableSpellchecker')) {
|
||||
const spellcheckerLanguageInput: HTMLElement = document.querySelector('#spellcheck-langs');
|
||||
const spellcheckerNote: HTMLElement = document.querySelector('#note');
|
||||
spellcheckerLanguageInput.style.display = 'none';
|
||||
spellcheckerNote.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
@@ -17,29 +19,29 @@ export default class PreferenceNav extends BaseComponent {
|
||||
this.init();
|
||||
}
|
||||
|
||||
template(): string {
|
||||
let navItemsTemplate = '';
|
||||
templateHTML(): string {
|
||||
let navItemsHTML = '';
|
||||
for (const navItem of this.navItems) {
|
||||
navItemsTemplate += `<div class="nav" id="nav-${navItem}">${t.__(navItem)}</div>`;
|
||||
navItemsHTML += htmlEscape`<div class="nav" id="nav-${navItem}">${t.__(navItem)}</div>`;
|
||||
}
|
||||
|
||||
return `
|
||||
return htmlEscape`
|
||||
<div>
|
||||
<div id="settings-header">${t.__('Settings')}</div>
|
||||
<div id="nav-container">${navItemsTemplate}</div>
|
||||
<div id="nav-container">` + navItemsHTML + htmlEscape`</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.$el = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.props.$root.append(this.$el);
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
registerListeners(): void {
|
||||
for (const navItem of this.navItems) {
|
||||
const $item = document.querySelector(`#nav-${navItem}`);
|
||||
const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`);
|
||||
$item.addEventListener('click', () => {
|
||||
this.props.onItemSelected(navItem);
|
||||
});
|
||||
@@ -57,12 +59,12 @@ export default class PreferenceNav extends BaseComponent {
|
||||
}
|
||||
|
||||
activate(navItem: string): void {
|
||||
const $item = document.querySelector(`#nav-${navItem}`);
|
||||
const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`);
|
||||
$item.classList.add('active');
|
||||
}
|
||||
|
||||
deactivate(navItem: string): void {
|
||||
const $item = document.querySelector(`#nav-${navItem}`);
|
||||
const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`);
|
||||
$item.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as ConfigUtil from '../../utils/config-util';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
|
||||
interface NetworkSectionProps {
|
||||
$root: Element;
|
||||
}
|
||||
@@ -20,8 +23,8 @@ export default class NetworkSection extends BaseSection {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-pane">
|
||||
<div class="title">${t.__('Proxy')}</div>
|
||||
<div id="appearance-option-settings" class="settings-card">
|
||||
@@ -58,7 +61,7 @@ export default class NetworkSection extends BaseSection {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.props.$root.innerHTML = this.template();
|
||||
this.props.$root.innerHTML = this.templateHTML();
|
||||
this.$proxyPAC = document.querySelector('#proxy-pac-option .setting-input-value');
|
||||
this.$proxyRules = document.querySelector('#proxy-rules-option .setting-input-value');
|
||||
this.$proxyBypass = document.querySelector('#proxy-bypass-option .setting-input-value');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {ipcRenderer, remote} from 'electron';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
import * as DomainUtil from '../../utils/domain-util';
|
||||
import * as LinkUtil from '../../utils/link-util';
|
||||
@@ -22,8 +24,8 @@ export default class NewServerForm extends BaseComponent {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="server-input-container">
|
||||
<div class="title">${t.__('Organization URL')}</div>
|
||||
<div class="add-server-info-row">
|
||||
@@ -56,20 +58,20 @@ export default class NewServerForm extends BaseComponent {
|
||||
}
|
||||
|
||||
initForm(): void {
|
||||
this.$newServerForm = this.generateNodeFromTemplate(this.template());
|
||||
this.$newServerForm = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.$saveServerButton = this.$newServerForm.querySelector('#connect');
|
||||
this.props.$root.innerHTML = '';
|
||||
this.props.$root.textContent = '';
|
||||
this.props.$root.append(this.$newServerForm);
|
||||
this.$newServerUrl = this.$newServerForm.querySelectorAll('input.setting-input-value')[0] as HTMLInputElement;
|
||||
}
|
||||
|
||||
async submitFormHandler(): Promise<void> {
|
||||
this.$saveServerButton.innerHTML = 'Connecting...';
|
||||
this.$saveServerButton.textContent = 'Connecting...';
|
||||
let serverConf;
|
||||
try {
|
||||
serverConf = await DomainUtil.checkDomain(this.$newServerUrl.value);
|
||||
} catch (error) {
|
||||
this.$saveServerButton.innerHTML = 'Connect';
|
||||
this.$saveServerButton.textContent = 'Connect';
|
||||
await dialog.showMessageBox({
|
||||
type: 'error',
|
||||
message: error.toString(),
|
||||
@@ -83,7 +85,7 @@ export default class NewServerForm extends BaseComponent {
|
||||
}
|
||||
|
||||
openCreateNewOrgExternalLink(): void {
|
||||
const link = 'https://zulipchat.com/new/';
|
||||
const link = 'https://zulip.com/new/';
|
||||
const externalCreateNewOrgElement = document.querySelector('#open-create-org-link');
|
||||
externalCreateNewOrgElement.addEventListener('click', async () => {
|
||||
await LinkUtil.openBrowser(new URL(link));
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import BaseComponent from '../../components/base';
|
||||
import Nav from './nav';
|
||||
import ServersSection from './servers-section';
|
||||
import GeneralSection from './general-section';
|
||||
import NetworkSection from './network-section';
|
||||
import ConnectedOrgSection from './connected-org-section';
|
||||
import ShortcutsSection from './shortcuts-section';
|
||||
import type {DNDSettings} from '../../utils/dnd-util';
|
||||
|
||||
import ConnectedOrgSection from './connected-org-section';
|
||||
import GeneralSection from './general-section';
|
||||
import Nav from './nav';
|
||||
import NetworkSection from './network-section';
|
||||
import ServersSection from './servers-section';
|
||||
import ShortcutsSection from './shortcuts-section';
|
||||
|
||||
type Section = ServersSection | GeneralSection | NetworkSection | ConnectedOrgSection | ShortcutsSection;
|
||||
|
||||
export default class PreferenceView extends BaseComponent {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {remote, ipcRenderer} from 'electron';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as Messages from '../../../../resources/messages';
|
||||
import BaseComponent from '../../components/base';
|
||||
import * as DomainUtil from '../../utils/domain-util';
|
||||
import * as Messages from '../../../../resources/messages';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
const {dialog} = remote;
|
||||
@@ -26,8 +28,8 @@ export default class ServerInfoForm extends BaseComponent {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="settings-card">
|
||||
<div class="server-info-left">
|
||||
<img class="server-info-icon" src="${this.props.server.icon}"/>
|
||||
@@ -56,7 +58,7 @@ export default class ServerInfoForm extends BaseComponent {
|
||||
}
|
||||
|
||||
initForm(): void {
|
||||
this.$serverInfoForm = this.generateNodeFromTemplate(this.template());
|
||||
this.$serverInfoForm = this.generateNodeFromHTML(this.templateHTML());
|
||||
this.$serverInfoAlias = this.$serverInfoForm.querySelectorAll('.server-info-alias')[0];
|
||||
this.$serverIcon = this.$serverInfoForm.querySelectorAll('.server-info-icon')[0];
|
||||
this.$deleteServerButton = this.$serverInfoForm.querySelectorAll('.server-delete-action')[0];
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
import NewServerForm from './new-server-form';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
interface ServersSectionProps {
|
||||
$root: Element;
|
||||
@@ -14,16 +17,16 @@ export default class ServersSection extends BaseSection {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
template(): string {
|
||||
return `
|
||||
<div class="add-server-modal">
|
||||
<div class="modal-container">
|
||||
<div class="settings-pane" id="server-settings-pane">
|
||||
<div class="page-title">${t.__('Add a Zulip organization')}</div>
|
||||
<div id="new-server-container"></div>
|
||||
templateHTML(): string {
|
||||
return htmlEscape`
|
||||
<div class="add-server-modal">
|
||||
<div class="modal-container">
|
||||
<div class="settings-pane" id="server-settings-pane">
|
||||
<div class="page-title">${t.__('Add a Zulip organization')}</div>
|
||||
<div id="new-server-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -32,9 +35,9 @@ export default class ServersSection extends BaseSection {
|
||||
}
|
||||
|
||||
initServers(): void {
|
||||
this.props.$root.innerHTML = '';
|
||||
this.props.$root.textContent = '';
|
||||
|
||||
this.props.$root.innerHTML = this.template();
|
||||
this.props.$root.innerHTML = this.templateHTML();
|
||||
this.$newServerContainer = document.querySelector('#new-server-container');
|
||||
|
||||
this.initNewServerForm();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import BaseSection from './base-section';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import * as LinkUtil from '../../utils/link-util';
|
||||
import * as t from '../../utils/translation-util';
|
||||
|
||||
import BaseSection from './base-section';
|
||||
|
||||
interface ShortcutsSectionProps {
|
||||
$root: Element;
|
||||
}
|
||||
@@ -13,14 +16,14 @@ export default class ShortcutsSection extends BaseSection {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
// TODO - Deduplicate templateMac and templateWinLin functions. In theory
|
||||
// TODO - Deduplicate templateMacHTML and templateWinLinHTML functions. In theory
|
||||
// they both should be the same the only thing different should be the userOSKey
|
||||
// variable but there seems to be inconsistences between both function, one has more
|
||||
// lines though one may just be using more new lines and other thing is the use of +.
|
||||
templateMac(): string {
|
||||
templateMacHTML(): string {
|
||||
const userOSKey = '⌘';
|
||||
|
||||
return `
|
||||
return htmlEscape`
|
||||
<div class="settings-pane">
|
||||
<div class="settings-card tip"><p><b><i class="material-icons md-14">settings</i>${t.__('Tip')}: </b>${t.__('These desktop app shortcuts extend the Zulip webapp\'s')} <span id="open-hotkeys-link"> ${t.__('keyboard shortcuts')}</span>.</p></div>
|
||||
<div class="title">${t.__('Application Shortcuts')}</div>
|
||||
@@ -181,10 +184,10 @@ export default class ShortcutsSection extends BaseSection {
|
||||
`;
|
||||
}
|
||||
|
||||
templateWinLin(): string {
|
||||
templateWinLinHTML(): string {
|
||||
const userOSKey = 'Ctrl';
|
||||
|
||||
return `
|
||||
return htmlEscape`
|
||||
<div class="settings-pane">
|
||||
<div class="settings-card tip"><p><b><i class="material-icons md-14">settings</i>${t.__('Tip')}: </b>${t.__('These desktop app shortcuts extend the Zulip webapp\'s')} <span id="open-hotkeys-link"> ${t.__('keyboard shortcuts')}</span>.</p></div>
|
||||
<div class="title">${t.__('Application Shortcuts')}</div>
|
||||
@@ -330,7 +333,7 @@ export default class ShortcutsSection extends BaseSection {
|
||||
}
|
||||
|
||||
openHotkeysExternalLink(): void {
|
||||
const link = 'https://zulipchat.com/help/keyboard-shortcuts';
|
||||
const link = 'https://zulip.com/help/keyboard-shortcuts';
|
||||
const externalCreateNewOrgElement = document.querySelector('#open-hotkeys-link');
|
||||
externalCreateNewOrgElement.addEventListener('click', async () => {
|
||||
await LinkUtil.openBrowser(new URL(link));
|
||||
@@ -339,7 +342,7 @@ export default class ShortcutsSection extends BaseSection {
|
||||
|
||||
init(): void {
|
||||
this.props.$root.innerHTML = (process.platform === 'darwin') ?
|
||||
this.templateMac() : this.templateWinLin();
|
||||
this.templateMacHTML() : this.templateWinLinHTML();
|
||||
this.openHotkeysExternalLink();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import {contextBridge, ipcRenderer, webFrame} from 'electron';
|
||||
import fs from 'fs';
|
||||
import * as SetupSpellChecker from './spellchecker';
|
||||
|
||||
import isDev from 'electron-is-dev';
|
||||
|
||||
import electron_bridge from './electron-bridge';
|
||||
import {loadBots} from './notification/helpers';
|
||||
import * as NetworkError from './pages/network';
|
||||
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
import './notification';
|
||||
|
||||
// Prevent drag and drop event in main process which prevents remote code executaion
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
import './shared/preventdrag';
|
||||
|
||||
import electron_bridge from './electron-bridge';
|
||||
contextBridge.exposeInMainWorld('raw_electron_bridge', electron_bridge);
|
||||
|
||||
electron_bridge.once('zulip-loaded', async () => {
|
||||
await loadBots();
|
||||
});
|
||||
|
||||
ipcRenderer.on('logout', () => {
|
||||
// Create the menu for the below
|
||||
const dropdown: HTMLElement = document.querySelector('.dropdown-toggle');
|
||||
@@ -54,13 +55,7 @@ ipcRenderer.on('show-notification-settings', () => {
|
||||
}, 100);
|
||||
});
|
||||
|
||||
electron_bridge.once('zulip-loaded', ({serverLanguage}) => {
|
||||
// Get the default language of the server
|
||||
if (serverLanguage) {
|
||||
// Init spellchecker
|
||||
SetupSpellChecker.init(serverLanguage);
|
||||
}
|
||||
|
||||
electron_bridge.once('zulip-loaded', () => {
|
||||
// Redirect users to network troubleshooting page
|
||||
const getRestartButton = document.querySelector('.restart_get_events_button');
|
||||
if (getRestartButton) {
|
||||
@@ -70,12 +65,6 @@ electron_bridge.once('zulip-loaded', ({serverLanguage}) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up spellchecker events after you navigate away from this page;
|
||||
// otherwise, you may experience errors
|
||||
window.addEventListener('beforeunload', (): void => {
|
||||
SetupSpellChecker.unsubscribeSpellChecker();
|
||||
});
|
||||
|
||||
window.addEventListener('load', (event: any): void => {
|
||||
if (!event.target.URL.includes('app/renderer/network.html')) {
|
||||
return;
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import type {Subject} from 'rxjs';
|
||||
import {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} from 'electron-spellchecker';
|
||||
|
||||
import * as ConfigUtil from './utils/config-util';
|
||||
import Logger from './utils/logger-util';
|
||||
|
||||
declare module 'electron-spellchecker' {
|
||||
interface SpellCheckHandler {
|
||||
currentSpellcheckerChanged: Subject<true>;
|
||||
currentSpellcheckerLanguage: string;
|
||||
}
|
||||
}
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'errors.log',
|
||||
timestamp: true
|
||||
});
|
||||
|
||||
let spellCheckHandler: SpellCheckHandler;
|
||||
let contextMenuListener: ContextMenuListener;
|
||||
|
||||
export function init(serverLanguage: string): void {
|
||||
if (ConfigUtil.getConfigItem('enableSpellchecker')) {
|
||||
enableSpellChecker();
|
||||
}
|
||||
|
||||
enableContextMenu(serverLanguage);
|
||||
}
|
||||
|
||||
function enableSpellChecker(): void {
|
||||
try {
|
||||
spellCheckHandler = new SpellCheckHandler();
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
function enableContextMenu(serverLanguage: string): void {
|
||||
if (spellCheckHandler) {
|
||||
spellCheckHandler.attachToInput();
|
||||
spellCheckHandler.switchLanguage(serverLanguage);
|
||||
spellCheckHandler.currentSpellcheckerChanged.subscribe(() => {
|
||||
spellCheckHandler.switchLanguage(spellCheckHandler.currentSpellcheckerLanguage);
|
||||
});
|
||||
}
|
||||
|
||||
const contextMenuBuilder = new ContextMenuBuilder(spellCheckHandler);
|
||||
contextMenuListener = new ContextMenuListener(info => {
|
||||
contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
}
|
||||
|
||||
export function unsubscribeSpellChecker(): void {
|
||||
if (spellCheckHandler) {
|
||||
spellCheckHandler.unsubscribe();
|
||||
}
|
||||
|
||||
if (contextMenuListener) {
|
||||
contextMenuListener.unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
import {ipcRenderer, remote, WebviewTag, NativeImage} from 'electron';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import * as ConfigUtil from './utils/config-util';
|
||||
|
||||
const {Tray, Menu, nativeImage, BrowserWindow, nativeTheme} = remote;
|
||||
const {Tray, Menu, nativeImage, BrowserWindow} = remote;
|
||||
|
||||
let tray: Electron.Tray;
|
||||
|
||||
// Get the theme on macOS
|
||||
const theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
|
||||
|
||||
const ICON_DIR = process.platform === 'darwin' ? `../../resources/tray/${theme}` : '../../resources/tray';
|
||||
const ICON_DIR = '../../resources/tray';
|
||||
|
||||
const TRAY_SUFFIX = 'tray';
|
||||
|
||||
@@ -21,7 +18,7 @@ const iconPath = (): string => {
|
||||
return APP_ICON + 'linux.png';
|
||||
}
|
||||
|
||||
return APP_ICON + (process.platform === 'win32' ? 'win.ico' : 'osx.png');
|
||||
return APP_ICON + (process.platform === 'win32' ? 'win.ico' : 'macOSTemplate.png');
|
||||
};
|
||||
|
||||
let unread = 0;
|
||||
@@ -210,7 +207,7 @@ function toggleTray(): void {
|
||||
|
||||
const selector = 'webview:not([class*=disabled])';
|
||||
const webview: WebviewTag = document.querySelector(selector);
|
||||
const webContents = webview.getWebContents();
|
||||
const webContents = remote.webContents.fromId(webview.getWebContentsId());
|
||||
webContents.send('toggletray', state);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import electron from 'electron';
|
||||
import {JsonDB} from 'node-json-db';
|
||||
import {initSetUp} from './default-util';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import {initSetUp} from './default-util';
|
||||
import Logger from './logger-util';
|
||||
|
||||
const {app, dialog} =
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Unescape already encoded/escaped strings
|
||||
export function decodeString(stringInput: string): string {
|
||||
const parser = new DOMParser();
|
||||
const dom = parser.parseFromString(
|
||||
'<!doctype html><body>' + stringInput,
|
||||
'text/html');
|
||||
return dom.body.textContent;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import electron from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import electron from 'electron';
|
||||
import Logger from './logger-util';
|
||||
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import * as EnterpriseUtil from './enterprise-util';
|
||||
import Logger from './logger-util';
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'config-util.log',
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import escape from 'escape-html';
|
||||
import request from 'request';
|
||||
import {remote, ipcRenderer} from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import Logger from './logger-util';
|
||||
import {remote} from 'electron';
|
||||
|
||||
import * as RequestUtil from './request-util';
|
||||
import * as EnterpriseUtil from './enterprise-util';
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import * as Messages from '../../../resources/messages';
|
||||
|
||||
import * as EnterpriseUtil from './enterprise-util';
|
||||
import Logger from './logger-util';
|
||||
|
||||
const {app, dialog} = remote;
|
||||
|
||||
export interface ServerConf {
|
||||
url: string;
|
||||
alias?: string;
|
||||
icon?: string;
|
||||
ignoreCerts?: boolean;
|
||||
}
|
||||
|
||||
const logger = new Logger({
|
||||
@@ -55,26 +52,14 @@ export function getDomain(index: number): ServerConf {
|
||||
return db.getData(`/domains[${index}]`);
|
||||
}
|
||||
|
||||
export function shouldIgnoreCerts(url: string): boolean {
|
||||
const domains = getDomains();
|
||||
for (const domain of domains) {
|
||||
if (domain.url === url) {
|
||||
return domain.ignoreCerts;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function updateDomain(index: number, server: ServerConf): void {
|
||||
reloadDB();
|
||||
db.push(`/domains[${index}]`, server, true);
|
||||
}
|
||||
|
||||
export async function addDomain(server: ServerConf): Promise<void> {
|
||||
const {ignoreCerts} = server;
|
||||
if (server.icon) {
|
||||
const localIconUrl = await saveServerIcon(server, ignoreCerts);
|
||||
const localIconUrl = await saveServerIcon(server);
|
||||
server.icon = localIconUrl;
|
||||
db.push('/domains[]', server, true);
|
||||
reloadDB();
|
||||
@@ -118,33 +103,16 @@ async function checkCertError(domain: string, serverConf: ServerConf, error: any
|
||||
const certErrorMessage = Messages.certErrorMessage(domain, error);
|
||||
const certErrorDetail = Messages.certErrorDetail();
|
||||
|
||||
const {response} = await dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['Yes', 'No'],
|
||||
defaultId: 1,
|
||||
await dialog.showMessageBox({
|
||||
type: 'error',
|
||||
buttons: ['OK'],
|
||||
message: certErrorMessage,
|
||||
detail: certErrorDetail
|
||||
});
|
||||
if (response === 0) {
|
||||
// Set ignoreCerts parameter to true in case user responds with yes
|
||||
serverConf.ignoreCerts = true;
|
||||
try {
|
||||
return await getServerSettings(domain, serverConf.ignoreCerts);
|
||||
} catch (_) {
|
||||
if (error === Messages.noOrgsError(domain)) {
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
return serverConf;
|
||||
}
|
||||
} else {
|
||||
throw new Error('Untrusted certificate.');
|
||||
}
|
||||
throw new Error('Untrusted certificate.');
|
||||
}
|
||||
|
||||
// ignoreCerts parameter helps in fetching server icon and
|
||||
// other server details when user chooses to ignore certificate warnings
|
||||
export async function checkDomain(domain: string, ignoreCerts = false, silent = false): Promise<ServerConf> {
|
||||
export async function checkDomain(domain: string, silent = false): Promise<ServerConf> {
|
||||
if (!silent && duplicateDomain(domain)) {
|
||||
// Do not check duplicate in silent mode
|
||||
throw new Error('This server has been added.');
|
||||
@@ -155,12 +123,11 @@ export async function checkDomain(domain: string, ignoreCerts = false, silent =
|
||||
const serverConf = {
|
||||
icon: defaultIconUrl,
|
||||
url: domain,
|
||||
alias: domain,
|
||||
ignoreCerts
|
||||
alias: domain
|
||||
};
|
||||
|
||||
try {
|
||||
return await getServerSettings(domain, serverConf.ignoreCerts);
|
||||
return await getServerSettings(domain);
|
||||
} catch (error_) {
|
||||
// Make sure that error is an error or string not undefined
|
||||
// so validation does not throw error.
|
||||
@@ -176,85 +143,20 @@ export async function checkDomain(domain: string, ignoreCerts = false, silent =
|
||||
}
|
||||
}
|
||||
|
||||
async function getServerSettings(domain: string, ignoreCerts = false): Promise<ServerConf> {
|
||||
const serverSettingsOptions = {
|
||||
url: domain + '/api/v1/server_settings',
|
||||
...RequestUtil.requestOptions(domain, ignoreCerts)
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(serverSettingsOptions, (error: Error, response: request.Response) => {
|
||||
if (!error && response.statusCode === 200) {
|
||||
const {realm_name, realm_uri, realm_icon} = JSON.parse(response.body);
|
||||
if (
|
||||
typeof realm_name === 'string' &&
|
||||
typeof realm_uri === 'string' &&
|
||||
typeof realm_icon === 'string'
|
||||
) {
|
||||
resolve({
|
||||
// Some Zulip Servers use absolute URL for server icon whereas others use relative URL
|
||||
// Following check handles both the cases
|
||||
icon: realm_icon.startsWith('/') ? realm_uri + realm_icon : realm_icon,
|
||||
url: realm_uri,
|
||||
alias: escape(realm_name),
|
||||
ignoreCerts
|
||||
});
|
||||
} else {
|
||||
reject(Messages.noOrgsError(domain));
|
||||
}
|
||||
} else {
|
||||
reject(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
async function getServerSettings(domain: string): Promise<ServerConf> {
|
||||
return ipcRenderer.invoke('get-server-settings', domain);
|
||||
}
|
||||
|
||||
export async function saveServerIcon(server: ServerConf, ignoreCerts = false): Promise<string> {
|
||||
const url = server.icon;
|
||||
const domain = server.url;
|
||||
|
||||
const serverIconOptions = {
|
||||
url,
|
||||
...RequestUtil.requestOptions(domain, ignoreCerts)
|
||||
};
|
||||
|
||||
// The save will always succeed. If url is invalid, downgrade to default icon.
|
||||
return new Promise(resolve => {
|
||||
const filePath = generateFilePath(url);
|
||||
const file = fs.createWriteStream(filePath);
|
||||
try {
|
||||
request(serverIconOptions).on('response', (response: request.Response) => {
|
||||
response.on('error', (err: Error) => {
|
||||
logger.log('Could not get server icon.');
|
||||
logger.log(err);
|
||||
logger.reportSentry(err);
|
||||
resolve(defaultIconUrl);
|
||||
});
|
||||
response.pipe(file).on('finish', () => {
|
||||
resolve(filePath);
|
||||
});
|
||||
}).on('error', (err: Error) => {
|
||||
logger.log('Could not get server icon.');
|
||||
logger.log(err);
|
||||
logger.reportSentry(err);
|
||||
resolve(defaultIconUrl);
|
||||
});
|
||||
} catch (error) {
|
||||
logger.log('Could not get server icon.');
|
||||
logger.log(error);
|
||||
logger.reportSentry(error);
|
||||
resolve(defaultIconUrl);
|
||||
}
|
||||
});
|
||||
export async function saveServerIcon(server: ServerConf): Promise<string> {
|
||||
return ipcRenderer.invoke('save-server-icon', server.icon);
|
||||
}
|
||||
|
||||
export async function updateSavedServer(url: string, index: number): Promise<void> {
|
||||
// Does not promise successful update
|
||||
const oldIcon = getDomain(index).icon;
|
||||
const {ignoreCerts} = getDomain(index);
|
||||
try {
|
||||
const newServerConf = await checkDomain(url, ignoreCerts, true);
|
||||
const localIconUrl = await saveServerIcon(newServerConf, ignoreCerts);
|
||||
const newServerConf = await checkDomain(url, true);
|
||||
const localIconUrl = await saveServerIcon(newServerConf);
|
||||
if (!oldIcon || localIconUrl !== '../renderer/img/icon.png') {
|
||||
newServerConf.icon = localIconUrl;
|
||||
updateDomain(index, newServerConf);
|
||||
@@ -289,25 +191,6 @@ function reloadDB(): void {
|
||||
db = new JsonDB(domainJsonPath, true, true);
|
||||
}
|
||||
|
||||
function generateFilePath(url: string): string {
|
||||
const dir = `${app.getPath('userData')}/server-icons`;
|
||||
const extension = path.extname(url).split('?')[0];
|
||||
|
||||
let hash = 5381;
|
||||
let {length} = url;
|
||||
|
||||
while (length) {
|
||||
hash = (hash * 33) ^ url.charCodeAt(--length);
|
||||
}
|
||||
|
||||
// Create 'server-icons' directory if not existed
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
return `${dir}/${hash >>> 0}${extension}`;
|
||||
}
|
||||
|
||||
export function formatUrl(domain: string): string {
|
||||
if (domain.startsWith('http://') || domain.startsWith('https://')) {
|
||||
return domain;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import {shell} from 'electron';
|
||||
import escape from 'escape-html';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
export function isUploadsUrl(server: string, url: URL): boolean {
|
||||
return url.origin === server && url.pathname.startsWith('/user_uploads/');
|
||||
}
|
||||
@@ -18,12 +19,12 @@ export async function openBrowser(url: URL): Promise<void> {
|
||||
path.join(os.tmpdir(), 'zulip-redirect-')
|
||||
);
|
||||
const file = path.join(dir, 'redirect.html');
|
||||
fs.writeFileSync(file, `\
|
||||
fs.writeFileSync(file, htmlEscape`\
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Refresh" content="0; url=${escape(url.href)}" />
|
||||
<meta http-equiv="Refresh" content="0; url=${url.href}" />
|
||||
<title>Redirecting</title>
|
||||
<style>
|
||||
html {
|
||||
@@ -32,11 +33,11 @@ export async function openBrowser(url: URL): Promise<void> {
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Opening <a href="${escape(url.href)}">${escape(url.href)}</a>…</p>
|
||||
<p>Opening <a href="${url.href}">${url.href}</a>…</p>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
shell.openItem(file);
|
||||
await shell.openPath(file);
|
||||
setTimeout(() => {
|
||||
fs.unlinkSync(file);
|
||||
fs.rmdirSync(dir);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import electron from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import electron from 'electron';
|
||||
|
||||
import {JsonDB} from 'node-json-db';
|
||||
|
||||
import Logger from './logger-util';
|
||||
|
||||
const remote =
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {Console} from 'console'; // eslint-disable-line node/prefer-global/console
|
||||
import {initSetUp} from './default-util';
|
||||
import {sentryInit, captureException} from './sentry-util';
|
||||
|
||||
import electron from 'electron';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
|
||||
import isDev from 'electron-is-dev';
|
||||
import electron from 'electron';
|
||||
|
||||
import {initSetUp} from './default-util';
|
||||
import {sentryInit, captureException} from './sentry-util';
|
||||
|
||||
interface LoggerOptions {
|
||||
timestamp?: true | (() => string);
|
||||
@@ -89,20 +90,21 @@ export default class Logger {
|
||||
nodeConsole, timestamp, level, logInDevMode
|
||||
} = this;
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (true) {
|
||||
case typeof timestamp === 'function':
|
||||
args.unshift(timestamp() + ' |\t');
|
||||
// Fall through
|
||||
|
||||
case (level):
|
||||
args.unshift(type.toUpperCase() + ' |');
|
||||
// Fall through
|
||||
|
||||
case isDev || logInDevMode:
|
||||
nodeConsole[type](...args);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
}
|
||||
/* eslint-enable no-fallthrough */
|
||||
|
||||
console[type](...args);
|
||||
}
|
||||
|
||||
@@ -5,45 +5,6 @@ export interface ProxyRule {
|
||||
port?: number;
|
||||
}
|
||||
|
||||
// Return proxy to be used for a particular uri, to be used for request
|
||||
export function getProxy(_uri: string): ProxyRule | void {
|
||||
let uri;
|
||||
try {
|
||||
uri = new URL(_uri);
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const proxyRules = ConfigUtil.getConfigItem('proxyRules', '').split(';');
|
||||
// If SPS is on and system uses no proxy then request should not try to use proxy from
|
||||
// environment. NO_PROXY = '*' makes request ignore all environment proxy variables.
|
||||
if (proxyRules[0] === '') {
|
||||
process.env.NO_PROXY = '*';
|
||||
return;
|
||||
}
|
||||
|
||||
const proxyRule: any = {};
|
||||
if (uri.protocol === 'http:') {
|
||||
proxyRules.forEach((proxy: string) => {
|
||||
if (proxy.includes('http=')) {
|
||||
proxyRule.hostname = proxy.split('http=')[1].trim().split(':')[0];
|
||||
proxyRule.port = proxy.split('http=')[1].trim().split(':')[1];
|
||||
}
|
||||
});
|
||||
return proxyRule;
|
||||
}
|
||||
|
||||
if (uri.protocol === 'https:') {
|
||||
proxyRules.forEach((proxy: string) => {
|
||||
if (proxy.includes('https=')) {
|
||||
proxyRule.hostname = proxy.split('https=')[1].trim().split(':')[0];
|
||||
proxyRule.port = proxy.split('https=')[1].trim().split(':')[1];
|
||||
}
|
||||
});
|
||||
return proxyRule;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Refactor to async function
|
||||
export async function resolveSystemProxy(mainWindow: Electron.BrowserWindow): Promise<void> {
|
||||
const page = mainWindow.webContents;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import type WebView from '../components/webview';
|
||||
import backoff from 'backoff';
|
||||
import request from 'request';
|
||||
import {htmlEscape} from 'escape-goat';
|
||||
|
||||
import type WebView from '../components/webview';
|
||||
|
||||
import Logger from './logger-util';
|
||||
import * as RequestUtil from './request-util';
|
||||
import * as DomainUtil from './domain-util';
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'domain-util.log',
|
||||
@@ -33,28 +33,7 @@ export default class ReconnectUtil {
|
||||
}
|
||||
|
||||
async isOnline(): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
try {
|
||||
const ignoreCerts = DomainUtil.shouldIgnoreCerts(this.url);
|
||||
if (ignoreCerts === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
request(
|
||||
{
|
||||
url: `${this.url}/static/favicon.ico`,
|
||||
...RequestUtil.requestOptions(this.url, ignoreCerts)
|
||||
},
|
||||
(error: Error, response: request.Response) => {
|
||||
const isValidResponse =
|
||||
!error && response.statusCode >= 200 && response.statusCode < 400;
|
||||
resolve(isValidResponse);
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
logger.log(error);
|
||||
}
|
||||
});
|
||||
return ipcRenderer.invoke('is-online', this.url);
|
||||
}
|
||||
|
||||
pollInternetAndReload(): void {
|
||||
@@ -82,7 +61,7 @@ export default class ReconnectUtil {
|
||||
logger.log('There is no internet connection, try checking network cables, modem and router.');
|
||||
const errorMessageHolder = document.querySelector('#description');
|
||||
if (errorMessageHolder) {
|
||||
errorMessageHolder.innerHTML = `
|
||||
errorMessageHolder.innerHTML = htmlEscape`
|
||||
<div>Your internet connection doesn't seem to work properly!</div>
|
||||
<div>Verify that it works and then click try again.</div>`;
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import {remote} from 'electron';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as ConfigUtil from './config-util';
|
||||
import Logger from './logger-util';
|
||||
import * as ProxyUtil from './proxy-util';
|
||||
import * as CertificateUtil from './certificate-util';
|
||||
import * as SystemUtil from './system-util';
|
||||
|
||||
const {app} = remote;
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'request-util.log',
|
||||
timestamp: true
|
||||
});
|
||||
|
||||
interface RequestUtilResponse {
|
||||
ca: string;
|
||||
proxy: string | void | ProxyUtil.ProxyRule;
|
||||
ecdhCurve: 'auto';
|
||||
headers: { 'User-Agent': string };
|
||||
rejectUnauthorized: boolean;
|
||||
}
|
||||
|
||||
// ignoreCerts parameter helps in fetching server icon and
|
||||
// other server details when user chooses to ignore certificate warnings
|
||||
export function requestOptions(domain: string, ignoreCerts: boolean): RequestUtilResponse {
|
||||
domain = formatUrl(domain);
|
||||
const certificate = CertificateUtil.getCertificate(
|
||||
encodeURIComponent(domain)
|
||||
);
|
||||
|
||||
let certificateFile = null;
|
||||
if (certificate?.includes('/')) {
|
||||
// Certificate saved using old app version
|
||||
certificateFile = certificate;
|
||||
} else if (certificate) {
|
||||
certificateFile = path.join(`${app.getPath('userData')}/certificates`, certificate);
|
||||
}
|
||||
|
||||
let certificateLocation = '';
|
||||
if (certificate) {
|
||||
// To handle case where certificate has been moved from the location in certificates.json
|
||||
try {
|
||||
certificateLocation = fs.readFileSync(certificateFile, 'utf8');
|
||||
} catch (error) {
|
||||
logger.warn('Error while trying to get certificate:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
// If certificate for the domain exists add it as a ca key in the request's parameter else consider only domain as the parameter for request
|
||||
// Add proxy as a parameter if it is being used.
|
||||
return {
|
||||
ca: certificateLocation ? certificateLocation : '',
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(domain) : '',
|
||||
ecdhCurve: 'auto',
|
||||
headers: {'User-Agent': SystemUtil.getUserAgent()},
|
||||
rejectUnauthorized: !ignoreCerts
|
||||
};
|
||||
}
|
||||
|
||||
function formatUrl(domain: string): string {
|
||||
const hasPrefix = domain.startsWith('http', 0);
|
||||
if (hasPrefix) {
|
||||
return domain;
|
||||
}
|
||||
|
||||
return domain.includes('localhost:') ? `http://${domain}` : `https://${domain}`;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import {init} from '@sentry/electron';
|
||||
|
||||
import isDev from 'electron-is-dev';
|
||||
|
||||
export const sentryInit = (): void => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {ipcRenderer} from 'electron';
|
||||
|
||||
import os from 'os';
|
||||
|
||||
export const connectivityERR: string[] = [
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import path from 'path';
|
||||
|
||||
import i18n from 'i18n';
|
||||
|
||||
import * as ConfigUtil from './config-util';
|
||||
|
||||
i18n.configure({
|
||||
directory: path.join(__dirname, '../../../translations/')
|
||||
directory: path.join(__dirname, '../../../translations/'),
|
||||
updateFiles: false
|
||||
});
|
||||
|
||||
/* Fetches the current appLocale from settings.json */
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
|
||||
<div id="feedback-modal">
|
||||
<send-feedback></send-feedback>
|
||||
<send-feedback show-cancel-button="show"></send-feedback>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Zulip - Settings</title>
|
||||
<link rel="stylesheet" href="css/preference.css" type="text/css" media="screen">
|
||||
<link id="tagify-css" rel="stylesheet" href="data:text/css,">
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
@@ -13,6 +14,7 @@
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
document.querySelector('#tagify-css').href = require.resolve('@yaireo/tagify/dist/tagify.css');
|
||||
require('./js/pages/preference/preference.js');
|
||||
require('./js/shared/preventdrag.js')
|
||||
</script>
|
||||
|
||||
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -19,14 +19,12 @@ export function noOrgsError(domain: string): string {
|
||||
}
|
||||
|
||||
export function certErrorMessage(domain: string, error: string): string {
|
||||
return `Do you trust certificate from ${domain}? \n ${error}`;
|
||||
return `Certificate error for ${domain}\n${error}`;
|
||||
}
|
||||
|
||||
export function certErrorDetail(): string {
|
||||
return `The organization you're connecting to is either someone impersonating the Zulip server you entered, or the server you're trying to connect to is configured in an insecure way.
|
||||
\nIf you have a valid certificate please add it from Settings>Organizations and try to add the organization again.
|
||||
\nUnless you have a good reason to believe otherwise, you should not proceed.
|
||||
\nYou can click here if you'd like to proceed with the connection.`;
|
||||
\nIf you have a valid certificate please add it from Settings>Organizations and try to add the organization again.`;
|
||||
}
|
||||
|
||||
export function enterpriseOrgError(length: number, domains: string[]): DialogBoxError {
|
||||
|
||||
|
Before Width: | Height: | Size: 436 B |
|
Before Width: | Height: | Size: 900 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 737 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
app/resources/tray/traymacOSTemplate.png
Normal file
|
After Width: | Height: | Size: 321 B |
BIN
app/resources/tray/traymacOSTemplate@2x.png
Normal file
|
After Width: | Height: | Size: 631 B |
BIN
app/resources/tray/traymacOSTemplate@3x.png
Normal file
|
After Width: | Height: | Size: 932 B |
BIN
app/resources/tray/traymacOSTemplate@4x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 13 KiB |
134
app/translations/ar.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "حول \"زوليب\"",
|
||||
"Actual Size": "الحجم الفعلي",
|
||||
"Add Custom Certificates": "إضافة رخصة معدلة",
|
||||
"Add Organization": "إضافة منظمة",
|
||||
"Add a Zulip organization": "إضافة منظمة \"زوليب\"",
|
||||
"Add custom CSS": "إصافة CSS معدلة",
|
||||
"Advanced": "متقدم",
|
||||
"All the connected organizations will appear here": "جميع المنظمات المتصلة تعرض هنا",
|
||||
"Always start minimized": "دائماً إبدأ بالقليل",
|
||||
"App Updates": "تحديث التطبيق",
|
||||
"Appearance": "المظهر",
|
||||
"Application Shortcuts": "إختصارات التطبيق",
|
||||
"Are you sure you want to disconnect this organization?": "هل أنت متأكد من فصل هذة المنظمة؟",
|
||||
"Auto hide Menu bar": "أخف القائمة تلقائياً",
|
||||
"Auto hide menu bar (Press Alt key to display)": "أخف القائمة تلقائياً (إضغط Alt لعرض القائمة)",
|
||||
"Back": "رجوع",
|
||||
"Bounce dock on new private message": "أخرج المنصة في حال رسالة خاصة جديدة",
|
||||
"Certificate file": "ملف الشهادة",
|
||||
"Change": "تغيير",
|
||||
"Check for Updates": "التحقق من التحديثات",
|
||||
"Close": "اغلاق",
|
||||
"Connect": "اتصال",
|
||||
"Connect to another organization": "التوصيل مع منظمة أخرى",
|
||||
"Connected organizations": "المنظمات المتصلة",
|
||||
"Copy": "نسخ",
|
||||
"Copy Zulip URL": "نسخ رابط زوليب",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Cut": "قص",
|
||||
"Default download location": "موقع التحميل الافتراضي",
|
||||
"Delete": "حذف",
|
||||
"Desktop App Settings": "إعدادت تطبيق سطح المكتب",
|
||||
"Desktop Notifications": "إشعارات سطح المكتب",
|
||||
"Desktop Settings": "إعدادات سطح المكتب",
|
||||
"Disconnect": "قطع الاتصال",
|
||||
"Download App Logs": "تنزيل سجلات التطبيق",
|
||||
"Edit": "تعديل",
|
||||
"Edit Shortcuts": "تعديل الاختصارات",
|
||||
"Enable auto updates": "تفعيل التحديثات التلقائية",
|
||||
"Enable error reporting (requires restart)": "تفعيل تقارير الأخطاء (يتطلب إعادة التشغيل)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "إعادة ضبط المصنع",
|
||||
"File": "ملف",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organization URL",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"About Zulip": "За Zulip",
|
||||
"About Zulip": "Относно Zulip",
|
||||
"Actual Size": "Действителен размер",
|
||||
"Add Custom Certificates": "Добавяне на персонализирани сертификати",
|
||||
"Add Organization": "Добавяне на организация",
|
||||
@@ -75,9 +75,6 @@
|
||||
"Release Notes": "Бележки към изданието",
|
||||
"Reload": "Презареди",
|
||||
"Report an Issue": "Подаване на сигнал за проблем",
|
||||
"Reset App Data": "Нулиране на данни за приложения",
|
||||
"Reset App Settings": "Нулиране на настройките на приложението",
|
||||
"Reset Application Data": "Нулиране на данните на приложението",
|
||||
"Save": "Запази",
|
||||
"Select All": "Избери всички",
|
||||
"Settings": "Настройки",
|
||||
@@ -113,5 +110,25 @@
|
||||
"Zoom Out": "Отдалечавам",
|
||||
"Zulip Help": "Помощ за Zulip",
|
||||
"keyboard shortcuts": "комбинация от клавиши",
|
||||
"script": "писменост"
|
||||
"script": "писменост",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
|
||||
134
app/translations/ca.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "Quant a Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organization",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Tancar",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Copia",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Crea una nova organització",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Elimina",
|
||||
"Desktop App Settings": "Configuració de l'aplicació d'escriptori",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Configuració d'escriptori",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Edita",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "Fitxer",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Centre d'ajuda",
|
||||
"History": "Historial",
|
||||
"History Shortcuts": "Dreceres d'historial",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Silencia tots els sons de Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "URL d'organització",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Guardar",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Configuració",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Mostrar una marca en la icona si hi ha missatges no llegits",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Pujada",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,117 +1,134 @@
|
||||
{
|
||||
"About Zulip": "O uživateli Zulip",
|
||||
"Actual Size": "Aktuální velikost",
|
||||
"About Zulip": "O Zulipu",
|
||||
"Actual Size": "Skutečná velikost",
|
||||
"Add Custom Certificates": "Přidat vlastní certifikáty",
|
||||
"Add Organization": "Přidat organizaci",
|
||||
"Add a Zulip organization": "Přidejte organizaci Zulip",
|
||||
"Add a Zulip organization": "Přidat organizaci Zulip",
|
||||
"Add custom CSS": "Přidat vlastní CSS",
|
||||
"Advanced": "Pokročilý",
|
||||
"All the connected organizations will appear here": "Zde se zobrazí všechny připojené organizace",
|
||||
"Always start minimized": "Vždy začněte minimalizovat",
|
||||
"App Updates": "Aktualizace aplikací",
|
||||
"Advanced": "Rozšířené",
|
||||
"All the connected organizations will appear here": "Všechny připojené organizace se objeví zde",
|
||||
"Always start minimized": "Vždy spouštět minimalizované",
|
||||
"App Updates": "Aktualizace aplikace",
|
||||
"Appearance": "Vzhled",
|
||||
"Application Shortcuts": "Zkratky aplikací",
|
||||
"Are you sure you want to disconnect this organization?": "Opravdu chcete tuto organizaci odpojit?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Automaticky skrýt lištu menu (stiskněte klávesu Alt pro zobrazení)",
|
||||
"Back": "Zadní",
|
||||
"Bounce dock on new private message": "Bounce dock na nové soukromé zprávy",
|
||||
"Certificate file": "Soubor certifikátu",
|
||||
"Change": "Změna",
|
||||
"Check for Updates": "Kontrola aktualizací",
|
||||
"Application Shortcuts": "Zkratky programu",
|
||||
"Are you sure you want to disconnect this organization?": "Opravdu chcete odpojit tuto organizaci?",
|
||||
"Auto hide Menu bar": "Automaticky skrývat menu",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Automaticky skrývat menu (pro zobrazení stiskněte klávesu Alt)",
|
||||
"Back": "Zpět",
|
||||
"Bounce dock on new private message": "Poskakování ikony v docku po obdržení nové soukromé zprávy",
|
||||
"Certificate file": "Soubor s certifikátem",
|
||||
"Change": "Změnit",
|
||||
"Check for Updates": "Zkontrolovat aktualizace",
|
||||
"Close": "Zavřít",
|
||||
"Connect": "Připojit",
|
||||
"Connect to another organization": "Připojte se k jiné organizaci",
|
||||
"Connect": "Připojit se",
|
||||
"Connect to another organization": "Připojit se k jiné organizaci",
|
||||
"Connected organizations": "Připojené organizace",
|
||||
"Copy": "kopírovat",
|
||||
"Copy Zulip URL": "Kopírovat adresu URL aplikace Zulip",
|
||||
"Copy": "Kopírovat",
|
||||
"Copy Zulip URL": "Kopírovat adresu (URL) Zulipu",
|
||||
"Create a new organization": "Vytvořit novou organizaci",
|
||||
"Cut": "Střih",
|
||||
"Cut": "Vyjmout",
|
||||
"Default download location": "Výchozí umístění stahování",
|
||||
"Delete": "Smazat",
|
||||
"Desktop App Settings": "Nastavení aplikace Desktop",
|
||||
"Desktop Notifications": "Oznámení o pracovní ploše",
|
||||
"Desktop App Settings": "Nastavení desktopové aplikace",
|
||||
"Desktop Notifications": "Oznámení na ploše",
|
||||
"Desktop Settings": "Nastavení plochy",
|
||||
"Disconnect": "Odpojit",
|
||||
"Download App Logs": "Stáhnout App Logs",
|
||||
"Download App Logs": "Stáhnout záznamy programu",
|
||||
"Edit": "Upravit",
|
||||
"Edit Shortcuts": "Upravit zkratky",
|
||||
"Enable auto updates": "Povolit automatické aktualizace",
|
||||
"Enable error reporting (requires restart)": "Povolit hlášení chyb (vyžaduje restart)",
|
||||
"Enable spellchecker (requires restart)": "Povolit kontrolu pravopisu (vyžaduje restartování)",
|
||||
"Factory Reset": "Tovární nastavení",
|
||||
"Enable error reporting (requires restart)": "Povolit hlášení chyb (vyžaduje opětovné spuštění programu)",
|
||||
"Enable spellchecker (requires restart)": "Povolit kontrolu pravopisu (vyžaduje opětovné spuštění programu)",
|
||||
"Factory Reset": "Obnovení do továrního nastavení",
|
||||
"File": "Soubor",
|
||||
"Find accounts": "Najít účty",
|
||||
"Find accounts by email": "Najít účty e-mailem",
|
||||
"Flash taskbar on new message": "Hlavní panel Flash na nové zprávě",
|
||||
"Find accounts by email": "Najít účty podle adresy elektronické pošty",
|
||||
"Flash taskbar on new message": "Blikání ikony v hlavním panelu při obdržení nové zprávy",
|
||||
"Forward": "Vpřed",
|
||||
"Functionality": "Funkčnost",
|
||||
"General": "Všeobecné",
|
||||
"Get beta updates": "Získejte aktualizace beta",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Pomoc",
|
||||
"Functionality": "Funkce",
|
||||
"General": "Obecné",
|
||||
"Get beta updates": "Dostávat beta aktualizace",
|
||||
"Hard Reload": "Tvrdé znovunahrání",
|
||||
"Help": "Nápověda",
|
||||
"Help Center": "Centrum nápovědy",
|
||||
"History": "Dějiny",
|
||||
"History Shortcuts": "Zkratky historie",
|
||||
"History": "Historie",
|
||||
"History Shortcuts": "Zkratky pro historii",
|
||||
"Keyboard Shortcuts": "Klávesové zkratky",
|
||||
"Log Out": "Odhlásit se",
|
||||
"Log Out of Organization": "Odhlásit se z organizace",
|
||||
"Manual proxy configuration": "Ruční konfigurace proxy",
|
||||
"Manual proxy configuration": "Ruční nastavení proxy",
|
||||
"Minimize": "Minimalizovat",
|
||||
"Mute all sounds from Zulip": "Vypněte všechny zvuky ze Zulipu",
|
||||
"Mute all sounds from Zulip": "Ztlumit všechny zvuky ze Zulipu",
|
||||
"NO": "NE",
|
||||
"Network": "Síť",
|
||||
"OR": "NEBO",
|
||||
"Organization URL": "URL organizace",
|
||||
"Organization URL": "Adresa organizace",
|
||||
"Organizations": "Organizace",
|
||||
"Paste": "Vložit",
|
||||
"Paste and Match Style": "Vložit a shodit styl",
|
||||
"Paste and Match Style": "Vložit a ponechat styl",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass pravidla",
|
||||
"Proxy rules": "Proxy pravidla",
|
||||
"Quit": "Přestat",
|
||||
"Quit Zulip": "Ukončete Zulip",
|
||||
"Redo": "Předělat",
|
||||
"Release Notes": "Poznámky k vydání",
|
||||
"Reload": "Znovu načíst",
|
||||
"Proxy bypass rules": "Pravidla pro obejití Proxy",
|
||||
"Proxy rules": "Pravidla Proxy",
|
||||
"Quit": "Ukončit",
|
||||
"Quit Zulip": "Ukončit Zulip",
|
||||
"Redo": "Znovu",
|
||||
"Release Notes": "Poznámky k této verzi",
|
||||
"Reload": "Nahrát znovu",
|
||||
"Report an Issue": "Nahlásit problém",
|
||||
"Reset App Data": "Resetovat data aplikace",
|
||||
"Reset App Settings": "Obnovit nastavení aplikace",
|
||||
"Reset Application Data": "Resetovat data aplikace",
|
||||
"Save": "Uložit",
|
||||
"Select All": "Vybrat vše",
|
||||
"Settings": "Nastavení",
|
||||
"Shortcuts": "Zkratky",
|
||||
"Show App Logs": "Zobrazit protokoly aplikací",
|
||||
"Show app icon in system tray": "Zobrazit ikonu aplikace v systémové liště",
|
||||
"Show app unread badge": "Zobrazit nepřečtený odznak aplikace",
|
||||
"Show desktop notifications": "Zobrazit oznámení na ploše",
|
||||
"Show App Logs": "Zobrazit záznamy programu",
|
||||
"Show app icon in system tray": "Zobrazovat ikonu programu v oznamovací oblasti panelu",
|
||||
"Show app unread badge": "Zobrazovat u ikony aplikace symbol nepřečteno",
|
||||
"Show desktop notifications": "Zobrazovat oznámení na ploše",
|
||||
"Show downloaded files in file manager": "Zobrazit stažené soubory ve správci souborů",
|
||||
"Show sidebar": "Zobrazit postranní panel",
|
||||
"Start app at login": "Spuštění aplikace při přihlášení",
|
||||
"Show sidebar": "Zobrazovat postranní panel",
|
||||
"Start app at login": "Spustit program při přihlášení",
|
||||
"Switch to Next Organization": "Přepnout na další organizaci",
|
||||
"Switch to Previous Organization": "Přepněte na předchozí organizaci",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Tyto klávesové zkratky pro aplikaci na ploše rozšiřují aplikaci Zulip webapp",
|
||||
"This will delete all application data including all added accounts and preferences": "Tím odstraníte všechna data aplikace včetně všech přidaných účtů a předvoleb",
|
||||
"Switch to Previous Organization": "Přepnout na předchozí organizaci",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Tyto zkratky rozšiřují webovou aplikaci Zulipu",
|
||||
"This will delete all application data including all added accounts and preferences": "Toto smaže všechna data programu včetně všech přidaných účtů a nastavení",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Přepnout DevTools pro Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Přepnout DevTools pro Zulip App",
|
||||
"Toggle Do Not Disturb": "Přepnout Do Nerušit",
|
||||
"Toggle DevTools for Active Tab": "Přepnout vývojářské nástroje pro aktivní kartu",
|
||||
"Toggle DevTools for Zulip App": "Přepnout vývojářské nástroje pro program Zulip",
|
||||
"Toggle Do Not Disturb": "Přepnout mód Nerušit",
|
||||
"Toggle Full Screen": "Přepnout na celou obrazovku",
|
||||
"Toggle Sidebar": "Přepnout postranní panel",
|
||||
"Toggle Tray Icon": "Přepnout ikonu zásobníku",
|
||||
"Toggle Sidebar": "Přepnout zobrazení postranního panelu",
|
||||
"Toggle Tray Icon": "Přepnout ikonu v oznamovací oblasti panelu",
|
||||
"Tools": "Nástroje",
|
||||
"Undo": "vrátit",
|
||||
"Upload": "nahrát",
|
||||
"Use system proxy settings (requires restart)": "Použít nastavení proxy serveru (vyžaduje restart)",
|
||||
"View": "Pohled",
|
||||
"View Shortcuts": "Zobrazit zástupce",
|
||||
"Undo": "Zpět",
|
||||
"Upload": "Nahrát",
|
||||
"Use system proxy settings (requires restart)": "Použít systémová nastavení proxy (vyžaduje opětovné spuštění programu)",
|
||||
"View": "Zobrazení",
|
||||
"View Shortcuts": "Zobrazit zkratky",
|
||||
"Window": "Okno",
|
||||
"Window Shortcuts": "Klávesové zkratky",
|
||||
"Window Shortcuts": "Zkratky pro okno",
|
||||
"YES": "ANO",
|
||||
"Zoom In": "Přiblížit",
|
||||
"Zoom Out": "Oddálit",
|
||||
"Zulip Help": "Nápověda Zulip",
|
||||
"Zulip Help": "Nápověda Zulipu",
|
||||
"keyboard shortcuts": "klávesové zkratky",
|
||||
"script": "skript"
|
||||
"script": "skript",
|
||||
"Quit when the window is closed": "Ukončit, když je okno zavřeno",
|
||||
"Ask where to save files before downloading": "Před stažením se zeptat kam uložit soubory",
|
||||
"Services": "Služby",
|
||||
"Hide": "Skrýt",
|
||||
"Hide Others": "Skrýt jiné",
|
||||
"Unhide": "Zobrazit",
|
||||
"AddServer": "Přidat server",
|
||||
"App language (requires restart)": "Jazyk programu (vyžaduje opětovné spuštění programu)",
|
||||
"Factory Reset Data": "Obnovení dat do továrního nastavení",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Obnovit program do výchozího nastavení. čili smazat všechny připojené organizace, účty a certifikáty.",
|
||||
"On macOS, the OS spellchecker is used.": "Na macOS se používá kontrola pravopisu OS.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Změnit jazyk v Nastavení systému → Klávesnice → Text → Kontrola pravopisu.",
|
||||
"Copy Link": "Kopírovat odkaz",
|
||||
"Copy Image": "Kopírovat obrázek",
|
||||
"Copy Image URL": "Kopírovat adresu (URL) obrázku",
|
||||
"No Suggestion Found": "Nenalezen žádný návrh",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "Pro kontrolu pravopisu můžete vybrat nejvíce 3 jazyky.",
|
||||
"Spellchecker Languages": "Kontrola pravopisu jazyků",
|
||||
"Add to Dictionary": "Přidat do slovníku",
|
||||
"Look Up": "Vyhledat"
|
||||
}
|
||||
|
||||
134
app/translations/da.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "Om Zulip",
|
||||
"Actual Size": "Faktisk størrelse",
|
||||
"Add Custom Certificates": "Tilføj egne certifikater",
|
||||
"Add Organization": "Opret organisation",
|
||||
"Add a Zulip organization": "Opret en Zulip organisation",
|
||||
"Add custom CSS": "Tilføj egen CSS",
|
||||
"Advanced": "Avanceret",
|
||||
"All the connected organizations will appear here": "Alle de tilsluttede organisationer vil blive vist her",
|
||||
"Always start minimized": "Start altid minimeret",
|
||||
"App Updates": "App-opdateringer",
|
||||
"Appearance": "Udseende",
|
||||
"Application Shortcuts": "Genveje",
|
||||
"Are you sure you want to disconnect this organization?": "Er du sikker på du vil frakoble denne organisation? ",
|
||||
"Auto hide Menu bar": "Skjul menu automatisk",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Skjul menu automatisk (tryk på Alt-tasten for at vise)",
|
||||
"Back": "Tilbage",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certifikat-fil",
|
||||
"Change": "Skift",
|
||||
"Check for Updates": "Tjek for opdateringer",
|
||||
"Close": "Luk",
|
||||
"Connect": "Tilslut",
|
||||
"Connect to another organization": "Forbind til en anden organisation",
|
||||
"Connected organizations": "Tilsluttede organisationer",
|
||||
"Copy": "Kopiér",
|
||||
"Copy Zulip URL": "Kopiér Zulip URL",
|
||||
"Create a new organization": "Opret ny organisation",
|
||||
"Cut": "Klip",
|
||||
"Default download location": "Default download placering",
|
||||
"Delete": "Slet",
|
||||
"Desktop App Settings": "Desktop app-indstillinger",
|
||||
"Desktop Notifications": "Desktop-notifikationer",
|
||||
"Desktop Settings": "Desktop-indstillinger",
|
||||
"Disconnect": "Frakobl",
|
||||
"Download App Logs": "Download app-logfiler",
|
||||
"Edit": "Redigér",
|
||||
"Edit Shortcuts": "Redigér genveje",
|
||||
"Enable auto updates": "Aktivér auto-opdateringer",
|
||||
"Enable error reporting (requires restart)": "Aktivér fejlrapportering (kræver genstart)",
|
||||
"Enable spellchecker (requires restart)": "Aktivér stavekontrol (kræver genstart)",
|
||||
"Factory Reset": "Nulstil til fabriksindstillinger",
|
||||
"File": "Fil",
|
||||
"Find accounts": "Find konti",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Funktionalitet",
|
||||
"General": "Generelt",
|
||||
"Get beta updates": "Få beta opdateringer",
|
||||
"Hard Reload": "Hård reload",
|
||||
"Help": "Hjælp",
|
||||
"Help Center": "Hjælpecenter",
|
||||
"History": "Historik",
|
||||
"History Shortcuts": "Historik genveje",
|
||||
"Keyboard Shortcuts": "Tastatur genveje",
|
||||
"Log Out": "Log ud",
|
||||
"Log Out of Organization": "Log ud af organisation",
|
||||
"Manual proxy configuration": "Manuel proxy opsætning",
|
||||
"Minimize": "Minimér",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NEJ",
|
||||
"Network": "Netværk",
|
||||
"OR": "ELLER",
|
||||
"Organization URL": "Organisation URL",
|
||||
"Organizations": "Organisationer",
|
||||
"Paste": "Indsæt",
|
||||
"Paste and Match Style": "Indsæt med samme formattering",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass regler",
|
||||
"Proxy rules": "Proxy regler",
|
||||
"Quit": "Luk",
|
||||
"Quit Zulip": "Luk Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,117 +1,134 @@
|
||||
{
|
||||
"About Zulip": "Über Zulip",
|
||||
"Actual Size": "Tatsächliche Größe",
|
||||
"Add Custom Certificates": "Benutzerdefinierte Zertifikate hinzufügen",
|
||||
"Add Custom Certificates": "Eigene Zertifikate hinzufügen",
|
||||
"Add Organization": "Organisation hinzufügen",
|
||||
"Add a Zulip organization": "Fügen Sie eine Zulip-Organisation hinzu",
|
||||
"Add custom CSS": "Fügen Sie benutzerdefiniertes CSS hinzu",
|
||||
"Advanced": "Fortgeschritten",
|
||||
"All the connected organizations will appear here": "Alle verbundenen Organisationen werden hier angezeigt",
|
||||
"Always start minimized": "Immer minimiert anfangen",
|
||||
"App Updates": "App-Updates",
|
||||
"Appearance": "Aussehen",
|
||||
"Application Shortcuts": "Anwendungsverknüpfungen",
|
||||
"Are you sure you want to disconnect this organization?": "Möchten Sie diese Organisation wirklich trennen?",
|
||||
"Auto hide Menu bar": "Menüleiste automatisch ausblenden",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Menüleiste automatisch ausblenden (Drücken Sie die Alt-Taste, um anzuzeigen)",
|
||||
"Add a Zulip organization": "Zulip-Organisation hinzufügen",
|
||||
"Add custom CSS": "Eigenes CSS hinzufügen",
|
||||
"Advanced": "Erweitert",
|
||||
"All the connected organizations will appear here": "Alle verbundenen Organisationen erscheinen hier",
|
||||
"Always start minimized": "Immer minimiert öffnen",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Erscheinungsbild",
|
||||
"Application Shortcuts": "App-Verknüpfungen",
|
||||
"Are you sure you want to disconnect this organization?": "Bist du dir sicher, dass du die Verbindung zur Organisation trennen möchtest?",
|
||||
"Auto hide Menu bar": "Menü automatisch verstecken",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Menü automatisch verstecken (zum Anzeigen die Alt-Taste drücken)",
|
||||
"Back": "Zurück",
|
||||
"Bounce dock on new private message": "Bounce-Dock für neue private Nachricht",
|
||||
"Bounce dock on new private message": "Im Dock hüpfen, wenn neue private Nachrichten eingehen",
|
||||
"Certificate file": "Zertifikatsdatei",
|
||||
"Change": "Veränderung",
|
||||
"Change": "Ändern",
|
||||
"Check for Updates": "Auf Updates prüfen",
|
||||
"Close": "Schließen",
|
||||
"Connect": "Verbinden",
|
||||
"Connect to another organization": "Stellen Sie eine Verbindung zu einer anderen Organisation her",
|
||||
"Connect to another organization": "Mit einer anderen Organisation verbinden",
|
||||
"Connected organizations": "Verbundene Organisationen",
|
||||
"Copy": "Kopieren",
|
||||
"Copy Zulip URL": "Zulip-URL kopieren",
|
||||
"Create a new organization": "Erstellen Sie eine neue Organisation",
|
||||
"Cut": "Schnitt",
|
||||
"Default download location": "Standard-Download-Speicherort",
|
||||
"Create a new organization": "Eine neue Organisation erstellen",
|
||||
"Cut": "Ausschneiden",
|
||||
"Default download location": "Voreingestelltes Ziel für Downloads",
|
||||
"Delete": "Löschen",
|
||||
"Desktop App Settings": "Desktop App-Einstellungen",
|
||||
"Desktop Notifications": "Desktop-Benachrichtigungen",
|
||||
"Desktop App Settings": "Einstellungen für Desktop-App",
|
||||
"Desktop Notifications": "Desktopbenachrichtigungen",
|
||||
"Desktop Settings": "Desktop-Einstellungen",
|
||||
"Disconnect": "Trennen",
|
||||
"Download App Logs": "App-Protokolle herunterladen",
|
||||
"Disconnect": "Verbindung trennen",
|
||||
"Download App Logs": "Logdateien der App herunterladen",
|
||||
"Edit": "Bearbeiten",
|
||||
"Edit Shortcuts": "Verknüpfungen bearbeiten",
|
||||
"Enable auto updates": "Automatische Updates aktivieren",
|
||||
"Enable error reporting (requires restart)": "Fehlerberichterstattung aktivieren (Neustart erforderlich)",
|
||||
"Enable spellchecker (requires restart)": "Rechtschreibprüfung aktivieren (Neustart erforderlich)",
|
||||
"Factory Reset": "Werkseinstellungen zurückgesetzt",
|
||||
"Edit Shortcuts": "Tastenkürzel bearbeiten",
|
||||
"Enable auto updates": "Automatisch aktualisieren",
|
||||
"Enable error reporting (requires restart)": "Fehlerberichte aktivieren (erfordert Neustart)",
|
||||
"Enable spellchecker (requires restart)": "Rechtschreibprüfung aktivieren (erfordert Neustart)",
|
||||
"Factory Reset": "Alle Einstellungen auf Standardwerte zurücksetzen",
|
||||
"File": "Datei",
|
||||
"Find accounts": "Konten suchen",
|
||||
"Find accounts by email": "Finden Sie Konten per E-Mail",
|
||||
"Flash taskbar on new message": "Flash-Taskleiste bei neuer Nachricht",
|
||||
"Forward": "Nach vorne",
|
||||
"Find accounts": "Accounts finden",
|
||||
"Find accounts by email": "Accounts anhand E-Mail-Adresse finden",
|
||||
"Flash taskbar on new message": "Farbliche Hervorhebung in Taskbar bei neuen Nachrichten",
|
||||
"Forward": "Weiter",
|
||||
"Functionality": "Funktionalität",
|
||||
"General": "Allgemeines",
|
||||
"Get beta updates": "Erhalten Sie Beta-Updates",
|
||||
"Hard Reload": "Festes Nachladen",
|
||||
"General": "Allgemein",
|
||||
"Get beta updates": "Auf Betaversionen aktualisieren",
|
||||
"Hard Reload": "Komplett neu laden",
|
||||
"Help": "Hilfe",
|
||||
"Help Center": "Hilfezentrum",
|
||||
"History": "Geschichte",
|
||||
"History Shortcuts": "Verlaufsverknüpfungen",
|
||||
"Keyboard Shortcuts": "Tastatürkürzel",
|
||||
"Log Out": "Ausloggen",
|
||||
"Log Out of Organization": "Aus Organisation ausloggen",
|
||||
"Help Center": "Hilfe-Zentrum",
|
||||
"History": "Verlauf",
|
||||
"History Shortcuts": "Kurzbefehle für Verlauf",
|
||||
"Keyboard Shortcuts": "Tastenkürzel",
|
||||
"Log Out": "Abmelden",
|
||||
"Log Out of Organization": "Von Organisation abmelden",
|
||||
"Manual proxy configuration": "Manuelle Proxy-Konfiguration",
|
||||
"Minimize": "Minimieren",
|
||||
"Mute all sounds from Zulip": "Schaltet alle Sounds von Zulip stumm",
|
||||
"Mute all sounds from Zulip": "Alle Zulip-Klänge stummschalten",
|
||||
"NO": "NEIN",
|
||||
"Network": "Netzwerk",
|
||||
"OR": "ODER",
|
||||
"Organization URL": "Organisations-URL",
|
||||
"Organization URL": "URL der Organisation",
|
||||
"Organizations": "Organisationen",
|
||||
"Paste": "Einfügen",
|
||||
"Paste and Match Style": "Einfügen und Format anpassen",
|
||||
"Paste and Match Style": "Ohne Formatierung einfügen",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy-Umgehungsregeln",
|
||||
"Proxy bypass rules": "Proxy-Ausnahmen",
|
||||
"Proxy rules": "Proxy-Regeln",
|
||||
"Quit": "Verlassen",
|
||||
"Quit Zulip": "Beenden Sie Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Versionshinweise",
|
||||
"Quit": "Beenden",
|
||||
"Quit Zulip": "Zulip beenden",
|
||||
"Redo": "Wiederholen",
|
||||
"Release Notes": "Hinweise zur Versionsfreigabe",
|
||||
"Reload": "Neu laden",
|
||||
"Report an Issue": "Ein Problem melden",
|
||||
"Reset App Data": "App-Daten zurücksetzen",
|
||||
"Reset App Settings": "App-Einstellungen zurücksetzen",
|
||||
"Reset Application Data": "Anwendungsdaten zurücksetzen",
|
||||
"Save": "sparen",
|
||||
"Select All": "Wählen Sie Alle",
|
||||
"Settings": "die Einstellungen",
|
||||
"Shortcuts": "Verknüpfungen",
|
||||
"Show App Logs": "App-Protokolle anzeigen",
|
||||
"Show app icon in system tray": "App-Symbol in der Taskleiste anzeigen",
|
||||
"Show app unread badge": "Zeige App ungelesenen Badge",
|
||||
"Show desktop notifications": "Desktop-Benachrichtigungen anzeigen",
|
||||
"Show downloaded files in file manager": "Heruntergeladene Dateien im Dateimanager anzeigen",
|
||||
"Save": "Speichern",
|
||||
"Select All": "Alles auswählen",
|
||||
"Settings": "Einstellungen",
|
||||
"Shortcuts": "Kurzbefehle",
|
||||
"Show App Logs": "Logdateien der App anzeigen",
|
||||
"Show app icon in system tray": "App-Icon in Systemleiste anzeigen",
|
||||
"Show app unread badge": "Anzahl ungelesener Nachrichten in App-Icon einblenden",
|
||||
"Show desktop notifications": "Desktopbenachrichtigungen anzeigen",
|
||||
"Show downloaded files in file manager": "Heruntergeladene Dateien in Dateimanager anzeigen",
|
||||
"Show sidebar": "Seitenleiste anzeigen",
|
||||
"Start app at login": "App beim Login starten",
|
||||
"Switch to Next Organization": "Wechseln Sie zur nächsten Organisation",
|
||||
"Switch to Previous Organization": "Zur vorherigen Organisation wechseln",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Diese Desktop-App-Verknüpfungen erweitern die Zulip-Webanwendungen",
|
||||
"This will delete all application data including all added accounts and preferences": "Dadurch werden alle Anwendungsdaten einschließlich aller hinzugefügten Konten und Einstellungen gelöscht",
|
||||
"Tip": "Spitze",
|
||||
"Toggle DevTools for Active Tab": "DevTools für aktive Registerkarte umschalten",
|
||||
"Toggle DevTools for Zulip App": "DevTools für Zulip App umschalten",
|
||||
"Toggle Do Not Disturb": "Nicht stören umschalten",
|
||||
"Toggle Full Screen": "Vollbild umschalten",
|
||||
"Start app at login": "App beim Login automatisch starten",
|
||||
"Switch to Next Organization": "Zur nächsten Organisation wechseln",
|
||||
"Switch to Previous Organization": "Zur vorhergehenden Organisation wechseln",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Dies sind zusätzliche Kurzbefehle in der Desktop-App gegenüber der Web-App",
|
||||
"This will delete all application data including all added accounts and preferences": "Hiermit werden alle Anwendungsdaten einschließlich aller Accounts und Einstellungen gelöscht",
|
||||
"Tip": "Tipp",
|
||||
"Toggle DevTools for Active Tab": "Entwickler-Tools für aktiven Tab umschalten",
|
||||
"Toggle DevTools for Zulip App": "Entwickler-Tools für Zulip-App umschalten",
|
||||
"Toggle Do Not Disturb": "Nicht-Stören-Modus umschalten",
|
||||
"Toggle Full Screen": "Vollbildschirm umschalten",
|
||||
"Toggle Sidebar": "Seitenleiste umschalten",
|
||||
"Toggle Tray Icon": "Taskleistensymbol umschalten",
|
||||
"Tools": "Werkzeuge",
|
||||
"Undo": "Rückgängig machen",
|
||||
"Toggle Tray Icon": "Tray-Icon umschalten",
|
||||
"Tools": "Extras",
|
||||
"Undo": "Rückgängig",
|
||||
"Upload": "Hochladen",
|
||||
"Use system proxy settings (requires restart)": "System-Proxy-Einstellungen verwenden (Neustart erforderlich)",
|
||||
"View": "Aussicht",
|
||||
"View Shortcuts": "Verknüpfungen anzeigen",
|
||||
"Use system proxy settings (requires restart)": "Systemweite Proxy-Einstellungen verwenden (erfordert Neustart)",
|
||||
"View": "Ansicht",
|
||||
"View Shortcuts": "Tastenkürzel anzeigen",
|
||||
"Window": "Fenster",
|
||||
"Window Shortcuts": "Fensterverknüpfungen",
|
||||
"Window Shortcuts": "Kurzbefehle für Fenster",
|
||||
"YES": "JA",
|
||||
"Zoom In": "Hineinzoomen",
|
||||
"Zoom Out": "Rauszoomen",
|
||||
"Zulip Help": "Zulip-Hilfe",
|
||||
"keyboard shortcuts": "Tastatürkürzel",
|
||||
"script": "Skript"
|
||||
"Zoom In": "Vergrößern",
|
||||
"Zoom Out": "Verkleinern",
|
||||
"Zulip Help": "Hilfe zu Zulip",
|
||||
"keyboard shortcuts": "Tastenkürzel",
|
||||
"script": "Skript",
|
||||
"Quit when the window is closed": "Beim Schließen des Fensters beenden",
|
||||
"Ask where to save files before downloading": "Fragen, wo heruntergeladene Dateien gespeichert werden sollen",
|
||||
"Services": "Dienste",
|
||||
"Hide": "Verbergen",
|
||||
"Hide Others": "Andere verbergen",
|
||||
"Unhide": "Nicht mehr verbergen",
|
||||
"AddServer": "ServerHinzufügen",
|
||||
"App language (requires restart)": "Sprache der App (benötigt Neustart)",
|
||||
"Factory Reset Data": "Auf Werkseinstellung zurücksetzen",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Die App wird zurückgesetzt, somit werden alle verbundenen Organisationen, Konten und Zertifikate gelöscht.",
|
||||
"On macOS, the OS spellchecker is used.": "In macOS wird die OS Rechtschreibprüfung verwendet.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Ändere die Spracheinstellung über Systemeinstellungen → Tastatur → Text → Rechtschreibung.",
|
||||
"Copy Link": "Link kopieren",
|
||||
"Copy Image": "Bild kopieren",
|
||||
"Copy Image URL": "Bild-URL kopieren",
|
||||
"No Suggestion Found": "Keine Vorschläge gefunden",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "Du kannst höchstens 3 Sprachen für die Rechtschreibprüfung auswählen.",
|
||||
"Spellchecker Languages": "Sprachen für die Rechtschreibprüfung",
|
||||
"Add to Dictionary": "Zum Wörterbuch hinzufügen",
|
||||
"Look Up": "Nachschlagen"
|
||||
}
|
||||
|
||||
@@ -1,119 +1,134 @@
|
||||
{
|
||||
"File": "File",
|
||||
"About Zulip": "About Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organization",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Minimize": "Minimize",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Close",
|
||||
"Quit": "Quit",
|
||||
"Edit": "Edit",
|
||||
"Undo": "Undo",
|
||||
"Redo": "Redo",
|
||||
"Cut": "Cut",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Copy",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Delete",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Edit",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "File",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organization URL",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Select All": "Select All",
|
||||
"View": "View",
|
||||
"Reload": "Reload",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Actual Size": "Actual Size",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"History": "History",
|
||||
"Back": "Back",
|
||||
"Forward": "Forward",
|
||||
"Window": "Window",
|
||||
"Tools": "Tools",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Help": "Help",
|
||||
"About Zulip": "About Zulip",
|
||||
"Help Center": "Help Center",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"General": "General",
|
||||
"Network": "Network",
|
||||
"AddServer": "AddServer",
|
||||
"Organizations": "Organizations",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Appearance": "Appearance",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"App Updates": "App Updates",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Functionality": "Functionality",
|
||||
"Start app at login": "Start app at login",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Advanced": "Advanced",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Upload": "Upload",
|
||||
"Delete": "Delete",
|
||||
"Default download location": "Default download location",
|
||||
"Change": "Change",
|
||||
"Reset Application Data": "Reset Application Data",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Reset App Data": "Reset App Data",
|
||||
"Proxy": "Proxy",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"script": "script",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Save": "Save",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"All the connected orgnizations will appear here.": "All the connected orgnizations will appear here.",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"All the connected orgnizations will appear here": "All the connected orgnizations will appear here",
|
||||
"Disconnect": "Disconnect",
|
||||
"Organization URL": "Organization URL",
|
||||
"Certificate file": "Certificate file",
|
||||
"Find accounts": "Find accounts",
|
||||
"Tip": "Tip",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Settings": "Settings",
|
||||
"Log Out": "Log Out",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Force social login in app instead of browser": "Force social login in app instead of browser",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Connect": "Connect",
|
||||
"OR": "OR",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Network and Proxy Settings": "Network and Proxy Settings",
|
||||
"YES": "YES",
|
||||
"NO": "NO",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?"
|
||||
}
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,122 +1,134 @@
|
||||
{
|
||||
"About Zulip": "About Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organization",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Close",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Copy",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Delete",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Edit",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "File",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organization URL",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"Minimize": "Minimize",
|
||||
"Close": "Close",
|
||||
"Quit": "Quit",
|
||||
"Edit": "Edit",
|
||||
"Undo": "Undo",
|
||||
"Redo": "Redo",
|
||||
"Cut": "Cut",
|
||||
"Copy": "Copy",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Select All": "Select All",
|
||||
"View": "View",
|
||||
"Reload": "Reload",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Actual Size": "Actual Size",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"History": "History",
|
||||
"Back": "Back",
|
||||
"Forward": "Forward",
|
||||
"Window": "Window",
|
||||
"Tools": "Tools",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Release Notes": "Release Notes",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Help": "Help",
|
||||
"About Zulip": "About Zulip",
|
||||
"Help Center": "Help Center",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"General": "General",
|
||||
"Network": "Network",
|
||||
"AddServer": "AddServer",
|
||||
"Organizations": "Organizations",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Settings": "Settings",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Organization URL": "Organization URL",
|
||||
"Connect": "Connect",
|
||||
"OR": "OR",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Proxy": "Proxy",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"script": "script",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Save": "Save",
|
||||
"Appearance": "Appearance",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"App Updates": "App Updates",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Functionality": "Functionality",
|
||||
"Start app at login": "Start app at login",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Advanced": "Advanced",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Upload": "Upload",
|
||||
"Delete": "Delete",
|
||||
"Default download location": "Default download location",
|
||||
"Change": "Change",
|
||||
"Reset Application Data": "Reset Application Data",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Reset App Data": "Reset App Data",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"All the connected orgnizations will appear here.": "All the connected orgnizations will appear here.",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"All the connected orgnizations will appear here": "All the connected orgnizations will appear here",
|
||||
"Disconnect": "Disconnect",
|
||||
"Certificate file": "Certificate file",
|
||||
"Find accounts": "Find accounts",
|
||||
"Tip": "Tip",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Reset App Settings": "Reset App Settings",
|
||||
"Log Out": "Log Out",
|
||||
"Hide Zulip": "Hide Zulip",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Emoji & Symbols": "Emoji & Symbols",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Enter Full Screen": "Enter Full Screen",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"File": "File",
|
||||
"Network and Proxy Settings": "Network and Proxy Settings",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading"
|
||||
}
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
134
app/translations/en_GB.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "About Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organisation",
|
||||
"Add a Zulip organization": "Add a Zulip organisation",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organisations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organisation?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Close",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organisation",
|
||||
"Connected organizations": "Connected organisations",
|
||||
"Copy": "Copy",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Create a new organisation",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Delete",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Edit",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "File",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organisation",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organisation URL",
|
||||
"Organizations": "Organisations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organisation",
|
||||
"Switch to Previous Organization": "Switch to Previous Organisation",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organisations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,117 +1,134 @@
|
||||
{
|
||||
"About Zulip": "Acerca de Zulip",
|
||||
"Actual Size": "Tamaño real",
|
||||
"Actual Size": "Tamaño actual",
|
||||
"Add Custom Certificates": "Añadir certificados personalizados",
|
||||
"Add Organization": "Añadir organización",
|
||||
"Add a Zulip organization": "Añadir una organización Zulip",
|
||||
"Add a Zulip organization": "Añadir una organización de Zulip",
|
||||
"Add custom CSS": "Añadir CSS personalizado",
|
||||
"Advanced": "Avanzado",
|
||||
"All the connected organizations will appear here": "Todas las organizaciones conectadas aparecerán aquí.",
|
||||
"Always start minimized": "Siempre empezar minimizado",
|
||||
"All the connected organizations will appear here": "Todas las organizaciones conectadas aparecerán aquí",
|
||||
"Always start minimized": "Iniciar siempre minimizado",
|
||||
"App Updates": "Actualizaciones de la aplicación",
|
||||
"Appearance": "Apariencia",
|
||||
"Application Shortcuts": "Atajos de aplicación",
|
||||
"Are you sure you want to disconnect this organization?": "¿Estás seguro de que quieres desconectar esta organización?",
|
||||
"Auto hide Menu bar": "Ocultar automáticamente la barra de menú",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Ocultar automáticamente la barra de menú (presionar la tecla Alt para mostrar)",
|
||||
"Back": "Espalda",
|
||||
"Bounce dock on new private message": "Bounce dock en nuevo mensaje privado",
|
||||
"Application Shortcuts": "Atajos de la aplicación",
|
||||
"Are you sure you want to disconnect this organization?": "Estas seguro de desconectar esta organización?",
|
||||
"Auto hide Menu bar": "Ocultar la barra de menú automáticamente",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Ocultar la barra de menú automáticamente (mantén tecla Alt para mostrar)",
|
||||
"Back": "Atrás",
|
||||
"Bounce dock on new private message": "Rebotar dock cuando se reciba un nuevo mensaje privado",
|
||||
"Certificate file": "Archivo de certificado",
|
||||
"Change": "Cambio",
|
||||
"Check for Updates": "Buscar actualizaciones",
|
||||
"Change": "Cambiar",
|
||||
"Check for Updates": "Comprobar actualizaciones",
|
||||
"Close": "Cerrar",
|
||||
"Connect": "Conectar",
|
||||
"Connect to another organization": "Conectarse a otra organización",
|
||||
"Connected organizations": "Organizaciones conectadas",
|
||||
"Copy": "Dupdo",
|
||||
"Connect to another organization": "Conectar a otra organización",
|
||||
"Connected organizations": "Organizaciones conectada",
|
||||
"Copy": "Copiar",
|
||||
"Copy Zulip URL": "Copiar URL de Zulip",
|
||||
"Create a new organization": "Crear una nueva organización",
|
||||
"Cut": "Cortar",
|
||||
"Default download location": "Ubicación de descarga predeterminada",
|
||||
"Delete": "Borrar",
|
||||
"Desktop App Settings": "Configuración de la aplicación de escritorio",
|
||||
"Default download location": "Ubicación por defecto de descargas",
|
||||
"Delete": "Eliminar",
|
||||
"Desktop App Settings": "Ajustes de la aplicación de escritorio",
|
||||
"Desktop Notifications": "Notificaciones de escritorio",
|
||||
"Desktop Settings": "Configuraciones de escritorio",
|
||||
"Desktop Settings": "Ajustes de escritorio",
|
||||
"Disconnect": "Desconectar",
|
||||
"Download App Logs": "Descargar App Logs",
|
||||
"Download App Logs": "Descargar registros de la aplicación",
|
||||
"Edit": "Editar",
|
||||
"Edit Shortcuts": "Editar accesos directos",
|
||||
"Enable auto updates": "Habilitar actualizaciones automáticas",
|
||||
"Enable error reporting (requires restart)": "Habilitar informes de errores (requiere reinicio)",
|
||||
"Enable spellchecker (requires restart)": "Habilitar el corrector ortográfico (requiere reinicio)",
|
||||
"Factory Reset": "Restablecimiento de fábrica",
|
||||
"File": "Expediente",
|
||||
"Edit Shortcuts": "Editar atajos",
|
||||
"Enable auto updates": "Activar actualizaciones automáticas",
|
||||
"Enable error reporting (requires restart)": "Activar reporte de fallos (necesita reinicio)",
|
||||
"Enable spellchecker (requires restart)": "Activar corrector ortográfico (necesita reinicio)",
|
||||
"Factory Reset": "Reinicio de fábrica",
|
||||
"File": "Archivo",
|
||||
"Find accounts": "Encontrar cuentas",
|
||||
"Find accounts by email": "Encuentra cuentas por correo electrónico",
|
||||
"Flash taskbar on new message": "Flash barra de tareas en nuevo mensaje",
|
||||
"Forward": "Adelante",
|
||||
"Find accounts by email": "Encontrar cuentas por correo electrónico",
|
||||
"Flash taskbar on new message": "Hacer que la barra de tareas parpadee cuando se reciba un mensaje nuevo",
|
||||
"Forward": "Reenviar",
|
||||
"Functionality": "Funcionalidad",
|
||||
"General": "General",
|
||||
"Get beta updates": "Recibe actualizaciones beta",
|
||||
"Hard Reload": "Recarga dura",
|
||||
"Get beta updates": "Obtener actualizaciones beta",
|
||||
"Hard Reload": "Recarga forzosa",
|
||||
"Help": "Ayuda",
|
||||
"Help Center": "Centro de ayuda",
|
||||
"History": "Historia",
|
||||
"History Shortcuts": "Atajos de historia",
|
||||
"History": "Historial",
|
||||
"History Shortcuts": "Atajos del historial",
|
||||
"Keyboard Shortcuts": "Atajos de teclado",
|
||||
"Log Out": "Cerrar sesión",
|
||||
"Log Out of Organization": "Salir de la organización",
|
||||
"Log Out of Organization": "Cerrar sesión de organización",
|
||||
"Manual proxy configuration": "Configuración de proxy manual",
|
||||
"Minimize": "Minimizar",
|
||||
"Mute all sounds from Zulip": "Silencia todos los sonidos de Zulip",
|
||||
"Mute all sounds from Zulip": "Silenciar todos los sonidos de Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Red",
|
||||
"OR": "O",
|
||||
"Organization URL": "URL de la organización",
|
||||
"Organizations": "Organizaciones",
|
||||
"Paste": "Pegar",
|
||||
"Paste and Match Style": "Pegar y combinar estilo",
|
||||
"Proxy": "Apoderado",
|
||||
"Proxy bypass rules": "Reglas de omisión de proxy",
|
||||
"Proxy rules": "Reglas de proxy",
|
||||
"Quit": "Dejar",
|
||||
"Quit Zulip": "Dejar Zulip",
|
||||
"Paste and Match Style": "Pegar y mantener estilo",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Reglas para ignorar proxy",
|
||||
"Proxy rules": "Reglas del proxy",
|
||||
"Quit": "Cerrar",
|
||||
"Quit Zulip": "Cerrar Zulip",
|
||||
"Redo": "Rehacer",
|
||||
"Release Notes": "Notas de lanzamiento",
|
||||
"Release Notes": "Notas de la versión",
|
||||
"Reload": "Recargar",
|
||||
"Report an Issue": "Reportar un problema",
|
||||
"Reset App Data": "Restablecer datos de la aplicación",
|
||||
"Reset App Settings": "Restablecer la configuración de la aplicación",
|
||||
"Reset Application Data": "Restablecer datos de aplicación",
|
||||
"Save": "Salvar",
|
||||
"Report an Issue": "Informar de un error",
|
||||
"Save": "Guardar",
|
||||
"Select All": "Seleccionar todo",
|
||||
"Settings": "Ajustes",
|
||||
"Shortcuts": "Atajos",
|
||||
"Show App Logs": "Mostrar registros de aplicaciones",
|
||||
"Show app icon in system tray": "Mostrar icono de la aplicación en la bandeja del sistema",
|
||||
"Show app unread badge": "Mostrar la aplicación de placa sin leer",
|
||||
"Shortcuts": "Atajos de teclado",
|
||||
"Show App Logs": "Mostrar registros de la aplicación",
|
||||
"Show app icon in system tray": "Mostrar un icono de la aplicación en la bandeja del sistema",
|
||||
"Show app unread badge": "Mostrar un globo en el icono si hay mensajes sin leer",
|
||||
"Show desktop notifications": "Mostrar notificaciones de escritorio",
|
||||
"Show downloaded files in file manager": "Mostrar los archivos descargados en el administrador de archivos",
|
||||
"Show downloaded files in file manager": "Mostrar archivos descargados en el explorador",
|
||||
"Show sidebar": "Mostrar barra lateral",
|
||||
"Start app at login": "Iniciar la aplicación al iniciar sesión",
|
||||
"Start app at login": "Lanzar aplicación al inicio",
|
||||
"Switch to Next Organization": "Cambiar a la siguiente organización",
|
||||
"Switch to Previous Organization": "Cambiar a la organización anterior",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Estos accesos directos de aplicaciones de escritorio extienden las aplicaciones web de Zulip.",
|
||||
"This will delete all application data including all added accounts and preferences": "Esto eliminará todos los datos de la aplicación, incluidas todas las cuentas y preferencias agregadas.",
|
||||
"Tip": "Propina",
|
||||
"Toggle DevTools for Active Tab": "Alternar DevTools para Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Alternar DevTools para Zulip App",
|
||||
"Toggle Do Not Disturb": "Alternar No molestar",
|
||||
"Toggle Full Screen": "Alternar pantalla completa",
|
||||
"Toggle Sidebar": "Alternar barra lateral",
|
||||
"Toggle Tray Icon": "Icono de bandeja de palanca",
|
||||
"Switch to Previous Organization": "Cambiar a la anterior organización",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Estos atajos de la aplicación de escritorio extienden los ya existentes en Zulip",
|
||||
"This will delete all application data including all added accounts and preferences": "Esto borrará todos los datos de la aplicación, incluyendo cuentas añadidas y preferencia",
|
||||
"Tip": "Consej",
|
||||
"Toggle DevTools for Active Tab": "Activar/desactivar herramientas de desarrollador para la pestaña activa",
|
||||
"Toggle DevTools for Zulip App": "Activar/desactivar herramientas de desarrollador para la aplicación de Zulip",
|
||||
"Toggle Do Not Disturb": "Activar/desactivar no molestar",
|
||||
"Toggle Full Screen": "Activar/desactivar pantalla completa",
|
||||
"Toggle Sidebar": "Activar/desactivar barra lateral",
|
||||
"Toggle Tray Icon": "Activar/desactivar icono en bandeja del sistema",
|
||||
"Tools": "Herramientas",
|
||||
"Undo": "Deshacer",
|
||||
"Upload": "Subir",
|
||||
"Use system proxy settings (requires restart)": "Usar la configuración del proxy del sistema (requiere reinicio)",
|
||||
"Use system proxy settings (requires restart)": "Usar ajustes de proxy del sistema (necesita reinicio)",
|
||||
"View": "Ver",
|
||||
"View Shortcuts": "Ver accesos directos",
|
||||
"View Shortcuts": "Ver atajos",
|
||||
"Window": "Ventana",
|
||||
"Window Shortcuts": "Atajos de ventana",
|
||||
"YES": "SÍ",
|
||||
"Zoom In": "Acercarse",
|
||||
"Zoom Out": "Disminuir el zoom",
|
||||
"Zulip Help": "Ayuda de Zulip",
|
||||
"Zoom In": "Aumentar zoom",
|
||||
"Zoom Out": "Reducir zoom",
|
||||
"Zulip Help": "Ayuda sobre Zulip",
|
||||
"keyboard shortcuts": "atajos de teclado",
|
||||
"script": "guión"
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Salir cuando la ventana se cierre",
|
||||
"Ask where to save files before downloading": "Preguntar dónde guardar los archivos antes de descargar",
|
||||
"Services": "Servicios",
|
||||
"Hide": "Ocultar",
|
||||
"Hide Others": "Ocultar otros",
|
||||
"Unhide": "Dejar de ocultar",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "Idioma de la aplicación (requiere reinicio)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reinicia la aplicación, borrando todas las organizaciones, cuentas y certificados conectados.",
|
||||
"On macOS, the OS spellchecker is used.": "En macOS se utiliza la verificación ortográfica del sistema operativo.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Modifica el idioma en Preferencias del sistema → Teclado → Texto → Ortografía.",
|
||||
"Copy Link": "Copiar enlace",
|
||||
"Copy Image": "Copiar imagen",
|
||||
"Copy Image URL": "Copiar URL de la imagen",
|
||||
"No Suggestion Found": "No se encontró ninguna sugerencia",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "Puedes elegir un máximo de 3 idiomas para la verificación ortográfica.",
|
||||
"Spellchecker Languages": "Idiomas de verificación ortográfica",
|
||||
"Add to Dictionary": "Añadir al diccionario",
|
||||
"Look Up": "Consultar"
|
||||
}
|
||||
|
||||
134
app/translations/fa.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "درباره Zulip ",
|
||||
"Actual Size": "اندازه واقعی",
|
||||
"Add Custom Certificates": "اضافه کردن مجوز دلخواه",
|
||||
"Add Organization": "اضافه کردن سازمان",
|
||||
"Add a Zulip organization": "اضافه کردن سازمان Zulip",
|
||||
"Add custom CSS": "اضافه کردن CSS دلخواه",
|
||||
"Advanced": "پیشرفته",
|
||||
"All the connected organizations will appear here": "همه سازمانهای متصل شده اینجا نمایش داده میشوند",
|
||||
"Always start minimized": "همواره به صورت کوچک شده اجرا شو",
|
||||
"App Updates": "بهروزرسانیهای برنامه",
|
||||
"Appearance": "شمایل",
|
||||
"Application Shortcuts": "میانبرهای برنامه",
|
||||
"Are you sure you want to disconnect this organization?": "آیا از قطع ارتباط از سازمان اطمینان دارید؟",
|
||||
"Auto hide Menu bar": "مخفیسازی خودکار نوار منو",
|
||||
"Auto hide menu bar (Press Alt key to display)": "مخفیسازی خودکار نوار منو (برای نمایش دکمه Alt را بزنید)",
|
||||
"Back": "عقب",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "فایل مجوز",
|
||||
"Change": "تغییر دادن",
|
||||
"Check for Updates": "بررسی برای بهروزرسانی",
|
||||
"Close": "بستن",
|
||||
"Connect": "اتصال",
|
||||
"Connect to another organization": "اتصال به یک سازمان دیگر",
|
||||
"Connected organizations": "سازمانهای وصل شده",
|
||||
"Copy": "رونوشت",
|
||||
"Copy Zulip URL": "رونوشت از Zulip URL",
|
||||
"Create a new organization": "ایجاد سازمان جدید",
|
||||
"Cut": "بریدن",
|
||||
"Default download location": "محل پیشفرض دانلود",
|
||||
"Delete": "حذف",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "اطلاعرسانیهای دسکتاپ",
|
||||
"Desktop Settings": "تنظیمات دسکتاپ",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "ویرایش",
|
||||
"Edit Shortcuts": "ویرایش میانبرها",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "فایل",
|
||||
"Find accounts": "پیدا کردن حساب های کاربری ",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "عمومی",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "کمک",
|
||||
"Help Center": "مرکز کمک",
|
||||
"History": "تاریخچه ",
|
||||
"History Shortcuts": "تاریخچه میانبرها",
|
||||
"Keyboard Shortcuts": "میانبرهای صفحهکلید",
|
||||
"Log Out": "خروج",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "یا",
|
||||
"Organization URL": "URL سازمان",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "ذخیره",
|
||||
"Select All": "Select All",
|
||||
"Settings": "تنظیمات",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
134
app/translations/fi.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "Tietoa Zulipista",
|
||||
"Actual Size": "Varsinainen koko",
|
||||
"Add Custom Certificates": "Lisää omia sertifikaatteja",
|
||||
"Add Organization": "Lisää organisaatio",
|
||||
"Add a Zulip organization": "Lisää Zulip-organisaatio",
|
||||
"Add custom CSS": "Lisää oma CSS",
|
||||
"Advanced": "Edistynyt",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Aloita aina pienennettynä",
|
||||
"App Updates": "Sovellspäivitykset",
|
||||
"Appearance": "Ulkonäkö",
|
||||
"Application Shortcuts": "Sovellusoikotiet",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Muuta",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Sulje",
|
||||
"Connect": "Yhdistä",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Kopioi",
|
||||
"Copy Zulip URL": "Kopioi Zulip-URL",
|
||||
"Create a new organization": "Luo uusi organisaatio",
|
||||
"Cut": "Leikkaa",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Poista",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Katkaise",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Muokkaa",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "Tiedosto",
|
||||
"Find accounts": "Löydä tilit",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Ohje",
|
||||
"Help Center": "Tukikeskus",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "EI",
|
||||
"Network": "Network",
|
||||
"OR": "TAI",
|
||||
"Organization URL": "Organisaation URL",
|
||||
"Organizations": "Organisaatiot",
|
||||
"Paste": "Liitä",
|
||||
"Paste and Match Style": "Liitä ja täsmää tyylit",
|
||||
"Proxy": "Välipalvelin",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Lopeta",
|
||||
"Quit Zulip": "Lopeta Zulip",
|
||||
"Redo": "Toista",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Lataa uudelleen",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Tallenna",
|
||||
"Select All": "Valitse kaikki",
|
||||
"Settings": "Asetukset",
|
||||
"Shortcuts": "Oikopolut",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Vinkki",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Työkalut",
|
||||
"Undo": "Peru",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "Näytä",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Ikkuna",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "KYLLÄ",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -1,117 +1,134 @@
|
||||
{
|
||||
"About Zulip": "À propos de Zulip",
|
||||
"Actual Size": "Taille actuelle",
|
||||
"Add Custom Certificates": "Ajouter des certificats personnalisés",
|
||||
"Add Custom Certificates": "Ajouter un certificat spécifique",
|
||||
"Add Organization": "Ajouter une organisation",
|
||||
"Add a Zulip organization": "Ajouter une organisation Zulip",
|
||||
"Add custom CSS": "Ajouter un CSS personnalisé",
|
||||
"Advanced": "Avancée",
|
||||
"Add custom CSS": "Ajouter un CSS spécifique",
|
||||
"Advanced": "Avancé",
|
||||
"All the connected organizations will appear here": "Toutes les organisations connectées apparaîtront ici",
|
||||
"Always start minimized": "Toujours commencer minimisé",
|
||||
"App Updates": "Mises à jour de l'application",
|
||||
"Always start minimized": "Toujours démarrer minimisé",
|
||||
"App Updates": "Mise à jour de l'application",
|
||||
"Appearance": "Apparence",
|
||||
"Application Shortcuts": "Raccourcis d'application",
|
||||
"Are you sure you want to disconnect this organization?": "Êtes-vous sûr de vouloir déconnecter cette organisation?",
|
||||
"Auto hide Menu bar": "Masquer automatiquement la barre de menus",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Masquer automatiquement la barre de menu (appuyez sur la touche Alt pour afficher)",
|
||||
"Back": "Retour",
|
||||
"Bounce dock on new private message": "Bounce Dock sur un nouveau message privé",
|
||||
"Certificate file": "Dossier de certificat",
|
||||
"Change": "Changement",
|
||||
"Application Shortcuts": "Raccourcis de l'application",
|
||||
"Are you sure you want to disconnect this organization?": "Êtes-vous certain de vouloir déconnecter cette organisation?",
|
||||
"Auto hide Menu bar": "Cacher automatiquement la barre de menu",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Cacher automatiquement la barre de menu (Appuyez sur la touche Alt pour l'afficher)",
|
||||
"Back": "Précédent",
|
||||
"Bounce dock on new private message": "Animer l'horloge à la réception d'un nouveau message privé",
|
||||
"Certificate file": "Fichier de certificat",
|
||||
"Change": "Changer",
|
||||
"Check for Updates": "Vérifier les mises à jour",
|
||||
"Close": "Fermer",
|
||||
"Connect": "Relier",
|
||||
"Connect": "Connecter",
|
||||
"Connect to another organization": "Se connecter à une autre organisation",
|
||||
"Connected organizations": "Organisations connectées",
|
||||
"Copy": "Copie",
|
||||
"Copy Zulip URL": "Copier l'URL Zulip",
|
||||
"Copy": "Copier",
|
||||
"Copy Zulip URL": "Copier l'URL de Zulip",
|
||||
"Create a new organization": "Créer une nouvelle organisation",
|
||||
"Cut": "Couper",
|
||||
"Default download location": "Emplacement de téléchargement par défaut",
|
||||
"Delete": "Effacer",
|
||||
"Default download location": "Destination de téléchargement par défaut",
|
||||
"Delete": "Supprimer",
|
||||
"Desktop App Settings": "Paramètres de l'application de bureau",
|
||||
"Desktop Notifications": "Notifications de bureau",
|
||||
"Desktop Settings": "Paramètres du bureau",
|
||||
"Desktop Settings": "Paramètres de bureau",
|
||||
"Disconnect": "Déconnecter",
|
||||
"Download App Logs": "Télécharger les journaux d'application",
|
||||
"Edit": "modifier",
|
||||
"Download App Logs": "Télécharger le journal de l'application",
|
||||
"Edit": "Modifier",
|
||||
"Edit Shortcuts": "Modifier les raccourcis",
|
||||
"Enable auto updates": "Activer les mises à jour automatiques",
|
||||
"Enable error reporting (requires restart)": "Activer le signalement des erreurs (nécessite un redémarrage)",
|
||||
"Enable spellchecker (requires restart)": "Activer le correcteur orthographique (nécessite un redémarrage)",
|
||||
"Factory Reset": "Retour aux paramètres d'usine",
|
||||
"Enable auto updates": "Activer la mise à jour automatique",
|
||||
"Enable error reporting (requires restart)": "Activer le rapport d'erreur (redémarrage nécessaire)",
|
||||
"Enable spellchecker (requires restart)": "Activer le correcteur orthographique (redémarrage nécessaire)",
|
||||
"Factory Reset": "Réinitialiser aux paramètres par défaut",
|
||||
"File": "Fichier",
|
||||
"Find accounts": "Trouver des comptes",
|
||||
"Find accounts by email": "Trouver des comptes par email",
|
||||
"Flash taskbar on new message": "Barre de tâches Flash sur un nouveau message",
|
||||
"Forward": "Vers l'avant",
|
||||
"Functionality": "La fonctionnalité",
|
||||
"Find accounts": "Rechercher un compte",
|
||||
"Find accounts by email": "Rechercher un compte par adresse courriel",
|
||||
"Flash taskbar on new message": "Clignoter la barre de tâche lors d'un nouveau message",
|
||||
"Forward": "Suivant",
|
||||
"Functionality": "Fonctionnalités",
|
||||
"General": "Général",
|
||||
"Get beta updates": "Obtenir les mises à jour bêta",
|
||||
"Hard Reload": "Rechargement dur",
|
||||
"Help": "Aidez-moi",
|
||||
"Get beta updates": "Recevoir les mises à jour Beta",
|
||||
"Hard Reload": "Forcer un rechargement",
|
||||
"Help": "Aide",
|
||||
"Help Center": "Centre d'aide",
|
||||
"History": "L'histoire",
|
||||
"History Shortcuts": "Raccourcis Histoire",
|
||||
"History": "Historique",
|
||||
"History Shortcuts": "Historique des raccourcis",
|
||||
"Keyboard Shortcuts": "Raccourcis clavier",
|
||||
"Log Out": "Connectez - Out",
|
||||
"Log Out of Organization": "Déconnexion de l'organisation",
|
||||
"Log Out": "Se déconnecter",
|
||||
"Log Out of Organization": "Se déconnecter de l'organisation",
|
||||
"Manual proxy configuration": "Configuration manuelle du proxy",
|
||||
"Minimize": "Minimiser",
|
||||
"Mute all sounds from Zulip": "Couper tous les sons de Zulip",
|
||||
"NO": "NON",
|
||||
"NO": "Non",
|
||||
"Network": "Réseau",
|
||||
"OR": "OU",
|
||||
"Organization URL": "URL de l'organisation",
|
||||
"Organizations": "Les organisations",
|
||||
"Organizations": "Organisations",
|
||||
"Paste": "Coller",
|
||||
"Paste and Match Style": "Coller et assortir le style",
|
||||
"Proxy": "Procuration",
|
||||
"Proxy bypass rules": "Règles de contournement des procurations",
|
||||
"Proxy rules": "Règles de procuration",
|
||||
"Paste and Match Style": "Coller et Conserver le style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Règles de contournement du proxy",
|
||||
"Proxy rules": "Règles du proxy",
|
||||
"Quit": "Quitter",
|
||||
"Quit Zulip": "Quittez Zulip",
|
||||
"Quit Zulip": "Quitter Zulip",
|
||||
"Redo": "Refaire",
|
||||
"Release Notes": "Notes de version",
|
||||
"Release Notes": "Notes sur la version",
|
||||
"Reload": "Recharger",
|
||||
"Report an Issue": "Signaler un problème",
|
||||
"Reset App Data": "Réinitialiser les données de l'application",
|
||||
"Reset App Settings": "Réinitialiser les paramètres de l'application",
|
||||
"Reset Application Data": "Réinitialiser les données d'application",
|
||||
"Save": "sauvegarder",
|
||||
"Select All": "Tout sélectionner",
|
||||
"Settings": "Réglages",
|
||||
"Report an Issue": "Rapporter un problème",
|
||||
"Save": "Sauvegarder",
|
||||
"Select All": "Sélectionner tout",
|
||||
"Settings": "Paramètres",
|
||||
"Shortcuts": "Raccourcis",
|
||||
"Show App Logs": "Afficher les journaux d'application",
|
||||
"Show app icon in system tray": "Afficher l'icône de l'application dans la barre d'état système",
|
||||
"Show app unread badge": "Afficher le badge non lu de l'application",
|
||||
"Show desktop notifications": "Afficher les notifications du bureau",
|
||||
"Show App Logs": "Afficher le journal de l'application",
|
||||
"Show app icon in system tray": "Afficher l'icone de l'application dans la barre d'état",
|
||||
"Show app unread badge": "Afficher un badge lors d'un message non lu",
|
||||
"Show desktop notifications": "Afficher les notifications sur le bureau",
|
||||
"Show downloaded files in file manager": "Afficher les fichiers téléchargés dans le gestionnaire de fichiers",
|
||||
"Show sidebar": "Afficher la barre latérale",
|
||||
"Start app at login": "Lancer l'application à la connexion",
|
||||
"Switch to Next Organization": "Passer à l'organisation suivante",
|
||||
"Switch to Previous Organization": "Passer à l'organisation précédente",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Ces raccourcis d’applications de bureau étendent les applications Web de Zulip.",
|
||||
"This will delete all application data including all added accounts and preferences": "Cela supprimera toutes les données de l'application, y compris tous les comptes et préférences ajoutés.",
|
||||
"Tip": "Pointe",
|
||||
"Toggle DevTools for Active Tab": "Basculer DevTools pour l'onglet actif",
|
||||
"Toggle DevTools for Zulip App": "Basculer DevTools pour Zulip App",
|
||||
"Toggle Do Not Disturb": "Basculer ne pas déranger",
|
||||
"Toggle Full Screen": "Basculer en plein écran",
|
||||
"Toggle Sidebar": "Basculer la barre latérale",
|
||||
"Toggle Tray Icon": "Basculer l'icône du plateau",
|
||||
"Start app at login": "Démarrer l'application à l'ouverture",
|
||||
"Switch to Next Organization": "Basculer à l'organisation suivante",
|
||||
"Switch to Previous Organization": "Basculer à l'organisation précédente",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "Ces raccourcis d'application vont au-delà de l'application web Zulip",
|
||||
"This will delete all application data including all added accounts and preferences": "Ceci supprimera toutes les données de l'application, incluant les comptes et préférences",
|
||||
"Tip": "Conseil",
|
||||
"Toggle DevTools for Active Tab": "Activer les outils de développement dans l'onglet actif",
|
||||
"Toggle DevTools for Zulip App": "Activer les outils de développement dans l'application Zulip",
|
||||
"Toggle Do Not Disturb": "Activer le mode Ne Pas Déranger",
|
||||
"Toggle Full Screen": "Activer le mode Plein Écran",
|
||||
"Toggle Sidebar": "Activer la barre latérale",
|
||||
"Toggle Tray Icon": "Activer l'icone dans la barre d'état",
|
||||
"Tools": "Outils",
|
||||
"Undo": "annuler",
|
||||
"Upload": "Télécharger",
|
||||
"Use system proxy settings (requires restart)": "Utiliser les paramètres proxy du système (nécessite un redémarrage)",
|
||||
"View": "Vue",
|
||||
"View Shortcuts": "Afficher les raccourcis",
|
||||
"Window": "La fenêtre",
|
||||
"Window Shortcuts": "Raccourcis de la fenêtre",
|
||||
"YES": "OUI",
|
||||
"Zoom In": "Agrandir",
|
||||
"Zoom Out": "Dézoomer",
|
||||
"Zulip Help": "Aide Zulip",
|
||||
"Undo": "Annuler",
|
||||
"Upload": "Envoyer",
|
||||
"Use system proxy settings (requires restart)": "Utiliser les paramètres de proxy du système (exige un redémarrage)",
|
||||
"View": "Affichage",
|
||||
"View Shortcuts": "Voir les raccourcis",
|
||||
"Window": "Fenêtre",
|
||||
"Window Shortcuts": "Raccourcis fenêtre",
|
||||
"YES": "Oui",
|
||||
"Zoom In": "Zoom avant",
|
||||
"Zoom Out": "Zoom arrière",
|
||||
"Zulip Help": "Aide sur Zulip",
|
||||
"keyboard shortcuts": "Raccourcis clavier",
|
||||
"script": "scénario"
|
||||
"script": "Script",
|
||||
"Quit when the window is closed": "Quitter l'application lors de la fermeture de la fenêtre",
|
||||
"Ask where to save files before downloading": "Demander où sauvegarder les fichiers avant de télécharger",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
|
||||
134
app/translations/gl.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "About Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organization",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Close",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Copy",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Delete",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Editar",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "File",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organization URL",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Gardar",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Configuración",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
@@ -75,9 +75,6 @@
|
||||
"Release Notes": "रिलीज नोट्स",
|
||||
"Reload": "सीमा से अधिक लादना",
|
||||
"Report an Issue": "मामले की रिपोर्ट करें",
|
||||
"Reset App Data": "ऐप डेटा रीसेट करें",
|
||||
"Reset App Settings": "ऐप सेटिंग रीसेट करें",
|
||||
"Reset Application Data": "एप्लिकेशन डेटा रीसेट करें",
|
||||
"Save": "बचाना",
|
||||
"Select All": "सभी का चयन करे",
|
||||
"Settings": "सेटिंग्स",
|
||||
@@ -114,5 +111,24 @@
|
||||
"Zulip Help": "Zulip मदद",
|
||||
"keyboard shortcuts": "कुंजीपटल अल्प मार्ग",
|
||||
"script": "लिपि",
|
||||
"AddServer": "AddServer"
|
||||
}
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||
|
||||
134
app/translations/hr.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"About Zulip": "About Zulip",
|
||||
"Actual Size": "Actual Size",
|
||||
"Add Custom Certificates": "Add Custom Certificates",
|
||||
"Add Organization": "Add Organization",
|
||||
"Add a Zulip organization": "Add a Zulip organization",
|
||||
"Add custom CSS": "Add custom CSS",
|
||||
"Advanced": "Advanced",
|
||||
"All the connected organizations will appear here": "All the connected organizations will appear here",
|
||||
"Always start minimized": "Always start minimized",
|
||||
"App Updates": "App Updates",
|
||||
"Appearance": "Appearance",
|
||||
"Application Shortcuts": "Application Shortcuts",
|
||||
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
|
||||
"Auto hide Menu bar": "Auto hide Menu bar",
|
||||
"Auto hide menu bar (Press Alt key to display)": "Auto hide menu bar (Press Alt key to display)",
|
||||
"Back": "Back",
|
||||
"Bounce dock on new private message": "Bounce dock on new private message",
|
||||
"Certificate file": "Certificate file",
|
||||
"Change": "Change",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Close": "Close",
|
||||
"Connect": "Connect",
|
||||
"Connect to another organization": "Connect to another organization",
|
||||
"Connected organizations": "Connected organizations",
|
||||
"Copy": "Copy",
|
||||
"Copy Zulip URL": "Copy Zulip URL",
|
||||
"Create a new organization": "Create a new organization",
|
||||
"Cut": "Cut",
|
||||
"Default download location": "Default download location",
|
||||
"Delete": "Delete",
|
||||
"Desktop App Settings": "Desktop App Settings",
|
||||
"Desktop Notifications": "Desktop Notifications",
|
||||
"Desktop Settings": "Desktop Settings",
|
||||
"Disconnect": "Disconnect",
|
||||
"Download App Logs": "Download App Logs",
|
||||
"Edit": "Edit",
|
||||
"Edit Shortcuts": "Edit Shortcuts",
|
||||
"Enable auto updates": "Enable auto updates",
|
||||
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
|
||||
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
|
||||
"Factory Reset": "Factory Reset",
|
||||
"File": "File",
|
||||
"Find accounts": "Find accounts",
|
||||
"Find accounts by email": "Find accounts by email",
|
||||
"Flash taskbar on new message": "Flash taskbar on new message",
|
||||
"Forward": "Forward",
|
||||
"Functionality": "Functionality",
|
||||
"General": "General",
|
||||
"Get beta updates": "Get beta updates",
|
||||
"Hard Reload": "Hard Reload",
|
||||
"Help": "Help",
|
||||
"Help Center": "Help Center",
|
||||
"History": "History",
|
||||
"History Shortcuts": "History Shortcuts",
|
||||
"Keyboard Shortcuts": "Keyboard Shortcuts",
|
||||
"Log Out": "Log Out",
|
||||
"Log Out of Organization": "Log Out of Organization",
|
||||
"Manual proxy configuration": "Manual proxy configuration",
|
||||
"Minimize": "Minimize",
|
||||
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
|
||||
"NO": "NO",
|
||||
"Network": "Network",
|
||||
"OR": "OR",
|
||||
"Organization URL": "Organization URL",
|
||||
"Organizations": "Organizations",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Proxy": "Proxy",
|
||||
"Proxy bypass rules": "Proxy bypass rules",
|
||||
"Proxy rules": "Proxy rules",
|
||||
"Quit": "Quit",
|
||||
"Quit Zulip": "Quit Zulip",
|
||||
"Redo": "Redo",
|
||||
"Release Notes": "Release Notes",
|
||||
"Reload": "Reload",
|
||||
"Report an Issue": "Report an Issue",
|
||||
"Save": "Save",
|
||||
"Select All": "Select All",
|
||||
"Settings": "Settings",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Show App Logs": "Show App Logs",
|
||||
"Show app icon in system tray": "Show app icon in system tray",
|
||||
"Show app unread badge": "Show app unread badge",
|
||||
"Show desktop notifications": "Show desktop notifications",
|
||||
"Show downloaded files in file manager": "Show downloaded files in file manager",
|
||||
"Show sidebar": "Show sidebar",
|
||||
"Start app at login": "Start app at login",
|
||||
"Switch to Next Organization": "Switch to Next Organization",
|
||||
"Switch to Previous Organization": "Switch to Previous Organization",
|
||||
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
|
||||
"This will delete all application data including all added accounts and preferences": "This will delete all application data including all added accounts and preferences",
|
||||
"Tip": "Tip",
|
||||
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
|
||||
"Toggle DevTools for Zulip App": "Toggle DevTools for Zulip App",
|
||||
"Toggle Do Not Disturb": "Toggle Do Not Disturb",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Toggle Sidebar": "Toggle Sidebar",
|
||||
"Toggle Tray Icon": "Toggle Tray Icon",
|
||||
"Tools": "Tools",
|
||||
"Undo": "Undo",
|
||||
"Upload": "Upload",
|
||||
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
|
||||
"View": "View",
|
||||
"View Shortcuts": "View Shortcuts",
|
||||
"Window": "Window",
|
||||
"Window Shortcuts": "Window Shortcuts",
|
||||
"YES": "YES",
|
||||
"Zoom In": "Zoom In",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zulip Help": "Zulip Help",
|
||||
"keyboard shortcuts": "keyboard shortcuts",
|
||||
"script": "script",
|
||||
"Quit when the window is closed": "Quit when the window is closed",
|
||||
"Ask where to save files before downloading": "Ask where to save files before downloading",
|
||||
"Services": "Services",
|
||||
"Hide": "Hide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Unhide": "Unhide",
|
||||
"AddServer": "AddServer",
|
||||
"App language (requires restart)": "App language (requires restart)",
|
||||
"Factory Reset Data": "Factory Reset Data",
|
||||
"Reset the application, thus deleting all the connected organizations, accounts, and certificates.": "Reset the application, thus deleting all the connected organizations, accounts, and certificates.",
|
||||
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
|
||||
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Image": "Copy Image",
|
||||
"Copy Image URL": "Copy Image URL",
|
||||
"No Suggestion Found": "No Suggestion Found",
|
||||
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
|
||||
"Spellchecker Languages": "Spellchecker Languages",
|
||||
"Add to Dictionary": "Add to Dictionary",
|
||||
"Look Up": "Look Up"
|
||||
}
|
||||