[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

View File

@@ -76,7 +76,7 @@ export const dbLogin = (email: string, password: string) => {
dispatch(globalActions.showNotificationSuccess())
dispatch(login(result.uid, result.emailVerified))
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(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) => {
// 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(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.
switch (error.code) {
case 'auth/requires-recent-login':
dispatch(globalActions.showErrorMessage(error.code))
dispatch(globalActions.showMessage(error.code))
dispatch(dbLogout())
break
default:
@@ -184,7 +184,7 @@ export const dbResetPassword = (email: string) => {
})
.catch((error: SocialError) => {
// 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) => {
// 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
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) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
// Set server request status to {Error} for following user
followReqestModel.status = ServerRequestStatusType.Error
@@ -150,7 +150,7 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
dispatch(closeSelectCircleBox(userFollowing.userId!))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideMasterLoading())
@@ -189,7 +189,7 @@ export let dbDeleteFollowingUser = (userFollowingId: string) => {
deleteFollowingUserRequest.status = ServerRequestStatusType.OK
dispatch(serverActions.sendRequest(deleteFollowingUserRequest))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideMasterLoading())
@@ -219,7 +219,7 @@ export const dbUpdateCircle = (newCircle: Circle) => {
.then(() => {
dispatch(updateCircle({ id: newCircle.id, ...circle }))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
})
}
@@ -238,7 +238,7 @@ export const dbDeleteCircle = (circleId: string) => {
.then(() => {
dispatch(deleteCircle(circleId))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
})
}
@@ -257,7 +257,7 @@ export const dbGetCircles = () => {
dispatch(addCircles(circles))
})
.catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
})
}
@@ -278,7 +278,7 @@ export const dbGetUserTies = () => {
})
.catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
})
}
}
@@ -298,7 +298,7 @@ export const dbGetFollowers = () => {
})
.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))
})
.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) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading())
})
@@ -139,7 +139,7 @@ export const dbUpdateComment = (comment: Comment) => {
dispatch(globalActions.hideTopLoading())
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading())
})
@@ -153,7 +153,7 @@ export const dbDeleteComment = (id?: string | null, postId?: string) => {
return (dispatch: any, getState: Function) => {
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())
@@ -163,7 +163,7 @@ export const dbDeleteComment = (id?: string | null, postId?: string) => {
dispatch(globalActions.hideTopLoading())
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading())
})

View File

