+ );
+};
diff --git a/examples/vite/src/AppSettings/tabs/EmojiPicker/index.ts b/examples/vite/src/AppSettings/tabs/EmojiPicker/index.ts
new file mode 100644
index 000000000..dc737187a
--- /dev/null
+++ b/examples/vite/src/AppSettings/tabs/EmojiPicker/index.ts
@@ -0,0 +1 @@
+export * from './EmojiPickerTab';
diff --git a/package.json b/package.json
index 6f810565c..54c1701ab 100644
--- a/package.json
+++ b/package.json
@@ -143,7 +143,7 @@
"@breezystack/lamejs": "^1.2.7",
"@commitlint/cli": "^21.0.1",
"@commitlint/config-conventional": "^21.0.1",
- "@emoji-mart/data": "^1.2.1",
+ "@emoji-mart/data": "1.2.1",
"@emoji-mart/react": "^1.1.1",
"@eslint/js": "^9.39.4",
"@semantic-release/changelog": "^6.0.3",
diff --git a/scripts/vendor-emoji-data.mjs b/scripts/vendor-emoji-data.mjs
new file mode 100644
index 000000000..0619c741b
--- /dev/null
+++ b/scripts/vendor-emoji-data.mjs
@@ -0,0 +1,49 @@
+// Regenerates the vendored emoji dataset used by the built-in emoji picker and
+// search index (src/plugins/Emojis/data/emoji-data.json).
+//
+// We vendor a snapshot of @emoji-mart/data's *native* set (no spritesheet) so the
+// SDK ships its own emoji data and does not depend on the unmaintained emoji-mart
+// packages at runtime. @emoji-mart/data stays a pinned devDependency used ONLY by
+// this script.
+//
+// Usage: node scripts/vendor-emoji-data.mjs
+//
+// The dataset is MIT-licensed (Copyright (c) Missive); its license is copied
+// verbatim to src/plugins/Emojis/data/LICENSE.
+
+import { createRequire } from 'node:module';
+import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
+import { dirname, join, resolve } from 'node:path';
+
+// @emoji-mart/data's "main" resolves to sets/15/native.json (its newest set), so
+// pinning 15 matches a bare `import data from '@emoji-mart/data'`.
+const SET = 15;
+
+const require = createRequire(import.meta.url);
+
+const sourcePath = require.resolve(`@emoji-mart/data/sets/${SET}/native.json`);
+const pkgPath = require.resolve('@emoji-mart/data/package.json');
+const pkg = require('@emoji-mart/data/package.json');
+const licensePath = join(dirname(pkgPath), 'LICENSE');
+
+const outDir = resolve(process.cwd(), 'src/plugins/Emojis/data');
+const outDataPath = join(outDir, 'emoji-data.json');
+const outLicensePath = join(outDir, 'LICENSE');
+
+const data = JSON.parse(readFileSync(sourcePath, 'utf8'));
+
+// `sheet` only describes spritesheet geometry (cols/rows); we render native unicode
+// exclusively, so it is dead weight. Everything else (categories, emojis, aliases)
+// is preserved verbatim so mapEmojiMartData and the search index keep working.
+delete data.sheet;
+
+mkdirSync(outDir, { recursive: true });
+writeFileSync(outDataPath, JSON.stringify(data));
+copyFileSync(licensePath, outLicensePath);
+
+const emojiCount = Object.keys(data.emojis).length;
+console.log(
+ `Vendored @emoji-mart/data@${pkg.version} (set ${SET}, native): ` +
+ `${emojiCount} emoji, ${data.categories.length} categories -> ${outDataPath}`,
+);
+console.log(`Copied upstream MIT LICENSE -> ${outLicensePath}`);
diff --git a/src/components/MessageComposer/MessageComposer.tsx b/src/components/MessageComposer/MessageComposer.tsx
index 70888f629..4febe2c20 100644
--- a/src/components/MessageComposer/MessageComposer.tsx
+++ b/src/components/MessageComposer/MessageComposer.tsx
@@ -49,7 +49,7 @@ export type MessageComposerProps = {
audioRecordingConfig?: CustomAudioRecordingConfig;
/** Controls whether the users will be provided with the UI to record voice messages. */
audioRecordingEnabled?: boolean;
- /** Mechanism to be used with autocomplete and text replace features of the `MessageComposer` component, see [emoji-mart `SearchIndex`](https://github.com/missive/emoji-mart#%EF%B8%8F%EF%B8%8F-headless-search) */
+ /** Custom emoji search index for `MessageComposer` autocomplete and emoticon replacement. Optional — the SDK ships a built-in `defaultEmojiSearchIndex` (used by `createTextComposerEmojiMiddleware`); emoji-mart's `SearchIndex` also satisfies this interface. */
emojiSearchIndex?: ComponentContextValue['emojiSearchIndex'];
/** If true, focuses the text input on component mount */
focus?: boolean;
diff --git a/src/context/ComponentContext.tsx b/src/context/ComponentContext.tsx
index ae6c5fb70..c0b3b4632 100644
--- a/src/context/ComponentContext.tsx
+++ b/src/context/ComponentContext.tsx
@@ -139,7 +139,7 @@ export type ComponentContextValue = {
EditedMessagePreview?: React.ComponentType;
/** Custom UI component for rendering button with emoji picker in MessageComposer */
EmojiPicker?: React.ComponentType;
- /** Mechanism to be used with autocomplete and text replace features of the `MessageComposer` component, see [emoji-mart `SearchIndex`](https://github.com/missive/emoji-mart#%EF%B8%8F%EF%B8%8F-headless-search) */
+ /** Custom emoji search index for `MessageComposer` autocomplete and emoticon replacement. Optional — the SDK ships a built-in `defaultEmojiSearchIndex` (used by `createTextComposerEmojiMiddleware`); emoji-mart's `SearchIndex` also satisfies this interface. */
emojiSearchIndex?: EmojiSearchIndex;
/** Custom UI component to be displayed when the `MessageList` is empty, defaults to and accepts same props as: [EmptyStateIndicator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/EmptyStateIndicator/EmptyStateIndicator.tsx) */
EmptyStateIndicator?: React.ComponentType;
diff --git a/src/i18n/de.json b/src/i18n/de.json
index ebe9c2644..53a87ab77 100644
--- a/src/i18n/de.json
+++ b/src/i18n/de.json
@@ -43,6 +43,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} hat abgestimmt: {{pollOptionText}}",
"📍Shared location": "📍Geteilter Standort",
"Actions": "Actions",
+ "Activities": "Aktivitäten",
"Add": "Hinzufügen",
"Add {{ count }} members_one": "{{ count }} Mitglied hinzufügen",
"Add {{ count }} members_other": "{{ count }} Mitglieder hinzufügen",
@@ -65,6 +66,7 @@
"Also sent in channel": "Auch im Kanal gesendet",
"An error has occurred during recording": "Ein Fehler ist während der Aufnahme aufgetreten",
"An error has occurred during the recording processing": "Ein Fehler ist während der Aufnahmeverarbeitung aufgetreten",
+ "Animals & Nature": "Tiere & Natur",
"Anonymous": "Anonym",
"Anonymous poll": "Anonyme Umfrage",
"Archive": "Archivieren",
@@ -100,8 +102,12 @@
"aria/Channel Actions": "Kanalaktionen",
"aria/Channel details": "Kanaldetails",
"aria/Channel list": "Kanalliste",
+ "aria/Channel search results": "Kanalsuchergebnisse",
"aria/Chat view controls": "Chat-Ansicht-Steuerelemente",
+ "aria/Chat view tabs": "Chat-Ansicht Tabs",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "Standard-Hautton wählen",
+ "aria/Clear emoji search": "Emoji-Suche löschen",
"aria/Clear search": "Suche leeren",
"aria/Close callout dialog": "Hinweisdialog schließen",
"aria/Close thread": "Thread schließen",
@@ -270,6 +276,8 @@
"Create a question, add options, and configure poll settings": "Erstelle eine Frage, füge Optionen hinzu und konfiguriere die Umfrageeinstellungen",
"Create poll": "Umfrage erstellen",
"Current location": "Aktueller Standort",
+ "Dark": "Dunkel",
+ "Default": "Standard",
"Delete": "Löschen",
"Delete chat": "Chat löschen",
"Delete for me": "Für mich löschen",
@@ -340,6 +348,7 @@
"Failed to jump to the first unread message": "Fehler beim Springen zur ersten ungelesenen Nachricht",
"Failed to leave channel": "Kanal konnte nicht verlassen werden",
"Failed to load channels": "Kanäle konnten nicht geladen werden",
+ "Failed to load emojis": "Emojis konnten nicht geladen werden",
"Failed to load more channels": "Weitere Kanäle konnten nicht geladen werden",
"Failed to mark channel as read": "Fehler beim Markieren des Kanals als gelesen",
"Failed to play the recording": "Wiedergabe der Aufnahme fehlgeschlagen",
@@ -357,6 +366,9 @@
"fileCount_other": "{{ count }} dateien",
"Files": "Dateien",
"Flag": "Melden",
+ "Flags": "Flaggen",
+ "Food & Drink": "Essen & Trinken",
+ "Frequently used": "Häufig verwendet",
"Generating...": "Generieren...",
"giphy-command-args": "[Text]",
"giphy-command-description": "Poste ein zufälliges Gif in den Kanal",
@@ -430,6 +442,7 @@
"Leave chat": "Kanal verlassen",
"Left channel": "Kanal verlassen",
"Let others add options": "Andere Optionen hinzufügen lassen",
+ "Light": "Hell",
"Limit votes per person": "Stimmen pro Person begrenzen",
"Link": "Link",
"linkCount_one": "Link",
@@ -448,6 +461,9 @@
"Mark as unread": "Als ungelesen markieren",
"Maximum number of votes (from 2 to 10)": "Maximale Anzahl der Stimmen (von 2 bis 10)",
"Maximum votes per person": "Maximale Stimmen pro Person",
+ "Medium": "Mittel",
+ "Medium-Dark": "Mitteldunkel",
+ "Medium-Light": "Mittelhell",
"Member detail": "Mitgliederdetails",
"mention/Channel": "Kanal",
"mention/Channel Description": "Alle in diesem Kanal benachrichtigen",
@@ -478,6 +494,7 @@
"Next image": "Nächstes Bild",
"No chats here yet…": "Noch keine Chats hier...",
"No conversations yet": "Noch keine Unterhaltungen",
+ "No emoji found": "Keine Emojis gefunden",
"No files": "Keine Dateien",
"No items exist": "Keine Elemente vorhanden",
"No member found": "Kein Mitglied gefunden",
@@ -489,6 +506,7 @@
"Nobody will be able to vote in this poll anymore.": "Niemand kann mehr in dieser Umfrage abstimmen.",
"Nothing yet...": "Noch nichts...",
"Notify all {{ role }} members": "Alle Mitglieder mit Rolle {{ role }} benachrichtigen",
+ "Objects": "Objekte",
"Offline": "Offline",
"Ok": "OK",
"Online": "Online",
@@ -508,6 +526,7 @@
"People matching": "Passende Personen",
"Photo": "Foto",
"Photos & videos": "Fotos & Videos",
+ "Pick an emoji…": "Emoji auswählen…",
"Pin": "Anheften",
"Pin a message to see it here": "Hefte eine Nachricht an, um sie hier zu sehen",
"Pinned by {{ name }}": "Angeheftet von {{ name }}",
@@ -553,6 +572,7 @@
"replyCount_one": "1 Antwort",
"replyCount_other": "{{ count }} Antworten",
"Resend": "Erneut senden",
+ "Retry": "Erneut versuchen",
"Retry upload": "Upload erneut versuchen",
"Review all options available in this poll": "Überprüfe alle verfügbaren Optionen in dieser Umfrage",
"Review comments submitted with poll answers": "Überprüfe Kommentare, die mit Umfrageantworten eingereicht wurden",
@@ -563,6 +583,7 @@
"Save for later": "Für später speichern",
"Saved for later": "Für später gespeichert",
"Search": "Suche",
+ "Search emoji": "Emoji suchen",
"Search GIFs": "GIFs suchen",
"search-results-header-filter-source-button-label--channels": "Kanäle",
"search-results-header-filter-source-button-label--messages": "Nachrichten",
@@ -598,12 +619,14 @@
"size limit": "Größenbeschränkung",
"Slow Mode ON": "Langsamer Modus EIN",
"Slow mode, wait {{ seconds }}s...": "Langsamer Modus, warte {{ seconds }}s...",
+ "Smileys & People": "Smileys & Personen",
"Some of the files will not be accepted": "Einige der Dateien werden nicht akzeptiert",
"Start typing to search": "Tippen Sie, um zu suchen",
"Stop sharing": "Teilen beenden",
"Submit": "Absenden",
"Suggest a new option to add to this poll": "Schlage eine neue Option vor, die zu dieser Umfrage hinzugefügt werden soll",
"Suggest an option": "Eine Option vorschlagen",
+ "Symbols": "Symbole",
"Tap to remove": "Tippen zum Entfernen",
"Tap to remove: {{ reactionName }}": "Tippen zum Entfernen: {{ reactionName }}",
"Thinking...": "Denken...",
@@ -642,6 +665,7 @@
"Translated": "Übersetzt",
"Translated from {{ language }}": "Übersetzung aus {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Reisen & Orte",
"Type a number from 2 to 10": "Geben Sie eine Zahl von 2 bis 10 ein",
"Unarchive": "Archivierung aufheben",
"unban-command-args": "[@Benutzername]",
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 4d2d536dd..3eea668af 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -43,6 +43,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} voted: {{pollOptionText}}",
"📍Shared location": "📍Shared location",
"Actions": "Actions",
+ "Activities": "Activities",
"Add": "Add",
"Add {{ count }} members_one": "Add {{ count }} member",
"Add {{ count }} members_other": "Add {{ count }} members",
@@ -65,6 +66,7 @@
"Also sent in channel": "Also sent in channel",
"An error has occurred during recording": "An error has occurred during recording",
"An error has occurred during the recording processing": "An error has occurred during the recording processing",
+ "Animals & Nature": "Animals & Nature",
"Anonymous": "Anonymous",
"Anonymous poll": "Anonymous Poll",
"Archive": "Archive",
@@ -100,8 +102,12 @@
"aria/Channel Actions": "Channel Actions",
"aria/Channel details": "Channel details",
"aria/Channel list": "Channel list",
+ "aria/Channel search results": "Channel search results",
"aria/Chat view controls": "Chat view controls",
+ "aria/Chat view tabs": "Chat view tabs",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "aria/Choose default skin tone",
+ "aria/Clear emoji search": "aria/Clear emoji search",
"aria/Clear search": "Clear search",
"aria/Close callout dialog": "Close callout dialog",
"aria/Close thread": "Close thread",
@@ -270,6 +276,8 @@
"Create a question, add options, and configure poll settings": "Create a question, add options, and configure poll settings",
"Create poll": "Create Poll",
"Current location": "Current location",
+ "Dark": "Dark",
+ "Default": "Default",
"Delete": "Delete",
"Delete chat": "Delete chat",
"Delete for me": "Delete for me",
@@ -340,6 +348,7 @@
"Failed to jump to the first unread message": "Failed to jump to the first unread message",
"Failed to leave channel": "Failed to leave channel",
"Failed to load channels": "Failed to load channels",
+ "Failed to load emojis": "Failed to load emojis",
"Failed to load more channels": "Failed to load more channels",
"Failed to mark channel as read": "Failed to mark channel as read",
"Failed to play the recording": "Failed to play the recording",
@@ -357,6 +366,9 @@
"fileCount_other": "{{ count }} files",
"Files": "Files",
"Flag": "Flag",
+ "Flags": "Flags",
+ "Food & Drink": "Food & Drink",
+ "Frequently used": "Frequently used",
"Generating...": "Generating...",
"giphy-command-args": "[text]",
"giphy-command-description": "Post a random gif to the channel",
@@ -430,6 +442,7 @@
"Leave chat": "Leave chat",
"Left channel": "Left channel",
"Let others add options": "Let Others Add Options",
+ "Light": "Light",
"Limit votes per person": "Limit Votes per Person",
"Link": "Link",
"linkCount_one": "Link",
@@ -448,6 +461,9 @@
"Mark as unread": "Mark as unread",
"Maximum number of votes (from 2 to 10)": "Maximum number of votes (from 2 to 10)",
"Maximum votes per person": "Maximum votes per person",
+ "Medium": "Medium",
+ "Medium-Dark": "Medium-Dark",
+ "Medium-Light": "Medium-Light",
"Member detail": "Member detail",
"mention/Channel": "Channel",
"mention/Channel Description": "Notify everyone in this channel",
@@ -478,6 +494,7 @@
"Next image": "Next image",
"No chats here yet…": "No chats here yet…",
"No conversations yet": "No conversations yet",
+ "No emoji found": "No emoji found",
"No files": "No files",
"No items exist": "No items exist",
"No member found": "No member found",
@@ -489,6 +506,7 @@
"Nobody will be able to vote in this poll anymore.": "Nobody will be able to vote in this poll anymore.",
"Nothing yet...": "Nothing yet...",
"Notify all {{ role }} members": "Notify all {{ role }} members",
+ "Objects": "Objects",
"Offline": "Offline",
"Ok": "Ok",
"Online": "Online",
@@ -508,6 +526,7 @@
"People matching": "People matching",
"Photo": "Photo",
"Photos & videos": "Photos & videos",
+ "Pick an emoji…": "Pick an emoji…",
"Pin": "Pin",
"Pin a message to see it here": "Pin a message to see it here",
"Pinned by {{ name }}": "Pinned by {{ name }}",
@@ -553,6 +572,7 @@
"replyCount_one": "1 reply",
"replyCount_other": "{{ count }} replies",
"Resend": "Resend",
+ "Retry": "Retry",
"Retry upload": "Retry upload",
"Review all options available in this poll": "Review all options available in this poll",
"Review comments submitted with poll answers": "Review comments submitted with poll answers",
@@ -563,6 +583,7 @@
"Save for later": "Save for later",
"Saved for later": "Saved for later",
"Search": "Search",
+ "Search emoji": "Search emoji",
"Search GIFs": "Search GIFs",
"search-results-header-filter-source-button-label--channels": "channels",
"search-results-header-filter-source-button-label--messages": "messages",
@@ -598,12 +619,14 @@
"size limit": "size limit",
"Slow Mode ON": "Slow Mode ON",
"Slow mode, wait {{ seconds }}s...": "Slow mode, wait {{ seconds }}s...",
+ "Smileys & People": "Smileys & People",
"Some of the files will not be accepted": "Some of the files will not be accepted",
"Start typing to search": "Start typing to search",
"Stop sharing": "Stop sharing",
"Submit": "Submit",
"Suggest a new option to add to this poll": "Suggest a new option to add to this poll",
"Suggest an option": "Suggest an Option",
+ "Symbols": "Symbols",
"Tap to remove": "Tap to remove",
"Tap to remove: {{ reactionName }}": "Tap to remove: {{ reactionName }}",
"Thinking...": "Thinking...",
@@ -642,6 +665,7 @@
"Translated": "Translated",
"Translated from {{ language }}": "Translated from {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Travel & Places",
"Type a number from 2 to 10": "Type a number from 2 to 10",
"Unarchive": "Unarchive",
"unban-command-args": "[@username]",
diff --git a/src/i18n/es.json b/src/i18n/es.json
index f0a743d48..3981a33e8 100644
--- a/src/i18n/es.json
+++ b/src/i18n/es.json
@@ -53,6 +53,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} votó: {{pollOptionText}}",
"📍Shared location": "📍Ubicación compartida",
"Actions": "Actions",
+ "Activities": "Actividades",
"Add": "Añadir",
"Add {{ count }} members_one": "Añadir {{ count }} miembro",
"Add {{ count }} members_many": "Añadir {{ count }} miembros",
@@ -76,6 +77,7 @@
"Also sent in channel": "También enviado en el canal",
"An error has occurred during recording": "Se ha producido un error durante la grabación",
"An error has occurred during the recording processing": "Se ha producido un error durante el procesamiento de la grabación",
+ "Animals & Nature": "Animales y naturaleza",
"Anonymous": "Anónimo",
"Anonymous poll": "Encuesta anónima",
"Archive": "Archivo",
@@ -116,8 +118,12 @@
"aria/Channel Actions": "Acciones del canal",
"aria/Channel details": "Detalles del canal",
"aria/Channel list": "Lista de canales",
+ "aria/Channel search results": "Resultados de búsqueda de canales",
"aria/Chat view controls": "Controles de la vista del chat",
+ "aria/Chat view tabs": "Pestañas de vista del chat",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "Elegir tono de piel predeterminado",
+ "aria/Clear emoji search": "Borrar búsqueda de emojis",
"aria/Clear search": "Borrar búsqueda",
"aria/Close callout dialog": "Cerrar diálogo de aviso",
"aria/Close thread": "Cerrar hilo",
@@ -287,6 +293,8 @@
"Create a question, add options, and configure poll settings": "Crea una pregunta, añade opciones y configura los ajustes de la encuesta",
"Create poll": "Crear encuesta",
"Current location": "Ubicación actual",
+ "Dark": "Oscuro",
+ "Default": "Predeterminado",
"Delete": "Borrar",
"Delete chat": "Eliminar chat",
"Delete for me": "Eliminar para mí",
@@ -357,6 +365,7 @@
"Failed to jump to the first unread message": "Error al saltar al primer mensaje no leído",
"Failed to leave channel": "No se pudo salir del canal",
"Failed to load channels": "No se pudieron cargar los canales",
+ "Failed to load emojis": "No se pudieron cargar los emojis",
"Failed to load more channels": "No se pudieron cargar más canales",
"Failed to mark channel as read": "Error al marcar el canal como leído",
"Failed to play the recording": "No se pudo reproducir la grabación",
@@ -375,6 +384,9 @@
"fileCount_other": "{{ count }} archivos",
"Files": "Archivos",
"Flag": "Marcar",
+ "Flags": "Banderas",
+ "Food & Drink": "Comida y bebida",
+ "Frequently used": "Usados frecuentemente",
"Generating...": "Generando...",
"giphy-command-args": "[texto]",
"giphy-command-description": "Publicar un gif aleatorio en el canal",
@@ -449,6 +461,7 @@
"Leave chat": "Abandonar canal",
"Left channel": "Canal abandonado",
"Let others add options": "Permitir que otros añadan opciones",
+ "Light": "Claro",
"Limit votes per person": "Limitar votos por persona",
"Link": "Enlace",
"linkCount_one": "Enlace",
@@ -468,6 +481,9 @@
"Mark as unread": "Marcar como no leído",
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
"Maximum votes per person": "Máximo de votos por persona",
+ "Medium": "Medio",
+ "Medium-Dark": "Medio oscuro",
+ "Medium-Light": "Medio claro",
"Member detail": "Detalle del miembro",
"mention/Channel": "Canal",
"mention/Channel Description": "Notificar a todos en este canal",
@@ -498,6 +514,7 @@
"Next image": "Siguiente imagen",
"No chats here yet…": "Aún no hay mensajes aquí...",
"No conversations yet": "Aún no hay conversaciones",
+ "No emoji found": "No se encontraron emojis",
"No files": "No hay archivos",
"No items exist": "No existen elementos",
"No member found": "No se encontró ningún miembro",
@@ -509,6 +526,7 @@
"Nobody will be able to vote in this poll anymore.": "Nadie podrá votar en esta encuesta.",
"Nothing yet...": "Nada aún...",
"Notify all {{ role }} members": "Notificar a todos los miembros con rol {{ role }}",
+ "Objects": "Objetos",
"Offline": "Desconectado",
"Ok": "Aceptar",
"Online": "En línea",
@@ -528,6 +546,7 @@
"People matching": "Personas que coinciden",
"Photo": "Foto",
"Photos & videos": "Fotos y videos",
+ "Pick an emoji…": "Elige un emoji…",
"Pin": "Fijar",
"Pin a message to see it here": "Fija un mensaje para verlo aquí",
"Pinned by {{ name }}": "Fijado por {{ name }}",
@@ -576,6 +595,7 @@
"replyCount_many": "{{ count }} respuestas",
"replyCount_other": "{{ count }} respuestas",
"Resend": "Reenviar",
+ "Retry": "Reintentar",
"Retry upload": "Reintentar la carga",
"Review all options available in this poll": "Revisa todas las opciones disponibles en esta encuesta",
"Review comments submitted with poll answers": "Revisa los comentarios enviados con las respuestas de la encuesta",
@@ -586,6 +606,7 @@
"Save for later": "Guardar para más tarde",
"Saved for later": "Guardado para más tarde",
"Search": "Buscar",
+ "Search emoji": "Buscar emoji",
"Search GIFs": "Buscar GIFs",
"search-results-header-filter-source-button-label--channels": "canales",
"search-results-header-filter-source-button-label--messages": "mensajes",
@@ -623,12 +644,14 @@
"size limit": "límite de tamaño",
"Slow Mode ON": "Modo lento activado",
"Slow mode, wait {{ seconds }}s...": "Modo lento, espera {{ seconds }} s...",
+ "Smileys & People": "Emoticonos y personas",
"Some of the files will not be accepted": "Algunos archivos no serán aceptados",
"Start typing to search": "Empieza a escribir para buscar",
"Stop sharing": "Dejar de compartir",
"Submit": "Enviar",
"Suggest a new option to add to this poll": "Sugiere una nueva opción para añadir a esta encuesta",
"Suggest an option": "Sugerir una opción",
+ "Symbols": "Símbolos",
"Tap to remove": "Toca para quitar",
"Tap to remove: {{ reactionName }}": "Toca para quitar: {{ reactionName }}",
"Thinking...": "Pensando...",
@@ -669,6 +692,7 @@
"Translated": "Traducido",
"Translated from {{ language }}": "Traducido de {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Viajes y lugares",
"Type a number from 2 to 10": "Escribe un número del 2 al 10",
"Unarchive": "Desarchivar",
"unban-command-args": "[@usuario]",
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index 838567394..ce5476a7e 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -53,6 +53,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} a voté : {{pollOptionText}}",
"📍Shared location": "📍Emplacement partagé",
"Actions": "Actions",
+ "Activities": "Activités",
"Add": "Ajouter",
"Add {{ count }} members_one": "Ajouter {{ count }} membre",
"Add {{ count }} members_many": "Ajouter {{ count }} membres",
@@ -76,6 +77,7 @@
"Also sent in channel": "Également envoyé dans le canal",
"An error has occurred during recording": "Une erreur s'est produite pendant l'enregistrement",
"An error has occurred during the recording processing": "Une erreur s'est produite pendant le traitement de l'enregistrement",
+ "Animals & Nature": "Animaux et nature",
"Anonymous": "Anonyme",
"Anonymous poll": "Sondage anonyme",
"Archive": "Archiver",
@@ -116,8 +118,12 @@
"aria/Channel Actions": "Actions du canal",
"aria/Channel details": "Détails du canal",
"aria/Channel list": "Liste des canaux",
+ "aria/Channel search results": "Résultats de recherche de canaux",
"aria/Chat view controls": "Commandes de la vue du chat",
+ "aria/Chat view tabs": "Onglets de la vue de chat",
"aria/Chat: {{ channelName }}": "Chat : {{ channelName }}",
+ "aria/Choose default skin tone": "Choisir le teint par défaut",
+ "aria/Clear emoji search": "Effacer la recherche d'emoji",
"aria/Clear search": "Effacer la recherche",
"aria/Close callout dialog": "Fermer la boîte de dialogue d'information",
"aria/Close thread": "Fermer le fil",
@@ -287,6 +293,8 @@
"Create a question, add options, and configure poll settings": "Créez une question, ajoutez des options et configurez les paramètres du sondage",
"Create poll": "Créer un sondage",
"Current location": "Emplacement actuel",
+ "Dark": "Foncé",
+ "Default": "Par défaut",
"Delete": "Supprimer",
"Delete chat": "Supprimer le chat",
"Delete for me": "Supprimer pour moi",
@@ -357,6 +365,7 @@
"Failed to jump to the first unread message": "Échec du saut vers le premier message non lu",
"Failed to leave channel": "Impossible de quitter le canal",
"Failed to load channels": "Impossible de charger les canaux",
+ "Failed to load emojis": "Échec du chargement des emojis",
"Failed to load more channels": "Impossible de charger davantage de canaux",
"Failed to mark channel as read": "Échec du marquage du canal comme lu",
"Failed to play the recording": "Impossible de lire l'enregistrement",
@@ -375,6 +384,9 @@
"fileCount_other": "{{ count }} fichiers",
"Files": "Fichiers",
"Flag": "Signaler",
+ "Flags": "Drapeaux",
+ "Food & Drink": "Nourriture et boissons",
+ "Frequently used": "Fréquemment utilisés",
"Generating...": "Génération...",
"giphy-command-args": "[texte]",
"giphy-command-description": "Poster un GIF aléatoire dans le canal",
@@ -449,6 +461,7 @@
"Leave chat": "Quitter le canal",
"Left channel": "Canal quitté",
"Let others add options": "Permettre à d'autres d'ajouter des options",
+ "Light": "Clair",
"Limit votes per person": "Limiter les votes par personne",
"Link": "Lien",
"linkCount_one": "Lien",
@@ -468,6 +481,9 @@
"Mark as unread": "Marquer comme non lu",
"Maximum number of votes (from 2 to 10)": "Nombre maximum de votes (de 2 à 10)",
"Maximum votes per person": "Nombre maximal de votes par personne",
+ "Medium": "Moyen",
+ "Medium-Dark": "Moyennement foncé",
+ "Medium-Light": "Moyennement clair",
"Member detail": "Détails du membre",
"mention/Channel": "Canal",
"mention/Channel Description": "Notifier tout le monde dans ce canal",
@@ -498,6 +514,7 @@
"Next image": "Image suivante",
"No chats here yet…": "Pas encore de messages ici...",
"No conversations yet": "Aucune conversation pour le moment",
+ "No emoji found": "Aucun emoji trouvé",
"No files": "Aucun fichier",
"No items exist": "Aucun élément",
"No member found": "Aucun membre trouvé",
@@ -509,6 +526,7 @@
"Nobody will be able to vote in this poll anymore.": "Personne ne pourra plus voter dans ce sondage.",
"Nothing yet...": "Rien pour l'instant...",
"Notify all {{ role }} members": "Notifier tous les membres ayant le rôle {{ role }}",
+ "Objects": "Objets",
"Offline": "Hors ligne",
"Ok": "D'accord",
"Online": "En ligne",
@@ -528,6 +546,7 @@
"People matching": "Correspondance de personnes",
"Photo": "Photo",
"Photos & videos": "Photos et vidéos",
+ "Pick an emoji…": "Choisissez un emoji…",
"Pin": "Épingler",
"Pin a message to see it here": "Épinglez un message pour le voir ici",
"Pinned by {{ name }}": "Épinglé par {{ name }}",
@@ -576,6 +595,7 @@
"replyCount_many": "{{ count }} réponses",
"replyCount_other": "{{ count }} réponses",
"Resend": "Renvoyer",
+ "Retry": "Réessayer",
"Retry upload": "Réessayer le téléchargement",
"Review all options available in this poll": "Consultez toutes les options disponibles dans ce sondage",
"Review comments submitted with poll answers": "Consultez les commentaires envoyés avec les réponses au sondage",
@@ -586,6 +606,7 @@
"Save for later": "Enregistrer pour plus tard",
"Saved for later": "Enregistré pour plus tard",
"Search": "Rechercher",
+ "Search emoji": "Rechercher un emoji",
"Search GIFs": "Rechercher des GIFs",
"search-results-header-filter-source-button-label--channels": "canaux",
"search-results-header-filter-source-button-label--messages": "messages",
@@ -623,12 +644,14 @@
"size limit": "limite de taille",
"Slow Mode ON": "Mode lent activé",
"Slow mode, wait {{ seconds }}s...": "Mode lent, attendez {{ seconds }} s...",
+ "Smileys & People": "Émoticônes et personnes",
"Some of the files will not be accepted": "Certains fichiers ne seront pas acceptés",
"Start typing to search": "Commencez à taper pour rechercher",
"Stop sharing": "Arrêter de partager",
"Submit": "Envoyer",
"Suggest a new option to add to this poll": "Suggérez une nouvelle option à ajouter à ce sondage",
"Suggest an option": "Suggérer une option",
+ "Symbols": "Symboles",
"Tap to remove": "Appuyez pour retirer",
"Tap to remove: {{ reactionName }}": "Appuyez pour retirer: {{ reactionName }}",
"Thinking...": "Réflexion...",
@@ -669,6 +692,7 @@
"Translated": "Traduit",
"Translated from {{ language }}": "Traduit du {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Voyages et lieux",
"Type a number from 2 to 10": "Tapez un nombre de 2 à 10",
"Unarchive": "Désarchiver",
"unban-command-args": "[@nomdutilisateur]",
diff --git a/src/i18n/hi.json b/src/i18n/hi.json
index 920881d77..c9e18310d 100644
--- a/src/i18n/hi.json
+++ b/src/i18n/hi.json
@@ -43,6 +43,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} ने वोट दिया: {{pollOptionText}}",
"📍Shared location": "📍साझा किया गया स्थान",
"Actions": "Actions",
+ "Activities": "गतिविधियाँ",
"Add": "जोड़ें",
"Add {{ count }} members_one": "{{ count }} सदस्य जोड़ें",
"Add {{ count }} members_other": "{{ count }} सदस्य जोड़ें",
@@ -65,6 +66,7 @@
"Also sent in channel": "चैनल में भी भेजा गया",
"An error has occurred during recording": "रेकॉर्डिंग के दौरान एक त्रुटि आ गई है",
"An error has occurred during the recording processing": "रेकॉर्डिंग प्रोसेसिंग के दौरान एक त्रुटि आ गई है",
+ "Animals & Nature": "जानवर और प्रकृति",
"Anonymous": "गुमनाम",
"Anonymous poll": "गुमनाम मतदान",
"Archive": "आर्काइव",
@@ -100,8 +102,12 @@
"aria/Channel Actions": "चैनल क्रियाएँ",
"aria/Channel details": "चैनल विवरण",
"aria/Channel list": "चैनल सूची",
+ "aria/Channel search results": "चैनल खोज परिणाम",
"aria/Chat view controls": "चैट व्यू नियंत्रण",
+ "aria/Chat view tabs": "चैट व्यू टैब",
"aria/Chat: {{ channelName }}": "चैट: {{ channelName }}",
+ "aria/Choose default skin tone": "डिफ़ॉल्ट त्वचा टोन चुनें",
+ "aria/Clear emoji search": "इमोजी खोज साफ़ करें",
"aria/Clear search": "खोज साफ़ करें",
"aria/Close callout dialog": "कॉलआउट संवाद बंद करें",
"aria/Close thread": "थ्रेड बंद करें",
@@ -270,6 +276,8 @@
"Create a question, add options, and configure poll settings": "एक प्रश्न बनाएं, विकल्प जोड़ें और पोल सेटिंग्स कॉन्फ़िगर करें",
"Create poll": "मतदान बनाएँ",
"Current location": "वर्तमान स्थान",
+ "Dark": "गहरा",
+ "Default": "डिफ़ॉल्ट",
"Delete": "डिलीट",
"Delete chat": "चैट हटाएं",
"Delete for me": "मेरे लिए डिलीट करें",
@@ -341,6 +349,7 @@
"Failed to jump to the first unread message": "पहले अपठित संदेश पर जाने में विफल",
"Failed to leave channel": "चैनल छोड़ने में विफल",
"Failed to load channels": "चैनल लोड करने में विफल",
+ "Failed to load emojis": "इमोजी लोड नहीं हो सके",
"Failed to load more channels": "और चैनल लोड करने में विफल",
"Failed to mark channel as read": "चैनल को पढ़ा हुआ चिह्नित करने में विफल।",
"Failed to play the recording": "रेकॉर्डिंग प्ले करने में विफल",
@@ -358,6 +367,9 @@
"fileCount_other": "{{ count }} फ़ाइलें",
"Files": "फ़ाइलें",
"Flag": "फ्लैग करे",
+ "Flags": "झंडे",
+ "Food & Drink": "खाना और पेय",
+ "Frequently used": "अक्सर उपयोग किए गए",
"Generating...": "बना रहा है...",
"giphy-command-args": "[पाठ]",
"giphy-command-description": "चैनल पर एक क्रॉफिल जीआइएफ पोस्ट करें",
@@ -431,6 +443,7 @@
"Leave chat": "चैनल छोड़ें",
"Left channel": "चैनल छोड़ दिया गया",
"Let others add options": "दूसरों को विकल्प जोड़ने दें",
+ "Light": "हल्का",
"Limit votes per person": "प्रति व्यक्ति वोट सीमित करें",
"Link": "लिंक",
"linkCount_one": "1 लिंक",
@@ -449,6 +462,9 @@
"Mark as unread": "अपठित चिह्नित करें",
"Maximum number of votes (from 2 to 10)": "अधिकतम वोटों की संख्या (2 से 10)",
"Maximum votes per person": "प्रति व्यक्ति अधिकतम वोट",
+ "Medium": "मध्यम",
+ "Medium-Dark": "मध्यम-गहरा",
+ "Medium-Light": "मध्यम-हल्का",
"Member detail": "सदस्य विवरण",
"mention/Channel": "चैनल",
"mention/Channel Description": "इस चैनल में सभी को सूचित करें",
@@ -479,6 +495,7 @@
"Next image": "अगली छवि",
"No chats here yet…": "यहां अभी तक कोई चैट नहीं...",
"No conversations yet": "अभी तक कोई बातचीत नहीं है",
+ "No emoji found": "कोई इमोजी नहीं मिला",
"No files": "कोई फ़ाइल नहीं",
"No items exist": "कोई आइटम मौजूद नहीं है",
"No member found": "कोई सदस्य नहीं मिला",
@@ -490,6 +507,7 @@
"Nobody will be able to vote in this poll anymore.": "अब कोई भी इस मतदान में मतदान नहीं कर सकेगा।",
"Nothing yet...": "कोई मैसेज नहीं है",
"Notify all {{ role }} members": "{{ role }} भूमिका वाले सभी सदस्यों को सूचित करें",
+ "Objects": "वस्तुएँ",
"Offline": "ऑफलाइन",
"Ok": "ठीक है",
"Online": "ऑनलाइन",
@@ -509,6 +527,7 @@
"People matching": "मेल खाते लोग",
"Photo": "फ़ोटो",
"Photos & videos": "फ़ोटो और वीडियो",
+ "Pick an emoji…": "इमोजी चुनें…",
"Pin": "पिन",
"Pin a message to see it here": "इसे यहाँ देखने के लिए संदेश पिन करें",
"Pinned by {{ name }}": "{{ name }} द्वारा पिन किया गया",
@@ -554,6 +573,7 @@
"replyCount_one": "1 रिप्लाई",
"replyCount_other": "{{ count }} रिप्लाई",
"Resend": "फिर से भेजें",
+ "Retry": "पुनः प्रयास करें",
"Retry upload": "अपलोड फिर से करें",
"Review all options available in this poll": "इस पोल में उपलब्ध सभी विकल्पों की समीक्षा करें",
"Review comments submitted with poll answers": "पोल उत्तरों के साथ भेजी गई टिप्पणियों की समीक्षा करें",
@@ -564,6 +584,7 @@
"Save for later": "बाद के लिए सहेजें",
"Saved for later": "बाद के लिए सहेजा गया",
"Search": "खोज",
+ "Search emoji": "इमोजी खोजें",
"Search GIFs": "GIF खोजें",
"search-results-header-filter-source-button-label--channels": "चैनल्स",
"search-results-header-filter-source-button-label--messages": "संदेश",
@@ -599,12 +620,14 @@
"size limit": "आकार सीमा",
"Slow Mode ON": "स्लो मोड ऑन",
"Slow mode, wait {{ seconds }}s...": "स्लो मोड, {{ seconds }} सेकंड प्रतीक्षा करें...",
+ "Smileys & People": "स्माइली और लोग",
"Some of the files will not be accepted": "कुछ फ़ाइलें स्वीकार नहीं की जाएंगी",
"Start typing to search": "खोजने के लिए टाइप करना शुरू करें",
"Stop sharing": "साझा करना बंद करें",
"Submit": "जमा करें",
"Suggest a new option to add to this poll": "इस पोल में जोड़ने के लिए एक नया विकल्प सुझाएं",
"Suggest an option": "एक विकल्प सुझाव दें",
+ "Symbols": "प्रतीक",
"Tap to remove": "हटाने के लिए टैप करें",
"Tap to remove: {{ reactionName }}": "हटाने के लिए टैप करें: {{ reactionName }}",
"Thinking...": "सोच रहा है...",
@@ -643,6 +666,7 @@
"Translated": "अनुवादित",
"Translated from {{ language }}": "{{ language }} से अनुवादित",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "यात्रा और स्थान",
"Type a number from 2 to 10": "2 से 10 तक का एक नंबर टाइप करें",
"Unarchive": "अनआर्काइव",
"unban-command-args": "[@उपयोगकर्तनाम]",
diff --git a/src/i18n/it.json b/src/i18n/it.json
index 3f23847bf..de794792e 100644
--- a/src/i18n/it.json
+++ b/src/i18n/it.json
@@ -53,6 +53,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} ha votato: {{pollOptionText}}",
"📍Shared location": "📍Posizione condivisa",
"Actions": "Actions",
+ "Activities": "Attività",
"Add": "Aggiungi",
"Add {{ count }} members_one": "Aggiungi {{ count }} membro",
"Add {{ count }} members_many": "Aggiungi {{ count }} membri",
@@ -76,6 +77,7 @@
"Also sent in channel": "Inviato anche nel canale",
"An error has occurred during recording": "Si è verificato un errore durante la registrazione",
"An error has occurred during the recording processing": "Si è verificato un errore durante l'elaborazione della registrazione",
+ "Animals & Nature": "Animali e natura",
"Anonymous": "Anonimo",
"Anonymous poll": "Sondaggio anonimo",
"Archive": "Archivia",
@@ -116,8 +118,12 @@
"aria/Channel Actions": "Azioni canale",
"aria/Channel details": "Dettagli canale",
"aria/Channel list": "Elenco dei canali",
+ "aria/Channel search results": "Risultati della ricerca dei canali",
"aria/Chat view controls": "Controlli visualizzazione chat",
+ "aria/Chat view tabs": "Schede visualizzazione chat",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "Scegli la tonalità della pelle predefinita",
+ "aria/Clear emoji search": "Cancella ricerca emoji",
"aria/Clear search": "Cancella ricerca",
"aria/Close callout dialog": "Chiudi finestra informativa",
"aria/Close thread": "Chiudi discussione",
@@ -287,6 +293,8 @@
"Create a question, add options, and configure poll settings": "Crea una domanda, aggiungi opzioni e configura le impostazioni del sondaggio",
"Create poll": "Crea sondaggio",
"Current location": "Posizione attuale",
+ "Dark": "Scuro",
+ "Default": "Predefinito",
"Delete": "Elimina",
"Delete chat": "Elimina chat",
"Delete for me": "Elimina per me",
@@ -357,6 +365,7 @@
"Failed to jump to the first unread message": "Impossibile passare al primo messaggio non letto",
"Failed to leave channel": "Impossibile lasciare il canale",
"Failed to load channels": "Impossibile caricare i canali",
+ "Failed to load emojis": "Impossibile caricare gli emoji",
"Failed to load more channels": "Impossibile caricare altri canali",
"Failed to mark channel as read": "Impossibile contrassegnare il canale come letto",
"Failed to play the recording": "Impossibile riprodurre la registrazione",
@@ -375,6 +384,9 @@
"fileCount_other": "{{ count }} file",
"Files": "File",
"Flag": "Segnala",
+ "Flags": "Bandiere",
+ "Food & Drink": "Cibo e bevande",
+ "Frequently used": "Usati di frequente",
"Generating...": "Generando...",
"giphy-command-args": "[testo]",
"giphy-command-description": "Pubblica un gif casuale sul canale",
@@ -449,6 +461,7 @@
"Leave chat": "Lascia il canale",
"Left channel": "Canale lasciato",
"Let others add options": "Lascia che altri aggiungano opzioni",
+ "Light": "Chiaro",
"Limit votes per person": "Limita i voti per persona",
"Link": "Collegamento",
"linkCount_one": "Link",
@@ -468,6 +481,9 @@
"Mark as unread": "Contrassegna come non letto",
"Maximum number of votes (from 2 to 10)": "Numero massimo di voti (da 2 a 10)",
"Maximum votes per person": "Voti massimi per persona",
+ "Medium": "Medio",
+ "Medium-Dark": "Medio scuro",
+ "Medium-Light": "Medio chiaro",
"Member detail": "Dettagli membro",
"mention/Channel": "Canale",
"mention/Channel Description": "Notifica tutti in questo canale",
@@ -498,6 +514,7 @@
"Next image": "Immagine successiva",
"No chats here yet…": "Non ci sono ancora messaggi qui...",
"No conversations yet": "Ancora nessuna conversazione",
+ "No emoji found": "Nessun emoji trovato",
"No files": "Nessun file",
"No items exist": "Nessun elemento presente",
"No member found": "Nessun membro trovato",
@@ -509,6 +526,7 @@
"Nobody will be able to vote in this poll anymore.": "Nessuno potrà più votare in questo sondaggio.",
"Nothing yet...": "Ancora niente...",
"Notify all {{ role }} members": "Notifica tutti i membri con ruolo {{ role }}",
+ "Objects": "Oggetti",
"Offline": "Offline",
"Ok": "OK",
"Online": "Online",
@@ -528,6 +546,7 @@
"People matching": "Persone che corrispondono",
"Photo": "Foto",
"Photos & videos": "Foto e video",
+ "Pick an emoji…": "Scegli un emoji…",
"Pin": "Appunta",
"Pin a message to see it here": "Appunta un messaggio per vederlo qui",
"Pinned by {{ name }}": "Appuntato da {{ name }}",
@@ -576,6 +595,7 @@
"replyCount_many": "{{ count }} risposte",
"replyCount_other": "{{ count }} risposte",
"Resend": "Invia di nuovo",
+ "Retry": "Riprova",
"Retry upload": "Riprova caricamento",
"Review all options available in this poll": "Rivedi tutte le opzioni disponibili in questo sondaggio",
"Review comments submitted with poll answers": "Rivedi i commenti inviati con le risposte al sondaggio",
@@ -586,6 +606,7 @@
"Save for later": "Salva per dopo",
"Saved for later": "Salvato per dopo",
"Search": "Cerca",
+ "Search emoji": "Cerca emoji",
"Search GIFs": "Cerca GIF",
"search-results-header-filter-source-button-label--channels": "canali",
"search-results-header-filter-source-button-label--messages": "messaggi",
@@ -623,12 +644,14 @@
"size limit": "limite di dimensione",
"Slow Mode ON": "Modalità lenta attivata",
"Slow mode, wait {{ seconds }}s...": "Modalità lenta, attendi {{ seconds }} s...",
+ "Smileys & People": "Faccine e persone",
"Some of the files will not be accepted": "Alcuni dei file non saranno accettati",
"Start typing to search": "Inizia a digitare per cercare",
"Stop sharing": "Ferma condivisione",
"Submit": "Invia",
"Suggest a new option to add to this poll": "Suggerisci una nuova opzione da aggiungere a questo sondaggio",
"Suggest an option": "Suggerisci un'opzione",
+ "Symbols": "Simboli",
"Tap to remove": "Tocca per rimuovere",
"Tap to remove: {{ reactionName }}": "Tocca per rimuovere: {{ reactionName }}",
"Thinking...": "Pensando...",
@@ -669,6 +692,7 @@
"Translated": "Tradotto",
"Translated from {{ language }}": "Tradotto da {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Viaggi e luoghi",
"Type a number from 2 to 10": "Digita un numero da 2 a 10",
"Unarchive": "Ripristina",
"unban-command-args": "[@nomeutente]",
diff --git a/src/i18n/ja.json b/src/i18n/ja.json
index 6770d1e19..c627eec70 100644
--- a/src/i18n/ja.json
+++ b/src/i18n/ja.json
@@ -40,6 +40,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} が投票: {{pollOptionText}}",
"📍Shared location": "📍共有された位置情報",
"Actions": "Actions",
+ "Activities": "アクティビティ",
"Add": "追加",
"Add {{ count }} members_other": "{{ count }}人のメンバーを追加",
"Add a comment": "コメントを追加",
@@ -61,6 +62,7 @@
"Also sent in channel": "チャンネルにも送信済み",
"An error has occurred during recording": "録音中にエラーが発生しました",
"An error has occurred during the recording processing": "録音処理中にエラーが発生しました",
+ "Animals & Nature": "動物と自然",
"Anonymous": "匿名",
"Anonymous poll": "匿名投票",
"Archive": "アーカイブ",
@@ -91,8 +93,12 @@
"aria/Channel Actions": "チャンネル操作",
"aria/Channel details": "チャンネル詳細",
"aria/Channel list": "チャンネル一覧",
+ "aria/Channel search results": "チャンネル検索結果",
"aria/Chat view controls": "チャットビューのコントロール",
+ "aria/Chat view tabs": "チャットビューのタブ",
"aria/Chat: {{ channelName }}": "チャット: {{ channelName }}",
+ "aria/Choose default skin tone": "デフォルトの肌の色を選択",
+ "aria/Clear emoji search": "絵文字検索をクリア",
"aria/Clear search": "検索をクリア",
"aria/Close callout dialog": "吹き出しダイアログを閉じる",
"aria/Close thread": "スレッドを閉じる",
@@ -261,6 +267,8 @@
"Create a question, add options, and configure poll settings": "質問を作成し、選択肢を追加して投票設定を構成",
"Create poll": "投票を作成",
"Current location": "現在の位置",
+ "Dark": "暗い",
+ "Default": "デフォルト",
"Delete": "消去",
"Delete chat": "チャットを削除",
"Delete for me": "自分用に削除",
@@ -331,6 +339,7 @@
"Failed to jump to the first unread message": "最初の未読メッセージにジャンプできませんでした",
"Failed to leave channel": "チャンネルの退出に失敗しました",
"Failed to load channels": "チャンネルの読み込みに失敗しました",
+ "Failed to load emojis": "絵文字を読み込めませんでした",
"Failed to load more channels": "さらにチャンネルを読み込めませんでした",
"Failed to mark channel as read": "チャンネルを既読にすることができませんでした",
"Failed to play the recording": "録音の再生に失敗しました",
@@ -347,6 +356,9 @@
"fileCount_other": "{{ count }}件のファイル",
"Files": "ファイル",
"Flag": "フラグ",
+ "Flags": "旗",
+ "Food & Drink": "食べ物と飲み物",
+ "Frequently used": "よく使う",
"Generating...": "生成中...",
"giphy-command-args": "[テキスト]",
"giphy-command-description": "チャンネルにランダムなGIFを投稿する",
@@ -419,6 +431,7 @@
"Leave chat": "チャンネルを退出",
"Left channel": "チャンネルを退出しました",
"Let others add options": "他の人が選択肢を追加できるようにする",
+ "Light": "明るい",
"Limit votes per person": "1人あたりの投票数を制限する",
"Link": "リンク",
"linkCount_other": "{{ count }}件のリンク",
@@ -436,6 +449,9 @@
"Mark as unread": "未読としてマーク",
"Maximum number of votes (from 2 to 10)": "最大投票数(2から10まで)",
"Maximum votes per person": "1人あたりの最大投票数",
+ "Medium": "普通",
+ "Medium-Dark": "やや暗い",
+ "Medium-Light": "やや明るい",
"Member detail": "メンバー詳細",
"mention/Channel": "チャンネル",
"mention/Channel Description": "このチャンネルの全員に通知",
@@ -466,6 +482,7 @@
"Next image": "次の画像",
"No chats here yet…": "ここにはまだチャットはありません…",
"No conversations yet": "まだ会話はありません",
+ "No emoji found": "絵文字が見つかりません",
"No files": "ファイルはありません",
"No items exist": "項目がありません",
"No member found": "メンバーが見つかりません",
@@ -477,6 +494,7 @@
"Nobody will be able to vote in this poll anymore.": "この投票では、誰も投票できなくなります。",
"Nothing yet...": "まだ何もありません...",
"Notify all {{ role }} members": "{{ role }} メンバー全員に通知",
+ "Objects": "物",
"Offline": "オフライン",
"Ok": "OK",
"Online": "オンライン",
@@ -496,6 +514,7 @@
"People matching": "一致する人",
"Photo": "写真",
"Photos & videos": "写真と動画",
+ "Pick an emoji…": "絵文字を選択…",
"Pin": "ピン",
"Pin a message to see it here": "ここに表示するにはメッセージをピン留めしてください",
"Pinned by {{ name }}": "{{ name }}がピンしました",
@@ -539,6 +558,7 @@
"replyCount_one": "1件の返信",
"replyCount_other": "{{ count }} 返信",
"Resend": "再送信",
+ "Retry": "再試行",
"Retry upload": "アップロードを再試行",
"Review all options available in this poll": "この投票で利用可能なすべての選択肢を確認",
"Review comments submitted with poll answers": "投票回答とともに送信されたコメントを確認",
@@ -549,6 +569,7 @@
"Save for later": "後で保存",
"Saved for later": "後で保存済み",
"Search": "探す",
+ "Search emoji": "絵文字を検索",
"Search GIFs": "GIFを検索",
"search-results-header-filter-source-button-label--channels": "チャンネル",
"search-results-header-filter-source-button-label--messages": "メッセージ",
@@ -584,12 +605,14 @@
"size limit": "サイズ制限",
"Slow Mode ON": "スローモードオン",
"Slow mode, wait {{ seconds }}s...": "スローモード、{{ seconds }}秒お待ちください...",
+ "Smileys & People": "スマイリーと人々",
"Some of the files will not be accepted": "一部のファイルは受け付けられません",
"Start typing to search": "検索するには入力を開始してください",
"Stop sharing": "共有を停止",
"Submit": "送信",
"Suggest a new option to add to this poll": "この投票に追加する新しい選択肢を提案",
"Suggest an option": "オプションを提案",
+ "Symbols": "記号",
"Tap to remove": "タップして削除",
"Tap to remove: {{ reactionName }}": "タップして削除: {{ reactionName }}",
"Thinking...": "考え中...",
@@ -626,6 +649,7 @@
"Translated": "翻訳済み",
"Translated from {{ language }}": "{{ language }}から翻訳",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "旅行と場所",
"Type a number from 2 to 10": "2から10までの数字を入力してください",
"Unarchive": "アーカイブ解除",
"unban-command-args": "[@ユーザ名]",
diff --git a/src/i18n/ko.json b/src/i18n/ko.json
index 85159367b..a4f1230ea 100644
--- a/src/i18n/ko.json
+++ b/src/i18n/ko.json
@@ -40,6 +40,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}}이(가) 투표함: {{pollOptionText}}",
"📍Shared location": "📍공유된 위치",
"Actions": "Actions",
+ "Activities": "활동",
"Add": "추가",
"Add {{ count }} members_other": "{{ count }}명 멤버 추가",
"Add a comment": "댓글 추가",
@@ -61,6 +62,7 @@
"Also sent in channel": "채널에도 전송됨",
"An error has occurred during recording": "녹음 중 오류가 발생했습니다",
"An error has occurred during the recording processing": "녹음 처리 중 오류가 발생했습니다",
+ "Animals & Nature": "동물 & 자연",
"Anonymous": "익명",
"Anonymous poll": "익명 투표",
"Archive": "아카이브",
@@ -91,8 +93,12 @@
"aria/Channel Actions": "채널 작업",
"aria/Channel details": "채널 세부 정보",
"aria/Channel list": "채널 목록",
+ "aria/Channel search results": "채널 검색 결과",
"aria/Chat view controls": "채팅 보기 컨트롤",
+ "aria/Chat view tabs": "채팅 보기 탭",
"aria/Chat: {{ channelName }}": "채팅: {{ channelName }}",
+ "aria/Choose default skin tone": "기본 피부색 선택",
+ "aria/Clear emoji search": "이모지 검색 지우기",
"aria/Clear search": "검색 지우기",
"aria/Close callout dialog": "콜아웃 대화 상자 닫기",
"aria/Close thread": "스레드 닫기",
@@ -261,6 +267,8 @@
"Create a question, add options, and configure poll settings": "질문을 만들고 옵션을 추가한 뒤 투표 설정 구성",
"Create poll": "투표 생성",
"Current location": "현재 위치",
+ "Dark": "어두움",
+ "Default": "기본",
"Delete": "삭제",
"Delete chat": "채팅 삭제",
"Delete for me": "나만 삭제",
@@ -331,6 +339,7 @@
"Failed to jump to the first unread message": "첫 번째 읽지 않은 메시지로 이동하지 못했습니다",
"Failed to leave channel": "채널 나가기에 실패했습니다",
"Failed to load channels": "채널을 불러오지 못했습니다",
+ "Failed to load emojis": "이모지를 불러오지 못했습니다",
"Failed to load more channels": "채널을 더 불러오지 못했습니다",
"Failed to mark channel as read": "채널을 읽음으로 표시하는 데 실패했습니다",
"Failed to play the recording": "녹음을 재생하지 못했습니다",
@@ -347,6 +356,9 @@
"fileCount_other": "파일 {{ count }}개",
"Files": "파일",
"Flag": "플래그",
+ "Flags": "깃발",
+ "Food & Drink": "음식 & 음료",
+ "Frequently used": "자주 사용함",
"Generating...": "생성 중...",
"giphy-command-args": "[텍스트]",
"giphy-command-description": "채널에 무작위 GIF 게시",
@@ -419,6 +431,7 @@
"Leave chat": "채널 나가기",
"Left channel": "채널을 나갔습니다",
"Let others add options": "다른 사람이 선택지를 추가할 수 있도록 허용",
+ "Light": "밝음",
"Limit votes per person": "1인당 투표 수 제한",
"Link": "링크",
"linkCount_other": "링크 {{ count }}개",
@@ -436,6 +449,9 @@
"Mark as unread": "읽지 않음으로 표시",
"Maximum number of votes (from 2 to 10)": "최대 투표 수 (2에서 10까지)",
"Maximum votes per person": "1인당 최대 투표 수",
+ "Medium": "중간",
+ "Medium-Dark": "중간 어두움",
+ "Medium-Light": "중간 밝음",
"Member detail": "멤버 상세 정보",
"mention/Channel": "채널",
"mention/Channel Description": "이 채널의 모두에게 알림",
@@ -466,6 +482,7 @@
"Next image": "다음 이미지",
"No chats here yet…": "아직 채팅이 없습니다...",
"No conversations yet": "아직 대화가 없습니다.",
+ "No emoji found": "이모지를 찾을 수 없습니다",
"No files": "파일이 없습니다",
"No items exist": "항목이 없습니다.",
"No member found": "멤버를 찾을 수 없습니다",
@@ -477,6 +494,7 @@
"Nobody will be able to vote in this poll anymore.": "이 투표에 더 이상 아무도 투표할 수 없습니다.",
"Nothing yet...": "아직 아무것도...",
"Notify all {{ role }} members": "{{ role }} 역할의 모든 멤버에게 알림",
+ "Objects": "사물",
"Offline": "오프라인",
"Ok": "확인",
"Online": "온라인",
@@ -496,6 +514,7 @@
"People matching": "일치하는 사람",
"Photo": "사진",
"Photos & videos": "사진 및 동영상",
+ "Pick an emoji…": "이모지 선택…",
"Pin": "핀",
"Pin a message to see it here": "여기에서 보려면 메시지를 고정하세요",
"Pinned by {{ name }}": "{{ name }}님이 핀함",
@@ -539,6 +558,7 @@
"replyCount_one": "답장 1개",
"replyCount_other": "{{ count }} 답장",
"Resend": "다시 보내기",
+ "Retry": "다시 시도",
"Retry upload": "업로드 다시 시도",
"Review all options available in this poll": "이 투표에서 사용 가능한 모든 옵션 검토",
"Review comments submitted with poll answers": "투표 답변과 함께 제출된 댓글 검토",
@@ -549,6 +569,7 @@
"Save for later": "나중에 저장",
"Saved for later": "나중에 저장됨",
"Search": "찾다",
+ "Search emoji": "이모지 검색",
"Search GIFs": "GIF 검색",
"search-results-header-filter-source-button-label--channels": "채널",
"search-results-header-filter-source-button-label--messages": "메시지",
@@ -584,12 +605,14 @@
"size limit": "크기 제한",
"Slow Mode ON": "슬로우 모드 켜짐",
"Slow mode, wait {{ seconds }}s...": "슬로우 모드, {{ seconds }}초 기다려 주세요...",
+ "Smileys & People": "스마일리 & 사람",
"Some of the files will not be accepted": "일부 파일은 허용되지 않을 수 있습니다",
"Start typing to search": "검색하려면 입력을 시작하세요",
"Stop sharing": "공유 중지",
"Submit": "제출",
"Suggest a new option to add to this poll": "이 투표에 추가할 새 옵션 제안",
"Suggest an option": "옵션 제안",
+ "Symbols": "기호",
"Tap to remove": "제거하려면 탭하세요",
"Tap to remove: {{ reactionName }}": "제거하려면 탭하세요: {{ reactionName }}",
"Thinking...": "생각 중...",
@@ -626,6 +649,7 @@
"Translated": "번역됨",
"Translated from {{ language }}": "{{ language }}(으)로 번역됨",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "여행 & 장소",
"Type a number from 2 to 10": "2에서 10 사이의 숫자를 입력하세요",
"Unarchive": "아카이브 해제",
"unban-command-args": "[@사용자이름]",
diff --git a/src/i18n/nl.json b/src/i18n/nl.json
index f83f5ad22..97ff04548 100644
--- a/src/i18n/nl.json
+++ b/src/i18n/nl.json
@@ -43,6 +43,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} heeft gestemd: {{pollOptionText}}",
"📍Shared location": "📍Gedeelde locatie",
"Actions": "Actions",
+ "Activities": "Activiteiten",
"Add": "Toevoegen",
"Add {{ count }} members_one": "{{ count }} lid toevoegen",
"Add {{ count }} members_other": "{{ count }} leden toevoegen",
@@ -65,6 +66,7 @@
"Also sent in channel": "Ook in kanaal verzonden",
"An error has occurred during recording": "Er is een fout opgetreden tijdens het opnemen",
"An error has occurred during the recording processing": "Er is een fout opgetreden tijdens de verwerking van de opname",
+ "Animals & Nature": "Dieren en natuur",
"Anonymous": "Anoniem",
"Anonymous poll": "Anonieme peiling",
"Archive": "Archief",
@@ -100,8 +102,12 @@
"aria/Channel Actions": "Kanaalacties",
"aria/Channel details": "Kanaaldetails",
"aria/Channel list": "Kanaallijst",
+ "aria/Channel search results": "Zoekresultaten voor kanalen",
"aria/Chat view controls": "Bedieningselementen chatweergave",
+ "aria/Chat view tabs": "Tabbladen chatweergave",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "Standaard huidskleur kiezen",
+ "aria/Clear emoji search": "Emoji zoekopdracht wissen",
"aria/Clear search": "Zoekopdracht wissen",
"aria/Close callout dialog": "Calloutdialoog sluiten",
"aria/Close thread": "Draad sluiten",
@@ -270,6 +276,8 @@
"Create a question, add options, and configure poll settings": "Maak een vraag, voeg opties toe en stel de pollinstellingen in",
"Create poll": "Maak peiling",
"Current location": "Huidige locatie",
+ "Dark": "Donker",
+ "Default": "Standaard",
"Delete": "Verwijder",
"Delete chat": "Chat verwijderen",
"Delete for me": "Voor mij verwijderen",
@@ -340,6 +348,7 @@
"Failed to jump to the first unread message": "Niet gelukt om naar het eerste ongelezen bericht te springen",
"Failed to leave channel": "Kanaal verlaten mislukt",
"Failed to load channels": "Kanalen konden niet worden geladen",
+ "Failed to load emojis": "Emoji's konden niet worden geladen",
"Failed to load more channels": "Meer kanalen konden niet worden geladen",
"Failed to mark channel as read": "Kanaal kon niet als gelezen worden gemarkeerd",
"Failed to play the recording": "Kan de opname niet afspelen",
@@ -357,6 +366,9 @@
"fileCount_other": "{{ count }} bestanden",
"Files": "Bestanden",
"Flag": "Markeer",
+ "Flags": "Vlaggen",
+ "Food & Drink": "Eten en drinken",
+ "Frequently used": "Veelgebruikt",
"Generating...": "Genereren...",
"giphy-command-args": "[tekst]",
"giphy-command-description": "Plaats een willekeurige gif in het kanaal",
@@ -430,6 +442,7 @@
"Leave chat": "Kanaal verlaten",
"Left channel": "Kanaal verlaten",
"Let others add options": "Laat anderen opties toevoegen",
+ "Light": "Licht",
"Limit votes per person": "Stemmen per persoon beperken",
"Link": "Link",
"linkCount_one": "Link",
@@ -448,6 +461,9 @@
"Mark as unread": "Markeren als ongelezen",
"Maximum number of votes (from 2 to 10)": "Maximaal aantal stemmen (van 2 tot 10)",
"Maximum votes per person": "Maximum aantal stemmen per persoon",
+ "Medium": "Middel",
+ "Medium-Dark": "Middeldonker",
+ "Medium-Light": "Middellicht",
"Member detail": "Lidgegevens",
"mention/Channel": "Kanaal",
"mention/Channel Description": "Iedereen in dit kanaal informeren",
@@ -478,6 +494,7 @@
"Next image": "Volgende afbeelding",
"No chats here yet…": "Nog geen chats hier...",
"No conversations yet": "Nog geen gesprekken",
+ "No emoji found": "Geen emoji gevonden",
"No files": "Geen bestanden",
"No items exist": "Er zijn geen items",
"No member found": "Geen lid gevonden",
@@ -489,6 +506,7 @@
"Nobody will be able to vote in this poll anymore.": "Niemand kan meer stemmen in deze peiling.",
"Nothing yet...": "Nog niets ...",
"Notify all {{ role }} members": "Alle leden met rol {{ role }} informeren",
+ "Objects": "Objecten",
"Offline": "Offline",
"Ok": "Oké",
"Online": "Online",
@@ -508,6 +526,7 @@
"People matching": "Mensen die matchen",
"Photo": "Foto",
"Photos & videos": "Foto's en video's",
+ "Pick an emoji…": "Kies een emoji…",
"Pin": "Vastmaken",
"Pin a message to see it here": "Maak een bericht vast om het hier te zien",
"Pinned by {{ name }}": "Vastgemaakt door {{ name }}",
@@ -553,6 +572,7 @@
"replyCount_one": "1 antwoord",
"replyCount_other": "{{ count }} antwoorden",
"Resend": "Opnieuw verzenden",
+ "Retry": "Opnieuw proberen",
"Retry upload": "Upload opnieuw proberen",
"Review all options available in this poll": "Bekijk alle beschikbare opties in deze poll",
"Review comments submitted with poll answers": "Bekijk reacties die met pollantwoorden zijn ingediend",
@@ -563,6 +583,7 @@
"Save for later": "Bewaren voor later",
"Saved for later": "Bewaard voor later",
"Search": "Zoeken",
+ "Search emoji": "Emoji zoeken",
"Search GIFs": "GIF's zoeken",
"search-results-header-filter-source-button-label--channels": "kanalen",
"search-results-header-filter-source-button-label--messages": "berichten",
@@ -600,12 +621,14 @@
"Slow mode, wait {{ seconds }}s...": "Langzame modus, wacht {{ seconds }}s...",
"Slow wait, wait {{ seconds }}s": "Langzame modus, wacht {{ seconds }}s",
"Slow wait, wait {{ seconds }}s...": "Langzame modus, wacht {{ seconds }}s...",
+ "Smileys & People": "Smileys en mensen",
"Some of the files will not be accepted": "Sommige bestanden zullen niet worden geaccepteerd",
"Start typing to search": "Begin met typen om te zoeken",
"Stop sharing": "Delen stoppen",
"Submit": "Versturen",
"Suggest a new option to add to this poll": "Stel een nieuwe optie voor om aan deze poll toe te voegen",
"Suggest an option": "Stel een optie voor",
+ "Symbols": "Symbolen",
"Tap to remove": "Tik om te verwijderen",
"Tap to remove: {{ reactionName }}": "Tik om te verwijderen: {{ reactionName }}",
"Thinking...": "Denken...",
@@ -644,6 +667,7 @@
"Translated": "Vertaald",
"Translated from {{ language }}": "Vertaald uit {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Reizen en plaatsen",
"Type a number from 2 to 10": "Typ een getal van 2 tot 10",
"Unarchive": "Uit archief halen",
"unban-command-args": "[@gebruikersnaam]",
diff --git a/src/i18n/pt.json b/src/i18n/pt.json
index 5cff8a41a..e1803f46c 100644
--- a/src/i18n/pt.json
+++ b/src/i18n/pt.json
@@ -53,6 +53,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} votou: {{pollOptionText}}",
"📍Shared location": "📍Localização compartilhada",
"Actions": "Actions",
+ "Activities": "Atividades",
"Add": "Adicionar",
"Add {{ count }} members_one": "Adicionar {{ count }} membro",
"Add {{ count }} members_many": "Adicionar {{ count }} membros",
@@ -76,6 +77,7 @@
"Also sent in channel": "Também enviado no canal",
"An error has occurred during recording": "Ocorreu um erro durante a gravação",
"An error has occurred during the recording processing": "Ocorreu um erro durante o processamento da gravação",
+ "Animals & Nature": "Animais e natureza",
"Anonymous": "Anônimo",
"Anonymous poll": "Enquete anônima",
"Archive": "Arquivar",
@@ -116,8 +118,12 @@
"aria/Channel Actions": "Ações do canal",
"aria/Channel details": "Detalhes do canal",
"aria/Channel list": "Lista de canais",
+ "aria/Channel search results": "Resultados de pesquisa de canais",
"aria/Chat view controls": "Controles da visualização do chat",
+ "aria/Chat view tabs": "Abas da visualização do chat",
"aria/Chat: {{ channelName }}": "Chat: {{ channelName }}",
+ "aria/Choose default skin tone": "Escolher tom de pele padrão",
+ "aria/Clear emoji search": "Limpar pesquisa de emoji",
"aria/Clear search": "Limpar pesquisa",
"aria/Close callout dialog": "Fechar diálogo de destaque",
"aria/Close thread": "Fechar tópico",
@@ -287,6 +293,8 @@
"Create a question, add options, and configure poll settings": "Crie uma pergunta, adicione opções e configure as definições da enquete",
"Create poll": "Criar enquete",
"Current location": "Localização atual",
+ "Dark": "Escuro",
+ "Default": "Padrão",
"Delete": "Excluir",
"Delete chat": "Excluir chat",
"Delete for me": "Excluir para mim",
@@ -357,6 +365,7 @@
"Failed to jump to the first unread message": "Falha ao pular para a primeira mensagem não lida",
"Failed to leave channel": "Falha ao sair do canal",
"Failed to load channels": "Falha ao carregar os canais",
+ "Failed to load emojis": "Falha ao carregar os emojis",
"Failed to load more channels": "Falha ao carregar mais canais",
"Failed to mark channel as read": "Falha ao marcar o canal como lido",
"Failed to play the recording": "Falha ao reproduzir a gravação",
@@ -375,6 +384,9 @@
"fileCount_other": "{{ count }} arquivos",
"Files": "Arquivos",
"Flag": "Reportar",
+ "Flags": "Bandeiras",
+ "Food & Drink": "Comida e bebida",
+ "Frequently used": "Usados com frequência",
"Generating...": "Gerando...",
"giphy-command-args": "[texto]",
"giphy-command-description": "Postar um gif aleatório no canal",
@@ -449,6 +461,7 @@
"Leave chat": "Sair do canal",
"Left channel": "Canal abandonado",
"Let others add options": "Permitir que outros adicionem opções",
+ "Light": "Claro",
"Limit votes per person": "Limitar votos por pessoa",
"Link": "Link",
"linkCount_one": "Link",
@@ -468,6 +481,9 @@
"Mark as unread": "Marcar como não lida",
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
"Maximum votes per person": "Máximo de votos por pessoa",
+ "Medium": "Médio",
+ "Medium-Dark": "Médio escuro",
+ "Medium-Light": "Médio claro",
"Member detail": "Detalhes do membro",
"mention/Channel": "Canal",
"mention/Channel Description": "Notificar todos neste canal",
@@ -498,6 +514,7 @@
"Next image": "Próxima imagem",
"No chats here yet…": "Ainda não há conversas aqui...",
"No conversations yet": "Ainda não há conversas",
+ "No emoji found": "Nenhum emoji encontrado",
"No files": "Nenhum arquivo",
"No items exist": "Não existem itens",
"No member found": "Nenhum membro encontrado",
@@ -509,6 +526,7 @@
"Nobody will be able to vote in this poll anymore.": "Ninguém mais poderá votar nesta pesquisa.",
"Nothing yet...": "Nada ainda...",
"Notify all {{ role }} members": "Notificar todos os membros com a função {{ role }}",
+ "Objects": "Objetos",
"Offline": "Offline",
"Ok": "OK",
"Online": "Online",
@@ -528,6 +546,7 @@
"People matching": "Pessoas correspondentes",
"Photo": "Foto",
"Photos & videos": "Fotos e vídeos",
+ "Pick an emoji…": "Escolha um emoji…",
"Pin": "Fixar",
"Pin a message to see it here": "Fixe uma mensagem para vê-la aqui",
"Pinned by {{ name }}": "Fixado por {{ name }}",
@@ -576,6 +595,7 @@
"replyCount_many": "{{ count }} respostas",
"replyCount_other": "{{ count }} respostas",
"Resend": "Reenviar",
+ "Retry": "Tentar novamente",
"Retry upload": "Tentar enviar novamente",
"Review all options available in this poll": "Revise todas as opções disponíveis nesta enquete",
"Review comments submitted with poll answers": "Revise comentários enviados com respostas da enquete",
@@ -586,6 +606,7 @@
"Save for later": "Salvar para depois",
"Saved for later": "Salvo para depois",
"Search": "Buscar",
+ "Search emoji": "Pesquisar emoji",
"Search GIFs": "Pesquisar GIFs",
"search-results-header-filter-source-button-label--channels": "canais",
"search-results-header-filter-source-button-label--messages": "mensagens",
@@ -623,12 +644,14 @@
"size limit": "limite de tamanho",
"Slow Mode ON": "Modo lento LIGADO",
"Slow mode, wait {{ seconds }}s...": "Modo lento, aguarde {{ seconds }} s...",
+ "Smileys & People": "Smileys e pessoas",
"Some of the files will not be accepted": "Alguns arquivos não serão aceitos",
"Start typing to search": "Comece a digitar para pesquisar",
"Stop sharing": "Parar de compartilhar",
"Submit": "Enviar",
"Suggest a new option to add to this poll": "Sugira uma nova opção para adicionar a esta enquete",
"Suggest an option": "Sugerir uma opção",
+ "Symbols": "Símbolos",
"Tap to remove": "Toque para remover",
"Tap to remove: {{ reactionName }}": "Toque para remover: {{ reactionName }}",
"Thinking...": "Pensando...",
@@ -669,6 +692,7 @@
"Translated": "Traduzido",
"Translated from {{ language }}": "Traduzido de {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Viagens e lugares",
"Type a number from 2 to 10": "Digite um número de 2 a 10",
"Unarchive": "Desarquivar",
"unban-command-args": "[@nomedeusuário]",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index f13f1c58f..8f76b9a8a 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -64,6 +64,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} проголосовал(а): {{pollOptionText}}",
"📍Shared location": "📍Общее местоположение",
"Actions": "Actions",
+ "Activities": "Активности",
"Add": "Добавить",
"Add {{ count }} members_one": "Добавить {{ count }} участника",
"Add {{ count }} members_few": "Добавить {{ count }} участников",
@@ -88,6 +89,7 @@
"Also sent in channel": "Также отправлено в канал",
"An error has occurred during recording": "Произошла ошибка во время записи",
"An error has occurred during the recording processing": "Произошла ошибка во время обработки записи",
+ "Animals & Nature": "Животные и природа",
"Anonymous": "Аноним",
"Anonymous poll": "Анонимный опрос",
"Archive": "Aрхивировать",
@@ -133,8 +135,12 @@
"aria/Channel Actions": "Действия канала",
"aria/Channel details": "Сведения о канале",
"aria/Channel list": "Список каналов",
+ "aria/Channel search results": "Результаты поиска по каналам",
"aria/Chat view controls": "Элементы управления видом чата",
+ "aria/Chat view tabs": "Вкладки вида чата",
"aria/Chat: {{ channelName }}": "Чат: {{ channelName }}",
+ "aria/Choose default skin tone": "Выбрать тон кожи по умолчанию",
+ "aria/Clear emoji search": "Очистить поиск эмодзи",
"aria/Clear search": "Очистить поиск",
"aria/Close callout dialog": "Закрыть диалог выноски",
"aria/Close thread": "Закрыть тему",
@@ -305,6 +311,8 @@
"Create a question, add options, and configure poll settings": "Создайте вопрос, добавьте варианты и настройте параметры опроса",
"Create poll": "Создать опрос",
"Current location": "Текущее местоположение",
+ "Dark": "Тёмный",
+ "Default": "По умолчанию",
"Delete": "Удалить",
"Delete chat": "Удалить чат",
"Delete for me": "Удалить для меня",
@@ -375,6 +383,7 @@
"Failed to jump to the first unread message": "Не удалось перейти к первому непрочитанному сообщению",
"Failed to leave channel": "Не удалось покинуть канал",
"Failed to load channels": "Не удалось загрузить каналы",
+ "Failed to load emojis": "Не удалось загрузить эмодзи",
"Failed to load more channels": "Не удалось загрузить больше каналов",
"Failed to mark channel as read": "Не удалось пометить канал как прочитанный",
"Failed to play the recording": "Не удалось воспроизвести запись",
@@ -397,6 +406,9 @@
"fileCount_three": "{{ count }} файла",
"Files": "Файлы",
"Flag": "Пожаловаться",
+ "Flags": "Флаги",
+ "Food & Drink": "Еда и напитки",
+ "Frequently used": "Часто используемые",
"Generating...": "Генерирую...",
"giphy-command-args": "[текст]",
"giphy-command-description": "Опубликовать случайную GIF-анимацию в канале",
@@ -472,6 +484,7 @@
"Leave chat": "Покинуть канал",
"Left channel": "Канал покинут",
"Let others add options": "Разрешить другим добавлять варианты",
+ "Light": "Светлый",
"Limit votes per person": "Ограничить голоса на человека",
"Link": "Линк",
"linkCount_one": "{{ count }} линк",
@@ -492,6 +505,9 @@
"Mark as unread": "Отметить как непрочитанное",
"Maximum number of votes (from 2 to 10)": "Максимальное количество голосов (от 2 до 10)",
"Maximum votes per person": "Максимум голосов на человека",
+ "Medium": "Средний",
+ "Medium-Dark": "Умеренно-тёмный",
+ "Medium-Light": "Умеренно-светлый",
"Member detail": "Сведения об участнике",
"mention/Channel": "Канал",
"mention/Channel Description": "Уведомить всех в этом канале",
@@ -522,6 +538,7 @@
"Next image": "Следующее изображение",
"No chats here yet…": "Здесь еще нет чатов...",
"No conversations yet": "Пока нет бесед",
+ "No emoji found": "Эмодзи не найдены",
"No files": "Нет файлов",
"No items exist": "Элементов нет",
"No member found": "Участник не найден",
@@ -533,6 +550,7 @@
"Nobody will be able to vote in this poll anymore.": "Никто больше не сможет голосовать в этом опросе.",
"Nothing yet...": "Пока ничего нет...",
"Notify all {{ role }} members": "Уведомить всех участников с ролью {{ role }}",
+ "Objects": "Объекты",
"Offline": "Не в сети",
"Ok": "Ок",
"Online": "В сети",
@@ -552,6 +570,7 @@
"People matching": "Совпадающие люди",
"Photo": "Фото",
"Photos & videos": "Фото и видео",
+ "Pick an emoji…": "Выберите эмодзи…",
"Pin": "Закрепить",
"Pin a message to see it here": "Закрепите сообщение, чтобы увидеть его здесь",
"Pinned by {{ name }}": "Закреплено: {{ name }}",
@@ -603,6 +622,7 @@
"replyCount_many": "{{ count }} ответов",
"replyCount_other": "{{ count }} ответов",
"Resend": "Отправить повторно",
+ "Retry": "Повторить",
"Retry upload": "Повторить загрузку",
"Review all options available in this poll": "Просмотрите все варианты, доступные в этом опросе",
"Review comments submitted with poll answers": "Просмотрите комментарии, отправленные вместе с ответами в опросе",
@@ -613,6 +633,7 @@
"Save for later": "Сохранить на потом",
"Saved for later": "Сохранено на потом",
"Search": "Поиск",
+ "Search emoji": "Поиск эмодзи",
"Search GIFs": "Поиск GIF",
"search-results-header-filter-source-button-label--channels": "каналы",
"search-results-header-filter-source-button-label--messages": "сообщения",
@@ -652,12 +673,14 @@
"size limit": "ограничение размера",
"Slow Mode ON": "Медленный режим включен",
"Slow mode, wait {{ seconds }}s...": "Медленный режим: подождите {{ seconds }} с...",
+ "Smileys & People": "Смайлики и люди",
"Some of the files will not be accepted": "Некоторые файлы не будут приняты",
"Start typing to search": "Начните вводить для поиска",
"Stop sharing": "Прекратить делиться",
"Submit": "Отправить",
"Suggest a new option to add to this poll": "Предложите новый вариант для добавления в этот опрос",
"Suggest an option": "Предложить вариант",
+ "Symbols": "Символы",
"Tap to remove": "Нажмите, чтобы удалить",
"Tap to remove: {{ reactionName }}": "Нажмите, чтобы удалить: {{ reactionName }}",
"Thinking...": "Думаю...",
@@ -700,6 +723,7 @@
"Translated": "Переведено",
"Translated from {{ language }}": "Переведено с {{ language }}",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Путешествия и места",
"Type a number from 2 to 10": "Введите число от 2 до 10",
"Unarchive": "Удалить из архива",
"unban-command-args": "[@имяпользователя]",
diff --git a/src/i18n/tr.json b/src/i18n/tr.json
index 962b95ad4..46b53593c 100644
--- a/src/i18n/tr.json
+++ b/src/i18n/tr.json
@@ -43,6 +43,7 @@
"📊 {{votedBy}} voted: {{pollOptionText}}": "📊 {{votedBy}} oy verdi: {{pollOptionText}}",
"📍Shared location": "📍Paylaşılan konum",
"Actions": "Actions",
+ "Activities": "Etkinlikler",
"Add": "Ekle",
"Add {{ count }} members_one": "{{ count }} üye ekle",
"Add {{ count }} members_other": "{{ count }} üye ekle",
@@ -65,6 +66,7 @@
"Also sent in channel": "Kanala da gönderildi",
"An error has occurred during recording": "Kayıt sırasında bir hata oluştu",
"An error has occurred during the recording processing": "Kayıt işlemi sırasında bir hata oluştu",
+ "Animals & Nature": "Hayvanlar ve Doğa",
"Anonymous": "Anonim",
"Anonymous poll": "Anonim anket",
"Archive": "Arşivle",
@@ -100,8 +102,12 @@
"aria/Channel Actions": "Kanal işlemleri",
"aria/Channel details": "Kanal ayrıntıları",
"aria/Channel list": "Kanal listesi",
+ "aria/Channel search results": "Kanal arama sonuçları",
"aria/Chat view controls": "Sohbet görünümü kontrolleri",
+ "aria/Chat view tabs": "Sohbet görünümü sekmeleri",
"aria/Chat: {{ channelName }}": "Sohbet: {{ channelName }}",
+ "aria/Choose default skin tone": "Varsayılan ten rengini seç",
+ "aria/Clear emoji search": "Emoji aramasını temizle",
"aria/Clear search": "Aramayı temizle",
"aria/Close callout dialog": "Bilgi balonu iletişim kutusunu kapat",
"aria/Close thread": "Konuyu kapat",
@@ -270,6 +276,8 @@
"Create a question, add options, and configure poll settings": "Bir soru oluşturun, seçenekler ekleyin ve anket ayarlarını yapılandırın",
"Create poll": "Anket oluştur",
"Current location": "Mevcut konum",
+ "Dark": "Koyu",
+ "Default": "Varsayılan",
"Delete": "Sil",
"Delete chat": "Sohbeti sil",
"Delete for me": "Benim için sil",
@@ -340,6 +348,7 @@
"Failed to jump to the first unread message": "İlk okunmamış mesaja atlamada hata oluştu",
"Failed to leave channel": "Kanaldan çıkılamadı",
"Failed to load channels": "Kanallar yüklenemedi",
+ "Failed to load emojis": "Emojiler yüklenemedi",
"Failed to load more channels": "Daha fazla kanal yüklenemedi",
"Failed to mark channel as read": "Kanalı okundu olarak işaretleme başarısız oldu",
"Failed to play the recording": "Kayıt oynatılamadı",
@@ -357,6 +366,9 @@
"fileCount_other": "{{ count }} dosya",
"Files": "Dosyalar",
"Flag": "Bayrak",
+ "Flags": "Bayraklar",
+ "Food & Drink": "Yiyecek ve İçecek",
+ "Frequently used": "Sık kullanılanlar",
"Generating...": "Oluşturuluyor...",
"giphy-command-args": "[metin]",
"giphy-command-description": "Rastgele bir gif'i kanala gönder",
@@ -430,6 +442,7 @@
"Leave chat": "Kanaldan ayrıl",
"Left channel": "Kanaldan ayrıldınız",
"Let others add options": "Başkalarının seçenek eklemesine izin ver",
+ "Light": "Açık",
"Limit votes per person": "Kişi başına oy sınırı",
"Link": "Bağlantı",
"linkCount_one": "Bağlantı",
@@ -448,6 +461,9 @@
"Mark as unread": "Okunmamış olarak işaretle",
"Maximum number of votes (from 2 to 10)": "Maksimum oy sayısı (2 ile 10 arası)",
"Maximum votes per person": "Kişi başına maksimum oy",
+ "Medium": "Orta",
+ "Medium-Dark": "Orta koyu",
+ "Medium-Light": "Orta açık",
"Member detail": "Üye detayı",
"mention/Channel": "Kanal",
"mention/Channel Description": "Bu kanaldaki herkesi bildir",
@@ -478,6 +494,7 @@
"Next image": "Sonraki görsel",
"No chats here yet…": "Henüz burada sohbet yok...",
"No conversations yet": "Henüz konuşma yok",
+ "No emoji found": "Emoji bulunamadı",
"No files": "Dosya yok",
"No items exist": "Hiç öğe yok",
"No member found": "Üye bulunamadı",
@@ -489,6 +506,7 @@
"Nobody will be able to vote in this poll anymore.": "Artık bu ankette kimse oy kullanamayacak.",
"Nothing yet...": "Şimdilik hiçbir şey...",
"Notify all {{ role }} members": "{{ role }} rolündeki tüm üyelere bildir",
+ "Objects": "Nesneler",
"Offline": "Çevrimdışı",
"Ok": "Tamam",
"Online": "Çevrimiçi",
@@ -508,6 +526,7 @@
"People matching": "Eşleşen kişiler",
"Photo": "Fotoğraf",
"Photos & videos": "Fotoğraflar ve videolar",
+ "Pick an emoji…": "Emoji seç…",
"Pin": "Sabitle",
"Pin a message to see it here": "Burada görmek için bir mesaj sabitle",
"Pinned by {{ name }}": "{{ name }} sabitledi",
@@ -553,6 +572,7 @@
"replyCount_one": "1 cevap",
"replyCount_other": "{{ count }} cevap",
"Resend": "Tekrar gönder",
+ "Retry": "Yeniden dene",
"Retry upload": "Yüklemeyi yeniden dene",
"Review all options available in this poll": "Bu anketteki tüm mevcut seçenekleri inceleyin",
"Review comments submitted with poll answers": "Anket yanıtlarıyla gönderilen yorumları inceleyin",
@@ -563,6 +583,7 @@
"Save for later": "Daha sonra kaydet",
"Saved for later": "Daha sonra kaydedildi",
"Search": "Arama",
+ "Search emoji": "Emoji ara",
"Search GIFs": "GIF ara",
"search-results-header-filter-source-button-label--channels": "kanallar",
"search-results-header-filter-source-button-label--messages": "mesajlar",
@@ -598,12 +619,14 @@
"size limit": "boyut sınırı",
"Slow Mode ON": "Yavaş Mod Açık",
"Slow mode, wait {{ seconds }}s...": "Yavaş mod, {{ seconds }} sn bekleyin...",
+ "Smileys & People": "Suratlar ve İnsanlar",
"Some of the files will not be accepted": "Bazı dosyalar kabul edilmeyecek",
"Start typing to search": "Aramak için yazmaya başlayın",
"Stop sharing": "Paylaşımı durdur",
"Submit": "Gönder",
"Suggest a new option to add to this poll": "Bu ankete eklenecek yeni bir seçenek önerin",
"Suggest an option": "Bir seçenek önerin",
+ "Symbols": "Semboller",
"Tap to remove": "Kaldırmak için dokunun",
"Tap to remove: {{ reactionName }}": "Kaldırmak için dokunun: {{ reactionName }}",
"Thinking...": "Düşünüyor...",
@@ -642,6 +665,7 @@
"Translated": "Çevrildi",
"Translated from {{ language }}": "{{ language }} dilinden çevrildi",
"translationBuilderTopic/notification": "{{value, notification}}",
+ "Travel & Places": "Seyahat ve Yerler",
"Type a number from 2 to 10": "2 ile 10 arasında bir sayı yazın",
"Unarchive": "Arşivden çıkar",
"unban-command-args": "[@kullanıcıadı]",
diff --git a/src/plugins/Emojis/EmojiPicker.tsx b/src/plugins/Emojis/EmojiPicker.tsx
index 4972da647..b9f6931c8 100644
--- a/src/plugins/Emojis/EmojiPicker.tsx
+++ b/src/plugins/Emojis/EmojiPicker.tsx
@@ -21,6 +21,9 @@ const Picker =
const isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;
+// Warn at most once per session that this engine is going away.
+let hasWarnedEmojiMartDeprecation = false;
+
export type EmojiPickerProps = {
ButtonIconComponent?: React.ComponentType;
buttonClassName?: string;
@@ -28,8 +31,8 @@ export type EmojiPickerProps = {
wrapperClassName?: string;
closeOnEmojiSelect?: boolean;
/**
- * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.5.2#options--props) to be
- * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.5.2#-picker) component
+ * Untyped [properties](https://github.com/missive/emoji-mart/tree/v5.6.0#options--props) to be
+ * passed down to the [emoji-mart `Picker`](https://github.com/missive/emoji-mart/tree/v5.6.0#-picker) component
*/
pickerProps?: Partial<{ theme: 'auto' | 'light' | 'dark' } & Record>;
/**
@@ -48,6 +51,11 @@ const classNames: Pick<
wrapperClassName: 'str-chat__message-textarea-emoji-picker',
};
+/**
+ * @deprecated The emoji-mart-based `EmojiPicker` will be removed in v15. Switch to
+ * `StreamEmojiPicker` from `stream-chat-react/emojis`, which needs no emoji-mart
+ * packages. See the emoji section of `AI.md` for migration notes.
+ */
export const EmojiPicker = (props: EmojiPickerProps) => {
const { t } = useTranslationContext('EmojiPicker');
const { textareaRef } = useMessageComposerContext('EmojiPicker');
@@ -63,6 +71,15 @@ export const EmojiPicker = (props: EmojiPickerProps) => {
placement: props.placement ?? 'top-end',
});
+ useEffect(() => {
+ if (hasWarnedEmojiMartDeprecation) return;
+ hasWarnedEmojiMartDeprecation = true;
+ console.warn(
+ '[stream-chat-react] The `emoji-mart`-based `EmojiPicker` is deprecated and will be removed in the next major version. ' +
+ 'Switch to `StreamEmojiPicker` from `stream-chat-react/emojis` as it offers the same functionality without 3rd party dependencies.',
+ );
+ }, []);
+
useEffect(() => {
refs.setReference(referenceElement);
}, [referenceElement, refs]);
diff --git a/src/plugins/Emojis/StreamEmojiPicker.tsx b/src/plugins/Emojis/StreamEmojiPicker.tsx
new file mode 100644
index 000000000..61e250e25
--- /dev/null
+++ b/src/plugins/Emojis/StreamEmojiPicker.tsx
@@ -0,0 +1,205 @@
+import React, { useEffect, useRef, useState } from 'react';
+
+import { useMessageComposerContext, useTranslationContext } from '../../context';
+import {
+ Button,
+ IconEmoji,
+ type PopperLikePlacement,
+ useMessageComposerController,
+} from '../../components';
+import { usePopoverPosition } from '../../components/Dialog/hooks/usePopoverPosition';
+import { useIsCooldownActive } from '../../components/MessageComposer/hooks/useIsCooldownActive';
+import { EmojiPickerPanel } from './components';
+import { useFrequentlyUsedEmoji } from './hooks/useFrequentlyUsedEmoji';
+import { useSkinTone } from './hooks/useSkinTone';
+import {
+ type EmojiPickerPassthroughProps,
+ resolveEmojiPickerOptions,
+ warnUnsupportedPickerProps,
+} from './options';
+
+const isShadowRoot = (node: Node): node is ShadowRoot => !!(node as ShadowRoot).host;
+
+export type {
+ EmojiPickerNavPosition,
+ EmojiPickerPassthroughProps,
+ EmojiPickerPreviewPosition,
+ EmojiPickerSearchPosition,
+ EmojiPickerSkinTonePosition,
+} from './options';
+
+export type StreamEmojiPickerProps = {
+ ButtonIconComponent?: React.ComponentType;
+ buttonClassName?: string;
+ pickerContainerClassName?: string;
+ wrapperClassName?: string;
+ closeOnEmojiSelect?: boolean;
+ /**
+ * Presentation + curated layout/behavior options for the picker panel, using
+ * emoji-mart-compatible names (`theme`, `style`, `perLine`, `navPosition`,
+ * `previewPosition`, `searchPosition`, `skinTonePosition`, `categories`,
+ * `exceptEmojis`, `emojiVersion`, `maxFrequentRows`, `noCountryFlags`,
+ * `previewEmoji`, `noResultsEmoji`, `autoFocus`, `onClickOutside`).
+ *
+ * Not every emoji-mart `Picker` option is supported: image sets (`set`,
+ * `getSpritesheetURL`), `custom` emoji, `data`, `i18n`/`locale`, `dynamicWidth`,
+ * `icons`, and `categoryIcons` are rejected by the type and ignored (with a console
+ * warning) at runtime; sizing knobs (`emojiSize`, …) are CSS tokens instead. See the
+ * emoji migration notes in `AI.md`.
+ */
+ pickerProps?: EmojiPickerPassthroughProps;
+ /**
+ * Floating UI placement (default: 'top-end') for the picker popover
+ */
+ placement?: PopperLikePlacement;
+ /** Uncontrolled initial skin tone index (0 = default, 1–5 = light → dark). */
+ defaultSkinTone?: number;
+ /**
+ * Controlled ordered list of recently used emoji ids (most recent first). The SDK
+ * does not persist this — provide it (and `onFrequentlyUsedChange`) to control the
+ * "frequently used" section; otherwise it is tracked in memory for the session.
+ */
+ frequentlyUsedEmoji?: string[];
+ /** Called with the updated recently-used list when an emoji is selected. */
+ onFrequentlyUsedChange?: (emojiIds: string[]) => void;
+ /** Called with the new skin tone index when it changes. */
+ onSkinToneChange?: (skinTone: number) => void;
+ /** Controlled skin tone index (0 = default, 1–5 = light → dark). */
+ skinTone?: number;
+};
+
+const defaultButtonClassName = 'str-chat__emoji-picker-button';
+
+const classNames: Pick<
+ StreamEmojiPickerProps,
+ 'pickerContainerClassName' | 'wrapperClassName'
+> = {
+ pickerContainerClassName: 'str-chat__message-textarea-emoji-picker-container',
+ wrapperClassName: 'str-chat__message-textarea-emoji-picker',
+};
+
+export const StreamEmojiPicker = (props: StreamEmojiPickerProps) => {
+ const { t } = useTranslationContext('EmojiPicker');
+ const { textareaRef } = useMessageComposerContext('EmojiPicker');
+ const { textComposer } = useMessageComposerController();
+ const isCooldownActive = useIsCooldownActive();
+ // Skin tone and frequently-used live here (not in the panel) so they survive the
+ // picker opening/closing — the panel below is mounted only while open.
+ const [skinTone, setSkinTone] = useSkinTone({
+ defaultSkinTone: props.defaultSkinTone,
+ onSkinToneChange: props.onSkinToneChange,
+ skinTone: props.skinTone,
+ });
+ const { frequentlyUsedIds, recordUse } = useFrequentlyUsedEmoji({
+ frequentlyUsedEmoji: props.frequentlyUsedEmoji,
+ onFrequentlyUsedChange: props.onFrequentlyUsedChange,
+ });
+ const [displayPicker, setDisplayPicker] = useState(false);
+ const [referenceElement, setReferenceElement] = useState(
+ null,
+ );
+ const [popperElement, setPopperElement] = useState(null);
+ const { refs, strategy, x, y } = usePopoverPosition({
+ offset: 8,
+ placement: props.placement ?? 'top-end',
+ });
+
+ useEffect(() => {
+ refs.setReference(referenceElement);
+ }, [referenceElement, refs]);
+ useEffect(() => {
+ refs.setFloating(popperElement);
+ }, [popperElement, refs]);
+
+ const { pickerContainerClassName, wrapperClassName } = classNames;
+
+ const { ButtonIconComponent = IconEmoji } = props;
+ const pickerStyle = props.pickerProps?.style;
+ const options = resolveEmojiPickerOptions(props.pickerProps);
+ // Latest-ref so the click-outside listener isn't re-attached when the callback identity
+ // changes between renders.
+ const onClickOutsideRef = useRef(props.pickerProps?.onClickOutside);
+ onClickOutsideRef.current = props.pickerProps?.onClickOutside;
+
+ const pickerPropsKeys = Object.keys(props.pickerProps ?? {});
+ useEffect(() => {
+ warnUnsupportedPickerProps(props.pickerProps);
+ // Re-check only when the set of provided keys changes.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [pickerPropsKeys.join(',')]);
+
+ useEffect(() => {
+ if (!popperElement || !referenceElement) return;
+
+ const handlePointerDown = (e: PointerEvent) => {
+ const target = e.target as HTMLElement;
+
+ const rootNode = target.getRootNode();
+
+ if (
+ popperElement.contains(isShadowRoot(rootNode) ? rootNode.host : target) ||
+ referenceElement.contains(target)
+ ) {
+ return;
+ }
+
+ onClickOutsideRef.current?.();
+ setDisplayPicker(false);
+ };
+
+ window.addEventListener('pointerdown', handlePointerDown);
+ return () => window.removeEventListener('pointerdown', handlePointerDown);
+ }, [referenceElement, popperElement]);
+
+ return (
+
+ {displayPicker && (
+
+ {
+ setDisplayPicker(false);
+ referenceElement?.focus();
+ }}
+ onEmojiSelect={(emoji) => {
+ const textarea = textareaRef.current;
+ if (!textarea) return;
+ // Record only once we know the emoji is actually being inserted.
+ recordUse(emoji.id);
+ textComposer.insertText({ text: emoji.native });
+ textarea.focus();
+ if (props.closeOnEmojiSelect) {
+ setDisplayPicker(false);
+ }
+ }}
+ onSkinToneChange={setSkinTone}
+ options={options}
+ skinToneIndex={skinTone}
+ style={pickerStyle}
+ theme={props.pickerProps?.theme}
+ />
+
+ )}
+
+
+ );
+};
diff --git a/src/plugins/Emojis/__tests__/EmojiPicker.test.tsx b/src/plugins/Emojis/__tests__/EmojiPicker.test.tsx
new file mode 100644
index 000000000..85e7088cc
--- /dev/null
+++ b/src/plugins/Emojis/__tests__/EmojiPicker.test.tsx
@@ -0,0 +1,86 @@
+import type { MouseEventHandler, ReactNode } from 'react';
+import { fireEvent, render, screen } from '@testing-library/react';
+
+// Mock emoji-mart's Picker so jsdom doesn't render the real web component.
+vi.mock('@emoji-mart/react', () => ({
+ default: ({ onEmojiSelect }: { onEmojiSelect: (e: { native: string }) => void }) => (
+
+
+
+ ),
+}));
+vi.mock('@emoji-mart/data', () => ({ default: {} }));
+
+const { textareaRef } = vi.hoisted(() => ({
+ textareaRef: {
+ current: document.createElement('textarea') as HTMLTextAreaElement | null,
+ },
+}));
+const insertText = vi.hoisted(() => vi.fn());
+
+vi.mock('../../../context', () => ({
+ useMessageComposerContext: () => ({ textareaRef }),
+ useTranslationContext: () => ({ t: (key: string) => key }),
+}));
+vi.mock('../../../components', async () => {
+ const { forwardRef } = await import('react');
+ return {
+ Button: forwardRef>(
+ function Button(props, ref) {
+ return (
+
+ );
+ },
+ ),
+ IconEmoji: () => emoji,
+ useMessageComposerController: () => ({ textComposer: { insertText } }),
+ };
+});
+vi.mock('../../../components/Dialog/hooks/usePopoverPosition', () => ({
+ usePopoverPosition: () => ({
+ refs: { setFloating: vi.fn(), setReference: vi.fn() },
+ strategy: 'absolute',
+ x: 0,
+ y: 0,
+ }),
+}));
+vi.mock('../../../components/MessageComposer/hooks/useIsCooldownActive', () => ({
+ useIsCooldownActive: () => false,
+}));
+
+import { EmojiPicker } from '../EmojiPicker';
+
+describe('EmojiPicker (deprecated emoji-mart)', () => {
+ it('warns once about deprecation, naming the successor', () => {
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
+ const { unmount } = render();
+ expect(warn).toHaveBeenCalledTimes(1);
+ expect(warn.mock.calls[0][0]).toMatch(/deprecated/i);
+ expect(warn.mock.calls[0][0]).toMatch(/StreamEmojiPicker/);
+ expect(warn.mock.calls[0][0]).toMatch(/next major version/i);
+ unmount();
+
+ warn.mockClear();
+ render(); // module-level flag → no second warning
+ expect(warn).not.toHaveBeenCalled();
+ warn.mockRestore();
+ });
+
+ it('renders emoji-mart Picker when opened and inserts the chosen emoji', () => {
+ vi.spyOn(console, 'warn').mockImplementation(() => {});
+ render();
+ fireEvent.click(screen.getByLabelText('aria/Emoji picker'));
+ expect(screen.getByTestId('em-picker')).toBeInTheDocument();
+ fireEvent.click(screen.getByText('pick'));
+ expect(insertText).toHaveBeenCalledWith({ text: '🚀' });
+ });
+});
diff --git a/src/plugins/Emojis/__tests__/StreamEmojiPicker.test.tsx b/src/plugins/Emojis/__tests__/StreamEmojiPicker.test.tsx
new file mode 100644
index 000000000..f3c270fe4
--- /dev/null
+++ b/src/plugins/Emojis/__tests__/StreamEmojiPicker.test.tsx
@@ -0,0 +1,173 @@
+import type { AriaAttributes, MouseEventHandler, ReactNode } from 'react';
+import { fireEvent, render, screen } from '@testing-library/react';
+
+// The panel is mounted only while the picker is open, so mock it to a controllable
+// stub. This lets us assert that the owner (EmojiPicker) preserves skin tone and
+// frequently-used across open/close — without depending on the real panel's
+// virtualized grid + async data load, which don't render reliably in jsdom.
+vi.mock('../components', () => ({
+ EmojiPickerPanel: ({
+ frequentlyUsedIds = [],
+ onEmojiSelect,
+ onSkinToneChange,
+ skinToneIndex = 0,
+ }: {
+ frequentlyUsedIds?: string[];
+ onEmojiSelect: (emoji: { id: string; name: string; native: string }) => void;
+ onSkinToneChange?: (skinTone: number) => void;
+ skinToneIndex?: number;
+ }) => (
+