Compare commits

...

78 Commits

Author SHA1 Message Date
Anders Kaseorg
3956252309 xo: Fix unicorn/prefer-event-target.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-10-02 00:43:33 -07:00
Anders Kaseorg
5eccd49fef Switch i18next-parser to i18next-cli.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-10-02 00:13:55 -07:00
Anders Kaseorg
c08bbf49ab release: New release v5.12.2.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-09-01 10:49:56 -07:00
Hosted Weblate
913eda8b1e translations: Update translations from Weblate. 2025-09-01 19:39:02 +02:00
Anders Kaseorg
52a3fa6bd1 release: New release v5.12.1.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-29 13:23:54 -07:00
Anders Kaseorg
c1f2ae5ef8 context-menu: Enable macOS Writing Tools.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-29 13:23:54 -07:00
Anders Kaseorg
301fe26d80 Upgrade dependencies, including Electron 37.4.0.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-29 12:41:45 -07:00
Hosted Weblate
92a2b4eae9 translations: Update translations from Weblate. 2025-08-29 19:41:14 +00:00
Anders Kaseorg
6e307570d0 Replace Transifex documentation and configuration with Weblate.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-29 12:35:20 -07:00
Anders Kaseorg
dc39c68389 Modernize APT configuration format.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-28 16:38:58 -07:00
Anders Kaseorg
73cdfa7249 how-to-install: Note that the Debian package configures APT.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-28 16:38:58 -07:00
Anders Kaseorg
d9e4b0a40b Update electron-builder configuration.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-28 16:23:57 -07:00
Anders Kaseorg
0c7ce62ce1 Update apt signing key with SHA-256 binding signatures.
Fixes #1437.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-12 20:37:06 -07:00
Anders Kaseorg
9dd5fd2aa5 Mark more strings for translation.
Fixes #1128 among many other things.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 14:04:43 -07:00
Anders Kaseorg
11e2635aa0 Correct node-json-db Errors.js imports.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 14:02:00 -07:00
Anders Kaseorg
b35cf13a77 tests: Move tests/package.json to its own folder.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 13:38:35 -07:00
Anders Kaseorg
814de8ad6a tests: Convert tests to TypeScript.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 13:29:46 -07:00
Anders Kaseorg
d9dbbf2359 tests: Switch from medium to p-fifo.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 13:29:46 -07:00
Anders Kaseorg
a9c9de2dee Convert i18next-parser configuration to TypeScript.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-06 13:29:46 -07:00
Anders Kaseorg
9b626950ae workflows: Use actions/setup-node.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 01:10:40 -07:00
Anders Kaseorg
45672432db Focus the webview for notification settings, keyboard shortcuts.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:57:36 -07:00
Anders Kaseorg
b5665abb3e Upgrade dependencies, including Electron 37.2.5.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:48:30 -07:00
Anders Kaseorg
5b30bb2a16 stylelint: Fix property-no-deprecated.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
598aa6f4b9 webview: Adjust app.dock feature test for TypeScript friendliness.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
2e7ed457f0 xo: Fix @typescript-eslint/prefer-nullish-coalescing.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
bb3cad818b xo: Fix unicorn/prefer-string-raw.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
e3d9308c21 xo: Fix unicorn/prefer-single-call.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
098d35fc5c index: Avoid deprecated Buffer#slice.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:40:03 -07:00
Anders Kaseorg
eb849a7b3d Switch to "type": "module".
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-05 00:32:25 -07:00
Anders Kaseorg
ab3698f56c Switch i18next-scanner to i18next-parser.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-08-02 11:53:21 -07:00
Anders Kaseorg
0fdeb1fd17 translations: Update translations from Transifex.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-07-31 17:48:29 -07:00
Anders Kaseorg
d270d56309 xo: Prohibit main-only and renderer-only APIs in wrong processes.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
2c5b1ad297 xo: Use eslint-import-resolver-typescript.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
26b226c7ae Use .ts extensions for imports.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
7f6699e235 tsconfig: Enable allowImportingTsExtensions.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
339f0d19c7 xo: Configure import/no-extraneous-dependencies packageDir.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
86882c0741 xo: Move configuration to xo.config.cjs.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Anders Kaseorg
cf5a691a36 Revert "enterprise: Quit app after showing error for invalid global config."
This reverts commit 51ff949d34.

It incorrectly uses a main-only API in app/common, which is shared
between the main and renderer processes.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-06-20 16:35:18 -07:00
Shubham Padia
51ff949d34 enterprise: Quit app after showing error for invalid global config.
Otherwise, the error will keep showing multiple times ultimately
leading to a non-working app after multiple errors.
2025-06-17 18:07:11 -07:00
Shubham Padia
e5680b12f4 enterprise: Show error dialogbox on invalid JSON.
Fixes #1404.

Co-authored-by: sammamama <samridhsame@gmail.com>
2025-06-17 18:07:11 -07:00
Shubham Padia
b42f9de27d preferences: Increase contrast of setting text and nav items.
The text in the settings panel was unnecessarily fade, making it hard to
read. Increasing the contrast makes it more readable. The setting text
color is the same as the heading of the settings. This commit also
changes the color of the nav items to be the same as `|` bar preceding
it.
https://chat.zulip.org/#narrow/channel/101-design/topic/zulip-desktop.20preferences.20contrast
2025-06-11 12:33:00 -07:00
Shubham Padia
201faa9449 settings: Make Do not disturb icon brigther when it's on.
It was not so obvious to users when they were in DND mode, making the
icon brigther when in DND mode hopes to address that.
https://chat.zulip.org/#narrow/channel/101-design/topic/zulip-desktop.20DND.20icon.20contrast
2025-06-11 12:32:11 -07:00
Shubham Padia
4125de4a60 css: Use hsl for action-button icon colors.
We only change this for `.action-button i` and `.action-button:hover i`
since we need to make the dnd icon lighter in comparison to these two.
These are the two that are absolutely necessary to change, we can also
change others to hsl color space after discussion on CZO.
2025-06-11 12:32:11 -07:00
Alex Vandiver
916fab7963 translations: Update translations from Transifex. 2025-05-20 18:59:55 +00:00
Anders Kaseorg
15902e51f6 release: New release v5.12.0.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-13 14:06:16 -07:00
Anders Kaseorg
19705bc90b Update macOS notarization configuration.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-13 14:06:12 -07:00
Anders Kaseorg
a9313f4756 Update Azure Trusted Signing configuration.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-13 14:06:12 -07:00
Anders Kaseorg
13b4d2037a Upgrade dependencies, including Electron 35.0.1.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-13 13:36:26 -07:00
Anders Kaseorg
ab63ec2a4a translations: Update translations from Transifex.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-12 17:22:53 -07:00
Anders Kaseorg
1de4f88c6c webview: Address deprecation of WebContents.goBack et al.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-12 17:15:03 -07:00
Anders Kaseorg
ab4381a6bf xo: Fix unicorn/prefer-global-this.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-12 17:15:03 -07:00
Anders Kaseorg
d409a0bf33 menu: Check focusedWindow type.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-12 17:15:03 -07:00
Anders Kaseorg
c40e05646e Update macOS icon with a native appearance.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-03-12 16:59:49 -07:00
Anders Kaseorg
13f3818c77 supported-locales: Fix for removal of el_GR and zh-Hant.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-11 14:44:47 -05:00
Tim Abbott
4a0e590921 github: Use zulip/zulip pull request template style.
Hopefully this will help improve the quality of pull requests to this
repository.
2024-12-11 11:22:04 -08:00
Shubham Padia
eb19b20da2 preference: Rename show app unread badge setting.
The original wording was found to be confusing, see
https://chat.zulip.org/#narrow/channel/16-desktop/topic/.22app.20unread.20badge.22/near/1993426
for more details.
2024-12-11 11:18:19 -08:00
Alex Vandiver
69cb509fe5 translations: Remove control characters from zh_TW translation string. 2024-12-11 11:28:13 -05:00
Alex Vandiver
123263e5bb translations: Remove zh-Hant translation.
The `zh_TW` translation is much more complete.
2024-12-11 11:24:47 -05:00
Alex Vandiver
a26a10849d translations: Remove empty el_GR duplicate translation. 2024-12-11 11:20:20 -05:00
Anders Kaseorg
da7e026550 Mark dialog strings for translation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:53:25 -08:00
Anders Kaseorg
c70f6df096 about: Remove inexplicable ‘cursor: pointer’.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:29 -08:00
Anders Kaseorg
ef0110f8e7 about: Mark strings for translation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:29 -08:00
Anders Kaseorg
b7a7ca3e5c renderer: Mark strings for translation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:29 -08:00
Anders Kaseorg
467e7b11c5 functional-tab: Split ‘name’ into ‘page’ and ‘label’.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:29 -08:00
Anders Kaseorg
105e7e93a1 translations: Add missing translatable strings with i18next-scanner.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:28 -08:00
Anders Kaseorg
a736f664c6 nav: Statically mark navigation items for translation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-12-02 15:52:06 -08:00
Anders Kaseorg
38c7695a99 release: New release v5.11.1.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-23 16:31:21 -07:00
Anders Kaseorg
b268fe9478 Sign Windows binaries with Azure Trusted Signing.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-23 16:22:19 -07:00
Anders Kaseorg
981a262836 xo: Remove obsolete scripts/notarize.js options.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:18:05 -07:00
Anders Kaseorg
527bb5ab2f Upgrade dependencies, including Electron 32.0.1.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:13:32 -07:00
Anders Kaseorg
e2947a0ce6 translations: Update translations from Transifex.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:13:27 -07:00
Anders Kaseorg
3b2c758e09 translations: Sort supported-locales by display name.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:13:27 -07:00
Anders Kaseorg
4867fc672a preference: Sort spellchecker language names with localeCompare.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:13:27 -07:00
Anders Kaseorg
f85f05d66b preference: Show spellchecker language names from Intl.DisplayNames.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-22 16:13:27 -07:00
Anders Kaseorg
39fd0e9877 tsconfig: Work around @sentry/electron regression.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-07 14:58:13 -07:00
Anders Kaseorg
f6ff112f0e stylelint: Fix declaration-block-no-shorthand-property-overrides.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-07 14:53:08 -07:00
Anders Kaseorg
6fcd1ef0d5 Remove rimraf.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-08-06 22:55:40 -07:00
Misha Brukman
92260b0f97 ci: Replace Travis CI badge with GitHub Actions.
Travis CI was replaced with GitHub Actions in this project.
2024-07-02 15:41:59 -07:00
161 changed files with 11834 additions and 7958 deletions

View File

@@ -6,6 +6,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.css,*.html,*.js,*.json,*.ts}]
[{*.cjs,*.css,*.html,*.js,*.json,*.ts}]
indent_style = space
indent_size = 2

View File

@@ -1,18 +1,49 @@
---
<!-- Describe your pull request here.-->
<!--
Remove the fields that are not appropriate
Please include:
Fixes: <!-- Issue link, or clear description.-->
<!-- If the PR makes UI changes, always include one or more still screenshots to demonstrate your changes. If it seems helpful, add a screen capture of the new functionality as well.
Tooling tips: https://zulip.readthedocs.io/en/latest/tutorials/screenshot-and-gif-software.html
-->
**What's this PR do?**
**Screenshots and screen captures:**
**Any background context you want to provide?**
**Screenshots?**
**You have tested this PR on:**
**Platforms this PR was tested on:**
- [ ] Windows
- [ ] Linux/Ubuntu
- [ ] macOS
- [ ] Linux (specify distro)
<details>
<summary>Self-review checklist</summary>
<!-- Prior to submitting a PR, follow our step-by-step guide to review your own code:
https://zulip.readthedocs.io/en/latest/contributing/code-reviewing.html#how-to-review-code -->
<!-- Once you create the PR, check off all the steps below that you have completed.
If any of these steps are not relevant or you have not completed, leave them unchecked.-->
- [ ] [Self-reviewed](https://zulip.readthedocs.io/en/latest/contributing/code-reviewing.html#how-to-review-code) the changes for clarity and maintainability
(variable names, code reuse, readability, etc.).
Communicate decisions, questions, and potential concerns.
- [ ] Explains differences from previous plans (e.g., issue description).
- [ ] Highlights technical choices and bugs encountered.
- [ ] Calls out remaining decisions and concerns.
- [ ] Automated tests verify logic where appropriate.
Individual commits are ready for review (see [commit discipline](https://zulip.readthedocs.io/en/latest/contributing/commit-discipline.html)).
- [ ] Each commit is a coherent idea.
- [ ] Commit message(s) explain reasoning and motivation for changes.
Completed manual review and testing of the following:
- [ ] Visual appearance of the changes.
- [ ] Responsiveness and internationalization.
- [ ] Strings and tooltips.
- [ ] End-to-end functionality of buttons, interactions and flows.
- [ ] Corner cases, error conditions, and easily imagined bugs.
</details>

View File

@@ -10,6 +10,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/*
- uses: actions/checkout@v4
- run: npm ci
- run: npm test

3
.gitignore vendored
View File

@@ -4,9 +4,6 @@
# npm cache directory
.npm
# transifexrc - if user prefers it to be in working tree
.transifexrc
# Compiled binary build directory
/dist/
/dist-electron/

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
node-options=--experimental-strip-types

View File

@@ -1,9 +0,0 @@
[main]
host = https://www.transifex.com
[o:zulip:p:zulip:r:desktopjson]
file_filter = public/translations/<lang>.json
minimum_perc = 0
source_file = public/translations/en.json
source_lang = en
type = KEYVALUEJSON

View File

@@ -1,6 +1,6 @@
# Zulip Desktop Client
[![Build Status](https://travis-ci.com/zulip/zulip-desktop.svg?branch=main)](https://travis-ci.com/github/zulip/zulip-desktop)
[![Build Status](https://github.com/zulip/zulip-desktop/actions/workflows/node.js.yml/badge.svg)](https://github.com/zulip/zulip-desktop/actions/workflows/node.js.yml?query=branch%3Amain)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/zulip/zulip-desktop?branch=main&svg=true)](https://ci.appveyor.com/project/zulip/zulip-desktop/branch/main)
[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://chat.zulip.org)

View File

@@ -37,6 +37,7 @@ export const configSchemata = {
useProxy: z.boolean(),
useSystemProxy: z.boolean(),
};
export type ConfigSchemata = typeof configSchemata;
export const enterpriseConfigSchemata = {
...configSchemata,

View File

@@ -3,16 +3,16 @@ import path from "node:path";
import * as Sentry from "@sentry/core";
import {JsonDB} from "node-json-db";
import {DataError} from "node-json-db/dist/lib/Errors";
import {DataError} from "node-json-db/dist/lib/Errors.js";
import type {z} from "zod";
import {app, dialog} from "zulip:remote";
import {configSchemata} from "./config-schemata.js";
import * as EnterpriseUtil from "./enterprise-util.js";
import Logger from "./logger-util.js";
import {type ConfigSchemata, configSchemata} from "./config-schemata.ts";
import * as EnterpriseUtil from "./enterprise-util.ts";
import Logger from "./logger-util.ts";
export type Config = {
[Key in keyof typeof configSchemata]: z.output<(typeof configSchemata)[Key]>;
[Key in keyof ConfigSchemata]: z.output<ConfigSchemata[Key]>;
};
const logger = new Logger({
@@ -26,7 +26,7 @@ reloadDatabase();
export function getConfigItem<Key extends keyof Config>(
key: Key,
defaultValue: Config[Key],
): z.output<(typeof configSchemata)[Key]> {
): z.output<ConfigSchemata[Key]> {
try {
database.reload();
} catch (error: unknown) {
@@ -35,7 +35,13 @@ export function getConfigItem<Key extends keyof Config>(
}
try {
return configSchemata[key].parse(database.getObject<unknown>(`/${key}`));
const typedSchemata: {
[Key in keyof Config]: z.ZodType<
z.output<ConfigSchemata[Key]>,
z.input<ConfigSchemata[Key]>
>;
} = configSchemata; // https://github.com/colinhacks/zod/issues/5154
return typedSchemata[key].parse(database.getObject<unknown>(`/${key}`));
} catch (error: unknown) {
if (!(error instanceof DataError)) throw error;
setConfigItem(key, defaultValue);

View File

@@ -2,8 +2,8 @@ import process from "node:process";
import type {z} from "zod";
import type {dndSettingsSchemata} from "./config-schemata.js";
import * as ConfigUtil from "./config-util.js";
import type {dndSettingsSchemata} from "./config-schemata.ts";
import * as ConfigUtil from "./config-util.ts";
export type DndSettings = {
[Key in keyof typeof dndSettingsSchemata]: z.output<

View File

@@ -3,9 +3,10 @@ import path from "node:path";
import process from "node:process";
import {z} from "zod";
import {dialog} from "zulip:remote";
import {enterpriseConfigSchemata} from "./config-schemata.js";
import Logger from "./logger-util.js";
import {enterpriseConfigSchemata} from "./config-schemata.ts";
import Logger from "./logger-util.ts";
type EnterpriseConfig = {
[Key in keyof typeof enterpriseConfigSchemata]: z.output<
@@ -25,8 +26,7 @@ reloadDatabase();
function reloadDatabase(): void {
let enterpriseFile = "/etc/zulip-desktop-config/global_config.json";
if (process.platform === "win32") {
enterpriseFile =
"C:\\Program Files\\Zulip-Desktop-Config\\global_config.json";
enterpriseFile = String.raw`C:\Program Files\Zulip-Desktop-Config\global_config.json`;
}
enterpriseFile = path.resolve(enterpriseFile);
@@ -40,6 +40,10 @@ function reloadDatabase(): void {
.partial()
.parse(data);
} catch (error: unknown) {
dialog.showErrorBox(
"Error loading global_config",
"We encountered an error while reading global_config.json, please make sure the file contains valid JSON.",
);
logger.log("Error while JSON parsing global_config.json: ");
logger.log(error);
}

View File

@@ -3,7 +3,8 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import {html} from "./html.js";
import {Html, html} from "./html.ts";
import * as t from "./translation-util.ts";
export async function openBrowser(url: URL): Promise<void> {
if (["http:", "https:", "mailto:"].includes(url.protocol)) {
@@ -21,7 +22,7 @@ export async function openBrowser(url: URL): Promise<void> {
<head>
<meta charset="UTF-8" />
<meta http-equiv="Refresh" content="0; url=${url.href}" />
<title>Redirecting</title>
<title>${t.__("Redirecting")}</title>
<style>
html {
font-family: menu, "Helvetica Neue", sans-serif;
@@ -29,7 +30,13 @@ export async function openBrowser(url: URL): Promise<void> {
</style>
</head>
<body>
<p>Opening <a href="${url.href}">${url.href}</a>…</p>
<p>
${new Html({
html: t.__("Opening {{{link}}}…", {
link: html`<a href="${url.href}">${url.href}</a>`.html,
}),
})}
</p>
</body>
</html>
`.html,

View File

@@ -5,7 +5,7 @@ import process from "node:process";
import {app} from "zulip:remote";
import {initSetUp} from "./default-util.js";
import {initSetUp} from "./default-util.ts";
type LoggerOptions = {
file?: string;

View File

@@ -1,3 +1,5 @@
import * as t from "./translation-util.ts";
type DialogBoxError = {
title: string;
content: string;
@@ -13,26 +15,24 @@ export function invalidZulipServerError(domain: string): string {
https://zulip.readthedocs.io/en/stable/production/ssl-certificates.html`;
}
export function enterpriseOrgError(
length: number,
domains: string[],
): DialogBoxError {
export function enterpriseOrgError(domains: string[]): DialogBoxError {
let domainList = "";
for (const domain of domains) {
domainList += `${domain}\n`;
}
return {
title: `Could not add the following ${
length === 1 ? "organization" : "organizations"
}`,
content: `${domainList}\nPlease contact your system administrator.`,
title: t.__mf(
"{number, plural, one {Could not add # organization} other {Could not add # organizations}}",
{number: domains.length},
),
content: `${domainList}\n${t.__("Please contact your system administrator.")}`,
};
}
export function orgRemovalError(url: string): DialogBoxError {
return {
title: `Removing ${url} is a restricted operation.`,
content: "Please contact your system administrator.",
title: t.__("Removing {{{url}}} is a restricted operation.", {url}),
content: t.__("Please contact your system administrator."),
};
}

View File

@@ -2,8 +2,8 @@ import path from "node:path";
import i18n from "i18n";
import * as ConfigUtil from "./config-util.js";
import {publicPath} from "./paths.js";
import * as ConfigUtil from "./config-util.ts";
import {publicPath} from "./paths.ts";
i18n.configure({
directory: path.join(publicPath, "translations/"),
@@ -13,4 +13,4 @@ i18n.configure({
/* Fetches the current appLocale from settings.json */
i18n.setLocale(ConfigUtil.getConfigItem("appLanguage", "en") ?? "en");
export {__} from "i18n";
export {__, __mf} from "i18n";

View File

@@ -1,5 +1,5 @@
import type {DndSettings} from "./dnd-util.js";
import type {MenuProperties, ServerConfig} from "./types.js";
import type {DndSettings} from "./dnd-util.ts";
import type {MenuProperties, ServerConfig} from "./types.ts";
export type MainMessage = {
"clear-app-settings": () => void;

View File

@@ -20,9 +20,11 @@ export type ServerConfig = {
};
export type TabRole = "server" | "function";
export type TabPage = "Settings" | "About";
export type TabData = {
role: TabRole;
name: string;
page?: TabPage;
label: string;
index: number;
};

View File

@@ -9,9 +9,10 @@ import {
autoUpdater,
} from "electron-updater";
import * as ConfigUtil from "../common/config-util.js";
import * as ConfigUtil from "../common/config-util.ts";
import * as t from "../common/translation-util.ts";
import {linuxUpdateNotification} from "./linuxupdater.js"; // Required only in case of linux
import {linuxUpdateNotification} from "./linuxupdater.ts"; // Required only in case of linux
let quitting = false;
@@ -58,9 +59,13 @@ export async function appUpdater(updateFromMenu = false): Promise<void> {
}
await dialog.showMessageBox({
message: `A new version ${info.version}, of Zulip Desktop is available`,
detail:
message: t.__(
"A new version {{{version}}} of Zulip Desktop is available.",
{version: info.version},
),
detail: t.__(
"The update will be downloaded in the background. You will be notified when it is ready to be installed.",
),
});
}
});
@@ -72,8 +77,11 @@ export async function appUpdater(updateFromMenu = false): Promise<void> {
autoUpdater.removeAllListeners();
await dialog.showMessageBox({
message: "No updates available",
detail: `You are running the latest version of Zulip Desktop.\nVersion: ${app.getVersion()}`,
message: t.__("No updates available."),
detail: t.__(
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}",
{version: app.getVersion()},
),
});
}
});
@@ -85,20 +93,20 @@ export async function appUpdater(updateFromMenu = false): Promise<void> {
autoUpdater.removeAllListeners();
const messageText = updateAvailable
? "Unable to download the updates"
: "Unable to check for updates";
? t.__("Unable to download the update.")
: t.__("Unable to check for updates.");
const link = "https://zulip.com/apps/";
const {response} = await dialog.showMessageBox({
type: "error",
buttons: ["Manual Download", "Cancel"],
buttons: [t.__("Manual Download"), t.__("Cancel")],
message: messageText,
detail: `Error: ${error.message}
The latest version of Zulip Desktop is available at -
https://zulip.com/apps/.
Current Version: ${app.getVersion()}`,
detail: t.__(
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}",
{error: error.message, link, version: app.getVersion()},
),
});
if (response === 0) {
await shell.openExternal("https://zulip.com/apps/");
await shell.openExternal(link);
}
}
});
@@ -108,10 +116,14 @@ Current Version: ${app.getVersion()}`,
// Ask user to update the app
const {response} = await dialog.showMessageBox({
type: "question",
buttons: ["Install and Relaunch", "Install Later"],
buttons: [t.__("Install and Relaunch"), t.__("Install Later")],
defaultId: 0,
message: `A new update ${event.version} has been downloaded`,
detail: "It will be installed the next time you restart the application",
message: t.__("A new update {{{version}}} has been downloaded.", {
version: event.version,
}),
detail: t.__(
"It will be installed the next time you restart the application.",
),
});
if (response === 0) {
quitting = true;

View File

@@ -2,9 +2,9 @@ import {nativeImage} from "electron/common";
import {type BrowserWindow, app} from "electron/main";
import process from "node:process";
import * as ConfigUtil from "../common/config-util.js";
import * as ConfigUtil from "../common/config-util.ts";
import {send} from "./typed-ipc-main.js";
import {send} from "./typed-ipc-main.ts";
function showBadgeCount(messageCount: number, mainWindow: BrowserWindow): void {
if (process.platform === "win32") {

View File

@@ -9,10 +9,11 @@ import {
import fs from "node:fs";
import path from "node:path";
import * as ConfigUtil from "../common/config-util.js";
import * as LinkUtil from "../common/link-util.js";
import * as ConfigUtil from "../common/config-util.ts";
import * as LinkUtil from "../common/link-util.ts";
import * as t from "../common/translation-util.ts";
import {send} from "./typed-ipc-main.js";
import {send} from "./typed-ipc-main.ts";
function isUploadsUrl(server: string, url: URL): boolean {
return url.origin === server && url.pathname.startsWith("/user_uploads/");
@@ -125,8 +126,8 @@ export default function handleExternalLink(
downloadPath,
async completed(filePath: string, fileName: string) {
const downloadNotification = new Notification({
title: "Download Complete",
body: `Click to show ${fileName} in folder`,
title: t.__("Download Complete"),
body: t.__("Click to show {{{fileName}}} in folder", {fileName}),
silent: true, // We'll play our own sound - ding.ogg
});
downloadNotification.on("click", () => {
@@ -149,8 +150,8 @@ export default function handleExternalLink(
if (state !== "cancelled") {
if (ConfigUtil.getConfigItem("promptDownload", false)) {
new Notification({
title: "Download Complete",
body: "Download failed",
title: t.__("Download Complete"),
body: t.__("Download failed"),
}).show();
} else {
contents.downloadURL(url.href);

View File

@@ -17,21 +17,22 @@ import process from "node:process";
import * as remoteMain from "@electron/remote/main";
import windowStateKeeper from "electron-window-state";
import * as ConfigUtil from "../common/config-util.js";
import {bundlePath, bundleUrl, publicPath} from "../common/paths.js";
import type {RendererMessage} from "../common/typed-ipc.js";
import type {MenuProperties} from "../common/types.js";
import * as ConfigUtil from "../common/config-util.ts";
import {bundlePath, bundleUrl, publicPath} from "../common/paths.ts";
import * as t from "../common/translation-util.ts";
import type {RendererMessage} from "../common/typed-ipc.ts";
import type {MenuProperties} from "../common/types.ts";
import {appUpdater, shouldQuitForUpdate} from "./autoupdater.js";
import * as BadgeSettings from "./badge-settings.js";
import handleExternalLink from "./handle-external-link.js";
import * as AppMenu from "./menu.js";
import {_getServerSettings, _isOnline, _saveServerIcon} from "./request.js";
import {sentryInit} from "./sentry.js";
import {setAutoLaunch} from "./startup.js";
import {ipcMain, send} from "./typed-ipc-main.js";
import {appUpdater, shouldQuitForUpdate} from "./autoupdater.ts";
import * as BadgeSettings from "./badge-settings.ts";
import handleExternalLink from "./handle-external-link.ts";
import * as AppMenu from "./menu.ts";
import {_getServerSettings, _isOnline, _saveServerIcon} from "./request.ts";
import {sentryInit} from "./sentry.ts";
import {setAutoLaunch} from "./startup.ts";
import {ipcMain, send} from "./typed-ipc-main.ts";
import "gatemaker/electron-setup"; // eslint-disable-line import/no-unassigned-import
import "gatemaker/electron-setup.js"; // eslint-disable-line import-x/no-unassigned-import
// eslint-disable-next-line @typescript-eslint/naming-convention
const {GDK_BACKEND} = process.env;
@@ -86,7 +87,7 @@ function createMainWindow(): BrowserWindow {
minWidth: 500,
minHeight: 400,
webPreferences: {
preload: path.join(bundlePath, "renderer.js"),
preload: path.join(bundlePath, "renderer.cjs"),
sandbox: false,
webviewTag: true,
},
@@ -238,9 +239,9 @@ function createMainWindow(): BrowserWindow {
try {
// Check that the data on the clipboard was encrypted to the key.
const data = Buffer.from(clipboard.readText(), "hex");
const iv = data.slice(0, 12);
const ciphertext = data.slice(12, -16);
const authTag = data.slice(-16);
const iv = data.subarray(0, 12);
const ciphertext = data.subarray(12, -16);
const authTag = data.subarray(-16);
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv, {
authTagLength: 16,
});
@@ -318,10 +319,11 @@ function createMainWindow(): BrowserWindow {
if (isMainFrame) {
const url = new URL(urlString);
dialog.showErrorBox(
"Certificate error",
`The server presented an invalid certificate for ${url.origin}:
${error}`,
t.__("Certificate error"),
t.__(
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}",
{origin: url.origin, error},
),
);
}
},
@@ -428,7 +430,7 @@ ${error}`,
AppMenu.setMenu(properties);
if (properties.activeTabIndex !== undefined) {
const activeTab = properties.tabs[properties.activeTabIndex];
mainWindow.setTitle(`Zulip - ${activeTab.name}`);
mainWindow.setTitle(`Zulip - ${activeTab.label}`);
}
});