@@ -1,5 +1,6 @@
// - Import image gallery action types
import { GlobalActionType } from 'constants/globalActionType'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions
import * as serverActions from 'actions/serverActions'
@@ -36,7 +37,7 @@ export let dbSendFeed = (newFeed: Feed) => {
dispatch(serverActions.sendRequest(feedbackRequest))
})
.catch((error: SocialError) => {
dispatch(showErrorMessage(error.message))
dispatch(showMessage(error.message))
// Set server request status to {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
*/
@@ -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
*/
@@ -101,12 +108,12 @@ export const hideMessage = () => {
}
/**
* Show error message
* Show message
* @param {string} message
*/
export const showErrorMessage = (message: string) => {
export const showMessage = (message: string) => {
return {
type: GlobalActionType.SHOW_ERROR_MESSAGE_GLOBAL,
type: GlobalActionType.SHOW_MESSAGE_GLOBAL,
payload: message
}

View File

@@ -36,7 +36,7 @@ export const dbGetImageGallery = () => {
dispatch(addImageList(images))
})
.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) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
})
}
}
@@ -89,7 +89,7 @@ export const dbDeleteImage = (id: string) => {
dispatch(deleteImage(id))
})
.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())
})
.catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.code))
dispatch(globalActions.showMessage(error.code))
dispatch(globalActions.hideTopLoading())
})
}
@@ -143,7 +143,7 @@ export const dbDownloadImage = (fileName: string) => {
}
})
.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 userActions from './userActions'
import * as voteActions from './voteActions'
import * as localeActions from './localeActions'
export {
authorizeActions,
@@ -17,5 +18,6 @@ export {
notifyActions,
postActions,
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(() => {
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(() => {
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(() => {
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()
})
.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())
})
.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) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading())
})
@@ -150,7 +150,7 @@ export const dbDeletePost = (id: string) => {
})
.catch((error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
dispatch(globalActions.showMessage(error.message))
dispatch(globalActions.hideTopLoading())
})
}
@@ -195,7 +195,7 @@ export const dbGetPosts = (page: number = 0, limit: number = 10) => {
dispatch(addPosts(parsedData))
})
.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))
})
.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))
})
.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
}))
})
.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
}
})
.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(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))
})
.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.votes = { ...post.votes!, [uid]: false}
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.votes = { ...post.votes!, [uid]: true}
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 moment from 'moment/moment'
import Linkify from 'react-linkify'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import { Comment } from 'core/domain/comments'
@@ -293,7 +294,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
/**
* Comment object from props
*/
const { comment, classes, fullName, avatar } = this.props
const { comment, classes, fullName, avatar, translate } = this.props
const { openMenu } = this.state
@@ -319,9 +320,9 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
<Grow in={openMenu!} style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role='menu'>
<MenuItem className={classes.rightIconMenuItem}>Reply</MenuItem>
{this.props.isCommentOwner ? (<MenuItem className={classes.rightIconMenuItem} onClick={this.handleEditComment}>Edit</MenuItem>) : ''}
{(this.props.isCommentOwner || this.props.isPostOwner) ? (<MenuItem className={classes.rightIconMenuItem} onClick={(evt: any) => this.handleDelete(evt, comment.id, comment.postId)}>Delete</MenuItem>) : ''}
<MenuItem className={classes.rightIconMenuItem}>{translate!('comment.replyButton')}</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)}>{translate!('comment.deleteButton')}</MenuItem>) : ''}
</MenuList>
</Paper>
</Grow>
@@ -342,7 +343,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
const commentBody = (
<div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}>
{ editorStatus ? <TextField
placeholder={'Add a comment...'}
placeholder={translate!('comment.updateCommentPlaceholder')}
multiline
autoFocus
rowsMax='4'
@@ -360,8 +361,8 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
<div style={{ display: (editorStatus ? 'flex' : 'none'), flexDirection: 'row-reverse' }}>
<Button color='primary' disabled={this.state.editDisabled}
style={{ float: 'right', clear: 'both', zIndex: 5, margin: '0px 5px 5px 0px', fontWeight: 400 }}
onClick={this.handleUpdateComment} > Update </Button>
<Button color='primary' style={this.styles.cancel as any} onClick={this.handleCancelEdit} > Cancel </Button>
onClick={this.handleUpdateComment} > {translate!('comment.updateButton')} </Button>
<Button color='primary' style={this.styles.cancel as any} onClick={this.handleCancelEdit} > {translate!('comment.cancelButton')} </Button>
</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 fullName = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].fullName || '' : ''
return {
translate: getTranslate(state.locale),
uid: uid,
isCommentOwner: (uid === ownProps.comment.userId),
info: state.user.info,

View File

@@ -100,4 +100,9 @@ export interface ICommentComponentProps {
*/
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 { connect } from 'react-redux'
import moment from 'moment/moment'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import Paper from 'material-ui/Paper'
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
*/
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
@@ -288,7 +289,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
avatar={<UserAvatar fullName={fullName!} fileName={avatar!} size={24} />}
subheader={<TextField
autoFocus
placeholder={'Add a comment...'}
placeholder={translate!('comment.addCommentPlaceholder')}
multiline
rowsMax='4'
InputProps={{
@@ -305,7 +306,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
</CardHeader>
<CardActions className={classes.postButton} >
<Button color='primary' disabled={this.state.postDisable} onClick={this.handlePostComment}>
Post
{translate!('comment.postButton')}
</Button>
</CardActions>
</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 getCommentsRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)] : null
return {
translate: getTranslate(state.locale),
getCommentsRequest,
commentSlides,
avatar: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].avatar || '' : '',

View File

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

View File

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

View File

@@ -60,4 +60,9 @@ export interface IEditProfileComponentProps {
* Styles
*/
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 Button from 'material-ui/Button'
import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions
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
*/
render () {
const {translate} = this.props
const paperStyle = {
minHeight: 370,
width: 450,
@@ -88,14 +89,14 @@ export class EmailVerificationComponent extends Component<IEmailVerificationComp
fontWeight: 400,
lineHeight: '32px',
margin: 0
}} className='zoomOutLCorner animated'>Email Verification</h2>
}} className='zoomOutLCorner animated'>{translate!('emailVerification.title')}</h2>
</div>
<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>
<div style={this.styles.buttons}>
<Button raised style={this.styles.homeButton} color='primary' onClick={() => this.props.homePage()}> Home </Button>
<Button raised color='primary' onClick={() => this.props.sendEmailVerification()}> Send Email Verification </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()}> {translate!('emailVerification.sendButton')} </Button>
</div>
<div>
</div>
@@ -131,7 +132,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IEmailVerificationComp
*/
const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => {
return {
translate: getTranslate(state.locale)
}
}

View File

@@ -1,5 +1,17 @@
export interface IEmailVerificationComponentProps {
/**
* Send email for verification
*/
sendEmailVerification: () => any
/**
* Redirect to home page
*/
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 Paper from 'material-ui/Paper'
import InfiniteScroll from 'react-infinite-scroller'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
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
*/
render () {
const {hasMorePeople} = this.props
const {hasMorePeople, translate} = this.props
return (
<div>
@@ -64,12 +65,12 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
{this.props.peopleInfo && Object.keys(this.props.peopleInfo).length !== 0 ? (<div>
<div className='profile__title'>
Suggestions for you
{translate!('people.suggestionsForYouLabel')}
</div>
<UserBoxList users={this.props.peopleInfo}/>
<div style={{ height: '24px' }}></div>
</div>) : (<div className='g__title-center'>
Nothing to show! :(
{translate!('people.nothingToShowLabel')}
</div>)}
</div>
</InfiniteScroll>
@@ -99,6 +100,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IFindPeopleComponentProps)
const mapStateToProps = (state: any, ownProps: IFindPeopleComponentProps) => {
const {people, info} = state.user
return {
translate: getTranslate(state.locale),
peopleInfo: info,
hasMorePeople: people.hasMoreData
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,4 +3,9 @@ import { UserTie } from 'core/domain/circles'
export interface IFollowingComponentProps {
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 { connect } from 'react-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 { MenuList, MenuItem } from 'material-ui/Menu'
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 SvgAccountCircle from 'material-ui-icons/AccountCircle'
import SvgPeople from 'material-ui-icons/People'
import config from 'src/config'
// - Import app components
import Sidebar from 'components/sidebar'
import StreamComponent from 'components/stream'
@@ -131,7 +134,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
*/
render () {
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 (
<div id='home'>
<HomeHeader sidebar={this.state.sidebarOpen} sidebarStatus={this.state.sidebarStatus} />
@@ -157,7 +160,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon>
<SvgHome />
</ListItemIcon>
<ListItemText inset primary='Home' />
<ListItemText inset primary={translate!('sidebar.home')} />
</MenuItem>
</NavLink>
<NavLink to={`/${this.props.uid}`}>
@@ -165,7 +168,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon>
<SvgAccountCircle />
</ListItemIcon>
<ListItemText inset primary='Profile' />
<ListItemText inset primary={translate!('sidebar.profile')} />
</MenuItem>
</NavLink>
<NavLink to='/people'>
@@ -173,7 +176,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon>
<SvgPeople />
</ListItemIcon>
<ListItemText inset primary='People' />
<ListItemText inset primary={translate!('sidebar.people')} />
</MenuItem>
</NavLink>
<Divider />
@@ -182,14 +185,14 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemIcon>
<SvgSettings />
</ListItemIcon>
<ListItemText inset primary='Settings' />
<ListItemText inset primary={translate!('sidebar.settings')} />
</MenuItem>
</NavLink>
<MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}>
<ListItemIcon>
<SvgFeedback />
</ListItemIcon>
<ListItemText inset primary='Send feedback' />
<ListItemText inset primary={translate!('sidebar.sendFeedback')} />
</MenuItem>
</MenuList>
</SidebarContent>
@@ -267,6 +270,8 @@ const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
authed: authorize.authed,
isVerifide: authorize.isVerifide,
mainStyle: global.sidebarMainStyle,
translate: getTranslate(state.locale),
currentLanguage: getActiveLanguage(state.locale).code,
mergedPosts,
global,
hasMorePosts,

View File

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

View File

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

View File

@@ -38,4 +38,9 @@ export interface IImageGalleryComponentProps {
* @memberof IImageGalleryComponentProps
*/
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 { grey } from 'material-ui/colors'
import uuid from 'uuid'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions
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 () {
const {translate} = this.props
/**
* Component styles
* @type {Object}
@@ -212,7 +209,7 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
/>
<label htmlFor='raised-button-file'>
<Button raised component='span' style={this.styles.uploadButton as any}>
Upload
{translate!('imageGallery.uploadButton')}
</Button>
</label>
</div>
@@ -247,6 +244,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImageGalleryComponentProps
*/
const mapStateToProps = (state: any) => {
return {
translate: getTranslate(state.locale),
images: state.imageGallery.images,
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
/**
* 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 SvgImage from 'material-ui-icons/Image'
import { withStyles } from 'material-ui/styles'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
@@ -85,7 +86,7 @@ export class ImgComponent extends Component<IImgComponentProps,IImgComponentStat
*/
render () {
let { fileName, style } = this.props
let { fileName, style, translate } = this.props
let { isImageLoaded } = this.state
const {classes} = this.props
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={this.styles.loadingContent as any}>
<SvgImage style={this.styles.loadingImage} />
<div>Image has not loaded</div>
<div>{translate!('image.notLoaded')}</div>
</div>
</div>
</div>
@@ -122,6 +123,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImgComponentProps) => {
*/
const mapStateToProps = (state: any, ownProps: IImgComponentProps) => {
return {
translate: getTranslate(state.locale),
avatarURL: state.imageGallery.imageURLList,
imageRequests: state.imageGallery.imageRequests
}

View File

@@ -39,4 +39,9 @@ export interface IImgCoverComponentProps {
* @memberof IImgCoverComponentProps
*/
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 { connect } from 'react-redux'
import SvgImage from 'material-ui-icons/Image'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
@@ -108,7 +109,7 @@ export class ImgCoverComponent extends Component<IImgCoverComponentProps,IImgCov
*/
render () {
let { fileName, style } = this.props
let { fileName, style, translate } = this.props
let { isImageLoaded } = this.state
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={this.styles.loadingContent as any}>
<SvgImage style={this.styles.loadingImage} />
<div>Image has not loaded</div>
<div>{translate!('image.notLoaded')}</div>
</div>
</div>
<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) => {
return {
translate: getTranslate(state.locale),
avatarURL: state.imageGallery.imageURLList,
imageRequests: state.imageGallery.imageRequests

View File

@@ -26,4 +26,9 @@ export interface ILoginComponentProps {
* Styles
*/
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 { withStyles } from 'material-ui/styles'
import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions
import * as authorizeActions from 'actions/authorizeActions'
@@ -104,18 +105,18 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
* Handle register form
*/
handleForm = () => {
const {translate} = this.props
let error = false
if (this.state.emailInput === '') {
this.setState({
emailInputError: 'This field is required'
emailInputError: translate!('login.emailRequiredError')
})
error = true
}
if (this.state.passwordInput === '') {
this.setState({
passwordInputError: 'This field is required'
passwordInputError: translate!('login.passwordRequiredError')
})
error = true
@@ -135,7 +136,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
* @return {react element} return the DOM which rendered by component
*/
render () {
const {classes} = this.props
const {classes, loginWithOAuth, translate} = this.props
const paperStyle = {
minHeight: 370,
@@ -145,7 +146,6 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
margin: 'auto'
}
const {loginWithOAuth} = this.props
return (
<form>
@@ -174,7 +174,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
fontWeight: 400,
lineHeight: '32px',
margin: 0
}} className='zoomOutLCorner animated'>Sign in</h2>
}} className='zoomOutLCorner animated'>{translate!('login.title')}</h2>
</div>
<div style={this.styles.singinOptions as any}>
<IconButton
@@ -196,7 +196,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
helperText={this.state.emailInputError}
error={this.state.emailInputError.trim() !== ''}
name='emailInput'
label='Email'
label={translate!('login.emailLabel')}
type='email'
tabIndex={1}
/><br />
@@ -206,7 +206,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
helperText={this.state.passwordInputError}
error={this.state.passwordInputError.trim() !== ''}
name='passwordInput'
label='Password'
label={translate!('login.passwordLabel')}
type='password'
tabIndex={2}
/><br />
@@ -214,13 +214,13 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
<br />
<div className='login__button-box'>
<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 >
<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>
<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>
</Paper>
</div>
@@ -255,7 +255,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: ILoginComponentProps) => {
*/
const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => {
return {
translate: getTranslate(state.locale)
}
}

View File

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

View File

@@ -29,4 +29,9 @@ export interface IPeopleComponentProps {
* @memberof IPeopleComponentProps
*/
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 AppBar from 'material-ui/AppBar'
import Typography from 'material-ui/Typography'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
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
return (
<div style={styles.people}>
@@ -135,9 +136,9 @@ export class PeopleComponent extends Component<IPeopleComponentProps,IPeopleComp
value={tabIndex} centered
textColor='primary'
>
<Tab label='Find People' />
<Tab label='Following' />
<Tab label='Followers' />
<Tab label={translate!('people.findPeopleTab')} />
<Tab label={translate!('people.followingTab')} />
<Tab label={translate!('people.followersTab')} />
</Tabs>
</AppBar>
{tabIndex === 0 && <TabContainer>{circlesLoaded ? <FindPeople /> : ''}</TabContainer>}
@@ -190,6 +191,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPeopleComponentProps) => {
const mapStateToProps = (state: any, ownProps: IPeopleComponentProps) => {
return {
translate: getTranslate(state.locale),
uid: state.authorize.uid,
circlesLoaded: state.circle.loaded

View File

@@ -119,4 +119,9 @@ export interface IPostComponentProps {
* Styles
*/
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 Linkify from 'react-linkify'
import copy from 'copy-to-clipboard'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Material UI
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
@@ -262,9 +263,10 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
* @memberof Post
*/
handleCopyLink = () => {
const {translate} = this.props
this.setState({
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
*/
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 RightIconMenu = () => (
<Manager>
@@ -359,15 +361,15 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Grow in={isPostMenuOpen!} style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role='menu'>
<MenuItem onClick={this.handleOpenPostWrite} > Edit </MenuItem>
<MenuItem onClick={this.handleDelete} > Delete </MenuItem>
<MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem>
<MenuItem onClick={this.handleDelete} > {translate!('post.delete')} </MenuItem>
<MenuItem
onClick={() => this.props.toggleDisableComments!(!post.disableComments)} >
{post.disableComments ? 'Enable comments' : 'Disable comments'}
{post.disableComments ? translate!('post.enableComments') : translate!('post.disableComments')}
</MenuItem>
<MenuItem
onClick={() => this.props.toggleSharingComments!(!post.disableSharing)} >
{post.disableSharing ? 'Enable sharing' : 'Disable sharing'}
{post.disableSharing ? translate!('post.enableSharing') : translate!('post.disableSharing')}
</MenuItem>
</MenuList>
</Paper>
@@ -383,7 +385,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Card>
<CardHeader
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>}
action={isPostOwner ? <RightIconMenu /> : ''}
>
@@ -461,7 +463,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<ListItemIcon>
<SvgLink />
</ListItemIcon>
<ListItemText inset primary='Copy Link' />
<ListItemText inset primary={translate!('post.copyLinkButton')} />
</MenuItem>
</MenuList>)
: <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 commentList: { [commentId: string]: Comment } = comment.postComments[ownProps.post.id!]
return {
translate: getTranslate(state.locale),
commentList,
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 || '' : '',

View File

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

View File

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

View File

@@ -84,4 +84,9 @@ export interface IProfileComponentProps {
* If there is more posts to show in profile
*/
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 Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
import ProfileHeader from 'components/profileHeader'
@@ -77,7 +78,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
border: '2px solid rgb(255, 255, 255)'
}
}
const {loadPosts, hasMorePosts} = this.props
const {loadPosts, hasMorePosts, translate} = this.props
const St = StreamComponent as any
return (
<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
? (<div style={styles.content}>
<div className='profile__title'>
{this.props.name}'s posts
{translate!('profile.headPostsLabel', {userName: this.props.name})}
</div>
<div style={{ height: '24px' }}></div>
@@ -99,7 +100,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
displayWriting={false} />
</div>)
: (<div className='profile__title'>
Nothing shared
{translate!('profile.nothingSharedLabel')}
</div>)
}
@@ -135,6 +136,7 @@ const mapStateToProps = (state: any, ownProps: IProfileComponentProps) => {
const hasMorePosts = state.post.profile.hasMoreData
const posts = state.post.userPosts ? state.post.userPosts[userId] : {}
return {
translate: getTranslate(state.locale),
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 || '' : '',
banner: state.user.info && state.user.info[userId] ? state.user.info[userId].banner || '' : '',

View File

@@ -62,4 +62,9 @@ export interface IProfileHeaderComponentProps {
* @memberof IProfileHeaderComponentProps
*/
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 EventListener, { withOptions } from 'react-event-listener'
import { Parallax, Background } from 'react-parallax'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
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
*/
render () {
const {translate, isAuthedUser} = this.props
const styles = {
avatar: {
border: '2px solid rgb(255, 255, 255)'
@@ -165,8 +166,6 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
</div>
)
const {isAuthedUser} = this.props
return (
<div>
@@ -200,7 +199,7 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
<div className='right'>
{isAuthedUser ? (<div style={this.state.isSmall ? styles.editButtonSmall : styles.editButton}>
<Button raised onClick={this.props.openEditor}>
EDIT PROFILE
{translate!('profile.editProfileButton')}
</Button>
</div>) : ''}
</div>
@@ -236,6 +235,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IProfileHeaderComponentProp
const mapStateToProps = (state: any, ownProps: IProfileHeaderComponentProps) => {
return {
translate: getTranslate(state.locale)
}
}

View File

@@ -18,4 +18,9 @@ export interface IResetPasswordComponentProps {
* Styles
*/
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 Typography from 'material-ui/Typography'
import config from 'src/config'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import actions
import * as authorizeActions from 'actions/authorizeActions'
@@ -71,11 +72,11 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
* Handle register form
*/
handleForm = () => {
const {translate} = this.props
let error = false
if (this.state.emailInput === '') {
this.setState({
emailInputError: 'This field is required'
emailInputError: translate!('resetPassword.emailRequiredError')
})
return
@@ -90,7 +91,7 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
*/
render () {
const {classes} = this.props
const {classes, translate} = this.props
const paperStyle = {
minHeight: 370,
@@ -127,7 +128,7 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
fontWeight: 400,
lineHeight: '32px',
margin: 0
}} className='zoomOutLCorner animated'>Reset Password</h2>
}} className='zoomOutLCorner animated'>{translate!('resetPassword.title')}</h2>
</div>
<TextField
@@ -137,22 +138,21 @@ export class ResetPasswordComponent extends Component<IResetPasswordComponentPro
helperText={this.state.emailInputError}
error={this.state.emailInputError.trim() !== ''}
name='emailInput'
label='Email'
label={translate!('resetPassword.emailLabel')}
type='email'
/><br />
<br />
<br />
<div className='settings__button-box'>
<div>
<Button onClick={this.props.loginPage}> Back </Button>
<Button onClick={this.props.loginPage}>{translate!('resetPassword.backButton')}</Button>
</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>
<Typography className={classes.caption} type='caption' component='p'>
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.
{translate!('resetPassword.description')}
</Typography>
</div>
</Paper>
@@ -185,7 +185,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IResetPasswordComponen
*/
const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => {
return {
translate: getTranslate(state.locale),
}
}

View File

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

View File

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

View File

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

View File

@@ -88,4 +88,9 @@ export interface IStreamComponentProps {
* Router match property
*/
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 List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
import InfiniteScroll from 'react-infinite-scroller'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
import PostComponent from 'components/post'
@@ -202,7 +203,7 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
*/
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
return (
@@ -224,7 +225,7 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
onClick={this.handleOpenPostWrite}
>
<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>
<SvgCamera />
</ListItemIcon>
@@ -278,6 +279,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IStreamComponentProps) => {
const mapStateToProps = (state: any, ownProps: IStreamComponentProps) => {
const { post } = state
return {
translate: getTranslate(state.locale),
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 : ''
}

View File

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

View File

@@ -1,3 +1,5 @@
import { LanguageType } from 'reducers/locale/langugeType'
export const environment = {
firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
@@ -8,6 +10,11 @@ export const environment = {
messagingSenderId: '964743099489'
},
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 = {
firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
@@ -8,6 +10,11 @@ export const environment = {
messagingSenderId: '964743099489'
},
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',
LOADING = 'LOADING',
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_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',
SHOW_TOP_LOADING = 'SHOW_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 'typeface-roboto'
import registerServiceWorker from './registerServiceWorker'
import config from 'src/config'
import { Provider } from 'react-redux'
import store, { history } from 'store/configureStore'
import { ConnectedRouter } from 'react-router-redux'
// - Actions
import * as localeActions from 'actions/localeActions'
// - Import app components
import Master from 'components/master'
// import { App } from 'components/AWS'
@@ -19,16 +23,20 @@ import Master from 'components/master'
// tslint:disable-next-line:no-empty
store.subscribe(() => { })
// - Initialize languages
store.dispatch(localeActions.initTranslation())
// Needed for onClick
// http://stackoverflow.com/a/34015469/988941
try { injectTapEventPlugin() } catch (e) {}
const theme = createMuiTheme({
palette: {
primary: { main: '#00b1b3' },
secondary: { main: '#4d545d' }
primary: { main: config.theme.primaryColor },
secondary: { main: config.theme.secondaryColor }
}
})
// 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,
defaultLoadDataStatus: true
}
case GlobalActionType.SHOW_ERROR_MESSAGE_GLOBAL:
case GlobalActionType.SHOW_MESSAGE_GLOBAL:
return {
...state,
message: action.payload,
@@ -43,18 +43,6 @@ export const globalReducer = (state: GlobalState = new GlobalState(), action: IG
message: action.payload,
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:
return {
...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 { connect } from 'react-redux'
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
// - Import app components
import StreamComponent from 'components/stream'
@@ -18,7 +19,7 @@ import { IRouterProps } from './IRouterProps'
*/
export class HomeRouter extends Component<IRouterProps, any> {
render () {
const { enabled, match, data } = this.props
const { enabled, match, data, translate } = this.props
const St = StreamComponent as any
return (
enabled ? (
@@ -33,7 +34,7 @@ export class HomeRouter extends Component<IRouterProps, any> {
<PrivateRoute path='/' component={(
<div className='blog'>
<St
homeTitle='Home'
homeTitle={translate!('header.home')}
posts={data.mergedPosts}
loadStream={data.loadDataStream}
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
/**
* 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 createHistory from 'history/createBrowserHistory'
import { createLogger } from 'redux-logger'
import { localeReducer as locale } from 'react-localize-redux'
// - Import reducers
import {
@@ -19,8 +20,6 @@ import {
notificationReducer
} from 'reducers'
declare const window: any
// Create a history of your choosing (we're using a browser history in this case)
export const history = createHistory()
@@ -30,6 +29,7 @@ const logger = createLogger()
// - Reducers
let reducer = redux.combineReducers({
locale,
imageGallery: imageGalleryReducer,
post: postReducer,
circle: circleReducer,