Skip to content

Commit 5ca145c

Browse files
authored
[AC-3103] feat: add locale (#307)
## Changes - Add `locale` to the constant state and configurations. (The `locale` will be used in sending multi-language messages.) - Use `navigator.language` as the default locale ticket: [AC-3103], [AC-3448] - [x] Update Chat SDK [AC-3103]: https://sendbird.atlassian.net/browse/AC-3103?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [AC-3448]: https://sendbird.atlassian.net/browse/AC-3448?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 3fc3551 commit 5ca145c

File tree

8 files changed

+26
-14
lines changed

8 files changed

+26
-14
lines changed

src/components/chat/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import useSendbirdStateContext from '@uikit/hooks/useSendbirdStateContext';
44

55
import { ChatContainer } from './context/ChatProvider';
66
import { ChatUI } from './ui';
7+
import { useConstantState } from '../../context/ConstantContext';
78
import { useWidgetSession, useWidgetSetting } from '../../context/WidgetSettingContext';
9+
import { useAssignGlobalFunction } from '../../hooks/useAssignGlobalFunction';
810
import useAutoDismissMobileKeyboardHandler from '../../hooks/useAutoDismissMobileKeyboardHandler';
911
import { useResetHistoryOnConnected } from '../../hooks/useResetHistoryOnConnected';
1012
import { useWidgetInactivityTimeout } from '../../hooks/useWidgetInactivityTimeout';
1113

1214
const Chat = ({ fullscreen = false }: { fullscreen?: boolean }) => {
1315
const { stores } = useSendbirdStateContext();
16+
const { locale } = useConstantState();
1417
const widgetSetting = useWidgetSetting();
1518
const widgetSession = useWidgetSession();
1619

@@ -29,6 +32,13 @@ const Chat = ({ fullscreen = false }: { fullscreen?: boolean }) => {
2932
stores.sdkStore.initialized,
3033
]);
3134

35+
// Set locale for chatbot
36+
useEffect(() => {
37+
if (locale && stores.sdkStore.initialized && stores.sdkStore.sdk) {
38+
stores.sdkStore.sdk.setLocaleForChatbot(locale);
39+
}
40+
}, [locale, stores.sdkStore.initialized, stores.sdkStore.sdk]);
41+
3242
return (
3343
<ChatContainer
3444
sdk={stores.sdkStore.sdk}
@@ -44,6 +54,7 @@ const Chat = ({ fullscreen = false }: { fullscreen?: boolean }) => {
4454
};
4555

4656
const HeadlessForHooks = ({ fullscreen }: { fullscreen: boolean }) => {
57+
useAssignGlobalFunction();
4758
useResetHistoryOnConnected();
4859
useWidgetInactivityTimeout(fullscreen);
4960
useAutoDismissMobileKeyboardHandler();

src/components/ui/WidgetButton.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,7 @@ const CloseIconWrapper = styled(IconWrapper)<IconWrapperProps>`
104104
const Icon = {
105105
Open: (props: { url?: string }) => {
106106
const { url } = props;
107-
108-
if (url) {
109-
if (url.endsWith('.svg')) {
110-
return <img src={url} alt={'widget-toggle-button'} data-svg={true} />;
111-
} else {
112-
return <img src={url} alt={'widget-toggle-button'} />;
113-
}
114-
}
115-
107+
if (url) return <img src={url} alt={'widget-toggle-button'} data-svg={url.endsWith('.svg')} />;
116108
return <BotOutlinedIcon />;
117109
},
118110
Close: () => <ChevronDownIcon />,

src/components/widget/ProviderContainer.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { generateCSSVariables } from '../../colors';
99
import { ConstantStateProvider, useConstantState } from '../../context/ConstantContext';
1010
import { useWidgetSession, useWidgetSetting, WidgetSettingProvider } from '../../context/WidgetSettingContext';
1111
import { useWidgetState, WidgetStateProvider } from '../../context/WidgetStateContext';
12-
import { useAssignGlobalFunction } from '../../hooks/useAssignGlobalFunction';
1312
import { useStyledComponentsTarget } from '../../hooks/useStyledComponentsTarget';
1413
import { getTheme } from '../../theme';
1514
import { isDashboardPreview } from '../../utils';
@@ -33,7 +32,6 @@ const SBComponent = ({ children }: { children: React.ReactElement }) => {
3332
enableHideWidgetForDeactivatedUser,
3433
} = useConstantState();
3534

36-
useAssignGlobalFunction();
3735
const { setIsVisible } = useWidgetState();
3836
const { botStyle } = useWidgetSetting();
3937
const session = useWidgetSession();

src/const.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ export interface Constant extends ConstantFeatureFlags {
164164
* @description Whether to open the widget automatically. (only works in desktop)
165165
*/
166166
autoOpen?: boolean;
167+
/**
168+
* @public
169+
* @description Sets the locale for the chatbot.
170+
*/
171+
locale?: string;
167172
/**
168173
* @public
169174
* @description Locale value to be applied to string values of message timestamp and date separator.
@@ -322,7 +327,6 @@ export const elementIds = {
322327
expandIcon: 'aichatbot-widget-expand-icon',
323328
closeIcon: 'aichatbot-widget-close-icon',
324329
refreshIcon: 'aichatbot-widget-refresh-icon',
325-
uikitModal: 'sendbird-modal-root',
326330
};
327331

328332
export const widgetServiceName = {

src/context/ConstantContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export const ConstantStateProvider = (props: PropsWithChildren<ConstantContextPr
8080
...initialState.messageInputControls,
8181
...props.messageInputControls,
8282
},
83+
locale: props.locale ?? navigator.language,
8384
dateLocale: props.dateLocale ?? initialState.dateLocale,
8485
// ----- Feature flag props ----- //
8586
autoOpen: props.autoOpen,

src/context/WidgetSettingContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const WidgetSettingProvider = ({ children }: React.PropsWithChildren) =>
4747
botStudioEditProps,
4848
autoOpen,
4949
callbacks,
50+
locale,
5051
} = useConstantState();
5152

5253
if (!appId || !botId) {
@@ -91,6 +92,7 @@ export const WidgetSettingProvider = ({ children }: React.PropsWithChildren) =>
9192
appId,
9293
botId,
9394
userId: strategy === 'manual' ? injectedUserId : cachedSession?.userId,
95+
locale,
9496
})
9597
.onError(callbacks?.onWidgetSettingFailure)
9698
.onGetBotStyle((style) => setBotStyle(style))

src/libs/api/widgetSetting.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Params = {
3030
createChannel?: boolean;
3131
userId?: string;
3232
// sessionToken?: string;
33+
locale?: string;
3334
};
3435

3536
type Response = {
@@ -59,12 +60,14 @@ export async function getWidgetSetting({
5960
createUserAndChannel,
6061
createChannel,
6162
userId,
63+
locale,
6264
}: Params): Promise<Response> {
6365
// const headers = sessionToken ? { 'Session-Key': sessionToken } : undefined;
6466
const params = asQueryParams({
6567
create_user_and_channel: asBoolString(createUserAndChannel),
6668
create_channel: asBoolString(createChannel),
6769
user_id: userId,
70+
locale,
6871
});
6972
const path = resolvePath(host, `/v3/bots/${botId}/${appId}/widget_setting?${params}`);
7073

@@ -221,7 +224,7 @@ function getParamsByStrategy(
221224
if (useCachedSession) {
222225
return { userId: params.userId };
223226
} else {
224-
return { createUserAndChannel: true };
227+
return { createUserAndChannel: true, locale: params.locale };
225228
}
226229
} else {
227230
if (useCachedSession) {

src/main.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ const WidgetApp = () => {
77
const urlParams = new URLSearchParams(window.location.search);
88
const appId = urlParams.get('app_id') ?? import.meta.env.VITE_CHAT_WIDGET_APP_ID;
99
const botId = urlParams.get('bot_id') ?? import.meta.env.VITE_CHAT_WIDGET_BOT_ID;
10+
const locale = urlParams.get('locale') ?? undefined;
1011

1112
if (!appId || !botId) {
1213
return null;
1314
}
1415

15-
return <App applicationId={appId} botId={botId} />;
16+
return <App applicationId={appId} botId={botId} locale={locale} />;
1617
};
1718

1819
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(

0 commit comments

Comments
 (0)