Skip to content

Commit

Permalink
umputun#10 translate comment form
Browse files Browse the repository at this point in the history
  • Loading branch information
Mavrin committed Feb 22, 2020
1 parent f1578a2 commit 302fbaa
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 55 deletions.
78 changes: 44 additions & 34 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 } from '@app/utils/errorUtils';
import { httpErrorMap, isFailedFetch } 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 @@ -73,46 +73,56 @@ const fetcher = methods.reduce<Partial<FetcherObject>>((acc, method) => {
rurl += (rurl.includes('?') ? '&' : '?') + `site=${siteId}`;
}

return fetch(rurl, parameters).then(res => {
const date = (res.headers.has('date') && res.headers.get('date')) || '';
const timestamp = isNaN(Date.parse(date)) ? 0 : Date.parse(date);
const timeDiff = (new Date().getTime() - timestamp) / 1000;
StaticStore.serverClientTimeDiff = timeDiff;
return fetch(rurl, parameters)
.then(res => {
const date = (res.headers.has('date') && res.headers.get('date')) || '';
const timestamp = isNaN(Date.parse(date)) ? 0 : Date.parse(date);
const timeDiff = (new Date().getTime() - timestamp) / 1000;
StaticStore.serverClientTimeDiff = timeDiff;

if (res.status >= 400) {
if (httpErrorMap.has(res.status)) {
const errString = httpErrorMap.get(res.status)!;
throw {
code: -1,
error: errString,
details: errString,
};
}
return res.text().then(text => {
let err;
try {
err = JSON.parse(text);
} catch (e) {
if (logError) {
// eslint-disable-next-line no-console
console.error(err);
}
if (res.status >= 400) {
if (httpErrorMap.has(res.status)) {
const errString = httpErrorMap.get(res.status)!;
throw {
code: -1,
error: 'Something went wrong.',
details: text,
error: errString,
details: errString,
};
}
throw err;
});
}
return res.text().then(text => {
let err;
try {
err = JSON.parse(text);
} catch (e) {
if (logError) {
// eslint-disable-next-line no-console
console.error(err);
}
throw {
code: -1,
error: 'Something went wrong.',
details: text,
};
}
throw err;
});
}

if (res.headers.has('Content-Type') && res.headers.get('Content-Type')!.indexOf('application/json') === 0) {
return res.json();
}
if (res.headers.has('Content-Type') && res.headers.get('Content-Type')!.indexOf('application/json') === 0) {
return res.json();
}

return res.text();
});
return res.text();
})
.catch(e => {
if (isFailedFetch(e)) {
throw {
code: -2,
error: e.message,
};
}
throw e;
});
};
return acc;
}, {}) as FetcherObject;
Expand Down
37 changes: 26 additions & 11 deletions frontend/app/components/comment-form/comment-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ const messages = defineMessages({
id: 'commentForm.input-placeholder',
defaultMessage: 'Your comment here',
},
uploadFileFail: {
id: 'commentForm.upload-file-fail',
defaultMessage: '{fileName} upload failed with "{errorMessage}"',
},
uploading: {
id: 'commentForm.uploading',
defaultMessage: 'Uploading...',
},
uploadingFile: {
id: 'commentForm.uploading-file',
defaultMessage: 'uploading {fileName}...',
},
});

