Skip to content

Commit a859e54

Browse files
authored
Merge pull request #612 from steemit/merge-master-develop
release 0.1.161109
2 parents e73d4e4 + d349ee7 commit a859e54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1566
-725
lines changed

app/ResolveRoute.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function resolveRoute(path)
5757
}
5858
match = path.match(/^\/(@[\w\.\d-]+)\/?$/) ||
5959
// @user/"posts" is deprecated in favor of "comments" as of oct-2016 (#443)
60-
path.match(/^\/(@[\w\.\d-]+)\/(blog|posts|comments|recommended|transfers|curation-rewards|author-rewards|permissions|created|recent-replies|feed|password|followed|followers)\/?$/);
60+
path.match(/^\/(@[\w\.\d-]+)\/(blog|posts|comments|recommended|transfers|curation-rewards|author-rewards|permissions|created|recent-replies|feed|password|followed|followers|settings)\/?$/);
6161
if (match) {
6262
return {page: 'UserProfile', params: match.slice(1)};
6363
}

app/Translator.js

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ import React from 'react';
22
import isString from 'lodash/isString';
33
import isObject from 'lodash/isObject';
44
import isUndefined from 'lodash/isUndefined';
5+
import { connect } from 'react-redux'
56
import { IntlProvider, addLocaleData, injectIntl } from 'react-intl';
7+
import store from 'store';
8+
import { DEFAULT_LANGUAGE } from 'config/client_config';
69

710
// most of this code creates a wrapper for i18n API.
811
// this is needed to make i18n future proof
912

1013
/*
11-
module exports two functions: translate and translateHtml
12-
usage example:
13-
translate('reply_to_user', {username: 'undeadlol1') == 'Reply to undeadlol1'
14-
translateHtml works the same, expcept it renders string with html tags in it
14+
module exports two functions: translate and translateHtml
15+
usage example:
16+
translate('reply_to_user', {username: 'undeadlol1') == 'Reply to undeadlol1'
17+
translateHtml works the same, expcept it renders string with html tags in it
1518
*/
1619

