Skip to content

Commit

Permalink
umputun#10 translate errors messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Mavrin committed Feb 22, 2020
1 parent 32f0322 commit 14ce267
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 67 deletions.
6 changes: 2 additions & 4 deletions frontend/app/common/fetcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ describe('fetcher', () => {
fail(data);
})
.catch(e => {
expect(e.code).toBe(-1);
expect(e.code).toBe(401);
expect(e.error).toBe('Not authorized.');
expect(e.details).toBe('Not authorized.');
});
});
it('should throw "Something went wrong." object on unknown status', async () => {
Expand All @@ -77,9 +76,8 @@ describe('fetcher', () => {
fail(data);
})
.catch(e => {
expect(e.code).toBe(-1);
expect(e.code).toBe(500);
expect(e.error).toBe('Something went wrong.');
expect(e.details).toBe('you given me something wrong');
});
});
});
Expand Down
14 changes: 6 additions & 8 deletions frontend/app/common/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BASE_URL, API_BASE } from './constants';
import { siteId } from './settings';
import { StaticStore } from './static_store';
import { getCookie } from './cookies';
import { httpErrorMap, isFailedFetch } from '@app/utils/errorUtils';
import { httpErrorMap, isFailedFetch, httpMessages } from '@app/utils/errorUtils';

