[New Feature] Support Localization

This commit is contained in:
Qolzam
2018-02-06 13:56:39 +07:00
parent 7aeb336949
commit 68ea715652
73 changed files with 1021 additions and 235 deletions

22
package-lock.json generated
View File

@@ -2931,6 +2931,14 @@
"xmlhttprequest": "1.8.0" "xmlhttprequest": "1.8.0"
} }
}, },
"flat": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat/-/flat-2.0.1.tgz",
"integrity": "sha1-cOKRiKdL4MPIlAnu0fqVd5B64y8=",
"requires": {
"is-buffer": "1.1.6"
}
},
"flatten": { "flatten": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
@@ -12732,6 +12740,15 @@
"tlds": "1.199.0" "tlds": "1.199.0"
} }
}, },
"react-localize-redux": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/react-localize-redux/-/react-localize-redux-2.15.1.tgz",
"integrity": "sha512-dJFXvnhgnAC8OOa4V6fXjzUOSRrSctrLta5fKlloba5QjUcMH4voBWBRv84veM1iz1psSAzGisbvyLSjjCdLhg==",
"requires": {
"flat": "2.0.1",
"reselect": "3.0.1"
}
},
"react-parallax": { "react-parallax": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/react-parallax/-/react-parallax-1.6.0.tgz", "resolved": "https://registry.npmjs.org/react-parallax/-/react-parallax-1.6.0.tgz",
@@ -14000,6 +14017,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
}, },
"reselect": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
"integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc="
},
"resolve": { "resolve": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",

View File

@@ -46,6 +46,7 @@
"react-event-listener": "^0.5.1", "react-event-listener": "^0.5.1",
"react-infinite-scroller": "^1.1.2", "react-infinite-scroller": "^1.1.2",
"react-linkify": "^0.2.1", "react-linkify": "^0.2.1",
"react-localize-redux": "^2.15.1",
"react-parallax": "^1.4.4", "react-parallax": "^1.4.4",
"react-redux": "^5.0.6", "react-redux": "^5.0.6",
"react-router": "^4.1.1 ", "react-router": "^4.1.1 ",

View File

@@ -76,7 +76,7 @@ export const dbLogin = (email: string, password: string) => {
dispatch(globalActions.showNotificationSuccess()) dispatch(globalActions.showNotificationSuccess())
dispatch(login(result.uid, result.emailVerified)) dispatch(login(result.uid, result.emailVerified))
dispatch(push('/')) dispatch(push('/'))
}, (error: SocialError) => dispatch(globalActions.showErrorMessage(error.code))) }, (error: SocialError) => dispatch(globalActions.showMessage(error.code)))
} }
} }
@@ -89,7 +89,7 @@ export const dbLogout = () => {
dispatch(logout()) dispatch(logout())
dispatch(push('/login')) dispatch(push('/login'))
}, (error: SocialError) => dispatch(globalActions.showErrorMessage(error.code))) }, (error: SocialError) => dispatch(globalActions.showMessage(error.code)))
} }
} }
@@ -108,7 +108,7 @@ export const dbSendEmailVerfication = () => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
// An error happened. // An error happened.
dispatch(globalActions.showErrorMessage(error.code)) dispatch(globalActions.showMessage(error.code))
}) })
} }
@@ -134,7 +134,7 @@ export const dbSignup = (user: UserRegisterModel) => {
dispatch(dbSendEmailVerfication()) dispatch(dbSendEmailVerfication())
dispatch(push('/emailVerification')) dispatch(push('/emailVerification'))
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.code))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.code)))
} }
} }
@@ -158,7 +158,7 @@ export const dbUpdatePassword = (newPassword: string) => {
// An error happened. // An error happened.
switch (error.code) { switch (error.code) {
case 'auth/requires-recent-login': case 'auth/requires-recent-login':
dispatch(globalActions.showErrorMessage(error.code)) dispatch(globalActions.showMessage(error.code))
dispatch(dbLogout()) dispatch(dbLogout())
break break
default: default:
@@ -184,7 +184,7 @@ export const dbResetPassword = (email: string) => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
// An error happened. // An error happened.
dispatch(globalActions.showErrorMessage(error.code)) dispatch(globalActions.showMessage(error.code))
}) })
} }
@@ -205,7 +205,7 @@ export const dbLoginWithOAuth = (type: OAuthType) => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
// An error happened. // An error happened.
dispatch(globalActions.showErrorMessage(error.code)) dispatch(globalActions.showMessage(error.code))
}) })
} }

View File

@@ -49,7 +49,7 @@ export let dbAddCircle = (circleName: string) => {
circle.ownerId = uid circle.ownerId = uid
dispatch(addCircle(circle)) dispatch(addCircle(circle))
}, (error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) }, (error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -99,7 +99,7 @@ export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie)
})) }))
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
// Set server request status to {Error} for following user // Set server request status to {Error} for following user
followReqestModel.status = ServerRequestStatusType.Error followReqestModel.status = ServerRequestStatusType.Error
@@ -150,7 +150,7 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
dispatch(closeSelectCircleBox(userFollowing.userId!)) dispatch(closeSelectCircleBox(userFollowing.userId!))
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideMasterLoading()) dispatch(globalActions.hideMasterLoading())
@@ -189,7 +189,7 @@ export let dbDeleteFollowingUser = (userFollowingId: string) => {
deleteFollowingUserRequest.status = ServerRequestStatusType.OK deleteFollowingUserRequest.status = ServerRequestStatusType.OK
dispatch(serverActions.sendRequest(deleteFollowingUserRequest)) dispatch(serverActions.sendRequest(deleteFollowingUserRequest))
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideMasterLoading()) dispatch(globalActions.hideMasterLoading())
@@ -219,7 +219,7 @@ export const dbUpdateCircle = (newCircle: Circle) => {
.then(() => { .then(() => {
dispatch(updateCircle({ id: newCircle.id, ...circle })) dispatch(updateCircle({ id: newCircle.id, ...circle }))
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -238,7 +238,7 @@ export const dbDeleteCircle = (circleId: string) => {
.then(() => { .then(() => {
dispatch(deleteCircle(circleId)) dispatch(deleteCircle(circleId))
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -257,7 +257,7 @@ export const dbGetCircles = () => {
dispatch(addCircles(circles)) dispatch(addCircles(circles))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -278,7 +278,7 @@ export const dbGetUserTies = () => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }
@@ -298,7 +298,7 @@ export const dbGetFollowers = () => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }
@@ -317,7 +317,7 @@ export const dbGetCirclesByUserId = (uid: string) => {
dispatch(addCircles(circles)) dispatch(addCircles(circles))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }

View File

@@ -69,7 +69,7 @@ export const dbAddComment = (ownerPostUserId: string, newComment: Comment, callB
} }
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
@@ -139,7 +139,7 @@ export const dbUpdateComment = (comment: Comment) => {
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
@@ -153,7 +153,7 @@ export const dbDeleteComment = (id?: string | null, postId?: string) => {
return (dispatch: any, getState: Function) => { return (dispatch: any, getState: Function) => {
if (id === undefined || id === null) { if (id === undefined || id === null) {
dispatch(globalActions.showErrorMessage('comment id can not be null or undefined')) dispatch(globalActions.showMessage('comment id can not be null or undefined'))
} }
dispatch(globalActions.showTopLoading()) dispatch(globalActions.showTopLoading())
@@ -163,7 +163,7 @@ export const dbDeleteComment = (id?: string | null, postId?: string) => {
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}, (error: SocialError) => { }, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })

View File

@@ -1,5 +1,6 @@
// - Import image gallery action types // - Import image gallery action types
import { GlobalActionType } from 'constants/globalActionType' import { GlobalActionType } from 'constants/globalActionType'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as serverActions from 'actions/serverActions' import * as serverActions from 'actions/serverActions'
@@ -36,7 +37,7 @@ export let dbSendFeed = (newFeed: Feed) => {
dispatch(serverActions.sendRequest(feedbackRequest)) dispatch(serverActions.sendRequest(feedbackRequest))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(showErrorMessage(error.message)) dispatch(showMessage(error.message))
// Set server request status to {Error} // Set server request status to {Error}
feedbackRequest.status = ServerRequestStatusType.Error feedbackRequest.status = ServerRequestStatusType.Error
@@ -45,6 +46,26 @@ export let dbSendFeed = (newFeed: Feed) => {
} }
} }
// - Show notification of request
export const showNotificationRequest = () => {
return (dispatch: Function, getState: Function) => {
const state = getState()
const translate = getTranslate(state.locale)
return dispatch(showMessage(String(translate('common.sentRequestMessage'))))
}
}
// - Show notification of success
export const showNotificationSuccess = () => {
return (dispatch: Function, getState: Function) => {
const state = getState()
const translate = getTranslate(state.locale)
return dispatch(showMessage(String(translate('common.successfulRequestMessage'))))
}
}
// - Internal request------------------
/** /**
* Progress change * Progress change
*/ */
@@ -75,20 +96,6 @@ export const defaultDataDisable = () => {
} }
} }
// - Show notification of request
export const showNotificationRequest = () => {
return {
type: GlobalActionType.SHOW_SEND_REQUEST_MESSAGE_GLOBAL
}
}
// - Show notification of success
export const showNotificationSuccess = () => {
return {
type: GlobalActionType.SHOW_REQUEST_SUCCESS_MESSAGE_GLOBAL
}
}
/** /**
* Hide global message * Hide global message
*/ */
@@ -101,12 +108,12 @@ export const hideMessage = () => {
} }
/** /**
* Show error message * Show message
* @param {string} message * @param {string} message
*/ */
export const showErrorMessage = (message: string) => { export const showMessage = (message: string) => {
return { return {
type: GlobalActionType.SHOW_ERROR_MESSAGE_GLOBAL, type: GlobalActionType.SHOW_MESSAGE_GLOBAL,
payload: message payload: message
} }

View File

@@ -36,7 +36,7 @@ export const dbGetImageGallery = () => {
dispatch(addImageList(images)) dispatch(addImageList(images))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }
@@ -69,7 +69,7 @@ export const dbSaveImage = (imageURL: string,imageFullPath: string) => {
})) }))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }
@@ -89,7 +89,7 @@ export const dbDeleteImage = (id: string) => {
dispatch(deleteImage(id)) dispatch(deleteImage(id))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -111,7 +111,7 @@ export const dbUploadImage = (image: any, imageName: string) => {
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.code)) dispatch(globalActions.showMessage(error.code))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
} }
@@ -143,7 +143,7 @@ export const dbDownloadImage = (fileName: string) => {
} }
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }

View File

@@ -7,6 +7,7 @@ import * as notifyActions from './notifyActions'
import * as postActions from './postActions' import * as postActions from './postActions'
import * as userActions from './userActions' import * as userActions from './userActions'
import * as voteActions from './voteActions' import * as voteActions from './voteActions'
import * as localeActions from './localeActions'
export { export {
authorizeActions, authorizeActions,
@@ -17,5 +18,6 @@ export {
notifyActions, notifyActions,
postActions, postActions,
userActions, userActions,
voteActions voteActions,
localeActions
} }

View File

@@ -0,0 +1,39 @@
import { initialize } from 'react-localize-redux'
import { addTranslationForLanguage } from 'react-localize-redux'
import { setActiveLanguage } from 'react-localize-redux'
import { LanguageType } from 'reducers/locale/langugeType'
import config from 'src/config'
/**
* Initialize translation
*/
export const initTranslation = () => {
return (dispatch: Function , getState: Function) => {
// - Intialize language
const languages = [
{ name: 'English', code: LanguageType.English },
{ name: 'French', code: LanguageType.French },
{ name: 'Spanish', code: LanguageType.Spanish }
]
dispatch(initialize(languages))
// To set a different default active language set the `defaultLanguage` option.
dispatch(initialize(languages, { defaultLanguage: config.settings.defaultLanguage }))
const englishLocale = require('locale/en.json')
const spanishLocale = require('locale/es.json')
dispatch(addTranslationForLanguage(englishLocale, LanguageType.English))
dispatch(addTranslationForLanguage(spanishLocale, LanguageType.Spanish))
}
}
/**
* Set active language for translation
*/
export const setLanguage = (language: LanguageType) => {
return (dispatch: Function , getState: Function) => {
// Dispatch `setActiveLanguage` and pass the language.
dispatch(setActiveLanguage(language))
}
}

View File

@@ -40,7 +40,7 @@ export const dbAddNotification = (newNotify: Notification) => {
.then(() => { .then(() => {
dispatch(addNotify()) dispatch(addNotify())
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -78,7 +78,7 @@ export const dbDeleteNotification = (id: string) => {
return notificationService.deleteNotification(id,uid).then(() => { return notificationService.deleteNotification(id,uid).then(() => {
dispatch(deleteNotify(id)) dispatch(deleteNotify(id))
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -106,7 +106,7 @@ export const dbSeenNotification = (id: string) => {
.then(() => { .then(() => {
dispatch(seenNotify(id)) dispatch(seenNotify(id))
}) })
.catch((error) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error) => dispatch(globalActions.showMessage(error.message)))
} }
} }

View File

@@ -59,7 +59,7 @@ export let dbAddPost = (newPost: Post, callBack: Function) => {
})) }))
callBack() callBack()
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -102,7 +102,7 @@ export const dbAddImagePost = (newPost: Post, callBack: Function) => {
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
@@ -124,7 +124,7 @@ export const dbUpdatePost = (updatedPost: Post, callBack: Function) => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
@@ -150,7 +150,7 @@ export const dbDeletePost = (id: string) => {
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())
}) })
} }
@@ -195,7 +195,7 @@ export const dbGetPosts = (page: number = 0, limit: number = 10) => {
dispatch(addPosts(parsedData)) dispatch(addPosts(parsedData))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -242,7 +242,7 @@ export const dbGetPostsByUserId = (userId: string, page: number = 0, limit: numb
dispatch(addPosts(parsedData)) dispatch(addPosts(parsedData))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
@@ -260,7 +260,7 @@ export const dbGetPostById = (uid: string, postId: string) => {
dispatch(addPost(uid, post)) dispatch(addPost(uid, post))
}) })
.catch((error: SocialError) => { .catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }

View File

@@ -37,7 +37,7 @@ export const dbGetUserInfo = () => {
creationDate: userProfile.creationDate creationDate: userProfile.creationDate
})) }))
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -76,7 +76,7 @@ export const dbGetUserInfoByUserId = (uid: string, callerKey: string) => {
break break
} }
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }
@@ -105,7 +105,7 @@ export const dbUpdateUserInfo = (newProfile: Profile) => {
dispatch(updateUserInfo(uid, updatedProfile)) dispatch(updateUserInfo(uid, updatedProfile))
dispatch(closeEditProfile()) dispatch(closeEditProfile())
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
@@ -144,7 +144,7 @@ export const dbGetPeopleInfo = (page: number, limit: number) => {
}) })
dispatch(addPeopleInfo(parsedData)) dispatch(addPeopleInfo(parsedData))
}) })
.catch((error: SocialError) => dispatch(globalActions.showErrorMessage(error.message))) .catch((error: SocialError) => dispatch(globalActions.showMessage(error.message)))
} }
} }

