diff options
author | Dessalines <dessalines@users.noreply.github.com> | 2019-08-09 17:14:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-09 17:14:43 -0700 |
commit | 536c3f491546b4546f43a46e7a1a699ca9ac2934 (patch) | |
tree | f080c86e51b9660560ac493cb7f6d9676ea12fbe /ui | |
parent | 5a1e8aa645c9f0898e765b45c2f362308292db26 (diff) |
Adding support for internationalization / i18n (#189)
* Still not working
* Starting to work on internationalization
* Main done.
* i18n translations first pass.
* Localization testing mostly done.
* Second front end pass.
* Added a few more translations.
* Adding back end translations.
Diffstat (limited to 'ui')
34 files changed, 772 insertions, 320 deletions
diff --git a/ui/package.json b/ui/package.json index 20ecdd82..d86725f2 100644 --- a/ui/package.json +++ b/ui/package.json @@ -23,7 +23,9 @@ "autosize": "^4.0.2", "classcat": "^1.1.3", "dotenv": "^6.1.0", + "i18next": "^17.0.9", "inferno": "^7.0.1", + "inferno-i18next": "nimbusec-oss/inferno-i18next", "inferno-router": "^7.0.1", "js-cookie": "^2.2.0", "jwt-decode": "^2.2.0", @@ -35,6 +37,7 @@ "ws": "^7.0.0" }, "devDependencies": { + "@types/i18next": "^12.1.0", "fuse-box": "^3.1.3", "ts-transform-classcat": "^0.0.2", "ts-transform-inferno": "^4.0.2", diff --git a/ui/src/components/comment-form.tsx b/ui/src/components/comment-form.tsx index 5181e45e..ed62fcf5 100644 --- a/ui/src/components/comment-form.tsx +++ b/ui/src/components/comment-form.tsx @@ -1,7 +1,10 @@ import { Component, linkEvent } from 'inferno'; import { CommentNode as CommentNodeI, CommentForm as CommentFormI } from '../interfaces'; +import { capitalizeFirstLetter } from '../utils'; import { WebSocketService, UserService } from '../services'; import * as autosize from 'autosize'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; interface CommentFormProps { postId?: number; @@ -25,12 +28,13 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> { post_id: this.props.node ? this.props.node.comment.post_id : this.props.postId, creator_id: UserService.Instance.user ? UserService.Instance.user.id : null, }, - buttonTitle: !this.props.node ? "Post" : this.props.edit ? "Edit" : "Reply", + buttonTitle: !this.props.node ? capitalizeFirstLetter(i18n.t('post')) : this.props.edit ? capitalizeFirstLetter(i18n.t('edit')) : capitalizeFirstLetter(i18n.t('reply')), } constructor(props: any, context: any) { super(props, context); + this.state = this.emptyState; if (this.props.node) { @@ -62,7 +66,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> { <div class="row"> <div class="col-sm-12"> <button type="submit" class="btn btn-sm btn-secondary mr-2" disabled={this.props.disabled}>{this.state.buttonTitle}</button> - {this.props.node && <button type="button" class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.handleReplyCancel)}>Cancel</button>} + {this.props.node && <button type="button" class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.handleReplyCancel)}><T i18nKey="cancel">#</T></button>} </div> </div> </form> @@ -84,7 +88,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> { if (i.props.node) { i.props.onReplyCancel(); } - + autosize.update(document.querySelector('textarea')); } diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index a201ddd6..a1ac93b3 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -7,6 +7,8 @@ import * as moment from 'moment'; import { MomentTime } from './moment-time'; import { CommentForm } from './comment-form'; import { CommentNodes } from './comment-nodes'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; enum BanType {Community, Site}; @@ -74,10 +76,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { <Link className="text-info" to={`/u/${node.comment.creator_name}`}>{node.comment.creator_name}</Link> </li> {this.isMod && - <li className="list-inline-item badge badge-light">mod</li> + <li className="list-inline-item badge badge-light"><T i18nKey="mod">#</T></li> } {this.isAdmin && - <li className="list-inline-item badge badge-light">admin</li> + <li className="list-inline-item badge badge-light"><T i18nKey="admin">#</T></li> } <li className="list-inline-item"> <span>( @@ -97,24 +99,24 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { {this.state.showEdit && <CommentForm node={node} edit onReplyCancel={this.handleReplyCancel} disabled={this.props.locked} />} {!this.state.showEdit && !this.state.collapsed && <div> - <div className="md-div" dangerouslySetInnerHTML={mdToHtml(node.comment.removed ? '*removed*' : node.comment.deleted ? '*deleted*' : node.comment.content)} /> + <div className="md-div" dangerouslySetInnerHTML={mdToHtml(node.comment.removed ? `*${i18n.t('removed')}*` : node.comment.deleted ? `*${i18n.t('deleted')}*` : node.comment.content)} /> <ul class="list-inline mb-1 text-muted small font-weight-bold"> {UserService.Instance.user && !this.props.viewOnly && <> <li className="list-inline-item"> - <span class="pointer" onClick={linkEvent(this, this.handleReplyClick)}>reply</span> + <span class="pointer" onClick={linkEvent(this, this.handleReplyClick)}><T i18nKey="reply">#</T></span> </li> <li className="list-inline-item mr-2"> - <span class="pointer" onClick={linkEvent(this, this.handleSaveCommentClick)}>{node.comment.saved ? 'unsave' : 'save'}</span> + <span class="pointer" onClick={linkEvent(this, this.handleSaveCommentClick)}>{node.comment.saved ? i18n.t('unsave') : i18n.t('save')}</span> </li> {this.myComment && <> <li className="list-inline-item"> - <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}>edit</span> + <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}><T i18nKey="edit">#</T></span> </li> <li className="list-inline-item"> <span class="pointer" onClick={linkEvent(this, this.handleDeleteClick)}> - {!this.props.node.comment.deleted ? 'delete' : 'restore'} + {!this.props.node.comment.deleted ? i18n.t('delete') : i18n.t('restore')} </span> </li> </> @@ -123,8 +125,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { {this.canMod && <li className="list-inline-item"> {!this.props.node.comment.removed ? - <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}>remove</span> : - <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}>restore</span> + <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> : + <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span> } </li> } @@ -134,14 +136,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { {!this.isMod && <li className="list-inline-item"> {!this.props.node.comment.banned_from_community ? - <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunityShow)}>ban</span> : - <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)}>unban</span> + <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunityShow)}><T i18nKey="ban">#</T></span> : + <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)}><T i18nKey="unban">#</T></span> } </li> } {!this.props.node.comment.banned_from_community && <li className="list-inline-item"> - <span class="pointer" onClick={linkEvent(this, this.handleAddModToCommunity)}>{`${this.isMod ? 'remove' : 'appoint'} as mod`}</span> + <span class="pointer" onClick={linkEvent(this, this.handleAddModToCommunity)}>{this.isMod ? i18n.t('remove_as_mod') : i18n.t('appoint_as_mod')}</span> </li> } </> @@ -152,14 +154,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { {!this.isAdmin && <li className="list-inline-item"> {!this.props.node.comment.banned ? - <span class="pointer" onClick={linkEvent(this, this.handleModBanShow)}>ban from site</span> : - <span class="pointer" onClick={linkEvent(this, this.handleModBanSubmit)}>unban from site</span> + <span class="pointer" onClick={linkEvent(this, this.handleModBanShow)}><T i18nKey="ban_from_site">#</T></span> : + <span class="pointer" onClick={linkEvent(this, this.handleModBanSubmit)}><T i18nKey="unban_from_site">#</T></span> } </li> } {!this.props.node.comment.banned && <li className="list-inline-item"> - <span class="pointer" onClick={linkEvent(this, this.handleAddAdmin)}>{`${this.isAdmin ? 'remove' : 'appoint'} as admin`}</span> + <span class="pointer" onClick={linkEvent(this, this.handleAddAdmin)}>{this.isAdmin ? i18n.t('remove_as_admin') : i18n.t('appoint_as_admin')}</span> </li> } </> @@ -167,11 +169,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { </> } <li className="list-inline-item"> - <Link className="text-muted" to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}>link</Link> + <Link className="text-muted" to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}><T i18nKey="link">#</T></Link> </li> {this.props.markable && <li className="list-inline-item"> - <span class="pointer" onClick={linkEvent(this, this.handleMarkRead)}>{`mark as ${node.comment.read ? 'unread' : 'read'}`}</span> + <span class="pointer" onClick={linkEvent(this, this.handleMarkRead)}>{node.comment.read ? i18n.t('mark_as_unread') : i18n.t('mark_as_read')}</span> </li> } </ul> @@ -180,23 +182,23 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { </div> {this.state.showRemoveDialog && <form class="form-inline" onSubmit={linkEvent(this, this.handleModRemoveSubmit)}> - <input type="text" class="form-control mr-2" placeholder="Reason" value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} /> - <button type="submit" class="btn btn-secondary">Remove Comment</button> + <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} /> + <button type="submit" class="btn btn-secondary"><T i18nKey="remove_comment">#</T></button> </form> } {this.state.showBanDialog && <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}> <div class="form-group row"> - <label class="col-form-label">Reason</label> - <input type="text" class="form-control mr-2" placeholder="Optional" value={this.state.banReason} onInput={linkEvent(this, this.handleModBanReasonChange)} /> + <label class="col-form-label"><T i18nKey="reason">#</T></label> + <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.banReason} onInput={linkEvent(this, this.handleModBanReasonChange)} /> </div> {/* TODO hold off on expires until later */} {/* <div class="form-group row"> */} {/* <label class="col-form-label">Expires</label> */} - {/* <input type="date" class="form-control mr-2" placeholder="Expires" value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */} + {/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */} {/* </div> */} <div class="form-group row"> - <button type="submit" class="btn btn-secondary">Ban {this.props.node.comment.creator_name}</button> + <button type="submit" class="btn btn-secondary">{i18n.t('ban')} {this.props.node.comment.creator_name}</button> </div> </form> } @@ -387,9 +389,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { handleModBanBothSubmit(i: CommentNode) { event.preventDefault(); - console.log(BanType[i.state.banType]); - console.log(i.props.node.comment.banned); - if (i.state.banType == BanType.Community) { let form: BanFromCommunityForm = { user_id: i.props.node.comment.creator_id, diff --git a/ui/src/components/comment-nodes.tsx b/ui/src/components/comment-nodes.tsx index da67bbc7..fca323e3 100644 --- a/ui/src/components/comment-nodes.tsx +++ b/ui/src/components/comment-nodes.tsx @@ -32,7 +32,7 @@ export class CommentNodes extends Component<CommentNodesProps, CommentNodesState moderators={this.props.moderators} admins={this.props.admins} markable={this.props.markable} - /> + /> )} </div> ) diff --git a/ui/src/components/communities.tsx b/ui/src/components/communities.tsx index c4efe1fb..49b982dc 100644 --- a/ui/src/components/communities.tsx +++ b/ui/src/components/communities.tsx @@ -5,6 +5,8 @@ import { retryWhen, delay, take } from 'rxjs/operators'; import { UserOperation, Community, ListCommunitiesResponse, CommunityResponse, FollowCommunityForm, ListCommunitiesForm, SortType } from '../interfaces'; import { WebSocketService } from '../services'; import { msgOp } from '../utils'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; declare const Sortable: any; @@ -26,12 +28,12 @@ export class Communities extends Component<any, CommunitiesState> { super(props, context); this.state = this.emptyState; this.subscription = WebSocketService.Instance.subject - .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) - .subscribe( - (msg) => this.parseMessage(msg), + .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) + .subscribe( + (msg) => this.parseMessage(msg), (err) => console.error(err), () => console.log('complete') - ); + ); this.refetch(); @@ -46,7 +48,7 @@ export class Communities extends Component<any, CommunitiesState> { } componentDidMount() { - document.title = `Communities - ${WebSocketService.Instance.site.name}`; + document.title = `${i18n.t('communities')} - ${WebSocketService.Instance.site.name}`; } // Necessary for back button for some reason @@ -64,17 +66,17 @@ export class Communities extends Component<any, CommunitiesState> { {this.state.loading ? <h5 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : <div> - <h5>List of communities</h5> + <h5><T i18nKey="list_of_communities">#</T></h5> <div class="table-responsive"> <table id="community_table" class="table table-sm table-hover"> <thead class="pointer"> <tr> - <th>Name</th> - <th class="d-none d-lg-table-cell">Title</th> - <th>Category</th> - <th class="text-right">Subscribers</th> - <th class="text-right d-none d-lg-table-cell">Posts</th> - <th class="text-right d-none d-lg-table-cell">Comments</th> + <th><T i18nKey="name">#</T></th> + <th class="d-none d-lg-table-cell"><T i18nKey="title">#</T></th> + <th><T i18nKey="category">#</T></th> + <th class="text-right"><T i18nKey="subscribers">#</T></th> + <th class="text-right d-none d-lg-table-cell"><T i18nKey="posts">#</T></th> + <th class="text-right d-none d-lg-table-cell"><T i18nKey="comments">#</T></th> <th></th> </tr> </thead> @@ -89,8 +91,8 @@ export class Communities extends Component<any, CommunitiesState> { <td class="text-right d-none d-lg-table-cell">{community.number_of_comments}</td> <td class="text-right"> {community.subscribed ? - <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</span> : - <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</span> + <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleUnsubscribe)}><T i18nKey="unsubscribe">#</T></span> : + <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleSubscribe)}><T i18nKey="subscribe">#</T></span> } </td> </tr> @@ -109,9 +111,9 @@ export class Communities extends Component<any, CommunitiesState> { return ( <div class="mt-2"> {this.state.page > 1 && - <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button> + <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button> } - <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button> + <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button> </div> ); } @@ -165,7 +167,7 @@ export class Communities extends Component<any, CommunitiesState> { console.log(msg); let op: UserOperation = msgOp(msg); if (msg.error) { - alert(msg.error); + alert(i18n.t(msg.error)); return; } else if (op == UserOperation.ListCommunities) { let res: ListCommunitiesResponse = msg; diff --git a/ui/src/components/community-form.tsx b/ui/src/components/community-form.tsx index e295dcbe..b039fb4d 100644 --- a/ui/src/components/community-form.tsx +++ b/ui/src/components/community-form.tsx @@ -3,8 +3,10 @@ import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; import { CommunityForm as CommunityFormI, UserOperation, Category, ListCategoriesResponse, CommunityResponse } from '../interfaces'; import { WebSocketService } from '../services'; -import { msgOp } from '../utils'; +import { msgOp, capitalizeFirstLetter } from '../utils'; import * as autosize from 'autosize'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; import { Community } from '../interfaces'; @@ -74,25 +76,25 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt return ( <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}> <div class="form-group row"> - <label class="col-12 col-form-label">Name</label> + <label class="col-12 col-form-label"><T i18nKey="name">#</T></label> <div class="col-12"> - <input type="text" class="form-control" value={this.state.communityForm.name} onInput={linkEvent(this, this.handleCommunityNameChange)} required minLength={3} maxLength={20} pattern="[a-z0-9_]+" title="lowercase, underscores, and no spaces."/> + <input type="text" class="form-control" value={this.state.communityForm.name} onInput={linkEvent(this, this.handleCommunityNameChange)} required minLength={3} maxLength={20} pattern="[a-z0-9_]+" title={i18n.t('community_reqs')}/> </div> </div> <div class="form-group row"> - <label class="col-12 col-form-label">Title</label> + <label class="col-12 col-form-label"><T i18nKey="title">#</T></label> <div class="col-12"> <input type="text" value={this.state.communityForm.title} onInput={linkEvent(this, this.handleCommunityTitleChange)} class="form-control" required minLength={3} maxLength={100} /> </div> </div> <div class="form-group row"> - <label class="col-12 col-form-label">Sidebar</label> + <label class="col-12 col-form-label"><T i18nKey="sidebar">#</T></label> <div class="col-12"> <textarea value={this.state.communityForm.description} onInput={linkEvent(this, this.handleCommunityDescriptionChange)} class="form-control" rows={3} maxLength={10000} /> </div> </div> <div class="form-group row"> - <label class="col-12 col-form-label">Category</label> + <label class="col-12 col-form-label"><T i18nKey="category">#</T></label> <div class="col-12"> <select class="form-control" value={this.state.communityForm.category_id} onInput={linkEvent(this, this.handleCommunityCategoryChange)}> {this.state.categories.map(category => @@ -106,8 +108,8 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt <button type="submit" class="btn btn-secondary mr-2"> {this.state.loading ? <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : - this.props.community ? 'Save' : 'Create'}</button> - {this.props.community && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleCancel)}>Cancel</button>} + this.props.community ? capitalizeFirstLetter(i18n.t('save')) : capitalizeFirstLetter(i18n.t('create'))}</button> + {this.props.community && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleCancel)}><T i18nKey="cancel">#</T></button>} </div> </div> </form> @@ -153,7 +155,7 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt let op: UserOperation = msgOp(msg); console.log(msg); if (msg.error) { - alert(msg.error); + alert(i18n.t(msg.error)); this.state.loading = false; this.setState(this.state); return; @@ -169,8 +171,7 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt this.state.loading = false; this.props.onCreate(res.community); } - - // TODO is this necessary? + // TODO is ths necessary else if (op == UserOperation.EditCommunity) { let res: CommunityResponse = msg; this.state.loading = false; diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx index 6a1f5da2..480b909e 100644 --- a/ui/src/components/community.tsx +++ b/ui/src/components/community.tsx @@ -6,6 +6,7 @@ import { WebSocketService } from '../services'; import { PostListings } from './post-listings'; import { Sidebar } from './sidebar'; import { msgOp, routeSortTypeToEnum, fetchLimit } from '../utils'; +import { T } from 'inferno-i18next'; interface State { community: CommunityI; @@ -102,7 +103,7 @@ export class Community extends Component<any, State> { <div class="col-12 col-md-8"> <h5>{this.state.community.title} {this.state.community.removed && - <small className="ml-2 text-muted font-italic">removed</small> + <small className="ml-2 text-muted font-italic"><T i18nKey="removed">#</T></small> } </h5> {this.selects()} @@ -126,15 +127,15 @@ export class Community extends Component<any, State> { return ( <div className="mb-2"> <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select custom-select-sm w-auto"> - <option disabled>Sort Type</option> - <option value={SortType.Hot}>Hot</option> - <option value={SortType.New}>New</option> + <option disabled><T i18nKey="sort_type">#</T></option> + <option value={SortType.Hot}><T i18nKey="hot">#</T></option> + <option value={SortType.New}><T i18nKey="new">#</T></option> <option disabled>──────────</option> - <option value={SortType.TopDay}>Top Day</option> - <option value={SortType.TopWeek}>Week</option> - <option value={SortType.TopMonth}>Month</option> - <option value={SortType.TopYear}>Year</option> - <option value={SortType.TopAll}>All</option> + <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option> + <option value={SortType.TopWeek}><T i18nKey="week">#</T></option> + <option value={SortType.TopMonth}><T i18nKey="month">#</T></option> + <option value={SortType.TopYear}><T i18nKey="year">#</T></option> + <option value={SortType.TopAll}><T i18nKey="all">#</T></option> </select> </div> ) @@ -144,9 +145,9 @@ export class Community extends Component<any, State> { return ( <div class="mt-2"> {this.state.page > 1 && - <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button> + <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button> } - <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button> + <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button> </div> ); } @@ -193,7 +194,7 @@ export class Community extends Component<any, State> { console.log(msg); let op: UserOperation = msgOp(msg); if (msg.error) { - alert(msg.error); + alert(i18n.t(msg.error)); return; } else if (op == UserOperation.GetCommunity) { let res: GetCommunityResponse = msg; diff --git a/ui/src/components/create-community.tsx b/ui/src/components/create-community.tsx index c2f89eef..61245e73 100644 --- a/ui/src/components/create-community.tsx +++ b/ui/src/components/create-community.tsx @@ -2,6 +2,8 @@ import { Component } from 'inferno'; import { CommunityForm } from './community-form'; import { Community } from '../interfaces'; import { WebSocketService } from '../services'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; export class CreateCommunity extends Component<any, any> { @@ -11,7 +13,7 @@ export class CreateCommunity extends Component<any, any> { } componentDidMount() { - document.title = `Create Community - ${WebSocketService.Instance.site.name}`; + document.title = `${i18n.t('create_community')} - ${WebSocketService.Instance.site.name}`; } render() { @@ -19,7 +21,7 @@ export class CreateCommunity extends Component<any, any> { <div class="container"> <div class="row"> <div class="col-12 col-lg-6 offset-lg-3 mb-4"> - <h5>Create Community</h5> + <h5><T i18nKey="create_community">#</T></h5> <CommunityForm onCreate={this.handleCommunityCreate}/> </div> </div> diff --git a/ui/src/components/create-post.tsx b/ui/src/components/create-post.tsx index e09bcf70..dd93a3c5 100644 --- a/ui/src/components/create-post.tsx +++ b/ui/src/components/create-post.tsx @@ -1,6 +1,8 @@ import { Component } from 'inferno'; import { PostForm } from './post-form'; import { WebSocketService } from '../services'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; export class CreatePost extends Component<any, any> { @@ -10,7 +12,7 @@ export class CreatePost extends Component<any, any> { } componentDidMount() { - document.title = `Create Post - ${WebSocketService.Instance.site.name}`; + document.title = `${i18n.t('create_post')} - ${WebSocketService.Instance.site.name}`; } render() { @@ -18,7 +20,7 @@ export class CreatePost extends Component<any, any> { <div clas |