Merge pull request #160 from intnick/i18n

i18n Support
This commit is contained in:
Jeremy Kauffman 2017-06-05 11:34:22 -04:00 committed by GitHub
commit 8d359629fb
48 changed files with 420 additions and 377 deletions

View file

@ -48,3 +48,7 @@ to create distributable packages, which is run by calling:
This project has currently only been worked on in Linux and macOS. If you are on Windows, you can
checkout out the build steps in [appveyor.yml](https://github.com/lbryio/lbry-app/blob/master/.appveyor.yml) and probably figure out something from there.
## Internationalization
If you want to help translating the lbry-app, you can copy the en.json file in /app/locales and modify the values while leaving the keys as their original English strings. An example for this would be: `"Skip": "Überspringen",` Translations should automatically show up in options.

View file

@ -1,12 +1,16 @@
import store from 'store.js';
import lbry from './lbry.js';
const env = ENV;
const config = require(`./config/${env}`);
const language = lbry.getClientSetting('language') ? lbry.getClientSetting('language') : 'en';
const i18n = require('y18n')({directory: 'app/locales', updateFiles: false, locale: language});
const logs = [];
const app = {
env: env,
config: config,
store: store,
i18n: i18n,
logs: logs,
log: function(message) {
console.log(message);
@ -14,5 +18,8 @@ const app = {
}
}
window.__ = i18n.__;
window.__n = i18n.__n;
global.app = app;
module.exports = app;
module.exports = app;

View file

@ -41,7 +41,7 @@ class SubmitEmailStage extends React.Component {
lbryio.call('user_email', 'new', {email: this.state.email}, 'post').then(() => {
this.onEmailSaved(this.state.email);
}, (error) => {
if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) {
if (error.xhr && (error.xhr.status == 409 || error.message == __("This email is already in use"))) {
this.onEmailSaved(this.state.email);
return;
} else if (this._emailRow) {
@ -55,11 +55,11 @@ class SubmitEmailStage extends React.Component {
return (
<section>
<form onSubmit={(event) => { this.handleSubmit(event) }}>
<FormRow ref={(ref) => { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io"
<FormRow ref={(ref) => { this._emailRow = ref }} type="text" label={__("Email")} placeholder="scrwvwls@lbry.io"
name="email" value={this.state.email}
onChange={(event) => { this.handleEmailChanged(event) }} />
<div className="form-row-submit">
<Link button="primary" label="Next" disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event) }} />
<Link button="primary" label={__("Next")} disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event) }} />
</div>
</form>
</section>
@ -102,7 +102,7 @@ class ConfirmEmailStage extends React.Component {
if (userEmail.is_verified) {
this.props.setStage("welcome")
} else {
onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen?
onSubmitError(new Error(__("Your email is still not verified."))) //shouldn't happen?
}
}, onSubmitError);
}
@ -111,14 +111,14 @@ class ConfirmEmailStage extends React.Component {
return (
<section>
<form onSubmit={(event) => { this.handleSubmit(event) }}>
<FormRow label="Verification Code" ref={(ref) => { this._codeRow = ref }} type="text"
<FormRow label={__("Verification Code")} ref={(ref) => { this._codeRow = ref }} type="text"
name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }}
helper="A verification code is required to access this version."/>
helper={__("A verification code is required to access this version.")}/>
<div className="form-row-submit form-row-submit--with-footer">
<Link button="primary" label="Verify" disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event)}} />
<Link button="primary" label={__("Verify")} disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event)}} />
</div>
<div className="form-field__helper">
No code? <Link onClick={() => { this.props.setStage("nocode")}} label="Click here" />.
{__("No code?")} <Link onClick={() => { this.props.setStage("nocode")}} label={__("Click here")} />.
</div>
</form>
</section>
@ -150,26 +150,26 @@ class WelcomeStage extends React.Component {
render() {
return (
!this.state.hasReward ?
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY" {...this.props}>
<Modal type="custom" isOpen={true} contentLabel={__("Welcome to LBRY")} {...this.props}>
<section>
<h3 className="modal__header">Welcome to LBRY.</h3>
<p>Using LBRY is like dating a centaur. Totally normal up top, and <em>way different</em> underneath.</p>
<p>Up top, LBRY is similar to popular media sites.</p>
<p>Below, LBRY is controlled by users -- you -- via blockchain and decentralization.</p>
<p>Thank you for making content freedom possible! Here's a nickel, kid.</p>
<h3 className="modal__header">{__("Welcome to LBRY.")}</h3>
<p>{__("Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.")}</p>
<p>{__("Up top, LBRY is similar to popular media sites.")}</p>
<p>{__("Below, LBRY is controlled by users -- you -- via blockchain and decentralization.")}</p>
<p>{__("Thank you for making content freedom possible! Here's a nickel, kid.")}</p>
<div style={{textAlign: "center", marginBottom: "12px"}}>
<RewardLink type="new_user" button="primary" onRewardClaim={(event) => { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} />
</div>
</section>
</Modal> :
<Modal type="alert" overlayClassName="modal-overlay modal-overlay--clear" isOpen={true} contentLabel="Welcome to LBRY" {...this.props} onConfirmed={() => { this.props.setStage(null) }}>
<Modal type="alert" overlayClassName="modal-overlay modal-overlay--clear" isOpen={true} contentLabel={__("Welcome to LBRY")} {...this.props} onConfirmed={() => { this.props.setStage(null) }}>
<section>
<h3 className="modal__header">About Your Reward</h3>
<p>You earned a reward of <CreditAmount amount={this.state.rewardAmount} label={false} /> LBRY credits, or <em>LBC</em>.</p>
<p>This reward will show in your Wallet momentarily, probably while you are reading this message.</p>
<p>LBC is used to compensate creators, to publish, and to have say in how the network works.</p>
<p>No need to understand it all just yet! Try watching or downloading something next.</p>
<p>Finally, know that LBRY is an early beta and that it earns the name.</p>
<h3 className="modal__header">{__("About Your Reward")}</h3>
<p>{__("You earned a reward of ")} <CreditAmount amount={this.state.rewardAmount} label={false} /> {__("LBRY credits, or \"LBC\".")}</p>
<p>{__("This reward will show in your Wallet momentarily, probably while you are reading this message.")}</p>
<p>{__("LBC is used to compensate creators, to publish, and to have say in how the network works.")}</p>
<p>{__("No need to understand it all just yet! Try watching or downloading something next.")}</p>
<p>{__("Finally, know that LBRY is an early beta and that it earns the name.")}</p>
</section>
</Modal>
);
@ -178,16 +178,16 @@ class WelcomeStage extends React.Component {
const ErrorStage = (props) => {
return <section>
<p>An error was encountered that we cannot continue from.</p>
<p>At least we're earning the name beta.</p>
{ props.errorText ? <p>Message: {props.errorText}</p> : '' }
<Link button="alt" label="Try Reload" onClick={() => { window.location.reload() } } />
<p>{__("An error was encountered that we cannot continue from.")}</p>
<p>{__("At least we're earning the name beta.")}</p>
{ props.errorText ? <p>{__("Message:")} {props.errorText}</p> : '' }
<Link button="alt" label={__("Try Reload")} onClick={() => { window.location.reload() } } />
</section>
}
const PendingStage = (props) => {
return <section>
<p>Preparing for first access <span className="busy-indicator"></span></p>
<p>{__("Preparing for first access")} <span className="busy-indicator"></span></p>
</section>
}
@ -230,20 +230,20 @@ class CodeRequiredStage extends React.Component {
return (
<div>
<section className="section-spaced">
<p>Access to LBRY is restricted as we build and scale the network.</p>
<p>There are two ways in:</p>
<h3>Own LBRY Credits</h3>
<p>If you own at least 1 LBC, you can get in right now.</p>
<p>{__("Access to LBRY is restricted as we build and scale the network.")}</p>
<p>{__("There are two ways in:")}</p>
<h3>{__("Own LBRY Credits")}</h3>
<p>{__("If you own at least 1 LBC, you can get in right now.")}</p>
<p style={{ textAlign: "center"}}><Link onClick={() => { setLocal('auth_bypassed', true); this.props.setStage(null); }}
disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } /></p>
<p>Your balance is <CreditAmount amount={this.state.balance} />. To increase your balance, send credits to this address:</p>
<p><Address address={ this.state.address ? this.state.address : "Generating Address..." } /></p>
<p>If you don't understand how to send credits, then...</p>
disabled={disabled} label={__("Let Me In")} button={ disabled ? "alt" : "primary" } /></p>
<p>{__("Your balance is ")}<CreditAmount amount={this.state.balance} />. {__("To increase your balance, send credits to this address:")}</p>
<p><Address address={ this.state.address ? this.state.address : __("Generating Address...") } /></p>
<p>{__("If you don't understand how to send credits, then...")}</p>
</section>
<section>
<h3>Wait For A Code</h3>
<p>If you provide your email, you'll automatically receive a notification when the system is open.</p>
<p><Link onClick={() => { this.props.setStage("email"); }} label="Return" /></p>
<h3>{__("Wait For A Code")}</h3>
<p>{__("If you provide your email, you'll automatically receive a notification when the system is open.")}</p>
<p><Link onClick={() => { this.props.setStage("email"); }} label={__("Return")} /></p>
</section>
</div>
);
@ -312,16 +312,16 @@ export class AuthOverlay extends React.Component {
const StageContent = this._stages[this.state.stage];
if (!StageContent) {
return <span className="empty">Unknown authentication step.</span>
return <span className="empty">{__("Unknown authentication step.")}</span>
}
return (
this.state.stage != "welcome" ?
<ModalPage className="modal-page--full" isOpen={true} contentLabel="Authentication">
<h1>LBRY Early Access</h1>
<ModalPage className="modal-page--full" isOpen={true} contentLabel={__("Authentication")}>
<h1>{__("LBRY Early Access")}</h1>
<StageContent {...this.state.stageProps} setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} />
</ModalPage> :
<StageContent setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} {...this.state.stageProps} />
);
}
}
}

View file

@ -68,9 +68,9 @@ export class CreditAmount extends React.Component {
const formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision);
let amountText;
if (this.props.showFree && parseFloat(formattedAmount) == 0) {
amountText = 'free';
amountText = __('free');
} else if (this.props.label) {
amountText = formattedAmount + (parseFloat(formattedAmount) == 1 ? ' credit' : ' credits');
amountText = formattedAmount + ' ' + (parseFloat(formattedAmount) == 1 ? __('credit') : __('credits'));
} else {
amountText = formattedAmount;
}
@ -80,7 +80,7 @@ export class CreditAmount extends React.Component {
<span>
{amountText}
</span>
{ this.props.isEstimate ? <span className="credit-amount__estimate" title="This is an estimate and does not include data fees">*</span> : null }
{ this.props.isEstimate ? <span className="credit-amount__estimate" title={__("This is an estimate and does not include data fees")}>*</span> : null }
</span>
);
}