View File

@@ -62,7 +62,7 @@ export const dbAddVote = (postId: string,ownerPostUserId: string) => {
post.score! -= 1 post.score! -= 1
post.votes = { ...post.votes!, [uid]: false} post.votes = { ...post.votes!, [uid]: false}
dispatch(postActions.updatePost(post)) dispatch(postActions.updatePost(post))
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }
@@ -113,7 +113,7 @@ export const dbDeleteVote = (postId: string, ownerPostUserId: string) => {
post.score! += 1 post.score! += 1
post.votes = { ...post.votes!, [uid]: true} post.votes = { ...post.votes!, [uid]: true}
dispatch(postActions.updatePost(post)) dispatch(postActions.updatePost(post))
dispatch(globalActions.showErrorMessage(error.message)) dispatch(globalActions.showMessage(error.message))
}) })
} }
} }

View File

@@ -5,6 +5,7 @@ import { NavLink } from 'react-router-dom'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import moment from 'moment/moment' import moment from 'moment/moment'
import Linkify from 'react-linkify' import Linkify from 'react-linkify'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import { Comment } from 'core/domain/comments' import { Comment } from 'core/domain/comments'
@@ -293,7 +294,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
/** /**
* Comment object from props * Comment object from props
*/ */
const { comment, classes, fullName, avatar } = this.props const { comment, classes, fullName, avatar, translate } = this.props
const { openMenu } = this.state const { openMenu } = this.state
@@ -319,9 +320,9 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
<Grow in={openMenu!} style={{ transformOrigin: '0 0 0' }}> <Grow in={openMenu!} style={{ transformOrigin: '0 0 0' }}>
<Paper> <Paper>
<MenuList role='menu'> <MenuList role='menu'>
<MenuItem className={classes.rightIconMenuItem}>Reply</MenuItem> <MenuItem className={classes.rightIconMenuItem}>{translate!('comment.replyButton')}</MenuItem>
{this.props.isCommentOwner ? (<MenuItem className={classes.rightIconMenuItem} onClick={this.handleEditComment}>Edit</MenuItem>) : ''} {this.props.isCommentOwner ? (<MenuItem className={classes.rightIconMenuItem} onClick={this.handleEditComment}>{translate!('comment.editButton')}</MenuItem>) : ''}
{(this.props.isCommentOwner || this.props.isPostOwner) ? (<MenuItem className={classes.rightIconMenuItem} onClick={(evt: any) => this.handleDelete(evt, comment.id, comment.postId)}>Delete</MenuItem>) : ''} {(this.props.isCommentOwner || this.props.isPostOwner) ? (<MenuItem className={classes.rightIconMenuItem} onClick={(evt: any) => this.handleDelete(evt, comment.id, comment.postId)}>{translate!('comment.deleteButton')}</MenuItem>) : ''}
</MenuList> </MenuList>
</Paper> </Paper>
</Grow> </Grow>
@@ -342,7 +343,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
const commentBody = ( const commentBody = (
<div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}> <div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}>
{ editorStatus ? <TextField { editorStatus ? <TextField
placeholder={'Add a comment...'} placeholder={translate!('comment.updateCommentPlaceholder')}
multiline multiline
autoFocus autoFocus
rowsMax='4' rowsMax='4'
@@ -360,8 +361,8 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
<div style={{ display: (editorStatus ? 'flex' : 'none'), flexDirection: 'row-reverse' }}> <div style={{ display: (editorStatus ? 'flex' : 'none'), flexDirection: 'row-reverse' }}>
<Button color='primary' disabled={this.state.editDisabled} <Button color='primary' disabled={this.state.editDisabled}
style={{ float: 'right', clear: 'both', zIndex: 5, margin: '0px 5px 5px 0px', fontWeight: 400 }} style={{ float: 'right', clear: 'both', zIndex: 5, margin: '0px 5px 5px 0px', fontWeight: 400 }}
onClick={this.handleUpdateComment} > Update </Button> onClick={this.handleUpdateComment} > {translate!('comment.updateButton')} </Button>
<Button color='primary' style={this.styles.cancel as any} onClick={this.handleCancelEdit} > Cancel </Button> <Button color='primary' style={this.styles.cancel as any} onClick={this.handleCancelEdit} > {translate!('comment.cancelButton')} </Button>
</div> </div>
</div> </div>
) )
@@ -417,6 +418,7 @@ const mapStateToProps = (state: any, ownProps: any) => {
const avatar = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].avatar || '' : '' const avatar = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].avatar || '' : ''
const fullName = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].fullName || '' : '' const fullName = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].fullName || '' : ''
return { return {
translate: getTranslate(state.locale),
uid: uid, uid: uid,
isCommentOwner: (uid === ownProps.comment.userId), isCommentOwner: (uid === ownProps.comment.userId),
info: state.user.info, info: state.user.info,

View File

@@ -100,4 +100,9 @@ export interface ICommentComponentProps {
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -5,6 +5,7 @@ import _ from 'lodash'
import { NavLink } from 'react-router-dom' import { NavLink } from 'react-router-dom'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import moment from 'moment/moment' import moment from 'moment/moment'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import Paper from 'material-ui/Paper' import Paper from 'material-ui/Paper'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
@@ -273,7 +274,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const { comments, classes, postId, fullName, avatar, getCommentsRequest, open, commentSlides } = this.props const { comments, classes, postId, fullName, avatar, getCommentsRequest, open, commentSlides, translate } = this.props
/** /**
* Comment list box * Comment list box
@@ -288,7 +289,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
avatar={<UserAvatar fullName={fullName!} fileName={avatar!} size={24} />} avatar={<UserAvatar fullName={fullName!} fileName={avatar!} size={24} />}
subheader={<TextField subheader={<TextField
autoFocus autoFocus
placeholder={'Add a comment...'} placeholder={translate!('comment.addCommentPlaceholder')}
multiline multiline
rowsMax='4' rowsMax='4'
InputProps={{ InputProps={{
@@ -305,7 +306,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
</CardHeader> </CardHeader>
<CardActions className={classes.postButton} > <CardActions className={classes.postButton} >
<Button color='primary' disabled={this.state.postDisable} onClick={this.handlePostComment}> <Button color='primary' disabled={this.state.postDisable} onClick={this.handlePostComment}>
Post {translate!('comment.postButton')}
</Button> </Button>
</CardActions> </CardActions>
</Card> </Card>
@@ -383,6 +384,7 @@ const mapStateToProps = (state: any, ownProps: ICommentGroupComponentProps) => {
const commentSlides = post.userPosts[ownerPostUserId] && post.userPosts[ownerPostUserId][postId] ? post.userPosts[ownerPostUserId][postId].comments : {} const commentSlides = post.userPosts[ownerPostUserId] && post.userPosts[ownerPostUserId][postId] ? post.userPosts[ownerPostUserId][postId].comments : {}
const getCommentsRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)] : null const getCommentsRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)] : null
return { return {
translate: getTranslate(state.locale),
getCommentsRequest, getCommentsRequest,
commentSlides, commentSlides,
avatar: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].avatar || '' : '', avatar: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].avatar || '' : '',

View File

@@ -109,4 +109,9 @@ export interface ICommentGroupComponentProps {
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -2,6 +2,8 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import { grey } from 'material-ui/colors' import { grey } from 'material-ui/colors'
import IconButton from 'material-ui/IconButton' import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/MoreVert' import MoreVertIcon from 'material-ui-icons/MoreVert'
@@ -291,7 +293,7 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
*/ */
render () { render () {
const {classes} = this.props const {classes, translate} = this.props
const iconButtonElement = ( const iconButtonElement = (
<IconButton style={this.state.isSmall ? this.styles.iconButtonSmall : this.styles.iconButton}> <IconButton style={this.state.isSmall ? this.styles.iconButtonSmall : this.styles.iconButton}>
<MoreVertIcon style={{...(this.state.isSmall ? this.styles.iconButtonSmall : this.styles.iconButton),color: grey[400]}} viewBox='10 0 24 24' /> <MoreVertIcon style={{...(this.state.isSmall ? this.styles.iconButtonSmall : this.styles.iconButton),color: grey[400]}} viewBox='10 0 24 24' />
@@ -350,10 +352,10 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
{/* Edit user information box*/} {/* Edit user information box*/}
<Paper style={this.styles.paper} elevation={1}> <Paper style={this.styles.paper} elevation={1}>
<div style={this.styles.title as any}>Personal Information</div> <div style={this.styles.title as any}>{translate!('profile.personalInformationLabel')}</div>
<div style={this.styles.box}> <div style={this.styles.box}>
<FormControl aria-describedby='fullNameInputError'> <FormControl aria-describedby='fullNameInputError'>
<InputLabel htmlFor='fullNameInput'>Full name</InputLabel> <InputLabel htmlFor='fullNameInput'>{translate!('profile.fullName')}</InputLabel>
<Input id='fullNameInput' <Input id='fullNameInput'
onChange={this.handleInputChange} onChange={this.handleInputChange}
name='fullNameInput' name='fullNameInput'
@@ -364,7 +366,7 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
<br /> <br />
<div style={this.styles.box}> <div style={this.styles.box}>
<FormControl aria-describedby='tagLineInputError'> <FormControl aria-describedby='tagLineInputError'>
<InputLabel htmlFor='tagLineInput'>Tagline</InputLabel> <InputLabel htmlFor='tagLineInput'>{translate!('profile.tagline')}</InputLabel>
<Input id='tagLineInput' <Input id='tagLineInput'
onChange={this.handleInputChange} onChange={this.handleInputChange}
name='tagLineInput' name='tagLineInput'
@@ -374,8 +376,8 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
</div> </div>
<br /> <br />
<div style={this.styles.actions as any}> <div style={this.styles.actions as any}>
<Button onClick={this.props.onRequestClose} > CANCEL </Button> <Button onClick={this.props.onRequestClose} > {translate!('profile.cancelButton')} </Button>
<Button raised color='primary' onClick={this.handleUpdate} style={this.styles.updateButton}> UPDATE </Button> <Button raised color='primary' onClick={this.handleUpdate} style={this.styles.updateButton}> {translate!('profile.updateButton')} </Button>
</div> </div>
</Paper> </Paper>
<div style={{ height: '16px' }}></div> <div style={{ height: '16px' }}></div>
@@ -389,7 +391,7 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
> >
<DialogTitle className={classes.dialogTitle}> <DialogTitle className={classes.dialogTitle}>
<AppDialogTitle title='Choose an banner image' onRequestClose={this.handleCloseBannerGallery} /> <AppDialogTitle title={translate!('profile.chooseBanerDialogTitle')} onRequestClose={this.handleCloseBannerGallery} />
</DialogTitle> </DialogTitle>
<ImageGallery set={this.handleRequestSetBanner} close={this.handleCloseBannerGallery} /> <ImageGallery set={this.handleRequestSetBanner} close={this.handleCloseBannerGallery} />
</Dialog> </Dialog>
@@ -400,7 +402,7 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,I
onClose={this.handleCloseAvatarGallery} onClose={this.handleCloseAvatarGallery}
> >
<DialogTitle className={classes.dialogTitle}> <DialogTitle className={classes.dialogTitle}>
<AppDialogTitle title='Choose an avatar image' onRequestClose={this.handleCloseAvatarGallery} /> <AppDialogTitle title={translate!('profile.chooseAvatarDialogTitle')} onRequestClose={this.handleCloseAvatarGallery} />
</DialogTitle> </DialogTitle>
<ImageGallery set={this.handleRequestSetAvatar} close={this.handleCloseAvatarGallery} /> <ImageGallery set={this.handleRequestSetAvatar} close={this.handleCloseAvatarGallery} />
</Dialog> </Dialog>
@@ -432,6 +434,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IEditProfileComponentProps)
*/ */
const mapStateToProps = (state: any, ownProps: IEditProfileComponentProps) => { const mapStateToProps = (state: any, ownProps: IEditProfileComponentProps) => {
return { return {
translate: getTranslate(state.locale),
open: state.user.openEditProfile, open: state.user.openEditProfile,
info: state.user.info[state.authorize.uid], info: state.user.info[state.authorize.uid],
avatarURL: state.imageGallery.imageURLList avatarURL: state.imageGallery.imageURLList

View File

@@ -60,4 +60,9 @@ export interface IEditProfileComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -8,6 +8,7 @@ import TextField from 'material-ui/TextField'
import RaisedButton from 'material-ui/Button' import RaisedButton from 'material-ui/Button'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
import config from 'src/config' import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -52,7 +53,7 @@ export class EmailVerificationComponent extends Component<IEmailVerificationComp
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {translate} = this.props
const paperStyle = { const paperStyle = {
minHeight: 370, minHeight: 370,
width: 450, width: 450,
@@ -88,14 +89,14 @@ export class EmailVerificationComponent extends Component<IEmailVerificationComp
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0 margin: 0
}} className='zoomOutLCorner animated'>Email Verification</h2> }} className='zoomOutLCorner animated'>{translate!('emailVerification.title')}</h2>
</div> </div>
<p style={this.styles.message as any}> <p style={this.styles.message as any}>
An verificiation email has been already sent to you. Please check your inbox. If you couldn't see the emai, please resend email verification. {translate!('emailVerification.description')}
</p> </p>
<div style={this.styles.buttons}> <div style={this.styles.buttons}>
<Button raised style={this.styles.homeButton} color='primary' onClick={() => this.props.homePage()}> Home </Button> <Button raised style={this.styles.homeButton} color='primary' onClick={() => this.props.homePage()}> {translate!('emailVerification.homeButton')} </Button>
<Button raised color='primary' onClick={() => this.props.sendEmailVerification()}> Send Email Verification </Button> <Button raised color='primary' onClick={() => this.props.sendEmailVerification()}> {translate!('emailVerification.sendButton')} </Button>
</div> </div>
<div> <div>
</div> </div>
@@ -131,7 +132,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IEmailVerificationComp
*/ */
const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => { const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => {
return { return {
translate: getTranslate(state.locale)
} }
} }

View File

@@ -1,5 +1,17 @@
export interface IEmailVerificationComponentProps { export interface IEmailVerificationComponentProps {
/**
* Send email for verification
*/
sendEmailVerification: () => any sendEmailVerification: () => any
/**
* Redirect to home page
*/
homePage: () => any homePage: () => any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -4,6 +4,7 @@ import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Paper from 'material-ui/Paper' import Paper from 'material-ui/Paper'
import InfiniteScroll from 'react-infinite-scroller' import InfiniteScroll from 'react-infinite-scroller'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import UserBoxList from 'components/userBoxList' import UserBoxList from 'components/userBoxList'
@@ -48,7 +49,7 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {hasMorePeople} = this.props const {hasMorePeople, translate} = this.props
return ( return (
<div> <div>
@@ -64,12 +65,12 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
{this.props.peopleInfo && Object.keys(this.props.peopleInfo).length !== 0 ? (<div> {this.props.peopleInfo && Object.keys(this.props.peopleInfo).length !== 0 ? (<div>
<div className='profile__title'> <div className='profile__title'>
Suggestions for you {translate!('people.suggestionsForYouLabel')}
</div> </div>
<UserBoxList users={this.props.peopleInfo}/> <UserBoxList users={this.props.peopleInfo}/>
<div style={{ height: '24px' }}></div> <div style={{ height: '24px' }}></div>
</div>) : (<div className='g__title-center'> </div>) : (<div className='g__title-center'>
Nothing to show! :( {translate!('people.nothingToShowLabel')}
</div>)} </div>)}
</div> </div>
</InfiniteScroll> </InfiniteScroll>
@@ -99,6 +100,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IFindPeopleComponentProps)
const mapStateToProps = (state: any, ownProps: IFindPeopleComponentProps) => { const mapStateToProps = (state: any, ownProps: IFindPeopleComponentProps) => {
const {people, info} = state.user const {people, info} = state.user
return { return {
translate: getTranslate(state.locale),
peopleInfo: info, peopleInfo: info,
hasMorePeople: people.hasMoreData hasMorePeople: people.hasMoreData
} }

View File

@@ -22,4 +22,9 @@ export interface IFindPeopleComponentProps {
*/ */
hasMorePeople?: boolean hasMorePeople?: boolean
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -2,6 +2,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import UserBoxList from 'components/userBoxList' import UserBoxList from 'components/userBoxList'
@@ -44,17 +45,18 @@ export class FollowersComponent extends Component<IFollowersComponentProps,IFoll
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {translate} = this.props
return ( return (
<div> <div>
{(this.props.followers && Object.keys(this.props.followers).length !== 0) ? (<div> {(this.props.followers && Object.keys(this.props.followers).length !== 0) ? (<div>
<div className='profile__title'> <div className='profile__title'>
Followers {translate!('people.followersLabel')}
</div> </div>
<UserBoxList users={this.props.followers} /> <UserBoxList users={this.props.followers} />
<div style={{ height: '24px' }}></div> <div style={{ height: '24px' }}></div>
</div>) </div>)
: (<div className='g__title-center'> : (<div className='g__title-center'>
No followers! {translate!('people.noFollowersLabel')}
</div>)} </div>)}
</div> </div>
) )
@@ -85,6 +87,7 @@ const mapStateToProps = (state: any,ownProps: IFollowersComponentProps) => {
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {} const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
const followers = circle ? circle.userTieds : {} const followers = circle ? circle.userTieds : {}
return{ return{
translate: getTranslate(state.locale),
followers followers
} }
} }

View File

@@ -9,4 +9,9 @@ export interface IFollowersComponentProps {
* @memberof IFindPeopleComponentProps * @memberof IFindPeopleComponentProps
*/ */
followers?: {[userId: string]: UserTie} followers?: {[userId: string]: UserTie}
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -2,6 +2,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import UserBoxList from 'components/userBoxList' import UserBoxList from 'components/userBoxList'
@@ -44,18 +45,18 @@ export class FollowingComponent extends Component<IFollowingComponentProps,IFoll
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {translate} = this.props
return ( return (
<div> <div>
{(this.props.followingUsers && Object.keys(this.props.followingUsers).length !== 0 ) ? (<div> {(this.props.followingUsers && Object.keys(this.props.followingUsers).length !== 0 ) ? (<div>
<div className='profile__title'> <div className='profile__title'>
Following {translate!('people.followingLabel')}
</div> </div>
<UserBoxList users={this.props.followingUsers} /> <UserBoxList users={this.props.followingUsers} />
<div style={{ height: '24px' }}></div> <div style={{ height: '24px' }}></div>
</div>) : (<div className='g__title-center'> </div>) : (<div className='g__title-center'>
No following user! {translate!('people.noFollowingLabel')}
</div>)} </div>)}
</div> </div>
) )
@@ -86,6 +87,7 @@ const mapStateToProps = (state: any,ownProps: IFollowingComponentProps) => {
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {} const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
const followingUsers = circle ? circle.userTies : {} const followingUsers = circle ? circle.userTies : {}
return { return {
translate: getTranslate(state.locale),
uid, uid,
circles, circles,
followingUsers followingUsers

View File

@@ -3,4 +3,9 @@ import { UserTie } from 'core/domain/circles'
export interface IFollowingComponentProps { export interface IFollowingComponentProps {
followingUsers?: {[userId: string]: UserTie} followingUsers?: {[userId: string]: UserTie}
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -5,6 +5,9 @@ import _ from 'lodash'
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom' import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { push } from 'react-router-redux' import { push } from 'react-router-redux'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import config from 'src/config'
import Menu from 'material-ui/Menu' import Menu from 'material-ui/Menu'
import { MenuList, MenuItem } from 'material-ui/Menu' import { MenuList, MenuItem } from 'material-ui/Menu'
import { ListItemIcon, ListItemText } from 'material-ui/List' import { ListItemIcon, ListItemText } from 'material-ui/List'
@@ -15,7 +18,7 @@ import SvgFeedback from 'material-ui-icons/Feedback'
import SvgSettings from 'material-ui-icons/Settings' import SvgSettings from 'material-ui-icons/Settings'
import SvgAccountCircle from 'material-ui-icons/AccountCircle' import SvgAccountCircle from 'material-ui-icons/AccountCircle'
import SvgPeople from 'material-ui-icons/People' import SvgPeople from 'material-ui-icons/People'
import config from 'src/config'
// - Import app components // - Import app components
import Sidebar from 'components/sidebar' import Sidebar from 'components/sidebar'
import StreamComponent from 'components/stream' import StreamComponent from 'components/stream'
@@ -131,7 +134,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
*/ */
render () { render () {
const HR = HomeRouter as any const HR = HomeRouter as any
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback } = this.props const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback, translate } = this.props
return ( return (
<div id='home'> <div id='home'>
<HomeHeader sidebar={this.state.sidebarOpen} sidebarStatus={this.state.sidebarStatus} /> <HomeHeader sidebar={this.state.sidebarOpen} sidebarStatus={this.state.sidebarStatus} />
@@ -157,7 +160,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon> <ListItemIcon>
<SvgHome /> <SvgHome />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='Home' /> <ListItemText inset primary={translate!('sidebar.home')} />
</MenuItem> </MenuItem>
</NavLink> </NavLink>
<NavLink to={`/${this.props.uid}`}> <NavLink to={`/${this.props.uid}`}>
@@ -165,7 +168,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon> <ListItemIcon>
<SvgAccountCircle /> <SvgAccountCircle />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='Profile' /> <ListItemText inset primary={translate!('sidebar.profile')} />
</MenuItem> </MenuItem>
</NavLink> </NavLink>
<NavLink to='/people'> <NavLink to='/people'>
@@ -173,7 +176,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon> <ListItemIcon>
<SvgPeople /> <SvgPeople />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='People' /> <ListItemText inset primary={translate!('sidebar.people')} />
</MenuItem> </MenuItem>
</NavLink> </NavLink>
<Divider /> <Divider />
@@ -182,14 +185,14 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon> <ListItemIcon>
<SvgSettings /> <SvgSettings />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='Settings' /> <ListItemText inset primary={translate!('sidebar.settings')} />
</MenuItem> </MenuItem>
</NavLink> </NavLink>
<MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}> <MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}>
<ListItemIcon> <ListItemIcon>
<SvgFeedback /> <SvgFeedback />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='Send feedback' /> <ListItemText inset primary={translate!('sidebar.sendFeedback')} />
</MenuItem> </MenuItem>
</MenuList> </MenuList>
</SidebarContent> </SidebarContent>
@@ -267,6 +270,8 @@ const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
authed: authorize.authed, authed: authorize.authed,
isVerifide: authorize.isVerifide, isVerifide: authorize.isVerifide,
mainStyle: global.sidebarMainStyle, mainStyle: global.sidebarMainStyle,
translate: getTranslate(state.locale),
currentLanguage: getActiveLanguage(state.locale).code,
mergedPosts, mergedPosts,
global, global,
hasMorePosts, hasMorePosts,

View File

@@ -108,4 +108,9 @@ export interface IHomeComponentProps {
*/ */
hideSendFeedback?: () => any hideSendFeedback?: () => any
/**
* Translate locale to string
*/
translate?: (state: any) => any
} }

View File

@@ -16,6 +16,7 @@ import Tooltip from 'material-ui/Tooltip'
import Typography from 'material-ui/Typography' import Typography from 'material-ui/Typography'
import { Manager, Target, Popper } from 'react-popper' import { Manager, Target, Popper } from 'react-popper'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import config from 'src/config' import config from 'src/config'
// - Import components // - Import components
@@ -184,7 +185,7 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
// Render app DOM component // Render app DOM component
render () { render () {
const { classes } = this.props const { classes , translate} = this.props
return ( return (
<AppBar position='fixed' color='secondary'> <AppBar position='fixed' color='secondary'>
@@ -212,14 +213,14 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
<Manager> <Manager>
<Target> <Target>
{this.props.notifyCount! > 0 ? ( {this.props.notifyCount! > 0 ? (
<Tooltip title='Notifications'> <Tooltip title={translate!('header.notificationTooltip')}>
<IconButton onClick={this.handleNotifyTouchTap}> <IconButton onClick={this.handleNotifyTouchTap}>
<div className='homeHeader__notify'> <div className='homeHeader__notify'>
<div className='title'>{this.props.notifyCount}</div> <div className='title'>{this.props.notifyCount}</div>
</div> </div>
</IconButton> </IconButton>
</Tooltip>) </Tooltip>)
: (<Tooltip title='Notifications'> : (<Tooltip title={translate!('header.notificationTooltip')}>
<IconButton onClick={this.handleNotifyTouchTap}> <IconButton onClick={this.handleNotifyTouchTap}>
<NotificationsIcon style={{ color: 'rgba(255, 255, 255, 0.87)' }} /> <NotificationsIcon style={{ color: 'rgba(255, 255, 255, 0.87)' }} />
</IconButton> </IconButton>
@@ -249,8 +250,8 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
horizontal: 'right' horizontal: 'right'
}} }}
onClose={this.handleRequestClose}> onClose={this.handleRequestClose}>
<MenuItem style={{ backgroundColor: 'white', color: blue[500], fontSize: '14px' }} > MY ACCOUNT </MenuItem> <MenuItem style={{ backgroundColor: 'white', color: blue[500], fontSize: '14px' }} > {translate!('header.myAccount')} </MenuItem>
<MenuItem style={{ fontSize: '14px' }} onClick={this.handleLogout.bind(this)} > LOGOUT </MenuItem> <MenuItem style={{ fontSize: '14px' }} onClick={this.handleLogout.bind(this)} > {translate!('header.logout')} </MenuItem>
</Menu> </Menu>
</div> </div>
@@ -277,6 +278,7 @@ const mapStateToProps = (state: any, ownProps: IHomeHeaderComponentProps) => {
.filter((key) => !state.notify.userNotifies[key].isSeen).length .filter((key) => !state.notify.userNotifies[key].isSeen).length
: 0 : 0
return { return {
translate: getTranslate(state.locale),
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '', avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : '', fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : '',
title: state.global.headerTitle, title: state.global.headerTitle,

View File

@@ -65,4 +65,9 @@ export interface IHomeHeaderComponentProps {
* Material ui theme style * Material ui theme style
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -38,4 +38,9 @@ export interface IImageGalleryComponentProps {
* @memberof IImageGalleryComponentProps * @memberof IImageGalleryComponentProps
*/ */
images?: Image[] images?: Image[]
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -11,6 +11,7 @@ import SvgAddImage from 'material-ui-icons/AddAPhoto'
import SvgDelete from 'material-ui-icons/Delete' import SvgDelete from 'material-ui-icons/Delete'
import { grey } from 'material-ui/colors' import { grey } from 'material-ui/colors'
import uuid from 'uuid' import uuid from 'uuid'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as imageGalleryActions from 'actions/imageGalleryActions' import * as imageGalleryActions from 'actions/imageGalleryActions'
@@ -181,13 +182,9 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
}) })
} }
/**
* When the post text changed
* @param {event} evt is an event passed by change post text callback funciton
* @param {string} data is the post content which user writes
*/
render () { render () {
const {translate} = this.props
/** /**
* Component styles * Component styles
* @type {Object} * @type {Object}
@@ -212,7 +209,7 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
/> />
<label htmlFor='raised-button-file'> <label htmlFor='raised-button-file'>
<Button raised component='span' style={this.styles.uploadButton as any}> <Button raised component='span' style={this.styles.uploadButton as any}>
Upload {translate!('imageGallery.uploadButton')}
</Button> </Button>
</label> </label>
</div> </div>
@@ -247,6 +244,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImageGalleryComponentProps
*/ */
const mapStateToProps = (state: any) => { const mapStateToProps = (state: any) => {
return { return {
translate: getTranslate(state.locale),
images: state.imageGallery.images, images: state.imageGallery.images,
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '' avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : ''

View File

@@ -21,4 +21,9 @@ export interface IImgComponentProps {
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import SvgImage from 'material-ui-icons/Image' import SvgImage from 'material-ui-icons/Image'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
@@ -85,7 +86,7 @@ export class ImgComponent extends Component<IImgComponentProps,IImgComponentStat
*/ */
render () { render () {
let { fileName, style } = this.props let { fileName, style, translate } = this.props
let { isImageLoaded } = this.state let { isImageLoaded } = this.state
const {classes} = this.props const {classes} = this.props
return ( return (
@@ -94,7 +95,7 @@ export class ImgComponent extends Component<IImgComponentProps,IImgComponentStat
<div style={Object.assign({},{ backgroundColor: 'white' }, isImageLoaded ? { display: 'none' } : this.styles.loding)}> <div style={Object.assign({},{ backgroundColor: 'white' }, isImageLoaded ? { display: 'none' } : this.styles.loding)}>
<div style={this.styles.loadingContent as any}> <div style={this.styles.loadingContent as any}>
<SvgImage style={this.styles.loadingImage} /> <SvgImage style={this.styles.loadingImage} />
<div>Image has not loaded</div> <div>{translate!('image.notLoaded')}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -122,6 +123,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImgComponentProps) => {
*/ */
const mapStateToProps = (state: any, ownProps: IImgComponentProps) => { const mapStateToProps = (state: any, ownProps: IImgComponentProps) => {
return { return {
translate: getTranslate(state.locale),
avatarURL: state.imageGallery.imageURLList, avatarURL: state.imageGallery.imageURLList,
imageRequests: state.imageGallery.imageRequests imageRequests: state.imageGallery.imageRequests
} }

View File

@@ -39,4 +39,9 @@ export interface IImgCoverComponentProps {
* @memberof IImgCoverComponentProps * @memberof IImgCoverComponentProps
*/ */
borderRadius?: string borderRadius?: string
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -3,6 +3,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import SvgImage from 'material-ui-icons/Image' import SvgImage from 'material-ui-icons/Image'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
@@ -108,7 +109,7 @@ export class ImgCoverComponent extends Component<IImgCoverComponentProps,IImgCov
*/ */
render () { render () {
let { fileName, style } = this.props let { fileName, style, translate } = this.props
let { isImageLoaded } = this.state let { isImageLoaded } = this.state
return ( return (
@@ -124,7 +125,7 @@ export class ImgCoverComponent extends Component<IImgCoverComponentProps,IImgCov
<div style={Object.assign({},{ backgroundColor: 'blue' },isImageLoaded ? { display: 'none' } : this.styles.loding)}> <div style={Object.assign({},{ backgroundColor: 'blue' },isImageLoaded ? { display: 'none' } : this.styles.loding)}>
<div style={this.styles.loadingContent as any}> <div style={this.styles.loadingContent as any}>
<SvgImage style={this.styles.loadingImage} /> <SvgImage style={this.styles.loadingImage} />
<div>Image has not loaded</div> <div>{translate!('image.notLoaded')}</div>
</div> </div>
</div> </div>
<img onLoad={this.handleLoadImage} src={fileName || ''} style={{ display: 'none'}} /> <img onLoad={this.handleLoadImage} src={fileName || ''} style={{ display: 'none'}} />
@@ -152,6 +153,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImgCoverComponentProps) =>
*/ */
const mapStateToProps = (state: any, ownProps: IImgCoverComponentProps) => { const mapStateToProps = (state: any, ownProps: IImgCoverComponentProps) => {
return { return {
translate: getTranslate(state.locale),
avatarURL: state.imageGallery.imageURLList, avatarURL: state.imageGallery.imageURLList,
imageRequests: state.imageGallery.imageRequests imageRequests: state.imageGallery.imageRequests

View File

@@ -26,4 +26,9 @@ export interface ILoginComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -12,6 +12,7 @@ import Divider from 'material-ui/Divider'
import ActionAndroid from 'material-ui-icons/Android' import ActionAndroid from 'material-ui-icons/Android'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import config from 'src/config' import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -104,18 +105,18 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
* Handle register form * Handle register form
*/ */
handleForm = () => { handleForm = () => {
const {translate} = this.props
let error = false let error = false
if (this.state.emailInput === '') { if (this.state.emailInput === '') {
this.setState({ this.setState({
emailInputError: 'This field is required' emailInputError: translate!('login.emailRequiredError')
}) })
error = true error = true
} }
if (this.state.passwordInput === '') { if (this.state.passwordInput === '') {
this.setState({ this.setState({
passwordInputError: 'This field is required' passwordInputError: translate!('login.passwordRequiredError')
}) })
error = true error = true
@@ -135,7 +136,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {classes} = this.props const {classes, loginWithOAuth, translate} = this.props
const paperStyle = { const paperStyle = {
minHeight: 370, minHeight: 370,
@@ -145,7 +146,6 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
margin: 'auto' margin: 'auto'
} }
const {loginWithOAuth} = this.props
return ( return (
<form> <form>
@@ -174,7 +174,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0 margin: 0
}} className='zoomOutLCorner animated'>Sign in</h2> }} className='zoomOutLCorner animated'>{translate!('login.title')}</h2>
</div> </div>
<div style={this.styles.singinOptions as any}> <div style={this.styles.singinOptions as any}>
<IconButton <IconButton
@@ -196,7 +196,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
helperText={this.state.emailInputError} helperText={this.state.emailInputError}
error={this.state.emailInputError.trim() !== ''} error={this.state.emailInputError.trim() !== ''}
name='emailInput' name='emailInput'
label='Email' label={translate!('login.emailLabel')}
type='email' type='email'
tabIndex={1} tabIndex={1}
/><br /> /><br />
@@ -206,7 +206,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
helperText={this.state.passwordInputError} helperText={this.state.passwordInputError}
error={this.state.passwordInputError.trim() !== ''} error={this.state.passwordInputError.trim() !== ''}
name='passwordInput' name='passwordInput'
label='Password' label={translate!('login.passwordLabel')}
type='password' type='password'
tabIndex={2} tabIndex={2}
/><br /> /><br />
@@ -214,13 +214,13 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
<br /> <br />
<div className='login__button-box'> <div className='login__button-box'>
<div> <div>
<Button onClick={this.props.signupPage} tabIndex={4}> Create an account </Button> <Button onClick={this.props.signupPage} tabIndex={4}>{translate!('login.createAccountButton')}</Button>
</div> </div>
<div > <div >
<Button raised color='primary' onClick={this.handleForm} tabIndex={3} > Login </Button> <Button raised color='primary' onClick={this.handleForm} tabIndex={3} >{translate!('login.loginButton')}</Button>
</div> </div>
</div> </div>
<span style={this.styles.restPassword as any}>Have you forgot your password? <NavLink to='/resetPassword' style={this.styles.restPasswordLink}>reset your password</NavLink></span> <span style={this.styles.restPassword as any}>{translate!('login.forgetPasswordMessage')} <NavLink to='/resetPassword' style={this.styles.restPasswordLink}>{translate!('login.resetPasswordLabel')}</NavLink></span>
</div> </div>
</Paper> </Paper>
</div> </div>
@@ -255,7 +255,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: ILoginComponentProps) => {
*/ */
const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => { const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => {
return { return {
translate: getTranslate(state.locale)
} }
} }

View File

@@ -41,7 +41,9 @@ const styles = (theme: any) => ({
pointerEvents: 'none' pointerEvents: 'none'
}, },
popperOpen: { popperOpen: {
zIndex: 1 zIndex: 1,
maxWidth: 500,
overflowY: 'auto'
} }
}) })

View File

@@ -29,4 +29,9 @@ export interface IPeopleComponentProps {
* @memberof IPeopleComponentProps * @memberof IPeopleComponentProps
*/ */
setHeaderTitle?: (title: string) => any setHeaderTitle?: (title: string) => any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -8,6 +8,7 @@ import { grey, cyan } from 'material-ui/colors'
import { push } from 'react-router-redux' import { push } from 'react-router-redux'
import AppBar from 'material-ui/AppBar' import AppBar from 'material-ui/AppBar'
import Typography from 'material-ui/Typography' import Typography from 'material-ui/Typography'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import FindPeople from 'components/findPeople' import FindPeople from 'components/findPeople'
@@ -125,7 +126,7 @@ export class PeopleComponent extends Component<IPeopleComponentProps,IPeopleComp
} }
} }
const {circlesLoaded, goTo, setHeaderTitle} = this.props const {circlesLoaded, goTo, setHeaderTitle, translate} = this.props
const {tabIndex} = this.state const {tabIndex} = this.state
return ( return (
<div style={styles.people}> <div style={styles.people}>
@@ -135,9 +136,9 @@ export class PeopleComponent extends Component<IPeopleComponentProps,IPeopleComp
value={tabIndex} centered value={tabIndex} centered
textColor='primary' textColor='primary'
> >
<Tab label='Find People' /> <Tab label={translate!('people.findPeopleTab')} />
<Tab label='Following' /> <Tab label={translate!('people.followingTab')} />
<Tab label='Followers' /> <Tab label={translate!('people.followersTab')} />
</Tabs> </Tabs>
</AppBar> </AppBar>
{tabIndex === 0 && <TabContainer>{circlesLoaded ? <FindPeople /> : ''}</TabContainer>} {tabIndex === 0 && <TabContainer>{circlesLoaded ? <FindPeople /> : ''}</TabContainer>}
@@ -190,6 +191,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPeopleComponentProps) => {
const mapStateToProps = (state: any, ownProps: IPeopleComponentProps) => { const mapStateToProps = (state: any, ownProps: IPeopleComponentProps) => {
return { return {
translate: getTranslate(state.locale),
uid: state.authorize.uid, uid: state.authorize.uid,
circlesLoaded: state.circle.loaded circlesLoaded: state.circle.loaded

View File

@@ -119,4 +119,9 @@ export interface IPostComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -7,6 +7,7 @@ import PropTypes from 'prop-types'
import moment from 'moment/moment' import moment from 'moment/moment'
import Linkify from 'react-linkify' import Linkify from 'react-linkify'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Material UI // - Material UI
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui' import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
@@ -262,9 +263,10 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
* @memberof Post * @memberof Post
*/ */
handleCopyLink = () => { handleCopyLink = () => {
const {translate} = this.props
this.setState({ this.setState({
openCopyLink: true, openCopyLink: true,
shareTitle: 'Copy Link' shareTitle: translate!('post.copyLinkButton')
}) })
} }
@@ -336,7 +338,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const { post, setHomeTitle, goTo, fullName, isPostOwner, commentList, avatar, classes } = this.props const { post, setHomeTitle, goTo, fullName, isPostOwner, commentList, avatar, classes , translate} = this.props
const { postMenuAnchorEl, isPostMenuOpen } = this.state const { postMenuAnchorEl, isPostMenuOpen } = this.state
const RightIconMenu = () => ( const RightIconMenu = () => (
<Manager> <Manager>
@@ -359,15 +361,15 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Grow in={isPostMenuOpen!} style={{ transformOrigin: '0 0 0' }}> <Grow in={isPostMenuOpen!} style={{ transformOrigin: '0 0 0' }}>
<Paper> <Paper>
<MenuList role='menu'> <MenuList role='menu'>
<MenuItem onClick={this.handleOpenPostWrite} > Edit </MenuItem> <MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem>
<MenuItem onClick={this.handleDelete} > Delete </MenuItem> <MenuItem onClick={this.handleDelete} > {translate!('post.delete')} </MenuItem>
<MenuItem <MenuItem
onClick={() => this.props.toggleDisableComments!(!post.disableComments)} > onClick={() => this.props.toggleDisableComments!(!post.disableComments)} >
{post.disableComments ? 'Enable comments' : 'Disable comments'} {post.disableComments ? translate!('post.enableComments') : translate!('post.disableComments')}
</MenuItem> </MenuItem>
<MenuItem <MenuItem
onClick={() => this.props.toggleSharingComments!(!post.disableSharing)} > onClick={() => this.props.toggleSharingComments!(!post.disableSharing)} >
{post.disableSharing ? 'Enable sharing' : 'Disable sharing'} {post.disableSharing ? translate!('post.enableSharing') : translate!('post.disableSharing')}
</MenuItem> </MenuItem>
</MenuList> </MenuList>
</Paper> </Paper>
@@ -383,7 +385,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Card> <Card>
<CardHeader <CardHeader
title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>} title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>}
subheader={moment.unix(creationDate!).fromNow() + ' | public'} subheader={moment.unix(creationDate!).fromNow() + ' | ' + translate!('post.public')}
avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>} avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>}
action={isPostOwner ? <RightIconMenu /> : ''} action={isPostOwner ? <RightIconMenu /> : ''}
> >
@@ -461,7 +463,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<ListItemIcon> <ListItemIcon>
<SvgLink /> <SvgLink />
</ListItemIcon> </ListItemIcon>
<ListItemText inset primary='Copy Link' /> <ListItemText inset primary={translate!('post.copyLinkButton')} />
</MenuItem> </MenuItem>
</MenuList>) </MenuList>)
: <div> : <div>
@@ -527,6 +529,7 @@ const mapStateToProps = (state: any, ownProps: IPostComponentProps) => {
const postOwner = (post.userPosts[uid] ? Object.keys(post.userPosts[uid]).filter((key) => { return ownProps.post.id === key }).length : 0) const postOwner = (post.userPosts[uid] ? Object.keys(post.userPosts[uid]).filter((key) => { return ownProps.post.id === key }).length : 0)
const commentList: { [commentId: string]: Comment } = comment.postComments[ownProps.post.id!] const commentList: { [commentId: string]: Comment } = comment.postComments[ownProps.post.id!]
return { return {
translate: getTranslate(state.locale),
commentList, commentList,
avatar: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].avatar || '' : '', avatar: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].avatar || '' : '',
fullName: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].fullName || '' : '', fullName: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].fullName || '' : '',

View File

@@ -75,4 +75,9 @@ export interface IPostWriteComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -2,6 +2,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui' import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
import List, { import List, {
@@ -366,13 +367,13 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
*/ */
render () { render () {
const { classes } = this.props const { classes, translate } = this.props
const { menuOpen } = this.state const { menuOpen } = this.state
const rightIconMenu = ( const rightIconMenu = (
<Manager> <Manager>
<Target> <Target>
<Tooltip id='tooltip-icon' title='more' placement='bottom-start'> <Tooltip id='tooltip-icon' title={translate!('post.moreTooltip')} placement='bottom-start'>
<IconButton <IconButton
onClick={this.handleOpenMenu} onClick={this.handleOpenMenu}
> >
@@ -413,7 +414,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
}}>{this.props.ownerDisplayName}</span><span style={{ }}>{this.props.ownerDisplayName}</span><span style={{
fontWeight: 100, fontWeight: 100,
fontSize: '10px' fontSize: '10px'
}}> | Public</span> }}> | {translate!('post.public')}</span>
</div> </div>
) )
@@ -483,7 +484,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
autoFocus autoFocus
value={this.state.postText} value={this.state.postText}
onChange={this.handleOnChange} onChange={this.handleOnChange}
placeholder='What is new with you?' placeholder={translate!('post.textareaPlaceholder')}
multiline multiline
rows={2} rows={2}
rowsMax={4} rowsMax={4}
@@ -514,7 +515,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
onClick={this.props.onRequestClose} onClick={this.props.onRequestClose}
style={{ color: grey[800] }} style={{ color: grey[800] }}
> >
Cancel {translate!('post.cancelButton')}
</Button> </Button>
<Button <Button
color='primary' color='primary'
@@ -523,7 +524,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
onClick={this.handlePost} onClick={this.handlePost}
disabled={this.state.disabledPost} disabled={this.state.disabledPost}
> >
{this.props.edit ? 'UPDATE' : 'POST'} {this.props.edit ? translate!('post.updateButton') : translate!('post.postButton')}
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
@@ -543,7 +544,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
onClick={this.handleCloseGallery} onClick={this.handleCloseGallery}
style={{ color: grey[800] }} style={{ color: grey[800] }}
> >
Cancel {translate!('post.cancelButton')}
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
@@ -574,6 +575,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPostWriteComponentProps) =
*/ */
const mapStateToProps = (state: any, ownProps: IPostWriteComponentProps) => { const mapStateToProps = (state: any, ownProps: IPostWriteComponentProps) => {
return { return {
translate: getTranslate(state.locale),
postImageState: state.imageGallery.status, postImageState: state.imageGallery.status,
ownerAvatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '', ownerAvatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
ownerDisplayName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : '' ownerDisplayName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : ''

View File

@@ -84,4 +84,9 @@ export interface IProfileComponentProps {
* If there is more posts to show in profile * If there is more posts to show in profile
*/ */
hasMorePosts: boolean hasMorePosts: boolean
/**
* Translate to locale string
*/
translate?: (state: any, params?: {}) => any
} }

View File

@@ -5,6 +5,7 @@ import PropTypes from 'prop-types'
import Dialog from 'material-ui/Dialog' import Dialog from 'material-ui/Dialog'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button' import RaisedButton from 'material-ui/Button'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import ProfileHeader from 'components/profileHeader' import ProfileHeader from 'components/profileHeader'
@@ -77,7 +78,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
border: '2px solid rgb(255, 255, 255)' border: '2px solid rgb(255, 255, 255)'
} }
} }
const {loadPosts, hasMorePosts} = this.props const {loadPosts, hasMorePosts, translate} = this.props
const St = StreamComponent as any const St = StreamComponent as any
return ( return (
<div style={styles.profile}> <div style={styles.profile}>
@@ -88,7 +89,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
{this.props.posts && Object.keys(this.props.posts).length !== 0 {this.props.posts && Object.keys(this.props.posts).length !== 0
? (<div style={styles.content}> ? (<div style={styles.content}>
<div className='profile__title'> <div className='profile__title'>
{this.props.name}'s posts {translate!('profile.headPostsLabel', {userName: this.props.name})}
</div> </div>
<div style={{ height: '24px' }}></div> <div style={{ height: '24px' }}></div>
@@ -99,7 +100,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
displayWriting={false} /> displayWriting={false} />
</div>) </div>)
: (<div className='profile__title'> : (<div className='profile__title'>
Nothing shared {translate!('profile.nothingSharedLabel')}
</div>) </div>)
} }
@@ -135,6 +136,7 @@ const mapStateToProps = (state: any, ownProps: IProfileComponentProps) => {
const hasMorePosts = state.post.profile.hasMoreData const hasMorePosts = state.post.profile.hasMoreData
const posts = state.post.userPosts ? state.post.userPosts[userId] : {} const posts = state.post.userPosts ? state.post.userPosts[userId] : {}
return { return {
translate: getTranslate(state.locale),
avatar: state.user.info && state.user.info[userId] ? state.user.info[userId].avatar || '' : '', avatar: state.user.info && state.user.info[userId] ? state.user.info[userId].avatar || '' : '',
name: state.user.info && state.user.info[userId] ? state.user.info[userId].fullName || '' : '', name: state.user.info && state.user.info[userId] ? state.user.info[userId].fullName || '' : '',
banner: state.user.info && state.user.info[userId] ? state.user.info[userId].banner || '' : '', banner: state.user.info && state.user.info[userId] ? state.user.info[userId].banner || '' : '',

View File

@@ -62,4 +62,9 @@ export interface IProfileHeaderComponentProps {
* @memberof IProfileHeaderComponentProps * @memberof IProfileHeaderComponentProps
*/ */
userId: string userId: string
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -10,6 +10,7 @@ import Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button' import RaisedButton from 'material-ui/Button'
import EventListener, { withOptions } from 'react-event-listener' import EventListener, { withOptions } from 'react-event-listener'
import { Parallax, Background } from 'react-parallax' import { Parallax, Background } from 'react-parallax'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import ImgCover from 'components/imgCover' import ImgCover from 'components/imgCover'
@@ -113,7 +114,7 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
* @return {react element} return the DOM which rendered by component * @return {react element} return the DOM which rendered by component
*/ */
render () { render () {
const {translate, isAuthedUser} = this.props
const styles = { const styles = {
avatar: { avatar: {
border: '2px solid rgb(255, 255, 255)' border: '2px solid rgb(255, 255, 255)'
@@ -165,8 +166,6 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
</div> </div>
) )
const {isAuthedUser} = this.props
return ( return (
<div> <div>
@@ -200,7 +199,7 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
<div className='right'> <div className='right'>
{isAuthedUser ? (<div style={this.state.isSmall ? styles.editButtonSmall : styles.editButton}> {isAuthedUser ? (<div style={this.state.isSmall ? styles.editButtonSmall : styles.editButton}>
<Button raised onClick={this.props.openEditor}> <Button raised onClick={this.props.openEditor}>
EDIT PROFILE {translate!('profile.editProfileButton')}
</Button> </Button>
</div>) : ''} </div>) : ''}
</div> </div>
@@ -236,6 +235,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IProfileHeaderComponentProp
const mapStateToProps = (state: any, ownProps: IProfileHeaderComponentProps) => { const mapStateToProps = (state: any, ownProps: IProfileHeaderComponentProps) => {
return { return {
translate: getTranslate(state.locale)
} }
} }

View File

@@ -18,4 +18,9 @@ export interface IResetPasswordComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -10,6 +10,7 @@ import Button from 'material-ui/Button'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import Typography from 'material-ui/Typography' import Typography from 'material-ui/Typography'
import config from 'src/config' import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -71,11 +72,11 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
* Handle register form * Handle register form
*/ */
handleForm = () => { handleForm = () => {
const {translate} = this.props
let error = false let error = false
if (this.state.emailInput === '') { if (this.state.emailInput === '') {
this.setState({ this.setState({
emailInputError: 'This field is required' emailInputError: translate!('resetPassword.emailRequiredError')
}) })
return return
@@ -90,7 +91,7 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
*/ */
render () { render () {
const {classes} = this.props const {classes, translate} = this.props
const paperStyle = { const paperStyle = {
minHeight: 370, minHeight: 370,
@@ -127,7 +128,7 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0 margin: 0
}} className='zoomOutLCorner animated'>Reset Password</h2> }} className='zoomOutLCorner animated'>{translate!('resetPassword.title')}</h2>
</div> </div>
<TextField <TextField
@@ -137,22 +138,21 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
helperText={this.state.emailInputError} helperText={this.state.emailInputError}
error={this.state.emailInputError.trim() !== ''} error={this.state.emailInputError.trim() !== ''}
name='emailInput' name='emailInput'
label='Email' label={translate!('resetPassword.emailLabel')}
type='email' type='email'
/><br /> /><br />
<br /> <br />
<br /> <br />
<div className='settings__button-box'> <div className='settings__button-box'>
<div> <div>
<Button onClick={this.props.loginPage}> Back </Button> <Button onClick={this.props.loginPage}>{translate!('resetPassword.backButton')}</Button>
</div> </div>
<div> <div>
<Button raised color='primary' onClick={this.handleForm}> Reset password </Button> <Button raised color='primary' onClick={this.handleForm}>{translate!('resetPassword.resetPasswordButton')} </Button>
</div> </div>
</div> </div>
<Typography className={classes.caption} type='caption' component='p'> <Typography className={classes.caption} type='caption' component='p'>
Please put your email and click on "RESET PASSWORD". If not click on "BACK". {translate!('resetPassword.description')}
We will send you an email contains the link of the reset password.
</Typography> </Typography>
</div> </div>
</Paper> </Paper>
@@ -185,7 +185,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IResetPasswordComponen
*/ */
const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => { const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => {
return { return {
translate: getTranslate(state.locale),
} }
} }

View File

@@ -27,4 +27,10 @@ export interface ISendFeedbackComponentProps {
* Current user profile * Current user profile
*/ */
currentUser?: Profile currentUser?: Profile
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -10,6 +10,7 @@ import SvgSad from 'material-ui-icons/Face'
import SvgClose from 'material-ui-icons/Clear' import SvgClose from 'material-ui-icons/Clear'
import { CircularProgress } from 'material-ui/Progress' import { CircularProgress } from 'material-ui/Progress'
import Tooltip from 'material-ui/Tooltip' import Tooltip from 'material-ui/Tooltip'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
@@ -73,12 +74,12 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
} }
mainForm = () => { mainForm = () => {
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest } = this.props const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest, translate } = this.props
const { feedText } = this.state const { feedText } = this.state
return ( return (
<div className='main-box'> <div className='main-box'>
<TextField <TextField
placeholder='What do you feel?' placeholder={translate!('feedback.textareaPlaceholder')}
multiline multiline
onChange={this.handleFeedText} onChange={this.handleFeedText}
rows={2} rows={2}
@@ -88,7 +89,7 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
/> />
<br /> <br />
<div className='buttons'> <div className='buttons'>
<Tooltip title='Sad' placement='bottom-start'> <Tooltip title={translate!('feedback.sadTooltip')} placement='bottom-start'>
<IconButton <IconButton
className='flaticon-sad-2 icon__svg' className='flaticon-sad-2 icon__svg'
onClick={() => this.handleSendFeed(FeedType.Sad)} onClick={() => this.handleSendFeed(FeedType.Sad)}
@@ -96,21 +97,21 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title='Acceptable' placement='bottom-start'> <Tooltip title={translate!('feedback.acceptableTooltip')} placement='bottom-start'>
<IconButton <IconButton
className='flaticon-neutral icon__svg' className='flaticon-neutral icon__svg'
onClick={() => this.handleSendFeed(FeedType.Acceptable)} onClick={() => this.handleSendFeed(FeedType.Acceptable)}
> >
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title='Happy' placement='bottom-start'> <Tooltip title={translate!('feedback.happyTooltip')} placement='bottom-start'>
<IconButton <IconButton
className='flaticon-happy-2 icon__svg' className='flaticon-happy-2 icon__svg'
onClick={() => this.handleSendFeed(FeedType.Happy)} onClick={() => this.handleSendFeed(FeedType.Happy)}
> >
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title='Awesome' placement='bottom-start'> <Tooltip title={translate!('feedback.awesomeTooltip')} placement='bottom-start'>
<IconButton <IconButton
className='flaticon-happy icon__svg' className='flaticon-happy icon__svg'
onClick={() => this.handleSendFeed(FeedType.Awesome)} onClick={() => this.handleSendFeed(FeedType.Awesome)}
@@ -122,10 +123,11 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
} }
loadingForm = () => { loadingForm = () => {
const {translate} = this.props
return ( return (
<div className='loading'> <div className='loading'>
<p> <p>
Your feedback is sending! {translate!('feedback.sendingMessage')}
</p> </p>
<div className='icon'> <div className='icon'>
<CircularProgress <CircularProgress
@@ -141,11 +143,13 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
} }
successForm = () => { successForm = () => {
return (<div className='success'>We appreciate your kind support as always ;)</div>) const {translate} = this.props
return (<div className='success'>{translate!('feedback.appreciateMessage')}</div>)
} }
errorForm = () => { errorForm = () => {
return (<div className='error'>Error in sending feedback :(</div>) const {translate} = this.props
return (<div className='error'>{translate!('feedback.errorMessage')}</div>)
} }
getFeedbackForm = () => { getFeedbackForm = () => {
@@ -228,6 +232,7 @@ const mapStateToProps = (state: any, ownProps: ISendFeedbackComponentProps) => {
const sendFeedbackRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, uid)] : null const sendFeedbackRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, uid)] : null
return { return {
translate: getTranslate(state.locale),
sendFeedbackStatus, sendFeedbackStatus,
sendFeedbackRequest, sendFeedbackRequest,
currentUser currentUser

View File

@@ -18,4 +18,10 @@ export interface ISettingComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -9,6 +9,7 @@ import RaisedButton from 'material-ui/Button'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import config from 'src/config' import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -84,23 +85,23 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
* Handle register form * Handle register form
*/ */
handleForm = () => { handleForm = () => {
const {translate} = this.props
let error = false let error = false
if (this.state.passwordInput === '') { if (this.state.passwordInput === '') {
this.setState({ this.setState({
passwordInputError: 'This field is required' passwordInputError: translate!('changePassword.newPasswordRequiredError')
}) })
error = true error = true
} else if (this.state.confirmInput === '') { } else if (this.state.confirmInput === '') {
this.setState({ this.setState({
confirmInputError: 'This field is required' confirmInputError: translate!('changePassword.confirmPasswordRequiredError')
}) })
error = true error = true
} else if (this.state.confirmInput !== this.state.passwordInput) { } else if (this.state.confirmInput !== this.state.passwordInput) {
this.setState({ this.setState({
confirmInputError: 'Password and confirm password should be equal!' confirmInputError: translate!('changePassword.confirmPasswordEqualNewPasswordError')
}) })
error = true error = true
@@ -121,7 +122,7 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
*/ */
render () { render () {
const {classes} = this.props const {classes, translate} = this.props
const paperStyle = { const paperStyle = {
minHeight: 370, minHeight: 370,
width: 450, width: 450,
@@ -157,7 +158,7 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0 margin: 0
}} className='zoomOutLCorner animated'>Change Password</h2> }} className='zoomOutLCorner animated'>{translate!('changePassword.title')}</h2>
</div> </div>
<TextField <TextField
@@ -166,7 +167,7 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
onChange={this.handleInputChange} onChange={this.handleInputChange}
helperText={this.state.passwordInputError} helperText={this.state.passwordInputError}
name='passwordInput' name='passwordInput'
label='New password' label={translate!('changePassword.newPasswordLabel')}
type='password' type='password'
error={this.state.passwordInputError.trim() !== ''} error={this.state.passwordInputError.trim() !== ''}
/><br /> /><br />
@@ -175,7 +176,7 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
onChange={this.handleInputChange} onChange={this.handleInputChange}
helperText={this.state.confirmInputError} helperText={this.state.confirmInputError}
name='confirmInput' name='confirmInput'
label='Confirm password' label={translate!('changePassword.confirmPasswordLabel')}
type='password' type='password'
error={this.state.confirmInputError.trim() !== ''} error={this.state.confirmInputError.trim() !== ''}
/><br /> /><br />
@@ -183,10 +184,10 @@ export class SettingComponent extends Component<ISettingComponentProps,ISettingC
<br /> <br />
<div className='settings__button-box'> <div className='settings__button-box'>
<div> <div>
<Button onClick={this.props.homePage} > Home </Button> <Button onClick={this.props.homePage} > {translate!('changePassword.homeButton')} </Button>
</div> </div>
<div> <div>
<Button raised color='primary' onClick={this.handleForm}> Change password </Button> <Button raised color='primary' onClick={this.handleForm}> {translate!('changePassword.changePasswordButton')} </Button>
</div> </div>
</div> </div>
@@ -224,7 +225,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: ISettingComponentProps) =>
*/ */
const mapStateToProps = (state: any, ownProps: ISettingComponentProps) => { const mapStateToProps = (state: any, ownProps: ISettingComponentProps) => {
return { return {
translate: getTranslate(state.locale)
} }
} }

View File

@@ -25,4 +25,9 @@ export interface ISignupComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -9,6 +9,7 @@ import RaisedButton from 'material-ui/Button'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
import { withStyles } from 'material-ui/styles' import { withStyles } from 'material-ui/styles'
import config from 'src/config' import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions // - Import actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -105,7 +106,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
handleForm = () => { handleForm = () => {
const {fullNameInput, emailInput, passwordInput, confirmInput} = this.state const {fullNameInput, emailInput, passwordInput, confirmInput} = this.state
const {register} = this.props const {register, translate} = this.props
let error = false let error = false
@@ -117,7 +118,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
|| fullNameCheck.indexOf('asd') > -1 || fullNameCheck.indexOf('asd') > -1
|| fullNameCheck.length < 4) { || fullNameCheck.length < 4) {
this.setState({ this.setState({
fullNameInputError: 'Please enter a valid name.' fullNameInputError: translate!('signup.validNameError')
}) })
error = true error = true
} }
@@ -125,7 +126,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
/* Validate email*/ /* Validate email*/
if (!StringAPI.isValidEmail(emailInput)) { if (!StringAPI.isValidEmail(emailInput)) {
this.setState({ this.setState({
emailInputError: 'Please enter a valid email.' emailInputError: translate!('signup.validEmailError')
}) })
error = true error = true
@@ -134,21 +135,21 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
/* Check password */ /* Check password */
if (passwordInput === '') { if (passwordInput === '') {
this.setState({ this.setState({
passwordInputError: 'This field is required.' passwordInputError: translate!('signup.passwordRequiredError')
}) })
error = true error = true
} }
if (confirmInput === '') { if (confirmInput === '') {
this.setState({ this.setState({
confirmInputError: 'This field is required.' confirmInputError: translate!('signup.confirmRequiredError')
}) })
error = true error = true
} else if (confirmInput !== passwordInput) { } else if (confirmInput !== passwordInput) {
this.setState({ this.setState({
passwordInputError: 'This field sould be equal to confirm password.', passwordInputError: translate!('signup.passwordEqualConfirmError'),
confirmInputError: 'This field sould be equal to password.' confirmInputError: translate!('signup.confirmEqualPasswordError')
}) })
error = true error = true
@@ -169,7 +170,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
*/ */
render () { render () {
const {classes} = this.props const {classes, translate} = this.props
const paperStyle = { const paperStyle = {
minHeight: 500, minHeight: 500,
width: 450, width: 450,
@@ -204,7 +205,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
fontSize: '24px', fontSize: '24px',
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0}} className='zoomOutLCorner animated'>Sign up</h2> margin: 0}} className='zoomOutLCorner animated'>{translate!('signup.title')}</h2>
</div> </div>
<TextField <TextField
@@ -214,7 +215,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
helperText={this.state.fullNameInputError} helperText={this.state.fullNameInputError}
error={this.state.fullNameInputError.trim() !== ''} error={this.state.fullNameInputError.trim() !== ''}
name='fullNameInput' name='fullNameInput'
label='Full Name' label={translate!('signup.fullNameLabel')}
type='text' type='text'
/><br /> /><br />
<TextField <TextField
@@ -223,7 +224,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
helperText={this.state.emailInputError} helperText={this.state.emailInputError}
error={this.state.emailInputError.trim() !== ''} error={this.state.emailInputError.trim() !== ''}
name='emailInput' name='emailInput'
label='Email' label={translate!('signup.emailLabel')}
type='email' type='email'
/><br /> /><br />
<TextField <TextField
@@ -232,7 +233,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
helperText={this.state.passwordInputError} helperText={this.state.passwordInputError}
error={this.state.passwordInputError.trim() !== ''} error={this.state.passwordInputError.trim() !== ''}
name='passwordInput' name='passwordInput'
label='Password' label={translate!('signup.passwordLabel')}
type='password' type='password'
/><br /> /><br />
<TextField <TextField
@@ -241,16 +242,16 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
helperText={this.state.confirmInputError} helperText={this.state.confirmInputError}
error={this.state.confirmInputError.trim() !== ''} error={this.state.confirmInputError.trim() !== ''}
name='confirmInput' name='confirmInput'
label='Confirm Password' label={translate!('signup.confirmPasswordLabel')}
type='password' type='password'
/><br /> /><br />
<br /> <br />
<div className='signup__button-box'> <div className='signup__button-box'>
<div> <div>
<Button onClick={this.props.loginPage}> Login </Button> <Button onClick={this.props.loginPage}>{translate!('signup.loginButton')}</Button>
</div> </div>
<div> <div>
<Button raised color='primary' onClick={this.handleForm}> Create </Button> <Button raised color='primary' onClick={this.handleForm}>{translate!('signup.createButton')}</Button>
</div> </div>
</div> </div>
@@ -273,7 +274,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
const mapDispatchToProps = (dispatch: any,ownProps: ISignupComponentProps) => { const mapDispatchToProps = (dispatch: any,ownProps: ISignupComponentProps) => {
return { return {
showError: (message: string) => { showError: (message: string) => {
dispatch(globalActions.showErrorMessage(message)) dispatch(globalActions.showMessage(message))
}, },
register: (userRegister: UserRegisterModel) => { register: (userRegister: UserRegisterModel) => {
dispatch(authorizeActions.dbSignup(userRegister)) dispatch(authorizeActions.dbSignup(userRegister))
@@ -292,7 +293,7 @@ const mapDispatchToProps = (dispatch: any,ownProps: ISignupComponentProps) => {
*/ */
const mapStateToProps = (state: any,ownProps: ISignupComponentProps) => { const mapStateToProps = (state: any,ownProps: ISignupComponentProps) => {
return{ return{
translate: getTranslate(state.locale),
} }
} }

View File

@@ -88,4 +88,9 @@ export interface IStreamComponentProps {
* Router match property * Router match property
*/ */
match?: any match?: any
/**
* Translate to locale string
*/
translate?: (state: any) => any
} }

View File

@@ -9,6 +9,7 @@ import SvgCamera from 'material-ui-icons/PhotoCamera'
import Paper from 'material-ui/Paper' import Paper from 'material-ui/Paper'
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List' import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
import InfiniteScroll from 'react-infinite-scroller' import InfiniteScroll from 'react-infinite-scroller'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import PostComponent from 'components/post' import PostComponent from 'components/post'
@@ -202,7 +203,7 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
*/ */
render() { render() {
const { tag, displayWriting, hasMorePosts } = this.props const { tag, displayWriting, hasMorePosts, translate } = this.props
const postList = this.postLoad() as { evenPostList: Post[], oddPostList: Post[], divided: boolean } | any const postList = this.postLoad() as { evenPostList: Post[], oddPostList: Post[], divided: boolean } | any
return ( return (
@@ -224,7 +225,7 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
onClick={this.handleOpenPostWrite} onClick={this.handleOpenPostWrite}
> >
<UserAvatarComponent fullName={this.props.fullName!} fileName={this.props.avatar!} size={36} /> <UserAvatarComponent fullName={this.props.fullName!} fileName={this.props.avatar!} size={36} />
<ListItemText inset primary={<span style={this.styles.postWritePrimaryText as any}> What's new with you? </span>} /> <ListItemText inset primary={<span style={this.styles.postWritePrimaryText as any}> {translate!('home.postWriteButtonText')}</span>} />
<ListItemIcon> <ListItemIcon>
<SvgCamera /> <SvgCamera />
</ListItemIcon> </ListItemIcon>
@@ -278,6 +279,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IStreamComponentProps) => {
const mapStateToProps = (state: any, ownProps: IStreamComponentProps) => { const mapStateToProps = (state: any, ownProps: IStreamComponentProps) => {
const { post } = state const { post } = state
return { return {
translate: getTranslate(state.locale),
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '', avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : '' fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : ''
} }

View File

@@ -160,4 +160,9 @@ export interface IUserBoxComponentProps {
* Styles * Styles
*/ */
classes?: any classes?: any
/**
* Translate to locale string
*/
translate?: (state: any, param?: {}) => any
} }

View File

@@ -4,6 +4,9 @@ import moment from 'moment/moment'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { push } from 'react-router-redux' import { push } from 'react-router-redux'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Material UI
import Paper from 'material-ui/Paper' import Paper from 'material-ui/Paper'
import Button from 'material-ui/Button' import Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button' import RaisedButton from 'material-ui/Button'
@@ -295,7 +298,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
*/ */
render () { render () {
const { disabledDoneCircles } = this.state const { disabledDoneCircles } = this.state
const { isFollowed, followRequest, userId, isSelecteCirclesOpen, addToCircleRequest, deleteFollowingUserRequest, classes } = this.props const { isFollowed, followRequest, userId, isSelecteCirclesOpen, addToCircleRequest, deleteFollowingUserRequest, classes, translate } = this.props
return ( return (
<Paper key={userId} style={this.styles.paper} elevation={1} className='grid-cell'> <Paper key={userId} style={this.styles.paper} elevation={1} className='grid-cell'>
@@ -330,8 +333,8 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
(deleteFollowingUserRequest ? deleteFollowingUserRequest.status === ServerRequestStatusType.Sent : false) (deleteFollowingUserRequest ? deleteFollowingUserRequest.status === ServerRequestStatusType.Sent : false)
} }
> >
{!isFollowed ? 'Follow' {!isFollowed ? translate!('userBox.followButton')
: (this.props.belongCirclesCount! > 1 ? `${this.props.belongCirclesCount} Circles` : ((this.props.firstBelongCircle) ? this.props.firstBelongCircle.name : 'Follow'))} : (this.props.belongCirclesCount! > 1 ? translate!('userBox.numberOfCircleButton', {circlesCount: this.props.belongCirclesCount}) : ((this.props.firstBelongCircle) ? this.props.firstBelongCircle.name : translate!('userBox.followButton')))}
</Button> </Button>
</div> </div>
</div> </div>
@@ -350,14 +353,14 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
<ListItemText primary={ <ListItemText primary={
<TextField <TextField
autoFocus autoFocus
placeholder='Group name' placeholder={translate!('userBox.groupNamePlaceholder')}
onChange={this.handleChangeName} onChange={this.handleChangeName}
value={this.state.circleName} value={this.state.circleName}
/> />
} /> } />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<IconButton onClick={this.onCreateCircle} disabled={this.state.disabledCreateCircle}> <IconButton onClick={this.onCreateCircle} disabled={this.state.disabledCreateCircle}>
<Tooltip title='Create circle'> <Tooltip title={translate!('userBox.createCircleTooltip')}>
<SvgAdd /> <SvgAdd />
</Tooltip> </Tooltip>
</IconButton> </IconButton>
@@ -373,7 +376,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
onClick={this.onRequestCloseAddCircle} onClick={this.onRequestCloseAddCircle}
style={{ color: grey[800] }} style={{ color: grey[800] }}
> >
Cancel {translate!('userBox.cancelButton')}
</Button> </Button>
<Button <Button
color='primary' color='primary'
@@ -382,7 +385,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
disabled={disabledDoneCircles || (addToCircleRequest ? addToCircleRequest!.status === ServerRequestStatusType.Sent : false)} disabled={disabledDoneCircles || (addToCircleRequest ? addToCircleRequest!.status === ServerRequestStatusType.Sent : false)}
onClick={this.handleDoneAddCircle} onClick={this.handleDoneAddCircle}
> >
Done {translate!('userBox.doneButton')}
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
@@ -436,6 +439,7 @@ const mapStateToProps = (state: any, ownProps: IUserBoxComponentProps) => {
const isSelecteCirclesOpen = circle.openSelecteCircles ? circle.openSelecteCircles[ownProps.userId] : [] const isSelecteCirclesOpen = circle.openSelecteCircles ? circle.openSelecteCircles[ownProps.userId] : []
return { return {
translate: getTranslate(state.locale),
isSelecteCirclesOpen, isSelecteCirclesOpen,
isFollowed, isFollowed,
selectedCircles, selectedCircles,

View File

@@ -1,3 +1,5 @@
import { LanguageType } from 'reducers/locale/langugeType'
export const environment = { export const environment = {
firebase: { firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg', apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
@@ -8,6 +10,11 @@ export const environment = {
messagingSenderId: '964743099489' messagingSenderId: '964743099489'
}, },
settings: { settings: {
appName: 'Green' appName: 'Green',
defaultLanguage: LanguageType.English
},
theme: {
primaryColor: '#00b1b3',
secondaryColor: '#4d545d'
} }
} }

View File

@@ -1,3 +1,5 @@
import { LanguageType } from 'reducers/locale/langugeType'
export const environment = { export const environment = {
firebase: { firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg', apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
@@ -8,6 +10,11 @@ export const environment = {
messagingSenderId: '964743099489' messagingSenderId: '964743099489'
}, },
settings: { settings: {
appName: 'Green' appName: 'Green',
defaultLanguage: LanguageType.English
},
theme: {
primaryColor: '#00b1b3',
secondaryColor: '#4d545d'
} }
} }

View File

@@ -5,10 +5,8 @@ export enum GlobalActionType {
DEFAULT_DATA_ENABLE = 'DEFAULT_DATA_ENABLE', DEFAULT_DATA_ENABLE = 'DEFAULT_DATA_ENABLE',
LOADING = 'LOADING', LOADING = 'LOADING',
HIDE_MESSAGE_GLOBAL = 'HIDE_MESSAGE_GLOBAL', HIDE_MESSAGE_GLOBAL = 'HIDE_MESSAGE_GLOBAL',
SHOW_ERROR_MESSAGE_GLOBAL = 'SHOW_ERROR_MESSAGE_GLOBAL', SHOW_MESSAGE_GLOBAL = 'SHOW_MESSAGE_GLOBAL',
SHOW_NORMAL_MESSAGE_GLOBAL = 'SHOW_NORMAL_MESSAGE_GLOBAL', SHOW_NORMAL_MESSAGE_GLOBAL = 'SHOW_NORMAL_MESSAGE_GLOBAL',
SHOW_SEND_REQUEST_MESSAGE_GLOBAL = 'SHOW_SEND_REQUEST_MESSAGE_GLOBAL',
SHOW_REQUEST_SUCCESS_MESSAGE_GLOBAL = 'SHOW_REQUEST_SUCCESS_MESSAGE_GLOBAL',
SET_HEADER_TITLE = 'SET_HEADER_TITLE', SET_HEADER_TITLE = 'SET_HEADER_TITLE',
SHOW_TOP_LOADING = 'SHOW_TOP_LOADING', SHOW_TOP_LOADING = 'SHOW_TOP_LOADING',
HIDE_TOP_LOADING = 'HIDE_TOP_LOADING', HIDE_TOP_LOADING = 'HIDE_TOP_LOADING',

View File

@@ -6,11 +6,15 @@ import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'
import 'reflect-metadata' import 'reflect-metadata'
import 'typeface-roboto' import 'typeface-roboto'
import registerServiceWorker from './registerServiceWorker' import registerServiceWorker from './registerServiceWorker'
import config from 'src/config'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import store, { history } from 'store/configureStore' import store, { history } from 'store/configureStore'
import { ConnectedRouter } from 'react-router-redux' import { ConnectedRouter } from 'react-router-redux'
// - Actions
import * as localeActions from 'actions/localeActions'
// - Import app components // - Import app components
import Master from 'components/master' import Master from 'components/master'
// import { App } from 'components/AWS' // import { App } from 'components/AWS'
@@ -19,16 +23,20 @@ import Master from 'components/master'
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
store.subscribe(() => { }) store.subscribe(() => { })
// - Initialize languages
store.dispatch(localeActions.initTranslation())
// Needed for onClick // Needed for onClick
// http://stackoverflow.com/a/34015469/988941 // http://stackoverflow.com/a/34015469/988941
try { injectTapEventPlugin() } catch (e) {} try { injectTapEventPlugin() } catch (e) {}
const theme = createMuiTheme({ const theme = createMuiTheme({
palette: { palette: {
primary: { main: '#00b1b3' }, primary: { main: config.theme.primaryColor },
secondary: { main: '#4d545d' } secondary: { main: config.theme.secondaryColor }
} }
}) })
// App css // App css
import './styles/app.css' import './styles/app.css'

154
src/locale/en.json Normal file
View File

@@ -0,0 +1,154 @@
{
"sidebar" : {
"home": "Home",
"profile": "Profile",
"people": "People",
"settings": "Settings",
"sendFeedback": "Send Feedback"
},
"header": {
"home":"Home",
"notificationTooltip": "Notifications",
"myAccount": "My Account",
"logout": "Logout"
},
"home": {
"postWriteButtonText": "What's new with you?"
},
"post": {
"edit": "Edit",
"delete": "Delete",
"disableComments": "Disable Comments",
"disableSharing": "Disable Sharing",
"enableComments": "Enable Comments",
"enableSharing": "Enable Sharing",
"public": "public",
"textareaPlaceholder": "What's new with you?",
"moreTooltip": "more",
"postButton": "POST",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"copyLinkButton": "Copy Link"
},
"imageGallery": {
"uploadButton": "UPLOAD",
"cancelButton": "CANCEL"
},
"image": {
"notLoaded": "Image has not loaded!"
},
"comment": {
"postButton": "POST",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"addCommentPlaceholder": "Add a comment ...",
"updateCommentPlaceholder": "Write your comment ...",
"replyButton": "Reply",
"editButton": "Edit",
"deleteButton": "Delete"
},
"profile": {
"editProfileButton": "Edit Profile",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"fullName": "Full Name",
"tagline": "Tagline",
"personalInformationLabel": "Personal Information",
"headPostsLabel": "${userName}'s posts",
"nothingSharedLabel": " Nothing shared",
"chooseAvatarDialogTitle": "Choose an avatar image",
"chooseBanerDialogTitle": "Choose an baner image"
},
"people": {
"findPeopleTab": "FIND PEOPLE",
"followingTab": "FOLLOWING",
"followersTab": "FOLLOWERS",
"suggestionsForYouLabel": "Suggestions for you",
"nothingToShowLabel": "Nothing to show! :(",
"followingLabel": "Following",
"noFollowingLabel": "No following user!",
"followersLabel": "Followers",
"noFollowersLabel": "No followers!"
},
"userBox": {
"followButton": "FOLLOW",
"cancelButton": "CANCEL",
"numberOfCircleButton": "${circlesCount} Circles",
"doneButton": "DONE",
"groupNamePlaceholder": "Group Name",
"createCircleTooltip": "Create Circle"
},
"changePassword": {
"title": "Change Password",
"newPasswordLabel": "New password",
"confirmPasswordLabel": "Confirm password",
"homeButton": "HOME",
"changePasswordButton": "CHANGE PASSWORD",
"newPasswordRequiredError": "This field is required",
"confirmPasswordRequiredError": "This field is required",
"confirmPasswordEqualNewPasswordError": "Password and confirm password should be equal!"
},
"feedback": {
"textareaPlaceholder": "What do you feel :) ?",
"sadTooltip": "Sad",
"acceptableTooltip": "Acceptable",
"happyTooltip": "Happy",
"awesomeTooltip": "Awesome",
"appreciateMessage": "We appreciate your kind support as always ;)",
"sendingMessage": "Your feedback is sending!",
"errorMessage": "Error in sending feedback :( "
},
"login": {
"title": "Sign in",
"emailLabel": "Email",
"passwordLabel": "Password",
"emailRequiredError": "This field is required.",
"passwordRequiredError": "This field is required.",
"createAccountButton": "CREATE AN ACCOUNT",
"loginButton": "LOGIN",
"forgetPasswordMessage": "Have you forgot your password?",
"resetPasswordLabel": "reset your password."
},
"signup": {
"title":"Sign up",
"fullNameLabel": "Full Name",
"emailLabel": "Email",
"passwordLabel": "Password",
"confirmPasswordLabel": "Confirm Password",
"validNameError":"Please enter a valid name.",
"validEmailError": "Please enter a valid email.",
"emailRequiredError": "This field is required.",
"passwordRequiredError": "This field is required.",
"confirmRequiredError": "This field is required.",
"passwordEqualConfirmError": "This field sould be equal to confirm password.",
"confirmEqualPasswordError": "This field sould be equal to password.",
"loginButton": "LOGIN",
"createButton": "CREATE"
},
"resetPassword": {
"title": "Reset Password",
"emailLabel": "Email",
"backButton": "BACK",
"resetPasswordButton": "RESET PASSWORD",
"emailRequiredError": "This field is required.",
"description": "Please put your email and click on `RESET PASSWORD`. If not click on `BACK`. We will send you an email contains the link of the reset password."
},
"emailVerification": {
"title": "Email Verification",
"homeButton": "HOME",
"sendButton": "Send Email Verification",
"description": "An verificiation email has been already sent to you. Please check your inbox. If you couldn't see the emai, please resend email verification."
},
"common": {
"sentRequestMessage": "Request has been sent.",
"successfulRequestMessage": "Request has been successful."
}
}

154
src/locale/es.json Normal file
View File

@@ -0,0 +1,154 @@
{
"sidebar" : {
"home": "Home",
"profile": "Profile",
"people": "People",
"settings": "Settings",
"sendFeedback": "Send Feedback"
},
"header": {
"home":"Home",
"notificationTooltip": "Notifications",
"myAccount": "My Account",
"logout": "Logout"
},
"home": {
"postWriteButtonText": "What's new with you?"
},
"post": {
"edit": "Edit",
"delete": "Delete",
"disableComments": "Disable Comments",
"disableSharing": "Disable Sharing",
"enableComments": "Enable Comments",
"enableSharing": "Enable Sharing",
"public": "public",
"textareaPlaceholder": "What's new with you?",
"moreTooltip": "more",
"postButton": "POST",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"copyLinkButton": "Copy Link"
},
"imageGallery": {
"uploadButton": "UPLOAD",
"cancelButton": "CANCEL"
},
"image": {
"notLoaded": "Image has not loaded!"
},
"comment": {
"postButton": "POST",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"addCommentPlaceholder": "Add a comment ...",
"updateCommentPlaceholder": "Write your comment ...",
"replyButton": "Reply",
"editButton": "Edit",
"deleteButton": "Delete"
},
"profile": {
"editProfileButton": "Edit Profile",
"cancelButton": "CANCEL",
"updateButton": "UPDATE",
"fullName": "Full Name",
"tagline": "Tagline",
"personalInformationLabel": "Personal Information",
"headPostsLabel": "${userName}'s posts",
"nothingSharedLabel": " Nothing shared",
"chooseAvatarDialogTitle": "Choose an avatar image",
"chooseBanerDialogTitle": "Choose an baner image"
},
"people": {
"findPeopleTab": "FIND PEOPLE",
"followingTab": "FOLLOWING",
"followersTab": "FOLLOWERS",
"suggestionsForYouLabel": "Suggestions for you",
"nothingToShowLabel": "Nothing to show! :(",
"followingLabel": "Following",
"noFollowingLabel": "No following user!",
"followersLabel": "Followers",
"noFollowersLabel": "No followers!"
},
"userBox": {
"followButton": "FOLLOW",
"cancelButton": "CANCEL",
"numberOfCircleButton": "${circlesCount} Circles",
"doneButton": "DONE",
"groupNamePlaceholder": "Group Name",
"createCircleTooltip": "Create Circle"
},
"changePassword": {
"title": "Change Password",
"newPasswordLabel": "New password",
"confirmPasswordLabel": "Confirm password",
"homeButton": "HOME",
"changePasswordButton": "CHANGE PASSWORD",
"newPasswordRequiredError": "This field is required",
"confirmPasswordRequiredError": "This field is required",
"confirmPasswordEqualNewPasswordError": "Password and confirm password should be equal!"
},
"feedback": {
"textareaPlaceholder": "What do you feel :) ?",
"sadTooltip": "Sad",
"acceptableTooltip": "Acceptable",
"happyTooltip": "Happy",
"awesomeTooltip": "Awesome",
"appreciateMessage": "We appreciate your kind support as always ;)",
"sendingMessage": "Your feedback is sending!",
"errorMessage": "Error in sending feedback :( "
},
"login": {
"title": "Sign in",
"emailLabel": "Email",
"passwordLabel": "Password",
"emailRequiredError": "This field is required.",
"passwordRequiredError": "This field is required.",
"createAccountButton": "CREATE AN ACCOUNT",
"loginButton": "LOGIN",
"forgetPasswordMessage": "Have you forgot your password?",
"resetPasswordLabel": "reset your password."
},
"signup": {
"title":"Sign up",
"fullNameLabel": "Full Name",
"emailLabel": "Email",
"passwordLabel": "Password",
"confirmPasswordLabel": "Confirm Password",
"validNameError":"Please enter a valid name.",
"validEmailError": "Please enter a valid email.",
"emailRequiredError": "This field is required.",
"passwordRequiredError": "This field is required.",
"confirmRequiredError": "This field is required.",
"passwordEqualConfirmError": "This field sould be equal to confirm password.",
"confirmEqualPasswordError": "This field sould be equal to password.",
"loginButton": "LOGIN",
"createButton": "CREATE"
},
"resetPassword": {
"title": "Reset Password",
"emailLabel": "Email",
"backButton": "BACK",
"resetPasswordButton": "RESET PASSWORD",
"emailRequiredError": "This field is required.",
"description": "Please put your email and click on `RESET PASSWORD`. If not click on `BACK`. We will send you an email contains the link of the reset password."
},
"emailVerification": {
"title": "Email Verification",
"homeButton": "HOME",
"sendButton": "Send Email Verification",
"description": "An verificiation email has been already sent to you. Please check your inbox. If you couldn't see the emai, please resend email verification."
},
"common": {
"sentRequestMessage": "Request has been sent.",
"successfulRequestMessage": "Request has been successful."
}
}

View File

@@ -31,7 +31,7 @@ export const globalReducer = (state: GlobalState = new GlobalState(), action: IG
...state, ...state,
defaultLoadDataStatus: true defaultLoadDataStatus: true
} }
case GlobalActionType.SHOW_ERROR_MESSAGE_GLOBAL: case GlobalActionType.SHOW_MESSAGE_GLOBAL:
return { return {
...state, ...state,
message: action.payload, message: action.payload,
@@ -43,18 +43,6 @@ export const globalReducer = (state: GlobalState = new GlobalState(), action: IG
message: action.payload, message: action.payload,
messageOpen: true messageOpen: true
} }
case GlobalActionType.SHOW_SEND_REQUEST_MESSAGE_GLOBAL:
return {
...state,
message: 'Request has been sent',
messageOpen: true
}
case GlobalActionType.SHOW_REQUEST_SUCCESS_MESSAGE_GLOBAL:
return {
...state,
message: 'Your request has processed successfuly',
messageOpen: true
}
case GlobalActionType.HIDE_MESSAGE_GLOBAL: case GlobalActionType.HIDE_MESSAGE_GLOBAL:
return { return {
...state, ...state,

View File

@@ -0,0 +1,198 @@
/**
* ISO 639-1 defines abbreviations for languages.
* Reference for country codes
* https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
*/
export enum LanguageType {
Abkhazian = 'ab',
Afar = 'aa',
Afrikaans = 'af',
Akan = 'ak',
Albanian = 'sq',
Amharic = 'am',
Arabic = 'ar',
Aragonese = 'an',
Armenian = 'hy',
Assamese = 'as',
Avaric = 'av',
Avestan = 'ae',
Aymara = 'ay',
Azerbaijani = 'az',
Bambara = 'bm',
Bashkir = 'ba',
Basque = 'eu',
Belarusian = 'be',
BengaliBangla = 'bn',
Bihari = 'bh',
Bislama = 'bi',
Bosnian = 'bs',
Breton= 'br',
Bulgarian = 'bg',
Burmese = 'my',
Catalan = 'ca',
Chamorro = 'ch',
Chechen = 'ce',
ChichewaChewaNyanja = 'ny',
Chinese = 'zh',
ChineseSimplified = 'zh-Hans',
ChineseTraditional = 'zh-Hant',
Chuvash = 'cv',
Cornish = 'kw',
Corsican = 'co',
Cree = 'cr',
Croatian = 'hr',
Czech = 'cs',
Danish = 'da',
DivehiDhivehiMaldivian = 'dv',
Dutch = 'nl',
Dzongkha = 'dz',
English = 'en',
Esperanto = 'eo',
Estonian = 'et',
Ewe = 'ee',
Faroese = 'fo',
Fijian = 'fj',
Finnish = 'fi',
French = 'fr',
FulaFulahPulaarPular = 'ff',
Galician = 'gl',
GaelicScottish = 'gd',
GaelicManx = 'gv',
Georgian = 'ka',
German = 'de',
Greek = 'el',
Greenlandic = 'kl',
Guarani = 'gn',
Gujarati = 'gu',
HaitianCreole = 'ht',
Hausa = 'ha',
Hebrew = 'he',
Herero = 'hz',
Hindi = 'hi',
HiriMotu = 'ho',
Hungarian = 'hu',
Icelandic = 'is',
Ido = 'io',
Igbo = 'ig',
Indonesian = 'in',
Interlingua = 'ia',
Interlingue = 'ie',
Inuktitut = 'iu',
Inupiak = 'ik',
Irish = 'ga',
Italian = 'it',
Japanese = 'ja',
Javanese = 'jv',
KalaallisutGreenlandic = 'kl',
Kannada = 'kn',
Kanuri = 'kr',
Kashmiri = 'ks',
Kazakh = 'kk',
Khmer = 'km',
Kikuyu = 'ki',
KinyarwandaRwanda = 'rw',
Kirundi = 'rn',
Kyrgyz = 'ky',
Komi = 'kv',
Kongo = 'kg',
Korean = 'ko',
Kurdish = 'ku',
Kwanyama = 'kj',
Lao = 'lo',
Latin = 'la',
LatvianLettish = 'lv',
LimburgishLimburger = 'li',
Lingala = 'ln',
Lithuanian = 'lt',
LugaKatanga = 'lu',
LugandaGanda = 'lg',
Luxembourgish = 'lb',
Manx = 'gv',
Macedonian = 'mk',
Malagasy = 'mg',
Malay = 'ms',
Malayalam = 'ml',
Maltese = 'mt',
Maori = 'mi',
Marathi = 'mr',
Marshallese = 'mh',
Moldavian = 'mo',
Mongolian = 'mn',
Nauru = 'na',
Navajo = 'nv',
Ndonga = 'ng',
NorthernNdebele = 'nd',
Nepali = 'ne',
Norwegian = 'no',
Norwegianbokmål = 'nb',
NorwegianNynorsk = 'nn',
Nuosu = 'ii',
Occitan = 'oc',
Ojibwe = 'oj',
OldChurchSlavonicOldBulgarian = 'cu',
Oriya = 'or',
OromoAfaanOromo = 'om',
Ossetian = 'os',
Pāli = 'pi',
PashtoPushto = 'ps',
PersianFarsi = 'fa',
Polish = 'pl',
Portuguese = 'pt',
PunjabiEastern = 'pa',
Quechua = 'qu',
Romansh = 'rm',
Romanian = 'ro',
Russian = 'ru',
Sami = 'se',
Samoan = 'sm',
Sango = 'sg',
Sanskrit = 'sa',
Serbian = 'sr',
SerboCroatian = 'sh',
Sesotho = 'st',
Setswana = 'tn',
Shona = 'sn',
SichuanYi = 'ii',
Sindhi = 'sd',
Sinhalese = 'si',
Siswati = 'ss',
Slovak = 'sk',
Slovenian = 'sl',
Somali = 'so',
SouthernNdebele = 'nr',
Spanish = 'es',
Sundanese = 'su',
SwahiliKiswahili = 'sw',
Swati = 'ss',
Swedish = 'sv',
Tagalog = 'tl',
Tahitian = 'ty',
Tajik = 'tg',
Tamil = 'ta',
Tatar = 'tt',
Telugu = 'te',
Thai = 'th',
Tibetan = 'bo',
Tigrinya = 'ti',
Tonga = 'to',
Tsonga = 'ts',
Turkish = 'tr',
Turkmen = 'tk',
Twi = 'tw',
Uyghur = 'ug',
Ukrainian = 'uk',
Urdu = 'ur',
Uzbek = 'uz',
Venda = 've',
Vietnamese = 'vi',
Volapük = 'vo',
Wallon = 'wa',
Welsh = 'cy',
Wolof = 'wo',
WesternFrisian = 'fy',
Xhosa = 'xh',
Yiddish = 'yi',
Yoruba = 'yo',
ZhuangChuang = 'za',
Zulu = 'zu',
}

View File

@@ -4,6 +4,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom' import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components // - Import app components
import StreamComponent from 'components/stream' import StreamComponent from 'components/stream'
@@ -18,7 +19,7 @@ import { IRouterProps } from './IRouterProps'
*/ */
export class HomeRouter extends Component<IRouterProps, any> { export class HomeRouter extends Component<IRouterProps, any> {
render () { render () {
const { enabled, match, data } = this.props const { enabled, match, data, translate } = this.props
const St = StreamComponent as any const St = StreamComponent as any
return ( return (
enabled ? ( enabled ? (
@@ -33,7 +34,7 @@ export class HomeRouter extends Component<IRouterProps, any> {
<PrivateRoute path='/' component={( <PrivateRoute path='/' component={(
<div className='blog'> <div className='blog'>
<St <St
homeTitle='Home' homeTitle={translate!('header.home')}
posts={data.mergedPosts} posts={data.mergedPosts}
loadStream={data.loadDataStream} loadStream={data.loadDataStream}
hasMorePosts={data.hasMorePosts} hasMorePosts={data.hasMorePosts}
@@ -47,4 +48,22 @@ export class HomeRouter extends Component<IRouterProps, any> {
) )
} }
} }
export default withRouter(connect(null, null)(HomeRouter as any) as any)
// - Map dispatch to props
const mapDispatchToProps = (dispatch: any, ownProps: IRouterProps) => {
return {}
}
/**
* Map state to props
*/
const mapStateToProps = (state: any, ownProps: IRouterProps) => {
return {
translate: getTranslate(state.locale),
currentLanguage: getActiveLanguage(state.locale).code,
}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(HomeRouter as any) as any) as typeof HomeRouter

View File

@@ -23,4 +23,9 @@ export interface IRouterProps {
*/ */
match?: any match?: any
/**
* Translate to locale strting
*/
translate?: (state: any) => any
} }

View File

@@ -4,6 +4,7 @@ import thunk from 'redux-thunk'
import { routerReducer, routerMiddleware } from 'react-router-redux' import { routerReducer, routerMiddleware } from 'react-router-redux'
import createHistory from 'history/createBrowserHistory' import createHistory from 'history/createBrowserHistory'
import { createLogger } from 'redux-logger' import { createLogger } from 'redux-logger'
import { localeReducer as locale } from 'react-localize-redux'
// - Import reducers // - Import reducers
import { import {
@@ -19,8 +20,6 @@ import {
notificationReducer notificationReducer
} from 'reducers' } from 'reducers'
declare const window: any
// Create a history of your choosing (we're using a browser history in this case) // Create a history of your choosing (we're using a browser history in this case)
export const history = createHistory() export const history = createHistory()
@@ -30,6 +29,7 @@ const logger = createLogger()
// - Reducers // - Reducers
let reducer = redux.combineReducers({ let reducer = redux.combineReducers({
locale,
imageGallery: imageGalleryReducer, imageGallery: imageGalleryReducer,
post: postReducer, post: postReducer,
circle: circleReducer, circle: circleReducer,