Skip to content

Commit

Permalink
[AC-3103] feat: add locale (#307)
Browse files Browse the repository at this point in the history
## 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
  • Loading branch information
bang9 authored Sep 11, 2024
1 parent 3fc3551 commit 5ca145c
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 14 deletions.
11 changes: 11 additions & 0 deletions src/components/chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import useSendbirdStateContext from '@uikit/hooks/useSendbirdStateContext';

import { ChatContainer } from './context/ChatProvider';
import { ChatUI } from './ui';
import { useConstantState } from '../../context/ConstantContext';
import { useWidgetSession, useWidgetSetting } from '../../context/WidgetSettingContext';
import { useAssignGlobalFunction } from '../../hooks/useAssignGlobalFunction';
import useAutoDismissMobileKeyboardHandler from '../../hooks/useAutoDismissMobileKeyboardHandler';
import { useResetHistoryOnConnected } from '../../hooks/useResetHistoryOnConnected';
import { useWidgetInactivityTimeout } from '../../hooks/useWidgetInactivityTimeout';

const Chat = ({ fullscreen = false }: { fullscreen?: boolean }) => {
const { stores } = useSendbirdStateContext();
const { locale } = useConstantState();
const widgetSetting = useWidgetSetting();
const widgetSession = useWidgetSession();

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

// Set locale for chatbot
useEffect(() => {
if (locale && stores.sdkStore.initialized && stores.sdkStore.sdk) {
stores.sdkStore.sdk.setLocaleForChatbot(locale);
}
}, [locale, stores.sdkStore.initialized, stores.sdkStore.sdk]);

return (
<ChatContainer
sdk={stores.sdkStore.sdk}
Expand All @@ -44,6 +54,7 @@ const Chat = ({ fullscreen = false }: { fullscreen?: boolean }) => {
};

const HeadlessForHooks = ({ fullscreen }: { fullscreen: boolean }) => {
useAssignGlobalFunction();
useResetHistoryOnConnected();
useWidgetInactivityTimeout(fullscreen);
useAutoDismissMobileKeyboardHandler();
Expand Down
10 changes: 1 addition & 9 deletions src/components/ui/WidgetButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,7 @@ const CloseIconWrapper = styled(IconWrapper)<IconWrapperProps>`
const Icon = {
Open: (props: { url?: string }) => {
const { url } = props;

if (url) {
if (url.endsWith('.svg')) {
return <img src={url} alt={'widget-toggle-button'} data-svg={true} />;
} else {
return <img src={url} alt={'widget-toggle-button'} />;
}
}

if (url) return <img src={url} alt={'widget-toggle-button'} data-svg={url.endsWith('.svg')} />;
return <BotOutlinedIcon />;
},
Close: () => <ChevronDownIcon />,
Expand Down
2 changes: 0 additions & 2 deletions src/components/widget/ProviderContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { generateCSSVariables } from '../../colors';
import { ConstantStateProvider, useConstantState } from '../../context/ConstantContext';
import { useWidgetSession, useWidgetSetting, WidgetSettingProvider } from '../../context/WidgetSettingContext';
import { useWidgetState, WidgetStateProvider } from '../../context/WidgetStateContext';
import { useAssignGlobalFunction } from '../../hooks/useAssignGlobalFunction';
import { useStyledComponentsTarget } from '../../hooks/useStyledComponentsTarget';
import { getTheme } from '../../theme';
import { isDashboardPreview } from '../../utils';
Expand All @@ -33,7 +32,6 @@ const SBComponent = ({ children }: { children: React.ReactElement }) => {
enableHideWidgetForDeactivatedUser,
} = useConstantState();

useAssignGlobalFunction();
const { setIsVisible } = useWidgetState();
const { botStyle } = useWidgetSetting();
const session = useWidgetSession();
Expand Down
6 changes: 5 additions & 1 deletion src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ export interface Constant extends ConstantFeatureFlags {
* @description Whether to open the widget automatically. (only works in desktop)
*/
autoOpen?: boolean;
/**
* @public
* @description Sets the locale for the chatbot.
*/
locale?: string;
/**
* @public
* @description Locale value to be applied to string values of message timestamp and date separator.
Expand Down Expand Up @@ -322,7 +327,6 @@ export const elementIds = {
expandIcon: 'aichatbot-widget-expand-icon',
closeIcon: 'aichatbot-widget-close-icon',
refreshIcon: 'aichatbot-widget-refresh-icon',
uikitModal: 'sendbird-modal-root',
};

export const widgetServiceName = {
Expand Down
1 change: 1 addition & 0 deletions src/context/ConstantContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const ConstantStateProvider = (props: PropsWithChildren<ConstantContextPr
...initialState.messageInputControls,
...props.messageInputControls,
},
locale: props.locale ?? navigator.language,
dateLocale: props.dateLocale ?? initialState.dateLocale,
// ----- Feature flag props ----- //
autoOpen: props.autoOpen,
Expand Down
2 changes: 2 additions & 0 deletions src/context/WidgetSettingContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const WidgetSettingProvider = ({ children }: React.PropsWithChildren) =>
botStudioEditProps,
autoOpen,
callbacks,
locale,
} = useConstantState();

if (!appId || !botId) {
Expand Down Expand Up @@ -91,6 +92,7 @@ export const WidgetSettingProvider = ({ children }: React.PropsWithChildren) =>
appId,
botId,
userId: strategy === 'manual' ? injectedUserId : cachedSession?.userId,
locale,
})
.onError(callbacks?.onWidgetSettingFailure)
.onGetBotStyle((style) => setBotStyle(style))
Expand Down
5 changes: 4 additions & 1 deletion src/libs/api/widgetSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Params = {
createChannel?: boolean;
userId?: string;
// sessionToken?: string;
locale?: string;
};

type Response = {
Expand Down Expand Up @@ -59,12 +60,14 @@ export async function getWidgetSetting({
createUserAndChannel,
createChannel,
userId,
locale,
}: Params): Promise<Response> {
// const headers = sessionToken ? { 'Session-Key': sessionToken } : undefined;
const params = asQueryParams({
create_user_and_channel: asBoolString(createUserAndChannel),
create_channel: asBoolString(createChannel),
user_id: userId,
locale,
});
const path = resolvePath(host, `/v3/bots/${botId}/${appId}/widget_setting?${params}`);

Expand Down Expand Up @@ -221,7 +224,7 @@ function getParamsByStrategy(
if (useCachedSession) {
return { userId: params.userId };
} else {
return { createUserAndChannel: true };
return { createUserAndChannel: true, locale: params.locale };
}
} else {
if (useCachedSession) {
Expand Down
3 changes: 2 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ const WidgetApp = () => {
const urlParams = new URLSearchParams(window.location.search);
const appId = urlParams.get('app_id') ?? import.meta.env.VITE_CHAT_WIDGET_APP_ID;
const botId = urlParams.get('bot_id') ?? import.meta.env.VITE_CHAT_WIDGET_BOT_ID;
const locale = urlParams.get('locale') ?? undefined;

if (!appId || !botId) {
return null;
}

return <App applicationId={appId} botId={botId} />;
return <App applicationId={appId} botId={botId} locale={locale} />;
};

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

0 comments on commit 5ca145c

Please sign in to comment.