Finishing up interpolation rework.

This commit is contained in:
Dessalines 2020-02-02 13:50:44 -05:00
parent e09e3b6a92
commit 680eab53c1
22 changed files with 309 additions and 485 deletions

24
README.md vendored
View file

@ -167,18 +167,18 @@ If you'd like to add translations, take a look at the [English translation file]
lang | done | missing lang | done | missing
---- | ---- | ------- ---- | ---- | -------
ca | 100% | old ca | 99% | old,time,action
de | 87% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message de | 87% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,old,docs,message_sent,messages,old_password,matrix_user_id,private_message_disclaimer,send_notifications_to_email,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
fa | 73% | cross_post,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message fa | 72% | cross_post,subscribed_to_communities,trending_communities,create_private_message,send_secure_message,send_message,message,mod,mods,moderates,remove_as_mod,appoint_as_mod,modlog,stickied,ban,ban_from_site,unban,unban_from_site,banned,number_of_subscribers,subscribers,both,saved,unsubscribe,subscribe,subscribed,old,api,docs,inbox,inbox_for,message_sent,notifications_error,messages,no_email_setup,matrix_user_id,private_message_disclaimer,url,body,copy_suggested_title,community,expand_here,subscribe_to_communities,theme,sponsor_message,general_sponsors,joined,by,to,from,landing_0,logged_in,community_moderator_already_exists,community_follower_already_exists,community_user_already_banned,no_slurs,admin_already_created,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
eo | 75% | number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message eo | 75% | number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,theme,donate_to_lemmy,donate,from,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
es | 100% | old es | 99% | old,time,action
fi | 100% | old fi | 99% | old,time,action
fr | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message fr | 82% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
it | 84% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message it | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
nl | 100% | nl | 99% | time,action
ru | 72% | cross_posts,cross_post,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message ru | 71% | cross_posts,cross_post,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
sv | 83% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message sv | 82% | create_private_message,send_secure_message,send_message,message,avatar,upload_avatar,show_avatars,archive_link,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,donate_to_lemmy,donate,from,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
zh | 70% | cross_posts,cross_post,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message zh | 69% | cross_posts,cross_post,users,number_of_communities,create_private_message,send_secure_message,send_message,message,preview,upload_image,avatar,upload_avatar,show_avatars,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,old,docs,replies,mentions,message_sent,messages,old_password,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,matrix_user_id,private_message_disclaimer,send_notifications_to_email,language,browser_default,downvotes_disabled,enable_downvotes,open_registration,registration_closed,enable_nsfw,recent_comments,nsfw,show_nsfw,theme,donate_to_lemmy,donate,monero,by,to,from,transfer_community,transfer_site,are_you_sure,yes,no,logged_in,email_already_exists,couldnt_create_private_message,no_private_message_edit_allowed,couldnt_update_private_message,time,action
<!-- translationsstop --> <!-- translationsstop -->
If you'd like to update this report, run: If you'd like to update this report, run:

View file

@ -15,7 +15,6 @@ import {
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { wsJsonToRes, toast } from '../utils'; import { wsJsonToRes, toast } from '../utils';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
declare const Sortable: any; declare const Sortable: any;
@ -76,37 +75,27 @@ export class Communities extends Component<any, CommunitiesState> {
return ( return (
<div class="container"> <div class="container">
{this.state.loading ? ( {this.state.loading ? (
<p class="text-center"> <h5 class="">
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
</p> </h5>
) : ( ) : (
<div> <div>
<h5> <h5>{i18n.t('list_of_communities')}</h5>
{ i18n.t('list_of_communities') }
</h5>
<div class="table-responsive"> <div class="table-responsive">
<table id="community_table" class="table table-sm table-hover"> <table id="community_table" class="table table-sm table-hover">
<thead class="pointer"> <thead class="pointer">
<tr> <tr>
<th> <th>{i18n.t('name')}</th>
{ i18n.t('name') } <th class="d-none d-lg-table-cell">{i18n.t('title')}</th>
</th> <th>{i18n.t('category')}</th>
<th class="d-none d-lg-table-cell"> <th class="text-right">{i18n.t('subscribers')}</th>
{ i18n.t('title') } <th class="text-right d-none d-lg-table-cell">
</th> {i18n.t('posts')}
<th>
{ i18n.t('category') }
</th>
<th class="text-right">
{ i18n.t('subscribers') }
</th> </th>
<th class="text-right d-none d-lg-table-cell"> <th class="text-right d-none d-lg-table-cell">
{ i18n.t('posts') } {i18n.t('comments')}
</th>
<th class="text-right d-none d-lg-table-cell">
{ i18n.t('comments') }
</th> </th>
<th></th> <th></th>
</tr> </tr>
@ -139,7 +128,7 @@ export class Communities extends Component<any, CommunitiesState> {
this.handleUnsubscribe this.handleUnsubscribe
)} )}
> >
<T i18nKey="unsubscribe">#</T> {i18n.t('unsubscribe')}
</span> </span>
) : ( ) : (
<span <span
@ -149,7 +138,7 @@ export class Communities extends Component<any, CommunitiesState> {
this.handleSubscribe this.handleSubscribe
)} )}
> >
{ i18n.t('subscribe') } {i18n.t('subscribe')}
</span> </span>
)} )}
</td> </td>
@ -173,7 +162,7 @@ export class Communities extends Component<any, CommunitiesState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
{ i18n.t('prev') } {i18n.t('prev')}
</button> </button>
)} )}
@ -182,7 +171,7 @@ export class Communities extends Component<any, CommunitiesState> {
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
)} )}
</div> </div>

View file

@ -21,7 +21,6 @@ import {
import Tribute from 'tributejs/src/Tribute.js'; import Tribute from 'tributejs/src/Tribute.js';
import autosize from 'autosize'; import autosize from 'autosize';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { Community } from '../interfaces'; import { Community } from '../interfaces';
@ -108,8 +107,8 @@ export class CommunityForm extends Component<
return ( return (
<form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}> <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="community-name"> <label class="col-12 col-form-label" htmlFor="community-name">
{ i18n.t('name') } {i18n.t('name')}
</label> </label>
<div class="col-12"> <div class="col-12">
<input <input
@ -128,8 +127,8 @@ export class CommunityForm extends Component<
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="community-title"> <label class="col-12 col-form-label" htmlFor="community-title">
{ i18n.t('title') } {i18n.t('title')}
</label> </label>
<div class="col-12"> <div class="col-12">
<input <input
@ -145,14 +144,13 @@ export class CommunityForm extends Component<
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="community-sidebar"> <label class="col-12 col-form-label" htmlFor={this.id}>
{ i18n.t('sidebar') } {i18n.t('sidebar')}
</label> </label>
<div class="col-12"> <div class="col-12">
<textarea <textarea
id={this.id} id={this.id}
value={this.state.communityForm.description} value={this.state.communityForm.description}
id="community-sidebar"
onInput={linkEvent(this, this.handleCommunityDescriptionChange)} onInput={linkEvent(this, this.handleCommunityDescriptionChange)}
class="form-control" class="form-control"
rows={3} rows={3}
@ -161,8 +159,8 @@ export class CommunityForm extends Component<
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="community-category"> <label class="col-12 col-form-label" htmlFor="community-category">
{ i18n.t('category') } {i18n.t('category')}
</label> </label>
<div class="col-12"> <div class="col-12">
<select <select
@ -189,8 +187,8 @@ export class CommunityForm extends Component<
checked={this.state.communityForm.nsfw} checked={this.state.communityForm.nsfw}
onChange={linkEvent(this, this.handleCommunityNsfwChange)} onChange={linkEvent(this, this.handleCommunityNsfwChange)}
/> />
<label class="form-check-label" for="community-nsfw"> <label class="form-check-label" htmlFor="community-nsfw">
{ i18n.t('nsfw') } {i18n.t('nsfw')}
</label> </label>
</div> </div>
</div> </div>
@ -215,7 +213,7 @@ export class CommunityForm extends Component<
class="btn btn-secondary" class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)} onClick={linkEvent(this, this.handleCancel)}
> >
{ i18n.t('cancel') } {i18n.t('cancel')}
</button> </button>
)} )}
</div> </div>

View file