View file

@ -15,22 +15,22 @@ class DownloadingModal extends React.Component {
} = this.props
return (
<Modal isOpen={true} contentLabel="Downloading Update" type="custom">
Downloading Update{downloadProgress ? `: ${downloadProgress}%` : null}
<Modal isOpen={true} contentLabel={__("Downloading Update")} type="custom">
{__("Downloading Update")}{downloadProgress ? `: ${downloadProgress}%` : null}
<Line percent={downloadProgress ? downloadProgress : 0} strokeWidth="4"/>
{downloadComplete ? (
<div>
<br />
<p>Click "Begin Upgrade" to start the upgrade process.</p>
<p>The app will close, and you will be prompted to install the latest version of LBRY.</p>
<p>After the install is complete, please reopen the app.</p>
<p>{__("Click \"Begin Upgrade\" to start the upgrade process.")}</p>
<p>{__("The app will close, and you will be prompted to install the latest version of LBRY.")}</p>
<p>{__("After the install is complete, please reopen the app.")}</p>
</div>
) : null }
<div className="modal__buttons">
{downloadComplete
? <Link button="primary" label="Begin Upgrade" className="modal__button" onClick={startUpgrade} />
? <Link button="primary" label={__("Begin Upgrade")} className="modal__button" onClick={startUpgrade} />
: null}
<Link button="alt" label="Cancel" className="modal__button" onClick={cancelUpgrade} />
<Link button="alt" label={__("Cancel")} className="modal__button" onClick={cancelUpgrade} />
</div>
</Modal>
)

View file

@ -15,12 +15,12 @@ class ErrorModal extends React.Component {
const errorObj = typeof error === "string" ? { error: error } : error
const error_key_labels = {
connectionString: 'API connection string',
method: 'Method',
params: 'Parameters',
code: 'Error code',
message: 'Error message',
data: 'Error data',
connectionString: __('API connection string'),
method: __('Method'),
params: __('Parameters'),
code: __('Error code'),
message: __('Error message'),
data: __('Error data'),
}
@ -35,16 +35,16 @@ class ErrorModal extends React.Component {
return(
<ExpandableModal
isOpen={modal == 'error'}
contentLabel="Error" className="error-modal"
contentLabel={__("Error")} className="error-modal"
overlayClassName="error-modal-overlay"
onConfirmed={closeModal}
extraContent={errorInfo}
>
<h3 className="modal__header">Error</h3>
<h3 className="modal__header">{__("Error")}</h3>
<div className="error-modal__content">
<div><img className="error-modal__warning-symbol" src={lbry.imagePath('warning.png')} /></div>
<p>We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem.</p>
<p>{__("We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem.")}</p>
</div>
</ExpandableModal>
)

View file

@ -41,14 +41,14 @@ class FileSelector extends React.Component {
<div className="file-selector">
<button type="button" className="file-selector__choose-button" onClick={() => this.handleButtonClick()}>
{this.props.type == 'file' ?
'Choose File' :
'Choose Directory'}
__('Choose File') :
__('Choose Directory')}
</button>
{' '}
<span className="file-selector__path">
{this.state.path ?
this.state.path :
'No File Chosen'}
__('No File Chosen')}
</span>
</div>
);

View file