1720
// locale data is needed for various messages, ie 'N minutes ago'
@@ -28,7 +31,7 @@ import { ru } from './locales/ru';
2831
import { fr } from './locales/fr';
2932
import { es } from './locales/es';
3033
import { it } from './locales/it';
31-
const translations = {
34+
const messages = {
3235
en: en,
3336
ru: ru,
3437
fr: fr,
@@ -38,9 +41,18 @@ const translations = {
3841

3942
// exported function placeholders
4043
// this is needed for proper export before react-intl functions with locale data,
41-
// will be properly created (they depend on react props and context,
42-
// which is not available until component is being created)
43-
let translate = () => {};
44+
// will be properly created (they depend on react props and context),
45+
// which is not available until component is being created
46+
//
47+
/*
48+
this placeholder is needed for usage outside of react. In server side code and in static html files.
49+
This function is very simple, it does NOT support dynamic values (for example: translate('your_email_is', {email: 'x@y.com'})). Use it carefully
50+
*/
51+
let translate = string => {
52+
let language = DEFAULT_LANGUAGE
53+
if (process.env.BROWSER) language = store.get('language') || DEFAULT_LANGUAGE
54+
return messages[language][string]
55+
};
4456
let translateHtml = () => {};
4557
let translatePlural = () => {};
4658

@@ -105,24 +117,30 @@ class Translator extends React.Component {
105117
// Define user's language. Different browsers have the user locale defined
106118
// on different fields on the `navigator` object, so we make sure to account
107119
// for these different by checking all of them
108-
let language = 'en';
109-
// while Server Side Rendering is in process, 'navigator' is undefined
120+
let language = this.props.locale; // usually 'en'
110121
if (process.env.BROWSER) {
111-
language = navigator ? (navigator.languages && navigator.languages[0])
112-
|| navigator.language
113-
|| navigator.userLanguage
114-
: 'en';
122+
const storredLanguage = store.get('language')
123+
if (storredLanguage) language = storredLanguage
115124
}
116-
117-
//Split locales with a region code (ie. 'en-EN' to 'en')
118-
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
119-
120-
// TODO: don't forget to add Safari polyfill
121-
122-
// to ensure dynamic language change, "key" property with same "locale" info must be added
123-
// see: https://github.com/yahoo/react-intl/wiki/Components#multiple-intl-contexts
124-
let messages = translations[languageWithoutRegionCode]
125-
return <IntlProvider locale={languageWithoutRegionCode} key={languageWithoutRegionCode} messages={messages}>
125+
// let language = DEFAULT_LANGUAGE; // usually 'en'
126+
// while Server Side Rendering is in process, 'navigator' is undefined
127+
// currently commented out, because in golos we need only russian
128+
// if (process.env.BROWSER) language = navigator
129+
// ? (navigator.languages && navigator.languages[0])
130+
// || navigator.language
131+
// || navigator.userLanguage
132+
// : DEFAULT_LANGUAGE;
133+
//Split locales with a region code (ie. 'en-EN' to 'en')
134+
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
135+
136+
return <IntlProvider
137+
// to ensure dynamic language change, "key" property with same "locale" info must be added
138+
// see: https://github.com/yahoo/react-intl/wiki/Components#multiple-intl-contexts
139+
key={languageWithoutRegionCode}
140+
defaultLocale={DEFAULT_LANGUAGE}
141+
locale={languageWithoutRegionCode}
142+
messages={messages[languageWithoutRegionCode]}
143+
>
126144
<div>
127145
<DummyComponentToExportProps />
128146
{this.props.children}
@@ -133,4 +151,13 @@ class Translator extends React.Component {
133151

134152
export { translate, translateHtml, translatePlural }
135153

136-
export default Translator
154+
export default connect(
155+
// mapStateToProps
156+
(state, ownProps) => {
157+
const locale = state.user.get('locale')
158+
return {
159+
...ownProps,
160+
locale
161+
}
162+
}
163+
)(Translator)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<browserconfig>
3+
<msapplication>
4+
<tile>
5+
<square150x150logo src="/images/favicons/mstile-150x150.png"/>
6+
<TileColor>#ffffff</TileColor>
7+
</tile>
8+
</msapplication>
9+
</browserconfig>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "Golos",
3+
"icons": [
4+
{
5+
"src": "\/images\/favicons\/android-chrome-192x192.png",
6+
"sizes": "192x192",
7+
"type": "image\/png"
8+
},
9+
{
10+
"src": "\/images\/favicons\/android-chrome-512x512.png",
11+
"sizes": "512x512",
12+
"type": "image\/png"
13+
}
14+
],
15+
"theme_color": "#ffffff",
16+
"display": "standalone"
17+
}

app/components/App.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class App extends React.Component {
167167
</li>
168168
<li>
169169
<a href="https://steem.io/SteemWhitePaper.pdf" onClick={this.navigate}>
170-
{translate("whitepaper")}
170+
{translate("APP_NAME_whitepaper")}
171171
</a>
172172
</li>
173173
<li>
@@ -177,12 +177,12 @@ class App extends React.Component {
177177
</li>
178178
<li>
179179
<a onClick={() => depositSteem()}>
180-
{translate("buy_steem")}
180+
{translate("buy_LIQUID_TOKEN")}
181181
</a>
182182
</li>
183183
<li>
184184
<a href="http://steemtools.com/" onClick={this.navigate}>
185-
{translate('steem_app_center')}
185+
{translate('APP_NAME_app_center')}
186186
</a>
187187
</li>
188188
<li>
@@ -202,7 +202,7 @@ class App extends React.Component {
202202
</li>
203203
<li>
204204
<a href="https://steemit.chat/home" target="_blank" rel="noopener noreferrer">
205-
{translate("steemit_chat")}&nbsp;<Icon name="extlink" />
205+
{translate("APP_NAME_chat")}&nbsp;<Icon name="extlink" />
206206
</a>
207207
</li>
208208
<li>

app/components/cards/CardView.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {connect} from 'react-redux'
33
import Link from 'app/components/elements/Link'
44
import g from 'app/redux/GlobalReducer'
55
import links from 'app/utils/Links'
6+
import { translate } from 'app/Translator';
67

78
/** @deprecated */
89
class CardView extends React.Component {
@@ -43,13 +44,13 @@ class CardView extends React.Component {
4344
const youTubeImage = links.youTube.test(link)
4445
return <span className="Card">
4546
{image && !youTubeImage && <div>
46-
{canEdit && <div>(<a onClick={this.onCloseImage}>remove</a>)<br /></div>}
47+
{canEdit && <div>(<a onClick={this.onCloseImage}>{translate('remove')}</a>)<br /></div>}
4748
<Link href={link}>
4849
<img src={image} alt={alt} />
4950
</Link>
5051
</div>}
5152
{description && <div>
52-
{canEdit && <span>(<a onClick={this.onCloseDescription}>remove</a>)</span>}
53+
{canEdit && <span>(<a onClick={this.onCloseDescription}>{translate('remove')}</a>)</span>}
5354
<Link href={link}>
5455
<blockquote>{description}</blockquote>
5556
</Link>

app/components/cards/CategorySelector.jsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import {connect} from 'react-redux'
33
import shouldComponentUpdate from 'app/utils/shouldComponentUpdate'
44
import {cleanReduxInput} from 'app/utils/ReduxForms'
5+
import { translate } from '../../Translator.js';
56

67
class CategorySelector extends React.Component {
78
static propTypes = {
@@ -21,7 +22,6 @@ class CategorySelector extends React.Component {
2122
}
2223
static defaultProps = {
2324
autoComplete: 'on',
24-
placeholder: 'Tag (up to 5 tags), the first tag is your main category.',
2525
id: 'CategorySelectorId',
2626
isEdit: false,
2727
}
@@ -60,7 +60,7 @@ class CategorySelector extends React.Component {
6060

6161
const categorySelect = (
6262
<select {...cleanReduxInput(this.props)} onChange={this.categorySelectOnChange} ref="categoryRef" tabIndex={tabIndex} disabled={disabled}>
63-
<option value="">Select a tag...</option>
63+
<option value="">{translate('select_a_tag')}...</option>
6464
{categoryOptions}
6565
<option value="new">{this.props.placeholder}</option>
6666
</select>
@@ -73,25 +73,25 @@ class CategorySelector extends React.Component {
7373
}
7474
}
7575
export function validateCategory(category, required = true) {
76-
if(!category || category.trim() === '') return required ? 'Required' : null
76+
if(!category || category.trim() === '') return required ? translate( 'required' ) : null
7777
const cats = category.trim().split(' ')
7878
return (
7979
// !category || category.trim() === '' ? 'Required' :
80-
cats.length > 5 ? 'Please use only five categories' :
81-
cats.find(c => c.length > 24) ? 'Maximum tag length is 24 characters' :
82-
cats.find(c => c.split('-').length > 2) ? 'Use only one dash' :
83-
cats.find(c => c.indexOf(',') >= 0) ? 'Use spaces to separate tags' :
84-
cats.find(c => /[A-Z]/.test(c)) ? 'Use only lowercase letters' :
85-
cats.find(c => !/^[a-z0-9-#]+$/.test(c)) ? 'Use only lowercase letters, digits and one dash' :
86-
cats.find(c => !/^[a-z-#]/.test(c)) ? 'Must start with a letter' :
87-
cats.find(c => !/[a-z0-9]$/.test(c)) ? 'Must end with a letter or number' :
80+
cats.length > 5 ? translate('use_limitied_amount_of_categories', {amount: 5}) :
81+
cats.find(c => c.length > 24) ? translate('maximum_tag_length_is_24_characters') :
82+
cats.find(c => c.split('-').length > 2) ? translate('use_one_dash') :
83+
cats.find(c => c.indexOf(',') >= 0) ? translate('use_spaces_to_separate_tags') :
84+
cats.find(c => /[A-Z]/.test(c)) ? translate('use_only_lowercase_letters') :
85+
cats.find(c => !/^[a-z0-9-#]+$/.test(c)) ? translate('use_only_allowed_characters') :
86+
cats.find(c => !/^[a-z-#]/.test(c)) ? translate('must_start_with_a_letter') :
87+
cats.find(c => !/[a-z0-9]$/.test(c)) ? translate('must_end_with_a_letter_or_number') :
8888
null
8989
)
9090
}
9191
export default connect((state, ownProps) => {
9292
const trending = state.global.get('category_idx').get('trending')
93-
return {
94-
trending,
95-
...ownProps,
96-
}
93+
// apply translations
94+
// they are used here because default prop can't acces intl property
95+
const placeholder = translate('tag_your_story');
96+
return { trending, placeholder, ...ownProps, }
9797
})(CategorySelector);

app/components/cards/Comment.jsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import Icon from 'app/components/elements/Icon';
1313
import Userpic from 'app/components/elements/Userpic';
1414
import transaction from 'app/redux/Transaction'
1515
import {List} from 'immutable'
16-
import pluralize from 'pluralize';
16+
import { translate } from 'app/Translator';
1717

18-
export function sortComments( g, comments, sort_order ){
18+
export function sortComments( g, comments, sort_order ) {
1919

2020
function netNegative(a) {
2121
return a.get("net_rshares") < 0;
@@ -85,7 +85,7 @@ class CommentImpl extends React.Component {
8585
// html props
8686
global: React.PropTypes.object.isRequired,
8787
content: React.PropTypes.string.isRequired,
88-
sort_order: React.PropTypes.oneOf(['active', 'update', 'created', 'trending']).isRequired,
88+
sort_order: React.PropTypes.oneOf(['active', 'updated', 'created', 'trending']).isRequired,
8989
root: React.PropTypes.bool,
9090
showNegativeComments: React.PropTypes.bool,
9191
onHide: React.PropTypes.func,
@@ -166,7 +166,7 @@ class CommentImpl extends React.Component {
166166

167167
/**
168168
* - `hide` is based on author reputation, and will hide the entire post on initial render.
169-
* - `hide_body` is true when comment rshares OR author rep is negative.
169+
* - `hide_body` is true when comment rshares OR author rep is negative.
170170
* it hides the comment body (but not the header) until the "reveal comment" link is clicked.
171171
*/
172172
_checkHide(props) {
@@ -216,7 +216,7 @@ class CommentImpl extends React.Component {
216216
let g = this.props.global;
217217
const dis = g.get('content').get(this.props.content);
218218
if (!dis) {
219-
return <div>Loading...</div>
219+
return <div>{translate('loading')}...</div>
220220
}
221221
const comment = dis.toJS();
222222
if(!comment.stats) {
@@ -260,9 +260,9 @@ class CommentImpl extends React.Component {
260260
<Voting post={post} />
261261
{!readonly &&
262262
<span className="Comment__footer__controls">
263-
{depth < 6 && <a onClick={onShowReply}>Reply</a>}
264-
{' '}{showEditOption && <a onClick={onShowEdit}>Edit</a>}
265-
{' '}{showDeleteOption && <a onClick={onDeletePost}>Delete</a>}
263+
{depth < 6 && <a onClick={onShowReply}>{translate('reply')}</a>}
264+
{' '}{showEditOption && <a onClick={onShowEdit}>{translate('edit')}</a>}
265+
{' '}{showDeleteOption && <a onClick={onDeletePost}>{translate('delete')}</a>}
266266
</span>}
267267
</div>;
268268
}
@@ -311,10 +311,12 @@ class CommentImpl extends React.Component {
311311
<div className="Comment__header">
312312
<div className="Comment__header_collapse">
313313
<Voting post={post} flag />
314-
<a title="Collapse/Expand" onClick={this.toggleCollapsed}>{ this.state.collapsed ? '[+]' : '[-]' }</a>
314+
<a title={translate('collapse_or_expand')} onClick={this.toggleCollapsed}>{ this.state.collapsed ? '[+]' : '[-]' }</a>
315315
</div>
316316
<span className="Comment__header-user">
317-
<Icon name="user" className="Comment__Userpic-small" />
317+
<div className="Comment__Userpic-small">
318+
<Userpic account={comment.author} />
319+
</div>
318320
<Author author={comment.author} authorRepLog10={authorRepLog10} />
319321
</span>
320322
&nbsp; &middot; &nbsp;
@@ -324,9 +326,9 @@ class CommentImpl extends React.Component {
324326
{ (this.state.collapsed || hide_body) &&
325327
<Voting post={post} showList={false} /> }
326328
{ this.state.collapsed && comment.children > 0 &&
327-
<span className="marginLeft1rem">{pluralize('replies', comment.children, true)}</span>}
329+
<span className="marginLeft1rem">{translate('reply_count', {replyCount: comment.children})}</span>}
328330
{ !this.state.collapsed && hide_body &&
329-
<a className="marginLeft1rem" onClick={this.revealBody}>reveal comment</a>}
331+
<a className="marginLeft1rem" onClick={this.revealBody}>{translate('reveal_comment')}</a>}
330332
</div>
331333
<div className="Comment__body entry-content">
332334
{showEdit ? renderedEditor : body}
@@ -378,7 +380,7 @@ const Comment = connect(
378380
dispatch(transaction.actions.broadcastOperation({
379381
type: 'delete_comment',
380382
operation: {author, permlink},
381-
confirm: 'Are you sure?'
383+
confirm: translate('are_you_sure'),
382384
}))
383385
},
384386
})

app/components/cards/Comment.scss

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@
77
}
88

99
.Comment__Userpic {
10+
float: left;
1011
position: relative;
1112
top: 0.4rem;
13+
padding-right: 0.6rem;
1214
}
1315

1416
.Comment__Userpic-small {
15-
position: relative;
16-
left: -2px;
1717
@include hide-for(medium);
18-
path {
19-
fill: $dark_gray;
18+
.Userpic {
19+
float: left;
20+
position: relative;
21+
padding-right: 0.2rem;
22+
img {
23+
width: 16px;
24+
height: 16px;
25+
}
2026
}
2127
}
2228

app/components/cards/PostFull.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ export default class PostFull extends React.Component {
232232
}
233233

234234
const readonly = post_content.get('mode') === 'archived' || $STM_Config.read_only_mode
235-
const showPromote = username && post_content.get('mode') === "first_payout" && post_content.get('depth') == 0
235+
//const showPromote = username && post_content.get('mode') === "first_payout" && post_content.get('depth') == 0
236+
const showPromote = false // TODO: revert when nodes are updated with https://github.com/steemit/steem/pull/550
236237
const showReplyOption = post_content.get('depth') < 6
237238
const showEditOption = username === author
238239
const authorRepLog10 = repLog10(content.author_reputation)

0 commit comments

Comments
 (0)