Skip to content

Commit

Permalink
Translator
Browse files Browse the repository at this point in the history
  • Loading branch information
sonic16x committed Nov 29, 2024
1 parent 21e7bd9 commit b5efc9c
Show file tree
Hide file tree
Showing 64 changed files with 50,735 additions and 61 deletions.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"classnames": "2.5.1",
"md5": "2.3.0",
"react": "18.3.1",
"dawgjs": "^0.1.4",
"react-dom": "18.3.1",
"react-redux": "9.1.2",
"redux": "5.0.1"
Expand Down
7 changes: 7 additions & 0 deletions src/actions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IModalDialog } from 'reducers';

export enum ActionTypes {
LANG = 'LANG',
TRANSLATOR_LANG = 'TRANSLATOR_LANG',
FROM_TEXT = 'FROM_TEXT',
SEARCH_TYPE = 'SEARCH_TYPE',
FLAVORISATION_TYPE = 'FLAVORISATION_TYPE',
Expand Down Expand Up @@ -34,6 +35,12 @@ export function langAction(data: {from: string, to: string}) {
data,
};
}
export function translatorLangAction(data: {from: string, to: string}) {
return {
type: ActionTypes.TRANSLATOR_LANG,
data,
};
}

export function showModalDialog(data: IModalDialog) {
return {
Expand Down
15 changes: 13 additions & 2 deletions src/components/Controls/Controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { useDispatch } from 'react-redux';

import { t } from 'translations';

import { fromTextAction, setSearchExpand } from 'actions';
import { fromTextAction, langAction, setSearchExpand } from 'actions';

import { useDictionaryLanguages } from 'hooks/useDictionaryLanguages';
import { useFromText } from 'hooks/useFromText';
import { useLang } from 'hooks/useLang';
import { useSearchExpanded } from 'hooks/useSearchExpanded';
Expand All @@ -32,6 +33,7 @@ export const Controls =
const short = useShortCardView();

const lang = useLang();
const langs = ['en', ...useDictionaryLanguages()];
const fromText = useFromText();
const spellCheck = lang.from !== 'isv';
const searchLanguage = toBCP47(lang.from);
Expand All @@ -42,11 +44,20 @@ export const Controls =

const onChangeExpand = () => dispatch(setSearchExpand(!expand));

const onLangChange = useCallback((newLang) => {
dispatch(langAction(newLang));
}, [dispatch]);


return (
<div
className={classNames('controls', { short })}
>
<LangSelector/>
<LangSelector
lang={lang}
langs={langs}
onChange={onLangChange}
/>
<InputText
testId="search-input"
size="L"
Expand Down
9 changes: 9 additions & 0 deletions src/components/LangSelector/LangSelector.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@
align-items: center;
justify-content: space-between;

&.disabled {
opacity: .7;
pointer-events: none;
}

option, select {
text-transform: capitalize;
}

svg {
color: var(--primary-color);
}

&__isv {
overflow: hidden;
min-width: 40%;
Expand Down
70 changes: 41 additions & 29 deletions src/components/LangSelector/LangSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
import classNames from 'classnames';
import { useDispatch } from 'react-redux';

import { t } from 'translations';

import { langAction } from 'actions';

import { useDictionaryLanguages } from 'hooks/useDictionaryLanguages';
import { useLang } from 'hooks/useLang';

import { Selector } from 'components/Selector';

import './LangSelector.scss';

import DirectionIcon from './images/direction-icon.svg';
import RightDirectionIcon from './images/right-direction-icon.svg';

interface ILangPart {
dir: string;
lang: string;
langs: string[];
onSelect: (lang: string) => void;
}

const LangPart =
({ lang, dir, onSelect }: ILangPart) => {
const langs = useDictionaryLanguages();
({ lang, dir, onSelect, langs }: ILangPart) => {
// const langs = useDictionaryLanguages();

if (lang === 'isv') {
return (
Expand All @@ -32,7 +28,7 @@ const LangPart =
);
}

const options = ['en', ...langs].map((value) => ({
const options = [...langs].map((value) => ({
name: t(`${value}Lang`),
value,
}));
Expand All @@ -55,40 +51,56 @@ const LangPart =
);
};

export interface ILangSelectorProps {
className?: string;
lang: { from: string, to: string };
langs: string[];
onChange: ({ from, to }: { from: string, to: string }) => void;
disabled?: boolean;
hideLangSwitch?: boolean;
}

export const LangSelector =
() => {
const { from, to } = useLang();
const dispatch = useDispatch();
({ className, lang, langs, onChange, disabled, hideLangSwitch }: ILangSelectorProps) => {
const { from, to } = lang;

return (
<div className="lang-selector">
<div className={classNames([className, 'lang-selector'], { disabled })}>
<LangPart
dir="from"
lang={from}
onSelect={(value) => dispatch(langAction({
langs={langs}
onSelect={(value) => onChange({
from: value,
to,
}))}
})}
/>
<button
data-testid="change-direction"
type="button"
aria-label="Change translation direction"
className={classNames('lang-selector__change-dir-button', { rotate: from === 'isv' })}
onClick={() => dispatch(langAction({
from: to,
to: from,
}))}
>
<DirectionIcon />
</button>
{hideLangSwitch ? (
<div>
<RightDirectionIcon />
</div>
) : (
<button
data-testid="change-direction"
type="button"
aria-label="Change translation direction"
className={classNames('lang-selector__change-dir-button', { rotate: from === 'isv' })}
onClick={() => onChange({
from: to,
to: from,
})}
>
<DirectionIcon />
</button>
)}
<LangPart
dir="to"
lang={to}
onSelect={(value) => dispatch(langAction({
langs={langs}
onSelect={(value) => onChange({
from,
to: value,
}))}
})}
/>
</div>
);
Expand Down
18 changes: 8 additions & 10 deletions src/components/LangSelector/images/direction-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/components/LangSelector/images/right-direction-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/components/Pages/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ export const Settings =
checked={enabledPages.includes('viewer')}
onChange={() => dispatch(togglePage('viewer'))}
/>
<Checkbox
key="translator"
title={t('translatorEnable')}
checked={enabledPages.includes('translator')}
onChange={() => dispatch(togglePage('translator'))}
/>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.translate-item {
position: relative;
padding: 0 3px;
border-radius: 3px;
margin: 1px;
font-size: var(--text-m);
line-height: var(--text-m-line);

&.loading {
opacity: 0.7;
pointer-events: none;
}

&.br {
display: block;
width: 100%;
height: 0;
}

&.forms {
&::before {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 3px;
border-radius: 3px;
background: var(--dark);
content: "";
opacity: 0.4;
}
}

&.error {
background: var(--invalid-color);
}

&.maybe {
background: var(--yellow-color);
}

&.valid {
background: var(--valid-color);
}

&.space {
background: var(--light-gray-color);
}

&__form-select {
position: absolute;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: calc(100% + 2px);
border-radius: 3px;
cursor: pointer;
font-size: var(--text-m);
line-height: var(--text-m-line);
opacity: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import classNames from 'classnames';

import { ITranslateNode } from 'services/translator';

import './TranslateItem.scss';

interface ITranslateItemProps {
node: ITranslateNode;
index: number;
onItemChange?: (itemIndex: number, formIndex: number) => void;
onHover?: (node: ITranslateNode, index: number, isHover: boolean) => void;
isLoading?: boolean;
}

export const TranslateItem = ({ node, onItemChange, onHover, index, isLoading }: ITranslateItemProps) => {
const { str, type, forms } = node;
const hasForms = forms && forms.length > 1;

return (
<div
className={classNames('translate-item', [type], { forms: hasForms, br: str === '\n', loading: isLoading })}
key={index}
onMouseOver={() => onHover(node, index, true)}
onMouseOut={() => onHover(node, index, false)}
>
{str}
{
hasForms && (
<select
className="translate-item__form-select"
onChange={(e) => onItemChange(index, e.currentTarget.selectedIndex)}
>
{forms.map((form, i) => <option key={i} value={i}>{form}</option>)}
</select>
)
}
</div>
);
}
1 change: 1 addition & 0 deletions src/components/Pages/TranslatorPage/TranslateItem/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TranslateItem';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.translate-results {
display: flex;
flex-wrap: wrap;
padding: var(--gap-size-s);
border: 1px solid var(--input-border-color);
border-radius: var(--border-radius-s);

&__loader {
display: flex;
align-items: center;
margin-left: 4px;
}
}
Loading

0 comments on commit b5efc9c

Please sign in to comment.