View File

@@ -3,9 +3,10 @@ import fs from "node:fs";
import path from "node:path";
import {JsonDB} from "node-json-db";
import {DataError} from "node-json-db/dist/lib/Errors";
import {DataError} from "node-json-db/dist/lib/Errors.js";
import Logger from "../common/logger-util.js";
import Logger from "../common/logger-util.ts";
import * as t from "../common/translation-util.ts";
const logger = new Logger({
file: "linux-update-util.log",
@@ -57,8 +58,8 @@ function reloadDatabase(): void {
if (fs.existsSync(linuxUpdateJsonPath)) {
fs.unlinkSync(linuxUpdateJsonPath);
dialog.showErrorBox(
"Error saving update notifications.",
"We encountered an error while saving the update notifications.",
t.__("Error saving update notifications"),
t.__("We encountered an error while saving the update notifications."),
);
logger.error("Error while JSON parsing updates.json: ");
logger.error(error);

View File

@@ -3,10 +3,11 @@ import {Notification, type Session, app} from "electron/main";
import * as semver from "semver";
import {z} from "zod";
import * as ConfigUtil from "../common/config-util.js";
import Logger from "../common/logger-util.js";
import * as ConfigUtil from "../common/config-util.ts";
import Logger from "../common/logger-util.ts";
import * as t from "../common/translation-util.ts";
import * as LinuxUpdateUtil from "./linux-update-util.js";
import * as LinuxUpdateUtil from "./linux-update-util.ts";
const logger = new Logger({
file: "linux-update-util.log",
@@ -34,8 +35,11 @@ export async function linuxUpdateNotification(session: Session): Promise<void> {
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.`,
title: t.__("Zulip Update"),
body: t.__(
"A new version {{{version}}} is available. Please update using your package manager.",
{version: latestVersion},
),
}).show();
LinuxUpdateUtil.setUpdateItem(latestVersion, true);
}

View File

@@ -9,14 +9,14 @@ import process from "node:process";
import AdmZip from "adm-zip";
import * as ConfigUtil from "../common/config-util.js";
import * as DNDUtil from "../common/dnd-util.js";
import * as t from "../common/translation-util.js";
import type {RendererMessage} from "../common/typed-ipc.js";
import type {MenuProperties, TabData} from "../common/types.js";
import * as ConfigUtil from "../common/config-util.ts";
import * as DNDUtil from "../common/dnd-util.ts";
import * as t from "../common/translation-util.ts";
import type {RendererMessage} from "../common/typed-ipc.ts";
import type {MenuProperties, TabData} from "../common/types.ts";
import {appUpdater} from "./autoupdater.js";
import {send} from "./typed-ipc-main.js";
import {appUpdater} from "./autoupdater.ts";
import {send} from "./typed-ipc-main.ts";
const appName = app.name;
@@ -94,7 +94,7 @@ function getToolsSubmenu(): MenuItemConstructorOptions[] {
accelerator:
process.platform === "darwin" ? "Alt+Command+I" : "Ctrl+Shift+I",
click(_item, focusedWindow) {
if (focusedWindow) {
if (focusedWindow instanceof BrowserWindow) {
focusedWindow.webContents.openDevTools({mode: "undocked"});
}
},
@@ -222,7 +222,7 @@ function getViewSubmenu(): MenuItemConstructorOptions[] {
{
label: t.__("Toggle Tray Icon"),
click(_item, focusedWindow) {
if (focusedWindow) {
if (focusedWindow instanceof BrowserWindow) {
send(focusedWindow.webContents, "toggletray");
}
},
@@ -231,7 +231,7 @@ function getViewSubmenu(): MenuItemConstructorOptions[] {
label: t.__("Toggle Sidebar"),
accelerator: "CommandOrControl+Shift+S",
click(_item, focusedWindow) {
if (focusedWindow) {
if (focusedWindow instanceof BrowserWindow) {
const newValue = !ConfigUtil.getConfigItem("showSidebar", true);
send(focusedWindow.webContents, "toggle-sidebar", newValue);
ConfigUtil.setConfigItem("showSidebar", newValue);
@@ -243,7 +243,7 @@ function getViewSubmenu(): MenuItemConstructorOptions[] {
checked: ConfigUtil.getConfigItem("autoHideMenubar", false),
visible: process.platform !== "darwin",
click(_item, focusedWindow) {
if (focusedWindow) {
if (focusedWindow instanceof BrowserWindow) {
const newValue = !ConfigUtil.getConfigItem("autoHideMenubar", false);
focusedWindow.autoHideMenuBar = newValue;
focusedWindow.setMenuBarVisibility(!newValue);
@@ -318,12 +318,12 @@ function getWindowSubmenu(
if (tab === undefined) continue;
// Do not add functional tab settings to list of windows in menu bar
if (tab.role === "function" && tab.name === "Settings") {
if (tab.role === "function" && tab.page === "Settings") {
continue;
}
initialSubmenu.push({
label: tab.name,
label: tab.label,
accelerator:
tab.role === "function" ? "" : `${shortcutKey} + ${tab.index + 1}`,
checked: tab.index === activeTabIndex,

View File

@@ -8,9 +8,9 @@ import type {ReadableStream} from "node:stream/web";
import * as Sentry from "@sentry/electron/main";
import {z} from "zod";
import Logger from "../common/logger-util.js";
import * as Messages from "../common/messages.js";
import type {ServerConfig} from "../common/types.js";
import Logger from "../common/logger-util.ts";
import * as Messages from "../common/messages.ts";
import type {ServerConfig} from "../common/types.ts";
/* Request: domain-util */
@@ -59,7 +59,7 @@ export const _getServerSettings = async (
} = z
.object({
realm_name: z.string(),
realm_uri: z.string().url(),
realm_uri: z.url(),
realm_icon: z.string(),
zulip_version: z.string().default("unknown"),
zulip_feature_level: z.number().default(0),

View File

@@ -2,7 +2,7 @@ import {app} from "electron/main";
import * as Sentry from "@sentry/electron/main";
import {getConfigItem} from "../common/config-util.js";
import {getConfigItem} from "../common/config-util.ts";
export const sentryInit = (): void => {
Sentry.init({

View File

@@ -3,7 +3,7 @@ import process from "node:process";
import AutoLaunch from "auto-launch";
import * as ConfigUtil from "../common/config-util.js";
import * as ConfigUtil from "../common/config-util.ts";
export const setAutoLaunch = async (
AutoLaunchValue: boolean,

View File

@@ -6,21 +6,4 @@
<div class="about" hidden>
<img class="logo" src="../resources/zulip.png" />
<p class="detail" id="version"></p>
<div class="maintenance-info">
<p class="detail maintainer">
Maintained by
<a href="https://zulip.com" target="_blank" rel="noopener noreferrer"
>Zulip</a
>
</p>
<p class="detail license">
Available under the
<a
href="https://github.com/zulip/zulip-desktop/blob/main/LICENSE"
target="_blank"
rel="noopener noreferrer"
>Apache 2.0 License</a
>
</p>
</div>
</div>

View File

@@ -47,7 +47,6 @@
}
.maintenance-info {
cursor: pointer;
position: absolute;
width: 100%;
left: 0;

View File

@@ -85,7 +85,7 @@ body {
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
overflow-wrap: normal;
white-space: nowrap;
direction: ltr;
@@ -114,12 +114,20 @@ body {
}
.action-button i {
color: rgb(108 133 146 / 100%);
color: hsl(200.53deg 14.96% 49.8%);
font-size: 28px;
}
.action-button:hover i {
color: rgb(152 169 179 / 100%);
color: hsl(202.22deg 15.08% 64.9%);
}
.action-button > .dnd-on {
color: hsl(200.53deg 14.96% 85%);
}
.action-button:hover > .dnd-on {
color: hsl(202.22deg 15.08% 95%);
}
.action-button.active {

View File

@@ -11,7 +11,7 @@
background: rgb(239 239 239 / 100%);
letter-spacing: -0.08px;
line-height: 18px;
color: rgb(139 142 143 / 100%);
color: rgb(34 44 49 / 100%);
/* Copied from https://github.com/yairEO/tagify/blob/v4.17.7/src/tagify.scss#L4-L8 */
--tagify-dd-color-primary: rgb(53 149 246);
@@ -68,7 +68,7 @@ td:nth-child(odd) {
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
overflow-wrap: normal;
white-space: nowrap;
direction: ltr;
@@ -101,7 +101,7 @@ td:nth-child(odd) {
.nav {
padding: 7px 0;
color: rgb(153 153 153 / 100%);
color: rgb(70 78 90 / 100%);
cursor: pointer;
}
@@ -578,7 +578,6 @@ input.toggle-round:checked + label::after {
text-align: center;
color: rgb(255 255 255 / 100%);
background: rgb(78 191 172 / 100%);
border-color: none;
border: none;
width: 98%;
height: 46px;

View File

@@ -1,4 +1,4 @@
import {ipcRenderer} from "./typed-ipc-renderer.js";
import {ipcRenderer} from "./typed-ipc-renderer.ts";
// This helper is exposed via electron_bridge for use in the social
// login flow.
@@ -33,10 +33,7 @@ export class ClipboardDecrypterImplementation implements ClipboardDecrypter {
this.pasted = new Promise((resolve) => {
let interval: NodeJS.Timeout | null = null;
const startPolling = () => {
if (interval === null) {
interval = setInterval(poll, 1000);
}
interval ??= setInterval(poll, 1000);
void poll();
};

View File

@@ -1,4 +1,4 @@
import type {Html} from "../../../common/html.js";
import type {Html} from "../../../common/html.ts";
export function generateNodeFromHtml(html: Html): Element {
const wrapper = document.createElement("div");

View File

@@ -6,9 +6,9 @@ import type {
} from "electron/renderer";
import process from "node:process";
import {Menu} from "@electron/remote";
import {BrowserWindow, Menu} from "@electron/remote";
import * as t from "../../../common/translation-util.js";
import * as t from "../../../common/translation-util.ts";
export const contextMenu = (
webContents: WebContents,
@@ -115,15 +115,6 @@ export const contextMenu = (
});
},
},
{
type: "separator",
visible: isLink || properties.mediaType === "image",
},
{
label: t.__("Services"),
visible: process.platform === "darwin",
role: "services",
},
];
if (properties.misspelledWord) {
@@ -149,5 +140,11 @@ export const contextMenu = (
(menuItem) => menuItem.visible ?? true,
);
const menu = Menu.buildFromTemplate(filteredMenuTemplate);
menu.popup();
menu.popup({
window: BrowserWindow.fromWebContents(webContents) ?? undefined,
frame: properties.frame ?? undefined,
x: properties.x,
y: properties.y,
sourceType: properties.menuSourceType,
});
};

View File

@@ -1,10 +1,12 @@
import {type Html, html} from "../../../common/html.js";
import {type Html, html} from "../../../common/html.ts";
import type {TabPage} from "../../../common/types.ts";
import {generateNodeFromHtml} from "./base.js";
import Tab, {type TabProperties} from "./tab.js";
import {generateNodeFromHtml} from "./base.ts";
import Tab, {type TabProperties} from "./tab.ts";
export type FunctionalTabProperties = {
$view: Element;
page: TabPage;
} & TabProperties;
export default class FunctionalTab extends Tab {
@@ -17,7 +19,7 @@ export default class FunctionalTab extends Tab {
this.$view = $view;
this.$el = generateNodeFromHtml(this.templateHtml());
if (this.properties.name !== "Settings") {
if (properties.page !== "Settings") {
this.properties.$root.append(this.$el);
this.$closeButton = this.$el.querySelector(".server-tab-badge")!;
this.registerListeners();

View File

@@ -1,11 +1,11 @@
import process from "node:process";
import {type Html, html} from "../../../common/html.js";
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {type Html, html} from "../../../common/html.ts";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
import {generateNodeFromHtml} from "./base.js";
import Tab, {type TabProperties} from "./tab.js";
import type WebView from "./webview.js";
import {generateNodeFromHtml} from "./base.ts";
import Tab, {type TabProperties} from "./tab.ts";
import type WebView from "./webview.ts";
export type ServerTabProperties = {
webview: Promise<WebView>;
@@ -49,7 +49,7 @@ export default class ServerTab extends Tab {
return html`
<div class="tab" data-tab-id="${this.properties.tabIndex}">
<div class="server-tooltip" style="display:none">
${this.properties.name}
${this.properties.label}
</div>
<div class="server-tab-badge"></div>
<div class="server-tab">
@@ -60,9 +60,9 @@ export default class ServerTab extends Tab {
`;
}
setName(name: string): void {
this.properties.name = name;
this.$name.textContent = name;
setLabel(label: string): void {
this.properties.label = label;
this.$name.textContent = label;
}
setIcon(icon: string): void {

View File

@@ -1,9 +1,10 @@
import type {TabRole} from "../../../common/types.js";
import type {TabPage, TabRole} from "../../../common/types.ts";
export type TabProperties = {
role: TabRole;
page?: TabPage;
icon?: string;
name: string;
label: string;
$root: Element;
onClick: () => void;
index: number;

View File

@@ -1,20 +1,20 @@
import type {WebContents} from "electron/main";
import fs from "node:fs";
import process from "node:process";
import * as remote from "@electron/remote";
import {app, dialog} from "@electron/remote";
import * as ConfigUtil from "../../../common/config-util.js";
import {type Html, html} from "../../../common/html.js";
import type {RendererMessage} from "../../../common/typed-ipc.js";
import type {TabRole} from "../../../common/types.js";
import * as ConfigUtil from "../../../common/config-util.ts";
import {type Html, html} from "../../../common/html.ts";
import * as t from "../../../common/translation-util.ts";
import type {RendererMessage} from "../../../common/typed-ipc.ts";
import type {TabRole} from "../../../common/types.ts";
import preloadCss from "../../css/preload.css?raw";
import {ipcRenderer} from "../typed-ipc-renderer.js";
import * as SystemUtil from "../utils/system-util.js";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
import * as SystemUtil from "../utils/system-util.ts";
import {generateNodeFromHtml} from "./base.js";
import {contextMenu} from "./context-menu.js";
import {generateNodeFromHtml} from "./base.ts";
import {contextMenu} from "./context-menu.ts";
const shouldSilentWebview = ConfigUtil.getConfigItem("silent", false);
@@ -142,6 +142,7 @@ export default class WebView {
showNotificationSettings(): void {
this.send("show-notification-settings");
this.focus();
}
focus(): void {
@@ -176,6 +177,7 @@ export default class WebView {
showKeyboardShortcuts(): void {
this.send("show-keyboard-shortcuts");
this.focus();
}
openDevTools(): void {
@@ -183,8 +185,8 @@ export default class WebView {
}
back(): void {
if (this.getWebContents().canGoBack()) {
this.getWebContents().goBack();
if (this.getWebContents().navigationHistory.canGoBack()) {
this.getWebContents().navigationHistory.goBack();
this.focus();
}
}
@@ -193,12 +195,15 @@ export default class WebView {
const $backButton = document.querySelector(
"#actions-container #back-action",
)!;
$backButton.classList.toggle("disable", !this.getWebContents().canGoBack());
$backButton.classList.toggle(
"disable",
!this.getWebContents().navigationHistory.canGoBack(),
);
}
forward(): void {
if (this.getWebContents().canGoForward()) {
this.getWebContents().goForward();
if (this.getWebContents().navigationHistory.canGoForward()) {
this.getWebContents().navigationHistory.goForward();
}
}
@@ -247,10 +252,7 @@ export default class WebView {
webContents.on("page-favicon-updated", (_event, favicons) => {
// This returns a string of favicons URL. If there is a PM counts in unread messages then the URL would be like
// https://chat.zulip.org/static/images/favicon/favicon-pms.png
if (
favicons[0].indexOf("favicon-pms") > 0 &&
process.platform === "darwin"
) {
if (favicons[0].indexOf("favicon-pms") > 0 && app.dock !== undefined) {
// This api is only supported on macOS
app.dock.setBadge("●");
// Bounce the dock
@@ -328,8 +330,8 @@ export default class WebView {
this.customCss = null;
ConfigUtil.setConfigItem("customCSS", null);
const errorMessage = "The custom css previously set is deleted!";
dialog.showErrorBox("custom css file deleted!", errorMessage);
const errorMessage = t.__("The custom CSS previously set is deleted.");
dialog.showErrorBox(t.__("Custom CSS file deleted"), errorMessage);
return;
}

View File

@@ -1,17 +1,17 @@
import {EventEmitter} from "node:events";
import * as z from "zod";
import {
type ClipboardDecrypter,
ClipboardDecrypterImplementation,
} from "./clipboard-decrypter.js";
import {type NotificationData, newNotification} from "./notification/index.js";
import {ipcRenderer} from "./typed-ipc-renderer.js";
} from "./clipboard-decrypter.ts";
import {type NotificationData, newNotification} from "./notification/index.ts";
import {ipcRenderer} from "./typed-ipc-renderer.ts";
type ListenerType = (...arguments_: any[]) => void;
type ListenerType = (...arguments_: unknown[]) => void;
/* eslint-disable @typescript-eslint/naming-convention */
export type ElectronBridge = {
send_event: (eventName: string | symbol, ...arguments_: unknown[]) => boolean;
send_event: (eventName: string, ...arguments_: unknown[]) => boolean;
on_event: (eventName: string, listener: ListenerType) => void;
new_notification: (
title: string,
@@ -32,15 +32,26 @@ let idle = false;
// Indicates the time at which user was last active
let lastActive = Date.now();
export const bridgeEvents = new EventEmitter(); // eslint-disable-line unicorn/prefer-event-target
export const bridgeEvents = new EventTarget();
export class BridgeEvent extends Event {
constructor(
type: string,
public readonly arguments_: unknown[] = [],
) {
super(type);
}
}
/* eslint-disable @typescript-eslint/naming-convention */
const electron_bridge: ElectronBridge = {
send_event: (eventName: string | symbol, ...arguments_: unknown[]): boolean =>
bridgeEvents.emit(eventName, ...arguments_),
send_event: (eventName: string, ...arguments_: unknown[]): boolean =>
bridgeEvents.dispatchEvent(new BridgeEvent(eventName, arguments_)),
on_event(eventName: string, listener: ListenerType): void {
bridgeEvents.on(eventName, listener);
bridgeEvents.addEventListener(eventName, (event) => {
listener(...z.instanceof(BridgeEvent).parse(event).arguments_);
});
},
new_notification: (
@@ -65,28 +76,25 @@ const electron_bridge: ElectronBridge = {
};
/* eslint-enable @typescript-eslint/naming-convention */
bridgeEvents.on("total_unread_count", (unreadCount: unknown) => {
if (typeof unreadCount !== "number") {
throw new TypeError("Expected string for unreadCount");
}
bridgeEvents.addEventListener("total_unread_count", (event) => {
const [unreadCount] = z
.tuple([z.number()])
.parse(z.instanceof(BridgeEvent).parse(event).arguments_);
ipcRenderer.send("unread-count", unreadCount);
});
bridgeEvents.on("realm_name", (realmName: unknown) => {
if (typeof realmName !== "string") {
throw new TypeError("Expected string for realmName");
}
bridgeEvents.addEventListener("realm_name", (event) => {
const [realmName] = z
.tuple([z.string()])
.parse(z.instanceof(BridgeEvent).parse(event).arguments_);
const serverUrl = location.origin;
ipcRenderer.send("realm-name-changed", serverUrl, realmName);
});
bridgeEvents.on("realm_icon_url", (iconUrl: unknown) => {
if (typeof iconUrl !== "string") {
throw new TypeError("Expected string for iconUrl");
}
bridgeEvents.addEventListener("realm_icon_url", (event) => {
const [iconUrl] = z
.tuple([z.string()])
.parse(z.instanceof(BridgeEvent).parse(event).arguments_);
const serverUrl = location.origin;
ipcRenderer.send(
"realm-icon-changed",

View File

@@ -1,3 +1,5 @@
import "./zod-config.ts"; // eslint-disable-line import-x/no-unassigned-import
import {clipboard} from "electron/common";
import path from "node:path";
import process from "node:process";
@@ -7,31 +9,34 @@ import {Menu, app, dialog, session} from "@electron/remote";
import * as remote from "@electron/remote";
import * as Sentry from "@sentry/electron/renderer";
import type {Config} from "../../common/config-util.js";
import * as ConfigUtil from "../../common/config-util.js";
import * as DNDUtil from "../../common/dnd-util.js";
import type {DndSettings} from "../../common/dnd-util.js";
import * as EnterpriseUtil from "../../common/enterprise-util.js";
import * as LinkUtil from "../../common/link-util.js";
import Logger from "../../common/logger-util.js";
import * as Messages from "../../common/messages.js";
import {bundlePath, bundleUrl} from "../../common/paths.js";
import type {Config} from "../../common/config-util.ts";
import * as ConfigUtil from "../../common/config-util.ts";
import * as DNDUtil from "../../common/dnd-util.ts";
import type {DndSettings} from "../../common/dnd-util.ts";
import * as EnterpriseUtil from "../../common/enterprise-util.ts";
import {html} from "../../common/html.ts";
import * as LinkUtil from "../../common/link-util.ts";
import Logger from "../../common/logger-util.ts";
import * as Messages from "../../common/messages.ts";
import {bundlePath, bundleUrl} from "../../common/paths.ts";
import * as t from "../../common/translation-util.ts";
import type {
NavigationItem,
ServerConfig,
TabData,
TabPage,
} from "../../common/types.js";
import defaultIcon from "../img/icon.png";
import FunctionalTab from "./components/functional-tab.js";
import ServerTab from "./components/server-tab.js";
import WebView from "./components/webview.js";
import {AboutView} from "./pages/about.js";
import {PreferenceView} from "./pages/preference/preference.js";
import {initializeTray} from "./tray.js";
import {ipcRenderer} from "./typed-ipc-renderer.js";
import * as DomainUtil from "./utils/domain-util.js";
import ReconnectUtil from "./utils/reconnect-util.js";
import FunctionalTab from "./components/functional-tab.ts";
import ServerTab from "./components/server-tab.ts";
import WebView from "./components/webview.ts";
import {AboutView} from "./pages/about.ts";
import {PreferenceView} from "./pages/preference/preference.ts";
import {initializeTray} from "./tray.ts";
import {ipcRenderer} from "./typed-ipc-renderer.ts";
import * as DomainUtil from "./utils/domain-util.ts";
import ReconnectUtil from "./utils/reconnect-util.ts";
Sentry.init({});
@@ -77,11 +82,10 @@ export class ServerManagerView {
$dndTooltip: HTMLElement;
$sidebar: Element;
$fullscreenPopup: Element;
$fullscreenEscapeKey: string;
loading: Set<string>;
activeTabIndex: number;
tabs: ServerOrFunctionalTab[];
functionalTabs: Map<string, number>;
functionalTabs: Map<TabPage, number>;
tabIndex: number;
presetOrgs: string[];
preferenceView?: PreferenceView;
@@ -118,8 +122,10 @@ export class ServerManagerView {
this.$sidebar = document.querySelector("#sidebar")!;
this.$fullscreenPopup = document.querySelector("#fullscreen-popup")!;
this.$fullscreenEscapeKey = process.platform === "darwin" ? "^⌘F" : "F11";
this.$fullscreenPopup.textContent = `Press ${this.$fullscreenEscapeKey} to exit full screen`;
this.$fullscreenPopup.textContent = t.__(
"Press {{{exitKey}}} to exit full screen",
{exitKey: process.platform === "darwin" ? "^⌘F" : "F11"},
);
this.loading = new Set();
this.activeTabIndex = -1;
@@ -258,7 +264,10 @@ export class ServerManagerView {
} catch (error: unknown) {
logger.error(error);
logger.error(
`Could not add ${domain}. Please contact your system administrator.`,
t.__(
"Could not add {{{domain}}}. Please contact your system administrator.",
{domain},
),
);
return false;
}
@@ -287,12 +296,9 @@ export class ServerManagerView {
// ask them before reloading the app
const {response} = await dialog.showMessageBox({
type: "question",
buttons: ["Yes", "Later"],
buttons: [t.__("Yes"), t.__("Later")],
defaultId: 0,
message:
"New server" +
(domainsAdded.length > 1 ? "s" : "") +
" added. Reload app now?",
message: t.__("New servers added. Reload app now?"),
});
if (response === 0) {
ipcRenderer.send("reload-full-app");
@@ -311,10 +317,7 @@ export class ServerManagerView {
failedDomains.push(org);
}
const {title, content} = Messages.enterpriseOrgError(
domainsAdded.length,
failedDomains,
);
const {title, content} = Messages.enterpriseOrgError(failedDomains);
dialog.showErrorBox(title, content);
if (DomainUtil.getDomains().length === 0) {
// No orgs present, stop showing loading gif
@@ -333,7 +336,7 @@ export class ServerManagerView {
server.url,
i,
);
tab.setName(serverConfig.alias);
tab.setLabel(serverConfig.alias);
tab.setIcon(DomainUtil.iconAsUrl(serverConfig.icon));
(await tab.webview).setUnsupportedMessage(
DomainUtil.getUnsupportedMessage(serverConfig),
@@ -376,7 +379,7 @@ export class ServerManagerView {
const tab = new ServerTab({
role: "server",
icon: DomainUtil.iconAsUrl(server.icon),
name: server.alias,
label: server.alias,
$root: this.$tabsContainer,
onClick: this.activateLastTab.bind(this, index),
index,
@@ -412,7 +415,7 @@ export class ServerManagerView {
await this.openNetworkTroubleshooting(index);
},
onTitleChange: this.updateBadge.bind(this),
preload: url.pathToFileURL(path.join(bundlePath, "preload.js")).href,
preload: url.pathToFileURL(path.join(bundlePath, "preload.cjs")).href,
unsupportedMessage: DomainUtil.getUnsupportedMessage(server),
}),
});
@@ -511,8 +514,7 @@ export class ServerManagerView {
}
$altIcon.textContent = realmName.charAt(0) || "Z";
$altIcon.classList.add("server-icon");
$altIcon.classList.add("alt-icon");
$altIcon.classList.add("server-icon", "alt-icon");
$img.remove();
$parent.append($altIcon);
@@ -558,18 +560,19 @@ export class ServerManagerView {
}
async openFunctionalTab(tabProperties: {
name: string;
label: string;
page: TabPage;
materialIcon: string;
makeView: () => Promise<Element>;
destroyView: () => void;
}): Promise<void> {
if (this.functionalTabs.has(tabProperties.name)) {
await this.activateTab(this.functionalTabs.get(tabProperties.name)!);
if (this.functionalTabs.has(tabProperties.page)) {
await this.activateTab(this.functionalTabs.get(tabProperties.page)!);
return;
}
const index = this.tabs.length;
this.functionalTabs.set(tabProperties.name, index);
this.functionalTabs.set(tabProperties.page, index);
const tabIndex = this.getTabIndex();
const $view = await tabProperties.makeView();
@@ -579,13 +582,14 @@ export class ServerManagerView {
new FunctionalTab({
role: "function",
materialIcon: tabProperties.materialIcon,
name: tabProperties.name,
label: tabProperties.label,
page: tabProperties.page,
$root: this.$tabsContainer,
index,
tabIndex,
onClick: this.activateTab.bind(this, index),
onDestroy: async () => {
await this.destroyTab(tabProperties.name, index);
await this.destroyFunctionalTab(tabProperties.page, index);
tabProperties.destroyView();
},
$view,
@@ -596,14 +600,15 @@ export class ServerManagerView {
// closed when the functional tab DOM is ready, handled in webview.js
this.$webviewsContainer.classList.remove("loaded");
await this.activateTab(this.functionalTabs.get(tabProperties.name)!);
await this.activateTab(this.functionalTabs.get(tabProperties.page)!);
}
async openSettings(
navigationItem: NavigationItem = "General",
): Promise<void> {
await this.openFunctionalTab({
name: "Settings",
page: "Settings",
label: t.__("Settings"),
materialIcon: "settings",
makeView: async () => {
this.preferenceView = await PreferenceView.create();
@@ -622,7 +627,8 @@ export class ServerManagerView {
async openAbout(): Promise<void> {
let aboutView: AboutView;
await this.openFunctionalTab({
name: "About",
page: "About",
label: t.__("About"),
materialIcon: "sentiment_very_satisfied",
async makeView() {
aboutView = await AboutView.create();
@@ -660,7 +666,8 @@ export class ServerManagerView {
get tabsForIpc(): TabData[] {
return this.tabs.map((tab) => ({
role: tab.properties.role,
name: tab.properties.name,
page: tab.properties.page,
label: tab.properties.label,
index: tab.properties.index,
}));
}
@@ -680,7 +687,7 @@ export class ServerManagerView {
// If old tab is functional tab Settings, remove focus from the settings icon at sidebar bottom
if (
this.tabs[this.activeTabIndex].properties.role === "function" &&
this.tabs[this.activeTabIndex].properties.name === "Settings"
this.tabs[this.activeTabIndex].properties.page === "Settings"
) {
this.$settingsButton.classList.remove("active");
}
@@ -722,7 +729,7 @@ export class ServerManagerView {
this.$loadingIndicator.classList.toggle("hidden", !loading);
}
async destroyTab(name: string, index: number): Promise<void> {
async destroyFunctionalTab(page: TabPage, index: number): Promise<void> {
const tab = this.tabs[index];
if (tab instanceof ServerTab && (await tab.webview).loading) {
return;
@@ -731,7 +738,7 @@ export class ServerManagerView {
await tab.destroy();
delete this.tabs[index]; // eslint-disable-line @typescript-eslint/no-array-delete
this.functionalTabs.delete(name);
this.functionalTabs.delete(page);
// Issue #188: If the functional tab was not focused, do not activate another tab.
if (this.activeTabIndex === index) {
@@ -791,11 +798,17 @@ export class ServerManagerView {
// Toggles the dnd button icon.
toggleDndButton(alert: boolean): void {
this.$dndTooltip.textContent =
(alert ? "Disable" : "Enable") + " Do Not Disturb";
this.$dndButton.querySelector("i")!.textContent = alert
? "notifications_off"
: "notifications";
this.$dndTooltip.textContent = alert
? t.__("Disable Do Not Disturb")
: t.__("Enable Do Not Disturb");
const $dndIcon = this.$dndButton.querySelector("i")!;
$dndIcon.textContent = alert ? "notifications_off" : "notifications";
if (alert) {
$dndIcon.classList.add("dnd-on");
} else {
$dndIcon.classList.remove("dnd-on");
}
}
async isLoggedIn(tabIndex: number): Promise<boolean> {
@@ -811,13 +824,15 @@ export class ServerManagerView {
event.preventDefault();
const template = [
{
label: "Disconnect organization",
label: t.__("Disconnect organization"),
async click() {
const {response} = await dialog.showMessageBox({
type: "warning",
buttons: ["YES", "NO"],
buttons: [t.__("Yes"), t.__("No")],
defaultId: 0,
message: "Are you sure you want to disconnect this organization?",
message: t.__(
"Are you sure you want to disconnect this organization?",
),
});
if (response === 0) {
if (DomainUtil.removeDomain(index)) {
@@ -832,7 +847,7 @@ export class ServerManagerView {
},
},
{
label: "Notification settings",
label: t.__("Notification settings"),
enabled: await this.isLoggedIn(index),
click: async () => {
// Switch to tab whose icon was right-clicked
@@ -843,7 +858,7 @@ export class ServerManagerView {
},
},
{
label: "Copy Zulip URL",
label: t.__("Copy Zulip URL"),
click() {
clipboard.writeText(DomainUtil.getDomain(index).url);
},
@@ -1002,8 +1017,8 @@ export class ServerManagerView {
await this.loadProxy();
if (showAlert) {
await dialog.showMessageBox({
message: "Proxy settings saved!",
buttons: ["OK"],
message: t.__("Proxy settings saved."),
buttons: [t.__("OK")],
});
ipcRenderer.send("reload-full-app");
}
@@ -1053,7 +1068,7 @@ export class ServerManagerView {
for (const [index, domain] of DomainUtil.getDomains().entries()) {
if (domain.url === serverURL) {
const tab = this.tabs[index];
if (tab instanceof ServerTab) tab.setName(realmName);
if (tab instanceof ServerTab) tab.setLabel(realmName);
domain.alias = realmName;
DomainUtil.updateDomain(index, domain);
// Update the realm name also on the Window menu
@@ -1179,6 +1194,62 @@ export class ServerManagerView {
}
window.addEventListener("load", async () => {
document.body.innerHTML = html`
<div id="content">
<div class="popup">
<span class="popuptext hidden" id="fullscreen-popup"></span>
</div>
<div id="sidebar" class="toggle-sidebar">
<div id="view-controls-container">
<div id="tabs-container"></div>
<div id="add-tab" class="tab functional-tab">
<div class="server-tab" id="add-action">
<i class="material-icons">add</i>
</div>
<span id="add-server-tooltip" style="display: none"
>${t.__("Add Organization")}</span
>
</div>
</div>
<div id="actions-container">
<div class="action-button" id="dnd-action">
<i class="material-icons md-48">notifications</i>
<span id="dnd-tooltip" style="display: none"
>${t.__("Do Not Disturb")}</span
>
</div>
<div class="action-button hidden" id="reload-action">
<i class="material-icons md-48">refresh</i>
<span id="reload-tooltip" style="display: none"
>${t.__("Reload")}</span
>
</div>
<div class="action-button disable" id="loading-action">
<i class="refresh material-icons md-48">loop</i>
<span id="loading-tooltip" style="display: none"
>${t.__("Loading")}</span
>
</div>
<div class="action-button disable" id="back-action">
<i class="material-icons md-48">arrow_back</i>
<span id="back-tooltip" style="display: none"
>${t.__("Go Back")}</span
>
</div>
<div class="action-button" id="settings-action">
<i class="material-icons md-48">settings</i>
<span id="setting-tooltip" style="display: none"
>${t.__("Settings")}</span
>
</div>
</div>
</div>
<div id="main-container">
<div id="webviews-container"></div>
</div>
</div>
`.html;
const serverManagerView = new ServerManagerView();
await serverManagerView.init();
});

View File

@@ -1,4 +1,4 @@
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
export type NotificationData = {
close: () => void;

View File

@@ -1,6 +1,9 @@
import {app} from "@electron/remote";
import {bundleUrl} from "../../../common/paths.js";
import {Html, html} from "../../../common/html.ts";
import {bundleUrl} from "../../../common/paths.ts";
import * as t from "../../../common/translation-util.ts";
import {generateNodeFromHtml} from "../components/base.ts";
export class AboutView {
static async create(): Promise<AboutView> {
@@ -16,6 +19,32 @@ export class AboutView {
const $shadow = this.$view.attachShadow({mode: "open"});
$shadow.innerHTML = templateHtml;
$shadow.querySelector("#version")!.textContent = `v${app.getVersion()}`;
const maintenanceInfoHtml = html`
<div class="maintenance-info">
<p class="detail maintainer">
${new Html({
html: t.__("Maintained by {{{link}}}Zulip{{{endLink}}}", {
link: '<a href="https://zulip.com" target="_blank" rel="noopener noreferrer">',
endLink: "</a>",
}),
})}
</p>
<p class="detail license">
${new Html({
html: t.__(
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}",
{
link: '<a href="https://github.com/zulip/zulip-desktop/blob/main/LICENSE" target="_blank" rel="noopener noreferrer">',
endLink: "</a>",
},
),
})}
</p>
</div>
`;
$shadow
.querySelector(".about")!
.append(generateNodeFromHtml(maintenanceInfoHtml));
}
destroy() {

View File

@@ -1,4 +1,4 @@
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
export function init(
$reconnectButton: Element,

View File

@@ -1,6 +1,7 @@
import {type Html, html} from "../../../../common/html.js";
import {generateNodeFromHtml} from "../../components/base.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import {type Html, html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import {generateNodeFromHtml} from "../../components/base.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
type BaseSectionProperties = {
$element: HTMLElement;
@@ -31,7 +32,7 @@ export function generateOptionHtml(
const labelHtml = disabled
? html`<label
class="disallowed"
title="Setting locked by system administrator."
title="${t.__("Setting locked by system administrator.")}"
></label>`
: html`<label></label>`;
if (settingOption) {

View File

@@ -1,11 +1,11 @@
import {html} from "../../../../common/html.js";
import * as t from "../../../../common/translation-util.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import * as DomainUtil from "../../utils/domain-util.js";
import {html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import * as DomainUtil from "../../utils/domain-util.ts";
import {reloadApp} from "./base-section.js";
import {initFindAccounts} from "./find-accounts.js";
import {initServerInfoForm} from "./server-info-form.js";
import {reloadApp} from "./base-section.ts";
import {initFindAccounts} from "./find-accounts.ts";
import {initServerInfoForm} from "./server-info-form.ts";
type ConnectedOrgSectionProperties = {
$root: Element;

View File

@@ -1,7 +1,7 @@
import {html} from "../../../../common/html.js";
import * as LinkUtil from "../../../../common/link-util.js";
import * as t from "../../../../common/translation-util.js";
import {generateNodeFromHtml} from "../../components/base.js";
import {html} from "../../../../common/html.ts";
import * as LinkUtil from "../../../../common/link-util.ts";
import * as t from "../../../../common/translation-util.ts";
import {generateNodeFromHtml} from "../../components/base.ts";
type FindAccountsProperties = {
$root: Element;

View File

@@ -6,17 +6,16 @@ import process from "node:process";
import * as remote from "@electron/remote";
import {app, dialog, session} from "@electron/remote";
import Tagify from "@yaireo/tagify";
import ISO6391 from "iso-639-1";
import {z} from "zod";
import supportedLocales from "../../../../../public/translations/supported-locales.json";
import * as ConfigUtil from "../../../../common/config-util.js";
import * as EnterpriseUtil from "../../../../common/enterprise-util.js";
import {html} from "../../../../common/html.js";
import * as t from "../../../../common/translation-util.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import * as ConfigUtil from "../../../../common/config-util.ts";
import * as EnterpriseUtil from "../../../../common/enterprise-util.ts";
import {html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import {generateSelectHtml, generateSettingOption} from "./base-section.js";
import {generateSelectHtml, generateSettingOption} from "./base-section.ts";
const currentBrowserWindow = remote.getCurrentWindow();
@@ -57,7 +56,7 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
</div>
<div class="setting-row" id="badge-option">
<div class="setting-description">
${t.__("Show app unread badge")}
${t.__("Show unread count badge on app icon")}
</div>
<div class="setting-control"></div>
</div>
@@ -456,9 +455,9 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
async function customCssDialog(): Promise<void> {
const showDialogOptions: OpenDialogOptions = {
title: "Select file",
title: t.__("Select file"),
properties: ["openFile"],
filters: [{name: "CSS file", extensions: ["css"]}],
filters: [{name: t.__("CSS file"), extensions: ["css"]}],
};
const {filePaths, canceled} =
@@ -525,7 +524,7 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
async function downloadFolderDialog(): Promise<void> {
const showDialogOptions: OpenDialogOptions = {
title: "Select Download Location",
title: t.__("Select Download Location"),
properties: ["openDirectory"],
};
@@ -562,15 +561,16 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
}
async function factoryResetSettings(): Promise<void> {
const clearAppDataMessage =
"When the application restarts, it will be as if you have just downloaded Zulip app.";
const clearAppDataMessage = t.__(
"When the application restarts, it will be as if you have just downloaded the Zulip app.",
);
const getAppPath = path.join(app.getPath("appData"), app.name);
const {response} = await dialog.showMessageBox({
type: "warning",
buttons: ["YES", "NO"],
buttons: [t.__("Yes"), t.__("No")],
defaultId: 0,
message: "Are you sure?",
message: t.__("Are you sure?"),
detail: clearAppDataMessage,
});
if (response === 0) {
@@ -610,7 +610,7 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
spellDiv.innerHTML += html`
<div class="setting-description">${t.__("Spellchecker Languages")}</div>
<div id="spellcheck-langs-value">
<input name="spellcheck" placeholder="Enter Languages" />
<input name="spellcheck" placeholder="${t.__("Enter Languages")}" />
</div>
`.html;
@@ -619,26 +619,23 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
).availableSpellCheckerLanguages;
let languagePairs = new Map<string, string>();
for (const l of availableLanguages) {
if (ISO6391.validate(l)) {
languagePairs.set(ISO6391.getName(l), l);
}
const locale = new Intl.Locale(l.replaceAll("_", "-"));
let displayName = new Intl.DisplayNames([locale], {
type: "language",
}).of(locale.language);
if (displayName === undefined) continue;
displayName = displayName.replace(/^./u, (firstChar) =>
firstChar.toLocaleUpperCase(locale),
);
if (locale.script !== undefined)
displayName += ` (${new Intl.DisplayNames([locale], {type: "script"}).of(locale.script)})`;
if (locale.region !== undefined)
displayName += ` (${new Intl.DisplayNames([locale], {type: "region"}).of(locale.region)})`;
languagePairs.set(displayName, 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)),
[...languagePairs].sort((a, b) => a[0].localeCompare(b[1])),
);
const tagField: HTMLInputElement = $root.querySelector(

View File

@@ -1,7 +1,7 @@
import {type Html, html} from "../../../../common/html.js";
import * as t from "../../../../common/translation-util.js";
import type {NavigationItem} from "../../../../common/types.js";
import {generateNodeFromHtml} from "../../components/base.js";
import {type Html, html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import type {NavigationItem} from "../../../../common/types.ts";
import {generateNodeFromHtml} from "../../components/base.ts";
type PreferenceNavigationProperties = {
$root: Element;
@@ -9,15 +9,15 @@ type PreferenceNavigationProperties = {
};
export default class PreferenceNavigation {
navigationItems: NavigationItem[];
navigationItems: Array<{navigationItem: NavigationItem; label: string}>;
$el: Element;
constructor(private readonly properties: PreferenceNavigationProperties) {
this.navigationItems = [
"General",
"Network",
"AddServer",
"Organizations",
"Shortcuts",
{navigationItem: "General", label: t.__("General")},
{navigationItem: "Network", label: t.__("Network")},
{navigationItem: "AddServer", label: t.__("Add Organization")},
{navigationItem: "Organizations", label: t.__("Organizations")},
{navigationItem: "Shortcuts", label: t.__("Shortcuts")},
];
this.$el = generateNodeFromHtml(this.templateHtml());
@@ -28,11 +28,8 @@ export default class PreferenceNavigation {
templateHtml(): Html {
const navigationItemsHtml = html``.join(
this.navigationItems.map(
(navigationItem) => html`
<div class="nav" id="nav-${navigationItem}">
${t.__(navigationItem)}
</div>
`,
({navigationItem, label}) =>
html`<div class="nav" id="nav-${navigationItem}">${label}</div>`,
),
);
@@ -45,7 +42,7 @@ export default class PreferenceNavigation {
}
registerListeners(): void {
for (const navigationItem of this.navigationItems) {
for (const {navigationItem} of this.navigationItems) {
const $item = this.$el.querySelector(
`#nav-${CSS.escape(navigationItem)}`,
)!;
@@ -56,7 +53,7 @@ export default class PreferenceNavigation {
}
select(navigationItemToSelect: NavigationItem): void {
for (const navigationItem of this.navigationItems) {
for (const {navigationItem} of this.navigationItems) {
if (navigationItem === navigationItemToSelect) {
this.activate(navigationItem);
} else {

View File

@@ -1,9 +1,9 @@
import * as ConfigUtil from "../../../../common/config-util.js";
import {html} from "../../../../common/html.js";
import * as t from "../../../../common/translation-util.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import * as ConfigUtil from "../../../../common/config-util.ts";
import {html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import {generateSettingOption} from "./base-section.js";
import {generateSettingOption} from "./base-section.ts";
type NetworkSectionProperties = {
$root: Element;
@@ -28,7 +28,7 @@ export function initNetworkSection({$root}: NetworkSectionProperties): void {
</div>
<div class="manual-proxy-block">
<div class="setting-row" id="proxy-pac-option">
<span class="setting-input-key">PAC ${t.__("script")}</span>
<span class="setting-input-key">${t.__("PAC script")}</span>
<input
class="setting-input-value"
placeholder="e.g. foobar.com/pacfile.js"

View File

@@ -1,11 +1,11 @@
import {dialog} from "@electron/remote";
import {html} from "../../../../common/html.js";
import * as LinkUtil from "../../../../common/link-util.js";
import * as t from "../../../../common/translation-util.js";
import {generateNodeFromHtml} from "../../components/base.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import * as DomainUtil from "../../utils/domain-util.js";
import {html} from "../../../../common/html.ts";
import * as LinkUtil from "../../../../common/link-util.ts";
import * as t from "../../../../common/translation-util.ts";
import {generateNodeFromHtml} from "../../components/base.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import * as DomainUtil from "../../utils/domain-util.ts";
type NewServerFormProperties = {
$root: Element;
@@ -23,7 +23,9 @@ export function initNewServerForm({
<input
class="setting-input-value"
autofocus
placeholder="your-organization.zulipchat.com or zulip.your-organization.com"
placeholder="${t.__(
"your-organization.zulipchat.com or zulip.your-organization.com",
)}"
/>
</div>
<div class="server-center">
@@ -60,19 +62,19 @@ export function initNewServerForm({
)!;
async function submitFormHandler(): Promise<void> {
$saveServerButton.textContent = "Connecting...";
$saveServerButton.textContent = t.__("Connecting…");
let serverConfig;
try {
serverConfig = await DomainUtil.checkDomain($newServerUrl.value.trim());
} catch (error: unknown) {
$saveServerButton.textContent = "Connect";
$saveServerButton.textContent = t.__("Connect");
await dialog.showMessageBox({
type: "error",
message:
error instanceof Error
? `${error.name}: ${error.message}`
: "Unknown error",
buttons: ["OK"],
: t.__("Unknown error"),
buttons: [t.__("OK")],
});
return;
}

View File

@@ -1,17 +1,17 @@
import type {IpcRendererEvent} from "electron/renderer";
import process from "node:process";
import type {DndSettings} from "../../../../common/dnd-util.js";
import {bundleUrl} from "../../../../common/paths.js";
import type {NavigationItem} from "../../../../common/types.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import type {DndSettings} from "../../../../common/dnd-util.ts";
import {bundleUrl} from "../../../../common/paths.ts";
import type {NavigationItem} from "../../../../common/types.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import {initConnectedOrgSection} from "./connected-org-section.js";
import {initGeneralSection} from "./general-section.js";
import Nav from "./nav.js";
import {initNetworkSection} from "./network-section.js";
import {initServersSection} from "./servers-section.js";
import {initShortcutsSection} from "./shortcuts-section.js";
import {initConnectedOrgSection} from "./connected-org-section.ts";
import {initGeneralSection} from "./general-section.ts";
import Nav from "./nav.ts";
import {initNetworkSection} from "./network-section.ts";
import {initServersSection} from "./servers-section.ts";
import {initShortcutsSection} from "./shortcuts-section.ts";
export class PreferenceView {
static async create(): Promise<PreferenceView> {
@@ -90,7 +90,7 @@ export class PreferenceView {
}
}
window.location.hash = `#${navigationItem}`;
location.hash = `#${navigationItem}`;
};
handleToggleTray(state: boolean) {

View File

@@ -1,12 +1,12 @@
import {dialog} from "@electron/remote";
import {html} from "../../../../common/html.js";
import * as Messages from "../../../../common/messages.js";
import * as t from "../../../../common/translation-util.js";
import type {ServerConfig} from "../../../../common/types.js";
import {generateNodeFromHtml} from "../../components/base.js";
import {ipcRenderer} from "../../typed-ipc-renderer.js";
import * as DomainUtil from "../../utils/domain-util.js";
import {html} from "../../../../common/html.ts";
import * as Messages from "../../../../common/messages.ts";
import * as t from "../../../../common/translation-util.ts";
import type {ServerConfig} from "../../../../common/types.ts";
import {generateNodeFromHtml} from "../../components/base.ts";
import {ipcRenderer} from "../../typed-ipc-renderer.ts";
import * as DomainUtil from "../../utils/domain-util.ts";
type ServerInfoFormProperties = {
$root: Element;
@@ -53,7 +53,7 @@ export function initServerInfoForm(properties: ServerInfoFormProperties): void {
$deleteServerButton.addEventListener("click", async () => {
const {response} = await dialog.showMessageBox({
type: "warning",
buttons: [t.__("YES"), t.__("NO")],
buttons: [t.__("Yes"), t.__("No")],
defaultId: 0,
message: t.__("Are you sure you want to disconnect this organization?"),
});

View File

@@ -1,8 +1,8 @@
import {html} from "../../../../common/html.js";
import * as t from "../../../../common/translation-util.js";
import {html} from "../../../../common/html.ts";
import * as t from "../../../../common/translation-util.ts";
import {reloadApp} from "./base-section.js";
import {initNewServerForm} from "./new-server-form.js";
import {reloadApp} from "./base-section.ts";
import {initNewServerForm} from "./new-server-form.ts";
type ServersSectionProperties = {
$root: Element;

View File

@@ -1,8 +1,8 @@
import process from "node:process";
import {html} from "../../../../common/html.js";
import * as LinkUtil from "../../../../common/link-util.js";
import * as t from "../../../../common/translation-util.js";
import {html} from "../../../../common/html.ts";
import * as LinkUtil from "../../../../common/link-util.ts";
import * as t from "../../../../common/translation-util.ts";
type ShortcutsSectionProperties = {
$root: Element;

View File

@@ -1,21 +1,21 @@
import {contextBridge} from "electron/renderer";
import electron_bridge, {bridgeEvents} from "./electron-bridge.js";
import * as NetworkError from "./pages/network.js";
import {ipcRenderer} from "./typed-ipc-renderer.js";
import electron_bridge, {BridgeEvent, bridgeEvents} from "./electron-bridge.ts";
import * as NetworkError from "./pages/network.ts";
import {ipcRenderer} from "./typed-ipc-renderer.ts";
contextBridge.exposeInMainWorld("electron_bridge", electron_bridge);
ipcRenderer.on("logout", () => {
bridgeEvents.emit("logout");
bridgeEvents.dispatchEvent(new BridgeEvent("logout"));
});
ipcRenderer.on("show-keyboard-shortcuts", () => {
bridgeEvents.emit("show-keyboard-shortcuts");
bridgeEvents.dispatchEvent(new BridgeEvent("show-keyboard-shortcuts"));
});
ipcRenderer.on("show-notification-settings", () => {
bridgeEvents.emit("show-notification-settings");
bridgeEvents.dispatchEvent(new BridgeEvent("show-notification-settings"));
});
window.addEventListener("load", () => {

View File

@@ -5,12 +5,13 @@ import process from "node:process";
import {BrowserWindow, Menu, Tray} from "@electron/remote";
import * as ConfigUtil from "../../common/config-util.js";
import {publicPath} from "../../common/paths.js";
import type {RendererMessage} from "../../common/typed-ipc.js";
import * as ConfigUtil from "../../common/config-util.ts";
import {publicPath} from "../../common/paths.ts";
import * as t from "../../common/translation-util.ts";
import type {RendererMessage} from "../../common/typed-ipc.ts";
import type {ServerManagerView} from "./main.js";
import {ipcRenderer} from "./typed-ipc-renderer.js";
import type {ServerManagerView} from "./main.ts";
import {ipcRenderer} from "./typed-ipc-renderer.ts";
let tray: ElectronTray | null = null;
@@ -147,13 +148,13 @@ function sendAction<Channel extends keyof RendererMessage>(
const createTray = function (): void {
const contextMenu = Menu.buildFromTemplate([
{
label: "Zulip",
label: t.__("Zulip"),
click() {
ipcRenderer.send("focus-app");
},
},
{
label: "Settings",
label: t.__("Settings"),
click() {
ipcRenderer.send("focus-app");
sendAction("open-settings");
@@ -163,7 +164,7 @@ const createTray = function (): void {
type: "separator",
},
{
label: "Quit",
label: t.__("Quit"),
click() {
ipcRenderer.send("quit-app");
},
@@ -202,12 +203,17 @@ export function initializeTray(serverManagerView: ServerManagerView) {
if (argument === 0) {
unread = argument;
tray.setImage(iconPath());
tray.setToolTip("No unread messages");
tray.setToolTip(t.__("No unread messages"));
} else {
unread = argument;
const image = renderNativeImage(argument);
tray.setImage(image);
tray.setToolTip(`${argument} unread messages`);
tray.setToolTip(
t.__mf(
"{number, plural, one {# unread message} other {# unread messages}}",
{number: `${argument}`},
),
);
}
}
});

View File

@@ -4,16 +4,16 @@ import path from "node:path";
import {app, dialog} from "@electron/remote";
import * as Sentry from "@sentry/electron/renderer";
import {JsonDB} from "node-json-db";
import {DataError} from "node-json-db/dist/lib/Errors";
import {DataError} from "node-json-db/dist/lib/Errors.js";
import {z} from "zod";
import * as EnterpriseUtil from "../../../common/enterprise-util.js";
import Logger from "../../../common/logger-util.js";
import * as Messages from "../../../common/messages.js";
import * as t from "../../../common/translation-util.js";
import type {ServerConfig} from "../../../common/types.js";
import * as EnterpriseUtil from "../../../common/enterprise-util.ts";
import Logger from "../../../common/logger-util.ts";
import * as Messages from "../../../common/messages.ts";
import * as t from "../../../common/translation-util.ts";
import type {ServerConfig} from "../../../common/types.ts";
import defaultIcon from "../../img/icon.png";
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
const logger = new Logger({
file: "domain-util.log",
@@ -24,7 +24,7 @@ const logger = new Logger({
export const defaultIconSentinel = "../renderer/img/icon.png";
const serverConfigSchema = z.object({
url: z.string().url(),
url: z.url(),
alias: z.string(),
icon: z.string(),
zulipVersion: z.string().default("unknown"),
@@ -182,9 +182,10 @@ function reloadDatabase(): void {
if (fs.existsSync(domainJsonPath)) {
fs.unlinkSync(domainJsonPath);
dialog.showErrorBox(
"Error saving new organization",
"There seems to be error while saving new organization, " +
"you may have to re-add your previous organizations back.",
t.__("Error saving new organization"),
t.__(
"There was an error while saving the new organization. You may have to add your previous organizations again.",
),
);
logger.error("Error while JSON parsing domain.json: ");
logger.error(error);

View File

@@ -1,9 +1,10 @@
import * as backoff from "backoff";
import {html} from "../../../common/html.js";
import Logger from "../../../common/logger-util.js";
import type WebView from "../components/webview.js";
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {html} from "../../../common/html.ts";
import Logger from "../../../common/logger-util.ts";
import * as t from "../../../common/translation-util.ts";
import type WebView from "../components/webview.ts";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
const logger = new Logger({
file: "domain-util.log",
@@ -55,8 +56,10 @@ export default class ReconnectUtil {
const errorMessageHolder = document.querySelector("#description");
if (errorMessageHolder) {
errorMessageHolder.innerHTML = html`
<div>Your internet connection doesn't seem to work properly!</div>
<div>Verify that it works and then click try again.</div>
<div>
${t.__("Your internet connection doesn't seem to work properly!")}
</div>
<div>${t.__("Verify that it works and then click Reconnect.")}</div>
`.html;
}

View File

@@ -1,4 +1,4 @@
import {ipcRenderer} from "../typed-ipc-renderer.js";
import {ipcRenderer} from "../typed-ipc-renderer.ts";
export const connectivityError: string[] = [
"ERR_INTERNET_DISCONNECTED",

View File

@@ -0,0 +1,6 @@
import * as z from "zod";
// In an Electron preload script, Content-Security-Policy only takes effect
// after the page has loaded, which breaks Zod's detection of whether eval is
// allowed.
z.config({jitless: true});

View File

@@ -12,49 +12,5 @@
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<div id="content">
<div class="popup">
<span class="popuptext hidden" id="fullscreen-popup"></span>
</div>
<div id="sidebar" class="toggle-sidebar">
<div id="view-controls-container">
<div id="tabs-container"></div>
<div id="add-tab" class="tab functional-tab">
<div class="server-tab" id="add-action">
<i class="material-icons">add</i>
</div>
<span id="add-server-tooltip" style="display: none"
>Add organization</span
>
</div>
</div>
<div id="actions-container">
<div class="action-button" id="dnd-action">
<i class="material-icons md-48">notifications</i>
<span id="dnd-tooltip" style="display: none">Do Not Disturb</span>
</div>
<div class="action-button hidden" id="reload-action">
<i class="material-icons md-48">refresh</i>
<span id="reload-tooltip" style="display: none">Reload</span>
</div>
<div class="action-button disable" id="loading-action">
<i class="refresh material-icons md-48">loop</i>
<span id="loading-tooltip" style="display: none">Loading</span>
</div>
<div class="action-button disable" id="back-action">
<i class="material-icons md-48">arrow_back</i>
<span id="back-tooltip" style="display: none">Go Back</span>
</div>
<div class="action-button" id="settings-action">
<i class="material-icons md-48">settings</i>
<span id="setting-tooltip" style="display: none">Settings</span>
</div>
</div>
</div>
<div id="main-container">
<div id="webviews-container"></div>
</div>
</div>
</body>
<body></body>
</html>

BIN
build/icon-macos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

1
build/icon-macos.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-100 -100 1024 1024"><defs><linearGradient id="a" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#50adff"/><stop offset="1" stop-color="#7877fc"/></linearGradient><mask id="b"><rect x="-100" y="-100" width="1024" height="1024" fill="#fff"/><path d="M566.66 527.25c0 33.03-24.23 60.05-53.84 60.05H260.29c-29.61 0-53.84-27.02-53.84-60.05 0-20.22 9.09-38.2 22.93-49.09l134.37-120c2.5-2.14 5.74 1.31 3.94 4.19l-49.29 98.69c-1.38 2.76.41 6.16 3.25 6.16h191.18c29.61 0 53.83 27.03 53.83 60.05zm0-281.39c0 20.22-9.09 38.2-22.93 49.09l-134.37 120c-2.5 2.14-5.74-1.31-3.94-4.19l49.29-98.69c1.38-2.76-.41-6.16-3.25-6.16H260.29c-29.61 0-53.84-27.02-53.84-60.05s24.23-60.05 53.84-60.05h252.54c29.61 0 53.83 27.02 53.83 60.05z" transform="scale(1.0658112582781456)" fill="#000"/></mask><path id="c" d="M824 257c0-64 0-104-14-141A173 173 0 00708 14C671 0 631 0 567 0H257C193 0 153 0 116 14A173 173 0 0014 116C0 153 0 193 0 257V567c0 64 0 104 14 141A173 173 0 00116 810c37 14 77 14 141 14H567c64 0 104 0 141-14A173 173 0 00810 708c14-37 14-77 14-141Z"/><filter id="d"><feGaussianBlur in="SourceGraphic" stdDeviation="10"/></filter><filter id="e"><feGaussianBlur in="SourceGraphic" stdDeviation="5"/></filter></defs><use href="#c" transform="translate(0 10)" fill-opacity="0.3" filter="url(#d)"/><rect x="120" y="120" width="584" height="584" fill="#fff" /><g filter="url(#e)"><rect x="120" y="120" width="584" height="584" fill="#32497f" mask="url(#b)" transform="translate(0 5)"/></g><use href="#c" mask="url(#b)" fill="url(#a)"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -2,6 +2,50 @@
All notable changes to the Zulip desktop app are documented in this file.
### v5.12.2 --2025-09-01
**Fixes**:
- Corrected broken translations in Chinese (simplified), Finnish, German, Greek, and Tamil that crashed the app.
### v5.12.1 --2025-08-29
**Enhancements**:
- Enabled macOS Writing Tools in the context menu.
- Marked untranslated strings for translation.
- Updated translations.
**Dependencies**:
- Upgraded all dependencies, including Electron 37.4.0.
### v5.12.0 --2025-03-13
**Enhancements**:
- Updated the icon in macOS with a native appearance.
- Marked untranslated strings for translation.
- Updated translations.
**Dependencies**:
- Upgraded all dependencies, including Electron 35.0.1.
**Removed features**:
- Removed support for macOS 10.15 and earlier, which reached end-of-life in 2022 and is [no longer supported](https://www.electronjs.org/blog/electron-33-0#removed-macos-1015-support) by Electron.
### v5.11.1 --2024-08-23
**Enhancements**:
- Updated translations.
**Dependencies**:
- Upgraded all dependencies, including Electron 32.0.1.
### v5.11.0 --2024-03-22
**Fixes**:
@@ -1108,7 +1152,6 @@ Minor improvements
**Fixes**:
- Fixed :
- Auto-updates
- Spellchecker
- Zooming functionality

View File

@@ -8,55 +8,13 @@ appropriate translation for a given string ("message") used in the UI.
To manage the set of UI messages and translations for them, and
provide a nice workflow for people to contribute translations, we use
(along with the rest of the Zulip project) a service called Transifex.
## Maintainers: syncing to/from Transifex
### Setup
You'll want Transifex's CLI client, `tx`.
- Install in your homedir with `easy_install transifex-client` or `pip3 install --user transifex-client`.
Or you can use your Zulip dev server virtualenv, which has it.
- Configure a `.transifexrc` with your API token. See [upstream
instructions](https://docs.transifex.com/client/client-configuration#transifexrc).
This can go either in your homedir, or in your working tree to make
the configuration apply only locally; it's already ignored in our
`.gitignore`.
- You'll need to be added [as a "maintainer"][tx-zulip-maintainers] to
the Zulip project on Transifex. (Upstream [recommends
this][tx-docs-maintainers] as the set of permissions on a Transifex
project needed for interacting with it as a developer.)
[tx-zulip-maintainers]: https://www.transifex.com/zulip/zulip/settings/maintainers/
[tx-docs-maintainers]: https://docs.transifex.com/teams/understanding-user-roles#project-maintainers
### Uploading strings to translate
Run `tx push -s`.
This uploads from `public/translations/en.json` to the
set of strings Transifex shows for contributors to translate.
(See `.tx/config` for how that's configured.)
### Downloading translated strings
Run `tools/tx-pull`.
This writes to files `public/translations/<lang>.json`.
(See `.tx/config` for how that's configured.)
Then look at the following sections to see if further updates are
needed to take full advantage of the new or updated translations.
(along with the rest of the Zulip project) a service called Weblate.
### Updating the languages supported in the code
Sometimes when downloading translated strings we get a file for a new
language. This happens when we've opened up a new language for people
to contribute translations into in the Zulip project on Transifex,
to contribute translations into in the Zulip project on Weblate,
which we do when someone expresses interest in contributing them.
The locales for supported languages are stored in `public/translations/supported-locales.json`

View File

@@ -41,32 +41,10 @@
1. Download [Zulip-x.x.x-amd64.deb][lr]
2. Double click and install, or run `dpkg -i Zulip-x.x.x-amd64.deb` in the terminal
3. Start the app with your app launcher or by running `zulip` in a terminal
4. Done! The app will NOT update automatically, but you can still check for updates
4. Done! You can update the app [using APT](https://documentation.ubuntu.com/server/how-to/software/package-management/#upgrading-packages).
**Other distros (Fedora, CentOS, Arch Linux etc)** :
1. Download Zulip-x.x.x-x86_64.AppImage[LR]
2. Make it executable using chmod a+x Zulip-x.x.x-x86_64.AppImage
3. Start the app with your app launcher
**You can also use `apt-get` (recommended)**:
- First download our signing key to make sure the deb you download is correct:
```bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 69AD12704E71A4803DCA3A682424BE5AE9BD10D9
```
- Add the repo to your apt source list :
```bash
echo "deb https://download.zulip.com/desktop/apt stable main" |
sudo tee -a /etc/apt/sources.list.d/zulip.list
```
- Now install the client :
```bash
sudo apt-get update
sudo apt-get install zulip
```

14
i18next.config.ts Normal file
View File

@@ -0,0 +1,14 @@
import {defineConfig} from "i18next-cli";
export default defineConfig({
locales: ["en"],
extract: {
input: ["app/**/*.ts"],
output: "public/translations/{{language}}.json",
functions: ["t.__", "t.__mf"],
keySeparator: false,
nsSeparator: false,
sort: (a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0),
indentation: "\t",
},
});

12931
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{
"name": "zulip",
"productName": "Zulip",
"version": "5.11.0",
"main": "./dist-electron",
"version": "5.12.2",
"main": "./dist-electron/index.cjs",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
"copyright": "Kandra Labs, Inc.",
@@ -17,8 +17,9 @@
"bugs": {
"url": "https://github.com/zulip/zulip-desktop/issues"
},
"type": "module",
"engines": {
"node": ">=16.13.2"
"node": ">=18"
},
"scripts": {
"start": "vite",
@@ -28,9 +29,9 @@
"lint-css": "stylelint \"app/**/*.css\"",
"lint-html": "htmlhint \"app/**/*.html\"",
"lint-js": "xo",
"prettier-non-js": "prettier --check --log-level=warn . \"!**/*.{js,ts}\"",
"prettier-non-js": "prettier --check --log-level=warn . \"!**/*.{cjs,js,ts}\"",
"test": "tsc && npm run lint-html && npm run lint-css && npm run lint-js && npm run prettier-non-js",
"test-e2e": "vite build && tape \"tests/**/*.js\"",
"test-e2e": "vite build && tape \"tests/**/*.ts\"",
"pack": "vite build && electron-builder --dir",
"dist": "vite build && electron-builder",
"mas": "vite build && electron-builder --mac mas"
@@ -50,6 +51,7 @@
"copyright": "©2020 Kandra Labs, Inc.",
"mac": {
"category": "public.app-category.productivity",
"icon": "build/icon-macos.png",
"target": [
{
"target": "default",
@@ -67,14 +69,11 @@
}
],
"darkModeSupport": true,
"artifactName": "${productName}-${version}-${arch}.${ext}",
"notarize": {
"teamId": "66KHCWMEYB"
}
"artifactName": "${productName}-${version}-${arch}.${ext}"
},
"linux": {
"category": "Chat;GNOME;GTK;Network;InstantMessaging",
"icon": "build/icon.icns",
"icon": "build/zulip.png",
"description": "Zulip Desktop Client for Linux",
"target": [
"deb",
@@ -90,8 +89,8 @@
"synopsis": "Zulip Desktop App",
"afterInstall": "./packaging/deb-after-install.sh",
"fpm": [
"./packaging/deb-apt.list=/etc/apt/sources.list.d/zulip-desktop.list",
"./packaging/deb-apt.asc=/etc/apt/trusted.gpg.d/zulip-desktop.asc",
"./packaging/deb-apt.sources=/etc/apt/sources.list.d/zulip-desktop.sources",
"./packaging/deb-apt.asc=/usr/share/keyrings/zulip-desktop.asc",
"./packaging/deb-release-upgrades.cfg=/etc/update-manager/release-upgrades.d/zulip-desktop.cfg"
]
},
@@ -120,7 +119,14 @@
}
],
"icon": "build/icon.ico",
"publisherName": "Kandra Labs, Inc."
"azureSignOptions": {
"endpoint": "https://eus.codesigning.azure.net/",
"codeSigningAccountName": "kandralabs",
"certificateProfileName": "kandralabs",
"publisherName": "Kandra Labs, Inc.",
"timestampRfc3161": "http://timestamp.acs.microsoft.com",
"timestampDigest": "SHA256"
}
},
"msi": {
"artifactName": "${productName}-${version}-${arch}.${ext}"
@@ -147,183 +153,53 @@
},
"devDependencies": {
"@electron/remote": "^2.0.8",
"@sentry/core": "^7.94.1",
"@sentry/electron": "^4.1.2",
"@sentry/core": "^10.1.0",
"@sentry/electron": "^6.1.0",
"@types/adm-zip": "^0.5.0",
"@types/auto-launch": "^5.0.2",
"@types/backoff": "^2.5.2",
"@types/i18n": "^0.13.1",
"@types/node": "^20.11.30",
"@types/node": "^22.13.10",
"@types/p-fifo": "^1.0.2",
"@types/requestidlecallback": "^0.3.4",
"@types/semver": "^7.5.8",
"@types/tape": "^5.8.1",
"@types/yaireo__tagify": "^4.3.2",
"@yaireo/tagify": "^4.5.0",
"adm-zip": "^0.5.5",
"auto-launch": "^5.0.5",
"backoff": "^2.5.0",
"electron": "^29.1.5",
"electron-builder": "^24.6.4",
"electron": "^37.2.5",
"electron-builder": "^26.0.12",
"electron-log": "^5.0.3",
"electron-updater": "^6.1.4",
"electron-updater": "^6.3.4",
"electron-window-state": "^5.0.3",
"escape-goat": "^4.0.0",
"eslint-import-resolver-typescript": "^4.4.4",
"htmlhint": "^1.1.2",
"i18n": "^0.15.1",
"iso-639-1": "^3.1.0",
"medium": "^1.2.0",
"i18next-cli": "^1.2.1",
"node-json-db": "^1.3.0",
"p-fifo": "^1.0.0",
"playwright-core": "^1.41.0-alpha-jan-9-2024",
"pre-commit": "^1.2.2",
"prettier": "^3.0.3",
"rimraf": "^5.0.0",
"semver": "^7.3.5",
"stylelint": "^16.1.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-config-standard": "^39.0.0",
"tape": "^5.2.2",
"typescript": "^5.0.4",
"vite": "^5.0.11",
"vite-plugin-electron": "^0.28.0",
"xo": "^0.58.0",
"zod": "^3.5.1"
"xo": "^1.2.1",
"zod": "^4.1.5"
},
"overrides": {
"@types/pg": "^8.15.1"
},
"prettier": {
"bracketSpacing": false,
"singleQuote": false,
"trailingComma": "all"
},
"xo": {
"prettier": true,
"rules": {
"@typescript-eslint/no-dynamic-delete": "off",
"arrow-body-style": "error",
"import/no-restricted-paths": [
"error",
{
"zones": [
{
"target": "./app/common",
"from": "./app",
"except": [
"./common"
]
},
{
"target": "./app/main",
"from": "./app",
"except": [
"./common",
"./main"
]
},
{
"target": "./app/renderer",
"from": "./app",
"except": [
"./common",
"./renderer",
"./resources"
]
}
]
}
],
"import/order": [
"error",
{
"alphabetize": {
"order": "asc"
},
"newlines-between": "always"
}
],
"import/unambiguous": "error",
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "@sentry/electron",
"message": "Use @sentry/electron/main, @sentry/electron/renderer, or @sentry/core."
},
{
"name": "electron",
"message": "Use electron/main, electron/renderer, or electron/common."
},
{
"name": "electron/main",
"importNames": [
"ipcMain"
],
"message": "Use typed-ipc-main."
},
{
"name": "electron/renderer",
"importNames": [
"ipcRenderer"
],
"message": "Use typed-ipc-renderer."
},
{
"name": "electron-log",
"message": "Use electron-log/main or electron-log/renderer."
}
]
}
],
"no-warning-comments": "off",
"sort-imports": [
"error",
{
"ignoreDeclarationSort": true
}
],
"strict": "error",
"unicorn/prefer-module": "off",
"unicorn/prefer-top-level-await": "off"
},
"envs": [
"node",
"browser"
],
"overrides": [
{
"files": [
"**/*.ts"
],
"rules": {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/consistent-type-imports": [
"error",
{
"disallowTypeAnnotations": false
}
],
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"caughtErrors": "all"
}
],
"unicorn/no-await-expression-member": "off"
}
},
{
"files": [
"scripts/notarize.js",
"tests/**/*.js"
],
"parserOptions": {
"sourceType": "script"
}
},
{
"files": [
"**/*.d.ts"
],
"rules": {
"import/unambiguous": "off"
}
}
]
}
}

View File

@@ -11,3 +11,6 @@ update-desktop-database /usr/share/applications || true
# Clean up configuration for old Bintray repository
rm -f /etc/apt/zulip.list
# Clean up legacy APT configuration
rm -f /etc/apt/sources.list.d/zulip-desktop.list /etc/apt/trusted.gpg.d/zulip-desktop.asc

View File

@@ -7,24 +7,28 @@ LoJVvA7uJHcsNaQVWQF4RP0MaI4TLyjHZAJlpthQfbmq0AbZMEjDu8Th5G9KTsqE
WRyFoAj/SWwKQK2U4xpnA6jEraMcvsYYQMrCXlG+MOV7zVknLrH5tfk7JlmWB4DV
cs+QP5Z/UrVu+YpTpaoJoZV6LlEU1kNGjtq9ABEBAAG0TVp1bGlwIEFQVCBSZXBv
c2l0b3J5IFNpZ25pbmcgS2V5IEJpbnRyYXkgKFByb2R1Y3Rpb24pIDxzdXBwb3J0
QHp1bGlwY2hhdC5jb20+iQE4BBMBAgAiBQJZnc70AhsDBgsJCAcDAgYVCAIJCgsE
FgIDAQIeAQIXgAAKCRAkJL5a6b0Q2Vg1CADJzrH0mbwKi5GiHo5+iX5/WuUkSA8S
lI7FWzkbnPD0sfxJBwBNhZnAALQUvCybHxoU8VZ5ZbU1vbU+EG7pUMzENZLgEhoC
MDl1j8uCSahjjO+bk8qHhgM1FUKpoGec2wKfPKpcz1P+/bLTRKe7aqilkPSYOjeV
u8JI713zRL0nHd9vYZDoN2HR30J5sqgjRHtK5okNhiFG+pF3HFATG7nbNOa/tv+q
ZvhbI/5S8P5VKPSK/1lmMh0UFyNIbPg6MvWiqnfy7DAvOZGJpawkiN2B0XhNZKZR
KKXvFk3qvFpNTCUrH77MlPgjn+oRbE9SYm0phj0o2jQi/s1s2r75tk/ZuQENBFmd
zvQBCACv7VNQ6x3hfaRl8YF8bbrWXN2ZWxEa353p4QryHODsa7wHtsoNR3P30TIL
yafjjcV8P6dzyDw6TpfRqqQDKLY6FtznT2HdceQSffGTXB4CRV7KURBqh81PX/Jo
dz0NwkNrd0NWqkk6BnLX6U5tGuYiqC3vLpjOHmVQezJ41xpf85ElJ2nBW0rEcmfk
fwQthJU7BbqWKd6nbt2G+xWkCVoN6q+CWLXtK0laHMKBGQnoiQpldotsKM8UnDeQ
XPqrEi28ksjVW8tBStCkLwV2hCxk49zdTvRjrhBTQ1Ff/kenuEwqbSERiKfA7I8o
mlqulSiJ6rYdDnGjNcoRgnHb50hTABEBAAGJAR8EGAECAAkFAlmdzvQCGwwACgkQ
JCS+Wum9ENnsOQgApQ2+4azOXprYQXj1ImamD30pmvvKD06Z7oDzappFpEXzRSJK
tMfNaowG7YrXujydrpqaOgv4kFzaAJizWGbmOKXTwQJnavGC1JC4Lijx0s3CLtms
OY3EC2GMNTp2rACuxZQ+26lBuPG8Nd+rNnP8DSzdQROQD2EITplqR1Rc0FLHGspu
rL0JsVTuWS3qSpR3nlmwuLjVgIs5KEaOVEa4pkH9QwyAFDsprF0uZP8xAAs8WrVr
Isg3zs7YUcAtu/i6C2jPuMsHjGfKStkYW/4+wONIynhoFjqeYrR0CiZ9lvVa3tJk
BCeqaQFskx1HhgWBT9Qqc73+i45udWUsa3issg==
=YJGK
QHp1bGlwY2hhdC5jb20+iQGSBBMBCACGBYJonATwBAsJCAcJECQkvlrpvRDZRxQA
AAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ5to4d/e2Ts692fK
y5pjZ8XOKTBvXckVdjBe8cSiLIkvAxUICgQWAgMBAheAAhsDAh4BFiEEaa0ScE5x
pIA9yjpoJCS+Wum9ENkAAP7XCACjGUAzUgOAbf1BJTbbR1Np4BNy31++93TNj+/3
gYPbNwSJBb99yZfI6J4KwT1WepIXRx2Ikx0ChxEU5oOjEcPoM8Xslg3/vTV76dcJ
CYtQdvIvLUBKN7MkDp6+H1LVu9AnzMYoAF8HiKk6NZNI2LjMMv1znYwod2Pp3EL7
q/TPwiaOuNVDlaRSCsmbWYNPWLXAna7PU/yZ7FYwaCAKeC079+5rY59RvA/3oOmG
nUAcADyuMaNkPPnkYW5adNfCHWEPUrIUJxyJ+yVf/E/mHoUKkqYhOs60WFPXpgpX
cnYYw8E/1kXM+kAfWIOi7dGlCFiWLyQF0wjwn/sehBXZy8yquQENBFmdzvQBCACv
7VNQ6x3hfaRl8YF8bbrWXN2ZWxEa353p4QryHODsa7wHtsoNR3P30TILyafjjcV8
P6dzyDw6TpfRqqQDKLY6FtznT2HdceQSffGTXB4CRV7KURBqh81PX/Jodz0NwkNr
d0NWqkk6BnLX6U5tGuYiqC3vLpjOHmVQezJ41xpf85ElJ2nBW0rEcmfkfwQthJU7
BbqWKd6nbt2G+xWkCVoN6q+CWLXtK0laHMKBGQnoiQpldotsKM8UnDeQXPqrEi28
ksjVW8tBStCkLwV2hCxk49zdTvRjrhBTQ1Ff/kenuEwqbSERiKfA7I8omlqulSiJ
6rYdDnGjNcoRgnHb50hTABEBAAGJAX4EGAEIAHIFgmicBPAJECQkvlrpvRDZRxQA
AAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ2yYQ1NoS1Il7WjP
HCfqbeXJc9dm9yLgL46FmSMjScRXAhsMFiEEaa0ScE5xpIA9yjpoJCS+Wum9ENkA
AMOECACo0hRteH+CWZDLKaufkxQvfqd0/zq+uGJ2VYOrIUkuuaA0YBe+uGaoFwgT
hxVs0UiOpMOzSyl+zC+7ShQu9t/jIm5sTmvHsgzmO11w4b1Td7Ow8dgAnAXKcbmA
O1yaMi1C40YUI1zHRt0xkrnTJB57q+8Hclum59UXiSIgU5bKVeJhsX4LVpxi67Qg
vIHgg6pL+kDzObjRuBw+8Qx/Cugf4W35IGLD6BGzLjZM98YhbaX52sFvuHj+8gAs
xFOefLGRjZNdcp3IViTcVeR41Y9mA1Pjtlvthqrq70yra+EWjR7hUFxE9/BWjb18
fQZRjlB5JKC69SdOMa5C2UTSWNbA
=5JdK
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -1 +0,0 @@
deb https://download.zulip.com/desktop/apt stable main

View File

@@ -0,0 +1,5 @@
Types: deb
URIs: https://download.zulip.com/desktop/apt/
Suites: stable
Components: main
Signed-By: /usr/share/keyrings/zulip-desktop.asc

Binary file not shown.

View File

@@ -4,17 +4,17 @@ These are _generated_ files (\*) that contain translations of the strings in
the app.
You can help translate Zulip Desktop into your language! We do our
translations in Transifex, which is a nice web app for collaborating on
translations in Weblate, which is a nice web app for collaborating on
translations; a maintainer then syncs those translations into this repo.
To help out, [join the Zulip project on
Transifex](https://www.transifex.com/zulip/zulip/) and enter translations
Weblate](https://hosted.weblate.org/projects/zulip/) and enter translations
there. More details in the [Zulip contributor docs](https://zulip.readthedocs.io/en/latest/translating/translating.html#translators-workflow).
Within that Transifex project, if you'd like to focus on Zulip Desktop, look
at `desktop.json`. The other resources there are for the Zulip web/mobile
Within that Weblate project, if you'd like to focus on Zulip Desktop, look
at the **Desktop** component. The other components are for the Zulip web/mobile
app, where translations are also very welcome.
(\*) One file is an exception: `en.json` is manually maintained as a
list of (English) messages in the source code, and is used when we upload to
Transifex a list of strings to be translated. It doesn't contain any
(\*) One file is an exception: `en.json` is maintained by `i18next-cli extract` as a
list of (English) messages in the source code, and is used by Weblate as
a list of strings to be translated. It doesn't contain any
translations.

View File

@@ -1,12 +1,10 @@
{
"About Zulip": "حول \"زوليب\"",
"Actual Size": "الحجم الفعلي",
"Add Organization": "إضافة منظمة",
"Add a Zulip organization": "إضافة منظمة \"زوليب\"",
"Add custom CSS": "إضافة CSS معدلة",
"AddServer": "AddServer",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "متقدم",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"All the connected organizations will appear here.": "جميع المنظمات المتصلة ستظهر هنا",
"Always start minimized": "دائماً إبدأ بالقليل",
"App Updates": "تحديثات التطبيق",
"App language (requires restart)": "App language (requires restart)",
@@ -18,6 +16,7 @@
"Auto hide menu bar (Press Alt key to display)": "أخف القائمة تلقائياً (إضغط Alt لعرض القائمة)",
"Back": "رجوع",
"Bounce dock on new private message": "أخرج المنصة في حال رسالة خاصة جديدة",
"Cancel": "إلغاء",
"Change": "تغيير",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "التحقق من التحديثات",
@@ -26,6 +25,9 @@
"Connect to another organization": "التوصيل مع منظمة أخرى",
"Connected organizations": "المنظمات المتصلة",
"Copy": "نسخ",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "نسخ رابط زوليب",
"Create a new organization": "إنشاء منظمة جديدة",
"Cut": "قص",
@@ -37,11 +39,11 @@
"Download App Logs": "تنزيل سجلات التطبيق",
"Edit": "تعديل",
"Edit Shortcuts": "تعديل الاختصارات",
"Emoji & Symbols": "Emoji & Symbols",
"Emoji & Symbols": "الإيموجي و الرموز",
"Enable auto updates": "تفعيل التحديثات التلقائية",
"Enable error reporting (requires restart)": "تفعيل تقارير الأخطاء (يتطلب إعادة التشغيل)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Enter Full Screen": "اعرض الشاشة كاملة",
"Factory Reset": "إعادة ضبط المصنع",
"Factory Reset Data": "Factory Reset Data",
"File": "ملف",
@@ -57,18 +59,20 @@
"Help Center": "Help Center",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"Hide Zulip": "أخفي زوليب",
"History": "History",
"History Shortcuts": "History Shortcuts",
"Keyboard Shortcuts": "Keyboard Shortcuts",
"Log Out": "Log Out",
"Log Out of Organization": "Log Out of Organization",
"Look Up": "Look Up",
"Manual proxy configuration": "Manual proxy configuration",
"Minimize": "Minimize",
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
"NO": "NO",
"Network": "Network",
"Network and Proxy Settings": "Network and Proxy Settings",
"Network and Proxy Settings": "الشبكة و إعدادات البروكسي",
"No Suggestion Found": "No Suggestion Found",
"OK": "حسنًا",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Organization URL": "Organization URL",
@@ -85,15 +89,14 @@
"Release Notes": "Release Notes",
"Reload": "Reload",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Reset App Settings": "أعد ضبط إعدادات التطبيق",
"Reset the application, thus deleting all the connected organizations and accounts.": "إعادة ضبط التطبيق, و بالتالي مسح جميع المنظمات المتصلة و الحسابات",
"Save": "Save",
"Select All": "Select All",
"Services": "Services",
"Settings": "Settings",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
@@ -117,11 +120,9 @@
"View Shortcuts": "View Shortcuts",
"Window": "Window",
"Window Shortcuts": "Window Shortcuts",
"YES": "YES",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} يقوم بتشغيل نسخة قديمة من خادم زوليب {{{version}}}. قد لا يعمل بشكل كامل مع هذا التطبيق"
}

View File

@@ -4,7 +4,7 @@
"Add Organization": "Дадаць арганізацыю",
"Add a Zulip organization": "Дадаць арганізацыю Zulip",
"Add custom CSS": "Дадаць свой CSS",
"AddServer": "Дадаць сэрвер",
"Add to Dictionary": "Дадаць у слоўнік",
"Advanced": "Пашыраныя",
"All the connected organizations will appear here.": "Тут з'явяцца ўсе звязаныя арганізацыі.",
"Always start minimized": "Заўсёды адкрываць згорнутым",
@@ -18,6 +18,7 @@
"Auto hide menu bar (Press Alt key to display)": "Аўтаматычна хаваць радок меню (для выявы націсніце клавішу Alt)",
"Back": "Назад",
"Bounce dock on new private message": "Подпрыгваючы dock пры новым асабістым паведамленні",
"Cancel": "Скасаваць",
"Change": "Змяніць",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Змяніце мову ў: Сістэмныя налады → Клавіятура → Тэкст → Правапіс.",
"Check for Updates": "Праверыць наяўнасць абнаўленняў",
@@ -26,6 +27,9 @@
"Connect to another organization": "Падлучыць да іншай арганізацыі",
"Connected organizations": "Падлучаныя арганізацыі",
"Copy": "Капіяваць",
"Copy Image": "Капіяваць відарыс",
"Copy Image URL": "Капіяваць URL відарысу",
"Copy Link": "Капіяваць спасылку",
"Copy Zulip URL": "Капіяваць Zulip URL",
"Create a new organization": "Стварыць новую арганізацыю",
"Cut": "Выразаць",
@@ -47,7 +51,7 @@
"File": "Файл",
"Find accounts": "Знайсці ўліковыя запісы",
"Find accounts by email": "Знайсці ўліковыя запісы паводле email",
"Flash taskbar on new message": "Успыхваць на панэлі заданняў пры новым асабістым паведамленні ",
"Flash taskbar on new message": "Успыхваць на панэлі заданняў пры новым асабістым паведамленні",
"Forward": "Пераадрасаваць",
"Functionality": "Функцыянальнасць",
"General": "Агульныя",
@@ -63,12 +67,13 @@
"Keyboard Shortcuts": "Спалучэнні клавішаў",
"Log Out": "Выйсці з уліковага запісу",
"Log Out of Organization": "Выйсці з уліковага запісу арганізацыі",
"Look Up": "Шукаць",
"Manual proxy configuration": "Ручная налада проксі",
"Minimize": "Згарнуць",
"Mute all sounds from Zulip": "Адключыць усе гукі з Zulip",
"NO": "NO",
"Network": "Сетка",
"Network and Proxy Settings": "Налады сеткі і проксі",
"No Suggestion Found": "Прапановы не знойдзеныя",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "У macOS выкарыстоўваецца сістэмная праверка правапісу.",
"Organization URL": "URL арганізацыі",
@@ -93,7 +98,6 @@
"Settings": "Налады",
"Shortcuts": "Спалучэнні клавішаў",
"Show app icon in system tray": "Паказаць значок праграмы ў вобласці паведамленняў",
"Show app unread badge": "Паказваць значок непрачытаных паведамленняў",
"Show desktop notifications": "Паказваць апавяшчэнні на працоўным стале",
"Show sidebar": "Паказваць бакавую панэль",
"Spellchecker Languages": "Мовы для праверкі правапісу",
@@ -104,8 +108,6 @@
"Tip": "Парада",
"Toggle DevTools for Active Tab": "Увамкнуць DevTools для актыўнай укладкі",
"Toggle DevTools for Zulip App": "Перамкнуць DevTools для праграмы Zulip",
"Toggle Do Not Disturb": "Перамкнуць рэжым \"Не турбаваць\"",
"Toggle Full Screen": "Перамкнуць \"На ўвесь экран\"",
"Toggle Sidebar": "Перамкнуць бакавую панэль",
"Toggle Tray Icon": "Перамкнуць значок у вобласці паведамленняў",
"Tools": "Інструменты",
@@ -117,11 +119,9 @@
"View Shortcuts": "Спалучэнні клавішаў прагляду",
"Window": "Акно",
"Window Shortcuts": "Спалучэнні клавішаў акна",
"YES": "ТАК",
"You can select a maximum of 3 languages for spellchecking.": "Вы можаце выбраць максімум 3 мовы для праверкі правапісу.",
"Zoom In": "Павялічыць",
"Zoom Out": "Паменшыць",
"keyboard shortcuts": "спалучэнні клавішаў",
"script": "скрыпт",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "На {{{server}}} працуе састарэлая версія сервера Zulip {{{version}}}. У гэтай праграме ён можа працаваць часткова."
}

View File

@@ -4,20 +4,22 @@
"Add Organization": "Добавяне на организация",
"Add a Zulip organization": "Добавете организация Zulip",
"Add custom CSS": "Добавете персонализиран CSS",
"AddServer": "AddServer",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "напреднал",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"All the connected organizations will appear here.": "Всички свързани организации ще се появят тук.",
"Always start minimized": "Винаги започвайте да минимизирате",
"App Updates": "Актуализации на приложения",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "Външен вид",
"Application Shortcuts": "Клавишни комбинации за приложения",
"Are you sure you want to disconnect this organization?": "Наистина ли искате да прекъснете връзката с тази организация?",
"Are you sure?": "Сигурни ли сте?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"Auto hide Menu bar": "Автоматично скриване на лентата с менюта",
"Auto hide menu bar (Press Alt key to display)": "Автоматично скриване на лентата с менюта (натиснете клавиша Alt за показване)",
"Back": "обратно",
"Bounce dock on new private message": "Прескочи док в новото лично съобщение",
"Cancel": "Откажи",
"Change": "промяна",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Провери за обновления",
@@ -26,6 +28,9 @@
"Connect to another organization": "Свържете се с друга организация",
"Connected organizations": "Свързани организации",
"Copy": "копие",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "Копирайте URL адреса на Zulip",
"Create a new organization": "Създайте нова организация",
"Cut": "Разрез",
@@ -37,11 +42,9 @@
"Download App Logs": "Изтеглете регистрационни файлове на приложенията",
"Edit": "редактиране",
"Edit Shortcuts": "Редактиране на преки пътища",
"Emoji & Symbols": "Emoji & Symbols",
"Enable auto updates": "Активиране на автоматичните актуализации",
"Enable error reporting (requires restart)": "Активиране на отчитането за грешки (изисква се рестартиране)",
"Enable spellchecker (requires restart)": "Активиране на проверката на правописа (изисква се рестартиране)",
"Enter Full Screen": "Enter Full Screen",
"Factory Reset": "Фабрично нулиране",
"Factory Reset Data": "Factory Reset Data",
"File": "досие",
@@ -57,18 +60,19 @@
"Help Center": "Помощен център",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"History": "история",
"History Shortcuts": "Преки пътища в историята",
"Keyboard Shortcuts": "Комбинация от клавиши",
"Log Out": "Излез от профила си",
"Log Out of Organization": "Излезте от организацията",
"Look Up": "Look Up",
"Manual proxy configuration": "Ръчна конфигурация на прокси",
"Minimize": "Минимизиране",
"Mute all sounds from Zulip": "Заглуши всички звуци от Zulip",
"NO": "НЕ",
"Network": "мрежа",
"Network and Proxy Settings": "Network and Proxy Settings",
"No Suggestion Found": "No Suggestion Found",
"Notification settings": "Настройки на известията",
"OK": "OK",
"OR": "ИЛИ",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Organization URL": "URL адрес на организацията",
@@ -85,15 +89,12 @@
"Release Notes": "Бележки към изданието",
"Reload": "Презареди",
"Report an Issue": "Подаване на сигнал за проблем",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "Запази",
"Select All": "Избери всички",
"Services": "Services",
"Settings": "Настройки",
"Shortcuts": "Shortcuts",
"Show app icon in system tray": "Показване на иконата на приложението в системната област",
"Show app unread badge": "Показване на непрочетената значка на приложението",
"Show desktop notifications": "Показване на известията на работния плот",
"Show sidebar": "Показване на страничната лента",
"Spellchecker Languages": "Spellchecker Languages",
@@ -117,11 +118,8 @@
"View Shortcuts": "Преглед на преки пътища",
"Window": "прозорец",
"Window Shortcuts": "Клавишни комбинации",
"YES": "ДА",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Увеличавам",
"Zoom Out": "Отдалечавам",
"keyboard shortcuts": "комбинация от клавиши",
"script": "писменост",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"keyboard shortcuts": "комбинация от клавиши"
}

View File

@@ -1,127 +1,60 @@
{
"About Zulip": "যুলিপ সম্পর্কে ",
"Actual Size": "প্রকৃত সাইজ ",
"About Zulip": "যুলিপ সম্পর্কে",
"Actual Size": "প্রকৃত সাইজ",
"Add Organization": "সংস্থা যুক্ত করুন",
"Add a Zulip organization": "একটি যুলিপ প্রতিষ্ঠান যুক্ত করুন",
"Add custom CSS": "কাস্টম সিএসএস যুক্ত করুন",
"AddServer": "এড সার্ভার ",
"Advanced": "অগ্রসর ",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"Always start minimized": "সব সময় মিনিমাইজড ভাবে শুরু করুন ",
"Advanced": "অগ্রসর",
"Always start minimized": "সব সময় মিনিমাইজড ভাবে শুরু করুন",
"App Updates": "অ্যাপ আপডেট",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "প্রকাশ",
"Application Shortcuts": "অ্যাপ্লিকেশান শর্টকাট ",
"Application Shortcuts": "অ্যাপ্লিকেশান শর্টকাট",
"Are you sure you want to disconnect this organization?": "আপনি কি নিশ্চিত যে আপনি এই সংস্থার সংযোগ বিচ্ছিন্ন করতে চান ?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"Auto hide Menu bar": "অটো মেনুবার হাইড করুন ",
"Auto hide Menu bar": "অটো মেনুবার হাইড করুন",
"Auto hide menu bar (Press Alt key to display)": "অটো মেনুবার হাইড করুন (দেখার জন্য অল্টার কি চাপুন)",
"Back": "পেছন",
"Bounce dock on new private message": "ব্যাক্তিগত মেসেজে ডক বাউন্স করুন ",
"Bounce dock on new private message": "ব্যাক্তিগত মেসেজে ডক বাউন্স করুন",
"Cancel": "বাতিল",
"Change": "পরিবর্তন",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "ভাষা পরিবর্তন করতে সিস্টেম প্রেফারেন্স কীবোর্ড → টেক্সট → স্পেলিং এ যান ",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "ভাষা পরিবর্তন করতে সিস্টেম প্রেফারেন্স কীবোর্ড → টেক্সট → স্পেলিং এ যান",
"Check for Updates": "আপডেট চেক করুন",
"Close": "বন্ধ করুন",
"Connect": "সংযুক্ত করুন",
"Connect to another organization": "অন্য একটি সংস্থার সাথে সংযুক্ত করুন",
"Connected organizations": "সংযুক্ত সংস্থা সমূহ ",
"Connected organizations": "সংযুক্ত সংস্থা সমূহ",
"Copy": "কপি",
"Copy Zulip URL": "যুলিপ ইউআরএল কপি করুন ",
"Create a new organization": "নতুন সংস্থা তৈরি করুন ",
"Cut": "কাট ",
"Default download location": "Default download location",
"Copy Zulip URL": "যুলিপ ইউআরএল কপি করুন",
"Create a new organization": "নতুন সংস্থা তৈরি করুন",
"Cut": "কাট",
"Delete": "ডিলিট",
"Desktop Notifications": "ডেস্কটপ নোটিফিকেশান ",
"Desktop Notifications": "ডেস্কটপ নোটিফিকেশান",
"Desktop Settings": "ডেস্কটপ সেটিংস",
"Disconnect": "সংযোগ বিছিন্ন করুন",
"Download App Logs": "অ্যাপ লগ ডাউনলোড করুন ",
"Download App Logs": "অ্যাপ লগ ডাউনলোড করুন",
"Edit": "এডিট",
"Edit Shortcuts": "শর্টকাটগুলো এডিট করুন ",
"Emoji & Symbols": "Emoji & Symbols",
"Edit Shortcuts": "শর্টকাটগুলো এডিট করুন",
"Enable auto updates": "অটো আপডেট চালু করুন",
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Factory Reset": "ফ্যাক্টরি রিসেট",
"Factory Reset Data": "Factory Reset Data",
"File": "ফাইল",
"Find accounts": "অ্যাকাউন্ট খুজুন",
"Find accounts by email": "ইমেইল ব্যাবহার করে অ্যাকাউন্ট খুজুন",
"Flash taskbar on new message": "Flash taskbar on new message",
"Forward": "ফরওয়ার্ড",
"Functionality": "Functionality",
"General": "সাধারন",
"Get beta updates": "Get beta updates",
"Hard Reload": "Hard Reload",
"Help": "সাহায্য",
"Help Center": "সাহায্য কেন্দ্র",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"History": "ইতিহাস",
"History Shortcuts": "History Shortcuts",
"Keyboard Shortcuts": "Keyboard Shortcuts",
"Log Out": "লগ আউট",
"Log Out of Organization": "সংস্থা থেকে লগ আউট করুন",
"Manual proxy configuration": "Manual proxy configuration",
"Minimize": "ছোট করুন",
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
"NO": "না",
"Network": "Network",
"Network and Proxy Settings": "Network and Proxy Settings",
"No Suggestion Found": "কোন সাজেশন পাওয়া যায়নি",
"OR": "অথবা",
"On macOS, the OS spellchecker is used.": "ম্যাক ওএস এ , ওএস এর স্পেলচেকার ব্যাবহার করা হয় ।",
"Organization URL": "Organization URL",
"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",
"Quit when the window is closed": "Quit when the window is closed",
"Redo": "Redo",
"Release Notes": "Release Notes",
"Reload": "Reload",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "সেভ",
"Select All": "Select All",
"Services": "Services",
"Settings": "সেটিংস",
"Shortcuts": "শর্টকাট সমূহ",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
"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",
"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": "অ্যান্ডু ",
"Unhide": "Unhide",
"Undo": "অ্যান্ডু",
"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": "হ্যাঁ",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "জুম আউট",
"keyboard shortcuts": "keyboard shortcuts",
"script": "স্ক্রিপ্ট ",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"Zoom Out": "জুম আউট"
}

View File

@@ -1,127 +1,12 @@
{
"About Zulip": "About Zulip",
"Actual Size": "Actual Size",
"Add Organization": "Add Organization",
"Add a Zulip organization": "Add a Zulip organization",
"Add custom CSS": "Add custom CSS",
"AddServer": "AddServer",
"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",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "Appearance",
"Application Shortcuts": "Application Shortcuts",
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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",
"Cancel": "raď kerdên",
"Change": "ālêštkâri",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Check for Updates",
"Close": "bastên",
"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": "pāk kerdên",
"Desktop Notifications": "Desktop Notifications",
"Desktop Settings": "Desktop Settings",
"Disconnect": "Disconnect",
"Download App Logs": "Download App Logs",
"Edit": "ālêšt",
"Edit Shortcuts": "Edit Shortcuts",
"Emoji & Symbols": "Emoji & Symbols",
"Enable auto updates": "Enable auto updates",
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Factory Reset": "Factory Reset",
"Factory Reset Data": "Factory Reset Data",
"File": "fāyl",
"Find accounts": "jostên hêsāvā mêntori",
"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",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"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",
"Network and Proxy Settings": "Network and Proxy Settings",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"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",
"Quit when the window is closed": "Quit when the window is closed",
"Redo": "Redo",
"Release Notes": "Release Notes",
"Reload": "Reload",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"OK": "xā",
"Save": "zaft kerdên",
"Select All": "Select All",
"Services": "Services",
"Settings": "sāmovā",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
"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",
"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",
"Unhide": "Unhide",
"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",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"Settings": "sāmovā"
}

View File

@@ -1,23 +1,29 @@
{
"A new update {{{version}}} has been downloaded.": "S'ha descarregat una nova actualització {{{version}}}.",
"A new version {{{version}}} of Zulip Desktop is available.": "Hi ha disponible una nova versió de Zulip Escriptori {{{version}}}.",
"About": "Sobre",
"About Zulip": "Quant a Zulip",
"Actual Size": "Actual Size",
"Add Organization": "Add Organization",
"Add a Zulip organization": "Add a Zulip organization",
"Actual Size": "Mida actual",
"Add Organization": "Afegir organització",
"Add a Zulip organization": "Afegir una organització de Zulip",
"Add custom CSS": "Add custom CSS",
"AddServer": "AddServer",
"Advanced": "Advanced",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "Avançat",
"Always start minimized": "Always start minimized",
"App Updates": "App Updates",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "Appearance",
"Application Shortcuts": "Application Shortcuts",
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
"Are you sure?": "Esteu segur/a?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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",
"CSS file": "Arxiu CSS",
"Cancel": "Cancel·la",
"Certificate error": "Error de certificat",
"Change": "Change",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Check for Updates",
@@ -26,6 +32,9 @@
"Connect to another organization": "Connect to another organization",
"Connected organizations": "Connected organizations",
"Copy": "Copia",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "Copy Zulip URL",
"Create a new organization": "Crea una nova organització",
"Cut": "Cut",
@@ -34,14 +43,16 @@
"Desktop Notifications": "Desktop Notifications",
"Desktop Settings": "Configuració d'escriptori",
"Disconnect": "Disconnect",
"Do Not Disturb": "No molesteu",
"Download App Logs": "Download App Logs",
"Edit": "Edita",
"Edit Shortcuts": "Edit Shortcuts",
"Emoji & Symbols": "Emoji & Symbols",
"Emoji & Symbols": "Emojis i símbols",
"Enable auto updates": "Enable auto updates",
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Enter Full Screen": "Entreu a pantalla sencera",
"Error saving new organization": "Error en guardar la nova organització",
"Factory Reset": "Factory Reset",
"Factory Reset Data": "Factory Reset Data",
"File": "Fitxer",
@@ -57,18 +68,18 @@
"Help Center": "Centre d'ajuda",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"History": "Historial",
"History Shortcuts": "Dreceres d'historial",
"Keyboard Shortcuts": "Keyboard Shortcuts",
"Log Out": "Tanca la sessió",
"Log Out of Organization": "Tanca la sessió de l'organització",
"Look Up": "Look Up",
"Manual proxy configuration": "Manual proxy configuration",
"Minimize": "Minimize",
"Mute all sounds from Zulip": "Silencia tots els sons de Zulip",
"NO": "NO",
"Network": "Network",
"Network and Proxy Settings": "Network and Proxy Settings",
"No Suggestion Found": "No Suggestion Found",
"OK": "D'acord",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Organization URL": "URL d'organització",
@@ -86,14 +97,12 @@
"Reload": "Recarrega",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reinicia la configuració de l'aplicació",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "Guardar",
"Select All": "Select All",
"Services": "Services",
"Settings": "Configuració",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
@@ -109,19 +118,20 @@
"Toggle Sidebar": "Toggle Sidebar",
"Toggle Tray Icon": "Toggle Tray Icon",
"Tools": "Tools",
"Unable to check for updates.": "No ha estat possible comprovar les actualitzacions.",
"Unable to download the update.": "No ha estat possible descarregar l'actualització.",
"Undo": "Undo",
"Unhide": "Unhide",
"Unknown error": "Error desconegut",
"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",
"Yes": "No",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"keyboard shortcuts": "keyboard shortcuts"
}

View File

@@ -1,10 +1,13 @@
{
"A new update {{{version}}} has been downloaded.": "Byla stažena nová aktualizace {{{version}}}.",
"A new version {{{version}}} of Zulip Desktop is available.": "Je dostupná nová verze {{{version}}} Zulip Desktop.",
"About": "O programu",
"About Zulip": "O Zulipu",
"Actual Size": "Skutečná velikost",
"Add Organization": "Přidat organizaci",
"Add a Zulip organization": "Přidat organizaci Zulip",
"Add custom CSS": "Přidat vlastní CSS",
"AddServer": "Přidat server",
"Add to Dictionary": "Přidat do slovníku",
"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é",
@@ -13,11 +16,16 @@
"Appearance": "Vzhled",
"Application Shortcuts": "Zkratky programu",
"Are you sure you want to disconnect this organization?": "Opravdu chcete odpojit tuto organizaci?",
"Are you sure?": "Jste si jistý?",
"Ask where to save files before downloading": "Před stažením se zeptat kam uložit soubory",
"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)",
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}": "Dostupné pod {{{link}}}licencí Apache 2.0{{{endLink}}}",
"Back": "Zpět",
"Bounce dock on new private message": "Poskakování ikony v docku po obdržení nové soukromé zprávy",
"CSS file": "Soubor CSS",
"Cancel": "Zrušit",
"Certificate error": "Chyba certifikátu",
"Change": "Změnit",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Změnit jazyk v Nastavení systému → Klávesnice → Text → Kontrola pravopisu.",
"Check for Updates": "Zkontrolovat aktualizace",
@@ -26,14 +34,21 @@
"Connect to another organization": "Připojit se k jiné organizaci",
"Connected organizations": "Připojené organizace",
"Copy": "Kopírovat",
"Copy Email Address": "Kopírovat adresu elektronické pošty",
"Copy Image": "Kopírovat obrázek",
"Copy Image URL": "Kopírovat adresu (URL) obrázku",
"Copy Link": "Kopírovat odkaz",
"Copy Zulip URL": "Kopírovat adresu (URL) Zulipu",
"Create a new organization": "Vytvořit novou organizaci",
"Custom CSS file deleted": "Vlastní soubor CSS smazán",
"Cut": "Vyjmout",
"Default download location": "Výchozí umístění stahování",
"Delete": "Smazat",
"Desktop Notifications": "Oznámení na ploše",
"Desktop Settings": "Nastavení plochy",
"Disconnect": "Odpojit",
"Disconnect organization": "Odpojit organizaci",
"Do Not Disturb": "Nerušit",
"Download App Logs": "Stáhnout záznamy programu",
"Edit": "Upravit",
"Edit Shortcuts": "Upravit zkratky",
@@ -42,6 +57,9 @@
"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)",
"Enter Full Screen": "Vstoupit na celou obrazovku",
"Error saving new organization": "Chyba při ukládání nové organizace",
"Error saving update notifications": "Chyba při ukládání oznámení aktualizace",
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}": "Chyba: {{{error}}}\n\nNejnovější verze aplikace Zulip Desktop je dostupná na adrese:\n{{{link}}}\nNynější verze: {{{version}}}",
"Factory Reset": "Obnovení do továrního nastavení",
"Factory Reset Data": "Obnovení dat do továrního nastavení",
"File": "Soubor",
@@ -52,6 +70,7 @@
"Functionality": "Funkce",
"General": "Obecné",
"Get beta updates": "Dostávat beta aktualizace",
"Go Back": "Jít zpět",
"Hard Reload": "Tvrdé znovunahrání",
"Help": "Nápověda",
"Help Center": "Centrum nápovědy",
@@ -60,15 +79,28 @@
"Hide Zulip": "Skrýt Zulip",
"History": "Historie",
"History Shortcuts": "Zkratky pro historii",
"Install Later": "Instalovat později",
"Install and Relaunch": "Nainstalovat a spustit znovu",
"It will be installed the next time you restart the application.": "Nainstaluje se při příštím restartu aplikace.",
"Keyboard Shortcuts": "Klávesové zkratky",
"Later": "Později",
"Loading": "Nahrává se",
"Log Out": "Odhlásit se",
"Log Out of Organization": "Odhlásit se z organizace",
"Look Up": "Vyhledat",
"Maintained by {{{link}}}Zulip{{{endLink}}}": "Udržováno {{{link}}}Zulip{{{endLink}}}",
"Manual Download": "Ruční stažení",
"Manual proxy configuration": "Ruční nastavení proxy",
"Minimize": "Minimalizovat",
"Mute all sounds from Zulip": "Ztlumit všechny zvuky ze Zulipu",
"NO": "NE",
"Network": "Síť",
"Network and Proxy Settings": "Nastavení sítě a proxy serveru",
"New servers added. Reload app now?": "Přidány nové servery. Nahrát nyní aplikaci znovu?",
"No": "Ne",
"No Suggestion Found": "Nenalezen žádný návrh",
"No updates available.": "Žádné dostupné aktualizace.",
"Notification settings": "Nastavení oznámení",
"OK": "OK",
"OR": "NEBO",
"On macOS, the OS spellchecker is used.": "Na macOS se používá kontrola pravopisu OS.",
"Organization URL": "Adresa organizace",
@@ -78,6 +110,7 @@
"Proxy": "Proxy",
"Proxy bypass rules": "Pravidla pro obejití Proxy",
"Proxy rules": "Pravidla Proxy",
"Proxy settings saved.": "Nastavení proxy serveru je uloženo.",
"Quit": "Ukončit",
"Quit Zulip": "Ukončit Zulip",
"Quit when the window is closed": "Ukončit, když je okno zavřeno",
@@ -89,17 +122,23 @@
"Reset the application, thus deleting all the connected organizations and accounts.": "Obnovit program do výchozího nastavení. čili smazat všechny připojené organizace a účty.",
"Save": "Uložit",
"Select All": "Vybrat vše",
"Select Download Location": "Vyberte umístění stahování",
"Select file": "Vybrat soubor",
"Services": "Služby",
"Settings": "Nastavení",
"Shortcuts": "Zkratky",
"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 sidebar": "Zobrazovat postranní panel",
"Show unread count badge on app icon": "Ukázat počet nepřečtených na ikoně aplikace",
"Spellchecker Languages": "Kontrola pravopisu jazyků",
"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řepnout na předchozí organizaci",
"The custom CSS previously set is deleted.": "Předtím nastavený vlastní soubor CSS je smazán.",
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}": "Server předložil neplatný certifikát pro {{{origin}}}:\n\n{{{error}}}",
"The update will be downloaded in the background. You will be notified when it is ready to be installed.": "Aktualizace se stáhne na pozadí. Až bude připravena k instalaci, budete o tom informováni.",
"There was an error while saving the new organization. You may have to add your previous organizations again.": "Při ukládání nové organizace došlo k chybě. Je možné, že budete muset předchozí organizace přidat znovu.",
"These desktop app shortcuts extend the Zulip webapp's": "Tyto zkratky rozšiřují webovou aplikaci Zulipu",
"Tip": "Tip",
"Toggle DevTools for Active Tab": "Přepnout vývojářské nástroje pro aktivní kartu",
@@ -109,19 +148,23 @@
"Toggle Sidebar": "Přepnout zobrazení postranního panelu",
"Toggle Tray Icon": "Přepnout ikonu v oznamovací oblasti panelu",
"Tools": "Nástroje",
"Unable to check for updates.": "Nelze zkontrolovat aktualizace.",
"Unable to download the update.": "Aktualizaci se nepodařilo stáhnout.",
"Undo": "Zpět",
"Unhide": "Zobrazit",
"Unknown error": "Neznámá chyba",
"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",
"We encountered an error while saving the update notifications.": "Při ukládání oznámení o aktualizaci jsme narazili na chybu.",
"Window": "Okno",
"Window Shortcuts": "Zkratky pro okno",
"YES": "ANO",
"Yes": "Ano",
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}": "Používáte nejnovější verzi aplikace Zulip Desktop.\nVerze: {{{version}}}",
"You can select a maximum of 3 languages for spellchecking.": "Pro kontrolu pravopisu můžete vybrat nejvíce 3 jazyky.",
"Zoom In": "Přiblížit",
"Zoom Out": "Oddálit",
"keyboard shortcuts": "klávesové zkratky",
"script": "skript",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} používá zastaralou verzi serveru Zulip {{{verze}}}. V této aplikaci nemusí plně pracovat."
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} používá zastaralou verzi serveru Zulip {{{version}}}. V této aplikaci nemusí plně pracovat."
}

View File

@@ -4,9 +4,9 @@
"Add Organization": "Ychwanegu Sefydliad",
"Add a Zulip organization": "Ychwanegwch sefydliad Zulip",
"Add custom CSS": "Ychwanegwch CSS wedi'i ddylunio'n benodol",
"AddServer": "AddServer",
"Add to Dictionary": "Ychwanegu at y Geiriadur",
"Advanced": "Uwch",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"All the connected organizations will appear here.": "Bydd yr holl sefydliadau cysylltiedig yn ymddangos yma.",
"Always start minimized": "Dechreuwch gyn lleied â phosibl bob amser",
"App Updates": "Diweddariadau Ap",
"App language (requires restart)": "Iaith ap (angen ailgychwyn)",
@@ -18,6 +18,7 @@
"Auto hide menu bar (Press Alt key to display)": "Cuddiwch y bar dewislen yn awtomatig (Pwyswch Alt i'w harddangos)",
"Back": "Yn ôl",
"Bounce dock on new private message": "Sbonciwch doc ar neges breifat newydd",
"Cancel": "Canslo",
"Change": "Newid",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Newid yr iaith o Dewisiadau System → Bysellfwrdd → Testun → Sillafu.",
"Check for Updates": "Chwiliwch am Ddiweddariadau",
@@ -26,6 +27,9 @@
"Connect to another organization": "Cysylltu â sefydliad arall",
"Connected organizations": "Sefydliadau cysylltiedig",
"Copy": "Copi",
"Copy Image": "Copi Delwedd",
"Copy Image URL": "Copi URL Delwedd",
"Copy Link": "Copi Dolen",
"Copy Zulip URL": "Copïwch URL Zulip",
"Create a new organization": "Creu sefydliad newydd",
"Cut": "Torri",
@@ -37,11 +41,11 @@
"Download App Logs": "Lawrlwythwch Logiau Ap",
"Edit": "Golygu",
"Edit Shortcuts": "Golygu Llwybrau Byr",
"Emoji & Symbols": "Emoji & Symbols",
"Emoji & Symbols": "Emoji a Symbolau",
"Enable auto updates": "Galluogi diweddariadau yn awtomatig",
"Enable error reporting (requires restart)": "Galluogi adrodd am wallau (angen ailgychwyn)",
"Enable spellchecker (requires restart)": "Galluogi gwiriwr sillafu (angen ailgychwyn)",
"Enter Full Screen": "Enter Full Screen",
"Enter Full Screen": "Rhowch sgrin lawn",
"Factory Reset": "Ailosod Ffatri",
"Factory Reset Data": "Ailosod Data Ffatri",
"File": "Ffeil",
@@ -57,24 +61,27 @@
"Help Center": "Canolfan Gymorth",
"Hide": "Cuddio",
"Hide Others": "Cuddio Eraill",
"Hide Zulip": "Hide Zulip",
"Hide Zulip": "Cuddiwch Zulip",
"History": "Hanes",
"History Shortcuts": "Hanes Llwybrau Byr ",
"History Shortcuts": "Hanes Llwybrau Byr",
"Keyboard Shortcuts": "Llwybrau Byr Bysellfwrdd",
"Log Out": "Allgofnodi",
"Log Out of Organization": "Allgofnodi Sefydliad",
"Look Up": "Ymchwiliwch",
"Manual proxy configuration": "Cyfluniad dirprwy â llaw",
"Minimize": "Lleihau",
"Mute all sounds from Zulip": "Tawelwch pob sain o Zulip",
"NO": "NA",
"Network": "Rhwydwaith",
"Network and Proxy Settings": "Network and Proxy Settings",
"Network and Proxy Settings": "Gosodiadau Rhwydwaith a Dirprwy",
"No Suggestion Found": "Ni chanfuwyd unrhyw awgrym",
"Notification settings": "Gosodiadau hysbysu",
"OK": "Iawn",
"OR": "NEU",
"On macOS, the OS spellchecker is used.": "Ar macOS, defnyddir gwiriwr sillafu OS.",
"Organization URL": "URL y sefydliad",
"Organizations": "Sefydliadau",
"Paste": "Gludo",
"Paste and Match Style": "Arddull Gludo a Paru ",
"Paste and Match Style": "Arddull Gludo a Paru",
"Proxy": "Dirprwy",
"Proxy bypass rules": "Rheolau ffordd osgoi dirprwy",
"Proxy rules": "Rheolau dirprwy",
@@ -85,15 +92,14 @@
"Release Notes": "Nodiadau ar y datganiad hwn",
"Reload": "Ail-lwytho",
"Report an Issue": "Adroddiwch mater",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Reset App Settings": "Ailosod Gosodiadau Ap",
"Reset the application, thus deleting all the connected organizations and accounts.": "Ailosod y cais, gan ddileu'r holl sefydliadau a chyfrifon cysylltiedig.",
"Save": "Cadw",
"Select All": "Dewiswch Bobeth",
"Services": "Gwasanaethau",
"Settings": "Gosodiadau",
"Shortcuts": "Llwybrau byr",
"Show app icon in system tray": "Dangos eicon ap yn yr hambwrdd system",
"Show app unread badge": "Dangos bathodyn heb ei ddarllen ",
"Show desktop notifications": "Dangos hysbysiadau bwrdd gwaith",
"Show sidebar": "Dangos bar ochr",
"Spellchecker Languages": "Ieithoedd Sillafu",
@@ -117,11 +123,10 @@
"View Shortcuts": "Gweld y Llwybrau Byr",
"Window": "Ffenestr",
"Window Shortcuts": "Llwybrau Byr Ffenestri",
"YES": "YDY",
"Yes": "Ydy",
"You can select a maximum of 3 languages for spellchecking.": "Gallwch ddewis uchafswm o 3 iaith ar gyfer gwirio sillafu.",
"Zoom In": "Chwyddo Mewn",
"Zoom Out": "Chwyddo allan",
"keyboard shortcuts": "llwybrau byr bysellfwrdd",
"script": "sgript",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "Mae {{{server}}} yn rhedeg fersiwn Zulip Server {{{version}}} sydd wedi dyddio. Efallai na fydd yn gweithio'n llawn yn yr app hon."
}

View File

@@ -1,23 +1,24 @@
{
"About Zulip": "Om Zulip",
"Actual Size": "Faktisk størrelse",
"Add Organization": "Opret organisation",
"Add a Zulip organization": "Opret en Zulip organisation",
"Add Organization": "Tilføj organisation",
"Add a Zulip organization": "Tilføj en Zulip organisation",
"Add custom CSS": "Tilføj egen CSS",
"AddServer": "AddServer",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "Avanceret",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"All the connected organizations will appear here.": "Alle forbundne organisationer vil blive vist her.",
"Always start minimized": "Start altid minimeret",
"App Updates": "App-opdateringer",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "Udseende",
"Application Shortcuts": "Genveje",
"Are you sure you want to disconnect this organization?": "Er du sikker på du vil frakoble denne organisation? ",
"Are you sure you want to disconnect this organization?": "Er du sikker på du vil frakoble denne organisation?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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": "Animér dock ved ny privat meddelelse",
"Cancel": "Annuller",
"Change": "Skift",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Tjek for opdateringer",
@@ -26,6 +27,9 @@
"Connect to another organization": "Forbind til en anden organisation",
"Connected organizations": "Tilsluttede organisationer",
"Copy": "Kopiér",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "Kopiér Zulip URL",
"Create a new organization": "Opret ny organisation",
"Cut": "Klip",
@@ -37,11 +41,11 @@
"Download App Logs": "Download app-logfiler",
"Edit": "Redigér",
"Edit Shortcuts": "Redigér genveje",
"Emoji & Symbols": "Emoji & Symbols",
"Emoji & Symbols": "Emoji og symboler",
"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)",
"Enter Full Screen": "Enter Full Screen",
"Enter Full Screen": "Fuld skærm",
"Factory Reset": "Nulstil til fabriksindstillinger",
"Factory Reset Data": "Factory Reset Data",
"File": "Fil",
@@ -55,20 +59,23 @@
"Hard Reload": "Hård reload",
"Help": "Hjælp",
"Help Center": "Hjælpecenter",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"Hide": "Skjul",
"Hide Others": "Skjul andre",
"Hide Zulip": "Skjul Zulip",
"History": "Historik",
"History Shortcuts": "Historik genveje",
"Keyboard Shortcuts": "Tastatur genveje",
"History Shortcuts": "Historikgenveje",
"Keyboard Shortcuts": "Tastaturgenveje",
"Log Out": "Log ud",
"Log Out of Organization": "Log ud af organisation",
"Look Up": "Look Up",
"Manual proxy configuration": "Manuel proxy opsætning",
"Minimize": "Minimér",
"Minimize": "Minimer",
"Mute all sounds from Zulip": "Dæmp alle lyde fra Zulip",
"NO": "NEJ",
"Network": "Netværk",
"Network and Proxy Settings": "Network and Proxy Settings",
"Network and Proxy Settings": "Netrk og proxy indstillinger",
"No Suggestion Found": "No Suggestion Found",
"Notification settings": "Indstillinger for notifikationer",
"OK": "OK",
"OR": "ELLER",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Organization URL": "Organisation URL",
@@ -85,15 +92,14 @@
"Release Notes": "Release Notes",
"Reload": "Reload",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "Save",
"Select All": "Select All",
"Services": "Services",
"Settings": "Settings",
"Reset App Settings": "Nulstil App-indstillinger",
"Reset the application, thus deleting all the connected organizations and accounts.": "Nulstil applikationen, dvs: slet alle forbundne organisationer og konti.",
"Save": "Gem",
"Select All": "Vælg alle",
"Services": "Tjenester",
"Settings": "Indstillinger",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
@@ -104,7 +110,7 @@
"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 Do Not Disturb": "Slå forstyr ej til eller fra",
"Toggle Full Screen": "Toggle Full Screen",
"Toggle Sidebar": "Toggle Sidebar",
"Toggle Tray Icon": "Toggle Tray Icon",
@@ -117,11 +123,9 @@
"View Shortcuts": "View Shortcuts",
"Window": "Window",
"Window Shortcuts": "Window Shortcuts",
"YES": "YES",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} kører en ældre version {{{version}}}. Den virker måske ikke fuld ud med denne app."
}

View File

@@ -1,47 +1,74 @@
{
"A new update {{{version}}} has been downloaded.": "Ein neues Update {{{version}}} wurde heruntergeladen.",
"A new version {{{version}}} is available. Please update using your package manager.": "Die neue Version {{{version}}} ist verfügbar. Bitte aktualisiere mithile deiner Paketverwaltung.",
"A new version {{{version}}} of Zulip Desktop is available.": "Eine neue Version {{{version}}} von Zulip Desktop ist verfügbar.",
"About": "Über",
"About Zulip": "Über Zulip",
"Actual Size": "Tatsächliche Größe",
"Add Organization": "Organisation hinzufügen",
"Add a Zulip organization": "Zulip-Organisation hinzufügen",
"Add custom CSS": "Eigenes CSS hinzufügen",
"AddServer": "ServerHinzufügen",
"Add custom CSS": "Eigene CSS hinzufügen",
"Add to Dictionary": "Zum Wörterbuch hinzufügen",
"Advanced": "Erweitert",
"All the connected organizations will appear here.": "Alle verbundenen Organisationen werden hier angezeigt.",
"Always start minimized": "Immer minimiert öffnen",
"App Updates": "App Updates",
"App Updates": "App-Updates",
"App language (requires restart)": "Sprache der App (benötigt Neustart)",
"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?",
"Are you sure?": "Sind Sie sicher?",
"Ask where to save files before downloading": "Fragen, wo heruntergeladene Dateien gespeichert werden sollen",
"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)",
"Auto hide Menu bar": "Menü automatisch verbergen",
"Auto hide menu bar (Press Alt key to display)": "Menü automatisch verbergen (zum Anzeigen die Alt-Taste drücken)",
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}": "Verfügbar unter der {{{link}}}Apache-2.0-Lizenz{{{endLink}}}",
"Back": "Zurück",
"Bounce dock on new private message": "Im Dock hüpfen, wenn neue private Nachrichten eingehen",
"CSS file": "CSS-Datei",
"Cancel": "Abbrechen",
"Certificate error": "Zertifikatfehler",
"Change": "Ändern",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Ändere die Spracheinstellung über Systemeinstellungen → Tastatur → Text → Rechtschreibung.",
"Check for Updates": "Auf Updates prüfen",
"Check for Updates": "Auf-Updates prüfen",
"Click to show {{{fileName}}} in folder": "Klicken, um {{{fileName}}} im Verzeichnis zu sehen",
"Close": "Schließen",
"Connect": "Verbinden",
"Connect to another organization": "Mit einer anderen Organisation verbinden",
"Connected organizations": "Verbundene Organisationen",
"Connecting…": "Verbinde …",
"Copy": "Kopieren",
"Copy Email Address": "Email-Addresse kopieren",
"Copy Image": "Bild kopieren",
"Copy Image URL": "Bild-URL kopieren",
"Copy Link": "Link kopieren",
"Copy Zulip URL": "Zulip-URL kopieren",
"Could not add {{{domain}}}. Please contact your system administrator.": "Konnte {{{domain}}} nicht hinzufügen. Bitte kontaktiere deinen Systemadminstrator.",
"Create a new organization": "Eine neue Organisation erstellen",
"Custom CSS file deleted": "Eigene CSS-Datei gelöscht",
"Cut": "Ausschneiden",
"Default download location": "Voreingestelltes Ziel für Downloads",
"Delete": "Löschen",
"Desktop Notifications": "Desktopbenachrichtigungen",
"Desktop Settings": "Desktop-Einstellungen",
"Disable Do Not Disturb": "Bitte nicht stören ausschalten",
"Disconnect": "Verbindung trennen",
"Disconnect organization": "Organisation trennen",
"Do Not Disturb": "Bitte nicht stören",
"Download App Logs": "Logdateien der App herunterladen",
"Download Complete": "Download vollständig",
"Download failed": "Download fehlgeschlagen",
"Edit": "Bearbeiten",
"Edit Shortcuts": "Tastenkürzel bearbeiten",
"Emoji & Symbols": "Emoji & Symbole",
"Enable Do Not Disturb": "Bitte nicht stören einschalten",
"Enable auto updates": "Automatisch aktualisieren",
"Enable error reporting (requires restart)": "Fehlerberichte aktivieren (erfordert Neustart)",
"Enable spellchecker (requires restart)": "Rechtschreibprüfung aktivieren (erfordert Neustart)",
"Enter Full Screen": "Vollbildschirm aktivieren",
"Enter Languages": "Sprachen eingeben",
"Error saving new organization": "Neue Organisation konnte nicht gespeichert werden",
"Error saving update notifications": "Update-Benachrichtigungen konnten nicht gespeichert werden",
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}": "Fehler: {{{error}}}\n\nDie neueste Version von Zulip Desktop ist hier verfügbar:\n{{{link}}}\nAktuelle Version: {{{version}}}",
"Factory Reset": "Alle Einstellungen auf Standardwerte zurücksetzen",
"Factory Reset Data": "Auf Werkseinstellung zurücksetzen",
"File": "Datei",
@@ -52,54 +79,83 @@
"Functionality": "Funktionalität",
"General": "Allgemein",
"Get beta updates": "Auf Betaversionen aktualisieren",
"Go Back": "Zurück",
"Hard Reload": "Komplett neu laden",
"Help": "Hilfe",
"Help Center": "Hilfe-Zentrum",
"Help Center": "Hilfecenter",
"Hide": "Verbergen",
"Hide Others": "Andere verbergen",
"Hide Zulip": "Zulip verbergen",
"History": "Verlauf",
"History Shortcuts": "Kurzbefehle für Verlauf",
"Install Later": "Später installieren",
"Install and Relaunch": "Installieren und neustarten",
"It will be installed the next time you restart the application.": "Es wird beim nächsten Neustart der Anwendung aktualisiert.",
"Keyboard Shortcuts": "Tastenkürzel",
"Later": "Später",
"Loading": "Laden",
"Log Out": "Abmelden",
"Log Out of Organization": "Von Organisation abmelden",
"Look Up": "Nachschlagen",
"Maintained by {{{link}}}Zulip{{{endLink}}}": "Maintained von {{{link}}}Zulip{{{endLink}}}",
"Manual Download": "Manueller Download",
"Manual proxy configuration": "Manuelle Proxy-Konfiguration",
"Minimize": "Minimieren",
"Mute all sounds from Zulip": "Alle Zulip-Klänge stummschalten",
"NO": "NEIN",
"Network": "Netzwerk",
"Network and Proxy Settings": "Netzwerk- und Proxy-Einstellungen",
"New servers added. Reload app now?": "Neue Server hinzugefügt. App jetzt erneut laden?",
"No": "Nein",
"No Suggestion Found": "Keine Vorschläge gefunden",
"No unread messages": "Keine ungelesenen Nachrichten",
"No updates available.": "Keine Updates verfügbar.",
"Notification settings": "Benachrichtigungseinstellungen",
"OK": "OK",
"OR": "ODER",
"On macOS, the OS spellchecker is used.": "In macOS wird die OS Rechtschreibprüfung verwendet.",
"Organization URL": "URL der Organisation",
"Opening {{{link}}}…": "Öffne {{{link}}}…",
"Organization URL": "Organisations-URL",
"Organizations": "Organisationen",
"PAC script": "PAC-Skript",
"Paste": "Einfügen",
"Paste and Match Style": "Ohne Formatierung einfügen",
"Please contact your system administrator.": "Bitte kontaktiere deinen Systemadministrator.",
"Press {{{exitKey}}} to exit full screen": "Drücke {{{exitKey}}} um den Vollbildmodus zu beenden",
"Proxy": "Proxy",
"Proxy bypass rules": "Proxy-Ausnahmen",
"Proxy rules": "Proxy-Regeln",
"Proxy settings saved.": "Proxy-Einstellungen gespeichert.",
"Quit": "Beenden",
"Quit Zulip": "Zulip beenden",
"Quit when the window is closed": "Beim Schließen des Fensters beenden",
"Redirecting": "Leite um",
"Redo": "Wiederholen",
"Release Notes": "Hinweise zur Versionsfreigabe",
"Reload": "Neu laden",
"Removing {{{url}}} is a restricted operation.": "Entfernung von {{{url}}} ist eine eingeschränkte Operation.",
"Report an Issue": "Ein Problem melden",
"Reset App Settings": "Einstellungen der App zurücksetzen",
"Reset App Settings": "App-Einstellungen zurücksetzen",
"Reset the application, thus deleting all the connected organizations and accounts.": "Die Anwendung zurücksetzen. Dabei werden alle verbundenen Organisationen und Konten gelöscht.",
"Save": "Speichern",
"Select All": "Alles auswählen",
"Select Download Location": "Wählen Sie das Download-Ziel",
"Select file": "Datei auswählen",
"Services": "Dienste",
"Setting locked by system administrator.": "Einstellung durch Systemadministrator gesperrt.",
"Settings": "Einstellungen",
"Shortcuts": "Kurzbefehle",
"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 sidebar": "Seitenleiste anzeigen",
"Show unread count badge on app icon": "Anzahl ungelesener Nachrichten auf dem App-Symbol anzeigen",
"Spellchecker Languages": "Sprachen für die Rechtschreibprüfung",
"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",
"The custom CSS previously set is deleted.": "Das zuvor eingestellte eigene CSS ist gelöscht.",
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}": "Der Server hat ein ungültiges Zertifikat für {{{origin}}} vorgelegt:\n\n{{{error}}}",
"The update will be downloaded in the background. You will be notified when it is ready to be installed.": "Das Update wird im Hintegrund heruntergeladen. Du wirst benachrichigt, wenn es zur Installation bereit ist.",
"There was an error while saving the new organization. You may have to add your previous organizations again.": "Beim Speichern der neuen Organisation ist ein Fehler aufgetreten. Möglicherweise musst du deine vorherigen Organisationen erneut hinzufügen.",
"These desktop app shortcuts extend the Zulip webapp's": "Dies sind zusätzliche Kurzbefehle in der Desktop-App gegenüber der Web-App",
"Tip": "Tipp",
"Toggle DevTools for Active Tab": "Entwickler-Tools für aktiven Tab umschalten",
@@ -109,19 +165,31 @@
"Toggle Sidebar": "Seitenleiste umschalten",
"Toggle Tray Icon": "Tray-Icon umschalten",
"Tools": "Extras",
"Unable to check for updates.": "Update-Verfügbarkeit konnte nicht geprüft werden.",
"Unable to download the update.": "Update konnte nicht heruntergeladen werden.",
"Undo": "Rückgängig",
"Unhide": "Nicht mehr verbergen",
"Unknown error": "Unbekannter Fehler",
"Upload": "Hochladen",
"Use system proxy settings (requires restart)": "Systemweite Proxy-Einstellungen verwenden (erfordert Neustart)",
"Verify that it works and then click Reconnect.": "Prüfe, das es funktioniert und klicke auf Wiederverbinden.",
"View": "Ansicht",
"View Shortcuts": "Tastenkürzel anzeigen",
"We encountered an error while saving the update notifications.": "Beim Speichern der Update-Benachrichtigungen ist ein Fehler aufgetreten.",
"When the application restarts, it will be as if you have just downloaded the Zulip app.": "Wenn die Anwendung neu startet, wird es sein als hättest du die Zulip-App erst heruntergeladen.",
"Window": "Fenster",
"Window Shortcuts": "Kurzbefehle für Fenster",
"YES": "JA",
"Yes": "Ja",
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}": "Du verwendest die neueste Version von Zulip Desktop.\nVersion: {{{version}}}",
"You can select a maximum of 3 languages for spellchecking.": "Du kannst höchstens 3 Sprachen für die Rechtschreibprüfung auswählen.",
"Your internet connection doesn't seem to work properly!": "Deine Internetverbindung scheint nicht ordentlich zu funktionieren!",
"Zoom In": "Vergrößern",
"Zoom Out": "Verkleinern",
"Zulip": "Zulip",
"Zulip Update": "Zulip-Aktualisierung",
"keyboard shortcuts": "Tastenkürzel",
"script": "Skript",
"your-organization.zulipchat.com or zulip.your-organization.com": "your-organization.zulipchat.com oder zulip.your-organization.com",
"{number, plural, one {# unread message} other {# unread messages}}": "{number, plural, one {# ungelesene Nachricht} other {# ungelesene Nachrichten}}",
"{number, plural, one {Could not add # organization} other {Could not add # organizations}}": "{number, plural, one {konnte # Organisation nicht hinzufügen} other {konnte # Organisationen nicht hinzufügen}}",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "Auf {{{server}}} läuft die nicht mehr aktuelle Version {{{version}}} von Zulip Server. Es kann sein, dass diese Anwendung damit nicht vollständig funktioniert."
}

View File

@@ -1,127 +1,193 @@
{
"About Zulip": "Σχετικά με το Zulip",
"A new update {{{version}}} has been downloaded.": "Έχει ληφθεί μια νέα ενημέρωση {{{version}}}.",
"A new version {{{version}}} is available. Please update using your package manager.": "Μια νέα έκδοση {{{version}}} είναι διαθέσιμη. Παρακαλούμε ενημερώστε χρησιμοποιώντας τον διαχειριστή πακέτων.",
"A new version {{{version}}} of Zulip Desktop is available.": "Μια νέα έκδοση {{{version}}} του Zulip Desktop είναι διαθέσιμη.",
"About": "Περί",
"About Zulip": "Περί Zulip",
"Actual Size": "Πραγματικό μέγεθος",
"Add Organization": "Προσθήκη Οργανισμού",
"Add a Zulip organization": "Προσθήκη οργανισμού Zulip",
"Add custom CSS": "Προσθήκη χειροποίητης CSS.",
"AddServer": "ΠροσθήκηServer",
"Add custom CSS": "Προσθήκη προσαρμοσμένου CSS",
"Add to Dictionary": "Προσθήκη σε Λεξικό",
"Advanced": "Για προχωρημένους",
"All the connected organizations will appear here.": "Όλοι οι συνδεδεμένοι οργανισμοί θα εμφανίζονται εδώ.",
"Always start minimized": "Να ξεκινά πάντα ελαχιστοποιημένο",
"App Updates": "Ενημερώσεις Εφαρμογής",
"App language (requires restart)": "Γλώσσα εφαρμογής (χρειάζεται επανεκκίνηση)",
"App Updates": "Ενημερώσεις εφαρμογής",
"App language (requires restart)": "Γλώσσα εφαρμογής (απαιτεί επανεκκίνηση)",
"Appearance": "Εμφάνιση",
"Application Shortcuts": "Συντομεύσεις εφαρμογής",
"Are you sure you want to disconnect this organization?": "Είστε σίγουροι ότι θέλετε να αποσυνδέσετε αυτό τον οργανισμό;",
"Ask where to save files before downloading": "Να ερωτούμαι πού να αποθηκευτούν τα αρχεία προτού κατεβούν.",
"Auto hide Menu bar": "Αυτόματη απόκρυψη γραμμής Μενού",
"Auto hide menu bar (Press Alt key to display)": "Αυτόματη απόκρυψη γραμμής Μενού (Πατήστε Alt για να εμφανιστεί)",
"Are you sure?": "Είστε σίγουροι;",
"Ask where to save files before downloading": "Ρώτησε πού να αποθηκευτούν τα αρχεία πριν από τη λήψη",
"Auto hide Menu bar": "Αυτόματη απόκρυψη γραμμής μενού",
"Auto hide menu bar (Press Alt key to display)": "Αυτόματη απόκρυψη γραμμής μενού (Πατήστε Alt για να εμφανιστεί)",
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}": "Διαθέσιμο υπό το {{{link}}}Apache 2.0 License{{{endLink}}}",
"Back": "Πίσω",
"Bounce dock on new private message": "Να χοροπηδάει το σχετικό εικονίδιο κατά τη λήψη ιδιωτικού μηνύματος",
"Bounce dock on new private message": "Να αναπηδά το εικονίδιο εφαρμογής σε νέο προσωπικό μήνυμα",
"CSS file": "Αρχείο CSS",
"Cancel": "Ακύρωση",
"Certificate error": "Σφάλμα πιστοποιητικού",
"Change": "Αλλαγή",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Αλλάξτε τη γλώσσα από τις Επιλογές Συστήματος → Πληκτρολόγιο → Κείμενο → Γραφή",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Αλλάξτε τη γλώσσα από τις Προτιμήσεις Συστήματος → Πληκτρολόγιο → Κείμενο → Γραφή.",
"Check for Updates": "Έλεγχος για Ενημερώσεις",
"Click to show {{{fileName}}} in folder": "Κάνετε κλικ για την εμφάνιση του {{{fileName}}} στο φάκελο",
"Close": "Κλείσιμο",
"Connect": "Σύνδεση",
"Connect to another organization": "Σύνδεση με άλλο οργανισμό",
"Connect to another organization": "Σύνδεση με διαφορετικό οργανισμό",
"Connected organizations": "Συνδεδεμένοι οργανισμοί",
"Connecting…": "Σύνδεση…",
"Copy": "Αντιγραφή",
"Copy Zulip URL": "Αντιγραφή διεύθυνσης URL Zulip",
"Copy Email Address": "Αντιγραφή διεύθυνσης email",
"Copy Image": "Αντιγραφή εικόνας",
"Copy Image URL": "Αντιγραφή διεύθυνσης εικόνας",
"Copy Link": "Αντιγραφή συνδέσμου",
"Copy Zulip URL": "Αντιγραφή Zulip URL",
"Could not add {{{domain}}}. Please contact your system administrator.": "Αδυναμία προσθήκης {{{domain}}}. Παρακαλούμε επικοινωνήστε με τον διαχειριστή συστήματος.",
"Create a new organization": "Δημιουργία νέου οργανισμού",
"Custom CSS file deleted": "Διεγράφη το προσαρμοσμένο αρχείο CSS",
"Cut": "Αποκοπή",
"Default download location": "Προεπιλεγμένη τοποθεσία λήψης",
"Delete": "Διαγραφή",
"Desktop Notifications": "Ειδοποιήσεις στην Επιφάνεια Εργασίας",
"Desktop Settings": "Ρυθμίσεις Επιφάνειας Εργασίας",
"Disable Do Not Disturb": "Απενεργοποίηση Μην Εχνοχλείτε",
"Disconnect": "Αποσύνδεση",
"Download App Logs": "Λήψη Logs Εφαρμογής",
"Edit": "Τροποποίηση",
"Edit Shortcuts": "Τροποποίηση Συντομεύσεων",
"Emoji & Symbols": "Φατσούλες Ιμότζι και Σύμβολα",
"Disconnect organization": "Αποσύνδεση οργανισμού",
"Do Not Disturb": "Μην ενοχλείτε",
"Download App Logs": "Λήψη καταγραφών Εφαρμογής",
"Download Complete": "Η λήψη ολοκληρώθηκε",
"Download failed": "Η λήψη απέτυχε",
"Edit": "Επεξεργασία",
"Edit Shortcuts": "Επεξεργασία Συντομεύσεων",
"Emoji & Symbols": "Emoji & Σύμβολα",
"Enable Do Not Disturb": "Ενεργοποίηση Μην Ενοχλείτε",
"Enable auto updates": "Ενεργοποίηση αυτόματων ενημερώσεων",
"Enable error reporting (requires restart)": "Ενεργοποίηση αναφοράς λαθών (χρειάζεται επανεκκίνηση)",
"Enable spellchecker (requires restart)": "Ενεργοποίηση ελέγχου ορθογραφίας (χρειάζεται επανεκκίνηση)",
"Enable error reporting (requires restart)": "Ενεργοποίηση αναφοράς σφαλμάτων (απαιτεί επανεκκίνηση)",
"Enable spellchecker (requires restart)": "Ενεργοποίηση ελέγχου ορθογραφίας (απαιτεί επανεκκίνηση)",
"Enter Full Screen": "Μετάβαση σε Πλήρη Οθόνη",
"Enter Languages": "Προσθήκη Γλωσσών",
"Error saving new organization": "Σφάλμα αποθήκευσης νέου οργανισμού",
"Error saving update notifications": "Σφάλμα αποθήκευσης ειδοποιήσεων ενημερώσεων",
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}": "Σφάλμα: {{{error}}}\n\nΗ πιο πρόσφατη έκδοση του Zulip Desktop είναι διαθέσιμη στο:\n{{{link}}}\nΤρέχουσα έκδοση: {{{version}}}",
"Factory Reset": "Επαναφορά Εργοστασιακών Ρυθμίσεων",
"Factory Reset Data": "Επαναφορά εργοστασιακών ρυθμίσεων - Δεδομένα",
"Factory Reset Data": "Διαγραφή Δεδομένων",
"File": "Αρχείο",
"Find accounts": "Εϋρεση λογαριασμών",
"Find accounts": "Εύρεση λογαριασμών",
"Find accounts by email": "Εύρεση λογαριασμών βάσει email",
"Flash taskbar on new message": "Αναλαμπή γραμμής εργασιών κατά τη λήψη νέου μηνύματος",
"Forward": "Μπροστά",
"Functionality": "Λειτουργία",
"Flash taskbar on new message": "Αναλαμπή γραμμής εργασιών σε νέο μήνυμα",
"Forward": "Εμπρός",
"Functionality": "Λειτουργικότητα",
"General": "Γενικά",
"Get beta updates": "Λήψη beta - δοκιμαστικών ενημερώσεων",
"Hard Reload": "Ολική επαναφόρτωση",
"Get beta updates": "Λήψη ενημερώσεων beta",
"Go Back": "Πίσω",
"Hard Reload": "Ολική Επαναφόρτωση",
"Help": "Βοήθεια",
"Help Center": "Κέντρο Βοήθειας",
"Hide": "Απόκρυψη",
"Hide Others": "Απόκρυψη των υπολοίπων",
"Hide Others": "Απόκρυψη των Yπολοίπων",
"Hide Zulip": "Απόκρυψη του Zulip",
"History": "Ιστορικό",
"History Shortcuts": "Συντομεύσεις Ιστορικού",
"Install Later": "Εγκατάσταση αργότερα",
"Install and Relaunch": "Εγκατάσταση και επανεκκίνηση",
"It will be installed the next time you restart the application.": "Θα εγκατασταθεί κατά την επανεκκίνηση της εφαρμογής.",
"Keyboard Shortcuts": "Συντομεύσεις Πληκτρολογίου",
"Log Out": "Αποσύνδεση",
"Log Out of Organization": "Αποσύνδεση από Οργανισμό",
"Manual proxy configuration": "Χειροκίνητη παραμετροποίηση proxy",
"Later": "Αργότερα",
"Loading": "Φόρτωση",
"Log Out": "Έξοδος",
"Log Out of Organization": "Έξοδος από Οργανισμό",
"Look Up": "Εύρεση",
"Maintained by {{{link}}}Zulip{{{endLink}}}": "Διατηρείται από {{{link}}}Zulip{{{endLink}}}",
"Manual Download": "Χειροκίνητη λήψη",
"Manual proxy configuration": "Χειροκίνητη διαμόρφωση διακομιστή μεσολάβησης",
"Minimize": "Ελαχιστοποίηση",
"Mute all sounds from Zulip": "Σίγαση όλων των ήχων του Zulip",
"NO": "ΟΧΙ",
"Network": "Δίκτυο",
"Network and Proxy Settings": "Ρυθμίσεις Δικτύου και Proxy",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "Στο macOS, χρησιμοποιείται ο έμφυτος έλεγχος ορθογραφίας του.",
"Network and Proxy Settings": "Ρυθμίσεις Δικτύου και Διακομιστή Μεσολάβησης",
"New servers added. Reload app now?": "Προστέθηκαν νέοι διακομιστές. Να γίνει επαναφόρτωση της εφαρμογής;",
"No": "Όχι",
"No Suggestion Found": "Δε βρέθηκαν Προτάσεις",
"No unread messages": "Κανένα μη αναγνωσμένο μήνυμα",
"No updates available.": "Δεν υπάρχουν διαθέσιμες ενημερώσεις.",
"Notification settings": "Ρυθμίσεις ειδοποιήσεων",
"OK": "ΟΚ",
"OR": "ή",
"On macOS, the OS spellchecker is used.": "Στο macOS, χρησιμοποιείται ο έλεγχος ορθογραφίας του λειτουργικού συστήματος.",
"Opening {{{link}}}…": "Άνοιγμα {{{link}}}…",
"Organization URL": "URL Οργανισμού",
"Organizations": "Οργανισμοί",
"PAC script": "PAC σκριπτ",
"Paste": "Επικόλληση",
"Paste and Match Style": "Επικόλληση και υιοθέτηση στυλ προορισμού",
"Proxy": "Proxy",
"Proxy bypass rules": "Κανόνες παράκαμψης Proxy",
"Proxy rules": "Κανόνες Proxy",
"Quit": "Έξοδος",
"Quit Zulip": "Έξοδος από Zulip",
"Quit when the window is closed": "Έξοδος όταν κλείνει το παράθυρο",
"Paste and Match Style": "Επικόλληση και Ταίριασμα Στυλ",
"Please contact your system administrator.": "Παρακαλώ επικοινωνήστε με τον διαχειριστή συστήματος.",
"Press {{{exitKey}}} to exit full screen": "Πιέστε {{{exitKey}}} για έξοδο από πλήρη οθόνη",
"Proxy": "Διακομιστής μεσολάβησης",
"Proxy bypass rules": "Κανόνες παράκαμψης Διακομιστή Μεσολάβησης",
"Proxy rules": "Κανόνες Διακομιστή Μεσολάβησης",
"Proxy settings saved.": "Αποθηκεύτηκαν οι ρυθμίσεις διακομιστή μεσολάβησης.",
"Quit": "Τερματισμός",
"Quit Zulip": "Τερματισμός Zulip",
"Quit when the window is closed": "Τερματισμός όταν κλείνει το παράθυρο",
"Redirecting": "Ανακατεύθυνση",
"Redo": "Ακύρωση αναίρεσης",
"Release Notes": "Σημειώσεις έκδοσης",
"Release Notes": "Σημειώσεις Έκδοσης",
"Reload": "Επαναφόρτωση",
"Report an Issue": "Αναφορά ενός προβλήματος",
"Removing {{{url}}} is a restricted operation.": "Η αφαίρεση του {{{url}}} υπόκειται σε περιορισμό.",
"Report an Issue": "Αναφορά ζητήματος",
"Reset App Settings": "Επαναφορά Ρυθμίσεων Εφαρμογής",
"Reset the application, thus deleting all the connected organizations and accounts.": "Επαναφορά της εφαρμογής, με διαγραφή όλων των συνδεδεμένων οργανισμών και λογαριασμών.",
"Save": "Αποθήκευση",
"Select All": "Επιλογή Όλων",
"Select Download Location": "Επιλογή τοποθεσίας λήψης",
"Select file": "Επιλογή αρχείου",
"Services": "Υπηρεσίες",
"Setting locked by system administrator.": "Η ρύθμιση είναι κλειδωμένη από τον διαχειριστή συστήματος.",
"Settings": "Ρυθμίσεις",
"Shortcuts": "Συντομεύσεις",
"Show app icon in system tray": "Εμφάνιση εικονιδίου στη γραμμή εργασιών",
"Show app unread badge": "Εμφάνιση ένδειξης μη αναγνωσμένων μηνυμάτων",
"Show desktop notifications": "Εμφάνιση ειδοποιήσεων στην Επιφάνεια Εργασίας",
"Show sidebar": "Εμφάνιση πλευρικής γραμμής εργαλείων",
"Show app icon in system tray": "Εμφάνιση εικονιδίου στην περιοχή ειδοποιήσεων",
"Show desktop notifications": "Εμφάνιση ειδοποιήσεων Επιφάνειας Εργασίας",
"Show sidebar": "Εμφάνιση πλευρικής γραμμής",
"Show unread count badge on app icon": "Εμφάνιση πλήθους μη αναγνωσμένων μηνυμάτων στο εικονίδιο της εφαρμογής",
"Spellchecker Languages": "Γλώσσες Ορθογραφικού Ελέγχου",
"Start app at login": "Έναρξη εφαρμογής κατά τη σύνδεση",
"Switch to Next Organization": "Μετάβαση σε Επόμενο Οργανισμό",
"Switch to Previous Organization": "Μετάβαση σε Προηγούμενο Οργανισμό",
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
"Start app at login": "Έναρξη εφαρμογής κατά την είσοδο",
"Switch to Next Organization": "Αλλαγή σε Επόμενο Οργανισμό",
"Switch to Previous Organization": "Αλλαγή σε Προηγούμενο Οργανισμό",
"The custom CSS previously set is deleted.": "Έχει διαγραφεί το προηγούμενο προσαρμοσμένο CSS.",
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}": "Ο διακομιστής παρουσίασε ένα μη έγκυρο πιστοποιητικό για {{{origin}}}:\n\n{{{error}}}",
"The update will be downloaded in the background. You will be notified when it is ready to be installed.": "Η ενημέρωση θα ληφθεί στο παρασκήνιο. Θα ειδοποιηθείτε όταν είναι έτοιμη προς εγκατάσταση.",
"There was an error while saving the new organization. You may have to add your previous organizations again.": "Παρουσιάστηκε σφάλμα κατά την αποθήκευση του νέου οργανισμού. Ενδέχεται να χρειαστεί να προσθέσετε ξανά τους προηγούμενους οργανισμούς σας.",
"These desktop app shortcuts extend the Zulip webapp's": "Αυτές οι συντομεύσεις εφαρμογών για υπολογιστές επεκτείνουν την εφαρμογή web Zulip",
"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 Sidebar": "Εμφάνιση/Απόκρυψη πλευρικής γραμμής εργαλείων",
"Toggle Tray Icon": "Εμφάνιση/Απόκρυψη εικονιδίου γραμμής εργασιών",
"Toggle DevTools for Active Tab": "Εναλλαγή DevTools για την Ενεργή Καρτέλα",
"Toggle DevTools for Zulip App": "Εναλλαγή DevTools για την Εφαρμογή Zulip",
"Toggle Do Not Disturb": "Εναλλαγή Μην Ενοχλείτε",
"Toggle Full Screen": "Εναλλαγή Πλήρους Οθόνης",
"Toggle Sidebar": "Εναλλαγή πλευρικής γραμμής εργαλείων",
"Toggle Tray Icon": "Εναλλαγή εικονιδίου γραμμής εργασιών",
"Tools": "Εργαλεία",
"Unable to check for updates.": "Δεν είναι δυνατός ο έλεγχος για ενημερώσεις.",
"Unable to download the update.": "Δεν είναι δυνατή η λήψη της ενημέρωσης.",
"Undo": "Αναίρεση",
"Unhide": "Επανεμφάνιση",
"Unknown error": "Άγνωστο σφάλμα",
"Upload": "Ανέβασμα",
"Use system proxy settings (requires restart)": "Χρήση ρυθμίσεων proxy συστήματος (χρειάζεται επανεκκίνηση)",
"Use system proxy settings (requires restart)": "Χρήση ρυθμίσεων συστήματος για Διακομιστή Μεσολάβησης (απαιτεί επανεκκίνηση)",
"Verify that it works and then click Reconnect.": "Επιβεβαιώστε ότι λειτουργεί και στη συνέχεια κάνετε κλικ στην Επανασύνδεση.",
"View": "Προβολή",
"View Shortcuts": "Εμφάνιση Συντομεύσεων",
"We encountered an error while saving the update notifications.": "Αντιμετωπίστηκε σφάλμα κατά την αποθήκευση των ειδοποιήσεων ενημερώσεων.",
"When the application restarts, it will be as if you have just downloaded the Zulip app.": "Μετά την επανεκκίνηση της εφαρμογής θα είναι σαν να έχετε μόλις κατεβάσει το Zulip.",
"Window": "Παράθυρο",
"Window Shortcuts": "Συντομεύσεις Παραθύρου",
"YES": "ΝΑΙ",
"Yes": "Ναι",
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}": "Εκτελείται η πιο πρόσφατη έκδοση του Zulip Desktop.\nΈκδοση: {{{version}}}",
"You can select a maximum of 3 languages for spellchecking.": "Μπορούν να επιλεγούν μέχρι 3 γλώσσες ορθογραφικού ελέγχου.",
"Zoom In": "Ζουμ εγγύτερα",
"Zoom Out": "Ζουμ μακρύτερα",
"Your internet connection doesn't seem to work properly!": "Η σύνδεση σας στo Internet δε φαίνεται να λειτουργεί σωστά!",
"Zoom In": "Μεγέθυνση",
"Zoom Out": "Σμίκρυνση",
"Zulip": "Zulip",
"Zulip Update": "Ενημέρωση Zulip",
"keyboard shortcuts": "συντομεύσεις πληκτρολογίου",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
"your-organization.zulipchat.com or zulip.your-organization.com": "your-organization.zulipchat.com ή zulip.your-organization.com",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} τρέχει μία παρωχημένη έκδοση του Zulip Server {{{version}}}. Ενδεχομένως να μη λειτουργεί πλήρως σε αυτή την εφαρμογή."
}

View File

@@ -1,127 +0,0 @@
{
"About Zulip": "About Zulip",
"Actual Size": "Actual Size",
"Add Organization": "Add Organization",
"Add a Zulip organization": "Add a Zulip organization",
"Add custom CSS": "Add custom CSS",
"AddServer": "AddServer",
"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",
"App language (requires restart)": "App language (requires restart)",
"Appearance": "Appearance",
"Application Shortcuts": "Application Shortcuts",
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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",
"Change": "Change",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"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 Notifications": "Desktop Notifications",
"Desktop Settings": "Desktop Settings",
"Disconnect": "Disconnect",
"Download App Logs": "Download App Logs",
"Edit": "Edit",
"Edit Shortcuts": "Edit Shortcuts",
"Emoji & Symbols": "Emoji & Symbols",
"Enable auto updates": "Enable auto updates",
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Factory Reset": "Factory Reset",
"Factory Reset Data": "Factory Reset Data",
"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",
"Hide": "Hide",
"Hide Others": "Hide Others",
"Hide Zulip": "Hide Zulip",
"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",
"Network and Proxy Settings": "Network and Proxy Settings",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"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",
"Quit when the window is closed": "Quit when the window is closed",
"Redo": "Redo",
"Release Notes": "Release Notes",
"Reload": "Reload",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "Save",
"Select All": "Select All",
"Services": "Services",
"Settings": "Settings",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Spellchecker Languages": "Spellchecker Languages",
"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",
"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",
"Unhide": "Unhide",
"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",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
}

View File

@@ -1,10 +1,14 @@
{
"A new update {{{version}}} has been downloaded.": "A new update {{{version}}} has been downloaded.",
"A new version {{{version}}} is available. Please update using your package manager.": "A new version {{{version}}} is available. Please update using your package manager.",
"A new version {{{version}}} of Zulip Desktop is available.": "A new version {{{version}}} of Zulip Desktop is available.",
"About": "About",
"About Zulip": "About Zulip",
"Actual Size": "Actual Size",
"Add Organization": "Add Organization",
"Add a Zulip organization": "Add a Zulip organization",
"Add custom CSS": "Add custom CSS",
"AddServer": "AddServer",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "Advanced",
"All the connected organizations will appear here.": "All the connected organizations will appear here.",
"Always start minimized": "Always start minimized",
@@ -13,35 +17,58 @@
"Appearance": "Appearance",
"Application Shortcuts": "Application Shortcuts",
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organization?",
"Are you sure?": "Are you sure?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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)",
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}": "Available under the {{{link}}}Apache 2.0 License{{{endLink}}}",
"Back": "Back",
"Bounce dock on new private message": "Bounce dock on new private message",
"CSS file": "CSS file",
"Cancel": "Cancel",
"Certificate error": "Certificate error",
"Change": "Change",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Check for Updates",
"Click to show {{{fileName}}} in folder": "Click to show {{{fileName}}} in folder",
"Close": "Close",
"Connect": "Connect",
"Connect to another organization": "Connect to another organization",
"Connected organizations": "Connected organizations",
"Connecting…": "Connecting…",
"Copy": "Copy",
"Copy Email Address": "Copy Email Address",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "Copy Zulip URL",
"Could not add {{{domain}}}. Please contact your system administrator.": "Could not add {{{domain}}}. Please contact your system administrator.",
"Create a new organization": "Create a new organization",
"Custom CSS file deleted": "Custom CSS file deleted",
"Cut": "Cut",
"Default download location": "Default download location",
"Delete": "Delete",
"Desktop Notifications": "Desktop Notifications",
"Desktop Settings": "Desktop Settings",
"Disable Do Not Disturb": "Disable Do Not Disturb",
"Disconnect": "Disconnect",
"Disconnect organization": "Disconnect organization",
"Do Not Disturb": "Do Not Disturb",
"Download App Logs": "Download App Logs",
"Download Complete": "Download Complete",
"Download failed": "Download failed",
"Edit": "Edit",
"Edit Shortcuts": "Edit Shortcuts",
"Emoji & Symbols": "Emoji & Symbols",
"Enable Do Not Disturb": "Enable Do Not Disturb",
"Enable auto updates": "Enable auto updates",
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Enter Languages": "Enter Languages",
"Error saving new organization": "Error saving new organization",
"Error saving update notifications": "Error saving update notifications",
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}": "Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}",
"Factory Reset": "Factory Reset",
"Factory Reset Data": "Factory Reset Data",
"File": "File",
@@ -52,6 +79,7 @@
"Functionality": "Functionality",
"General": "General",
"Get beta updates": "Get beta updates",
"Go Back": "Go Back",
"Hard Reload": "Hard Reload",
"Help": "Help",
"Help Center": "Help Center",
@@ -60,46 +88,74 @@
"Hide Zulip": "Hide Zulip",
"History": "History",
"History Shortcuts": "History Shortcuts",
"Install Later": "Install Later",
"Install and Relaunch": "Install and Relaunch",
"It will be installed the next time you restart the application.": "It will be installed the next time you restart the application.",
"Keyboard Shortcuts": "Keyboard Shortcuts",
"Later": "Later",
"Loading": "Loading",
"Log Out": "Log Out",
"Log Out of Organization": "Log Out of Organization",
"Look Up": "Look Up",
"Maintained by {{{link}}}Zulip{{{endLink}}}": "Maintained by {{{link}}}Zulip{{{endLink}}}",
"Manual Download": "Manual Download",
"Manual proxy configuration": "Manual proxy configuration",
"Minimize": "Minimize",
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
"NO": "NO",
"Network": "Network",
"Network and Proxy Settings": "Network and Proxy Settings",
"New servers added. Reload app now?": "New servers added. Reload app now?",
"No": "No",
"No Suggestion Found": "No Suggestion Found",
"No unread messages": "No unread messages",
"No updates available.": "No updates available.",
"Notification settings": "Notification settings",
"OK": "OK",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Opening {{{link}}}…": "Opening {{{link}}}…",
"Organization URL": "Organization URL",
"Organizations": "Organizations",
"PAC script": "PAC script",
"Paste": "Paste",
"Paste and Match Style": "Paste and Match Style",
"Please contact your system administrator.": "Please contact your system administrator.",
"Press {{{exitKey}}} to exit full screen": "Press {{{exitKey}}} to exit full screen",
"Proxy": "Proxy",
"Proxy bypass rules": "Proxy bypass rules",
"Proxy rules": "Proxy rules",
"Proxy settings saved.": "Proxy settings saved.",
"Quit": "Quit",
"Quit Zulip": "Quit Zulip",
"Quit when the window is closed": "Quit when the window is closed",
"Redirecting": "Redirecting",
"Redo": "Redo",
"Release Notes": "Release Notes",
"Reload": "Reload",
"Removing {{{url}}} is a restricted operation.": "Removing {{{url}}} is a restricted operation.",
"Report an Issue": "Report an Issue",
"Reset App Settings": "Reset App Settings",
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organizations and accounts.",
"Save": "Save",
"Select All": "Select All",
"Select Download Location": "Select Download Location",
"Select file": "Select file",
"Services": "Services",
"Setting locked by system administrator.": "Setting locked by system administrator.",
"Settings": "Settings",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Show unread count badge on app icon": "Show unread count badge on app icon",
"Spellchecker Languages": "Spellchecker Languages",
"Start app at login": "Start app at login",
"Switch to Next Organization": "Switch to Next Organization",
"Switch to Previous Organization": "Switch to Previous Organization",
"The custom CSS previously set is deleted.": "The custom CSS previously set is deleted.",
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}": "The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}",
"The update will be downloaded in the background. You will be notified when it is ready to be installed.": "The update will be downloaded in the background. You will be notified when it is ready to be installed.",
"There was an error while saving the new organization. You may have to add your previous organizations again.": "There was an error while saving the new organization. You may have to add your previous organizations again.",
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
"Tip": "Tip",
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
@@ -109,19 +165,31 @@
"Toggle Sidebar": "Toggle Sidebar",
"Toggle Tray Icon": "Toggle Tray Icon",
"Tools": "Tools",
"Unable to check for updates.": "Unable to check for updates.",
"Unable to download the update.": "Unable to download the update.",
"Undo": "Undo",
"Unhide": "Unhide",
"Unknown error": "Unknown error",
"Upload": "Upload",
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
"Verify that it works and then click Reconnect.": "Verify that it works and then click Reconnect.",
"View": "View",
"View Shortcuts": "View Shortcuts",
"We encountered an error while saving the update notifications.": "We encountered an error while saving the update notifications.",
"When the application restarts, it will be as if you have just downloaded the Zulip app.": "When the application restarts, it will be as if you have just downloaded the Zulip app.",
"Window": "Window",
"Window Shortcuts": "Window Shortcuts",
"YES": "YES",
"Yes": "Yes",
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}": "You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Your internet connection doesn't seem to work properly!": "Your internet connection doesn't seem to work properly!",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"Zulip": "Zulip",
"Zulip Update": "Zulip Update",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"your-organization.zulipchat.com or zulip.your-organization.com": "your-organization.zulipchat.com or zulip.your-organization.com",
"{number, plural, one {# unread message} other {# unread messages}}": "{number, plural, one {# unread message} other {# unread messages}}",
"{number, plural, one {Could not add # organization} other {Could not add # organizations}}": "{number, plural, one {Could not add # organization} other {Could not add # organizations}}",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
}

View File

@@ -1,10 +1,13 @@
{
"A new update {{{version}}} has been downloaded.": "A new update {{{version}}} has been downloaded.",
"A new version {{{version}}} of Zulip Desktop is available.": "A new version {{{version}}} of Zulip Desktop is available.",
"About": "About",
"About Zulip": "About Zulip",
"Actual Size": "Actual Size",
"Add Organization": "Add Organisation",
"Add a Zulip organization": "Add a Zulip organisation",
"Add custom CSS": "Add custom CSS",
"AddServer": "AddServer",
"Add to Dictionary": "Add to Dictionary",
"Advanced": "Advanced",
"All the connected organizations will appear here.": "All the connected organisations will appear here.",
"Always start minimized": "Always start minimized",
@@ -13,11 +16,16 @@
"Appearance": "Appearance",
"Application Shortcuts": "Application Shortcuts",
"Are you sure you want to disconnect this organization?": "Are you sure you want to disconnect this organisation?",
"Are you sure?": "Are you sure?",
"Ask where to save files before downloading": "Ask where to save files before downloading",
"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)",
"Available under the {{{link}}}Apache 2.0 License{{{endLink}}}": "Available under the {{{link}}}Apache 2.0 License{{{endLink}}}",
"Back": "Back",
"Bounce dock on new private message": "Bounce dock on new private message",
"CSS file": "CSS file",
"Cancel": "Cancel",
"Certificate error": "Certificate error",
"Change": "Change",
"Change the language from System Preferences → Keyboard → Text → Spelling.": "Change the language from System Preferences → Keyboard → Text → Spelling.",
"Check for Updates": "Check for Updates",
@@ -26,14 +34,21 @@
"Connect to another organization": "Connect to another organisation",
"Connected organizations": "Connected organisations",
"Copy": "Copy",
"Copy Email Address": "Copy Email Address",
"Copy Image": "Copy Image",
"Copy Image URL": "Copy Image URL",
"Copy Link": "Copy Link",
"Copy Zulip URL": "Copy Zulip URL",
"Create a new organization": "Create a new organisation",
"Custom CSS file deleted": "Custom CSS file deleted",
"Cut": "Cut",
"Default download location": "Default download location",
"Delete": "Delete",
"Desktop Notifications": "Desktop Notifications",
"Desktop Settings": "Desktop Settings",
"Disconnect": "Disconnect",
"Disconnect organization": "Disconnect organisation",
"Do Not Disturb": "Do Not Disturb",
"Download App Logs": "Download App Logs",
"Edit": "Edit",
"Edit Shortcuts": "Edit Shortcuts",
@@ -42,6 +57,9 @@
"Enable error reporting (requires restart)": "Enable error reporting (requires restart)",
"Enable spellchecker (requires restart)": "Enable spellchecker (requires restart)",
"Enter Full Screen": "Enter Full Screen",
"Error saving new organization": "Error saving new organisation",
"Error saving update notifications": "Error saving update notifications",
"Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}": "Error: {{{error}}}\n\nThe latest version of Zulip Desktop is available at:\n{{{link}}}\nCurrent version: {{{version}}}",
"Factory Reset": "Factory Reset",
"Factory Reset Data": "Factory Reset Data",
"File": "File",
@@ -52,6 +70,7 @@
"Functionality": "Functionality",
"General": "General",
"Get beta updates": "Get beta updates",
"Go Back": "Go Back",
"Hard Reload": "Hard Reload",
"Help": "Help",
"Help Center": "Help Center",
@@ -60,15 +79,28 @@
"Hide Zulip": "Hide Zulip",
"History": "History",
"History Shortcuts": "History Shortcuts",
"Install Later": "Install Later",
"Install and Relaunch": "Install and Relaunch",
"It will be installed the next time you restart the application.": "It will be installed the next time you restart the application.",
"Keyboard Shortcuts": "Keyboard Shortcuts",
"Later": "Later",
"Loading": "Loading",
"Log Out": "Log Out",
"Log Out of Organization": "Log Out of Organisation",
"Look Up": "Look Up",
"Maintained by {{{link}}}Zulip{{{endLink}}}": "Maintained by {{{link}}}Zulip{{{endLink}}}",
"Manual Download": "Manual Download",
"Manual proxy configuration": "Manual proxy configuration",
"Minimize": "Minimize",
"Mute all sounds from Zulip": "Mute all sounds from Zulip",
"NO": "NO",
"Network": "Network",
"Network and Proxy Settings": "Network and Proxy Settings",
"New servers added. Reload app now?": "New servers added. Reload app now?",
"No": "No",
"No Suggestion Found": "No Suggestion Found",
"No updates available.": "No updates available.",
"Notification settings": "Notification settings",
"OK": "OK",
"OR": "OR",
"On macOS, the OS spellchecker is used.": "On macOS, the OS spellchecker is used.",
"Organization URL": "Organisation URL",
@@ -78,6 +110,7 @@
"Proxy": "Proxy",
"Proxy bypass rules": "Proxy bypass rules",
"Proxy rules": "Proxy rules",
"Proxy settings saved.": "Proxy settings saved.",
"Quit": "Quit",
"Quit Zulip": "Quit Zulip",
"Quit when the window is closed": "Quit when the window is closed",
@@ -89,17 +122,23 @@
"Reset the application, thus deleting all the connected organizations and accounts.": "Reset the application, thus deleting all the connected organisations and accounts.",
"Save": "Save",
"Select All": "Select All",
"Select Download Location": "Select Download Location",
"Select file": "Select file",
"Services": "Services",
"Settings": "Settings",
"Shortcuts": "Shortcuts",
"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 sidebar": "Show sidebar",
"Show unread count badge on app icon": "Show unread count badge on app icon",
"Spellchecker Languages": "Spellchecker Languages",
"Start app at login": "Start app at login",
"Switch to Next Organization": "Switch to Next Organisation",
"Switch to Previous Organization": "Switch to Previous Organisation",
"The custom CSS previously set is deleted.": "The custom CSS previously set is deleted.",
"The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}": "The server presented an invalid certificate for {{{origin}}}:\n\n{{{error}}}",
"The update will be downloaded in the background. You will be notified when it is ready to be installed.": "The update will be downloaded in the background. You will be notified when it is ready to be installed.",
"There was an error while saving the new organization. You may have to add your previous organizations again.": "There was an error while saving the new organisation. You may have to add your previous organisations again.",
"These desktop app shortcuts extend the Zulip webapp's": "These desktop app shortcuts extend the Zulip webapp's",
"Tip": "Tip",
"Toggle DevTools for Active Tab": "Toggle DevTools for Active Tab",
@@ -109,19 +148,23 @@
"Toggle Sidebar": "Toggle Sidebar",
"Toggle Tray Icon": "Toggle Tray Icon",
"Tools": "Tools",
"Unable to check for updates.": "Unable to check for updates.",
"Unable to download the update.": "Unable to download the update.",
"Undo": "Undo",
"Unhide": "Unhide",
"Unknown error": "Unknown error",
"Upload": "Upload",
"Use system proxy settings (requires restart)": "Use system proxy settings (requires restart)",
"View": "View",
"View Shortcuts": "View Shortcuts",
"We encountered an error while saving the update notifications.": "We encountered an error while saving the update notifications.",
"Window": "Window",
"Window Shortcuts": "Window Shortcuts",
"YES": "YES",
"Yes": "Yes",
"You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}": "You are running the latest version of Zulip Desktop.\nVersion: {{{version}}}",
"You can select a maximum of 3 languages for spellchecking.": "You can select a maximum of 3 languages for spellchecking.",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"keyboard shortcuts": "keyboard shortcuts",
"script": "script",
"{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app.": "{{{server}}} runs an outdated Zulip Server version {{{version}}}. It may not fully work in this app."
}

Some files were not shown because too many files have changed in this diff Show More