fix(locale): remove hard coded strings (#3193)

This commit is contained in:
tiuweehan 2020-02-04 20:49:47 +08:00 committed by GitHub
parent 18e284ece8
commit fc91bf8781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 108 additions and 39 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ npm-debug.log
.tern-project .tern-project
yarn-error.log yarn-error.log
.vscode/ .vscode/
.idea/
manifest.yml manifest.yml
.imdone/ .imdone/
website/data/contributors.json website/data/contributors.json

View File

@ -17,6 +17,7 @@ export default class BitbucketAuthenticationPage extends React.Component {
authEndpoint: PropTypes.string, authEndpoint: PropTypes.string,
config: PropTypes.object.isRequired, config: PropTypes.object.isRequired,
clearHash: PropTypes.func, clearHash: PropTypes.func,
t: PropTypes.func.isRequired,
}; };
state = {}; state = {};
@ -70,7 +71,7 @@ export default class BitbucketAuthenticationPage extends React.Component {
}; };
render() { render() {
const { inProgress, config } = this.props; const { inProgress, config, t } = this.props;
return ( return (
<AuthenticationPage <AuthenticationPage
@ -82,7 +83,7 @@ export default class BitbucketAuthenticationPage extends React.Component {
renderButtonContent={() => ( renderButtonContent={() => (
<React.Fragment> <React.Fragment>
<LoginButtonIcon type="bitbucket" /> <LoginButtonIcon type="bitbucket" />
{inProgress ? 'Logging in...' : 'Login with Bitbucket'} {inProgress ? t('auth.loggingIn') : t('auth.loginWithBitbucket')}
</React.Fragment> </React.Fragment>
)} )}
/> />

View File

@ -29,6 +29,7 @@ export default class GitHubAuthenticationPage extends React.Component {
authEndpoint: PropTypes.string, authEndpoint: PropTypes.string,
config: PropTypes.object.isRequired, config: PropTypes.object.isRequired,
clearHash: PropTypes.func, clearHash: PropTypes.func,
t: PropTypes.func.isRequired,
}; };
state = {}; state = {};
@ -92,15 +93,17 @@ export default class GitHubAuthenticationPage extends React.Component {
}); });
}; };
renderLoginButton = () => renderLoginButton = () => {
this.props.inProgress || this.state.findingFork ? ( const { inProgress, t } = this.props;
'Logging in...' return inProgress || this.state.findingFork ? (
t('auth.loggingIn')
) : ( ) : (
<React.Fragment> <React.Fragment>
<LoginButtonIcon type="github" /> <LoginButtonIcon type="github" />
{' Login with GitHub'} {t('auth.loginWithGitHub')}
</React.Fragment> </React.Fragment>
); );
};
getAuthenticationPageRenderArgs() { getAuthenticationPageRenderArgs() {
const { requestingFork } = this.state; const { requestingFork } = this.state;

View File

@ -17,6 +17,7 @@ export default class GitLabAuthenticationPage extends React.Component {
authEndpoint: PropTypes.string, authEndpoint: PropTypes.string,
config: PropTypes.object.isRequired, config: PropTypes.object.isRequired,
clearHash: PropTypes.func, clearHash: PropTypes.func,
t: PropTypes.func.isRequired,
}; };
state = {}; state = {};
@ -68,7 +69,7 @@ export default class GitLabAuthenticationPage extends React.Component {
}; };
render() { render() {
const { inProgress, config } = this.props; const { inProgress, config, t } = this.props;
return ( return (
<AuthenticationPage <AuthenticationPage
onLogin={this.handleLogin} onLogin={this.handleLogin}
@ -78,7 +79,8 @@ export default class GitLabAuthenticationPage extends React.Component {
siteUrl={config.site_url} siteUrl={config.site_url}
renderButtonContent={() => ( renderButtonContent={() => (
<React.Fragment> <React.Fragment>
<LoginButtonIcon type="gitlab" /> {inProgress ? 'Logging in...' : 'Login with GitLab'} <LoginButtonIcon type="gitlab" />{' '}
{inProgress ? t('auth.loggingIn') : t('auth.loginWithGitLab')}
</React.Fragment> </React.Fragment>
)} )}
/> />

View File

@ -38,6 +38,7 @@ export default class AuthenticationPage extends React.Component {
onLogin: PropTypes.func.isRequired, onLogin: PropTypes.func.isRequired,
inProgress: PropTypes.bool, inProgress: PropTypes.bool,
config: PropTypes.object.isRequired, config: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
}; };
handleLogin = e => { handleLogin = e => {
@ -46,13 +47,13 @@ export default class AuthenticationPage extends React.Component {
}; };
render() { render() {
const { config, inProgress } = this.props; const { config, inProgress, t } = this.props;
return ( return (
<StyledAuthenticationPage> <StyledAuthenticationPage>
<PageLogoIcon size="300px" type="netlify-cms" /> <PageLogoIcon size="300px" type="netlify-cms" />
<LoginButton disabled={inProgress} onClick={this.handleLogin}> <LoginButton disabled={inProgress} onClick={this.handleLogin}>
{inProgress ? 'Logging in...' : 'Login'} {inProgress ? t('auth.loggingIn') : t('auth.login')}
</LoginButton> </LoginButton>
{config.site_url && <GoBackButton href={config.site_url}></GoBackButton>} {config.site_url && <GoBackButton href={config.site_url}></GoBackButton>}
</StyledAuthenticationPage> </StyledAuthenticationPage>

View File

@ -38,6 +38,7 @@ export default class AuthenticationPage extends React.Component {
onLogin: PropTypes.func.isRequired, onLogin: PropTypes.func.isRequired,
inProgress: PropTypes.bool, inProgress: PropTypes.bool,
config: PropTypes.object.isRequired, config: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
}; };
componentDidMount() { componentDidMount() {
@ -56,13 +57,13 @@ export default class AuthenticationPage extends React.Component {
}; };
render() { render() {
const { config, inProgress } = this.props; const { config, inProgress, t } = this.props;
return ( return (
<StyledAuthenticationPage> <StyledAuthenticationPage>
<PageLogoIcon size="300px" type="netlify-cms" /> <PageLogoIcon size="300px" type="netlify-cms" />
<LoginButton disabled={inProgress} onClick={this.handleLogin}> <LoginButton disabled={inProgress} onClick={this.handleLogin}>
{inProgress ? 'Logging in...' : 'Login'} {inProgress ? t('auth.loggingIn') : t('auth.login')}
</LoginButton> </LoginButton>
{config.site_url && <GoBackButton href={config.site_url}></GoBackButton>} {config.site_url && <GoBackButton href={config.site_url}></GoBackButton>}
</StyledAuthenticationPage> </StyledAuthenticationPage>

View File

@ -182,7 +182,9 @@ class EditorControl extends React.Component {
hasErrors={!!errors} hasErrors={!!errors}
htmlFor={this.uniqueFieldId} htmlFor={this.uniqueFieldId}
> >
{`${field.get('label', field.get('name'))}${isFieldOptional ? ' (optional)' : ''}`} {`${field.get('label', field.get('name'))}${
isFieldOptional ? ` (${t('editor.editorControl.field.optional')})` : ''
}`}
</FieldLabel> </FieldLabel>
<Widget <Widget
classNameWrapper={cx( classNameWrapper={cx(

View File

@ -3,6 +3,9 @@ const en = {
login: 'Login', login: 'Login',
loggingIn: 'Logging in...', loggingIn: 'Logging in...',
loginWithNetlifyIdentity: 'Login with Netlify Identity', loginWithNetlifyIdentity: 'Login with Netlify Identity',
loginWithBitbucket: 'Login with Bitbucket',
loginWithGitHub: 'Login with GitHub',
loginWithGitLab: 'Login with GitLab',
errors: { errors: {
email: 'Make sure to enter your email.', email: 'Make sure to enter your email.',
password: 'Please enter your password.', password: 'Please enter your password.',
@ -44,6 +47,11 @@ const en = {
}, },
}, },
editor: { editor: {
editorControl: {
field: {
optional: 'optional',
},
},
editorControlPane: { editorControlPane: {
widget: { widget: {
required: '%{fieldLabel} is required.', required: '%{fieldLabel} is required.',
@ -105,6 +113,20 @@ const en = {
deployButtonLabel: 'View Live', deployButtonLabel: 'View Live',
}, },
editorWidgets: { editorWidgets: {
markdown: {
richText: 'Rich Text',
markdown: 'Markdown',
},
image: {
choose: 'Choose an image',
chooseDifferent: 'Choose different image',
remove: 'Remove image',
},
file: {
choose: 'Choose a file',
chooseDifferent: 'Choose different file',
remove: 'Remove file',
},
unknownControl: { unknownControl: {
noControl: "No control for widget '%{widget}'.", noControl: "No control for widget '%{widget}'.",
}, },

View File

@ -102,6 +102,20 @@ const ja = {
deployButtonLabel: 'ライブで見る', deployButtonLabel: 'ライブで見る',
}, },
editorWidgets: { editorWidgets: {
markdown: {
richText: 'リッチテキスト',
markdown: 'マークダウン',
},
image: {
choose: '画像を選択',
chooseDifferent: '他の画像を選択',
remove: '画像を削除',
},
file: {
choose: 'ファイルを選択',
chooseDifferent: '他のファイルを選択',
remove: 'ファイルを削除',
},
unknownControl: { unknownControl: {
noControl: "'%{widget}'はウィジェットとして利用できません。", noControl: "'%{widget}'はウィジェットとして利用できません。",
}, },

View File

@ -33,6 +33,11 @@ const pl = {
}, },
}, },
editor: { editor: {
editorControl: {
field: {
optional: 'opcjonalne',
},
},
editorControlPane: { editorControlPane: {
widget: { widget: {
required: '%{fieldLabel} jest wymagane.', required: '%{fieldLabel} jest wymagane.',

View File

@ -104,6 +104,7 @@ export default function withFileControl({ forImage } = {}) {
onRemoveMediaControl: PropTypes.func.isRequired, onRemoveMediaControl: PropTypes.func.isRequired,
classNameWrapper: PropTypes.string.isRequired, classNameWrapper: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
t: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {
@ -236,37 +237,40 @@ export default function withFileControl({ forImage } = {}) {
); );
}; };
renderSelection = subject => ( renderSelection = subject => {
<div> const { t } = this.props;
{forImage ? this.renderImages() : null} return (
<div> <div>
{forImage ? null : this.renderFileLinks()} {forImage ? this.renderImages() : null}
<FileWidgetButton onClick={this.handleChange}> <div>
Choose different {subject} {forImage ? null : this.renderFileLinks()}
</FileWidgetButton> <FileWidgetButton onClick={this.handleChange}>
<FileWidgetButtonRemove onClick={this.handleRemove}> {t(`editor.editorWidgets.${subject}.chooseDifferent`)}
Remove {subject} </FileWidgetButton>
</FileWidgetButtonRemove> <FileWidgetButtonRemove onClick={this.handleRemove}>
{t(`editor.editorWidgets.${subject}.remove`)}
</FileWidgetButtonRemove>
</div>
</div> </div>
</div> );
); };
renderNoSelection = (subject, article) => ( renderNoSelection = subject => {
<FileWidgetButton onClick={this.handleChange}> const { t } = this.props;
Choose {article} {subject} return (
</FileWidgetButton> <FileWidgetButton onClick={this.handleChange}>
); {t(`editor.editorWidgets.${subject}.choose`)}
</FileWidgetButton>
);
};
render() { render() {
const { value, classNameWrapper } = this.props; const { value, classNameWrapper } = this.props;
const subject = forImage ? 'image' : 'file'; const subject = forImage ? 'image' : 'file';
const article = forImage ? 'an' : 'a';
return ( return (
<div className={classNameWrapper}> <div className={classNameWrapper}>
<span> <span>{value ? this.renderSelection(subject) : this.renderNoSelection(subject)}</span>
{value ? this.renderSelection(subject) : this.renderNoSelection(subject, article)}
</span>
</div> </div>
); );
} }

View File

@ -101,7 +101,7 @@ export default class RawEditor extends React.Component {
}; };
render() { render() {
const { className, field } = this.props; const { className, field, t } = this.props;
return ( return (
<RawEditorContainer> <RawEditorContainer>
<EditorControlBar> <EditorControlBar>
@ -110,6 +110,7 @@ export default class RawEditor extends React.Component {
buttons={field.get('buttons')} buttons={field.get('buttons')}
disabled disabled
rawMode rawMode
t={t}
/> />
</EditorControlBar> </EditorControlBar>
<ClassNames> <ClassNames>
@ -127,6 +128,7 @@ export default class RawEditor extends React.Component {
onCut={this.handleCut} onCut={this.handleCut}
onCopy={this.handleCopy} onCopy={this.handleCopy}
ref={this.processRef} ref={this.processRef}
t={t}
/> />
)} )}
</ClassNames> </ClassNames>
@ -141,4 +143,5 @@ RawEditor.propTypes = {
className: PropTypes.string.isRequired, className: PropTypes.string.isRequired,
value: PropTypes.string, value: PropTypes.string,
field: ImmutablePropTypes.map.isRequired, field: ImmutablePropTypes.map.isRequired,
t: PropTypes.func.isRequired,
}; };

View File

@ -83,6 +83,7 @@ export default class Toolbar extends React.Component {
hasMark: PropTypes.func, hasMark: PropTypes.func,
hasInline: PropTypes.func, hasInline: PropTypes.func,
hasBlock: PropTypes.func, hasBlock: PropTypes.func,
t: PropTypes.func.isRequired,
}; };
isHidden = button => { isHidden = button => {
@ -113,6 +114,7 @@ export default class Toolbar extends React.Component {
hasMark = () => {}, hasMark = () => {},
hasInline = () => {}, hasInline = () => {},
hasBlock = () => {}, hasBlock = () => {},
t,
} = this.props; } = this.props;
return ( return (
@ -246,10 +248,12 @@ export default class Toolbar extends React.Component {
</div> </div>
<ToolbarToggle> <ToolbarToggle>
<ToolbarToggleLabel isActive={!rawMode} offPosition> <ToolbarToggleLabel isActive={!rawMode} offPosition>
Rich Text {t('editor.editorWidgets.markdown.richText')}
</ToolbarToggleLabel> </ToolbarToggleLabel>
<StyledToggle active={rawMode} onChange={onToggleMode} /> <StyledToggle active={rawMode} onChange={onToggleMode} />
<ToolbarToggleLabel isActive={rawMode}>Markdown</ToolbarToggleLabel> <ToolbarToggleLabel isActive={rawMode}>
{t('editor.editorWidgets.markdown.markdown')}
</ToolbarToggleLabel>
</ToolbarToggle> </ToolbarToggle>
</ToolbarContainer> </ToolbarContainer>
); );

View File

@ -82,6 +82,7 @@ export default class Editor extends React.Component {
value: PropTypes.string, value: PropTypes.string,
field: ImmutablePropTypes.map.isRequired, field: ImmutablePropTypes.map.isRequired,
getEditorComponents: PropTypes.func.isRequired, getEditorComponents: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
}; };
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
@ -142,7 +143,7 @@ export default class Editor extends React.Component {
}; };
render() { render() {
const { onAddAsset, getAsset, className, field } = this.props; const { onAddAsset, getAsset, className, field, t } = this.props;
return ( return (
<div <div
css={coreCss` css={coreCss`
@ -163,6 +164,7 @@ export default class Editor extends React.Component {
hasMark={this.hasMark} hasMark={this.hasMark}
hasInline={this.hasInline} hasInline={this.hasInline}
hasBlock={this.hasBlock} hasBlock={this.hasBlock}
t={t}
/> />
</EditorControlBar> </EditorControlBar>
<ClassNames> <ClassNames>

View File

@ -24,6 +24,7 @@ export default class MarkdownControl extends React.Component {
value: PropTypes.string, value: PropTypes.string,
field: ImmutablePropTypes.map.isRequired, field: ImmutablePropTypes.map.isRequired,
getEditorComponents: PropTypes.func, getEditorComponents: PropTypes.func,
t: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {
@ -61,6 +62,7 @@ export default class MarkdownControl extends React.Component {
field, field,
getEditorComponents, getEditorComponents,
resolveWidget, resolveWidget,
t,
} = this.props; } = this.props;
const { mode, pendingFocus } = this.state; const { mode, pendingFocus } = this.state;
@ -77,6 +79,7 @@ export default class MarkdownControl extends React.Component {
getEditorComponents={getEditorComponents} getEditorComponents={getEditorComponents}
resolveWidget={resolveWidget} resolveWidget={resolveWidget}
pendingFocus={pendingFocus && this.setFocusReceived} pendingFocus={pendingFocus && this.setFocusReceived}
t={t}
/> />
</div> </div>
); );
@ -91,6 +94,7 @@ export default class MarkdownControl extends React.Component {
value={value} value={value}
field={field} field={field}
pendingFocus={pendingFocus && this.setFocusReceived} pendingFocus={pendingFocus && this.setFocusReceived}
t={t}
/> />
</div> </div>
); );