Skip to content

Commit bd0d9b0

Browse files
committed
updated language changes
1 parent 79d9a58 commit bd0d9b0

File tree

4 files changed

+112
-24
lines changed

4 files changed

+112
-24
lines changed

src/components/OnboardingComponents/SemanticSearch/QuerySuggestions.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
11
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import React from 'react';
4+
import React, {useCallback, useMemo} from 'react';
55
import {Box, Chip, Typography} from '@mui/material';
66
import {useTranslation} from 'react-i18next';
7+
import {Localization} from 'types/localization';
78

89
interface QuerySuggestionsProps {
910
/** A list of suggestion strings to display. */
1011
suggestions: string[];
1112
/** The function to call when a suggestion chip is clicked. */
1213
onSuggestionClick: (query: string) => void;
14+
/** Optional localization settings for the component, including number formatting and language overrides. */
15+
localization?: Localization;
1316
}
1417

1518
/**
1619
* A component that displays a list of clickable query suggestion chips.
1720
*/
18-
export default function QuerySuggestions({suggestions, onSuggestionClick}: QuerySuggestionsProps): JSX.Element {
19-
const {t} = useTranslation('global');
21+
export default function QuerySuggestions({
22+
suggestions,
23+
onSuggestionClick,
24+
localization,
25+
}: QuerySuggestionsProps): JSX.Element {
26+
const {t: defaultT, i18n} = useTranslation();
27+
28+
const memoizedLocalization = useMemo(
29+
() =>
30+
localization ?? {
31+
formatNumber: (v: number) => v.toLocaleString(i18n.language),
32+
customLang: 'global',
33+
overrides: {},
34+
},
35+
[localization, i18n.language]
36+
);
37+
38+
const {t: customT} = useTranslation(memoizedLocalization.customLang);
39+
40+
const tOverride = useCallback(
41+
(key: string) =>
42+
memoizedLocalization.overrides?.[key] ? customT(memoizedLocalization.overrides[key]) : defaultT(key),
43+
[customT, defaultT, memoizedLocalization.overrides]
44+
);
2045

2146
return (
2247
<Box mb={2}>
2348
<Typography variant='caption' sx={{color: 'GrayText', mb: 1, display: 'block'}}>
24-
{t('semanticSearch.suggestions.title')}
49+
{tOverride('semanticSearch.suggestions.title')}
2550
</Typography>
2651
<Box display='flex' flexWrap='wrap' gap={1}>
2752
{suggestions.map((suggestion) => (

src/components/OnboardingComponents/SemanticSearch/SearchResultItem.tsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,45 @@
11
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import React from 'react';
4+
import React, {useCallback, useMemo} from 'react';
55
import {Box, Chip, Paper, Typography, useTheme} from '@mui/material';
66
import {SearchResult} from 'types/semanticSearch';
77
import {useTranslation} from 'react-i18next';
8+
import {Localization} from 'types/localization';
89

910
interface SearchResultItemProps {
1011
result: SearchResult;
1112
onResultClick: (result: SearchResult) => void;
13+
localization?: Localization;
1214
}
1315

1416
/**
1517
* A component that displays a single, styled search result item,
1618
* including title, snippet, relevance score, and classification tags.
1719
*/
18-
export default function SearchResultItem({result, onResultClick}: SearchResultItemProps): JSX.Element {
20+
export default function SearchResultItem({result, onResultClick, localization}: SearchResultItemProps): JSX.Element {
1921
const theme = useTheme();
20-
const {t} = useTranslation('global');
22+
const {t: defaultT, i18n} = useTranslation();
23+
24+
const memoizedLocalization = useMemo(
25+
() =>
26+
localization ?? {
27+
formatNumber: (v: number) => v.toLocaleString(i18n.language),
28+
customLang: 'global',
29+
overrides: {},
30+
},
31+
[localization, i18n.language]
32+
);
33+
34+
const {t: customT} = useTranslation(memoizedLocalization.customLang);
35+
36+
const tOverride = useCallback(
37+
(key: string) =>
38+
memoizedLocalization.overrides?.[key]
39+
? customT(memoizedLocalization.overrides[key])
40+
: defaultT(key, {count: result.score}),
41+
[customT, defaultT, memoizedLocalization.overrides, result.score]
42+
);
2143

2244
const classificationStyles = {
2345
direct: {
@@ -38,9 +60,9 @@ export default function SearchResultItem({result, onResultClick}: SearchResultIt
3860
};
3961

4062
const classificationText = {
41-
direct: t('semanticSearch.classification.direct'),
42-
high: t('semanticSearch.classification.high'),
43-
related: t('semanticSearch.classification.related'),
63+
direct: tOverride('semanticSearch.classification.direct'),
64+
high: tOverride('semanticSearch.classification.high'),
65+
related: tOverride('semanticSearch.classification.related'),
4466
};
4567

4668
const truncateText = (text: string, wordLimit: number) => {

src/components/OnboardingComponents/SemanticSearch/SearchResultsList.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,27 @@ import React from 'react';
55
import {Box} from '@mui/material';
66
import {SearchResult} from 'types/semanticSearch';
77
import SearchResultItem from './SearchResultItem';
8+
import {Localization} from 'types/localization';
89

910
interface SearchResultsListProps {
1011
results: SearchResult[];
1112
onResultClick: (result: SearchResult) => void;
13+
localization?: Localization;
1214
}
1315

1416
/**
1517
* Renders a list of search result items.
1618
*/
17-
export default function SearchResultsList({results, onResultClick}: SearchResultsListProps): JSX.Element {
19+
export default function SearchResultsList({results, onResultClick, localization}: SearchResultsListProps): JSX.Element {
1820
return (
1921
<Box mt={2}>
2022
{results.map((result, index) => (
21-
<SearchResultItem key={result.id + index} result={result} onResultClick={onResultClick} />
23+
<SearchResultItem
24+
key={result.id + index}
25+
result={result}
26+
onResultClick={onResultClick}
27+
localization={localization}
28+
/>
2229
))}
2330
</Box>
2431
);

src/components/OnboardingComponents/SemanticSearch/SemanticSearchContainer.tsx

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import React, {useState} from 'react';
4+
import React, {useState, useMemo, useCallback} from 'react';
55
import {Box, Typography, Divider, TextField, IconButton, InputAdornment, CircularProgress} from '@mui/material';
66
import {useSemanticSearch} from 'context/SemanticSearchContext';
77
import QuerySuggestions from './QuerySuggestions';
@@ -12,20 +12,46 @@ import {setSemanticSearchQuery} from 'store/SemanticSearchSlice';
1212
import SearchResultsList from './SearchResultsList';
1313
import ArticleDialog from './ArticleDialog';
1414
import {SearchResult} from 'types/semanticSearch';
15+
import {Localization} from 'types/localization';
1516

1617
/**
1718
* Main container for the Semantic Search feature.
1819
* It will manage the search state and orchestrate the child components.
1920
*/
20-
export default function SemanticSearchContainer(): JSX.Element {
21+
export default function SemanticSearchContainer({localization}: {localization?: Localization}): JSX.Element {
2122
const {searchResults, isLoading, performSearch, clearSearch} = useSemanticSearch();
2223
const dispatch = useAppDispatch();
2324
const query = useAppSelector((state) => state.semanticSearch.searchQuery);
2425
const searchStatus = useAppSelector((state) => state.semanticSearch.searchStatus);
25-
const {t} = useTranslation('global');
26+
const {t: defaultT, i18n} = useTranslation();
2627
const [selectedArticle, setSelectedArticle] = useState<SearchResult | null>(null);
2728

28-
const suggestions = [t('semanticSearch.suggestions.scenarioForecasting'), t('semanticSearch.suggestions.purpose')];
29+
const memoizedLocalization = useMemo(
30+
() =>
31+
localization ?? {
32+
formatNumber: (v: number) => v.toLocaleString(i18n.language),
33+
customLang: 'global',
34+
overrides: {},
35+
},
36+
[localization, i18n.language]
37+
);
38+
39+
const {t: customT} = useTranslation(memoizedLocalization.customLang);
40+
41+
const tOverride = useCallback(
42+
(key: string, options?: {[key: string]: string | number}) =>
43+
memoizedLocalization.overrides?.[key]
44+
? customT(memoizedLocalization.overrides[key], options)
45+
: defaultT(key, options),
46+
[customT, defaultT, memoizedLocalization.overrides]
47+
);
48+
49+
const fmtNum = memoizedLocalization.formatNumber ?? ((v: number) => v.toLocaleString(i18n.language));
50+
51+
const suggestions = [
52+
tOverride('semanticSearch.suggestions.scenarioForecasting'),
53+
tOverride('semanticSearch.suggestions.purpose'),
54+
];
2955

3056
const handleSearch = () => {
3157
// performSearch is now required and will not be undefined.
@@ -58,17 +84,17 @@ export default function SemanticSearchContainer(): JSX.Element {
5884
<Box mt={4}>
5985
<Divider sx={{mb: 3}} />
6086
<Typography variant='h2' gutterBottom>
61-
{t('semanticSearch.title')}
87+
{tOverride('semanticSearch.title')}
6288
</Typography>
6389
<Typography variant='body1' paragraph sx={{color: 'GrayText'}}>
64-
{t('semanticSearch.description')}
90+
{tOverride('semanticSearch.description')}
6591
</Typography>
6692

6793
<TextField
6894
fullWidth
6995
size='small'
7096
variant='outlined'
71-
placeholder={t('semanticSearch.placeholder')}
97+
placeholder={tOverride('semanticSearch.placeholder')}
7298
value={query}
7399
onChange={(e) => dispatch(setSemanticSearchQuery(e.target.value))}
74100
onKeyDown={(e) => {
@@ -108,7 +134,11 @@ export default function SemanticSearchContainer(): JSX.Element {
108134
}}
109135
/>
110136

111-
<QuerySuggestions suggestions={suggestions} onSuggestionClick={handleSuggestionClick} />
137+
<QuerySuggestions
138+
suggestions={suggestions}
139+
onSuggestionClick={handleSuggestionClick}
140+
localization={memoizedLocalization}
141+
/>
112142

113143
<Box
114144
mt={3}
@@ -120,11 +150,11 @@ export default function SemanticSearchContainer(): JSX.Element {
120150
>
121151
{searchResults.length > 0 && (
122152
<Typography variant='body2' sx={{color: 'GrayText', mb: 1.5, px: 1}}>
123-
{t(
153+
{tOverride(
124154
searchResults.length === 1
125155
? 'semanticSearch.results.resultsFound_one'
126156
: 'semanticSearch.results.resultsFound_other',
127-
{count: searchResults.length}
157+
{count: fmtNum(searchResults.length)}
128158
)}{' '}
129159
&quot;
130160
<Box component='span' sx={{fontStyle: 'italic', color: 'primary.main'}}>
@@ -138,10 +168,14 @@ export default function SemanticSearchContainer(): JSX.Element {
138168
<CircularProgress />
139169
</Box>
140170
) : searchResults.length > 0 ? (
141-
<SearchResultsList results={searchResults} onResultClick={handleResultClick} />
171+
<SearchResultsList
172+
results={searchResults}
173+
onResultClick={handleResultClick}
174+
localization={memoizedLocalization}
175+
/>
142176
) : searchStatus === 'succeeded' ? (
143177
<Box display='flex' justifyContent='center' alignItems='center' sx={{py: 4}}>
144-
<Typography sx={{color: 'GrayText'}}>{t('semanticSearch.results.noResults')}</Typography>
178+
<Typography sx={{color: 'GrayText'}}>{tOverride('semanticSearch.results.noResults')}</Typography>
145179
</Box>
146180
) : null}
147181
</Box>

0 commit comments

Comments
 (0)