export type FetcherMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head';
const methods: FetcherMethod[] = ['get', 'post', 'put', 'patch', 'delete', 'head'];
Expand Down Expand Up @@ -82,11 +82,10 @@ const fetcher = methods.reduce<Partial<FetcherObject>>((acc, method) => {

if (res.status >= 400) {
if (httpErrorMap.has(res.status)) {
const errString = httpErrorMap.get(res.status)!;
const descriptor = httpErrorMap.get(res.status) || httpMessages.unexpectedError;
throw {
code: -1,
error: errString,
details: errString,
code: descriptor ? res.status : 500,
error: descriptor.defaultMessage,
};
}
return res.text().then(text => {
Expand All @@ -99,9 +98,8 @@ const fetcher = methods.reduce<Partial<FetcherObject>>((acc, method) => {
console.error(err);
}
throw {
code: -1,
error: 'Something went wrong.',
details: text,
code: 500,
error: httpMessages.unexpectedError.defaultMessage,
};
}
throw err;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { EmailLoginForm, Props, State } from './auth-panel__email-login-form';
import { User } from '@app/common/types';
import { sleep } from '@app/utils/sleep';
import { validToken } from '@app/testUtils/mocks/jwt';
import { createIntl } from 'react-intl';
import enMessages from '../../../locales/en.json';

jest.mock('@app/utils/jwt', () => ({
isJwtExpired: jest
Expand All @@ -13,6 +15,11 @@ jest.mock('@app/utils/jwt', () => ({
.mockImplementationOnce(() => true),
}));

const intl = createIntl({
locale: `en`,
messages: enMessages,
});

describe('EmailLoginForm', () => {
const testUser = ({} as any) as User;
const onSuccess = jest.fn(async () => {});
Expand All @@ -27,6 +34,7 @@ describe('EmailLoginForm', () => {
onSignIn={onSignIn}
onSuccess={onSuccess}
theme="light"
intl={intl}
/>
);

Expand Down Expand Up @@ -57,6 +65,7 @@ describe('EmailLoginForm', () => {
onSignIn={onSignIn}
onSuccess={onSuccess}
theme="light"
intl={intl}
/>
);
await new Promise(resolve =>
Expand All @@ -82,6 +91,7 @@ describe('EmailLoginForm', () => {
onSignIn={onSignIn}
onSuccess={onSuccess}
theme="light"
intl={intl}
/>
);
await new Promise(resolve =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import TextareaAutosize from '@app/components/comment-form/textarea-autosize';
import { Input } from '@app/components/input';
import { Button } from '@app/components/button';
import { isJwtExpired } from '@app/utils/jwt';
import { IntlShape, useIntl } from 'react-intl';

const mapStateToProps = () => ({
sendEmailVerification: sendEmailVerificationRequest,
Expand All @@ -24,7 +25,7 @@ interface OwnProps {
className?: string;
}

export type Props = OwnProps & ReturnType<typeof mapStateToProps>;
export type Props = OwnProps & ReturnType<typeof mapStateToProps> & { intl: IntlShape };

export interface State {
usernameValue: string;
Expand Down Expand Up @@ -70,7 +71,7 @@ export class EmailLoginForm extends Component<Props, State> {
this.tokenRef.current && this.tokenRef.current.focus();
}, 100);
} catch (e) {
this.setState({ error: extractErrorMessageFromResponse(e) });
this.setState({ error: extractErrorMessageFromResponse(e, this.props.intl) });
} finally {
this.setState({ loading: false });
}
Expand All @@ -87,7 +88,7 @@ export class EmailLoginForm extends Component<Props, State> {
this.setState({ verificationSent: false, tokenValue: '' });
this.props.onSuccess && this.props.onSuccess(user);
} catch (e) {
this.setState({ error: extractErrorMessageFromResponse(e) });
this.setState({ error: extractErrorMessageFromResponse(e, this.props.intl) });
} finally {
this.setState({ loading: false });
}
Expand Down Expand Up @@ -233,5 +234,6 @@ export type EmailLoginFormRef = EmailLoginForm;

export const EmailLoginFormConnected = forwardRef<EmailLoginForm, OwnProps>((props, ref) => {
const connectedProps = useSelector(mapStateToProps);
return <EmailLoginForm {...props} {...connectedProps} ref={ref} />;
const intl = useIntl();
return <EmailLoginForm {...props} {...connectedProps} intl={intl} ref={ref} />;
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { Input } from '@app/components/input';
import { Button } from '@app/components/button';
import { Dropdown } from '@app/components/dropdown';
import TextareaAutosize from '@app/components/comment-form/textarea-autosize';
import { IntlProvider } from 'react-intl';
import enMessages from '../../../locales/en.json';

import { SubscribeByEmail, SubscribeByEmailForm } from './';

Expand All @@ -40,9 +42,11 @@ jest.mock('@app/utils/jwt', () => ({
describe('<SubscribeByEmail/>', () => {
const createWrapper = (store: ReturnType<typeof mockStore> = mockStore(initialStore)) =>
mount(
<Provider store={store}>
<SubscribeByEmail />
</Provider>
<IntlProvider locale="en" messages={enMessages}>
<Provider store={store}>
<SubscribeByEmail />
</Provider>
</IntlProvider>
);

it('should be rendered with disabled email button when user is anonymous', () => {
Expand All @@ -67,9 +71,11 @@ describe('<SubscribeByEmail/>', () => {
describe('<SubscribeByEmailForm/>', () => {
const createWrapper = (store: ReturnType<typeof mockStore> = mockStore(initialStore)) =>
mount(
<Provider store={store}>
<SubscribeByEmailForm />
</Provider>
<IntlProvider locale="en" messages={enMessages}>
<Provider store={store}>
<SubscribeByEmailForm />
</Provider>
</IntlProvider>
);
it('should render email form by default', () => {
const store = mockStore(initialStore);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { Preloader } from '@app/components/preloader';
import TextareaAutosize from '@app/components/comment-form/textarea-autosize';
import { isUserAnonymous } from '@app/utils/isUserAnonymous';
import { isJwtExpired } from '@app/utils/jwt';
import { useIntl } from 'react-intl';

const emailRegex = /[^@]+@[^.]+\..+/;

Expand Down Expand Up @@ -78,6 +79,7 @@ const renderTokenPart = (
export const SubscribeByEmailForm: FunctionComponent = () => {
const theme = useTheme();
const dispatch = useDispatch();
const intl = useIntl();
const subscribed = useSelector<StoreState, boolean>(({ user }) =>
user === null ? false : Boolean(user.email_subscription)
);
Expand Down Expand Up @@ -114,7 +116,7 @@ export const SubscribeByEmailForm: FunctionComponent = () => {
break;
}
} catch (e) {
setError(extractErrorMessageFromResponse(e));
setError(extractErrorMessageFromResponse(e, intl));
} finally {
setLoading(false);
}
Expand Down Expand Up @@ -189,7 +191,7 @@ export const SubscribeByEmailForm: FunctionComponent = () => {
previousStep.current = Step.Subscribed;
setStep(Step.Unsubscribed);
} catch (e) {
setError(extractErrorMessageFromResponse(e));
setError(extractErrorMessageFromResponse(e, intl));
} finally {
setLoading(false);
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/components/comment-form/comment-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export class CommentForm extends Component<Props, State> {
this.setState({ preview: null, text: '' });
})
.catch(e => {
const errorMessage = extractErrorMessageFromResponse(e);
const errorMessage = extractErrorMessageFromResponse(e, this.props.intl);
this.setState({ isErrorShown: true, errorMessage });
})
.finally(() => this.setState({ isDisabled: false }));
Expand Down Expand Up @@ -259,7 +259,7 @@ export class CommentForm extends Component<Props, State> {
return new Error(
intl.formatMessage(messages.uploadFileFail, {
fileName: file.name,
errorMessage: extractErrorMessageFromResponse(e),
errorMessage: extractErrorMessageFromResponse(e, this.props.intl),
})
);
});
Expand Down
1 change: 1 addition & 0 deletions frontend/app/components/comment-form/markdown-toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export default class MarkdownToolbar extends Component<Props> {
const unorderedListLabel = intl.formatMessage(messages.unorderedList);
const orderedListLabel = intl.formatMessage(messages.orderedList);
const attachImageLabel = intl.formatMessage(messages.attachImage);

return (
<markdown-toolbar className="comment-form__toolbar" for={props.textareaId}>
<div className="comment-form__toolbar-group">
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/components/comment/comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class Comment extends Component<Props, State> {
this.setState({
scoreDelta: originalDelta,
cachedScore: originalScore,
voteErrorMessage: extractErrorMessageFromResponse(e),
voteErrorMessage: extractErrorMessageFromResponse(e, this.props.intl),
});
};

Expand Down
26 changes: 25 additions & 1 deletion frontend/app/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,29 @@
"toolbar.link": "Add a link <cmd-k>",
"toolbar.unordered-list": "Add a bulleted list",
"toolbar.ordered-list": "Add a numbered list",
"toolbar.attach-image": "Attach the image, drag & drop or paste from clipboard"
"toolbar.attach-image": "Attach the image, drag & drop or paste from clipboard",
"errors.failed-fetch": "Failed to fetch. Please check your internet connection or try again a bit later",
"errors.0": "Something went wrong. Please try again a bit later.",
"errors.1": "Comment cannot be found. Please refresh the page and try again.",
"errors.2": "Failed to unmarshal incoming request.",
"errors.3": "You don't have permission for this operation.",
"errors.4": "Invalid comment data.",
"errors.5": "Comment cannot be found. Please refresh the page and try again.",
"errors.6": "Site cannot be found. Please refresh the page and try again.",
"errors.7": "User has been blocked.",
"errors.8": "User has been blocked.",
"errors.9": "Comment changing failed. Please try again a bit later.",
"errors.10": "It is too late to edit the comment.",
"errors.11": "Comment already has reply, editing is not possible.",
"errors.12": "Cannot save voting result. Please try again a bit later.",
"errors.13": "You cannot vote for your own comment.",
"errors.14": "You have already voted for the comment.",
"errors.15": "Too many votes for the comment.",
"errors.16": "Min score reached for the comment.",
"errors.17": "Action rejected. Please try again a bit later.",
"errors.18": "Requested file cannot be found.",
"errors.not-authorized": "Not authorized.",
"errors.forbidden": "Forbidden.",
"errors.to-many-request": "You have reached maximum request limit.",
"errors.unexpected-error": "Something went wrong."
}
26 changes: 25 additions & 1 deletion frontend/app/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,29 @@
"toolbar.link": "Ссылка <cmd-k>",
"toolbar.unordered-list": "Неупорядоченный список",
"toolbar.ordered-list": "Упорядоченный список",
"toolbar.attach-image": "Attach the image, drag & drop or paste from clipboard"
"toolbar.attach-image": "Attach the image, drag & drop or paste from clipboard",
"errors.failed-fetch": "Нет ответа с сервера. Проверьте ваше соеденение с интернетом или попробуйте позже.",
"errors.0": "Something went wrong. Please try again a bit later.",
"errors.1": "Comment cannot be found. Please refresh the page and try again.",
"errors.2": "Failed to unmarshal incoming request.",
"errors.3": "You don't have permission for this operation.",
"errors.4": "Invalid comment data.",
"errors.5": "Comment cannot be found. Please refresh the page and try again.",
"errors.6": "Site cannot be found. Please refresh the page and try again.",
"errors.7": "User has been blocked.",
"errors.8": "User has been blocked.",
"errors.9": "Comment changing failed. Please try again a bit later.",
"errors.10": "It is too late to edit the comment.",
"errors.11": "Comment already has reply, editing is not possible.",
"errors.12": "Cannot save voting result. Please try again a bit later.",
"errors.13": "You cannot vote for your own comment.",
"errors.14": "Вы уже голосовали за этот комментарий.",
"errors.15": "Too many votes for the comment.",
"errors.16": "Min score reached for the comment.",
"errors.17": "Action rejected. Please try again a bit later.",
"errors.18": "Requested file cannot be found.",
"errors.not-authorized": "Not authorized.",
"errors.forbidden": "Forbidden.",
"errors.to-many-request": "Слишком много запросов.",
"errors.unexpected-error": "Что-то пошло не так."
}
Loading

0 comments on commit 14ce267

Please sign in to comment.