@ -68,7 +68,7 @@ class FileActions extends React.Component {
const deleteChecked = this.state.deleteChecked,
metadata = fileInfo ? fileInfo.metadata : null,
openInFolderMessage = platform.startsWith('Mac') ? 'Open in Finder' : 'Open in Folder',
openInFolderMessage = platform.startsWith('Mac') ? __('Open in Finder') : __('Open in Folder'),
showMenu = fileInfo && Object.keys(fileInfo).length > 0,
title = metadata ? metadata.title : uri;
@ -78,7 +78,7 @@ class FileActions extends React.Component {
const
progress = (fileInfo && fileInfo.written_bytes) ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0,
label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...',
label = fileInfo ? progress.toFixed(0) + __('% complete') : __('Connecting...'),
labelWithIcon = <span className="button__content"><Icon icon="icon-download" /><span>{label}</span></span>;
content = <div className="faux-button-block file-actions__download-status-bar button-set-item">
@ -88,27 +88,27 @@ class FileActions extends React.Component {
} else if (!fileInfo && isAvailable === undefined) {
content = <BusyMessage message="Checking availability" />
content = <BusyMessage message={__("Checking availability")} />
} else if (!fileInfo && !isAvailable && !this.state.forceShowActions) {
content = <div>
<div className="button-set-item empty">Content unavailable.</div>
<ToolTip label="Why?"
body="The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment."
<div className="button-set-item empty">{__("Content unavailable.")}</div>
<ToolTip label={__("Why?")}
body={__("The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment.")}
className="button-set-item" />
<Link label="Try Anyway" onClick={this.onShowFileActionsRowClicked.bind(this)} className="button-text button-set-item" />
<Link label={__("Try Anyway")} onClick={this.onShowFileActionsRowClicked.bind(this)} className="button-text button-set-item" />
</div>
} else if (fileInfo === null && !downloading) {
if (!costInfo) {
content = <BusyMessage message="Fetching cost info" />
content = <BusyMessage message={__("Fetching cost info")} />
} else {
content = <Link button="text" label="Download" icon="icon-download" onClick={() => { startDownload(uri) } } />;
content = <Link button="text" label={__("Download")} icon="icon-download" onClick={() => { startDownload(uri) } } />;
}
} else if (fileInfo && fileInfo.download_path) {
content = <Link label="Open" button="text" icon="icon-folder-open" onClick={() => openInShell(fileInfo)} />;
content = <Link label={__("Open")} button="text" icon="icon-folder-open" onClick={() => openInShell(fileInfo)} />;
} else {
console.log('handle this case of file action props?');
}
@ -119,29 +119,29 @@ class FileActions extends React.Component {
{ showMenu ?
<DropDownMenu>
<DropDownMenuItem key={0} onClick={() => openInFolder(fileInfo)} label={openInFolderMessage} />
<DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label="Remove..." />
<DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label={__("Remove...")} />
</DropDownMenu> : '' }
<Modal type="confirm" isOpen={modal == 'affirmPurchase'}
contentLabel="Confirm Purchase" onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={closeModal}>
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
contentLabel={__("Confirm Purchase")} onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={closeModal}>
{__("This will purchase")} <strong>{title}</strong> {__("for")} <strong><FilePrice uri={uri} look="plain" /></strong> {__("credits")}.
</Modal>
<Modal isOpen={modal == 'notEnoughCredits'} contentLabel="Not enough credits"
<Modal isOpen={modal == 'notEnoughCredits'} contentLabel={__("Not enough credits")}
onConfirmed={closeModal}>
You don't have enough LBRY credits to pay for this stream.
{__("You don't have enough LBRY credits to pay for this stream.")}
</Modal>
<Modal isOpen={modal == 'timedOut'} contentLabel="Download failed"
<Modal isOpen={modal == 'timedOut'} contentLabel={__("Download failed")}
onConfirmed={closeModal}>
LBRY was unable to download the stream <strong>{uri}</strong>.
{__("LBRY was unable to download the stream")} <strong>{uri}</strong>.
</Modal>
<Modal isOpen={modal == 'confirmRemove'}
contentLabel="Not enough credits"
contentLabel={__("Not enough credits")}
type="confirm"
confirmButtonLabel="Remove"
confirmButtonLabel={__("Remove")}
onConfirmed={() => deleteFile(fileInfo.outpoint, deleteChecked)}
onAborted={closeModal}>
<p>Are you sure you'd like to remove <cite>{title}</cite> from LBRY?</p>
<p>{__("Are you sure you'd like to remove")} <cite>{title}</cite> {__("from LBRY?")}</p>
<label><FormField type="checkbox" checked={deleteChecked} onClick={this.handleDeleteCheckboxClicked.bind(this)} /> Delete this file from my computer</label>
<label><FormField type="checkbox" checked={deleteChecked} onClick={this.handleDeleteCheckboxClicked.bind(this)} /> {__("Delete this file from my computer")}</label>
</Modal>
</section>
);

View file

@ -68,11 +68,11 @@ class FileCard extends React.Component {
let description = ""
if (isResolvingUri) {
description = "Loading..."
description = __("Loading...")
} else if (metadata && metadata.description) {
description = metadata.description
} else if (claim === null) {
description = 'This address contains no content.'
description = __("This address contains no content.")
}
return (
@ -99,8 +99,7 @@ class FileCard extends React.Component {
{obscureNsfw && this.state.hovered
? <div className='card-overlay'>
<p>
This content is Not Safe For Work.
To view adult content, please change your <Link className="button-text" onClick={() => navigate('settings')} label="Settings" />.
{__("This content is Not Safe For Work. To view adult content, please change your")} <Link className="button-text" onClick={() => navigate('settings')} label={__("Settings")} />.
</p>
</div>
: null}

View file

@ -77,11 +77,11 @@ class FileList extends React.Component {
<section className="file-list__header">
{ fetching && <span className="busy-indicator"/> }
<span className='sort-section'>
Sort by { ' ' }
{__("Sort by")} { ' ' }
<FormField type="select" onChange={this.handleSortChanged.bind(this)}>
<option value="date">Date</option>
<option value="title">Title</option>
<option value="filename">File name</option>
<option value="date">{__("Date")}</option>
<option value="title">{__("Title")}</option>
<option value="filename">{__("File name")}</option>
</FormField>
</span>
{content}

View file

@ -16,8 +16,8 @@ const SearchNoResults = (props) => {
return <section>
<span className="empty">
No one has checked anything in for {query} yet. { ' ' }
<Link label="Be the first" onClick={() => navigate('/publish')} />
{__("No one has checked anything in for %s yet."), query} { ' ' }
<Link label={__("Be the first")} onClick={() => navigate('/publish')} />
</span>
</section>;
}
@ -60,10 +60,10 @@ class FileListSearch extends React.Component{
return (
<div>
{isSearching && !results &&
<BusyMessage message="Looking up the Dewey Decimals" />}
<BusyMessage message={__("Looking up the Dewey Decimals")} />}
{isSearching && results &&
<BusyMessage message="Refreshing the Dewey Decimals" />}
<BusyMessage message={__("Refreshing the Dewey Decimals")} />}
{(results && !!results.length) ?
<FileListSearchResults {...this.props} /> :
@ -73,4 +73,4 @@ class FileListSearch extends React.Component{
}
}
export default FileListSearch
export default FileListSearch

View file

@ -68,15 +68,15 @@ class FileTile extends React.Component {
if (isClaimed) {
description = metadata && metadata.description
} else if (isResolvingUri) {
description = "Loading..."
description = __("Loading...")
} else if (showEmpty === FileTile.SHOW_EMPTY_PUBLISH) {
onClick = () => navigate('/publish', { })
description = <span className="empty">
This location is unused. { ' ' }
{ isClaimable && <span className="button-text">Put something here!</span> }
{__("This location is unused.")} { ' ' }
{ isClaimable && <span className="button-text">{__("Put something here!")}</span> }
</span>
} else if (showEmpty === FileTile.SHOW_EMPTY_PENDING) {
description = <span className="empty">This file is pending confirmation.</span>
description = <span className="empty">{__("This file is pending confirmation.")}</span>
}
return (
@ -103,8 +103,7 @@ class FileTile extends React.Component {
{this.state.showNsfwHelp
? <div className='card-overlay'>
<p>
This content is Not Safe For Work.
To view adult content, please change your <Link className="button-text" onClick={() => navigate('/settings')} label="Settings" />.
{__("This content is Not Safe For Work. To view adult content, please change your")} <Link className="button-text" onClick={() => navigate('/settings')} label={__("Settings")} />.
</p>
</div>
: null}

View file

@ -21,7 +21,7 @@ export class FormField extends React.Component {
constructor(props) {
super(props);
this._fieldRequiredText = 'This field is required';
this._fieldRequiredText = __('This field is required');
this._type = null;
this._element = null;
@ -136,7 +136,7 @@ export class FormRow extends React.Component {
constructor(props) {
super(props);
this._fieldRequiredText = 'This field is required';
this._fieldRequiredText = __('This field is required');
this.state = {
isError: false,

View file

@ -13,7 +13,8 @@ import {
import Header from './view'
const select = (state) => ({
balance: lbry.formatCredits(selectBalance(state), 1)
balance: lbry.formatCredits(selectBalance(state), 1),
publish: __("Publish"),
})
const perform = (dispatch) => ({

View file

@ -6,7 +6,8 @@ export const Header = (props) => {
const {
balance,
back,
navigate
navigate,
publish,
} = props
return <header id="header">
@ -17,13 +18,13 @@ export const Header = (props) => {
<Link onClick={() => navigate('/discover')} button="alt button--flat" icon="icon-home" />
</div>
<div className="header__item header__item--wunderbar">
<WunderBar/>
<WunderBar />
</div>
<div className="header__item">
<Link onClick={() => navigate('/wallet')} button="text" icon="icon-bank" label={balance} ></Link>
</div>
<div className="header__item">
<Link onClick={() => navigate('/publish')} button="primary button--flat" icon="icon-upload" label="Publish" />
<Link onClick={() => navigate('/publish')} button="primary button--flat" icon="icon-upload" label={publish} />
</div>
<div className="header__item">
<Link onClick={() => navigate('/downloaded')} button="alt button--flat" icon="icon-folder" />

View file

@ -1,7 +1,7 @@
import React from 'react';
import ReactModal from 'react-modal';
import Link from 'component/link';
import app from '../app.js'
export class Modal extends React.Component {
static propTypes = {
@ -18,8 +18,8 @@ export class Modal extends React.Component {
static defaultProps = {
type: 'alert',
overlay: true,
confirmButtonLabel: 'OK',
abortButtonLabel: 'Cancel',
confirmButtonLabel: app.i18n.__('OK'),
abortButtonLabel: app.i18n.__('Cancel'),
confirmButtonDisabled: false,
abortButtonDisabled: false,
}
@ -52,9 +52,9 @@ export class ExpandableModal extends React.Component {
}
static defaultProps = {
confirmButtonLabel: 'OK',
expandButtonLabel: 'Show More...',
hideButtonLabel: 'Show Less',
confirmButtonLabel: app.i18n.__('OK'),
expandButtonLabel: app.i18n.__('Show More...'),
hideButtonLabel: app.i18n.__('Show Less'),
}
constructor(props) {

View file

@ -77,15 +77,15 @@ export class RewardLink extends React.Component {
return (
<div className="reward-link">
{this.props.claimed
? <span><Icon icon="icon-check" /> Reward claimed.</span>
? <span><Icon icon="icon-check" /> {__("Reward claimed.")}</span>
: <Link button={this.props.button ? this.props.button : 'alt'} disabled={this.state.pending || !this.state.claimable }
label={ this.state.pending ? "Claiming..." : "Claim Reward"} onClick={() => { this.claimReward() }} />}
label={ this.state.pending ? __("Claiming...") : __("Claim Reward")} onClick={() => { this.claimReward() }} />}
{this.state.errorMessage ?
<Modal isOpen={true} contentLabel="Reward Claim Error" className="error-modal" onConfirmed={() => { this.clearError() }}>
<Modal isOpen={true} contentLabel={__("Reward Claim Error")} className="error-modal" onConfirmed={() => { this.clearError() }}>
{this.state.errorMessage}
</Modal>
: ''}
</div>
);
}
}
}

View file

@ -12,8 +12,8 @@ export class SplashScreen extends React.Component {
super(props);
this.state = {
details: 'Starting daemon',
message: "Connecting",
details: __('Starting daemon'),
message: __("Connecting"),
isLagging: false,
};
}
@ -30,8 +30,8 @@ export class SplashScreen extends React.Component {
// TODO: This is a hack, and the logic should live in the daemon
// to give us a better sense of when we are actually started
this.setState({
message: "Testing Network",
details: "Waiting for name resolution",
message: __("Testing Network"),
details: __("Waiting for name resolution"),
isLagging: false
});
@ -55,8 +55,8 @@ export class SplashScreen extends React.Component {
.catch(() => {
this.setState({
isLagging: true,
message: "Connection Failure",
details: "Try closing all LBRY processes and starting again. If this still happpens, your anti-virus software or firewall may be preventing LBRY from connecting. Contact hello@lbry.io if you think this is a software bug."
message: __("Connection Failure"),
details: __("Try closing all LBRY processes and starting again. If this still happpens, your anti-virus software or firewall may be preventing LBRY from connecting. Contact hello@lbry.io if you think this is a software bug.")
})
})
}

View file

@ -22,8 +22,8 @@ class TransactionList extends React.Component{
rows.push(
<tr key={item.id}>
<td>{ (item.amount > 0 ? '+' : '' ) + item.amount }</td>
<td>{ item.date ? item.date.toLocaleDateString() : <span className="empty">(Transaction pending)</span> }</td>
<td>{ item.date ? item.date.toLocaleTimeString() : <span className="empty">(Transaction pending)</span> }</td>
<td>{ item.date ? item.date.toLocaleDateString() : <span className="empty">{__("(Transaction pending)")}</span> }</td>
<td>{ item.date ? item.date.toLocaleTimeString() : <span className="empty">{__("(Transaction pending)")}</span> }</td>
<td>
<a className="button-text" href={"https://explorer.lbry.io/#!/transaction?id="+item.id}>{item.id.substr(0, 7)}</a>
</td>
@ -35,19 +35,19 @@ class TransactionList extends React.Component{
return (
<section className="card">
<div className="card__title-primary">
<h3>Transaction History</h3>
<h3>{__("Transaction History")}</h3>
</div>
<div className="card__content">
{ fetchingTransactions && <BusyMessage message="Loading transactions" /> }
{ !fetchingTransactions && rows.length === 0 ? <div className="empty">You have no transactions.</div> : '' }
{ fetchingTransactions && <BusyMessage message={__("Loading transactions")} /> }
{ !fetchingTransactions && rows.length === 0 ? <div className="empty">{__("You have no transactions.")}</div> : '' }
{ rows.length > 0 ?
<table className="table-standard table-stretch">
<thead>
<tr>
<th>Amount</th>
<th>Date</th>
<th>Time</th>
<th>Transaction</th>
<th>{__("Amount")}</th>
<th>{__("Date")}</th>
<th>{__("Time")}</th>
<th>{__("Transaction")}</th>
</tr>
</thead>
<tbody>
@ -62,4 +62,4 @@ class TransactionList extends React.Component{
}
}
export default TransactionList
export default TransactionList

View file

@ -17,13 +17,13 @@ class UpgradeModal extends React.Component {
return (
<Modal
isOpen={true}
contentLabel="Update available"
contentLabel={__("Update available")}
type="confirm"
confirmButtonLabel="Upgrade"
abortButtonLabel="Skip"
confirmButtonLabel={__("Upgrade")}
abortButtonLabel={__("Skip")}
onConfirmed={downloadUpgrade}
onAborted={skipUpgrade}>
Your version of LBRY is out of date and may be unreliable or insecure.
{__("Your version of LBRY is out of date and may be unreliable or insecure.")}
</Modal>
)
}

View file

@ -58,20 +58,20 @@ class VideoPlayButton extends React.Component {
className="video__play-button"
icon={icon}
onClick={this.onWatchClick.bind(this)} />
<Modal contentLabel="Not enough credits" isOpen={modal == 'notEnoughCredits'} onConfirmed={closeModal}>
You don't have enough LBRY credits to pay for this stream.
<Modal contentLabel={__("Not enough credits")} isOpen={modal == 'notEnoughCredits'} onConfirmed={closeModal}>
{__("You don't have enough LBRY credits to pay for this stream.")}
</Modal>
<Modal
type="confirm"
isOpen={modal == 'affirmPurchaseAndPlay'}
contentLabel="Confirm Purchase"
contentLabel={__("Confirm Purchase")}
onConfirmed={this.onPurchaseConfirmed.bind(this)}
onAborted={closeModal}>
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
{__("This will purchase")} <strong>{title}</strong> {__("for")} <strong><FilePrice uri={uri} look="plain" /></strong> {__("credits")}.
</Modal>
<Modal
isOpen={modal == 'timedOut'} onConfirmed={closeModal} contentLabel="Timed Out">
Sorry, your download timed out :(
isOpen={modal == 'timedOut'} onConfirmed={closeModal} contentLabel={__("Timed Out")}>
{__("Sorry, your download timed out :(")}
</Modal>
</div>);
}
@ -107,11 +107,11 @@ class Video extends React.Component {
let loadStatusMessage = ''
if(fileInfo && fileInfo.completed && !fileInfo.written_bytes) {
loadStatusMessage = "It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds."
loadStatusMessage = __("It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds.")
} else if (isLoading) {
loadStatusMessage = "Requesting stream... it may sit here for like 15-20 seconds in a really awkward way... we're working on it"
loadStatusMessage = __("Requesting stream... it may sit here for like 15-20 seconds in a really awkward way... we're working on it")
} else if (isDownloading) {
loadStatusMessage = "Downloading stream... not long left now!"
loadStatusMessage = __("Downloading stream... not long left now!")
}
let klassName = ""
@ -128,7 +128,7 @@ class Video extends React.Component {
<div className={klassName}>{
isPlaying ?
(!isReadyToPlay ?
<span>this is the world's worst loading screen and we shipped our software with it anyway... <br /><br />{loadStatusMessage}</span> :
<span>{__("this is the world's worst loading screen and we shipped our software with it anyway...")} <br /><br />{loadStatusMessage}</span> :
<VideoPlayer filename={fileInfo.file_name} poster={poster} downloadPath={fileInfo.download_path} mediaType={mediaType} poster={poster} />) :
<div className="video__cover" style={{backgroundImage: 'url("' + metadata.thumbnail + '")'}}>
<VideoPlayButton startPlaying={this.startPlaying.bind(this)} {...this.props} mediaType={mediaType} />

View file

@ -19,18 +19,18 @@ class WalletAddress extends React.Component {
return (
<section className="card">
<div className="card__title-primary">
<h3>Wallet Address</h3>
<h3>{__("Wallet Address")}</h3>
</div>
<div className="card__content">
<Address address={receiveAddress} />
</div>
<div className="card__actions">
<Link label="Get New Address" button="primary" icon='icon-refresh' onClick={getNewAddress} disabled={gettingNewAddress} />
<Link label={__("Get New Address")} button="primary" icon='icon-refresh' onClick={getNewAddress} disabled={gettingNewAddress} />
</div>
<div className="card__content">
<div className="help">
<p>Other LBRY users may send credits to you by entering this address on the "Send" page.</p>
<p>You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.</p>
<p>{__("Other LBRY users may send credits to you by entering this address on the \"Send\" page.")}</p>
<p>{__("You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.")}</p>
</div>
</div>
</section>

View file

@ -20,27 +20,27 @@ const WalletSend = (props) => {
<section className="card">
<form onSubmit={sendToAddress}>
<div className="card__title-primary">
<h3>Send Credits</h3>
<h3>{__("Send Credits")}</h3>
</div>
<div className="card__content">
<FormRow label="Amount" postfix="LBC" step="0.01" type="number" placeholder="1.23" size="10" onChange={setAmount} value={amount} />
<FormRow label={__("Amount")} postfix="LBC" step="0.01" type="number" placeholder="1.23" size="10" onChange={setAmount} value={amount} />
</div>
<div className="card__content">
<FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={setAddress} value={address} />
<FormRow label={__("Recipient Address")} placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={setAddress} value={address} />
</div>
<div className="card__actions card__actions--form-submit">
<Link button="primary" label="Send" onClick={sendToAddress} disabled={!(parseFloat(amount) > 0.0) || !address} />
<Link button="primary" label={_("Send")} onClick={sendToAddress} disabled={!(parseFloat(amount) > 0.0) || !address} />
<input type='submit' className='hidden' />
</div>
</form>
{modal == 'insufficientBalance' && <Modal isOpen={true} contentLabel="Insufficient balance" onConfirmed={closeModal}>
Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.
{modal == 'insufficientBalance' && <Modal isOpen={true} contentLabel={__("Insufficient balance")} onConfirmed={closeModal}>
{__("Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.")}
</Modal>}
{modal == 'transactionSuccessful' && <Modal isOpen={true} contentLabel="Transaction successful" onConfirmed={closeModal}>
Your transaction was successfully placed in the queue.
{modal == 'transactionSuccessful' && <Modal isOpen={true} contentLabel={__("Transaction successful")} onConfirmed={closeModal}>
{__("Your transaction was successfully placed in the queue.")}
</Modal>}
{modal == 'transactionFailed' && <Modal isOpen={true} contentLabel="Transaction failed" onConfirmed={closeModal}>
Something went wrong:
{modal == 'transactionFailed' && <Modal isOpen={true} contentLabel={__("Transaction failed")} onConfirmed={closeModal}>
{__("Something went wrong")}:
</Modal>}
</section>
)

View file

@ -151,7 +151,7 @@ class WunderBar extends React.PureComponent {
onChange={this.onChange}
onKeyPress={this.onKeyPress}
value={this.state.address}
placeholder="Find movies, music, games, and more" />
placeholder={__("Find movies, music, games, and more")} />
</div>
);
}

View file

@ -11,7 +11,7 @@ jsonrpc.call = function (connectionString, method, params, callback, errorCallba
connectFailedCallback(e);
});
xhr.addEventListener('timeout', function() {
connectFailedCallback(new Error('XMLHttpRequest connection timed out'));
connectFailedCallback(new Error(__('XMLHttpRequest connection timed out')));
})
}
xhr.addEventListener('load', function() {
@ -50,7 +50,7 @@ jsonrpc.call = function (connectionString, method, params, callback, errorCallba
method: method,
params: params,
code: xhr.status,
message: 'Connection to API server failed'
message: __('Connection to API server failed')
}
});
document.dispatchEvent(errorEvent);

View file

@ -18,6 +18,7 @@ let lbry = {
useCustomLighthouseServers: false,
customLighthouseServers: [],
showDeveloperMenu: false,
language: 'en',
}
};
@ -416,7 +417,7 @@ lbry._resolveXhrs = {}
lbry.resolve = function(params={}) {
return new Promise((resolve, reject) => {
if (!params.uri) {
throw "Resolve has hacked cache on top of it that requires a URI"
throw __("Resolve has hacked cache on top of it that requires a URI")
}
if (params.uri && lbry._claimCache[params.uri] !== undefined) {
resolve(lbry._claimCache[params.uri]);

View file

@ -34,20 +34,20 @@ lbryio.getExchangeRates = function() {
lbryio.call = function(resource, action, params={}, method='get', evenIfDisabled=false) { // evenIfDisabled is just for development, when we may have some calls working and some not
return new Promise((resolve, reject) => {
if (!lbryio.enabled && !evenIfDisabled && (resource != 'discover' || action != 'list')) {
console.log("Internal API disabled");
reject(new Error("LBRY internal API is disabled"))
console.log(__("Internal API disabled"));
reject(new Error(__("LBRY internal API is disabled")))
return
}
const xhr = new XMLHttpRequest;
xhr.addEventListener('error', function (event) {
reject(new Error("Something went wrong making an internal API call."));
reject(new Error(__("Something went wrong making an internal API call.")));
});
xhr.addEventListener('timeout', function() {
reject(new Error('XMLHttpRequest connection timed out'));
reject(new Error(__('XMLHttpRequest connection timed out')));
});
xhr.addEventListener('load', function() {
@ -89,7 +89,7 @@ lbryio.call = function(resource, action, params={}, method='get', evenIfDisabled
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring.stringify(fullParams));
} else {
reject(new Error("Invalid method"));
reject(new Error(__("Invalid method")));
}
});
};
@ -139,7 +139,7 @@ lbryio.authenticate = function() {
app_id: installation_id,
}, 'post').then(function(responseData) {
if (!responseData.id) {
reject(new Error("Received invalid authentication response."));
reject(new Error(__("Received invalid authentication response.")));
}
lbryio.setAccessToken(installation_id)
setCurrentUser()

View file

@ -39,12 +39,12 @@ lbryuri.parse = function(uri, requireProto=false) {
// Validate protocol
if (requireProto && !proto) {
throw new Error('LBRY URIs must include a protocol prefix (lbry://).');
throw new Error(__('LBRY URIs must include a protocol prefix (lbry://).'));
}
// Validate and process name
if (!name) {
throw new Error('URI does not include name.');
throw new Error(__('URI does not include name.'));
}
const isChannel = name.startsWith('@');
@ -52,11 +52,11 @@ lbryuri.parse = function(uri, requireProto=false) {
if (isChannel) {
if (!channelName) {
throw new Error('No channel name after @.');
throw new Error(__('No channel name after @.'));
}
if (channelName.length < CHANNEL_NAME_MIN_LEN) {
throw new Error(`Channel names must be at least ${CHANNEL_NAME_MIN_LEN} characters.`);
throw new Error(__(`Channel names must be at least %s characters.`, CHANNEL_NAME_MIN_LEN));
}
contentName = path;
@ -64,14 +64,14 @@ lbryuri.parse = function(uri, requireProto=false) {
const nameBadChars = (channelName || name).match(/[^A-Za-z0-9-]/g);
if (nameBadChars) {
throw new Error(`Invalid character${nameBadChars.length == 1 ? '' : 's'} in name: ${nameBadChars.join(', ')}.`);
throw new Error(__(`Invalid character %s in name: %s.`, nameBadChars.length == 1 ? '' : 's', nameBadChars.join(', ') ));
}
// Validate and process modifier (claim ID, bid position or claim sequence)
let claimId, claimSequence, bidPosition;
if (modSep) {
if (!modVal) {
throw new Error(`No modifier provided after separator ${modSep}.`);
throw new Error(__(`No modifier provided after separator %s.`, modSep));
}
if (modSep == '#') {
@ -84,31 +84,31 @@ lbryuri.parse = function(uri, requireProto=false) {
}
if (claimId && (claimId.length > CLAIM_ID_MAX_LEN || !claimId.match(/^[0-9a-f]+$/))) {
throw new Error(`Invalid claim ID ${claimId}.`);
throw new Error(__(`Invalid claim ID %s.`, claimId));
}
if (claimSequence && !claimSequence.match(/^-?[1-9][0-9]*$/)) {
throw new Error('Claim sequence must be a number.');
throw new Error(__('Claim sequence must be a number.'));
}
if (bidPosition && !bidPosition.match(/^-?[1-9][0-9]*$/)) {
throw new Error('Bid position must be a number.');
throw new Error(__('Bid position must be a number.'));
}
// Validate and process path
if (path) {
if (!isChannel) {
throw new Error('Only channel URIs may have a path.');
throw new Error(__('Only channel URIs may have a path.'));
}
const pathBadChars = path.match(/[^A-Za-z0-9-]/g);
if (pathBadChars) {
throw new Error(`Invalid character${count == 1 ? '' : 's'} in path: ${nameBadChars.join(', ')}`);
throw new Error(__(`Invalid character %s in path: %s`,count == 1 ? '' : 's',nameBadChars.join(', ')));
}
contentName = path;
} else if (pathSep) {
throw new Error('No path provided after /');
throw new Error(__('No path provided after /'));
}
return {
@ -135,7 +135,7 @@ lbryuri.build = function(uriObj, includeProto=true, allowExtraProps=false) {
if (!name) {
name = channelNameFormatted;
} else if (name !== channelNameFormatted) {
throw new Error('Received a channel content URI, but name and channelName do not match. "name" represents the value in the name position of the URI (lbry://name...), which for channel content will be the channel name. In most cases, to construct a channel URI you should just pass channelName and contentName.');
throw new Error(__('Received a channel content URI, but name and channelName do not match. \"name\" represents the value in the name position of the URI (lbry://name...), which for channel content will be the channel name. In most cases, to construct a channel URI you should just pass channelName and contentName.'));
}
}
@ -146,7 +146,7 @@ lbryuri.build = function(uriObj, includeProto=true, allowExtraProps=false) {
path = contentName;
}
if (path && path !== contentName) {
throw new Error('path and contentName do not match. Only one is required; most likely you wanted contentName.');
throw new Error(__('Path and contentName do not match. Only one is required; most likely you wanted contentName.'));
}
}

View file

@ -21,7 +21,7 @@ function getServers() {
function call(method, params, callback, errorCallback) {
if (connectTryNum >= maxQueryTries) {
errorCallback(new Error(`Could not connect to Lighthouse server. Last server attempted: ${server}`));
errorCallback(new Error(__(`Could not connect to Lighthouse server. Last server attempted: %s`, server)));
return;
}

View file

@ -4,11 +4,11 @@ import lbry from './lbry.js';
import lbryio from './lbryio.js';
import lighthouse from './lighthouse.js';
import App from 'component/app/index.js';
import SplashScreen from 'component/splash.js';
import SnackBar from 'component/snackBar';
import {AuthOverlay} from 'component/auth.js';
import { Provider } from 'react-redux';
import store from 'store.js';
import SplashScreen from 'component/splash.js';
import {AuthOverlay} from 'component/auth.js';
import {
doChangePath,
doNavigate,
@ -28,6 +28,7 @@ const {remote, ipcRenderer, shell} = require('electron');
const contextMenu = remote.require('./menu/context-menu');
const app = require('./app')
lbry.showMenuIfNeeded();
window.addEventListener('contextmenu', (event) => {

View file

@ -27,11 +27,11 @@ class ChannelPage extends React.Component{
let contentList
if (claimsInChannel === undefined) {
contentList = <BusyMessage message="Fetching content" />
contentList = <BusyMessage message={__("Fetching content")} />
} else if (claimsInChannel) {
contentList = claimsInChannel.length ?
claimsInChannel.map((claim) => <FileTile key={claim.claim_id} uri={lbryuri.build({name: claim.name, claimId: claim.claim_id})} />) :
<span className="empty">No content found.</span>
<span className="empty">{__("No content found.")}</span>
}
return <main className="main--single-column">
@ -41,11 +41,11 @@ class ChannelPage extends React.Component{
</div>
<div className="card__content">
<p>
This channel page is a stub.
{__("This channel page is a stub.")}
</p>
</div>
</section>
<h3 className="card-row__header">Published Content</h3>
<h3 className="card-row__header">{__("Published Content")}</h3>
{contentList}
</main>
}

View file

@ -42,7 +42,7 @@ class DeveloperPage extends React.Component {
handleForceUpgradeClick() {
let upgradeSent = false;
if (!this.state.upgradePath) {
alert('Please select a file to upgrade from');
alert(__('Please select a file to upgrade from'));
} else {
try {
const stats = fs.lstatSync(this.state.upgradePath);
@ -63,17 +63,17 @@ class DeveloperPage extends React.Component {
return (
<main>
<section className="card">
<h3>Developer Settings</h3>
<h3>{__("Developer Settings")}</h3>
<div className="form-row">
<label><FormField type="checkbox" onChange={(event) => { this.handleShowDeveloperMenuChange() }} checked={this.state.showDeveloperMenu} /> Show developer menu</label>
<label><FormField type="checkbox" onChange={(event) => { this.handleShowDeveloperMenuChange() }} checked={this.state.showDeveloperMenu} /> {__("Show developer menu")}</label>
</div>
<div className="form-row">
<label><FormField type="checkbox" onChange={(event) => { this.handleUseCustomLighthouseServersChange() }} checked={this.state.useCustomLighthouseServers} /> Use custom search servers</label>
<label><FormField type="checkbox" onChange={(event) => { this.handleUseCustomLighthouseServersChange() }} checked={this.state.useCustomLighthouseServers} /> {__("Use custom search servers")}</label>
</div>
{this.state.useCustomLighthouseServers
? <div className="form-row">
<label>
Custom search servers (one per line)
{__("Custom search servers (one per line)")}
<div><FormField type="textarea" className="developer-page__custom-lighthouse-servers" value={this.state.customLighthouseServers} onChange={(event) => { this.handleCustomLighthouseServersChange() }} checked={this.state.debugMode} /></div>
</label>
</div>
@ -83,7 +83,7 @@ class DeveloperPage extends React.Component {
<div className="form-row">
<FormField name="file" ref="file" type="file" onChange={(event) => { this.handleUpgradeFileChange() }}/>
&nbsp;
<Link label="Force Upgrade" button="alt" onClick={(event) => { this.handleForceUpgradeClick() }} />
<Link label={__("Force Upgrade")} button="alt" onClick={(event) => { this.handleForceUpgradeClick() }} />
</div>
</section>
</main>

View file

@ -17,7 +17,7 @@ const FeaturedCategory = (props) => {
return <div className="card-row card-row--small">
<h3 className="card-row__header">{category}
{category && category.match(/^community/i) && <ToolTip label="What's this?" body={communityCategoryToolTipText} className="tooltip--header" />}
{category && category.match(/^community/i) && <ToolTip label={__("What's this?")} body={__(communityCategoryToolTipText)} className="tooltip--header" />}
</h3>
{names && names.map(name => <FileCard key={name} displayStyle="card" uri={lbryuri.normalize(name)} />)}
</div>
@ -42,7 +42,7 @@ class DiscoverPage extends React.Component{
<main>
{
fetchingFeaturedUris &&
<BusyMessage message="Fetching content" />
<BusyMessage message={__("Fetching content")} />
}
{
typeof featuredUris === "object" &&
@ -52,11 +52,11 @@ class DiscoverPage extends React.Component{
}
{
failedToLoad &&
<div className="empty">Failed to load landing content.</div>
<div className="empty">{__("Failed to load landing content.")}</div>
}
</main>
)
}
}
export default DiscoverPage;
export default DiscoverPage;

View file

@ -27,9 +27,9 @@ class FileListDownloaded extends React.Component {
content = <FileList fileInfos={fileInfos} fetching={isPending} />
} else {
if (isPending) {
content = <BusyMessage message="Loading" />
content = <BusyMessage message={__("Loading")} />
} else {
content = <span>You haven't downloaded anything from LBRY yet. Go <Link onClick={() => navigate('/discover')} label="search for your first download" />!</span>
content = <span>{__("You haven't downloaded anything from LBRY yet. Go")} <Link onClick={() => navigate('/discover')} label={__("search for your first download")} />!</span>
}
}

View file

@ -49,9 +49,9 @@ class FileListPublished extends React.Component {
content = <FileList fileInfos={fileInfos} fetching={isPending} fileTileShowEmpty={FileTile.SHOW_EMPTY_PENDING} />
} else {
if (isPending) {
content = <BusyMessage message="Loading" />
content = <BusyMessage message={__("Loading")} />
} else {
content = <span>It looks like you haven't published anything to LBRY yet. Go <Link onClick={() => navigate('/publish')} label="share your beautiful cats with the world" />!</span>
content = <span>{__("It looks like you haven't published anything to LBRY yet. Go")} <Link onClick={() => navigate('/publish')} label={__("share your beautiful cats with the world")} />!</span>
}
}

View file

@ -26,16 +26,16 @@ const FormatItem = (props) => {
<table className="table-standard">
<tbody>
<tr>
<td>Content-Type</td><td>{mediaType}</td>
<td>{__("Content-Type")}</td><td>{mediaType}</td>
</tr>
<tr>
<td>Author</td><td>{author}</td>
<td>{__("Author")}</td><td>{author}</td>
</tr>
<tr>
<td>Language</td><td>{language}</td>
<td>{__("Language")}</td><td>{language}</td>
</tr>
<tr>
<td>License</td><td>{license}</td>
<td>{__("License")}</td><td>{license}</td>
</tr>
</tbody>
</table>
@ -75,7 +75,7 @@ class FilePage extends React.Component{
} = this.props
if (!claim || !metadata) {
return <span className="empty">Empty claim or metadata info.</span>
return <span className="empty">{__("Empty claim or metadata info.")}</span>
}
const {
@ -125,7 +125,7 @@ class FilePage extends React.Component{
<FormatItem metadata={metadata} contentType={contentType} />
</div> : '' }
<div className="card__content">
<Link href="https://lbry.io/dmca" label="report" className="button-text-help" />
<Link href="https://lbry.io/dmca" label={__("report")} className="button-text-help" />
</div>
</section>
</main>
@ -133,4 +133,4 @@ class FilePage extends React.Component{
}
}
export default FilePage;
export default FilePage;

View file

@ -66,70 +66,71 @@ class HelpPage extends React.Component {
<SubHeader />
<section className="card">
<div className="card__title-primary">
<h3>Read the FAQ</h3>
<h3>{__("Read the FAQ")}</h3>
</div>
<div className="card__content">
<p>Our FAQ answers many common questions.</p>
<p><Link href="https://lbry.io/faq" label="Read the FAQ" icon="icon-question" button="alt"/></p>
<p>{__("Our FAQ answers many common questions.")}</p>
<p><Link href="https://lbry.io/faq" label={__("Read the FAQ")} icon="icon-question" button="alt"/></p>
</div>
</section>
<section className="card">
<div className="card__title-primary">
<h3>Get Live Help</h3>
<h3>{__("Get Live Help")}</h3>
</div>
<div className="card__content">
<p>
Live help is available most hours in the <strong>#help</strong> channel of our Slack chat room.
{__("Live help is available most hours in the")} <strong>#help</strong> {__("channel of our Slack chat room.")}
</p>
<p>
<Link button="alt" label="Join Our Slack" icon="icon-slack" href="https://slack.lbry.io" />
<Link button="alt" label={__("Join Our Slack")} icon="icon-slack" href="https://slack.lbry.io" />
</p>
</div>
</section>
<section className="card">
<div className="card__title-primary"><h3>Report a Bug</h3></div>
<div className="card__title-primary"><h3>{__("Report a Bug")}</h3></div>
<div className="card__content">
<p>Did you find something wrong?</p>
<p><Link onClick={() => navigate('report')} label="Submit a Bug Report" icon="icon-bug" button="alt" /></p>
<div className="meta">Thanks! LBRY is made by its users.</div>
<p>{__("Did you find something wrong?")}</p>
<p><Link onClick={() => navigate('report')} label={__("Submit a Bug Report")} icon="icon-bug" button="alt" /></p>
<div className="meta">{__("Thanks! LBRY is made by its users.")}</div>
</div>
</section>
<section className="card">
<div className="card__title-primary"><h3>About</h3></div>
<div className="card__content">
<div className="card__title-primary"><h3>{__("About")}</h3></div>
<div className="card__content">
{ this.state.upgradeAvailable === null ? '' :
( this.state.upgradeAvailable ?
<p>A newer version of LBRY is available. <Link href={newVerLink} label={`Download now!`} /></p>
: <p>Your copy of LBRY is up to date.</p>)}
<p>{__("A newer version of LBRY is available.")} <Link href={newVerLink} label={__("Download now!")} /></p>
: <p>{__("Your copy of LBRY is up to date.")}</p>)}
{ this.state.uiVersion && ver ?
<table className="table-standard">
<tbody>
<tr>
<th>daemon (lbrynet)</th>
<th>{__("daemon (lbrynet)")}</th>
<td>{ver.lbrynet_version}</td>
</tr>
<tr>
<th>wallet (lbryum)</th>
<th>{__("wallet (lbryum)")}</th>
<td>{ver.lbryum_version}</td>
</tr>
<tr>
<th>interface</th>
<th>{__("interface")}</th>
<td>{this.state.uiVersion}</td>
</tr>
<tr>
<th>Platform</th>
<th>{__("Platform")}</th>
<td>{platform}</td>
</tr>
<tr>
<th>Installation ID</th>
<th>{__("Installation ID")}</th>
<td>{this.state.lbryId}</td>
</tr>
</tbody>
</table> :
<BusyMessage message="Looking up version info" />
<BusyMessage message={__("Looking up version info")} />
}
</div>
</section>
}
</main>
);
}

View file

@ -179,7 +179,7 @@ class PublishPage extends React.Component {
}
if (!lbryuri.isValidName(rawName, false)) {
this.refs.name.showError('LBRY names must contain only letters, numbers and dashes.');
this.refs.name.showError(__("LBRY names must contain only letters, numbers and dashes."));
return;
}
@ -266,7 +266,7 @@ class PublishPage extends React.Component {
};
if (licenseType == 'copyright') {
newState.copyrightNotice = 'All rights reserved.'
newState.copyrightNotice = __("All rights reserved.")
}
this.setState(newState);
@ -302,7 +302,7 @@ class PublishPage extends React.Component {
const newChannelName = (event.target.value.startsWith('@') ? event.target.value : '@' + event.target.value);
if (newChannelName.length > 1 && !lbryuri.isValidName(newChannelName.substr(1), false)) {
this.refs.newChannelName.showError('LBRY channel names must contain only letters, numbers and dashes.');
this.refs.newChannelName.showError(__("LBRY channel names must contain only letters, numbers and dashes."));
return;
} else {
this.refs.newChannelName.clearError()
@ -327,7 +327,7 @@ class PublishPage extends React.Component {
handleCreateChannelClick(event) {
if (this.state.newChannelName.length < 5) {
this.refs.newChannelName.showError('LBRY channel names must be at least 4 characters in length.');
this.refs.newChannelName.showError(__("LBRY channel names must be at least 4 characters in length."));
return;
}
@ -346,7 +346,7 @@ class PublishPage extends React.Component {
}, 5000);
}, (error) => {
// TODO: better error handling
this.refs.newChannelName.showError('Unable to create channel due to an internal error.');
this.refs.newChannelName.showError(__("Unable to create channel due to an internal error."));
this.setState({
creatingChannel: false,
});
@ -377,14 +377,17 @@ class PublishPage extends React.Component {
getNameBidHelpText() {
if (!this.state.name) {
return "Select a URL for this publish.";
return __("Select a URL for this publish.");
} else if (this.state.nameResolved === false) {
return "This URL is unused.";
return __("This URL is unused.");
} else if (this.state.myClaimExists) {
return "You have already used this URL. Publishing to it again will update your previous publish."
return __("You have already used this URL. Publishing to it again will update your previous publish.")
} else if (this.state.topClaimValue) {
return <span>A deposit of at least <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit ' : 'credits '}
is required to win <strong>{this.state.name}</strong>. However, you can still get a permanent URL for any amount.</span>
return <span>{__n("A deposit of at least \"%s\" credit is required to win \"%s\". However, you can still get a permanent URL for any amount."
, "A deposit of at least \"%s\" credits is required to win \"%s\". However, you can still get a permanent URL for any amount."
, this.state.topClaimValue /*pluralization param*/
, this.state.topClaimValue, this.state.name /*regular params*/
)}</span>
} else {
return '';
}
@ -401,49 +404,49 @@ class PublishPage extends React.Component {
return null;
}
const lbcInputHelp = "This LBC remains yours and the deposit can be undone at any time."
const lbcInputHelp = __("This LBC remains yours and the deposit can be undone at any time.");
return (
<main className="main--single-column">
<form onSubmit={(event) => { this.handleSubmit(event) }}>
<section className="card">
<div className="card__title-primary">
<h4>Content</h4>
<h4>{__("Content")}</h4>
<div className="card__subtitle">
What are you publishing?
{__("What are you publishing?")}
</div>
</div>
<div className="card__content">
<FormRow name="file" label="File" ref="file" type="file" onChange={(event) => { this.onFileChange(event) }}
helper={this.state.myClaimExists ? "If you don't choose a file, the file from your existing claim will be used." : null}/>
helper={this.state.myClaimExists ? __("If you don't choose a file, the file from your existing claim will be used.") : null}/>
</div>
{ !this.state.hasFile ? '' :
<div>
<div className="card__content">
<FormRow label="Title" type="text" ref="meta_title" name="title" placeholder="Titular Title" />
<FormRow label={__("Title")} type="text" ref="meta_title" name="title" placeholder={__("Title")} />
</div>
<div className="card__content">
<FormRow type="text" label="Thumbnail URL" ref="meta_thumbnail" name="thumbnail" placeholder="http://spee.ch/mylogo" />
<FormRow type="text" label={__("Thumbnail URL")} ref="meta_thumbnail" name="thumbnail" placeholder="http://spee.ch/mylogo" />
</div>
<div className="card__content">
<FormRow label="Description" type="textarea" ref="meta_description" name="description" placeholder="Description of your content" />
<FormRow label={__("Description")} type="textarea" ref="meta_description" name="description" placeholder={__("Description of your content")} />
</div>
<div className="card__content">
<FormRow label="Language" type="select" defaultValue="en" ref="meta_language" name="language">
<option value="en">English</option>
<option value="zh">Chinese</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="jp">Japanese</option>
<option value="ru">Russian</option>
<option value="es">Spanish</option>
<FormRow label={__("Language")} type="select" defaultValue="en" ref="meta_language" name="language">
<option value="en">{__("English")}</option>
<option value="zh">{__("Chinese")}</option>
<option value="fr">{__("French")}</option>
<option value="de">{__("German")}</option>
<option value="jp">{__("Japanese")}</option>
<option value="ru">{__("Russian")}</option>
<option value="es">{__("Spanish")}</option>
</FormRow>
</div>
<div className="card__content">
<FormRow type="select" label="Maturity" defaultValue="en" ref="meta_nsfw" name="nsfw">
<FormRow type="select" label={__("Maturity")} defaultValue="en" ref="meta_nsfw" name="nsfw">
{/* <option value=""></option> */}
<option value="0">All Ages</option>
<option value="1">Adults Only</option>
<option value="0">{__("All Ages")}</option>
<option value="1">{__("Adults Only")}</option>
</FormRow>
</div>
</div>}
@ -451,73 +454,73 @@ class PublishPage extends React.Component {
<section className="card">
<div className="card__title-primary">
<h4>Access</h4>
<h4>{__("Access")}</h4>
<div className="card__subtitle">
How much does this content cost?
{__("How much does this content cost?")}
</div>
</div>
<div className="card__content">
<div className="form-row__label-row">
<label className="form-row__label">Price</label>
<label className="form-row__label">{__("Price")}</label>
</div>
<FormRow label="Free" type="radio" name="isFree" value="1" onChange={ () => { this.handleFeePrefChange(false) } } defaultChecked={!this.state.isFee} />
<FormField type="radio" name="isFree" label={!this.state.isFee ? 'Choose price...' : 'Price ' }
<FormRow label={__("Free")} type="radio" name="isFree" value="1" onChange={ () => { this.handleFeePrefChange(false) } } defaultChecked={!this.state.isFee} />
<FormField type="radio" name="isFree" label={!this.state.isFee ? __('Choose price...') : __('Price ') }
onChange={ () => { this.handleFeePrefChange(true) } } defaultChecked={this.state.isFee} />
<span className={!this.state.isFee ? 'hidden' : ''}>
<FormField type="number" className="form-field__input--inline" step="0.01" placeholder="1.00" onChange={(event) => this.handleFeeAmountChange(event)} /> <FormField type="select" onChange={(event) => { this.handleFeeCurrencyChange(event) }}>
<option value="USD">US Dollars</option>
<option value="LBC">LBRY credits</option>
<option value="USD">{__("US Dollars")}</option>
<option value="LBC">{__("LBRY credits")}</option>
</FormField>
</span>
{ this.state.isFee ?
<div className="form-field__helper">
If you choose to price this content in dollars, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase.
{__("If you choose to price this content in dollars, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase.")}
</div> : '' }
<FormRow label="License" type="select" ref="meta_license" name="license" onChange={(event) => { this.handleLicenseChange(event) }}>
<option></option>
<option>Public Domain</option>
<option data-url="https://creativecommons.org/licenses/by/4.0/legalcode">Creative Commons Attribution 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-sa/4.0/legalcode">Creative Commons Attribution-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nd/4.0/legalcode">Creative Commons Attribution-NoDerivatives 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc/4.0/legalcode">Creative Commons Attribution-NonCommercial 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International</option>
<option data-license-type="copyright" {... this.state.copyrightChosen ? {value: this.state.copyrightNotice} : {}}>Copyrighted...</option>
<option data-license-type="other" {... this.state.otherLicenseChosen ? {value: this.state.otherLicenseDescription} : {}}>Other...</option>
<option>{__("Public Domain")}</option>
<option data-url="https://creativecommons.org/licenses/by/4.0/legalcode">{__("Creative Commons Attribution 4.0 International")}</option>
<option data-url="https://creativecommons.org/licenses/by-sa/4.0/legalcode">{__("Creative Commons Attribution-ShareAlike 4.0 International")}</option>
<option data-url="https://creativecommons.org/licenses/by-nd/4.0/legalcode">{__("Creative Commons Attribution-NoDerivatives 4.0 International")}</option>
<option data-url="https://creativecommons.org/licenses/by-nc/4.0/legalcode">{__("Creative Commons Attribution-NonCommercial 4.0 International")}</option>
<option data-url="https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode">{__("Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International")}</option>
<option data-url="https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode">{__("Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International")}</option>
<option data-license-type="copyright" {... this.state.copyrightChosen ? {value: this.state.copyrightNotice} : {}}>{__("Copyrighted...")}</option>
<option data-license-type="other" {... this.state.otherLicenseChosen ? {value: this.state.otherLicenseDescription} : {}}>{__("Other...")}</option>
</FormRow>
<FormField type="hidden" ref="meta_license_url" name="license_url" value={this.getLicenseUrl()} />
{this.state.copyrightChosen
? <FormRow label="Copyright notice" type="text" name="copyright-notice"
? <FormRow label={__("Copyright notice")} type="text" name="copyright-notice"
value={this.state.copyrightNotice} onChange={(event) => { this.handleCopyrightNoticeChange(event) }} />
: null}
{this.state.otherLicenseChosen ?
<FormRow label="License description" type="text" name="other-license-description" onChange={(event) => { this.handleOtherLicenseDescriptionChange() }} />
<FormRow label={__("License description")} type="text" name="other-license-description" onChange={(event) => { this.handleOtherLicenseDescriptionChange() }} />
: null}
{this.state.otherLicenseChosen ?
<FormRow label="License URL" type="text" name="other-license-url" onChange={(event) => { this.handleOtherLicenseUrlChange(event) }} />
<FormRow label={__("License URL")} type="text" name="other-license-url" onChange={(event) => { this.handleOtherLicenseUrlChange(event) }} />
: null}
</div>
</section>
<section className="card">
<div className="card__title-primary">
<h4>Identity</h4>
<h4>{__("Identity")}</h4>
<div className="card__subtitle">
Who created this content?
{__("Who created this content?")}
</div>
</div>
<div className="card__content">
<FormRow type="select" tabIndex="1" onChange={(event) => { this.handleChannelChange(event) }} value={this.state.channel}>
<option key="anonymous" value="anonymous">Anonymous</option>
<option key="anonymous" value="anonymous">{__("Anonymous")}</option>
{this.state.channels.map(({name}) => <option key={name} value={name}>{name}</option>)}
<option key="new" value="new">New identity...</option>
<option key="new" value="new">{__("New identity...")}</option>
</FormRow>
</div>
{this.state.channel == 'new' ?
<div className="card__content">
<FormRow label="Name" type="text" onChange={(event) => { this.handleNewChannelNameChange(event) }} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
<FormRow label={__("Name")} type="text" onChange={(event) => { this.handleNewChannelNameChange(event) }} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
value={this.state.newChannelName} />
<FormRow label="Deposit"
<FormRow label={__("Deposit")}
postfix="LBC"
step="0.01"
type="number"
@ -525,7 +528,7 @@ class PublishPage extends React.Component {
onChange={(event) => { this.handleNewChannelBidChange(event) }}
value={this.state.newChannelBid} />
<div className="form-row-submit">
<Link button="primary" label={!this.state.creatingChannel ? 'Create identity' : 'Creating identity...'} onClick={(event) => { this.handleCreateChannelClick(event) }} disabled={this.state.creatingChannel} />
<Link button="primary" label={!this.state.creatingChannel ? __("Create identity") : __("Creating identity...")} onClick={(event) => { this.handleCreateChannelClick(event) }} disabled={this.state.creatingChannel} />
</div>
</div>
: null}
@ -534,8 +537,8 @@ class PublishPage extends React.Component {
<section className="card">
<div className="card__title-primary">
<h4>Address</h4>
<div className="card__subtitle">Where should this content permanently reside? <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>
<h4>{__("Address")}</h4>
<div className="card__subtitle">{__("Where should this content permanently reside?")} <Link label={__("Read more")} href="https://lbry.io/faq/naming" />.</div>
</div>
<div className="card__content">
<FormRow prefix="lbry://" type="text" ref="name" placeholder="myname" value={this.state.rawName} onChange={(event) => { this.handleNameChange(event) }}
@ -546,7 +549,7 @@ class PublishPage extends React.Component {
<FormRow ref="bid"
type="number"
step="0.01"
label="Deposit"
label={__("Deposit")}
postfix="LBC"
onChange={(event) => { this.handleBidChange(event) }}
value={this.state.bid}
@ -557,30 +560,30 @@ class PublishPage extends React.Component {
<section className="card">
<div className="card__title-primary">
<h4>Terms of Service</h4>
<h4>{__("Terms of Service")}</h4>
</div>
<div className="card__content">
<FormRow label={
<span>I agree to the <Link href="https://www.lbry.io/termsofservice" label="LBRY terms of service" checked={this.state.TOSAgreed} /></span>
<span>{__("I agree to the")} <Link href="https://www.lbry.io/termsofservice" label={__("LBRY terms of service")} checked={this.state.TOSAgreed} /></span>
} type="checkbox" name="tos_agree" ref={(field) => { this.refs.tos_agree = field }} onChange={(event) => { this.handleTOSChange(event)}} />
</div>
</section>
<div className="card-series-submit">
<Link button="primary" label={!this.state.submitting ? 'Publish' : 'Publishing...'} onClick={(event) => { this.handleSubmit(event) }} disabled={this.state.submitting} />
<Link button="cancel" onClick={this.props.back} label="Cancel" />
<Link button="primary" label={!this.state.submitting ? __("Publish") : __("Publishing...")} onClick={(event) => { this.handleSubmit(event) }} disabled={this.state.submitting} />
<Link button="cancel" onClick={this.props.back} label={__("Cancel")} />
<input type="submit" className="hidden" />
</div>
</form>
<Modal isOpen={this.state.modal == 'publishStarted'} contentLabel="File published"
<Modal isOpen={this.state.modal == 'publishStarted'} contentLabel={__("File published")}
onConfirmed={(event) => { this.handlePublishStartedConfirmed(event) }}>
<p>Your file has been published to LBRY at the address <code>lbry://{this.state.name}</code>!</p>
<p>The file will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.</p>
<p>{__("Your file has been published to LBRY at the address")} <code>lbry://{this.state.name}</code>!</p>
<p>{__('The file will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.')}</p>
</Modal>
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error publishing file"
<Modal isOpen={this.state.modal == 'error'} contentLabel={__("Error publishing file")}
onConfirmed={(event) => { this.closeModal(event) }}>
The following error occurred when attempting to publish your file: {this.state.errorMessage}
{__("The following error occurred when attempting to publish your file")}: {this.state.errorMessage}
</Modal>
</main>
);

View file

@ -40,25 +40,25 @@ class ReportPage extends React.Component {
<main className="main--single-column">
<section className="card">
<div className="card__content">
<h3>Report an Issue</h3>
<p>Please describe the problem you experienced and any information you think might be useful to us. Links to screenshots are great!</p>
<h3>{__("Report an Issue")}</h3>
<p>{__("Please describe the problem you experienced and any information you think might be useful to us. Links to screenshots are great!")}</p>
<div className="form-row">
<FormRow type="textarea" ref={(t) => this._messageArea = t} rows="10" name="message" placeholder="Description of your issue" />
<FormRow type="textarea" ref={(t) => this._messageArea = t} rows="10" name="message" placeholder={__("Description of your issue")} />
</div>
<div className="form-row form-row-submit">
<button onClick={(event) => { this.submitMessage(event) }} className={'button-block button-primary ' + (this.state.submitting ? 'disabled' : '')}>{this.state.submitting ? 'Submitting...' : 'Submit Report'}</button>
<button onClick={(event) => { this.submitMessage(event) }} className={'button-block button-primary ' + (this.state.submitting ? 'disabled' : '')}>{this.state.submitting ? __('Submitting...') : __('Submit Report')}</button>
</div>
</div>
</section>
<section className="card">
<div className="card__content">
<h3>Developer?</h3>
You can also <Link href="https://github.com/lbryio/lbry/issues" label="submit an issue on GitHub"/>.
<h3>{__("Developer?")}</h3>
{__("You can also")} <Link href="https://github.com/lbryio/lbry/issues" label={__("submit an issue on GitHub")}/>.
</div>
</section>
<Modal isOpen={this.state.modal == 'submitted'} contentLabel="Bug report submitted"
<Modal isOpen={this.state.modal == 'submitted'} contentLabel={__("Bug report submitted")}
onConfirmed={(event) => { this.closeModal(event) }}>
Your bug report has been submitted! Thank you for your feedback.
{__("Your bug report has been submitted! Thank you for your feedback.")}
</Modal>
</main>
);

View file

@ -24,7 +24,7 @@ export class RewardTile extends React.Component {
</div>
<div className="card__actions">
{this.props.claimed
? <span><Icon icon="icon-check" /> Reward claimed.</span>
? <span><Icon icon="icon-check" /> {__("Reward claimed.")}</span>
: <RewardLink {...this.props} />}
</div>
<div className="card__content">{this.props.description}</div>
@ -64,9 +64,9 @@ export class RewardsPage extends React.Component {
<SubHeader />
<div>
{!this.state.userRewards
? (this.state.failed ? <div className="empty">Failed to load rewards.</div> : '')
? (this.state.failed ? <div className="empty">{__("Failed to load rewards.")}</div> : '')
: this.state.userRewards.map(({reward_type, reward_title, reward_description, transaction_id, reward_amount}) => {
return <RewardTile key={reward_type} onRewardClaim={this.loadRewards} type={reward_type} title={reward_title} description={reward_description} claimed={!!transaction_id} value={reward_amount} />;
return <RewardTile key={reward_type} onRewardClaim={this.loadRewards} type={reward_type} title={__(reward_title)} description={__(reward_description)} claimed={!!transaction_id} value={reward_amount} />;
})}
</div>
</main>

View file

@ -17,14 +17,14 @@ class SearchPage extends React.Component{
{ lbryuri.isValid(query) ?
<section className="section-spaced">
<h3 className="card-row__header">
Exact URL <ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc."
{__("Exact URL")} <ToolTip label="?" body={__("This is the resolution of a LBRY URL and not controlled by LBRY Inc.")}
className="tooltip--header" />
</h3>
<FileTile uri={lbryuri.normalize(query)} showEmpty={FileTile.SHOW_EMPTY_PUBLISH} />
</section> : '' }
<section className="section-spaced">
<h3 className="card-row__header">
Search Results for {query} <ToolTip label="?" body="These search results are provided by LBRY, Inc."
{__("Search Results for")} {query} <ToolTip label="?" body={__("These search results are provided by LBRY, Inc.")}
className="tooltip--header" />
</h3>
<FileListSearch query={query} />

View file

@ -3,6 +3,7 @@ import {FormField, FormRow} from 'component/form.js';
import SubHeader from 'component/subHeader'
import lbry from 'lbry.js';
class SettingsPage extends React.Component {
constructor(props) {
super(props);
@ -14,6 +15,7 @@ class SettingsPage extends React.Component {
isMaxDownload: daemonSettings && daemonSettings.max_download != 0,
showNsfw: lbry.getClientSetting('showNsfw'),
showUnavailable: lbry.getClientSetting('showUnavailable'),
language: lbry.getClientSetting('language'),
}
}
@ -68,6 +70,12 @@ class SettingsPage extends React.Component {
lbry.setClientSetting('showNsfw', event.target.checked);
}
// onLanguageChange(language) {
// lbry.setClientSetting('language', language);
// i18n.setLocale(language);
// this.setState({language: language})
// }
onShowUnavailableChange(event) {
}
@ -78,7 +86,7 @@ class SettingsPage extends React.Component {
} = this.props
if (!daemonSettings) {
return <main className="main--single-column"><span className="empty">Failed to load settings.</span></main>;
return <main className="main--single-column"><span className="empty">{__("Failed to load settings.")}</span></main>;
}
/*
<section className="card">
@ -98,33 +106,33 @@ class SettingsPage extends React.Component {
<SubHeader />
<section className="card">
<div className="card__content">
<h3>Download Directory</h3>
<h3>{__("Download Directory")}</h3>
</div>
<div className="card__content">
<FormRow type="directory"
name="download_directory"
defaultValue={daemonSettings.download_directory}
helper="LBRY downloads will be saved here."
helper={__("LBRY downloads will be saved here.")}
onChange={this.onDownloadDirChange.bind(this)} />
</div>
</section>
<section className="card">
<div className="card__content">
<h3>Bandwidth Limits</h3>
<h3>{__("Bandwidth Limits")}</h3>
</div>
<div className="card__content">
<div className="form-row__label-row"><div className="form-field__label">Max Upload</div></div>
<div className="form-row__label-row"><div className="form-field__label">{__("Max Upload")}</div></div>
<FormRow type="radio"
name="max_upload_pref"
onChange={() => { this.onMaxUploadPrefChange(false) }}
defaultChecked={!this.state.isMaxUpload}
label="Unlimited" />
label={__("Unlimited")} />
<div className="form-row">
<FormField type="radio"
name="max_upload_pref"
onChange={() => { this.onMaxUploadPrefChange(true) }}
defaultChecked={this.state.isMaxUpload}
label={ this.state.isMaxUpload ? 'Up to' : 'Choose limit...' } />
label={ this.state.isMaxUpload ? __("Up to") : __("Choose limit...") } />
{ this.state.isMaxUpload ?
<FormField type="number"
min="0"
@ -141,8 +149,8 @@ class SettingsPage extends React.Component {
</div>
</div>
<div className="card__content">
<div className="form-row__label-row"><div className="form-field__label">Max Download</div></div>
<FormRow label="Unlimited"
<div className="form-row__label-row"><div className="form-field__label">{__("Max Download")}</div></div>
<FormRow label={__("Unlimited")}
type="radio"
name="max_download_pref"
onChange={() => { this.onMaxDownloadPrefChange(false) }}
@ -152,7 +160,7 @@ class SettingsPage extends React.Component {
name="max_download_pref"
onChange={() => { this.onMaxDownloadPrefChange(true) }}
defaultChecked={this.state.isMaxDownload}
label={ this.state.isMaxDownload ? 'Up to' : 'Choose limit...' } />
label={ this.state.isMaxDownload ? __("Up to") : __("Choose limit...") } />
{ this.state.isMaxDownload ?
<FormField type="number"
min="0"
@ -171,29 +179,53 @@ class SettingsPage extends React.Component {
</section>
<section className="card">
<div className="card__content">
<h3>Content</h3>
<h3>{__("Content")}</h3>
</div>
<div className="card__content">
<FormRow type="checkbox"
onChange={this.onShowUnavailableChange.bind(this)}
defaultChecked={this.state.showUnavailable}
label="Show unavailable content in search results" />
label={__("Show unavailable content in search results")} />
</div>
<div className="card__content">
<FormRow label="Show NSFW content" type="checkbox"
<FormRow label={__("Show NSFW content")} type="checkbox"
onChange={this.onShowNsfwChange.bind(this)} defaultChecked={this.state.showNsfw}
helper="NSFW content may include nudity, intense sexuality, profanity, or other adult content. By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction. " />
helper={__("NSFW content may include nudity, intense sexuality, profanity, or other adult content. By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ")} />
</div>
</section>
{/*}
<section className="card">
<div className="card__content">
<h3>Share Diagnostic Data</h3>
<h3>{__("Language")}</h3>
</div>
<div className="card__content">
<div className="form-row">
<FormField type="radio"
name="language"
label={__("English")}
onChange={() => { this.onLanguageChange('en') }}
defaultChecked={this.state.language=='en'} />
</div>
<div className="form-row">
<FormField type="radio"
name="language"
label="Serbian"
onChange={() => { this.onLanguageChange('rs') }}
defaultChecked={this.state.language=='rs'} />
</div>
</div>
</section>*/}
<section className="card">
<div className="card__content">
<h3>{__("Share Diagnostic Data")}</h3>
</div>
<div className="card__content">
<FormRow type="checkbox"
onChange={this.onShareDataChange.bind(this)}
defaultChecked={daemonSettings.share_usage_data}
label="Help make LBRY better by contributing diagnostic data about my usage" />
label={__("Help make LBRY better by contributing diagnostic data about my usage")} />
</div>
</section>
</main>

View file

@ -43,8 +43,8 @@ class ShowPage extends React.Component{
<div className="card__title-identity"><h1>{uri}</h1></div>
</div>
<div className="card__content">
{ isResolvingUri && <BusyMessage message="Loading magic decentralized data..." /> }
{ claim === null && <span className="empty">There's nothing at this location.</span> }
{ isResolvingUri && <BusyMessage message={__("Loading magic decentralized data...")} /> }
{ claim === null && <span className="empty">{__("There's nothing at this location.")}</span> }
</div>
</section>
}
@ -61,4 +61,4 @@ class ShowPage extends React.Component{
}
}
export default ShowPage
export default ShowPage

View file

@ -9,8 +9,8 @@ class StartPage extends React.Component {
render() {
return (
<main className="main--single-column">
<h3>LBRY is Closed</h3>
<Link href="lbry://lbry" label="Click here to start LBRY" />
<h3>{__("LBRY is Closed")}</h3>
<Link href="lbry://lbry" label={__("Click here to start LBRY")} />
</main>
);
}

View file

@ -19,7 +19,7 @@ const WalletPage = (props) => {
<SubHeader />
<section className="card">
<div className="card__title-primary">
<h3>Balance</h3>
<h3>{__("Balance")}</h3>
</div>
<div className="card__content">
<CreditAmount amount={balance} precision={8} />

View file

@ -7,13 +7,13 @@ import {
function rewardMessage(type, amount) {
return {
new_developer: `You earned ${amount} for registering as a new developer.`,
new_user: `You earned ${amount} LBC new user reward.`,
confirm_email: `You earned ${amount} LBC for verifying your email address.`,
new_channel: `You earned ${amount} LBC for creating a publisher identity.`,
first_stream: `You earned ${amount} LBC for streaming your first video.`,
many_downloads: `You earned ${amount} LBC for downloading some of the things.`,
first_publish: `You earned ${amount} LBC for making your first publication.`,
new_developer: __("You earned %s for registering as a new developer.", amount),
new_user: __("You earned %s LBC new user reward.", amount),
confirm_email: __("You earned %s LBC for verifying your email address.", amount),
new_channel: __("You earned %s LBC for creating a publisher identity.", amount),
first_stream: __("You earned %s LBC for streaming your first video.", amount),
many_downloads: __("You earned %s LBC for downloading some of the things.", amount),
first_publish: __("You earned %s LBC for making your first publication.", amount),
}[type];
}
@ -82,7 +82,7 @@ rewards.claimReward = function (type) {
function requestReward(resolve, reject, params) {
if (!lbryio.enabled) {
reject(new Error("Rewards are not enabled."))
reject(new Error(__("Rewards are not enabled.")))
return;
}
lbryio.call('reward', 'new', params, 'post').then(({reward_amount}) => {
@ -97,7 +97,7 @@ rewards.claimReward = function (type) {
// Display global notice
const action = doShowSnackBar({
message,
linkText: "Show All",
linkText: __("Show All"),
linkTarget: "/rewards",
isError: false,
})
@ -126,7 +126,7 @@ rewards.claimReward = function (type) {
params.transaction_id = claim.txid;
requestReward(resolve, reject, params)
} else {
reject(new Error("Please create a channel identity first."))
reject(new Error(__("Please create a channel identity first.")))
}
}).catch(reject)
break;
@ -141,8 +141,8 @@ rewards.claimReward = function (type) {
requestReward(resolve, reject, params)
} else {
reject(claims.length ?
new Error("Please publish something and wait for confirmation by the network to claim this reward.") :
new Error("Please publish something to claim this reward."))
new Error(__("Please publish something and wait for confirmation by the network to claim this reward.")) :
new Error(__("Please publish something to claim this reward.")))
}
}).catch(reject)
break;

View file

@ -38,35 +38,28 @@ export const selectPageTitle = createSelector(
selectCurrentParams,
(page, params) => {
switch (page) {
case 'search':
return params.query ? `Search results for ${params.query}` : 'Search'
case 'settings':
return 'Settings'
case 'help':
return 'Help'
case 'report':
return 'Report'
case 'wallet':
case 'send':
case 'receive':
case 'rewards':
return page.charAt(0).toUpperCase() + page.slice(1)
case 'start':
case 'publish':
case 'help':
case 'developer':
return __(page.charAt(0).toUpperCase() + page.slice(1))
case 'search':
return params.query ? __("Search results for %s", params.query) : __('Search')
case 'show':
return lbryuri.normalize(params.uri)
case 'downloaded':
return 'Downloads & Purchases'
return __('Downloads & Purchases')
case 'published':
return 'Publishes'
case 'start':
return 'Start'
case 'publish':
return 'Publish'
case 'help':
return 'Help'
case 'developer':
return 'Developer'
return __('Publishes')
case 'discover':
return 'Home'
return __('Home')
default:
return '';
}
@ -142,22 +135,22 @@ export const selectHeaderLinks = createSelector(
case 'receive':
case 'rewards':
return {
'wallet': 'Overview',
'send': 'Send',
'receive': 'Receive',
'rewards': 'Rewards',
'wallet': __('Overview'),
'send': __('Send'),
'receive': __('Receive'),
'rewards': __('Rewards'),
};
case 'downloaded':
case 'published':
return {
'downloaded': 'Downloaded',
'published': 'Published',
'downloaded': __('Downloaded'),
'published': __('Published'),
};
case 'settings':
case 'help':
return {
'settings': 'Settings',
'help': 'Help',
'settings': __('Settings'),
'help': __('Help'),
}
default:
return null;
@ -203,4 +196,4 @@ export const selectSnackBar = createSelector(
export const selectSnackBarSnacks = createSelector(
selectSnackBar,
(snackBar) => snackBar.snacks || []
)
)

View file

@ -34,7 +34,8 @@
"redux-logger": "^3.0.1",
"redux-thunk": "^2.2.0",
"render-media": "^2.10.0",
"reselect": "^3.0.0"
"reselect": "^3.0.0",
"y18n": "^3.2.1"
},
"devDependencies": {
"babel": "^6.5.2",