docs: Add comma to all uses of "e.g." in contributor docs.

This commit is contained in:
Lauryn Menard 2024-07-04 12:33:43 +02:00 committed by Tim Abbott
parent 2bb037f2a0
commit 62d452f983
72 changed files with 255 additions and 255 deletions

View File

@ -213,13 +213,13 @@ down the line!
- Open up the parts of the UI that were changed, and make sure they look as
you were expecting.
- Is the new UI consistent with similar UI elements? Think about fonts, colors,
sizes, etc. If a new or modified element has multiple states (e.g. "on" and
sizes, etc. If a new or modified element has multiple states (e.g., "on" and
"off"), consider all of them.
- Is the new UI aligned correctly with the elements around it, both vertically and
horizontally?
- If the PR adds or modifies a clickable element, does it have a hover behavior
that's consistent with similar UI elements?
- If the PR adds or modifies an element (e.g. a button or checkbox) that is
- If the PR adds or modifies an element (e.g., a button or checkbox) that is
sometimes disabled, is the disabled version of the UI consistent with similar
UI elements?
- Did the PR accidentally affect any other parts of the UI? E.g., if the PR

View File

@ -171,7 +171,7 @@ This is a **complete sentence** that briefly summarizes your changes. There are
a few rules to keep in mind:
- Start the sentence with an
[imperative](https://en.wikipedia.org/wiki/Imperative_mood) verb, e.g.
[imperative](https://en.wikipedia.org/wiki/Imperative_mood) verb, e.g.,
"fix", "add", "change", "rename", etc.
- Use proper capitalization and punctuation.
- Avoid abbreviations and acronyms.

View File

@ -60,7 +60,7 @@ better decisions as a group, and learn and have fun along the way.
where they are coming from.
- If you think someone is factually mistaken, consider how they might have reached
their conclusion, and aim to get to a shared understanding. E.g.:
their conclusion, and aim to get to a shared understanding. E.g.,:
- “I wasn't able to replicate this -- is it possible you are on an old Zulip
server?”, rather than “This bug report is wrong.”
@ -86,7 +86,7 @@ question in the development community, or suggesting a new feature. It's
especially important to thank and encourage folks who are stretching themselves
to try something new.
- Remember to say “thanks” when responding to a question or suggestion. E.g.:
- Remember to say “thanks” when responding to a question or suggestion. E.g.,:
- “Thanks for the report! ... ” when someone reports a bug.
- “Thanks for reviewing my PR! ... ”
@ -101,7 +101,7 @@ to try something new.
- You can use a variety of channels to express your appreciation. A comment
directly in a Zulip thread or on a pull request is often best, but in some
cases you may also want to send a friendly direct message. E.g.:
cases you may also want to send a friendly direct message. E.g.,:
- “I've noticed that you've been answering lots of questions in #**development
help** lately. Thanks so much for doing that!”

View File

@ -171,7 +171,7 @@ actual flows for LDAP configuration.
- To disable fakeldap, set `FAKE_LDAP_MODE` back to `None`.
- In all fakeldap configurations, users' fake LDAP passwords are equal
to their usernames (e.g. for `ldapuser1@zulip.com`, the password is
to their usernames (e.g., for `ldapuser1@zulip.com`, the password is
`ldapuser1`).
- `FAKE_LDAP_NUM_USERS` in `zproject/dev_settings.py` can be used to

View File

@ -151,7 +151,7 @@ guide][rtd-git-guide]. In brief, the steps are as follows.
On your **local computer**:
1. Open _Terminal_ (macOS/Linux) or _Git for BASH_.
2. Change directory to where you cloned Zulip (e.g. `cd zulip`).
2. Change directory to where you cloned Zulip (e.g., `cd zulip`).
3. Use `git add` and `git commit` to stage and commit your changes (if you
haven't already).
4. Push your commits to GitHub with `git push origin branchname`.
@ -282,7 +282,7 @@ Next, read the following to learn more about developing for Zulip:
## Using an nginx reverse proxy
For some applications (e.g. developing an OAuth2 integration for
For some applications (e.g., developing an OAuth2 integration for
Facebook), you may need your Zulip development to have a valid SSL
certificate. While `run-dev` doesn't support that, you can do this
with an `nginx` reverse proxy sitting in front of `run-dev`.

View File

@ -132,7 +132,7 @@ installation method described here. We require version 0.67.6+ of WSL 2.
$ sudo apt install rabbitmq-server memcached redis-server postgresql
```
1. Open `/etc/rabbitmq/rabbitmq-env.conf` using e.g.:
1. Open `/etc/rabbitmq/rabbitmq-env.conf` using e.g.,:
```console
$ sudo nano /etc/rabbitmq/rabbitmq-env.conf
@ -955,7 +955,7 @@ The `vagrant up` command basically does the following:
To debug such errors, you can log in to the Vagrant guest machine by
running `vagrant ssh`, which should present you with a standard shell
prompt. You can debug interactively by using e.g.
prompt. You can debug interactively by using e.g.,
`cd zulip && ./tools/provision`, and then running the individual
subcommands that failed. Once you've resolved the problem, you can
rerun `tools/provision` to proceed; the provisioning system is
@ -1094,7 +1094,7 @@ NO_PROXY localhost,127.0.0.1,.example.com,.zulipdev.com
```
For proxies that require authentication, the config will be a bit more
complex, e.g.:
complex, e.g.,:
```text
HTTP_PROXY http://userName:userPassword@192.168.1.1:8080
@ -1119,7 +1119,7 @@ then do a `vagrant reload`.
### Using a different port for Vagrant
You can also change the port on the host machine that Vagrant uses by
adding to your `~/.zulip-vagrant-config` file. E.g. if you set:
adding to your `~/.zulip-vagrant-config` file. E.g., if you set:
```text
HOST_PORT 9971

View File

@ -1,12 +1,12 @@
If you ever want to recreate your development environment again from
scratch (e.g. to test a change you've made to the provisioning
scratch (e.g., to test a change you've made to the provisioning
process, or because you think something is broken), you can do so
using `vagrant destroy` and then `vagrant up`. This will usually be
much faster than the original `vagrant up` since the base image is
already cached on your machine (it takes about 5 minutes to run with a
fast Internet connection).
Any additional programs (e.g. Zsh, emacs, etc.) or configuration that
Any additional programs (e.g., Zsh, emacs, etc.) or configuration that
you may have installed in the development environment will be lost
when you recreate it. To address this, you can create a script called
`tools/custom_provision` in your Zulip Git checkout; and place any

View File

@ -62,7 +62,7 @@ branch, or a significant time has passed since you last used it.
### Test an install
The `test-install` tooling takes a distribution release name
(e.g. "jammy"), the path to an unpacked release directory
(e.g., "jammy"), the path to an unpacked release directory
or tarball, and then any of the normal options you want to pass down
into the installer.

View File

@ -13,7 +13,7 @@ the development environment][authentication-dev-server].
## Common
- Zulip's `main` branch moves quickly, and you should rebase
constantly with e.g.
constantly with e.g.,
`git fetch upstream; git rebase upstream/main` to avoid developing
on an old version of the Zulip codebase (leading to unnecessary
merge conflicts).

View File

@ -354,7 +354,7 @@ it? There's several major benefits to this system:
pre-substituted for the user.
- We're able to share implementation language and visual styling with
our Help Center, which is especially useful for the extensive
non-REST API documentation pages (e.g. our bot framework).
non-REST API documentation pages (e.g., our bot framework).
Using the standard OpenAPI format gives us flexibility, though; if we
later choose to migrate to third-party tools, we don't need to redo
@ -393,7 +393,7 @@ documentation for the REST API endpoint for uploading a file,
There are no parameters for this endpoint, and only one return value
specific to this endpoint, `uri`, which is the URL of the uploaded file.
If we comment out that return value and example from the existing API
documentation in `zerver/openapi/zulip.yaml`, e.g.:
documentation in `zerver/openapi/zulip.yaml`, e.g.,:
```yaml
/user_uploads:

View File

@ -19,7 +19,7 @@ and a handful of longer guides. The feature articles serve a few different purpo
organization settings.
Zulip help center documentation is available under `/help/` on any Zulip server;
(e.g. <https://zulip.com/help/> or `http://localhost:9991/help/` in
(e.g., <https://zulip.com/help/> or `http://localhost:9991/help/` in
the Zulip development environment). The help center documentation is not hosted
on ReadTheDocs, since Zulip supports running a server completely disconnected
from the Internet, and we'd like the documentation to be available in that
@ -55,7 +55,7 @@ There are over 100 feature articles and longer guides in the
the current documentation as a resource and guide as you begin.
- Use the list on [Zulip help center home](https://zulip.com/help/)
to find the section of the docs (e.g. Preferences, Sending
to find the section of the docs (e.g., Preferences, Sending
messages, Reading messages, etc.) that relates to the new feature
you're documenting.
@ -144,7 +144,7 @@ updating existing documentation:
An anti-pattern is trying to make up for bad UX by adding help center
documentation. It's worth remembering that for most articles, almost 100% of
the users of the feature will never read the article. Instructions for
filling out forms, interacting with UI widgets (e.g. typeaheads), interacting
filling out forms, interacting with UI widgets (e.g., typeaheads), interacting
with modals, etc. should never go in the help center documentation.
In such cases, you may be able to fix the problem by adding text in-app,
where the user will see it as they are interacting with the feature.
@ -208,7 +208,7 @@ as guidance when documenting Zulip's features.
### User interface
When you refer to the features in the Zulip UI, you should **bold** the
feature's name followed by the feature itself (e.g. **Settings** page,
feature's name followed by the feature itself (e.g., **Settings** page,
**Change password** button, **Email** field). No quotation marks should be
used. Use **bold** for channel names, and quotation marks for topic names.
@ -242,7 +242,7 @@ an arrow key (↑, ↓, ←, →) will also need the `"arrow-key"` CSS class inc
in the `<kbd>` start tag (e.g., ` <kbd class="arrow-key">↑</kbd>`).
Use the labels one sees on the actual keyboard rather than the letter they
produce when pressed (e.g. `R` and `Shift` + `R` rather than `r` and `R`).
produce when pressed (e.g., `R` and `Shift` + `R` rather than `r` and `R`).
For symbols, such as `?` or `@`, that are produced through key combinations that
change depending on the user's keyboard layout, you should use the symbol as it
appears on a keyboard instead of any specific combination of keys.
@ -290,7 +290,7 @@ your documentation to help improve its readability:
### Images
Images and screenshots should be included in help center documentation
only if they will help guide the user in how to do something (e.g. if
only if they will help guide the user in how to do something (e.g., if
the image will make it much clearer which element on the page the user
should interact with). For instance, an image of an element should
not be included if the element the user needs to interact with is the
@ -435,7 +435,7 @@ languages in API docs, etc. To create a tab switcher, write:
{end_tabs}
```
The tab identifiers (e.g. `desktop-web` above) and their mappings to
The tab identifiers (e.g., `desktop-web` above) and their mappings to
the tabs' labels are declared in
[zerver/lib/markdown/tabbed_sections.py][tabbed-sections-code].

View File

@ -46,7 +46,7 @@ for every pull request, accessible from a "Details" link in the
to submit a screenshot with any pull request modifying documentation
to help make reviews efficient.
If you want to build the developer documentation locally (e.g. to test
If you want to build the developer documentation locally (e.g., to test
your changes), the dependencies are automatically installed as part of
Zulip development environment provisioning, and you can build the
documentation using:
@ -58,7 +58,7 @@ documentation using:
and then opening `http://127.0.0.1:9991/docs/index.html` in your
browser. The raw files are available at
`file:///path/to/zulip/docs/_build/html/index.html` in your browser
(so you can also use e.g. `firefox docs/_build/html/index.html` from
(so you can also use e.g., `firefox docs/_build/html/index.html` from
the root of your Zulip checkout).
If you are adding a new page to the table of contents, you will want

View File

@ -19,7 +19,7 @@ In the Zulip project, we encourage submitting [draft pull
requests][github-help-draft-pr] early and often. This allows you to
share your code to make it easier to get feedback and help with your
changes, even if you don't think your pull request is ready to be
merged (e.g. it might not work or pass tests). This sets expectations
merged (e.g., it might not work or pass tests). This sets expectations
correctly for any feedback from other developers, and prevents your
work from being merged before you're confident in it.

View File

@ -410,7 +410,7 @@ To git@github.com:christi3k/zulip.git
! [rejected] 1754-docs-add-git-workflow -> 1754-docs-add-git-workflow (non-fast-forward)
error: failed to push some refs to 'git@github.com:christi3k/zulip.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: its remote counterpart. Integrate the remote changes (e.g.,
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

View File

@ -120,7 +120,7 @@ HEAD is now at 5a1e982 tools: Update clean-branches to clean review branches.
`tools/push-to-pull-request` is primarily useful for maintainers who
are merging other users' commits into a Zulip repository. After doing
`reset-to-pull-request` or `fetch-pull-request` and making some
changes, you can push a branch back to a pull request with e.g.
changes, you can push a branch back to a pull request with e.g.,
`tools/push-to-pull-request 1234`. This is useful for a few things:
- Getting CI to run and enabling you to use the GitHub "Merge" buttons

View File

@ -1,6 +1,6 @@
# How to have an amazing experience
If you are joining Zulip as part of an outreach program (e.g.
If you are joining Zulip as part of an outreach program (e.g.,
[GSoC](https://summerofcode.withgoogle.com/) or
[Outreachy](https://www.outreachy.org/)), welcome! Please make sure you read
this page carefully early on, and we encourage you to come back to it over the
@ -125,7 +125,7 @@ You can find many examples in the
working on, not just issue/PR numbers.
- For projects where you are waiting on feedback, what **type of feedback** is
needed (e.g. product review, next round of code review after initial
needed (e.g., product review, next round of code review after initial
feedback has been addressed, answer to some question, etc.). Use [silent
mentions](https://zulip.com/help/mention-a-user-or-group#silently-mention-a-user)
to indicate whose feedback is required, if you think you know who it should
@ -183,7 +183,7 @@ time, start by quickly sharing your initial thoughts or feedback on the general
direction, and let the PR author know when you expect to provide a more detailed
review.
Make sure the GitHub comments on the PR are always clear on the status -- e.g.
Make sure the GitHub comments on the PR are always clear on the status -- e.g.,
buddy code review has been requested, feedback is being discussed, code buddy
has approved the PR, etc. This will help project maintainers know when it's time
to move on to the next step of the review process.

View File

@ -90,7 +90,7 @@ requests to those services, but the Django-based database libraries we
use in most of our codebase don't support that, and in any case,
our architecture doesn't require Tornado to do that).
The parts that are activated relatively rarely (e.g. when people type or
The parts that are activated relatively rarely (e.g., when people type or
click on something) are processed by the Django application server.
There is detailed documentation on the
@ -209,7 +209,7 @@ RabbitMQ is a queueing system. Its config files live in
`zulip/puppet/zulip/files/rabbitmq`. Initial configuration happens in
`zulip/scripts/setup/configure-rabbitmq`.
We use RabbitMQ for queuing expensive work (e.g. sending emails
We use RabbitMQ for queuing expensive work (e.g., sending emails
triggered by a message, push notifications, some analytics, etc.) that
require reliable delivery but which we don't want to do on the main
thread. It's also used for communication between the application server
@ -256,7 +256,7 @@ administrator, e.g., in case of outages.
This component is intended to install Nagios plugins intended to be run
on a Nagios server; most of the Zulip Nagios plugins are intended to be
run on the Zulip servers themselves, and are included with the relevant
component of the Zulip server (e.g.
component of the Zulip server (e.g.,
`puppet/zulip/manifests/postgresql_backups.pp` installs a few under
`/usr/lib/nagios/plugins/zulip_backups`).

View File

@ -198,7 +198,7 @@ _Released 2024-03-19_
- Fixed the “Topics are required for this organization” pop-up incorrectly
closing on some keypresses.
- Fixed the analytics cron job leaking its lock if unexpectedly interrupted
(e.g. by a reboot).
(e.g., by a reboot).
- Fixed sorting by expiration date in the “Invites” settings panel.
- Fixed the gear menu staying open after clicking on “plan management”.
- Fixed a small visual issue with bot icons in the left sidebar DM section.
@ -1697,7 +1697,7 @@ _Released 2021-07-22_
- Fixed a performance/scalability issue for installations using the S3
file uploads backend.
- Fixed a bug where users could turn other users messages they could
read into widgets (e.g. polls).
read into widgets (e.g., polls).
- Fixed a bug where emoji and avatar image requests were sent through
Camo; doing so does not add any security benefit, and broke custom
emoji that had been imported from Slack in Zulip 1.8.1 or earlier.
@ -1813,7 +1813,7 @@ _Released 2021-05-13_
`zulip::foo` to `zulip::profile::foo`. Configuration referencing
these `/etc/zulip/zulip.conf` will be automatically updated during
the upgrade process, but if you have a complex deployment or you
maintain `zulip.conf` is another system (E.g. with the [manual
maintain `zulip.conf` is another system (e.g., with the [manual
configuration][docker-zulip-manual] option for
[docker-zulip][docker-zulip]), you'll want to manually update the
`puppet_classes` variable.
@ -1895,7 +1895,7 @@ _Released 2021-05-13_
unsubscribe links.
- Password forms now have a "Show password" widget.
- Fixed performance issues when creating hundreds of new users in
quick succession (E.g. at the start of a conference or event).
quick succession (e.g., at the start of a conference or event).
- Fixed performance issues in organizations with thousands of online users.
- Fixed numerous rare exceptions when running Zulip at scale.
- Fixed several subtle installer bugs.
@ -3439,7 +3439,7 @@ _Released 2017-10-25_
- Switched from npm to yarn for downloading JS packages.
- Switched the function of the 'q' and 'w' search hotkeys.
- Simplified the settings for configuring senders for our emails.
- Emoji can now be typed with spaces, e.g. entering "robot face" in
- Emoji can now be typed with spaces, e.g., entering "robot face" in
the typeahead as well as "robot_face".
- Improved title and alt text for Unicode emoji.
- Added development tools to make iterating on emails and error pages easy.
@ -3657,7 +3657,7 @@ _Released 2017-02-06_
notifications.
- Added buttons to download .zuliprc files.
- Added italics and strikethrough support in Markdown implementation.
- Added errors for common installations mistakes (e.g. too little RAM).
- Added errors for common installations mistakes (e.g., too little RAM).
- Added a new /authors page showing the contributors to the current
Zulip version.
- Added illustrations to the 404 and 500 pages.
@ -3678,7 +3678,7 @@ _Released 2017-02-06_
- Fixed Zulip Tornado service not working with http_proxy set in environment.
- Fixed text overflow in stream subscriptions.
- Fixed CSS issues with message topic editing.
- Fixed several transactionality bugs (e.g. in Huddle creation).
- Fixed several transactionality bugs (e.g., in Huddle creation).
- Fixed missed-message email configuration error handling.
- Fixed annoying @-mentions in Jira integration.
- Fixed various mismatches between frontend and backend Markdown
@ -3892,7 +3892,7 @@ _Released 2016-05-02_
- Added options for configuring PostgreSQL, RabbitMQ, Redis, and memcached
in settings.py.
- Added documentation on using Hubot to integrate with useful services
not yet integrated with Zulip directly (e.g. Google Hangouts).
not yet integrated with Zulip directly (e.g., Google Hangouts).
- Added new management command to test sending email from Zulip.
- Added Codeship, Pingdom, Taiga, TeamCity, and Yo integrations.
- Added Nagios plugins to the main distribution.

View File

@ -92,7 +92,7 @@ Django context (i.e. with database access).
- `zerver/management/commands/`
[Management commands](../subsystems/management-commands.md) one might run at a
production deployment site (e.g. scripts to change a value or
production deployment site (e.g., scripts to change a value or
deactivate a user properly).
- `zilencer/management/commands/` includes some dev-specific
@ -115,7 +115,7 @@ Django context (i.e. with database access).
- `tools/` Scripts used only in a Zulip development environment.
These are not included in production release tarballs for Zulip, so
that we can include scripts here one wouldn't want someone to run in
production accidentally (e.g. things that delete the Zulip database
production accidentally (e.g., things that delete the Zulip database
without prompting).
- `tools/setup/` Subdirectory of `tools/` for things only used during

View File

@ -32,7 +32,7 @@ server repository][zulip-server].
Organizations self-hosting Zulip primarily use stable releases.
- The numbering scheme is simple: the first digit indicates the major
release series (which we'll refer to as "7.x"). (Before Zulip 3.0,
Zulip versions had another digit, e.g. 1.9.2 was a bug fix release
Zulip versions had another digit, e.g., 1.9.2 was a bug fix release
in the Zulip 1.9.x major release series).
- [New major releases][blog-major-releases], like Zulip 7.0, are
published every 3-6 months, and contain hundreds of features, bug
@ -121,7 +121,7 @@ bug fix release, transparently documenting the issue(s) using the
industry-standard [CVE advisory process](https://cve.mitre.org/).
When new security releases are published, we simultaneously publish
the fixes to the `main` and stable release branches (E.g. `4.x`), so
the fixes to the `main` and stable release branches (e.g., `4.x`), so
that anyone using those branches can immediately upgrade as well.
See also our [security model][security-model] documentation.
@ -143,7 +143,7 @@ The nag will appear only to organization administrators starting a
month before the deadline; after that, it will appear for all users on
the server.
You can adjust the deadline for your installation by setting e.g.
You can adjust the deadline for your installation by setting e.g.,
`SERVER_UPGRADE_NAG_DEADLINE_DAYS = 30 * 21` in
`/etc/zulip/settings.py` and then [restarting the server](../production/settings.md).

View File

@ -367,7 +367,7 @@ Other fields you may want to sync from LDAP include:
group last, if you'd like a user who is in both groups to be a realm
owner rather than a guest).
- String fields like `default_language` (e.g. `en`) or `timezone`, if
- String fields like `default_language` (e.g., `en`) or `timezone`, if
you have that data in the right format in your LDAP database.
You can look at the [full list of fields][models-py] in the Zulip user
@ -544,7 +544,7 @@ it as follows:
metadata and enter them on the right-hand side of this
Python dictionary:
1. Set the outer `idp_name` key to be an identifier for your IdP,
e.g. `testshib` or `okta`. This field appears in URLs for
e.g., `testshib` or `okta`. This field appears in URLs for
parts of your Zulip server's SAML authentication flow.
2. The IdP should provide the `url` and `entity_id` values.
3. Save the `x509cert` value to a file; you'll use it in the
@ -1165,7 +1165,7 @@ If you need to use this feature in combination with those backends,
you should make your logic be applied when processing the
`ZulipDummyBackend` - which is the final layer of the authentication
checks for whether authentication should succeed. If you want to
reject authentication requests e.g. based on IP address of the
reject authentication requests e.g., based on IP address of the
request, this is where it should happen.
:::

View File

@ -206,7 +206,7 @@ the following after unpacking a Zulip production release tarball:
```
To run the database on a separate server, including a cloud provider's managed
PostgreSQL instance (e.g. AWS RDS), or with a warm-standby replica for
PostgreSQL instance (e.g., AWS RDS), or with a warm-standby replica for
reliability, see our [dedicated PostgreSQL documentation][postgresql].
[standalone.pp]: https://github.com/zulip/zulip/blob/main/puppet/zulip/manifests/profile/standalone.pp

View File

@ -80,7 +80,7 @@ with [`EMAIL_USE_SSL = True`](https://docs.djangoproject.com/en/5.0/ref/settings
### Using system email
If you'd like to send outgoing email using the local operating
system's email delivery configuration (e.g. you have `postfix`
system's email delivery configuration (e.g., you have `postfix`
configuration on the system that forwards email sent locally into your
corporate email system), you will likely need to use something like
these setting values:
@ -118,7 +118,7 @@ how to make it work:
["less secure"](https://support.google.com/accounts/answer/6010255);
Gmail doesn't allow servers to send outgoing email by default.
- Note also that the rate limits for Gmail are also quite low
(e.g. 100 / day), so it's easy to get rate-limited if your server
(e.g., 100 / day), so it's easy to get rate-limited if your server
has significant traffic. For more active servers, we recommend
moving to a free account on a transactional email service.

View File

@ -123,7 +123,7 @@ When that finishes, your Zulip server should be fully operational again.
It's common, when testing backup restoration, to restore backups with a
different user-facing hostname than the original server to avoid
disrupting service (e.g. `zuliptest.example.com` rather than
disrupting service (e.g., `zuliptest.example.com` rather than
`zulip.example.com`).
If you do so, just like any other time you change the hostname, you'll
@ -136,7 +136,7 @@ errors when trying to access it via `zuliptest.example.com`.
#### Changing database settings
If you wish to restore onto a very differently configured host (e.g. with
If you wish to restore onto a very differently configured host (e.g., with
`REMOTE_POSTGRES_HOST` set to a different value), you can edit
`/etc/zulip/settings.py` to configure the host to suit the new host's needs,
then restore with `--keep-settings`:
@ -197,7 +197,7 @@ emails to send). You can check whether these queues are empty using
#### Backup details
This section is primarily for users managing backups themselves
(E.g. if they're using a remote PostgreSQL database with an existing
(e.g., if they're using a remote PostgreSQL database with an existing
backup strategy), and also serves as documentation for what is
included in the backups generated by Zulip's standard tools. The
data includes:
@ -213,7 +213,7 @@ data includes:
will be stored in that directory and you'll want to back it up.
- Your Zulip configuration including secrets from `/etc/zulip/`.
E.g. if you lose the value of `secret_key`, all users will need to
E.g., if you lose the value of `secret_key`, all users will need to
log in again when you set up a replacement server since you won't be
able to verify their cookies. If you lose `avatar_salt`, any
user-uploaded avatars will need to be re-uploaded (since avatar
@ -408,7 +408,7 @@ importing.
The commands above create an imported organization on the root domain
(`EXTERNAL_HOST`) of the Zulip installation. You can also import into a
custom subdomain, e.g. if you already have an existing organization on the
custom subdomain, e.g., if you already have an existing organization on the
root domain. Replace the last two lines above with the following, after replacing
`<subdomain>` with the desired subdomain.
@ -433,7 +433,7 @@ recommend starting with sending one to yourself for testing:
./manage.py send_password_reset_email -u username@example.com
```
and then once you're ready, you can email them to everyone using e.g.
and then once you're ready, you can email them to everyone using e.g.,
```bash
./manage.py send_password_reset_email -r '' --all-users
@ -467,7 +467,7 @@ If you're hosting multiple organizations and would like to remove
uploads from a single organization, you'll need to access `realm.id`
in the management shell before deleting the organization from the
database (this will be `2` for the first organization created on a
Zulip server, shown in the example below), e.g.:
Zulip server, shown in the example below), e.g.,:
```bash
rm -rf /home/zulip/uploads/*/2/

View File

@ -54,14 +54,14 @@ unlikely to ever need to interact with that realm.)
Unless you are
[hosting multiple organizations on your Zulip server](multiple-organizations.md),
your single Zulip organization on the root domain will have the empty
string (`''`) as its `string_id`. So you can run e.g.:
string (`''`) as its `string_id`. So you can run e.g.,:
```console
zulip@zulip:~$ /home/zulip/deployments/current/manage.py show_admins -r ''
```
Otherwise, the `string_id` will correspond to the organization's
subdomain. E.g. on `it.zulip.example.com`, use
subdomain. E.g., on `it.zulip.example.com`, use
`/home/zulip/deployments/current/manage.py show_admins -r it`.
## manage.py shell

View File

@ -8,7 +8,7 @@ If you do modify Zulip and then report an issue you see in your
modified version of Zulip, please be responsible about communicating
that fact:
- Ideally, you'd reproduce the issue in an unmodified version (e.g. in
- Ideally, you'd reproduce the issue in an unmodified version (e.g., in
[the Zulip development community](https://zulip.com/development-community/) or on
[zulip.com](https://zulip.com)).
- Where that is difficult or you think it's very unlikely your changes
@ -159,7 +159,7 @@ responsive in debugging any problems caused by a patch we asked
you to apply.
Also, consider asking whether a small fix that is important to you can
be added to the current stable release branch (E.g. `2.1.x`). In
be added to the current stable release branch (e.g., `2.1.x`). In
addition to scheduling that change for Zulip's next bug fix release,
we support changes in stable release branches as though they were
released.
@ -190,8 +190,8 @@ upgrade to Zulip `main` using [upgrade-zulip-from-git][]. Before
upgrading to `main`, make sure you understand:
- In Zulip's version numbering scheme, `main` will always be "newer"
than the latest maintenance release (E.g. `3.1` or `2.1.6`) and
"older" than the next major release (E.g. `3.0` or `4.0`).
than the latest maintenance release (e.g., `3.1` or `2.1.6`) and
"older" than the next major release (e.g., `3.0` or `4.0`).
- The `main` branch is under very active development; dozens of new
changes are integrated into it on most days. The `main` branch
can have thousands of changes not present in the latest release (all

View File

@ -14,7 +14,7 @@ reading.
Zulip's approach for supporting multiple organizations on a single
Zulip server is for each organization to be hosted on its own
subdomain. E.g. you'd have `org1.zulip.example.com` and
subdomain. E.g., you'd have `org1.zulip.example.com` and
`org2.zulip.example.com`.
Web security standards mean that one subdomain per organization is
@ -81,12 +81,12 @@ into the database.
### The root domain
Most Zulip servers host a single Zulip organization on the root domain
(e.g. `zulip.example.com`). The way this is implemented internally
(e.g., `zulip.example.com`). The way this is implemented internally
involves the organization having the empty string (`''`) as its
"subdomain".
You can mix having an organization on the root domain and some others
on subdomains (e.g. `subdivision.zulip.example.com`), but this only
on subdomains (e.g., `subdivision.zulip.example.com`), but this only
works well if there are no users in common between the two
organizations, because the auth cookies for the root domain are
visible to the subdomain (so it's not possible for a single
@ -111,7 +111,7 @@ provider with a whitelist of callback URLs to your Zulip server (or
even a single URL). For those vendors that support a whitelist, you
can provide the callback URLs for each of your Zulip organizations.
The cleaner solution is to register a special subdomain, e.g.
The cleaner solution is to register a special subdomain, e.g.,
`auth.zulip.example.com` with the third-party provider, and then set
`SOCIAL_AUTH_SUBDOMAIN = 'auth'` in `/etc/zulip/settings.py`, so that
Zulip knows to use that subdomain for these authentication callbacks.

View File

@ -19,13 +19,13 @@ primary application server. There are two possible flavors of this -- using a
managed PostgreSQL instance from a cloud provider, or separating the PostgreSQL
server onto a separate (but still Zulip-managed) server for scaling purposes.
### Cloud-provider-managed PostgreSQL (e.g. Amazon RDS)
### Cloud-provider-managed PostgreSQL (e.g., Amazon RDS)
You can use a database-as-a-service like Amazon RDS for the Zulip database. The
experience is slightly degraded, in that most providers don't include useful
dictionary files in their installations, and don't provide a way to provide them
yourself, resulting in a degraded [full-text search][fts] experience around
issues dictionary files are relevant (e.g. stemming).
issues dictionary files are relevant (e.g., stemming).
[fts]: ../subsystems/full-text-search.md

View File

@ -99,7 +99,7 @@ on hardware requirements for larger organizations.
features](https://zulip.com/help/allow-image-link-previews).
- Outgoing SMTP access (usually port 587) to your [SMTP
server](email.md) so that Zulip can send emails.
- A domain name (e.g. `zulip.example.com`) that your users will use to
- A domain name (e.g., `zulip.example.com`) that your users will use to
access the Zulip server. In order to generate valid SSL
certificates [with Certbot][doc-certbot], and to enable other
services such as Google authentication, public DNS name is simpler,
@ -143,7 +143,7 @@ certificate documentation](ssl-certificates.md).
#### Outgoing email
- Outgoing email (SMTP) credentials that Zulip can use to send
outgoing emails to users (e.g. email address confirmation emails
outgoing emails to users (e.g., email address confirmation emails
during the signup process, message notification emails, password
reset, etc.). If you don't have an existing outgoing SMTP solution,
read about
@ -158,7 +158,7 @@ This section details some basic guidelines for running a Zulip server
for larger organizations (especially >1000 users or 500+ daily active
users). Zulip's resource needs depend mainly on 3 parameters:
- daily active users (e.g. number of employees if everyone's an
- daily active users (e.g., number of employees if everyone's an
employee)
- total user accounts (can be much larger)
- message volume.

View File

@ -87,7 +87,7 @@ that your Zulip server sits at `https://10.10.10.10:443`; see
1. Configure the root `nginx.conf` file. We recommend using
`/etc/nginx/nginx.conf` from your Zulip server for our recommended
settings. E.g. if you don't set `client_max_body_size`, it won't be
settings. E.g., if you don't set `client_max_body_size`, it won't be
possible to upload large files to your Zulip server.
1. Configure the `nginx` site-specific configuration (in
@ -149,7 +149,7 @@ Apache requires you use the hostname, not the IP address; see
1. Create an Apache2 virtual host configuration file, similar to the
following. Place it the appropriate path for your Apache2
installation and enable it (E.g. if you use Debian or Ubuntu, then
installation and enable it (e.g., if you use Debian or Ubuntu, then
place it in `/etc/apache2/sites-available/zulip.example.com.conf`
and then run
`a2ensite zulip.example.com && systemctl reload apache2`):
@ -268,7 +268,7 @@ things you need to be careful about when configuring it:
addresses for a given hostname. This can result in mysterious errors
that can be quite difficult to debug. Be sure to declare your
`upstreams` equivalent in a way that won't do load-balancing
unexpectedly (e.g. pointing to a DNS name that you haven't configured
unexpectedly (e.g., pointing to a DNS name that you haven't configured
with multiple IPs for your Zulip machine; sometimes this happens with
IPv6 configuration).

View File

@ -124,7 +124,7 @@ strength allowed is controlled by two settings in
already been sent. As a general philosophy, our policies provide
hard limits on the ways in which message content can be changed or
undone. In contrast, our policies around message topics favor
usefulness (e.g. for conversational organization) over faithfulness
usefulness (e.g., for conversational organization) over faithfulness
to the original. In all configurations:
- Message content can only ever be modified by the original author.
@ -158,7 +158,7 @@ strength allowed is controlled by two settings in
- Administrators can change the ownership of a bot. If a bot is subscribed
to a private channel, then an administrator can indirectly get access to
channel messages by taking control of the bot, though the access will be
limited to what the bot can do. (E.g. incoming webhook bots cannot read
limited to what the bot can do. (e.g., incoming webhook bots cannot read
messages.)
- Every Zulip user has an API key, available on the settings page.
@ -187,7 +187,7 @@ strength allowed is controlled by two settings in
- Incoming webhook bots can only send messages into Zulip.
- Outgoing webhook bots and Generic bots can essentially do anything a
non-administrator user can, with a few exceptions (e.g. a bot cannot
non-administrator user can, with a few exceptions (e.g., a bot cannot
log in to the web application, register for mobile push
notifications, or create other bots).
- Bots with the `can_forge_sender` permission can send messages that appear to have been sent by
@ -203,7 +203,7 @@ strength allowed is controlled by two settings in
- Zulip supports user-uploaded files. Ideally they should be hosted
from a separate domain from the main Zulip server to protect against
various same-domain attacks (e.g. zulip-user-content.example.com).
various same-domain attacks (e.g., zulip-user-content.example.com).
We support two ways of hosting them: the basic `LOCAL_UPLOADS_DIR`
file storage backend, where they are stored in a directory on the
@ -221,7 +221,7 @@ strength allowed is controlled by two settings in
instead of the URL, so this is arguably pretty good protection.)
However, to help protect against accidental sharing of URLs to
restricted files (e.g. by forwarding a missed-message email or leaks
restricted files (e.g., by forwarding a missed-message email or leaks
involving the Referer header), every access to an uploaded file has
access control verified (confirming that the browser is logged into
a Zulip account that has received the uploaded file in question).

View File

@ -142,7 +142,7 @@ processes to use][supervisor-minfds]; defaults to 40000. If your Zulip deploymen
is very large (hundreds of thousands of concurrent users), your Django processes
hit this limit and refuse connections to clients. Raising it above this default
may require changing system-level limits, particularly if you are using a
virtualized environment (e.g. Docker, or Proxmox LXC).
virtualized environment (e.g., Docker, or Proxmox LXC).
[supervisor-minfds]: http://supervisord.org/configuration.html?highlight=minfds#supervisord-section-values

View File

@ -87,11 +87,11 @@ that version of Zulip.
Branches with names like `2.1.x` are stable release branches,
containing the changes planned for the next minor release
(E.g. 2.1.5); we support these stable release branches as though they
(e.g., 2.1.5); we support these stable release branches as though they
were a published release.
The `main` branch contains changes planned for the next major
release (E.g. 3.0); see our documentation on [running
release (e.g., 3.0); see our documentation on [running
`main`](modify.md#upgrading-to-main) before upgrading to it.
By default, this uses the main upstream Zulip server repository, but
@ -168,7 +168,7 @@ guide](troubleshooting.md).
The upgrade scripts are idempotent, so there's no harm in trying again
after resolving an issue. The most common causes of errors are:
- Networking issues (e.g. your Zulip server doesn't have reliable
- Networking issues (e.g., your Zulip server doesn't have reliable
Internet access or needs a proxy set up). Fix the networking issue
and try again.
- Especially when using `upgrade-zulip-from-git`, systems with the
@ -197,7 +197,7 @@ in any reports.
### Rolling back to a prior version
This rollback process is intended for minor releases (e.g. `2.0.3` to
This rollback process is intended for minor releases (e.g., `2.0.3` to
`2.0.6`); a more complicated process is required to roll back database
migrations before downgrading to an older major release.
@ -229,8 +229,8 @@ code, the upgrade will abort.
The hook is run with the following environment variables set:
- `ZULIP_OLD_VERSION`: The version being upgraded from, which may either be a
release name (e.g. `7.0` or `7.0-beta3`) or the output from `git describe`
(e.g. `7.0-beta3-2-gdc158b18f2`).
release name (e.g., `7.0` or `7.0-beta3`) or the output from `git describe`
(e.g., `7.0-beta3-2-gdc158b18f2`).
- `ZULIP_NEW_VERSION`: The version being upgraded to, in the same format as
`ZULIP_OLD_VERSION`.
@ -258,7 +258,7 @@ hooks included with Zulip.
:::{warning}
If you have modified service configuration files installed by
Zulip (e.g. the nginx configuration), the Zulip upgrade process will
Zulip (e.g., the nginx configuration), the Zulip upgrade process will
overwrite your configuration when it does the `puppet apply`.
:::
@ -292,7 +292,7 @@ and the latter for `server` contexts.
## Upgrading the operating system
When you upgrade the operating system on which Zulip is installed
(E.g. Ubuntu 20.04 Focal to Ubuntu 22.04 Jammy), you need to take
(e.g., Ubuntu 20.04 Focal to Ubuntu 22.04 Jammy), you need to take
some additional steps to update your Zulip installation, documented
below.
@ -314,7 +314,7 @@ instructions for other supported platforms.
```
3. Switch to the root user and upgrade the operating system using the
OS's standard tooling. E.g. for Ubuntu, this means running
OS's standard tooling. E.g., for Ubuntu, this means running
`do-release-upgrade` and following the prompts until it completes
successfully:
@ -367,7 +367,7 @@ instructions for other supported platforms.
```
3. Switch to the root user and upgrade the operating system using the
OS's standard tooling. E.g. for Ubuntu, this means running
OS's standard tooling. E.g., for Ubuntu, this means running
`do-release-upgrade` and following the prompts until it completes
successfully:

View File

@ -33,17 +33,17 @@ backend. To enable this backend, you need to do the following:
1. Set the `S3_AUTH_UPLOADS_BUCKET` and `S3_AVATAR_BUCKET` settings in
`/etc/zulip/settings.py` to be the names of the S3 buckets you
created (e.g. `"exampleinc-zulip-uploads"`).
created (e.g., `"exampleinc-zulip-uploads"`).
1. Comment out the `LOCAL_UPLOADS_DIR` setting in
`/etc/zulip/settings.py` (add a `#` at the start of the line).
1. If you are using a non-AWS block storage provider,
you need to set the `S3_ENDPOINT_URL` setting to your
endpoint url (e.g. `"https://s3.eu-central-1.amazonaws.com"`).
endpoint url (e.g., `"https://s3.eu-central-1.amazonaws.com"`).
For certain AWS regions, you may need to set the `S3_REGION`
setting to your default AWS region's code (e.g. `"eu-central-1"`).
setting to your default AWS region's code (e.g., `"eu-central-1"`).
1. Finally, restart the Zulip server so that your settings changes
take effect

View File

@ -7,7 +7,7 @@ designed around the following goals:
- Minimal impact on scalability and service complexity.
- Well-tested so that we can count on the results being correct.
- Efficient to query so that we can display data in-app (e.g. on the channels
- Efficient to query so that we can display data in-app (e.g., on the channels
page) with minimum impact on the overall performance of those pages.
- Storage size smaller than the size of the main Message/UserMessage
database tables, so that we can store the data in the main PostgreSQL
@ -45,7 +45,7 @@ set of database tables. Each of these tables has the following fields:
an hour (or UTC day) boundary for stats collected at hourly (or daily)
frequency. The time interval is determined by the `CountStat`.
- various "id" fields: Foreign keys into `Realm`, `UserProfile`, `Stream`, or
nothing. E.g. the `RealmCount` table has a foreign key into `Realm`.
nothing. E.g., the `RealmCount` table has a foreign key into `Realm`.
- value: The integer counts. For `"active_users_audit:is_bot:hour"` in the
`RealmCount` table, this is the number of active humans or bots (depending
on subgroup) in a particular realm at a particular `end_time`. For
@ -114,7 +114,7 @@ efficient:
for this, which is why we use raw database queries (which we usually avoid
in Zulip) rather than the ORM.
- Aggregating where possible to avoid unnecessary queries against the
`Message` and `UserMessage` tables. E.g. rather than querying the `Message`
`Message` and `UserMessage` tables. E.g., rather than querying the `Message`
table both to generate sent message counts for each realm and again for
each user, we just query for each user, and then add up the numbers for
the users to get the totals for the realm.
@ -147,10 +147,10 @@ analytics tests, to make sure it stays that way as we refactor.
The system discussed above is designed primarily around the technical
problem of showing useful analytics about things where the raw data is
already stored in the database (e.g. `Message`, `UserMessage`). This is great
already stored in the database (e.g., `Message`, `UserMessage`). This is great
because we can always backfill that data to the beginning of time, but of
course sometimes one wants to do analytics on things that aren't worth
storing every data point for (e.g. activity data, request performance
storing every data point for (e.g., activity data, request performance
statistics, etc.). There is currently a reference implementation of a
`LoggingCountStat` that shows how to handle such a situation.
@ -203,7 +203,7 @@ Tips and tricks:
better in Chrome than in Firefox, though this hasn't been extensively
verified.
- Unless a graph has a ton of data, it is typically better to just redraw it
when something changes (e.g. in the various aggregation click handlers)
when something changes (e.g., in the various aggregation click handlers)
rather than to use retrace or relayout or do other complicated
things. Performance on the `/stats` page is nice but not critical, and we've
run into a lot of small bugs when trying to use Plotly's retrace/relayout.
@ -211,7 +211,7 @@ Tips and tricks:
isn't documented well.
- `'paper'` as a Plotly option refers to the bounding box of the graph (or
something related to that).
- You can't right click and inspect the elements of a Plotly graph (e.g. the
- You can't right click and inspect the elements of a Plotly graph (e.g., the
bars in a bar graph) in your browser, since there is an interaction layer
on top of it. But if you hunt around the document tree you should be able
to find it.

View File

@ -47,7 +47,7 @@ work.
As a side note, the policy of using these accessor functions wherever
possible is a good idea, regardless of caching, because the functions
also generally take care of details you might not think about
(e.g. case-insensitive matching of channel names or email addresses).
(e.g., case-insensitive matching of channel names or email addresses).
It's amazing how slightly tricky logic that's duplicated in several
places invariably ends up buggy in some of those places, and in
aggregate we call these accessor functions hundreds of times in
@ -158,7 +158,7 @@ those keys from the cache (if present).
Maintaining these flush functions requires some care (every time we
add a new cache, we need to look through them), but overall it's a
pretty simple algorithm: If the changed data appears in any form in a
given cache key, that cache key needs to be cleared. E.g. the
given cache key, that cache key needs to be cleared. E.g., the
`active_user_ids_cache_key` cache for a realm needs to be flushed
whenever a new user is created in that realm, or user is
deactivated/reactivated, even though it's just a list of IDs and thus
@ -231,7 +231,7 @@ them in loops (the same applies for database queries!). Instead, one
should use a bulk query. We have a fancy function,
`generate_bulk_cached_fetch`, which is super magical and handles this
for us, with support for a bunch of fancy features like marshalling
data before/after going into the cache (e.g. to compress `message`
data before/after going into the cache (e.g., to compress `message`
objects to minimize data transfer between Django and memcached).
## In-process caching in Django

View File

@ -3,7 +3,7 @@
`zerver.models.Client` is Zulip's analogue of the HTTP User-Agent
header (and is populated from User-Agent). It exists for use in
analytics and other places to provide human-readable summary data
about "which Zulip client" was used for an operation (e.g. was it the
about "which Zulip client" was used for an operation (e.g., was it the
Android app, the desktop app, or a bot?).
In general, it shouldn't be used for anything controlling the behavior

View File

@ -136,7 +136,7 @@ highlighting. The system is largely managed by the code in
versions in a `requirements.txt` file to declare what we're using.
Since we have a few different installation targets, we maintain
several `requirements.txt` format files in the `requirements/`
directory (e.g. `dev.in` for development, `prod.in` for
directory (e.g., `dev.in` for development, `prod.in` for
production, `docs.in` for ReadTheDocs, `common.in` for the vast
majority of packages common to prod and development, etc.). We use
`pip install --no-deps` to ensure we only install the packages we

View File

@ -3,7 +3,7 @@
This page has developer documentation on the Zulip email system. If you're
trying to configure your server to send email, you might be looking for our
guide to [sending outgoing email](../production/email.md). If you're trying to
configure an email integration to receive incoming email (e.g. so that users
configure an email integration to receive incoming email (e.g., so that users
can reply to message notification emails via email), you might be interested in
our instructions for
[setting up an email integration](https://zulip.com/integrations/doc/email).
@ -33,7 +33,7 @@ with only a few things you need to know to get started.
One slightly complicated decision you may have to make when adding an email
is figuring out how to schedule it. There are 3 ways to schedule email.
- Send it immediately, in the current Django process, e.g. by calling
- Send it immediately, in the current Django process, e.g., by calling
`send_email` directly. An example of this is the `confirm_registration`
email.
- Add it to a queue. An example is the `invitation` email.
@ -56,7 +56,7 @@ custom backend, `EmailLogBackEnd`. It does the following:
- Logs any sent emails to `var/log/email_content.log`. This log is
displayed by the `/emails` endpoint
(e.g. http://zulip.zulipdev.com:9991/emails).
(e.g., http://zulip.zulipdev.com:9991/emails).
- Print a friendly message on console advertising `/emails` to make
this nice and discoverable.
@ -157,7 +157,7 @@ are multiple copies or they contain CSS colors, you did it wrong.
A final note for translating emails is that strings that are sent to
user accounts (where we know the user's language) are higher-priority
to translate than things sent to an email address (where we don't).
E.g. for password reset emails, it makes sense for the code path for
E.g., for password reset emails, it makes sense for the code path for
people with an actual account can be tagged for translation, while the
code path for the "you don't have an account email" might not be,
since we might not know what language to use in the second case.

View File

@ -64,15 +64,15 @@ to be consumed by the delivery system.
Usually, this list of users is one of 3 things:
- A single user (e.g. for user-level settings changes).
- Everyone in the realm (e.g. for organization-level settings changes,
- A single user (e.g., for user-level settings changes).
- Everyone in the realm (e.g., for organization-level settings changes,
like new realm emoji).
- Everyone who would receive a given message (for messages, emoji
reactions, message editing, etc.); i.e. the subscribers to a channel
or the people on a direct message thread.
It is the responsibility of the caller of `send_event` to choose the
list of user IDs correctly. There can be security problems if e.g. an
list of user IDs correctly. There can be security problems if e.g., an
event containing direct message content is sent to the entire
organization. However, if an event isn't sent to enough clients,
there will likely be user-visible real-time sync bugs.
@ -175,7 +175,7 @@ anyway).
When a client starts up, it usually wants to get 2 things from the
server:
- The "current state" of various pieces of data, e.g. the current
- The "current state" of various pieces of data, e.g., the current
settings, set of users in the organization (for typeahead), channel,
messages, etc. (aka the "initial state").
- A subscription to receive updates to those data when they are
@ -212,7 +212,7 @@ request; the logic is in `zerver/views/events_register.py` and
that had been added to the Tornado event queue since it
was created.
- Finally, Django "applies" the events (see the `apply_events`
function) to the initial state that it fetched. E.g. for a name
function) to the initial state that it fetched. E.g., for a name
change event, it finds the user data in the `realm_user` data
structure, and updates it to have the new name.
@ -266,7 +266,7 @@ action and then fetching a fresh copy of the state.
In particular, `verify_action` does the following:
- Call `fetch_initial_state_data` to get the current state.
- Call the action function (e.g. `do_add_default_stream`).
- Call the action function (e.g., `do_add_default_stream`).
- Capture the events generated by the action function.
- Check the events generated are documented in the [OpenAPI
schema](../documentation/api.md) defined in
@ -421,7 +421,7 @@ to make sure we handle backwards-compatibility properly.
`GET /events` API documentation. It's also a good idea to and open
issues with the mobile and terminal projects to notify them.
- If we're making changes that could confuse existing client app logic
that parses events (E.g. changing the type/meaning of an existing
that parses events (e.g., changing the type/meaning of an existing
field, or removing a field), we need to be very careful, since Zulip
supports old clients connecting to a modern server. See our
[release lifecycle](../overview/release-lifecycle.md) documentation
@ -441,14 +441,14 @@ to make sure we handle backwards-compatibility properly.
format, or Tornado may crash when upgrading past the relevant
commit. We attempt to contain that sort of logic in the `from_dict`
function (which is used for changing event queue formats) and
`client_capabilities` conditionals (E.g. in
`client_capabilities` conditionals (e.g., in
`process_deletion_event`). Compatibility code not related to a
`client_capabilities` entry should be marked with a
`# TODO/compatibility: ...` comment noting when it can be safely deleted;
we grep for these comments entries during major releases.
- Schema changes are a sensitive operation, and like with database
schema changes, it's critical to do thoughtful manual testing.
E.g. run the mobile app against your test server and verify it
E.g., run the mobile app against your test server and verify it
handles the new event properly, or arrange for your new Tornado code
to actually process a pre-upgrade event and verify via the browser
console what came out.

View File

@ -30,9 +30,9 @@ different flows:
- The user uses the "back" button in their browser (basically
equivalent to the previous one, as a _link_ out of the browser history
will be visited).
- The user clicking some in-app click handler (e.g. "Channel settings"
- The user clicking some in-app click handler (e.g., "Channel settings"
for an individual channel), that potentially does
several UI-manipulating things including e.g. loading the channels
several UI-manipulating things including e.g., loading the channels
overlay, and needs to update the hash without re-triggering the open
animation (etc.).
- Within an overlay like the channels overlay, the user clicks to
@ -45,7 +45,7 @@ different flows:
- A server-initiated browser reload (done after a new version is
deployed, or when a user comes back after being idle for a while,
see [notes below][self-server-reloads]), where we try to preserve
extra state (e.g. content of compose box, scroll position within a
extra state (e.g., content of compose box, scroll position within a
narrow) using the `/#reload` hash prefix.
When making changes to the hashchange system, it is **essential** to
@ -65,7 +65,7 @@ The main external API lives in `web/src/browser_history.js`:
Internally you have these functions:
- `hashchange.hashchanged` is the function used to handle the hash,
whether it's changed by the browser (e.g. by clicking on a link to
whether it's changed by the browser (e.g., by clicking on a link to
a hash or using the back button) or triggered internally.
- `hashchange.do_hashchange_normal` handles most cases, like loading the main
page (but maybe with a specific URL if you are narrowed to a

View File

@ -83,8 +83,8 @@ with its corresponding CSS selector as `.my-multiword-class`.
When changing any part of the Zulip CSS, it's important to check that
the new CSS looks good at a wide range of screen widths, from very
wide screen (e.g. 1920px) all the way down to narrow phone screens
(e.g. 480px).
wide screen (e.g., 1920px) all the way down to narrow phone screens
(e.g., 480px).
For complex changes, it's definitely worth testing in a few different
browsers to make sure things look the same.
@ -228,9 +228,9 @@ needs to be accessible from one of the entry points defined either in
`web/src/bundles/common.ts` which itself is imported to the
`app` and `common` bundles.
- If it's just used on a single standalone page which is only used in
a development environment (e.g. `/devlogin`) create a new entry
a development environment (e.g., `/devlogin`) create a new entry
point in `web/webpack.dev-assets.json` or it's used in both
production and development (e.g. `/stats`) create a new entry point
production and development (e.g., `/stats`) create a new entry point
in `web/webpack.assets.json`. Use the `bundle` macro (defined in
`templates/zerver/base.html`) in the relevant Jinja2 template to
inject the compiled JS and CSS.
@ -246,10 +246,10 @@ A few useful notes are:
`/home/zulip/prod-static`. When a new version is deployed, before the
server is restarted, files are copied into that directory.
- We use the VFL (versioned file layout) strategy, where each file in
the codebase (e.g. `favicon.ico`) gets a new name
(e.g. `favicon.c55d45ae8c58.ico`) that contains a hash in it. Each
the codebase (e.g., `favicon.ico`) gets a new name
(e.g., `favicon.c55d45ae8c58.ico`) that contains a hash in it. Each
deployment, has a manifest file
(e.g. `/home/zulip/deployments/current/staticfiles.json`) that maps
(e.g., `/home/zulip/deployments/current/staticfiles.json`) that maps
codebase filenames to serving filenames for that deployment. The
benefit of this VFL approach is that all the static files for past
deployments can coexist, which in turn eliminates most classes of
@ -257,7 +257,7 @@ A few useful notes are:
deployment can't find their static assets. It also is necessary for
any incremental rollout strategy where different clients get
different versions of the site.
- Some paths for files (e.g. emoji) are stored in the
- Some paths for files (e.g., emoji) are stored in the
`rendered_content` of past messages, and thus cannot be removed
without breaking the rendering of old messages (or doing a
mass-rerender of old messages).

View File

@ -111,7 +111,7 @@ The format of this output is:
- HTTP method
- HTTP status code
- Time to process
- (Optional perf data details, e.g. database time/queries, memcached
- (Optional perf data details, e.g., database time/queries, memcached
time/queries, Django process startup time, Markdown processing time,
etc.)
- Endpoint/URL from zproject/urls.py
@ -200,7 +200,7 @@ Blueslip supports several error levels:
than returning execution to the caller.
- `blueslip.error`: For logging of events that are definitely caused by a bug
and thus sufficiently important to be reported, but where we can handle the
error without creating major user-facing problems (e.g. an exception when
error without creating major user-facing problems (e.g., an exception when
handling a presence update).
- `blueslip.warn`: For logging of events that are a problem but not important
enough to log an error to Sentry in production. They are, however, highlighted
@ -208,7 +208,7 @@ Blueslip supports several error levels:
production.
- `blueslip.log` (and `blueslip.info`): Logged to the JS console in development
and also in the Sentry breadcrumb log in production. Useful for data that
might help discern what state the browser was in during an error (e.g. whether
might help discern what state the browser was in during an error (e.g., whether
the user was in a narrow).
- `blueslip.debug`: Similar to `blueslip.log`, but are not printed to
the JS console in development.

View File

@ -13,22 +13,22 @@ While Zulip takes advantage of built-in Django management commands for
things like managing Django migrations, we also have dozens that we've
written for a range of purposes:
- Cron jobs to do regular updates, e.g. `update_analytics_counts.py`,
- Cron jobs to do regular updates, e.g., `update_analytics_counts.py`,
`sync_ldap_user_data`, etc.
- Useful parts of provisioning or upgrading a Zulip development
environment or server, e.g. `makemessages`, `compilemessages`,
environment or server, e.g., `makemessages`, `compilemessages`,
`populate_db`, `fill_memcached_caches`, etc.
- The actual scripts run by supervisord to run the persistent
processes in a Zulip server, e.g. `runtornado` and `process_queue`.
processes in a Zulip server, e.g., `runtornado` and `process_queue`.
- For a sysadmin to verify a Zulip server's configuration during
installation, e.g. `checkconfig`, `send_test_email`.
installation, e.g., `checkconfig`, `send_test_email`.
- As the interface for doing those rare operations that don't have a
UI yet, e.g. `deactivate_realm`, `reactivate_realm`,
UI yet, e.g., `deactivate_realm`, `reactivate_realm`,
`change_user_email` (for the case where the user doesn't control the
old email address).
- For a sysadmin to easily interact with and script common possible
changes they might want to make to the database on a Zulip server.
E.g. `send_password_reset_email`, `export`, `purge_queue`.
E.g., `send_password_reset_email`, `export`, `purge_queue`.
## Writing management commands

View File

@ -147,10 +147,10 @@ object and other arguments passed into `do_convert` (`sent_by_bot`,
`translate_emoticons`, `mention_data`, etc.). Because
Python-Markdown doesn't support directly passing arguments into the
Markdown processor, our logic attaches these data to the Markdown
processor object via e.g. `_md_engine.zulip_db_data`, and then
processor object via e.g., `_md_engine.zulip_db_data`, and then
individual Markdown rules can access the data from there.
For non-message contexts (e.g. an organization's profile (aka the
For non-message contexts (e.g., an organization's profile (aka the
thing on the right-hand side of the login page), channel descriptions,
or rendering custom profile fields), one needs to just pass in a
`message_realm` (see, for example, `zulip_default_context` for the
@ -166,7 +166,7 @@ Markdown, not newer Markdown variants like CommonMark.
Markdown is great for group chat for the same reason it's been
successful in products ranging from blogs to wikis to bug trackers:
it's close enough to how people try to express themselves when writing
plain text (e.g. emails) that it helps more than getting in the way.
plain text (e.g., emails) that it helps more than getting in the way.
The main issue for using Markdown in instant messaging is that the
Markdown standard syntax used in a lot of wikis/blogs has nontrivial
@ -212,7 +212,7 @@ accurate.
- Allow only `*` syntax for italics, not `_`. This resolves an issue where
people were using `_` and hitting it by mistake too often. Asterisks
surrounded by spaces won't trigger italics, either (e.g. with stock Markdown
surrounded by spaces won't trigger italics, either (e.g., with stock Markdown
`You should use char * instead of void * there` would produce undesired
results).

View File

@ -28,7 +28,7 @@ as follows:
- `do_send_messages` is the synchronous message-sending code path,
and passing the following data in its `send_event` call:
- Data about the message's content (E.g. mentions, wildcard
- Data about the message's content (e.g., mentions, wildcard
mentions, and alert words) and encodes it into the `UserMessage`
table's `flags` structure, which is in turn passed into
`send_event` for each user receiving the message.
@ -72,7 +72,7 @@ as follows:
`receiver_is_off_zulip` returns `True`, which checks whether the user has any
current events system clients registered to receive `message`
events. This check is done immediately (handling soft disconnects,
where E.g. the user closes their last Zulip tab and we get the
where e.g., the user closes their last Zulip tab and we get the
`DELETE /events/{queue_id}` request).
- The `receiver_is_off_zulip` check is effectively repeated when
event queues are garbage-collected (in `missedmessage_hook`) by
@ -89,7 +89,7 @@ as follows:
notifications in cases like a mention added during message
editing.
- The notification sending logic for message edits
inside Tornado has extensive automated test suites; e.g.
inside Tornado has extensive automated test suites; e.g.,
`test_message_edit_notifications.py` covers all the cases around
editing a message to add/remove a mention.
- We may in the future want to add some sort of system for letting

View File

@ -4,7 +4,7 @@ When you're using Zulip and you reload, or narrow to a channel, how
does Zulip decide where to place you?
Conceptually, Zulip takes you to the place where you left off
(e.g. the first unread message), not the most recent messages, to
(e.g., the first unread message), not the most recent messages, to
facilitate reviewing all the discussions that happened while you were
away from your computer. The scroll position is then set to keep that
message in view and away from both the top and bottom of the visible
@ -53,7 +53,7 @@ channels.)
### Unnarrow: previous sequence
When you unnarrow using e.g. the `a` key, you will automatically be
When you unnarrow using e.g., the `a` key, you will automatically be
taken to the same message that was selected in the Combined feed view before
you narrowed, unless in the narrow you read new messages, in which
case you will be jumped forward to the first unread and non-muted

View File

@ -13,7 +13,7 @@ scalability problems for a team chat tool like Zulip.
There's a lot of performance-related details in the backend and
network protocol design that we won't get into here. The focus of
this is what one needs to know to correctly implement a Zulip client's
presence implementation (e.g. web app, mobile app, terminal client, or
presence implementation (e.g., web app, mobile app, terminal client, or
other tool that's intended to represent whether a user is online and
using Zulip).
@ -36,7 +36,7 @@ about that data structure:
- It's really important that the timestamp is the last time we heard
from the client. A client can only interpret the status to display
about another user by doing a simple computation using the (status,
timestamp) pair. E.g. a user who last used Zulip 1 week ago will
timestamp) pair. E.g., a user who last used Zulip 1 week ago will
have a timestamp of 1 week ago and a status of "active". Why?
Because this correctly handles the race conditions. For example, if
the threshold for displaying a user as "offline" was 5 minutes
@ -50,7 +50,7 @@ about that data structure:
- The `status_from_timestamp` function in `web/src/presence.js` is
useful sample code; the `OFFLINE_THRESHOLD_SECS` check is critical
to correct output.
- We provide the data for e.g. whether the user was online on their
- We provide the data for e.g., whether the user was online on their
desktop or the mobile app, but for a basic client, you will likely
only want to parse the "aggregated" key, which shows the summary
answer for "is this user online".

View File

@ -5,11 +5,11 @@ used for a variety of purposes:
- Asynchronously doing expensive operations like sending email
notifications which can take seconds per email and thus would
otherwise time out when 100s are triggered at once (E.g. inviting a
otherwise time out when 100s are triggered at once (e.g., inviting a
lot of new users to a realm).
- Asynchronously doing non-time-critical somewhat expensive operations
like updating analytics tables (e.g. UserActivityInternal) which
like updating analytics tables (e.g., UserActivityInternal) which
don't have any immediate runtime effect.
- Communicating events to push to clients (browsers, etc.) from the
@ -40,7 +40,7 @@ To add a new queue processor:
processor. This suffices to test your queue worker in the Zulip development
environment (`tools/run-dev` will automatically restart the queue processors
and start running your new queue processor code). You can also run a single
queue processor manually using e.g. `./manage.py process_queue --queue=user_activity`.
queue processor manually using e.g., `./manage.py process_queue --queue=user_activity`.
- So that supervisord will know to run the queue processor in
production, you will need to add to the `queues` variable in

View File

@ -92,5 +92,5 @@ lookup should still work even if you disable proxy for
127.0.0.1 testsubdomain.zulipdev.com
```
These records are also useful if you want to e.g. run the Puppeteer tests
These records are also useful if you want to e.g., run the Puppeteer tests
when you are not connected to the Internet.

View File

@ -5,12 +5,12 @@ preparing a new release.
### A week before the release
- _Major releases only (e.g. 4.0):_
- _Major releases only (e.g., 4.0):_
- Upgrade all Python dependencies in
`requirements` to latest upstream versions so they can burn in (use
`pip list --outdated`).
- Upgrade all puppet dependencies in `puppet/deps.yaml`
- Upgrade all puppet-installed dependencies (e.g. Smokescreen, go,
- Upgrade all puppet-installed dependencies (e.g., Smokescreen, go,
etc) in `puppet/zulip/manifests/common.pp`
- [Upload strings to
Transifex](../translating/internationalization.md#translation-process)
@ -49,7 +49,7 @@ preparing a new release.
- If the draft post should remain secret until release, avoid using
a guessable Git branch name for the pull request (the deployment
preview URL is based on the branch name).
- _Major releases only (e.g. 4.0):_ Schedule team members to provide
- _Major releases only (e.g., 4.0):_ Schedule team members to provide
extra responsive #production help support following the release.
### Executing the release
@ -94,12 +94,12 @@ preparing a new release.
once it is built, and how to test it. Verify it, then publish it to
DigitalOcean marketplace.
- _Major releases only:_
- Create a release branch (e.g. `4.x`).
- Create a release branch (e.g., `4.x`).
- On the release branch, update `ZULIP_VERSION` in `version.py` to
the present release with a `+git` suffix, e.g. `4.0+git`.
the present release with a `+git` suffix, e.g., `4.0+git`.
- On `main`, update `ZULIP_VERSION` to the future major release with
a `-dev+git` suffix, e.g. `5.0-dev+git`. Make a Git tag for this
update commit with a `-dev` suffix, e.g. `5.0-dev`. Push the tag
a `-dev+git` suffix, e.g., `5.0-dev+git`. Make a Git tag for this
update commit with a `-dev` suffix, e.g., `5.0-dev`. Push the tag
to both zulip.git and zulip-internal.git to get a correct version
number for future Cloud deployments.
- Add the new release to `.github/ISSUE_TEMPLATE/2_bug_report.md`.
@ -113,16 +113,16 @@ preparing a new release.
- Add a new line to the `production_upgrade` matrix in
`.github/workflows/production-suite.yml`.
- Update /history page in `templates/corporate/history.md`.
- _Minor releases only (e.g. 3.2):_
- _Minor releases only (e.g., 3.2):_
- On the release branch, update `ZULIP_VERSION` to the present
release with a `+git` suffix, e.g. `3.2+git`.
release with a `+git` suffix, e.g., `3.2+git`.
- On main, update `LATEST_RELEASE_VERSION` with the released
version, as well as the changelog changes from the release branch.
- _Prereleases only (e.g. 7.0-beta3):_
- Atop the prerelease commit (e.g. `7.0-beta3`), make a commit
- _Prereleases only (e.g., 7.0-beta3):_
- Atop the prerelease commit (e.g., `7.0-beta3`), make a commit
updating `ZULIP_VERSION` to the prerelease version with a `+git`
suffix, e.g. `7.0-beta3+git`. Push this to `main`. (If `main` has
suffix, e.g., `7.0-beta3+git`. Push this to `main`. (If `main` has
already diverged from the prerelease, a merge commit will be
needed here.)
- Delete the prerelease branch (e.g. `7.0-beta3-branch`); it's now
- Delete the prerelease branch (e.g., `7.0-beta3-branch`); it's now
an ancestor of `main` and thus unnecessary.

View File

@ -49,7 +49,7 @@ migrations.
migration that exists on the release branch. This should be
followed, on `main`, by a migration which merges the two resulting
tips; you can make such a merge with `manage.py makemigrations --merge`.
- **Large tables**: For our very largest tables (e.g. Message and
- **Large tables**: For our very largest tables (e.g., Message and
UserMessage), we often need to take precautions when adding columns
to the table, performing data backfills, or building indexes. We
have a `zerver/lib/migrate.py` library to help with adding columns
@ -63,7 +63,7 @@ migrations.
- **Atomicity**. By default, each Django migration is run atomically
inside a transaction. This can be problematic if one wants to do
something in a migration that touches a lot of data and would best
be done in batches of e.g. 1000 objects (e.g. a `Message` or
be done in batches of e.g., 1000 objects (e.g., a `Message` or
`UserMessage` table change). There is a [useful Django
feature][migrations-non-atomic] that makes it possible to add
`atomic=False` at the top of a `Migration` class and thus not have
@ -130,7 +130,7 @@ migrations.
to do lots of small batches, potentially with a brief sleep in
between, so that we don't block other operations from finishing.
- **Rerunnability/idempotency**. Good migrations are ones where if
operational concerns (e.g. it taking down the Zulip server for
operational concerns (e.g., it taking down the Zulip server for
users) interfere with it finishing, it's easy to restart the
migration without doing a bunch of hand investigation. Ideally,
the migration can even continue where it left off, without needing
@ -144,7 +144,7 @@ migrations.
2. Second, do a migration to copy values from the old column to
the new column, to ensure that the two data stores agree.
3. Third, a commit that stops writing to the old field.
4. Any cleanup work, e.g. if the old field were a column, we'd do
4. Any cleanup work, e.g., if the old field were a column, we'd do
a migration to remove it entirely here.
This multi-step process is how most migrations on large database

View File

@ -22,7 +22,7 @@ There are 3 related structures:
IDs go in what order.
- A `message_list` is built on top of `message_list_data` and
additionally contains the data for a visible-to-the-user message list
(E.g. where trailing bookends should appear, a selected message,
(e.g., where trailing bookends should appear, a selected message,
etc.).
- A `message_list_view` is built on top of `message_list` and
additionally contains rendering details like a window of up to 400
@ -37,7 +37,7 @@ and narrowing).
The compose box does a lot of fancy things that are out of scope for
this article. But it also does a decent amount of client-side
validation before sending a message off to the server, especially
around mentions (E.g. checking the channel name is a valid channel,
around mentions (e.g., checking the channel name is a valid channel,
displaying a warning about the number of recipients before a user can
use `@**all**` or mention a user who is not subscribed to the current
channel, etc.).
@ -62,12 +62,12 @@ This section details the ways in which it is different:
[queue](queuing.md) to actually send the message.
See `maybe_enqueue_notifications` and `zerver/lib/notification_data.py` for
this part of the logic.
- Splicing user-dependent data (E.g. `flags` such as when the user
- Splicing user-dependent data (e.g., `flags` such as when the user
was `mentioned`) into the events.
- Handling the [local echo details](#local-echo).
- Handling certain client configuration options that affect
messages. E.g. determining whether to send the
plaintext/Markdown raw content or the rendered HTML (e.g. the
messages. E.g., determining whether to send the
plaintext/Markdown raw content or the rendered HTML (e.g., the
`apply_markdown` and `client_gravatar` features in our
[events API docs](https://zulip.com/api/register-queue)).
- Following our standard naming convention, input validation is done
@ -94,7 +94,7 @@ This section details the ways in which it is different:
step adds a lot of complexity, because the events system cannot
make queries to the database directly.
- Trigger any other deferred work caused by the current message,
e.g. [outgoing webhooks](https://zulip.com/api/outgoing-webhooks)
e.g., [outgoing webhooks](https://zulip.com/api/outgoing-webhooks)
or embedded bots.
- Every query is designed to be a bulk query; we carefully
unit-test this system for how many database and memcached queries
@ -146,7 +146,7 @@ messages.
is passed two special parameters that clients not implementing local
echo don't use: `queue_id` and `local_id`. The `queue_id` is the ID
of the client's event queue; here, it is used just as a unique
identifier for the specific client (e.g. a browser tab) that sent
identifier for the specific client (e.g., a browser tab) that sent
the message. And the `local_id` is, by the construction above, a
unique value within that namespace identifying the message.
- The `do_send_messages` backend code path includes the `queue_id` and

View File

@ -29,7 +29,7 @@ Zulip uses the [Django settings
system](https://docs.djangoproject.com/en/5.0/topics/settings/), which
means that the settings files are Python programs that set a lot of
variables with all-capital names like `EMAIL_GATEWAY_PATTERN`. You can
access these anywhere in the Zulip Django code using e.g.:
access these anywhere in the Zulip Django code using e.g.,:
```python
from django.conf import settings
@ -37,7 +37,7 @@ print(settings.EMAIL_GATEWAY_PATTERN)
```
Additionally, if you need to access a Django setting in a shell
script (or just on the command line for debugging), you can use e.g.:
script (or just on the command line for debugging), you can use e.g.,:
```console
$ ./scripts/get-django-setting EMAIL_GATEWAY_PATTERN
@ -55,7 +55,7 @@ In a production environment, we have:
administrator-facing settings file for Zulip. It contains all the
server-specific settings, such as how to send outgoing email, the
hostname of the PostgreSQL database, etc., but does not contain any
secrets (e.g. passwords, secret API keys, cryptographic keys, etc.).
secrets (e.g., passwords, secret API keys, cryptographic keys, etc.).
The way we generally do settings that can be controlled with shell
access to a Zulip server is to put a default in
`zproject/default_settings.py`, and then override it here. As this
@ -91,7 +91,7 @@ In a production environment, we have:
- `zproject/computed_settings.py` contains all the settings that are
constant for all Zulip installations or computed as a function of
`zproject/configured_settings.py` (e.g. configuration for logging,
`zproject/configured_settings.py` (e.g., configuration for logging,
static assets, middleware, etc.).
In a development environment, we have `zproject/settings.py`, and
@ -106,7 +106,7 @@ additionally:
features like [authentication
options](../development/authentication.md) that require secrets to
work. It is also used to set certain settings that in production
belong in `/etc/zulip/settings.py`, e.g. `SOCIAL_AUTH_GITHUB_KEY`.
belong in `/etc/zulip/settings.py`, e.g., `SOCIAL_AUTH_GITHUB_KEY`.
You can see a full list with `git grep development_only=True`, or
add additional settings of this form if needed.
@ -152,11 +152,11 @@ want those settings.
### Testing non-default settings
You can write tests for settings using e.g.
You can write tests for settings using e.g.,
`with self.settings(TERMS_OF_SERVICE=None)`. However, this only works
for settings which are checked at runtime, not settings which are only
accessed in initialization of Django (or Zulip) internals
(e.g. `DATABASES`). See the [Django docs on overriding settings in
(e.g., `DATABASES`). See the [Django docs on overriding settings in
tests][django-test-settings] for more details.
[django-test-settings]: https://docs.djangoproject.com/en/5.0/topics/testing/tools/#overriding-settings

View File

@ -172,7 +172,7 @@ is the extent of our checking.
Finally, we're checking line length in Python code (and hope to extend
this to other parts of the codebase soon). You can use
`#ignorelinelength` for special cases where a very long line makes
sense (e.g. a link in a comment to an extremely long URL).
sense (e.g., a link in a comment to an extremely long URL).
#### Python code

View File

@ -160,7 +160,7 @@ So, to summarize our approach to integration vs. unit testing:
HTTP response and the internal state of the server following the request
are both correct.
- Following the end-to-end principle in system design, where possible
we write tests that execute a complete flow (e.g. registering a new
we write tests that execute a complete flow (e.g., registering a new
Zulip account) rather than testing the implementations of individual
functions.
- We invest in the performance of Zulip in part to give users a great
@ -214,7 +214,7 @@ test conditions.
The benefit of this strategy is that you guarantee that the test setup
only differs as intended: Done well, it helps avoid the otherwise
extremely common failure mode where a `test_foo_failure` test passes
for the wrong reason. (E.g. the action fails not because of the
for the wrong reason. (e.g., the action fails not because of the
permission check, but because a required HTTP parameter was only added
to an adjacent `test_foo_success`).

View File

@ -121,7 +121,7 @@ Here are some example action methods that tests may use for data setup:
### Testing code that accesses the filesystem
Some tests need to access the filesystem (e.g. `test_upload.py` tests
Some tests need to access the filesystem (e.g., `test_upload.py` tests
for `LocalUploadBackend` and the data import tests). Doing
this correctly requires care to avoid problems like:
@ -142,7 +142,7 @@ To avoid these problems, you can do the following:
avoid conflicts with other tests run later by the same test process.
Our common testing infrastructure handles some of this for you,
e.g. it replaces `settings.LOCAL_UPLOADS_DIR` for each test process
e.g., it replaces `settings.LOCAL_UPLOADS_DIR` for each test process
with a unique path under `/var/<uuid>/test-backend`. And
`UploadSerializeMixin` manages some of the cleanup work for
`test_upload.py`.
@ -252,7 +252,7 @@ foo.qux = 42
```
is _not_ going to throw any errors. Our mock silently accepts all these calls and records them.
`Mock` also implements methods for us to access and assert its records, e.g.
`Mock` also implements methods for us to access and assert its records, e.g.,
```python
foo.bar.assert_called_with('quux')

View File

@ -274,7 +274,7 @@ These instructions assume you're using the Vagrant development environment.
1. In the `Configure Node.js Remote Interpreter`, window select `Vagrant`
1. Wait for WebStorm to connect to Vagrant. This will be displayed
by the `Vagrant Host URL` section updating to contain the Vagrant
SSH URL, e.g. `ssh://vagrant@127.0.0.1:2222`.
SSH URL, e.g., `ssh://vagrant@127.0.0.1:2222`.
1. **Set the `Node.js interpreter path` to `/usr/local/bin/node`**
1. Hit `OK` 2 times to get back to the `Run/Debug Configurations` window.
1. Under `Working Directory` select the root `zulip` directory.
@ -288,7 +288,7 @@ Congratulations! You've now set up the integration.
To use Webstorm to debug a given node test file, do the following:
1. Under `Application parameters` choose the node test file that you
are trying to test (e.g. `web/tests/message_store.test.js`).
are trying to test (e.g., `web/tests/message_store.test.js`).
1. Under `Path Mappings`, set `Project Root` to `/srv/zulip`
(i.e. where the `zulip` Git repository is mounted in the Vagrant guest).
1. Use the WebStorm debugger; see [this overview][webstorm-debugging]

View File

@ -3,8 +3,8 @@
While our [node test suite](testing-with-node.md) is the
preferred way to test most frontend code because they are easy to
write and maintain, some code is best tested in a real browser, either
because of navigation (E.g. login) or because we want to verify the
interaction between Zulip logic and browser behavior (E.g. copy/paste,
because of navigation (e.g., login) or because we want to verify the
interaction between Zulip logic and browser behavior (e.g., copy/paste,
keyboard shortcuts, etc.).
## Running tests
@ -74,7 +74,7 @@ integration](continuous-integration.md):
affects any of the selectors used in the tests? If so, the test may
just need to be updated for your changes.
- Does the test fail deterministically when you run it locally using
E.g. `./tools/test-js-with-puppeteer compose.ts`? If so, you can
e.g., `./tools/test-js-with-puppeteer compose.ts`? If so, you can
iteratively debug to see the failure.
- Does the test fail nondeterministically? If so, the problem is
likely that a `waitForSelector` statement is either missing or not
@ -141,7 +141,7 @@ notes above:
`main`.
- With black-box browser tests like these, it's very important to write your code
to wait for browser's UI to update before taking any action that
assumes the last step was processed by the browser (E.g. after you
assumes the last step was processed by the browser (e.g., after you
click on a user's avatar, you need an explicit wait for the profile
popover to appear before you can try to click on a menu item in that
popover). This means that before essentially every action in your

View File

@ -40,7 +40,7 @@ typically involve running subsets of the tests with commands like these:
```
The commands above will all run in just a few seconds. Many more
useful options are discussed in each tool's documentation (e.g.
useful options are discussed in each tool's documentation (e.g.,
`./tools/test-backend --help`).
## Major test suites
@ -117,7 +117,7 @@ reasons:
As a result, Zulip's major test suites should never access the
Internet directly. Since code in Zulip does need to access the
Internet (e.g. to access various third-party APIs), this means that
Internet (e.g., to access various third-party APIs), this means that
the Zulip tests use mocking to basically hardcode (for the purposes of
the test) what responses should be used for any outgoing Internet
requests that Zulip would make in the code path being tested.

View File

@ -71,7 +71,7 @@ Our plan is to order which modules we migrate carefully, starting with
those that:
- Appear frequently as reverse dependencies of other modules
(e.g. `people.js`). These are most valuable to do first because
(e.g., `people.js`). These are most valuable to do first because
then we have types on the data being interacted with by other
modules when we migrate those.
- Don't have large open pull requests (to avoid merge conflicts); one
@ -82,11 +82,11 @@ those that:
When migrating a module, we want to be especially thoughtful about
putting together a commit structure that makes mistakes unlikely and
the changes easy to verify. E.g.:
the changes easy to verify. E.g.,:
- First a commit that just converts the language to TypeScript adding
types. The result may potentially have some violations of the
long-term style we want (e.g. not using `const`). Depending on how
long-term style we want (e.g., not using `const`). Depending on how
we're handling linting, we set some override eslint rules at the top
of the module at this stage so CI still passes.
- Then a commit just migrating use of `var` to `const/let` without

View File

@ -30,7 +30,7 @@ Message 可直译为“消息”、“信息”等,两者皆可,这里统一
- Stream - **频道**
There were several other optional translations, e.g. "群组(Group)", "
There were several other optional translations, e.g., "群组(Group)", "
主题(Subject)", and "栏目(Column)". The "频道(Channel)" is in use now,
which is inspired by the chat "Channel" in the game Ingress. Since
"Stream" can be "Created/Deleted" or "Subscribed/Unsubscribed",
@ -96,7 +96,7 @@ The perfect tense subscribed/unsubscribed is translated as "已订阅/已
scope of ...". The two words share the common meanings.
2. "筛选" is a common computer phrase and has been well
accepted by public, e.g. the "Filter(筛选)" feature in Microsoft
accepted by public, e.g., the "Filter(筛选)" feature in Microsoft
Excel.
In addition, in the searching context "Narrow to ..." is not

View File

@ -57,9 +57,9 @@ the reader and remember to capitalize _Du_.
**Prefer imperative over constructions with auxiliary verbs.**
For instructions, try to use the imperative (e.g. _"Gehe auf die Seite"_ -
For instructions, try to use the imperative (e.g., _"Gehe auf die Seite"_ -
_"Go to the page"_) instead of constructions with auxiliary verbs
(e.g. _"Du musst auf die Seite ... gehen"_ - _"You have to go the page ..."_).
(e.g., _"Du musst auf die Seite ... gehen"_ - _"You have to go the page ..."_).
This keeps the phrases short, less stiff and avoids unnecessary addressing
of the reader.
@ -69,14 +69,14 @@ of the reader.
To be consistent with other online platforms, use continuous labels for buttons,
item titles, etc. with verbs in infinitive form,
e.g. _Manage streams_ - _Kanäle verwalten_ instead of _Verwalte Kanäle_.
e.g., _Manage streams_ - _Kanäle verwalten_ instead of _Verwalte Kanäle_.
### Concatenation of words
**Try to avoid it.**
German is famous for its concatenations of nouns
(e.g. _Heizölrückstoßdämpfung_, which means _fuel oil recoil attenuation_).
(e.g., _Heizölrückstoßdämpfung_, which means _fuel oil recoil attenuation_).
For the sake of correct rendering and simplicity, you should try to avoid such
concatenations whenever possible, since they can break the layout of the Zulip
frontend. Try to stick to a maximum length of 20 characters and follow your
@ -99,7 +99,7 @@ so you should not be afraid of using them if they provide an advantage over
the German equivalent. Take the following two examples as a reference:
- Translating _Bot_: Use _Bot_, as a completely accurate German
equivalent **doesn't** exist (e.g. _Roboter_) and the term _Bot_ is not
equivalent **doesn't** exist (e.g., _Roboter_) and the term _Bot_ is not
unknown to German speakers.
### Special characters
@ -133,7 +133,7 @@ Make sure to not walk into such a trap.
- Balance common verbs and nouns with specific IT-related translations
of English terms - this can be tricky, try to check how other resources
were translated (e.g. Gmail, Microsoft websites, Facebook) to decide
were translated (e.g., Gmail, Microsoft websites, Facebook) to decide
what wouldn't sound awkward / rude in German.
- For additional translation information, feel free to check out
@ -152,7 +152,7 @@ _"Nachricht" (Facebook, WhatsApp, Transifex)_
- Direct Message (DM), Direct Messages (DMs) - **Direktnachricht (DM), Direktnachrichten (DMs)**
While we try to avoid concatenating words whenever possible, "Direktnachricht" is used
by many other platforms (e.g. X/Twitter, Slack, Discord).
by many other platforms (e.g., X/Twitter, Slack, Discord).
Use _DM_ with its plural form _DMs_ rather than DN/DNs in line with other services.
_"Direktnachricht" (X/Twitter, Slack)_
@ -272,7 +272,7 @@ _"Deabonnieren" (YouTube, Transifex)_
Transifex has two different translations for "Narrow to" -
"Schränke auf ... ein." and "Begrenze auf ... ." Both sound a bit strange to a
German speaker, since they would expect grammatically correct sentences when
using the imperative (e.g. "Schränke diesen Stream ein auf ... .") Since this
using the imperative (e.g., "Schränke diesen Stream ein auf ... .") Since this
would be too long for many labels, the infinitive "begrenzen auf" is preferable.
"einschränken auf" sounds equally good, but Transifex shows more use cases for
"begrenzen auf".
@ -282,7 +282,7 @@ _"Schränke auf ... ein." (Transifex) "Begrenze auf ... ." (Transifex)_
- Filter - **Filtern**
A direct translation is fine here. Watch out to to use the infinitive instead
of the imperative, e.g. "Nachrichten filtern" instead of "Filtere Nachrichten".
of the imperative, e.g., "Nachrichten filtern" instead of "Filtere Nachrichten".
_"Filtern" (Thunderbird, LinkedIn)_

View File

@ -3,7 +3,7 @@
- Use _आप_ as the second-person pronoun. Don't use तुम or तू.
(See [chat thread](https://chat.zulip.org/#narrow/channel/58-translation/topic/Hindi.20Translation/near/1762384).)
- Imperative, active, and continuous verbs, e.g. _manage streams_ -
- Imperative, active, and continuous verbs, e.g., _manage streams_ -
_चैनल प्रबंधित करें_, not _चैनल प्रबंधन_.
- Warm and friendly phrasing whenever appropriate.
@ -12,7 +12,7 @@
- Balance common verbs and nouns with specific IT-related translations
of English terms - this can be tricky, try to check how other
resources were translated (e.g. Gmail, Microsoft websites, Facebook)
resources were translated (e.g., Gmail, Microsoft websites, Facebook)
to decide what wouldn't sound awkward / rude in Hindi.
Some terms are very tricky to translate, so be sure to communicate

View File

@ -13,7 +13,7 @@ principles are important in how we think about internationalization:
tagged for translation in both [HTML templates](#html-templates) and
code, and our linters attempt to enforce this. There are some
exceptions: we don't tag strings in Zulip's landing pages
(e.g. /features/) and other documentation (e.g. /help/) for
(e.g., /features/) and other documentation (e.g., /help/) for
translation at this time (though we do aim for those pages to be
usable with tools like Google Translate).
- Translating all the strings in Zulip for a language and maintaining
@ -41,12 +41,12 @@ their style guidelines.
There are a few critical details about human language that are important
to understand when implementing an internationalized application:
- **Punctuation** varies between languages (e.g. Japanese doesn't use
- **Punctuation** varies between languages (e.g., Japanese doesn't use
`.`s at the end of sentences). This means that you should always
include end-of-sentence symbols like `.` and `?` inside the
to-be-translated strings, so that translators can correctly
translate the content.
- **Word order** varies between languages (e.g. some languages put
- **Word order** varies between languages (e.g., some languages put
subjects before verbs, others the other way around). This means
that **concatenating translatable strings** produces broken results
(more details with examples are below).
@ -63,7 +63,7 @@ to understand when implementing an internationalized application:
find your string.
There's a lot of other interesting differences that are important for
i18n (e.g. Zulip has a "full name" field rather than "first name" and
i18n (e.g., Zulip has a "full name" field rather than "first name" and
"last name" because different cultures order the surnames and given
names differently), but the above issues are likely to be relevant to
most people working on Zulip.
@ -172,7 +172,7 @@ from django.utils.translation import gettext as _
Zulip expects all the error messages to be translatable as well. To
ensure this, the error message passed to `JsonableError`
should always be a literal string enclosed by `_()`
function, e.g.:
function, e.g.,:
```python
JsonableError(_('English text'))
@ -180,7 +180,7 @@ JsonableError(_('English text'))
If you're declaring a user-facing string at top level or in a class, you need to
use `gettext_lazy` instead, to ensure that the translation happens at
request-processing time when Django knows what language to use, e.g.:
request-processing time when Django knows what language to use, e.g.,:
```python
from zproject.backends import check_password_strength, email_belongs_to_ldap

View File

@ -2,22 +2,22 @@
Use semi-formal Polish for translation, some specifics:
- Informal "you" (_ty_) instead of more formal approaches (e.g. plural
- Informal "you" (_ty_) instead of more formal approaches (e.g., plural
"you" (_wy_), using any formal titles like _Państwo_, _Pan/Pani_).
- Gender-neutral forms of verbs, e.g. _unsubscribed_ - _odsubskrybowano_,
- Gender-neutral forms of verbs, e.g., _unsubscribed_ - _odsubskrybowano_,
not \*odsubskrybowałeś".
- Imperative, active and continuous verbs, e.g. _manage streams_ -
- Imperative, active and continuous verbs, e.g., _manage streams_ -
_zarządzaj kanałami_, not _zarządź kanałami_.
- Not using reflexive _się_, e.g. _log out_ would be simply _wyloguj_,
- Not using reflexive _się_, e.g., _log out_ would be simply _wyloguj_,
not _wyloguj się_.
- Warm and friendly phrasing whenever appropriate.
- No slang or regional phrases that could be unclear or too informal,
e.g. _zajawka_.
e.g., _zajawka_.
- Consistent usage of Zulip-specific terms and common verbs for
actions, even if it means repeating - this is one of the key aspects
@ -30,7 +30,7 @@ Use semi-formal Polish for translation, some specifics:
- Balance common verbs and nouns with specific IT-related translations
of English terms - this can be tricky, try to check how other
resources were translated (e.g. Gmail, Microsoft websites, Facebook)
resources were translated (e.g., Gmail, Microsoft websites, Facebook)
to decide what wouldn't sound awkward in Polish.
Some terms are very tricky to translate, so be sure to communicate
@ -69,7 +69,7 @@ and _dostosowanie do potrzeb klienta_ is too long
example:
You can personalize Zulip in many ways, e.g. by pinning certain streams.
You can personalize Zulip in many ways, e.g., by pinning certain streams.
> Możesz spersonalizować Zulipa na wiele sposobów, np. przypinając niektóre kanały.

View File

@ -3,14 +3,14 @@
Use informal Spanish for translation:
- Informal "you" (_tú_) instead of formal form _usted_. Many top software
companies (e.g. Google) use the informal one, because it's much more common in
companies (e.g., Google) use the informal one, because it's much more common in
the daily language and avoids making translations look like they were written
by machines.
- Imperative, active, and continuous verbs, e.g. _manage streams_ -
- Imperative, active, and continuous verbs, e.g., _manage streams_ -
_gestionar canales_, not _gestión de canales_.
- Not using reflexive _se_ e.g. _log out_ should be _salir_, not _salirse_,
- Not using reflexive _se_ e.g., _log out_ should be _salir_, not _salirse_,
whenever the infinitive form is possible without making the translation
awkward.
@ -20,7 +20,7 @@ Use informal Spanish for translation:
- Balance common verbs and nouns with specific IT-related translations
of English terms - this can be tricky, try to check how other
resources were translated (e.g. Gmail, Microsoft websites, Facebook)
resources were translated (e.g., Gmail, Microsoft websites, Facebook)
to decide what wouldn't sound awkward / rude in Spanish.
- Latest RAE rule ("solo" should

View File

@ -32,7 +32,7 @@ Zulip:
:::{note}
Unless you plan to contribute country-specific translations, do not
select a country-specific language in the **Languages** menu when you sign
up. E.g. use **English (United Kingdom)** if you plan to translate Zulip
up. E.g., use **English (United Kingdom)** if you plan to translate Zulip
into UK English, but select **Russian** rather than **Russian (Russia)** for
general Russian translations.
:::
@ -132,13 +132,13 @@ There are a few ways to see your translations in the Zulip UI:
- If your system has languages configured in your OS/browser, Zulip's
portico (logged-out) pages will automatically use your configured
language. Note that we only tag for translation strings in pages
that individual users need to use (e.g. `/login/`, `/register/`,
that individual users need to use (e.g., `/login/`, `/register/`,
etc.), not marketing pages like `/features/`.
- In case you need to understand how the above interact, Zulip figures
out the language the user requests in a browser using the following
prioritization (mostly copied from the Django docs):
1. It looks for the language code as a URL prefix (e.g. `/de/login/`).
1. It looks for the language code as a URL prefix (e.g., `/de/login/`).
1. It looks for the cookie named 'django_language'. You can set a
different name through the `LANGUAGE_COOKIE_NAME` setting.
1. It looks for the `Accept-Language` HTTP header in the HTTP request
@ -180,7 +180,7 @@ translation:
### Translation style guides
We maintain translation style guides for Zulip, giving guidance on how
Zulip should be translated into specific languages (e.g. what word to
Zulip should be translated into specific languages (e.g., what word to
translate words like "channel" to), with reasoning, so that future
translators can understand and preserve those decisions:
@ -223,6 +223,6 @@ The Zulip test suite enforces these capitalization guidelines in the
web app codebase [in our test
suite](../testing/testing.md#other-test-suites)
(`./tools/check-capitalization`; `tools/lib/capitalization.py` has
some exclude lists, e.g. `IGNORED_PHRASES`).
some exclude lists, e.g., `IGNORED_PHRASES`).
[translation-channel]: https://chat.zulip.org/#narrow/channel/58-translation

View File

@ -3,10 +3,10 @@
Use semi-formal Urdu for translation:
- Formal "you" (_آپ_) instead of informal form _تم_. Many top software
companies (e.g. Google, Facebook, Microsoft) use the formal one, because it's typically
companies (e.g., Google, Facebook, Microsoft) use the formal one, because it's typically
considered rude to use the informal one without an established acquaintance with someone.
- Imperative, active, and continuous verbs, e.g. _manage streams_ -
- Imperative, active, and continuous verbs, e.g., _manage streams_ -
_سٹریمس کی رہنمائ کریں_, not _سٹریمس کی رہنمائ_.
- Warm and friendly phrasing whenever appropriate.
@ -15,7 +15,7 @@ Use semi-formal Urdu for translation:
- Balance common verbs and nouns with specific IT-related translations
of English terms - this can be tricky, try to check how other
resources were translated (e.g. Gmail, Microsoft websites, Facebook)
resources were translated (e.g., Gmail, Microsoft websites, Facebook)
to decide what wouldn't sound awkward/rude in Urdu.
Some terms are very tricky to translate, so be sure to communicate

View File

@ -117,7 +117,7 @@ includes both views that serve HTML (new pages on Zulip) as well as new
API endpoints that serve JSON-formatted data.
**Testing:** At the very least, add a test of your event data flowing
through the system in `test_events.py` and an API test (e.g. for a
through the system in `test_events.py` and an API test (e.g., for a
Realm setting, in `test_realm.py`).
### Frontend changes
@ -506,7 +506,7 @@ framework is `do_set_realm_property_test`, and in `test_realm.py`, it is
`do_test_realm_update_api`.
One still needs to add a test for whether the setting actually
controls the feature it is supposed to control, however (e.g. for this
controls the feature it is supposed to control, however (e.g., for this
example feature, whether sending a message without a topic fails with
the setting enabled).

View File

@ -19,7 +19,7 @@ Linux/macOS environments (Unix shells). You can also use a tool, for example
When searching Google, or Zulip's docs, you'll find commands that begin
with a dollar sign `$` or a dollar sign preceded by some text
(e.g. `(venv)john@laptop:~$`).
(e.g., `(venv)john@laptop:~$`).
This is called the **prompt**, and it's only an indicator that the shell is
awaiting new orders. The prompt can contain useful information, let's look
@ -168,7 +168,7 @@ the shell provides two different separators:
Sometimes you end up with a very long command, that is hard to read and may
be unclear. This is a problem, especially if you want to share that command,
e.g. in a documentation file.
e.g., in a documentation file.
In those cases, you can use a backslash at the end of each line, to inform the
shell "wait, there's more on the next line".
@ -328,7 +328,7 @@ There are many more commands in the shell, besides the ones explained in this
file.
[Here](https://www.git-tower.com/blog/command-line-cheat-sheet/) you can find
a simple yet useful cheatsheet, created by Tower, that could help you
understand and remember what other common commands do (e.g. `ls`).
understand and remember what other common commands do (e.g., `ls`).
## Git

View File

@ -193,7 +193,7 @@ REQ also helps us with request variable validation. For example:
not automatically marshall the input from JSON).
- Since there is no need to JSON-encode strings, usually simply
`my_string=REQ()` is correct. One can pass e.g.
`my_string=REQ()` is correct. One can pass e.g.,
`str_validator=check_string_in(...)` where one wants to run a
validator on the value of a string.
@ -252,7 +252,7 @@ code (i.e. all 400 type errors are thrown there), and the actions code
is responsible for atomically executing the change (this is usually
signalled by having the actions function have a name starting with
`do_`. So in most cases, errors in an actions function will be the
result of an operational problem (e.g. lost connection to the
result of an operational problem (e.g., lost connection to the
database) and lead to a 500 error. If an actions function is
responsible for validation as well, it should have a name starting
with `check_`.