Skip to content

Announcement

The Announcement module allows your app to show a message to everyone in the organization, in the header alert or on a glossary page. Crowdin requests the announcements each time it renders one of these placements and passes the reader’s context, so your app decides what to show per request.

index.js
import crowdinModule from '@crowdin/app-project-module';
const configuration = {
baseUrl: 'https://123.ngrok.io',
clientId: 'clientId',
clientSecret: 'clientSecret',
name: 'Sample App',
identifier: 'sample-app',
description: 'Sample App description',
port: 8080,
dbFolder: import.meta.dirname,
imagePath: import.meta.dirname + '/logo.png',
announcement: [
{
placement: 'header-alert',
getAnnouncements: async () => [
{
id: 'release-freeze-2024-05',
text: 'Merges are frozen until Monday.',
dismissible: false,
expiresAt: '2024-05-27T08:00:00Z',
actionLabel: 'Release schedule',
actionUrl: 'https://wiki.example.com/release-schedule',
}
]
},
{
placement: 'glossary',
getAnnouncements: async ({ glossaryId }) => [
{
id: 'glossary-guidelines-v3',
text: `Follow the naming rules before adding terms to glossary ${glossaryId}.`,
dismissible: true,
}
]
}
]
};
crowdinModule.createApp(configuration);
ParameterDescriptionAllowed valuesDefault value
keyRaw module key, sent as jwt.module. Required when several modules share one placement. The derived key comes from the placement alone, so reordering the list never changes it.String<identifier>-announcement-<placement>
nameModule name shown in the installation dialog.Stringderived from placement, e.g. Header announcements
placementWhere Crowdin shows this module’s items. Declare one module per placement, because an admin grants the audience per module on install.'header-alert' | 'glossary'
getAnnouncementsAsync callback that returns what to show for the given context.Function
environmentsRestrict the module to crowdin and/or crowdin-enterprise.'crowdin' | 'crowdin-enterprise' or arrayboth

This function is called each time Crowdin renders the declared placement, with the context of the user looking at the page.

  • placement - The placement being rendered: 'header-alert' or 'glossary'.
  • organizationId - Numeric Crowdin organization ID, read from the verified JWT. Safe to key your own storage by.
  • userId - Numeric ID of the user looking at the page. The JWT is cached per organization and module, so it identifies the installing user rather than the viewer — which is why this one arrives in the request body instead. Use it to choose what to show, not to decide who may see it: Crowdin has already authorized the reader before calling.
  • glossaryId - Numeric glossary ID. Only sent for the glossary placement.
  • client - Crowdin API client.
  • context - Context object.

The function should return an array of announcements, most important first. An empty array means nothing to show, which is the normal case rather than an error.

FieldDescriptionRequired
idKeys the reader’s dismiss state. Changed text under a new id shows again to everyone who closed the old one. Up to 255 characters.yes
textPlain text. Crowdin renders no markup; the browser links bare http/https addresses.yes
dismissibleWhether the reader can close it. A non-dismissible announcement stays until it expires.yes
expiresAtISO 8601 timestamp after which Crowdin stops showing it.no
actionLabelLabel of the call-to-action link. Up to 255 characters.only with actionUrl
actionUrlTarget of the call-to-action link. https:// only, up to 2048 characters.only with actionLabel

Omit an optional field you have no value for: null, '' and [] are rejected rather than read as “no value”, and the announcement carrying one is skipped.

Crowdin validates each announcement separately and takes at most 10 per module. An invalid announcement is skipped and the rest still show. If the app fails to answer, Crowdin skips the request silently and the page renders unchanged.

You can register multiple announcement modules in a single app by providing an array. One keyless module per placement is enough, as in the sample above. Two modules on the same placement need an explicit key each, because the derived key comes from the placement alone:

index.js
const configuration = {
// ... other configuration
announcement: [
{
key: 'release-notes',
name: 'Release notes',
placement: 'header-alert',
getAnnouncements: async () => []
},
{
key: 'incidents',
name: 'Incidents',
placement: 'header-alert',
getAnnouncements: async () => []
}
]
};