# Context, Theme, and Events

The SDK tells your app where it is rendered (context), keeps it in the host's theme, and notifies it about what happens around it (events):

```tsx
import {
  AppUiProvider,
  useCrowdinContext,
  useCrowdinEvent,
} from "@crowdin/serverless-apps-sdk/react";

function App() {
  return (
    <AppUiProvider>
      <Panel />
    </AppUiProvider>
  );
}

function Panel() {
  const context = useCrowdinContext();
  useCrowdinEvent("language.change", () => {
    // refresh whatever depends on the selected language
  });
  return <p>Project: {context.project?.id}</p>;
}
```

## Context fields

`useCrowdinContext()` (and `getContext()` in the core) return a `CrowdinContext`:

| Field | Type | Description |
|-------|------|-------------|
| `app` | `{ id, type, key }` | The app id, the module type being rendered, and its manifest `key` |
| `user` | `{ locale, timezone, id?, login? }` | The current Crowdin user. `locale`/`timezone` can be `null`; `id` and `login` are present only for an authenticated viewer |
| `project` | `{ id, identifier? }` or `null` | The current project, when the module renders in a project context. `identifier` is present when the host page knows it |
| `organization` | `{ id, domain? }` or `null` | The current organization, when there is one. `domain` is present on Crowdin Enterprise only |
| `isEnterprise` | `boolean` | Whether the host is Crowdin Enterprise |
| `parentOrigin` | `string` or `null` | Origin of the hosting Crowdin page |
| `assetsBaseUrl` | `string` or `null` | Base URL the app's bundle assets are served from |

`user.locale` is a normalized [BCP-47](https://developer.mozilla.org/en-US/docs/Glossary/BCP_47_language_tag) tag (`en-US`, `uk-UA`), so it is safe to pass to `Intl.DateTimeFormat`, `Intl.NumberFormat`, `toLocaleDateString`, and friends.

## Events

`useCrowdinEvent(name, handler)` is fully typed - the payload type follows the event name. The core `events.on(name, handler)` accepts the same events with an untyped payload; cast it with the exported payload types (e.g. `TranslationObject`). These are the host events of the Crowdin Apps platform; the payloads are described in the [supported events reference](https://support.crowdin.com/developer/crowdin-apps-js/#supported-events).

The table lists the events typed in this SDK version. The platform can start emitting new events at any time, and they work on any SDK version right away - both `events.on` and `useCrowdinEvent` accept any event name string.

| Event | Fires when |
|-------|-----------|
| `string.change` | The active source string changes |
| `string.selected` | The string selection changes (multiple selection) |
| `textarea.edited` | The translation textarea content is edited |
| `translation.added` | A translation is suggested |
| `translation.deleted` | A translation is deleted |
| `translation.restored` | A translation is restored |
| `translation.vote` | A translation is voted on |
| `translation.approve` | A translation is approved |
| `translation.disapprove` | A translation approval is revoked |
| `language.change` | The target language changes |
| `file.change` | The active file changes |
| `asset.source.preview` | The asset source preview is shown |
| `asset.suggestion.preview` | An asset suggestion preview is shown |
| `theme.changed` | The host switches between light and dark theme |
| `intersection.changed` | A registered intersection observer reports a change |
| `context.menu.click` | The user activates one of the app's context-menu entries |

## Theme

`AppUiProvider` syncs the host theme: it toggles dark mode and applies Crowdin's CSS variables, so the [`/ui` components](/serverless-apps/building-app/user-interface/) automatically match the Crowdin look.

Inside `AppUiProvider`, the `useTheme()` hook returns the current theme (`{ mode: "light" | "dark" }`) and re-renders when the host switches theme - use it for custom rendering that the CSS variables don't cover.

## Without React

The framework-free core offers the same capabilities without React: `getContext()`, `getTheme()`, `onThemeChange()`, `events.on()`, plus the typed [host actions](/serverless-apps/building-app/host-actions/) such as `editor`, `project`, `profile`, and `modal`.

```ts
import { getContext, events } from "@crowdin/serverless-apps-sdk";

const context = getContext();
events.on("language.change", () => {
  // refresh whatever depends on the selected language
});
```