export class CommentForm extends Component<Props, State> {
Expand Down Expand Up @@ -168,7 +180,6 @@ export class CommentForm extends Component<Props, State> {
this.setState({ preview: null, text: '' });
})
.catch(e => {
console.error(e); // eslint-disable-line no-console
const errorMessage = extractErrorMessageFromResponse(e);
this.setState({ isErrorShown: true, errorMessage });
})
Expand Down Expand Up @@ -231,18 +242,20 @@ export class CommentForm extends Component<Props, State> {

/** wrapper with error handling for props.uploadImage */
uploadImage(file: File): Promise<Image | Error> {
return this.props.uploadImage!(file).catch(
(e: ApiError | string) =>
new Error(
typeof e === 'string'
? `${file.name} upload failed with "${e}"`
: `${file.name} upload failed with "${e.error}"`
)
);
const intl = this.props.intl;
return this.props.uploadImage!(file).catch((e: ApiError | string) => {
return new Error(
intl.formatMessage(messages.uploadFileFail, {
fileName: file.name,
errorMessage: extractErrorMessageFromResponse(e),
})
);
});
}

/** performs upload process */
async uploadImages(files: File[]) {
const intl = this.props.intl;
if (!this.props.uploadImage) return;
if (!this.textAreaRef.current) return;

Expand All @@ -258,7 +271,7 @@ export class CommentForm extends Component<Props, State> {
errorMessage: null,
isErrorShown: false,
isDisabled: true,
buttonText: 'Uploading...',
buttonText: intl.formatMessage(messages.uploading),
});

// fallback for ie < 9
Expand Down Expand Up @@ -297,7 +310,9 @@ export class CommentForm extends Component<Props, State> {
const isFirst = i === 0;
const placeholderStart = this.state.text.length === 0 ? '' : '\n';

const uploadPlaceholder = `${placeholderStart}![uploading ${file.name}...]()`;
const uploadPlaceholder = `${placeholderStart}![${intl.formatMessage(messages.uploadingFile, {
fileName: file.name,
})}]()`;
const uploadPlaceholderLength = uploadPlaceholder.length;
const selection = this.textAreaRef.current.getSelection();
/** saved selection in case of error */
Expand Down
7 changes: 5 additions & 2 deletions frontend/app/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"vote.deleted": "Can't vote for deleted comment",
"vote.anonymous": "Anonymous users can't vote",
"vote.only-positive": "Only positive score allowed",
"comment.block-user": "Do you want to verify {userName}?",
"comment.block-user": "Do you want to block {userName} {duration}?",
"comment.unblock-user": "Do you want to unblock this user?",
"blockingDuration.permanently": "Permanently",
"blockingDuration.month": "For a month",
Expand All @@ -70,5 +70,8 @@
"comment.unverified-user": "Unverified user",
"comment.go-to-parent": "Go to parent comment",
"comment.expired-time": "Editing time has expired.",
"comment.vote-error": "Voting error: {voteErrorMessage}"
"comment.vote-error": "Voting error: {voteErrorMessage}",
"commentForm.upload-file-fail": "{fileName} upload failed with \"{errorMessage}\"",
"commentForm.uploading": "Uploading...",
"commentForm.uploading-file": "uploading {fileName}..."
}
17 changes: 10 additions & 7 deletions frontend/app/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"authPanel.logout": "Выйти?",
"authPanel.login": "Вход:",
"authPanel.logged-as": "Вы вошли как",
"comment.hide-user-comment": "Do you want to hide comments of {userName}?",
"comment.hide-user-comment": "Спрятать комментарии от пользователя {userName}?",
"comment.cancel": "Отменить",
"comment.reply": "Ответить",
"comment.edit": "Редактировать",
Expand Down Expand Up @@ -36,8 +36,8 @@
"commentSort.sort-by": "Сортировать по",
"comment.pin-comment": "Закрепить комментарий?",
"comment.unpin-comment": "Открепить комментарий?",
"comment.verify-user": "Do you want to verify {userName}?",
"comment.unverify-user": "Do you want to unverify {userName}?",
"comment.verify-user": "Подвердить подлинность учетной записи для {userName}?",
"comment.unverify-user": "Убрать статус подлинности учетной записи для {userName}?",
"commentForm.input-placeholder": "Написать комментарий",
"commentForm.notice-about-styling": "Поддерживается <a>Markdown</a> форматирование",
"commentForm.subscribe-by": "Подписаться",
Expand Down Expand Up @@ -65,10 +65,13 @@
"comment.copy": "Копировать",
"comment.unblock": "Разблокировать",
"comment.block": "Блокировать",
"comment.toggle-verification": "Toggle verification",
"comment.verified-user": "Verified user",
"comment.unverified-user": "Unverified user",
"comment.toggle-verification": "Изменить статут подлинности учетной записи",
"comment.verified-user": "Подлинная учетная запись",
"comment.unverified-user": " Не проверенная на подлинность учетная запись",
"comment.go-to-parent": "Go to parent comment",
"comment.expired-time": "Время редактирования истекло.",
"comment.vote-error": "Ошибка голосования: {voteErrorMessage}"
"comment.vote-error": "Ошибка голосования: {voteErrorMessage}",
"commentForm.upload-file-fail": "{fileName} невозможно загрузить из-за ошибки: \"{errorMessage}\"",
"commentForm.uploading": "Загрузка...",
"commentForm.uploading-file": "Загрузка {fileName}..."
}
5 changes: 5 additions & 0 deletions frontend/app/utils/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* to client readable version
*/
const errorMessageForCodes = new Map([
[-2, 'Failed to fetch. Please check your internet connection.'],
[0, 'Something went wrong. Please try again a bit later.'],
[1, 'Comment cannot be found. Please refresh the page and try again.'],
[2, 'Failed to unmarshal incoming request.'],
Expand Down Expand Up @@ -33,6 +34,10 @@ export const httpErrorMap = new Map([
[429, 'You have reached maximum request limit.'],
]);

export function isFailedFetch(e?: Error): boolean {
return Boolean(e && e.message && e.message === `Failed to fetch`);
}

export type FetcherError =
| string
| {
Expand Down
2 changes: 1 addition & 1 deletion frontend/tasks/generateDictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ locales.forEach(locale => {
currentDict = require(pathToDict);
}
keyMessagePairs.forEach(([key, defaultMessage]) => {
if (!currentDict[key]) {
if (!currentDict[key] || locale === `en`) {
currentDict[key] = defaultMessage;
}
});
Expand Down

0 comments on commit 302fbaa

Please sign in to comment.