@ -14,7 +14,7 @@ import {
GetCommunityForm, GetCommunityForm,
ListingType, ListingType,
GetPostsResponse, GetPostsResponse,
CreatePostLikeResponse, PostResponse,
WebSocketJsonResponse, WebSocketJsonResponse,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
@ -28,7 +28,6 @@ import {
postRefetchSeconds, postRefetchSeconds,
toast, toast,
} from '../utils'; } from '../utils';
import { T } from 'inferno-i18next';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
interface State { interface State {
@ -128,11 +127,11 @@ export class Community extends Component<any, State> {
return ( return (
<div class="container"> <div class="container">
{this.state.loading ? ( {this.state.loading ? (
<p class="text-center"> <h5>
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
</p> </h5>
) : ( ) : (
<div class="row"> <div class="row">
<div class="col-12 col-md-8"> <div class="col-12 col-md-8">
@ -140,12 +139,12 @@ export class Community extends Component<any, State> {
{this.state.community.title} {this.state.community.title}
{this.state.community.removed && ( {this.state.community.removed && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('removed') } {i18n.t('removed')}
</small> </small>
)} )}
{this.state.community.nsfw && ( {this.state.community.nsfw && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('nsfw') } {i18n.t('nsfw')}
</small> </small>
)} )}
</h5> </h5>
@ -192,7 +191,7 @@ export class Community extends Component<any, State> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
{ i18n.t('prev') } {i18n.t('prev')}
</button> </button>
)} )}
{this.state.posts.length == fetchLimit && ( {this.state.posts.length == fetchLimit && (
@ -200,7 +199,7 @@ export class Community extends Component<any, State> {
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
)} )}
</div> </div>
@ -287,7 +286,7 @@ export class Community extends Component<any, State> {
this.state.loading = false; this.state.loading = false;
this.setState(this.state); this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as CreatePostLikeResponse; let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id); let found = this.state.posts.find(c => c.id == data.post.id);
found.my_vote = data.post.my_vote; found.my_vote = data.post.my_vote;
found.score = data.post.score; found.score = data.post.score;

View file

@ -3,7 +3,6 @@ import { CommunityForm } from './community-form';
import { Community } from '../interfaces'; import { Community } from '../interfaces';
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
export class CreateCommunity extends Component<any, any> { export class CreateCommunity extends Component<any, any> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
@ -22,9 +21,7 @@ export class CreateCommunity extends Component<any, any> {
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4"> <div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5> <h5>{i18n.t('create_community')}</h5>
{ i18n.t('create_community') }
</h5>
<CommunityForm onCreate={this.handleCommunityCreate} /> <CommunityForm onCreate={this.handleCommunityCreate} />
</div> </div>
</div> </div>

View file

@ -3,7 +3,6 @@ import { PostForm } from './post-form';
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { PostFormParams } from '../interfaces'; import { PostFormParams } from '../interfaces';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
export class CreatePost extends Component<any, any> { export class CreatePost extends Component<any, any> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
@ -22,9 +21,7 @@ export class CreatePost extends Component<any, any> {
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4"> <div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5> <h5>{i18n.t('create_post')}</h5>
{ i18n.t('create_post') }
</h5>
<PostForm onCreate={this.handlePostCreate} params={this.params} /> <PostForm onCreate={this.handlePostCreate} params={this.params} />
</div> </div>
</div> </div>

View file

@ -122,7 +122,7 @@ export class Inbox extends Component<any, InboxState> {
<ul class="list-inline mb-1 text-muted small font-weight-bold"> <ul class="list-inline mb-1 text-muted small font-weight-bold">
<li className="list-inline-item"> <li className="list-inline-item">
<span class="pointer" onClick={this.markAllAsRead}> <span class="pointer" onClick={this.markAllAsRead}>
{ i18n.t('mark_all_as_read') } {i18n.t('mark_all_as_read')}
</span> </span>
</li> </li>
</ul> </ul>
@ -147,40 +147,20 @@ export class Inbox extends Component<any, InboxState> {
onChange={linkEvent(this, this.handleUnreadOrAllChange)} onChange={linkEvent(this, this.handleUnreadOrAllChange)}
class="custom-select custom-select-sm w-auto mr-2" class="custom-select custom-select-sm w-auto mr-2"
> >
<option disabled> <option disabled>{i18n.t('type')}</option>
{ i18n.t('type') } <option value={UnreadOrAll.Unread}>{i18n.t('unread')}</option>
<option value={UnreadOrAll.All}>{i18n.t('all')}</option>
</option>
<option value={UnreadOrAll.Unread}>
{ i18n.t('unread') }
</option>
<option value={UnreadOrAll.All}>
{ i18n.t('all') }
</option>
</select> </select>
<select <select
value={this.state.unreadType} value={this.state.unreadType}
onChange={linkEvent(this, this.handleUnreadTypeChange)} onChange={linkEvent(this, this.handleUnreadTypeChange)}
class="custom-select custom-select-sm w-auto mr-2" class="custom-select custom-select-sm w-auto mr-2"
> >
<option disabled> <option disabled>{i18n.t('type')}</option>
{ i18n.t('type') } <option value={UnreadType.All}>{i18n.t('all')}</option>
</option> <option value={UnreadType.Replies}>{i18n.t('replies')}</option>
<option value={UnreadType.All}> <option value={UnreadType.Mentions}>{i18n.t('mentions')}</option>
{ i18n.t('all') } <option value={UnreadType.Messages}>{i18n.t('messages')}</option>
</option>
<option value={UnreadType.Both}>
{ i18n.t('both') }
</option>
<option value={UnreadType.Replies}>
{ i18n.t('replies') }
</option>
<option value={UnreadType.Mentions}>
{ i18n.t('mentions') }
</option>
<option value={UnreadType.Messages}>
{ i18n.t('messages') }
</option>
</select> </select>
<SortSelect <SortSelect
sort={this.state.sort} sort={this.state.sort}
@ -252,14 +232,14 @@ export class Inbox extends Component<any, InboxState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
{ i18n.t('prev') } {i18n.t('prev')}
</button> </button>
)} )}
<button <button
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
</div> </div>
); );

View file

@ -13,7 +13,6 @@ import {
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
import { wsJsonToRes, validEmail, toast } from '../utils'; import { wsJsonToRes, validEmail, toast } from '../utils';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface State { interface State {
loginForm: LoginForm; loginForm: LoginForm;
@ -78,10 +77,13 @@ export class Login extends Component<any, State> {
return ( return (
<div> <div>
<form onSubmit={linkEvent(this, this.handleLoginSubmit)}> <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
<h5>{ i18n.t('login') }</h5> <h5>{i18n.t('login')}</h5>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="login-email-or-username"> <label
{ i18n.t('email_or_username') } class="col-sm-2 col-form-label"
htmlFor="login-email-or-username"
>
{i18n.t('email_or_username')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -96,8 +98,8 @@ export class Login extends Component<any, State> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="login-password"> <label class="col-sm-2 col-form-label" htmlFor="login-password">
{ i18n.t('password') } {i18n.t('password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -113,7 +115,7 @@ export class Login extends Component<any, State> {
onClick={linkEvent(this, this.handlePasswordReset)} onClick={linkEvent(this, this.handlePasswordReset)}
className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold" className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold"
> >
{ i18n.t('forgot_password') } {i18n.t('forgot_password')}
</button> </button>
</div> </div>
</div> </div>
@ -137,13 +139,11 @@ export class Login extends Component<any, State> {
registerForm() { registerForm() {
return ( return (
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}> <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
<h2> <h5>{i18n.t('sign_up')}</h5>
{ i18n.t('sign_up') }
</h2>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="register-username"> <label class="col-sm-2 col-form-label" htmlFor="register-username">
{ i18n.t('username') } {i18n.t('username')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
@ -162,8 +162,8 @@ export class Login extends Component<any, State> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="register-email"> <label class="col-sm-2 col-form-label" htmlFor="register-email">
{ i18n.t('email') } {i18n.t('email')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -179,8 +179,8 @@ export class Login extends Component<any, State> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="register-password"> <label class="col-sm-2 col-form-label" htmlFor="register-password">
{ i18n.t('password') } {i18n.t('password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -195,8 +195,11 @@ export class Login extends Component<any, State> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="register-verify-password"> <label
{ i18n.t('verify_password') } class="col-sm-2 col-form-label"
htmlFor="register-verify-password"
>
{i18n.t('verify_password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -210,7 +213,7 @@ export class Login extends Component<any, State> {
</div> </div>
</div> </div>
{ this.state.enable_nsfw && ( {this.state.enable_nsfw && (
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-10"> <div class="col-sm-10">
<div class="form-check"> <div class="form-check">
@ -221,8 +224,8 @@ export class Login extends Component<any, State> {
checked={this.state.registerForm.show_nsfw} checked={this.state.registerForm.show_nsfw}
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)} onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
/> />
<label class="form-check-label" for="register-show-nsfw"> <label class="form-check-label" htmlFor="register-show-nsfw">
{ i18n.t('show_nsfw') } {i18n.t('show_nsfw')}
</label> </label>
</div> </div>
</div> </div>

View file

@ -14,7 +14,7 @@ import {
ListingType, ListingType,
SiteResponse, SiteResponse,
GetPostsResponse, GetPostsResponse,
CreatePostLikeResponse, PostResponse,
Post, Post,
GetPostsForm, GetPostsForm,
WebSocketJsonResponse, WebSocketJsonResponse,
@ -159,7 +159,9 @@ export class Main extends Component<any, MainState> {
return ( return (
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<main role="main" class="col-12 col-md-8">{this.posts()}</main> <main role="main" class="col-12 col-md-8">
{this.posts()}
</main>
<aside class="col-12 col-md-4">{this.my_sidebar()}</aside> <aside class="col-12 col-md-4">{this.my_sidebar()}</aside>
</div> </div>
</div> </div>
@ -200,7 +202,7 @@ export class Main extends Component<any, MainState> {
class="btn btn-sm btn-secondary btn-block" class="btn btn-sm btn-secondary btn-block"
to="/create_community" to="/create_community"
> >
<T i18nKey="create_a_community">#</T> {i18n.t('create_a_community')}
</Link> </Link>
</div> </div>
</div> </div>
@ -270,73 +272,43 @@ export class Main extends Component<any, MainState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleEditClick)} onClick={linkEvent(this, this.handleEditClick)}
> >
<T i18nKey="edit">#</T> {i18n.t('edit')}
</span> </span>
</li> </li>
</ul> </ul>
)} )}
<ul class="my-2 list-inline"> <ul class="my-2 list-inline">
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_online', { count: this.state.site.online })}
i18nKey="number_online"
interpolation={{ count: this.state.site.online }}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_users', {
i18nKey="number_of_users" count: this.state.site.site.number_of_users,
interpolation={{ })}
count: this.state.site.site.number_of_users,
}}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_communities', {
i18nKey="number_of_communities" count: this.state.site.site.number_of_communities,
interpolation={{ })}
count: this.state.site.site.number_of_communities,
}}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_posts', {
i18nKey="number_of_posts" count: this.state.site.site.number_of_posts,
interpolation={{ })}
count: this.state.site.site.number_of_posts,
}}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_comments', {
i18nKey="number_of_comments" count: this.state.site.site.number_of_comments,
interpolation={{ })}
count: this.state.site.site.number_of_comments,
}}
>
#
</T>
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">
<Link className="badge badge-secondary" to="/modlog"> <Link className="badge badge-secondary" to="/modlog">
<T i18nKey="modlog">#</T> {i18n.t('modlog')}
</Link> </Link>
</li> </li>
</ul> </ul>
<ul class="mt-1 list-inline small mb-0"> <ul class="mt-1 list-inline small mb-0">
<li class="list-inline-item"> <li class="list-inline-item">{i18n.t('admins')}:</li>
<T i18nKey="admins" class="d-inline">
#
</T>
:
</li>
{this.state.site.admins.map(admin => ( {this.state.site.admins.map(admin => (
<li class="list-inline-item"> <li class="list-inline-item">
<Link class="text-info" to={`/u/${admin.name}`}> <Link class="text-info" to={`/u/${admin.name}`}>
@ -376,9 +348,7 @@ export class Main extends Component<any, MainState> {
<div class="card border-secondary"> <div class="card border-secondary">
<div class="card-body"> <div class="card-body">
<h5> <h5>
<T i18nKey="powered_by" class="d-inline"> {i18n.t('powered_by')}
#
</T>
<svg class="icon mx-2"> <svg class="icon mx-2">
<use xlinkHref="#icon-mouse">#</use> <use xlinkHref="#icon-mouse">#</use>
</svg> </svg>
@ -415,11 +385,11 @@ export class Main extends Component<any, MainState> {
return ( return (
<div class="main-content-wrapper"> <div class="main-content-wrapper">
{this.state.loading ? ( {this.state.loading ? (
<p class="text-center"> <h5>
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
</p> </h5>
) : ( ) : (
<div> <div>
{this.selects()} {this.selects()}
@ -476,7 +446,7 @@ export class Main extends Component<any, MainState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
<T i18nKey="prev">#</T> {i18n.t('prev')}
</button> </button>
)} )}
{this.state.posts.length == fetchLimit && ( {this.state.posts.length == fetchLimit && (
@ -484,7 +454,7 @@ export class Main extends Component<any, MainState> {
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
<T i18nKey="next">#</T> {i18n.t('next')}
</button> </button>
)} )}
</div> </div>
@ -601,7 +571,7 @@ export class Main extends Component<any, MainState> {
this.state.loading = false; this.state.loading = false;
this.setState(this.state); this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as CreatePostLikeResponse; let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id); let found = this.state.posts.find(c => c.id == data.post.id);
found.my_vote = data.post.my_vote; found.my_vote = data.post.my_vote;
found.score = data.post.score; found.score = data.post.score;

View file

@ -15,6 +15,7 @@ import {
ModBan, ModBan,
ModAddCommunity, ModAddCommunity,
ModAdd, ModAdd,
WebSocketJsonResponse,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { wsJsonToRes, addTypeInfo, fetchLimit, toast } from '../utils'; import { wsJsonToRes, addTypeInfo, fetchLimit, toast } from '../utils';
@ -343,7 +344,7 @@ export class Modlog extends Component<any, ModlogState> {
return ( return (
<div class="container"> <div class="container">
{this.state.loading ? ( {this.state.loading ? (
<h5 class="text-center"> <h5 class="">
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
@ -359,15 +360,15 @@ export class Modlog extends Component<any, ModlogState> {
/c/{this.state.communityName}{' '} /c/{this.state.communityName}{' '}
</Link> </Link>
)} )}
<span>{ i18n.t('modlog') }</span> <span>{i18n.t('modlog')}</span>
</h5> </h5>
<div class="table-responsive"> <div class="table-responsive">
<table id="modlog_table" class="table table-sm table-hover"> <table id="modlog_table" class="table table-sm table-hover">
<thead class="pointer"> <thead class="pointer">
<tr> <tr>
<th> { i18n.t('time')}</th> <th> {i18n.t('time')}</th>
<th>{ i18n.t('mod')}</th> <th>{i18n.t('mod')}</th>
<th>{ i18n.t('action')}</th> <th>{i18n.t('action')}</th>
</tr> </tr>
</thead> </thead>
{this.combined()} {this.combined()}
@ -388,14 +389,14 @@ export class Modlog extends Component<any, ModlogState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
{ i18n.t('prev') } {i18n.t('prev')}
</button> </button>
)} )}
<button <button
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
</div> </div>
); );

View file

@ -27,7 +27,6 @@ import {
} from '../utils'; } from '../utils';
import { version } from '../version'; import { version } from '../version';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface NavbarState { interface NavbarState {
isLoggedIn: boolean; isLoggedIn: boolean;
@ -113,12 +112,12 @@ export class Navbar extends Component<any, NavbarState> {
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
<li class="nav-item"> <li class="nav-item">
<Link class="nav-link" to="/communities"> <Link class="nav-link" to="/communities">
{ i18n.t('communities') } {i18n.t('communities')}
</Link> </Link>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<Link class="nav-link" to="/search"> <Link class="nav-link" to="/search">
{ i18n.t('search') } {i18n.t('search')}
</Link> </Link>
</li> </li>
<li class="nav-item"> <li class="nav-item">
@ -129,17 +128,17 @@ export class Navbar extends Component<any, NavbarState> {
state: { prevPath: this.currentLocation }, state: { prevPath: this.currentLocation },
}} }}
> >
{ i18n.t('create_post') } {i18n.t('create_post')}
</Link> </Link>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<Link class="nav-link" to="/create_community"> <Link class="nav-link" to="/create_community">
{ i18n.t('create_community') } {i18n.t('create_community')}
</Link> </Link>
</li> </li>
<li className="nav-item"> <li className="nav-item">
<Link <Link
class="nav-link ml-2" class="nav-link"
to="/sponsors" to="/sponsors"
title={i18n.t('donate_to_lemmy')} title={i18n.t('donate_to_lemmy')}
> >
@ -187,7 +186,7 @@ export class Navbar extends Component<any, NavbarState> {
</> </>
) : ( ) : (
<Link class="nav-link" to="/login"> <Link class="nav-link" to="/login">
{ i18n.t('login_sign_up') } {i18n.t('login_sign_up')}
</Link> </Link>
)} )}
</ul> </ul>

View file

@ -10,7 +10,6 @@ import {
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
import { wsJsonToRes, capitalizeFirstLetter, toast } from '../utils'; import { wsJsonToRes, capitalizeFirstLetter, toast } from '../utils';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface State { interface State {
passwordChangeForm: PasswordChangeForm; passwordChangeForm: PasswordChangeForm;
@ -58,9 +57,7 @@ export class PasswordChange extends Component<any, State> {
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4"> <div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5> <h5>{i18n.t('password_change')}</h5>
{ i18n.t('password_change') }
</h5>
{this.passwordChangeForm()} {this.passwordChangeForm()}
</div> </div>
</div> </div>
@ -73,7 +70,7 @@ export class PasswordChange extends Component<any, State> {
<form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}> <form onSubmit={linkEvent(this, this.handlePasswordChangeSubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label"> <label class="col-sm-2 col-form-label">
<T i18nKey="new_password">#</T> {i18n.t('new_password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -87,7 +84,7 @@ export class PasswordChange extends Component<any, State> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label"> <label class="col-sm-2 col-form-label">
<T i18nKey="verify_password">#</T> {i18n.t('verify_password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input

View file

@ -36,7 +36,6 @@ import {
import autosize from 'autosize'; import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js'; import Tribute from 'tributejs/src/Tribute.js';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface PostFormProps { interface PostFormProps {
post?: Post; // If a post is given, that means this is an edit post?: Post; // If a post is given, that means this is an edit
@ -151,8 +150,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
<div> <div>
<form onSubmit={linkEvent(this, this.handlePostSubmit)}> <form onSubmit={linkEvent(this, this.handlePostSubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="post-url"> <label class="col-sm-2 col-form-label" htmlFor="post-url">
{ i18n.t('url') } {i18n.t('url')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -168,12 +167,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
class="mt-1 text-muted small font-weight-bold pointer" class="mt-1 text-muted small font-weight-bold pointer"
onClick={linkEvent(this, this.copySuggestedTitle)} onClick={linkEvent(this, this.copySuggestedTitle)}
> >
<T {i18n.t('copy_suggested_title', {
i18nKey="copy_suggested_title" title: this.state.suggestedTitle,
interpolation={{ title: this.state.suggestedTitle }} })}
>
#
</T>
</div> </div>
)} )}
<form> <form>
@ -182,7 +178,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
className={`${UserService.Instance.user && className={`${UserService.Instance.user &&
'pointer'} d-inline-block mr-2 float-right text-muted small font-weight-bold`} 'pointer'} d-inline-block mr-2 float-right text-muted small font-weight-bold`}
> >
{ i18n.t('upload_image') } {i18n.t('upload_image')}
</label> </label>
<input <input
id="file-upload" id="file-upload"
@ -202,7 +198,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
target="_blank" target="_blank"
class="mr-2 d-inline-block float-right text-muted small font-weight-bold" class="mr-2 d-inline-block float-right text-muted small font-weight-bold"
> >
{ i18n.t('archive_link') } {i18n.t('archive_link')}
</a> </a>
)} )}
{this.state.imageLoading && ( {this.state.imageLoading && (
@ -216,7 +212,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
{this.state.crossPosts.length > 0 && ( {this.state.crossPosts.length > 0 && (
<> <>
<div class="my-1 text-muted small font-weight-bold"> <div class="my-1 text-muted small font-weight-bold">
{ i18n.t('cross_posts') } {i18n.t('cross_posts')}
</div> </div>
<PostListings showCommunity posts={this.state.crossPosts} /> <PostListings showCommunity posts={this.state.crossPosts} />
</> </>
@ -224,8 +220,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="post-title"> <label class="col-sm-2 col-form-label" htmlFor="post-title">
{ i18n.t('title') } {i18n.t('title')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea <textarea
@ -241,7 +237,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
{this.state.suggestedPosts.length > 0 && ( {this.state.suggestedPosts.length > 0 && (
<> <>
<div class="my-1 text-muted small font-weight-bold"> <div class="my-1 text-muted small font-weight-bold">
{ i18n.t('related_posts') } {i18n.t('related_posts')}
</div> </div>
<PostListings posts={this.state.suggestedPosts} /> <PostListings posts={this.state.suggestedPosts} />
</> </>
@ -250,14 +246,13 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="post-body"> <label class="col-sm-2 col-form-label" htmlFor={this.id}>
{ i18n.t('body') } {i18n.t('body')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea <textarea
id={this.id} id={this.id}
value={this.state.postForm.body} value={this.state.postForm.body}
id="post-body"
onInput={linkEvent(this, this.handlePostBodyChange)} onInput={linkEvent(this, this.handlePostBodyChange)}
className={`form-control ${this.state.previewMode && 'd-none'}`} className={`form-control ${this.state.previewMode && 'd-none'}`}
rows={4} rows={4}
@ -275,7 +270,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
.previewMode && 'active'}`} .previewMode && 'active'}`}
onClick={linkEvent(this, this.handlePreviewToggle)} onClick={linkEvent(this, this.handlePreviewToggle)}
> >
{ i18n.t('preview') } {i18n.t('preview')}
</button> </button>
)} )}
<a <a
@ -283,14 +278,14 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
target="_blank" target="_blank"
class="d-inline-block float-right text-muted small font-weight-bold" class="d-inline-block float-right text-muted small font-weight-bold"
> >
{ i18n.t('formatting_help') } {i18n.t('formatting_help')}
</a> </a>
</div> </div>
</div> </div>
{!this.props.post && ( {!this.props.post && (
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="post-community"> <label class="col-sm-2 col-form-label" htmlFor="post-community">
{ i18n.t('community') } {i18n.t('community')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<select <select
@ -317,8 +312,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
checked={this.state.postForm.nsfw} checked={this.state.postForm.nsfw}
onChange={linkEvent(this, this.handlePostNsfwChange)} onChange={linkEvent(this, this.handlePostNsfwChange)}
/> />
<label class="form-check-label" for="post-nsfw"> <label class="form-check-label" htmlFor="post-nsfw">
{ i18n.t('nsfw') } {i18n.t('nsfw')}
</label> </label>
</div> </div>
</div> </div>
@ -343,7 +338,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
class="btn btn-secondary" class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)} onClick={linkEvent(this, this.handleCancel)}
> >
{ i18n.t('cancel') } {i18n.t('cancel')}
</button> </button>
)} )}
</div> </div>

View file

@ -30,7 +30,6 @@ import {
imageThumbnailer, imageThumbnailer,
} from '../utils'; } from '../utils';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface PostListingState { interface PostListingState {
showEdit: boolean; showEdit: boolean;
@ -247,27 +246,27 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
)} )}
{post.removed && ( {post.removed && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('removed') } {i18n.t('removed')}
</small> </small>
)} )}
{post.deleted && ( {post.deleted && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('deleted') } {i18n.t('deleted')}
</small> </small>
)} )}
{post.locked && ( {post.locked && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('locked') } {i18n.t('locked')}
</small> </small>
)} )}
{post.stickied && ( {post.stickied && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('stickied') } {i18n.t('stickied')}
</small> </small>
)} )}
{post.nsfw && ( {post.nsfw && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('nsfw') } {i18n.t('nsfw')}
</small> </small>
)} )}
</div> </div>
@ -288,18 +287,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<span>{post.creator_name}</span> <span>{post.creator_name}</span>
</Link> </Link>
{this.isMod && ( {this.isMod && (
<span className="mx-1 badge badge-light"> <span className="mx-1 badge badge-light">{i18n.t('mod')}</span>
{ i18n.t('mod') }
</span>
)} )}
{this.isAdmin && ( {this.isAdmin && (
<span className="mx-1 badge badge-light"> <span className="mx-1 badge badge-light">
{ i18n.t('admin') } {i18n.t('admin')}
</span> </span>
)} )}
{(post.banned_from_community || post.banned) && ( {(post.banned_from_community || post.banned) && (
<span className="mx-1 badge badge-danger"> <span className="mx-1 badge badge-danger">
{ i18n.t('banned') } {i18n.t('banned')}
</span> </span>
)} )}
{this.props.showCommunity && ( {this.props.showCommunity && (
@ -326,12 +323,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">
<Link className="text-muted" to={`/post/${post.id}`}> <Link className="text-muted" to={`/post/${post.id}`}>
<T {i18n.t('number_of_comments', {
i18nKey="number_of_comments" count: post.number_of_comments,
interpolation={{ count: post.number_of_comments }} })}
>
#
</T>
</Link> </Link>
</li> </li>
</ul> </ul>
@ -353,7 +347,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
className="text-muted" className="text-muted"
to={`/create_post${this.crossPostParams}`} to={`/create_post${this.crossPostParams}`}
> >
<T i18nKey="cross_post">#</T> {i18n.t('cross_post')}
</Link> </Link>
</li> </li>
</> </>
@ -365,7 +359,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleEditClick)} onClick={linkEvent(this, this.handleEditClick)}
> >
<T i18nKey="edit">#</T> {i18n.t('edit')}
</span> </span>
</li> </li>
<li className="list-inline-item mr-2"> <li className="list-inline-item mr-2">
@ -406,14 +400,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModRemoveShow)} onClick={linkEvent(this, this.handleModRemoveShow)}
> >
{ i18n.t('remove') } {i18n.t('remove')}
</span> </span>
) : ( ) : (
<span <span
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModRemoveSubmit)} onClick={linkEvent(this, this.handleModRemoveSubmit)}
> >
{ i18n.t('restore') } {i18n.t('restore')}
</span> </span>
)} )}
</li> </li>
@ -430,7 +424,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleModBanFromCommunityShow this.handleModBanFromCommunityShow
)} )}
> >
{ i18n.t('ban') } {i18n.t('ban')}
</span> </span>
) : ( ) : (
<span <span
@ -440,7 +434,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleModBanFromCommunitySubmit this.handleModBanFromCommunitySubmit
)} )}
> >
{ i18n.t('unban') } {i18n.t('unban')}
</span> </span>
)} )}
</li> </li>
@ -473,12 +467,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleShowConfirmTransferCommunity this.handleShowConfirmTransferCommunity
)} )}
> >
<T i18nKey="transfer_community">#</T> {i18n.t('transfer_community')}
</span> </span>
) : ( ) : (
<> <>
<span class="d-inline-block mr-1"> <span class="d-inline-block mr-1">
<T i18nKey="are_you_sure">#</T> {i18n.t('are_you_sure')}
</span> </span>
<span <span
class="pointer d-inline-block mr-1" class="pointer d-inline-block mr-1"
@ -487,7 +481,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleTransferCommunity this.handleTransferCommunity
)} )}
> >
{ i18n.t('yes') } {i18n.t('yes')}
</span> </span>
<span <span
class="pointer d-inline-block" class="pointer d-inline-block"
@ -496,7 +490,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleCancelShowConfirmTransferCommunity this.handleCancelShowConfirmTransferCommunity
)} )}
> >
{ i18n.t('no') } {i18n.t('no')}
</span> </span>
</> </>
)} )}
@ -512,14 +506,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModBanShow)} onClick={linkEvent(this, this.handleModBanShow)}
> >
{ i18n.t('ban_from_site') } {i18n.t('ban_from_site')}
</span> </span>
) : ( ) : (
<span <span
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModBanSubmit)} onClick={linkEvent(this, this.handleModBanSubmit)}
> >
{ i18n.t('unban_from_site') } {i18n.t('unban_from_site')}
</span> </span>
)} )}
</li> </li>
@ -549,18 +543,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleShowConfirmTransferSite this.handleShowConfirmTransferSite
)} )}
> >
{ i18n.t('transfer_site') } {i18n.t('transfer_site')}
</span> </span>
) : ( ) : (
<> <>
<span class="d-inline-block mr-1"> <span class="d-inline-block mr-1">
{ i18n.t('are_you_sure') } {i18n.t('are_you_sure')}
</span> </span>
<span <span
class="pointer d-inline-block mr-1" class="pointer d-inline-block mr-1"
onClick={linkEvent(this, this.handleTransferSite)} onClick={linkEvent(this, this.handleTransferSite)}
> >
{ i18n.t('yes') } {i18n.t('yes')}
</span> </span>
<span <span
class="pointer d-inline-block" class="pointer d-inline-block"
@ -569,7 +563,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleCancelShowConfirmTransferSite this.handleCancelShowConfirmTransferSite
)} )}
> >
{ i18n.t('no') } {i18n.t('no')}
</span> </span>
</> </>
)} )}
@ -583,7 +577,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
className="pointer" className="pointer"
onClick={linkEvent(this, this.handleViewSource)} onClick={linkEvent(this, this.handleViewSource)}
> >
{ i18n.t('view_source') } {i18n.t('view_source')}
</span> </span>
</li> </li>
)} )}
@ -601,15 +595,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onInput={linkEvent(this, this.handleModRemoveReasonChange)} onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/> />
<button type="submit" class="btn btn-secondary"> <button type="submit" class="btn btn-secondary">
{ i18n.t('remove_post') } {i18n.t('remove_post')}
</button> </button>
</form> </form>
)} )}
{this.state.showBanDialog && ( {this.state.showBanDialog && (
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}> <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-form-label" for="post-listing-reason"> <label class="col-form-label" htmlFor="post-listing-reason">
{ i18n.t('reason') } {i18n.t('reason')}
</label> </label>
<input <input
type="text" type="text"

View file

@ -3,7 +3,6 @@ import { Link } from 'inferno-router';
import { Post } from '../interfaces'; import { Post } from '../interfaces';
import { PostListing } from './post-listing'; import { PostListing } from './post-listing';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface PostListingsProps { interface PostListingsProps {
posts: Array<Post>; posts: Array<Post>;
@ -31,12 +30,12 @@ export class PostListings extends Component<PostListingsProps, any> {
)) ))
) : ( ) : (
<> <>
<h5> <div>{i18n.t('no_posts')}</div>
{ i18n.t('no_posts') }
</h5>
{this.props.showCommunity !== undefined && ( {this.props.showCommunity !== undefined && (
<div> <div>
<Link to="/communities">{ i18n.t('subscribe_to_communities') }</Link> <Link to="/communities">
{i18n.t('subscribe_to_communities')}
</Link>
</div> </div>
)} )}
</> </>

View file

@ -11,7 +11,6 @@ import {
CommentForm as CommentFormI, CommentForm as CommentFormI,
CommentResponse, CommentResponse,
CommentSortType, CommentSortType,
CreatePostLikeResponse,
CommunityUser, CommunityUser,
CommunityResponse, CommunityResponse,
CommentNode as CommentNodeI, CommentNode as CommentNodeI,
@ -38,7 +37,6 @@ import { CommentForm } from './comment-form';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import autosize from 'autosize'; import autosize from 'autosize';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface PostState { interface PostState {
post: PostI; post: PostI;
@ -155,11 +153,11 @@ export class Post extends Component<any, PostState> {
return ( return (
<div class="container"> <div class="container">
{this.state.loading ? ( {this.state.loading ? (
<p class="text-center"> <h5>
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
</p> </h5>
) : ( ) : (
<div class="row"> <div class="row">
<div class="col-12 col-md-8 mb-3"> <div class="col-12 col-md-8 mb-3">
@ -173,7 +171,7 @@ export class Post extends Component<any, PostState> {
{this.state.crossPosts.length > 0 && ( {this.state.crossPosts.length > 0 && (
<> <>
<div class="my-1 text-muted small font-weight-bold"> <div class="my-1 text-muted small font-weight-bold">
{ i18n.t('cross_posts') } {i18n.t('cross_posts')}
</div> </div>
<PostListings showCommunity posts={this.state.crossPosts} /> <PostListings showCommunity posts={this.state.crossPosts} />
</> </>
@ -243,9 +241,7 @@ export class Post extends Component<any, PostState> {
return ( return (
<div class="d-none d-md-block new-comments mb-3 card border-secondary"> <div class="d-none d-md-block new-comments mb-3 card border-secondary">
<div class="card-body small"> <div class="card-body small">
<h6> <h6>{i18n.t('recent_comments')}</h6>
{ i18n.t('recent_comments') }
</h6>
{this.state.comments.map(comment => ( {this.state.comments.map(comment => (
<CommentNodes <CommentNodes
nodes={[{ comment: comment }]} nodes={[{ comment: comment }]}
@ -412,7 +408,7 @@ export class Post extends Component<any, PostState> {
} }
this.setState(this.state); this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as CreatePostLikeResponse; let data = res.data as PostResponse;
this.state.post.my_vote = data.post.my_vote; this.state.post.my_vote = data.post.my_vote;
this.state.post.score = data.post.score; this.state.post.score = data.post.score;
this.state.post.upvotes = data.post.upvotes; this.state.post.upvotes = data.post.upvotes;

View file

@ -12,7 +12,7 @@ import {
SearchForm, SearchForm,
SearchResponse, SearchResponse,
SearchType, SearchType,
CreatePostLikeResponse, PostResponse,
CommentResponse, CommentResponse,
WebSocketJsonResponse, WebSocketJsonResponse,
} from '../interfaces'; } from '../interfaces';
@ -30,7 +30,6 @@ import { PostListing } from './post-listing';
import { SortSelect } from './sort-select'; import { SortSelect } from './sort-select';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface SearchState { interface SearchState {
q: string; q: string;
@ -126,9 +125,7 @@ export class Search extends Component<any, SearchState> {
render() { render() {
return ( return (
<div class="container"> <div class="container">
<h5> <h5>{i18n.t('search')}</h5>
{ i18n.t('search') }
</h5>
{this.selects()} {this.selects()}
{this.searchForm()} {this.searchForm()}
{this.state.type_ == SearchType.All && this.all()} {this.state.type_ == SearchType.All && this.all()}
@ -163,9 +160,7 @@ export class Search extends Component<any, SearchState> {
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
) : ( ) : (
<span> <span>{i18n.t('search')}</span>
{ i18n.t('search') }
</span>
)} )}
</button> </button>
</form> </form>
@ -180,24 +175,14 @@ export class Search extends Component<any, SearchState> {
onChange={linkEvent(this, this.handleTypeChange)} onChange={linkEvent(this, this.handleTypeChange)}
class="custom-select custom-select-sm w-auto" class="custom-select custom-select-sm w-auto"
> >
<option disabled> <option disabled>{i18n.t('type')}</option>
{ i18n.t('type') } <option value={SearchType.All}>{i18n.t('all')}</option>
</option> <option value={SearchType.Comments}>{i18n.t('comments')}</option>
<option value={SearchType.All}> <option value={SearchType.Posts}>{i18n.t('posts')}</option>
{ i18n.t('all') }
</option>
<option value={SearchType.Comments}>
{ i18n.t('comments') }
</option>
<option value={SearchType.Posts}>
{ i18n.t('posts') }
</option>
<option value={SearchType.Communities}> <option value={SearchType.Communities}>
{ i18n.t('communities') } {i18n.t('communities')}
</option>
<option value={SearchType.Users}>
{ i18n.t('users') }
</option> </option>
<option value={SearchType.Users}>{i18n.t('users')}</option>
</select> </select>
<span class="ml-2"> <span class="ml-2">
<SortSelect <SortSelect
@ -383,14 +368,14 @@ export class Search extends Component<any, SearchState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
{ i18n.t('prev') } {i18n.t('prev')}
</button> </button>
)} )}
<button <button
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
</div> </div>
); );
@ -404,11 +389,7 @@ export class Search extends Component<any, SearchState> {
res.posts.length == 0 && res.posts.length == 0 &&
res.comments.length == 0 && res.comments.length == 0 &&
res.communities.length == 0 && res.communities.length == 0 &&
res.users.length == 0 && ( res.users.length == 0 && <span>{i18n.t('no_results')}</span>}
<span>
{ i18n.t('no_results') }
</span>
)}
</div> </div>
); );
} }
@ -506,7 +487,7 @@ export class Search extends Component<any, SearchState> {
} }
this.setState(this.state); this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as CreatePostLikeResponse; let data = res.data as PostResponse;
let found = this.state.searchResponse.posts.find( let found = this.state.searchResponse.posts.find(
c => c.id == data.post.id c => c.id == data.post.id
); );

View file

@ -11,7 +11,6 @@ import { WebSocketService, UserService } from '../services';
import { wsJsonToRes, toast } from '../utils'; import { wsJsonToRes, toast } from '../utils';
import { SiteForm } from './site-form'; import { SiteForm } from './site-form';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface State { interface State {
userForm: RegisterForm; userForm: RegisterForm;
@ -61,9 +60,7 @@ export class Setup extends Component<any, State> {
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 offset-lg-3 col-lg-6"> <div class="col-12 offset-lg-3 col-lg-6">
<h3> <h3>{i18n.t('lemmy_instance_setup')}</h3>
{ i18n.t('lemmy_instance_setup') }
</h3>
{!this.state.doneRegisteringUser ? ( {!this.state.doneRegisteringUser ? (
this.registerUser() this.registerUser()
) : ( ) : (
@ -78,10 +75,10 @@ export class Setup extends Component<any, State> {
registerUser() { registerUser() {
return ( return (
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}> <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
<h4>{ i18n.t('setup_admin')}</h4> <h5>{i18n.t('setup_admin')}</h5>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="username"> <label class="col-sm-2 col-form-label" htmlFor="username">
{ i18n.t('username') } {i18n.t('username')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -98,8 +95,8 @@ export class Setup extends Component<any, State> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="email"> <label class="col-sm-2 col-form-label" htmlFor="email">
{ i18n.t('email') } {i18n.t('email')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
@ -115,8 +112,8 @@ export class Setup extends Component<any, State> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="password"> <label class="col-sm-2 col-form-label" htmlFor="password">
{ i18n.t('password')} {i18n.t('password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input
@ -130,8 +127,8 @@ export class Setup extends Component<any, State> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label" for="verify-password"> <label class="col-sm-2 col-form-label" htmlFor="verify-password">
{ i18n.t('verify_password') } {i18n.t('verify_password')}
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<input <input

View file

@ -16,7 +16,6 @@ import {
} from '../utils'; } from '../utils';
import { CommunityForm } from './community-form'; import { CommunityForm } from './community-form';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface SidebarProps { interface SidebarProps {
community: Community; community: Community;
@ -72,12 +71,12 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
<span>{community.title}</span> <span>{community.title}</span>
{community.removed && ( {community.removed && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
{ i18n.t('removed') } {i18n.t('removed')}
</small> </small>
)} )}
{community.deleted && ( {community.deleted && (
<small className="ml-2 text-muted font-italic"> <small className="ml-2 text-muted font-italic">
<T i18nKey="deleted">#</T> {i18n.t('deleted')}
</small> </small>
)} )}
</h5> </h5>
@ -92,7 +91,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleEditClick)} onClick={linkEvent(this, this.handleEditClick)}
> >
{ i18n.t('edit') } {i18n.t('edit')}
</span> </span>
</li> </li>
{this.amCreator && ( {this.amCreator && (
@ -116,14 +115,14 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModRemoveShow)} onClick={linkEvent(this, this.handleModRemoveShow)}
> >
{ i18n.t('remove') } {i18n.t('remove')}
</span> </span>
) : ( ) : (
<span <span
class="pointer" class="pointer"
onClick={linkEvent(this, this.handleModRemoveSubmit)} onClick={linkEvent(this, this.handleModRemoveSubmit)}
> >
{ i18n.t('restore') } {i18n.t('restore')}
</span> </span>
)} )}
</li> </li>
@ -132,8 +131,8 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
{this.state.showRemoveDialog && ( {this.state.showRemoveDialog && (
<form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}> <form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
<div class="form-group row"> <div class="form-group row">
<label class="col-form-label" for="remove-reason"> <label class="col-form-label" htmlFor="remove-reason">
{ i18n.t('reason') } {i18n.t('reason')}
</label> </label>
<input <input
type="text" type="text"
@ -151,7 +150,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
{/* </div> */} {/* </div> */}
<div class="form-group row"> <div class="form-group row">
<button type="submit" class="btn btn-secondary"> <button type="submit" class="btn btn-secondary">
{ i18n.t('remove_community') } {i18n.t('remove_community')}
</button> </button>
</div> </div>
</form> </form>
@ -163,35 +162,26 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
</Link> </Link>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_subscribers', {
i18nKey="number_of_subscribers" count: community.number_of_subscribers,
interpolation={{ count: community.number_of_subscribers }} })}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_posts', {
i18nKey="number_of_posts" count: community.number_of_posts,
interpolation={{ count: community.number_of_posts }} })}
>
#
</T>
</li> </li>
<li className="list-inline-item badge badge-secondary"> <li className="list-inline-item badge badge-secondary">
<T {i18n.t('number_of_comments', {
i18nKey="number_of_comments" count: community.number_of_comments,
interpolation={{ count: community.number_of_comments }} })}
>
#
</T>
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">
<Link <Link
className="badge badge-secondary" className="badge badge-secondary"
to={`/modlog/community/${this.props.community.id}`} to={`/modlog/community/${this.props.community.id}`}
> >
<T i18nKey="modlog">#</T> {i18n.t('modlog')}
</Link> </Link>
</li> </li>
</ul> </ul>
@ -219,7 +209,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
'no-click'}`} 'no-click'}`}
to={`/create_post?community=${community.name}`} to={`/create_post?community=${community.name}`}
> >
{ i18n.t('create_a_post') } {i18n.t('create_a_post')}
</Link> </Link>
<div> <div>
{community.subscribed ? ( {community.subscribed ? (
@ -227,14 +217,14 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
class="btn btn-sm btn-secondary btn-block" class="btn btn-sm btn-secondary btn-block"
onClick={linkEvent(community.id, this.handleUnsubscribe)} onClick={linkEvent(community.id, this.handleUnsubscribe)}
> >
{ i18n.t('unsubscribe') } {i18n.t('unsubscribe')}
</button> </button>
) : ( ) : (
<button <button
class="btn btn-sm btn-secondary btn-block" class="btn btn-sm btn-secondary btn-block"
onClick={linkEvent(community.id, this.handleSubscribe)} onClick={linkEvent(community.id, this.handleSubscribe)}
> >
{ i18n.t('subscribe') } {i18n.t('subscribe')}
</button> </button>
)} )}
</div> </div>

View file

@ -5,7 +5,6 @@ import { capitalizeFirstLetter, randomStr, setupTribute } from '../utils';
import autosize from 'autosize'; import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js'; import Tribute from 'tributejs/src/Tribute.js';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface SiteFormProps { interface SiteFormProps {
site?: Site; // If a site is given, that means this is an edit site?: Site; // If a site is given, that means this is an edit
@ -67,8 +66,8 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
: capitalizeFirstLetter(i18n.t('name')) : capitalizeFirstLetter(i18n.t('name'))
} ${i18n.t('your_site')}`}</h5> } ${i18n.t('your_site')}`}</h5>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="create-site-name"> <label class="col-12 col-form-label" htmlFor="create-site-name">
{ i18n.t('name') } {i18n.t('name')}
</label> </label>
<div class="col-12"> <div class="col-12">
<input <input
@ -84,14 +83,13 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-12 col-form-label" for="create-site-sidebar"> <label class="col-12 col-form-label" htmlFor={this.id}>
{ i18n.t('sidebar') } {i18n.t('sidebar')}
</label> </label>
<div class="col-12"> <div class="col-12">
<textarea <textarea
id={this.id} id={this.id}
value={this.state.siteForm.description} value={this.state.siteForm.description}
id="create-site-sidebar"
onInput={linkEvent(this, this.handleSiteDescriptionChange)} onInput={linkEvent(this, this.handleSiteDescriptionChange)}
class="form-control" class="form-control"
rows={3} rows={3}
@ -109,8 +107,8 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
checked={this.state.siteForm.enable_downvotes} checked={this.state.siteForm.enable_downvotes}
onChange={linkEvent(this, this.handleSiteEnableDownvotesChange)} onChange={linkEvent(this, this.handleSiteEnableDownvotesChange)}
/> />
<label class="form-check-label" for="create-site-downvotes"> <label class="form-check-label" htmlFor="create-site-downvotes">
{ i18n.t('enable_downvotes') } {i18n.t('enable_downvotes')}
</label> </label>
</div> </div>
</div> </div>
@ -125,8 +123,8 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
checked={this.state.siteForm.enable_nsfw} checked={this.state.siteForm.enable_nsfw}
onChange={linkEvent(this, this.handleSiteEnableNsfwChange)} onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
/> />
<label class="form-check-label" for="create-site-enable-nsfw"> <label class="form-check-label" htmlFor="create-site-enable-nsfw">
{ i18n.t('enable_nsfw') } {i18n.t('enable_nsfw')}
</label> </label>
</div> </div>
</div> </div>
@ -144,8 +142,11 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
this.handleSiteOpenRegistrationChange this.handleSiteOpenRegistrationChange
)} )}
/> />
<label class="form-check-label" for="create-site-open-registration"> <label
{ i18n.t('open_registration') } class="form-check-label"
htmlFor="create-site-open-registration"
>
{i18n.t('open_registration')}
</label> </label>
</div> </div>
</div> </div>
@ -169,7 +170,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
class="btn btn-secondary" class="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)} onClick={linkEvent(this, this.handleCancel)}
> >
{ i18n.t('cancel') } {i18n.t('cancel')}
</button> </button>
)} )}
</div> </div>

View file

@ -1,7 +1,6 @@
import { Component, linkEvent } from 'inferno'; import { Component, linkEvent } from 'inferno';
import { SortType } from '../interfaces'; import { SortType } from '../interfaces';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
interface SortSelectProps { interface SortSelectProps {
sort: SortType; sort: SortType;
@ -30,33 +29,17 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
onChange={linkEvent(this, this.handleSortChange)} onChange={linkEvent(this, this.handleSortChange)}
class="custom-select custom-select-sm w-auto" class="custom-select custom-select-sm w-auto"
> >
<option disabled> <option disabled>{i18n.t('sort_type')}</option>
{ i18n.t('sort_type') }
</option>
{!this.props.hideHot && ( {!this.props.hideHot && (
<option value={SortType.Hot}> <option value={SortType.Hot}>{i18n.t('hot')}</option>
{ i18n.t('hot') }
</option>
)} )}
<option value={SortType.New}> <option value={SortType.New}>{i18n.t('new')}</option>
{ i18n.t('new') }
</option>
<option disabled></option> <option disabled></option>
<option value={SortType.TopDay}> <option value={SortType.TopDay}>{i18n.t('top_day')}</option>
{ i18n.t('top_day') } <option value={SortType.TopWeek}>{i18n.t('week')}</option>
</option> <option value={SortType.TopMonth}>{i18n.t('month')}</option>
<option value={SortType.TopWeek}> <option value={SortType.TopYear}>{i18n.t('year')}</option>
{ i18n.t('week') } <option value={SortType.TopAll}>{i18n.t('all')}</option>
</option>
<option value={SortType.TopMonth}>
{ i18n.t('month') }
</option>
<option value={SortType.TopYear}>
{ i18n.t('year') }
</option>
<option value={SortType.TopAll}>
{ i18n.t('all') }
</option>
</select> </select>
); );
} }

View file

@ -18,7 +18,7 @@ import {
BanUserResponse, BanUserResponse,
AddAdminResponse, AddAdminResponse,
DeleteAccountForm, DeleteAccountForm,
CreatePostLikeResponse, PostResponse,
WebSocketJsonResponse, WebSocketJsonResponse,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
@ -39,7 +39,6 @@ import { ListingTypeSelect } from './listing-type-select';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import { MomentTime } from './moment-time'; import { MomentTime } from './moment-time';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
enum View { enum View {
Overview, Overview,
@ -199,11 +198,11 @@ export class User extends Component<any, UserState> {
return ( return (
<div class="container"> <div class="container">
{this.state.loading ? ( {this.state.loading ? (
<p class="text-center"> <h5>
<svg class="icon icon-spinner spin"> <svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use> <use xlinkHref="#icon-spinner"></use>
</svg> </svg>
</p> </h5>
) : ( ) : (
<div class="row"> <div class="row">
<div class="col-12 col-md-8"> <div class="col-12 col-md-8">
@ -245,21 +244,11 @@ export class User extends Component<any, UserState> {
onChange={linkEvent(this, this.handleViewChange)} onChange={linkEvent(this, this.handleViewChange)}
class="custom-select custom-select-sm w-auto" class="custom-select custom-select-sm w-auto"
> >
<option disabled> <option disabled>{i18n.t('view')}</option>
{ i18n.t('view') } <option value={View.Overview}>{i18n.t('overview')}</option>
</option> <option value={View.Comments}>{i18n.t('comments')}</option>
<option value={View.Overview}> <option value={View.Posts}>{i18n.t('posts')}</option>
{ i18n.t('overview') } <option value={View.Saved}>{i18n.t('saved')}</option>
</option>
<option value={View.Comments}>
{ i18n.t('comments') }
</option>
<option value={View.Posts}>
{ i18n.t('posts') }
</option>
<option value={View.Saved}>
{ i18n.t('saved') }
</option>
</select> </select>
<span class="ml-2"> <span class="ml-2">
<SortSelect <SortSelect
@ -359,7 +348,7 @@ export class User extends Component<any, UserState> {
<li className="list-inline-item">{user.name}</li> <li className="list-inline-item">{user.name}</li>
{user.banned && ( {user.banned && (
<li className="list-inline-item badge badge-danger"> <li className="list-inline-item badge badge-danger">
{ i18n.t('banned') } {i18n.t('banned')}
</li> </li>
)} )}
</ul> </ul>
@ -371,38 +360,20 @@ export class User extends Component<any, UserState> {
<table class="table table-bordered table-sm mt-2 mb-0"> <table class="table table-bordered table-sm mt-2 mb-0">
<tr> <tr>
<td> <td>
<T {i18n.t('number_of_points', { count: user.post_score })}
i18nKey="number_of_points"
interpolation={{ count: user.post_score }}
>
#
</T>
</td> </td>
<td> <td>
<T {i18n.t('number_of_posts', { count: user.number_of_posts })}
i18nKey="number_of_posts"
interpolation={{ count: user.number_of_posts }}
>
#
</T>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
<T {i18n.t('number_of_points', { count: user.comment_score })}
i18nKey="number_of_points"
interpolation={{ count: user.comment_score }}
>
#
</T>
</td> </td>
<td> <td>
<T {i18n.t('number_of_comments', {
i18nKey="number_of_comments" count: user.number_of_comments,
interpolation={{ count: user.number_of_comments }} })}
>
#
</T>
</td> </td>
</tr> </tr>
</table> </table>
@ -412,7 +383,7 @@ export class User extends Component<any, UserState> {
class="btn btn-block btn-secondary mt-3" class="btn btn-block btn-secondary mt-3"
onClick={linkEvent(this, this.handleLogoutClick)} onClick={linkEvent(this, this.handleLogoutClick)}
> >
{ i18n.t('logout') } {i18n.t('logout')}
</button> </button>
) : ( ) : (
<> <>
@ -443,14 +414,10 @@ export class User extends Component<any, UserState> {
<div> <div>
<div class="card border-secondary mb-3"> <div class="card border-secondary mb-3">
<div class="card-body"> <div class="card-body">
<h5> <h5>{i18n.t('settings')}</h5>
{ i18n.t('settings') }
</h5>
<form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}> <form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
<div class="form-group"> <div class="form-group">
<label> <label>{i18n.t('avatar')}</label>
{ i18n.t('avatar') }
</label>
<form class="d-inline"> <form class="d-inline">
<label <label
htmlFor="file-upload" htmlFor="file-upload"
@ -458,7 +425,7 @@ export class User extends Component<any, UserState> {
> >
{!this.state.userSettingsForm.avatar ? ( {!this.state.userSettingsForm.avatar ? (
<span class="btn btn-sm btn-secondary"> <span class="btn btn-sm btn-secondary">
{ i18n.t('upload_avatar') } {i18n.t('upload_avatar')}
</span> </span>
) : ( ) : (
<img <img
@ -481,20 +448,14 @@ export class User extends Component<any, UserState> {
</form> </form>
</div> </div>
<div class="form-group"> <div class="form-group">
<label> <label>{i18n.t('language')}</label>
{ i18n.t('language') }
</label>
<select <select
value={this.state.userSettingsForm.lang} value={this.state.userSettingsForm.lang}
onChange={linkEvent(this, this.handleUserSettingsLangChange)} onChange={linkEvent(this, this.handleUserSettingsLangChange)}
class="ml-2 custom-select custom-select-sm w-auto" class="ml-2 custom-select custom-select-sm w-auto"
> >
<option disabled> <option disabled>{i18n.t('language')}</option>
{ i18n.t('language') } <option value="browser">{i18n.t('browser_default')}</option>
</option>
<option value="browser">
{ i18n.t('browser_default') }
</option>
<option disabled></option> <option disabled></option>
{languages.map(lang => ( {languages.map(lang => (
<option value={lang.code}>{lang.name}</option> <option value={lang.code}>{lang.name}</option>
@ -502,17 +463,13 @@ export class User extends Component<any, UserState> {
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label> <label>{i18n.t('theme')}</label>
{ i18n.t('theme') }
</label>
<select <select
value={this.state.userSettingsForm.theme} value={this.state.userSettingsForm.theme}
onChange={linkEvent(this, this.handleUserSettingsThemeChange)} onChange={linkEvent(this, this.handleUserSettingsThemeChange)}
class="ml-2 custom-select custom-select-sm w-auto" class="ml-2 custom-select custom-select-sm w-auto"
> >
<option disabled> <option disabled>{i18n.t('theme')}</option>
{ i18n.t('theme') }
</option>
{themes.map(theme => ( {themes.map(theme => (
<option value={theme}>{theme}</option> <option value={theme}>{theme}</option>
))} ))}
@ -520,9 +477,7 @@ export class User extends Component<any, UserState> {
</div> </div>
<form className="form-group"> <form className="form-group">
<label> <label>
<T i18nKey="sort_type" class="mr-2"> <div class="mr-2">{i18n.t('sort_type')}</div>
#
</T>
</label> </label>
<ListingTypeSelect <ListingTypeSelect
type_={this.state.userSettingsForm.default_listing_type} type_={this.state.userSettingsForm.default_listing_type}
@ -531,9 +486,7 @@ export class User extends Component<any, UserState> {
</form> </form>
<form className="form-group"> <form className="form-group">
<label> <label>
<T i18nKey="type" class="mr-2"> <div class="mr-2">{i18n.t('type')}</div>
#
</T>
</label> </label>
<SortSelect <SortSelect
sort={this.state.userSettingsForm.default_sort_type} sort={this.state.userSettingsForm.default_sort_type}
@ -541,8 +494,8 @@ export class User extends Component<any, UserState> {
/> />
</form> </form>
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-3 col-form-label" for="user-email"> <label class="col-lg-3 col-form-label" htmlFor="user-email">
{ i18n.t('email') } {i18n.t('email')}
</label> </label>
<div class="col-lg-9"> <div class="col-lg-9">
<input <input
@ -580,8 +533,8 @@ export class User extends Component<any, UserState> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-5 col-form-label" for="user-password"> <label class="col-lg-5 col-form-label" htmlFor="user-password">
{ i18n.t('new_password') } {i18n.t('new_password')}
</label> </label>
<div class="col-lg-7"> <div class="col-lg-7">
<input <input
@ -597,8 +550,11 @@ export class User extends Component<any, UserState> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-5 col-form-label" for="user-verify-password"> <label
{ i18n.t('verify_password') } class="col-lg-5 col-form-label"
htmlFor="user-verify-password"
>
{i18n.t('verify_password')}
</label> </label>
<div class="col-lg-7"> <div class="col-lg-7">
<input <input
@ -614,8 +570,11 @@ export class User extends Component<any, UserState> {
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-5 col-form-label" for="user-old-password"> <label
{ i18n.t('old_password') } class="col-lg-5 col-form-label"
htmlFor="user-old-password"
>
{i18n.t('old_password')}
</label> </label>
<div class="col-lg-7"> <div class="col-lg-7">
<input <input
@ -643,8 +602,8 @@ export class User extends Component<any, UserState> {
this.handleUserSettingsShowNsfwChange this.handleUserSettingsShowNsfwChange
)} )}
/> />
<label class="form-check-label" for="user-show-nsfw"> <label class="form-check-label" htmlFor="user-show-nsfw">
{ i18n.t('show_nsfw') } {i18n.t('show_nsfw')}
</label> </label>
</div> </div>
</div> </div>
@ -661,8 +620,8 @@ export class User extends Component<any, UserState> {
this.handleUserSettingsShowAvatarsChange this.handleUserSettingsShowAvatarsChange
)} )}
/> />
<label class="form-check-label" for="user-show-avatars"> <label class="form-check-label" htmlFor="user-show-avatars">
{ i18n.t('show_avatars') } {i18n.t('show_avatars')}
</label> </label>
</div> </div>
</div> </div>
@ -681,8 +640,11 @@ export class User extends Component<any, UserState> {
this.handleUserSettingsSendNotificationsToEmailChange this.handleUserSettingsSendNotificationsToEmailChange
)} )}
/> />
<label class="form-check-label" for="user-send-notifications-to-email"> <label
{ i18n.t('send_notifications_to_email') } class="form-check-label"
htmlFor="user-send-notifications-to-email"
>
{i18n.t('send_notifications_to_email')}
</label> </label>
</div> </div>
</div> </div>
@ -706,12 +668,12 @@ export class User extends Component<any, UserState> {
this.handleDeleteAccountShowConfirmToggle this.handleDeleteAccountShowConfirmToggle
)} )}
> >
{ i18n.t('delete_account') } {i18n.t('delete_account')}
</button> </button>
{this.state.deleteAccountShowConfirm && ( {this.state.deleteAccountShowConfirm && (
<> <>
<div class="my-2 alert alert-danger" role="alert"> <div class="my-2 alert alert-danger" role="alert">
{ i18n.t('delete_account_confirm') } {i18n.t('delete_account_confirm')}
</div> </div>
<input <input
type="password" type="password"
@ -742,7 +704,7 @@ export class User extends Component<any, UserState> {
this.handleDeleteAccountShowConfirmToggle this.handleDeleteAccountShowConfirmToggle
)} )}
> >
{ i18n.t('cancel') } {i18n.t('cancel')}
</button> </button>
</> </>
)} )}
@ -760,9 +722,7 @@ export class User extends Component<any, UserState> {
{this.state.moderates.length > 0 && ( {this.state.moderates.length > 0 && (
<div class="card border-secondary mb-3"> <div class="card border-secondary mb-3">
<div class="card-body"> <div class="card-body">
<h5> <h5>{i18n.t('moderates')}</h5>
{ i18n.t('moderates') }
</h5>
<ul class="list-unstyled mb-0"> <ul class="list-unstyled mb-0">
{this.state.moderates.map(community => ( {this.state.moderates.map(community => (
<li> <li>
@ -785,9 +745,7 @@ export class User extends Component<any, UserState> {
{this.state.follows.length > 0 && ( {this.state.follows.length > 0 && (
<div class="card border-secondary mb-3"> <div class="card border-secondary mb-3">
<div class="card-body"> <div class="card-body">
<h5> <h5>{i18n.t('subscribed')}</h5>
{ i18n.t('subscribed') }
</h5>
<ul class="list-unstyled mb-0"> <ul class="list-unstyled mb-0">
{this.state.follows.map(community => ( {this.state.follows.map(community => (
<li> <li>
@ -812,14 +770,14 @@ export class User extends Component<any, UserState> {
class="btn btn-sm btn-secondary mr-1" class="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)} onClick={linkEvent(this, this.prevPage)}
> >
<T i18nKey="prev">#</T> {i18n.t('prev')}
</button> </button>
)} )}
<button <button
class="btn btn-sm btn-secondary" class="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)} onClick={linkEvent(this, this.nextPage)}
> >
{ i18n.t('next') } {i18n.t('next')}
</button> </button>
</div> </div>
); );
@ -1097,7 +1055,7 @@ export class User extends Component<any, UserState> {
if (data.comment.my_vote !== null) found.my_vote = data.comment.my_vote; if (data.comment.my_vote !== null) found.my_vote = data.comment.my_vote;
this.setState(this.state); this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
let data = res.data as CreatePostLikeResponse; let data = res.data as PostResponse;
let found = this.state.posts.find(c => c.id == data.post.id); let found = this.state.posts.find(c => c.id == data.post.id);
found.my_vote = data.post.my_vote; found.my_vote = data.post.my_vote;
found.score = data.post.score; found.score = data.post.score;