1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

Merge branch 'master' into add-editor-rulers

This commit is contained in:
Junyoung Choi
2018-03-22 22:30:03 +09:00
45 changed files with 381 additions and 119 deletions

View File

@@ -1,3 +1,4 @@
node_modules/ node_modules/
compiled/ compiled/
dist/ dist/
extra_scripts/

View File

@@ -3,7 +3,9 @@
"plugins": ["react"], "plugins": ["react"],
"rules": { "rules": {
"no-useless-escape": 0, "no-useless-escape": 0,
"prefer-const": "warn", "prefer-const": ["warn", {
"destructuring": "all"
}],
"no-unused-vars": "warn", "no-unused-vars": "warn",
"no-undef": "warn", "no-undef": "warn",
"no-lone-blocks": "warn", "no-lone-blocks": "warn",

View File

@@ -282,6 +282,7 @@ class MarkdownEditor extends React.Component {
indentSize={editorIndentSize} indentSize={editorIndentSize}
scrollPastEnd={config.preview.scrollPastEnd} scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes} smartQuotes={config.preview.smartQuotes}
sanitize={config.preview.sanitize}
ref='preview' ref='preview'
onContextMenu={(e) => this.handleContextMenu(e)} onContextMenu={(e) => this.handleContextMenu(e)}
onDoubleClick={(e) => this.handleDoubleClick(e)} onDoubleClick={(e) => this.handleDoubleClick(e)}

View File

@@ -135,8 +135,11 @@ export default class MarkdownPreview extends React.Component {
} }
initMarkdown () { initMarkdown () {
const { smartQuotes } = this.props const { smartQuotes, sanitize } = this.props
this.markdown = new Markdown({ typographer: smartQuotes }) this.markdown = new Markdown({
typographer: smartQuotes,
sanitize
})
} }
handlePreviewAnchorClick (e) { handlePreviewAnchorClick (e) {
@@ -318,7 +321,7 @@ export default class MarkdownPreview extends React.Component {
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (prevProps.value !== this.props.value) this.rewriteIframe() if (prevProps.value !== this.props.value) this.rewriteIframe()
if (prevProps.smartQuotes !== this.props.smartQuotes) { if (prevProps.smartQuotes !== this.props.smartQuotes || prevProps.sanitize !== this.props.sanitize) {
this.initMarkdown() this.initMarkdown()
this.rewriteIframe() this.rewriteIframe()
} }

View File

@@ -130,6 +130,7 @@ class MarkdownSplitEditor extends React.Component {
lineNumber={config.preview.lineNumber} lineNumber={config.preview.lineNumber}
scrollPastEnd={config.preview.scrollPastEnd} scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes} smartQuotes={config.preview.smartQuotes}
sanitize={config.preview.sanitize}
ref='preview' ref='preview'
tabInde='0' tabInde='0'
value={value} value={value}

View File

@@ -58,7 +58,7 @@ body
.katex .katex
font 400 1.2em 'KaTeX_Main' font 400 1.2em 'KaTeX_Main'
line-height 1.2em line-height 1.2em
white-space nowrap white-space initial
text-indent 0 text-indent 0
.katex .mfrac>.vlist>span:nth-child(2) .katex .mfrac>.vlist>span:nth-child(2)
top 0 !important top 0 !important

View File

@@ -1,7 +1,7 @@
// load package for localization // load package for localization
const i18n = new (require('i18n-2'))({ const i18n = new (require('i18n-2'))({
// setup some locales - other locales default to the first locale // setup some locales - other locales default to the first locale
locales: ['en', 'sq', 'zh-CN', 'zh-TW', 'da', 'fr', 'de', 'ja', 'ko', 'no', 'pl', 'pt', 'es'], locales: ['en', 'sq', 'zh-CN', 'zh-TW', 'da', 'fr', 'de', 'hu', 'ja', 'ko', 'no', 'pl', 'pt', 'es'],
extension: '.json', extension: '.json',
devMode: process.env.NODE_ENV !== 'production' devMode: process.env.NODE_ENV !== 'production'
}) })

View File

@@ -45,52 +45,62 @@ class Markdown {
'<code class="' + langType + '">' + '<code class="' + langType + '">' +
str + str +
'</code></pre>' '</code></pre>'
} },
sanitize: 'STRICT'
} }
const updatedOptions = Object.assign(defaultOptions, options) const updatedOptions = Object.assign(defaultOptions, options)
this.md = markdownit(updatedOptions) this.md = markdownit(updatedOptions)
// Sanitize use rinput before other plugins if (updatedOptions.sanitize !== 'NONE') {
this.md.use(sanitize, { const allowedTags = ['iframe', 'input', 'b',
allowedTags: ['iframe', 'input', 'b',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'br', 'b', 'i', 'strong', 'em', 'a', 'pre', 'code', 'img', 'tt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'br', 'b', 'i', 'strong', 'em', 'a', 'pre', 'code', 'img', 'tt',
'div', 'ins', 'del', 'sup', 'sub', 'p', 'ol', 'ul', 'table', 'thead', 'tbody', 'tfoot', 'blockquote', 'div', 'ins', 'del', 'sup', 'sub', 'p', 'ol', 'ul', 'table', 'thead', 'tbody', 'tfoot', 'blockquote',
'dl', 'dt', 'dd', 'kbd', 'q', 'samp', 'var', 'hr', 'ruby', 'rt', 'rp', 'li', 'tr', 'td', 'th', 's', 'strike', 'summary', 'details' 'dl', 'dt', 'dd', 'kbd', 'q', 'samp', 'var', 'hr', 'ruby', 'rt', 'rp', 'li', 'tr', 'td', 'th', 's', 'strike', 'summary', 'details'
], ]
allowedAttributes: { const allowedAttributes = [
'*': [ 'abbr', 'accept', 'accept-charset',
'style', 'accesskey', 'action', 'align', 'alt', 'axis',
'abbr', 'accept', 'accept-charset', 'border', 'cellpadding', 'cellspacing', 'char',
'accesskey', 'action', 'align', 'alt', 'axis', 'charoff', 'charset', 'checked',
'border', 'cellpadding', 'cellspacing', 'char', 'clear', 'cols', 'colspan', 'color',
'charoff', 'charset', 'checked', 'compact', 'coords', 'datetime', 'dir',
'clear', 'cols', 'colspan', 'color', 'disabled', 'enctype', 'for', 'frame',
'compact', 'coords', 'datetime', 'dir', 'headers', 'height', 'hreflang',
'disabled', 'enctype', 'for', 'frame', 'hspace', 'ismap', 'label', 'lang',
'headers', 'height', 'hreflang', 'maxlength', 'media', 'method',
'hspace', 'ismap', 'label', 'lang', 'multiple', 'name', 'nohref', 'noshade',
'maxlength', 'media', 'method', 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
'multiple', 'name', 'nohref', 'noshade', 'rows', 'rowspan', 'rules', 'scope',
'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev', 'selected', 'shape', 'size', 'span',
'rows', 'rowspan', 'rules', 'scope', 'start', 'summary', 'tabindex', 'target',
'selected', 'shape', 'size', 'span', 'title', 'type', 'usemap', 'valign', 'value',
'start', 'summary', 'tabindex', 'target', 'vspace', 'width', 'itemprop'
'title', 'type', 'usemap', 'valign', 'value', ]
'vspace', 'width', 'itemprop'
], if (updatedOptions.sanitize === 'ALLOW_STYLES') {
'a': ['href'], allowedTags.push('style')
'div': ['itemscope', 'itemtype'], allowedAttributes.push('style')
'blockquote': ['cite'], }
'del': ['cite'],
'ins': ['cite'], // Sanitize use rinput before other plugins
'q': ['cite'], this.md.use(sanitize, {
'img': ['src', 'width', 'height'], allowedTags,
'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'], allowedAttributes: {
'input': ['type', 'id', 'checked'] '*': allowedAttributes,
}, 'a': ['href'],
allowedIframeHostnames: ['www.youtube.com'] 'div': ['itemscope', 'itemtype'],
}) 'blockquote': ['cite'],
'del': ['cite'],
'ins': ['cite'],
'q': ['cite'],
'img': ['src', 'width', 'height'],
'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
'input': ['type', 'id', 'checked']
},
allowedIframeHostnames: ['www.youtube.com']
})
}
this.md.use(emoji, { this.md.use(emoji, {
shortcuts: {} shortcuts: {}

View File

@@ -3,6 +3,7 @@ import React from 'react'
import CSSModules from 'browser/lib/CSSModules' import CSSModules from 'browser/lib/CSSModules'
import styles from './FolderSelect.styl' import styles from './FolderSelect.styl'
import _ from 'lodash' import _ from 'lodash'
import i18n from 'browser/lib/i18n'
class FolderSelect extends React.Component { class FolderSelect extends React.Component {
constructor (props) { constructor (props) {
@@ -249,7 +250,7 @@ class FolderSelect extends React.Component {
<input styleName='search-input' <input styleName='search-input'
ref='search' ref='search'
value={this.state.search} value={this.state.search}
placeholder='Folder...' placeholder={i18n.__('Folder...')}
onChange={(e) => this.handleSearchInputChange(e)} onChange={(e) => this.handleSearchInputChange(e)}
onBlur={(e) => this.handleSearchInputBlur(e)} onBlur={(e) => this.handleSearchInputBlur(e)}
onKeyDown={(e) => this.handleSearchInputKeyDown(e)} onKeyDown={(e) => this.handleSearchInputKeyDown(e)}

View File

@@ -2,13 +2,14 @@ import PropTypes from 'prop-types'
import React from 'react' import React from 'react'
import CSSModules from 'browser/lib/CSSModules' import CSSModules from 'browser/lib/CSSModules'
import styles from './FullscreenButton.styl' import styles from './FullscreenButton.styl'
import i18n from 'browser/lib/i18n'
const FullscreenButton = ({ const FullscreenButton = ({
onClick onClick
}) => ( }) => (
<button styleName='control-fullScreenButton' title='Fullscreen' onMouseDown={(e) => onClick(e)}> <button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')} onMouseDown={(e) => onClick(e)}>
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' /> <img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
<span styleName='tooltip'>Fullscreen</span> <span styleName='tooltip'>{i18n.__('Fullscreen')}</span>
</button> </button>
) )

View File

@@ -2,6 +2,7 @@ import PropTypes from 'prop-types'
import React from 'react' import React from 'react'
import CSSModules from 'browser/lib/CSSModules' import CSSModules from 'browser/lib/CSSModules'
import styles from './InfoButton.styl' import styles from './InfoButton.styl'
import i18n from 'browser/lib/i18n'
const InfoButton = ({ const InfoButton = ({
onClick onClick
@@ -10,7 +11,7 @@ const InfoButton = ({
onClick={(e) => onClick(e)} onClick={(e) => onClick(e)}
> >
<img className='infoButton' src='../resources/icon/icon-info.svg' /> <img className='infoButton' src='../resources/icon/icon-info.svg' />
<span styleName='tooltip'>Info</span> <span styleName='tooltip'>{i18n.__('Info')}</span>
</button> </button>
) )

View File

@@ -640,7 +640,7 @@ class SnippetNoteDetail extends React.Component {
type: 'warning', type: 'warning',
message: i18n.__('Sorry!'), message: i18n.__('Sorry!'),
detail: i18n.__('md/text import is available only a markdown note.'), detail: i18n.__('md/text import is available only a markdown note.'),
buttons: ['OK'] buttons: [i18n.__('OK')]
}) })
} }
@@ -766,10 +766,10 @@ class SnippetNoteDetail extends React.Component {
isActive={note.isStarred} isActive={note.isStarred}
/> />
<button styleName='control-fullScreenButton' title='Fullscreen' <button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')}
onMouseDown={(e) => this.handleFullScreenButton(e)}> onMouseDown={(e) => this.handleFullScreenButton(e)}>
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' /> <img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
<span styleName='tooltip'>Fullscreen</span> <span styleName='tooltip'>{i18n.__('Fullscreen')}</span>
</button> </button>
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} /> <TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
@@ -807,7 +807,7 @@ class SnippetNoteDetail extends React.Component {
fontSize: parseInt(config.preview.fontSize, 10) fontSize: parseInt(config.preview.fontSize, 10)
}} }}
ref='description' ref='description'
placeholder='Description...' placeholder={i18n.__('Description...')}
value={this.state.note.description} value={this.state.note.description}
onChange={(e) => this.handleChange(e)} onChange={(e) => this.handleChange(e)}
/> />
@@ -846,7 +846,7 @@ class SnippetNoteDetail extends React.Component {
onClick={(e) => this.handleModeButtonClick(e, this.state.snippetIndex)} onClick={(e) => this.handleModeButtonClick(e, this.state.snippetIndex)}
> >
{this.state.note.snippets[this.state.snippetIndex].mode == null {this.state.note.snippets[this.state.snippetIndex].mode == null
? 'Select Syntax...' ? i18n.__('Select Syntax...')
: this.state.note.snippets[this.state.snippetIndex].mode : this.state.note.snippets[this.state.snippetIndex].mode
}&nbsp; }&nbsp;
<i className='fa fa-caret-down' /> <i className='fa fa-caret-down' />

View File

@@ -3,6 +3,7 @@ import React from 'react'
import CSSModules from 'browser/lib/CSSModules' import CSSModules from 'browser/lib/CSSModules'
import styles from './StarButton.styl' import styles from './StarButton.styl'
import _ from 'lodash' import _ from 'lodash'
import i18n from 'browser/lib/i18n'
class StarButton extends React.Component { class StarButton extends React.Component {
constructor (props) { constructor (props) {
@@ -53,7 +54,7 @@ class StarButton extends React.Component {
: '../resources/icon/icon-star.svg' : '../resources/icon/icon-star.svg'
} }
/> />
<span styleName='tooltip'>Star</span> <span styleName='tooltip'>{i18n.__('Star')}</span>
</button> </button>
) )
} }

View File

@@ -4,6 +4,7 @@ import CSSModules from 'browser/lib/CSSModules'
import styles from './TagSelect.styl' import styles from './TagSelect.styl'
import _ from 'lodash' import _ from 'lodash'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import i18n from 'browser/lib/i18n'
class TagSelect extends React.Component { class TagSelect extends React.Component {
constructor (props) { constructor (props) {
@@ -137,7 +138,7 @@ class TagSelect extends React.Component {
<input styleName='newTag' <input styleName='newTag'
ref='newTag' ref='newTag'
value={this.state.newTag} value={this.state.newTag}
placeholder='Add tag...' placeholder={i18n.__('Add tag...')}
onChange={(e) => this.handleNewTagInputChange(e)} onChange={(e) => this.handleNewTagInputChange(e)}
onKeyDown={(e) => this.handleNewTagInputKeyDown(e)} onKeyDown={(e) => this.handleNewTagInputKeyDown(e)}
onBlur={(e) => this.handleNewTagBlur(e)} onBlur={(e) => this.handleNewTagBlur(e)}

View File

@@ -161,6 +161,8 @@ class Main extends React.Component {
i18n.setLocale('fr') i18n.setLocale('fr')
} else if (config.ui.language === 'de') { } else if (config.ui.language === 'de') {
i18n.setLocale('de') i18n.setLocale('de')
} else if (config.ui.language === 'hu') {
i18n.setLocale('hu')
} else if (config.ui.language === 'ja') { } else if (config.ui.language === 'ja') {
i18n.setLocale('ja') i18n.setLocale('ja')
} else if (config.ui.language === 'ko') { } else if (config.ui.language === 'ko') {

View File

@@ -57,9 +57,9 @@ class NewNoteButton extends React.Component {
} }
} }
if (storage == null) this.showMessageBox('No storage to create a note') if (storage == null) this.showMessageBox(i18n.__('No storage to create a note'))
const folder = _.find(storage.folders, {key: params.folderKey}) || storage.folders[0] const folder = _.find(storage.folders, {key: params.folderKey}) || storage.folders[0]
if (folder == null) this.showMessageBox('No folder to create a note') if (folder == null) this.showMessageBox(i18n.__('No folder to create a note'))
return { return {
storage, storage,

View File

@@ -445,9 +445,9 @@ class NoteList extends React.Component {
if (this.notes[targetIndex].type === 'SNIPPET_NOTE') { if (this.notes[targetIndex].type === 'SNIPPET_NOTE') {
dialog.showMessageBox(remote.getCurrentWindow(), { dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning', type: 'warning',
message: 'Sorry!', message: i18n.__('Sorry!'),
detail: 'md/text import is available only a markdown note.', detail: i18n.__('md/text import is available only a markdown note.'),
buttons: ['OK', 'Cancel'] buttons: [i18n.__('OK'), i18n.__('Cancel')]
}) })
} }
} }
@@ -471,14 +471,14 @@ class NoteList extends React.Component {
this.handleNoteClick(e, uniqueKey) this.handleNoteClick(e, uniqueKey)
} }
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top' const pinLabel = note.isPinned ? i18n.__('Remove pin') : i18n.__('Pin to Top')
const deleteLabel = 'Delete Note' const deleteLabel = i18n.__('Delete Note')
const cloneNote = 'Clone Note' const cloneNote = i18n.__('Clone Note')
const restoreNote = 'Restore Note' const restoreNote = i18n.__('Restore Note')
const copyNoteLink = 'Copy Note Link' const copyNoteLink = i18n.__('Copy Note Link')
const publishLabel = 'Publish Blog' const publishLabel = i18n.__('Publish Blog')
const updateLabel = 'Update Blog' const updateLabel = i18n.__('Update Blog')
const openBlogLabel = 'Open Blog' const openBlogLabel = i18n.__('Open Blog')
const menu = new Menu() const menu = new Menu()
if (!location.pathname.match(/\/starred|\/trash/)) { if (!location.pathname.match(/\/starred|\/trash/)) {
@@ -585,9 +585,9 @@ class NoteList extends React.Component {
const noteExp = selectedNotes.length > 1 ? 'notes' : 'note' const noteExp = selectedNotes.length > 1 ? 'notes' : 'note'
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), { const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning', type: 'warning',
message: 'Confirm note deletion', message: i18n.__('Confirm note deletion'),
detail: `This will permanently remove ${selectedNotes.length} ${noteExp}.`, detail: `This will permanently remove ${selectedNotes.length} ${noteExp}.`,
buttons: ['Confirm', 'Cancel'] buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
}) })
if (dialogueButtonIndex === 1) return if (dialogueButtonIndex === 1) return
Promise.all( Promise.all(
@@ -757,9 +757,9 @@ class NoteList extends React.Component {
const { dialog } = remote const { dialog } = remote
const alertError = { const alertError = {
type: 'warning', type: 'warning',
message: 'Publish Failed', message: i18n.__('Publish Failed'),
detail: 'Check and update your blog setting and try again.', detail: i18n.__('Check and update your blog setting and try again.'),
buttons: ['Confirm'] buttons: [i18n.__('Confirm')]
} }
dialog.showMessageBox(remote.getCurrentWindow(), alertError) dialog.showMessageBox(remote.getCurrentWindow(), alertError)
} }
@@ -767,9 +767,9 @@ class NoteList extends React.Component {
confirmPublish (note) { confirmPublish (note) {
const buttonIndex = dialog.showMessageBox(remote.getCurrentWindow(), { const buttonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning', type: 'warning',
message: 'Publish Succeeded', message: i18n.__('Publish Succeeded'),
detail: `${note.title} is published at ${note.blog.blogLink}`, detail: `${note.title} is published at ${note.blog.blogLink}`,
buttons: ['Confirm', 'Open Blog'] buttons: [i18n.__('Confirm'), i18n.__('Open Blog')]
}) })
if (buttonIndex === 1) { if (buttonIndex === 1) {
@@ -874,7 +874,7 @@ class NoteList extends React.Component {
dialog.showMessageBox(remote.getCurrentWindow(), { dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning', type: 'warning',
message: message, message: message,
buttons: ['OK'] buttons: [i18n.__('OK')]
}) })
} }
@@ -992,7 +992,7 @@ class NoteList extends React.Component {
<div styleName='control-sortBy'> <div styleName='control-sortBy'>
<i className='fa fa-angle-down' /> <i className='fa fa-angle-down' />
<select styleName='control-sortBy-select' <select styleName='control-sortBy-select'
title='Select filter mode' title={i18n.__('Select filter mode')}
value={config.sortBy} value={config.sortBy}
onChange={(e) => this.handleSortByChange(e)} onChange={(e) => this.handleSortByChange(e)}
> >

View File

@@ -27,14 +27,14 @@ class StorageItem extends React.Component {
handleHeaderContextMenu (e) { handleHeaderContextMenu (e) {
const menu = Menu.buildFromTemplate([ const menu = Menu.buildFromTemplate([
{ {
label: 'Add Folder', label: i18n.__('Add Folder'),
click: (e) => this.handleAddFolderButtonClick(e) click: (e) => this.handleAddFolderButtonClick(e)
}, },
{ {
type: 'separator' type: 'separator'
}, },
{ {
label: 'Unlink Storage', label: i18n.__('Unlink Storage'),
click: (e) => this.handleUnlinkStorageClick(e) click: (e) => this.handleUnlinkStorageClick(e)
} }
]) ])
@@ -94,21 +94,21 @@ class StorageItem extends React.Component {
handleFolderButtonContextMenu (e, folder) { handleFolderButtonContextMenu (e, folder) {
const menu = Menu.buildFromTemplate([ const menu = Menu.buildFromTemplate([
{ {
label: 'Rename Folder', label: i18n.__('Rename Folder'),
click: (e) => this.handleRenameFolderClick(e, folder) click: (e) => this.handleRenameFolderClick(e, folder)
}, },
{ {
type: 'separator' type: 'separator'
}, },
{ {
label: 'Export Folder', label: i18n.__('Export Folder'),
submenu: [ submenu: [
{ {
label: 'Export as txt', label: i18n.__('Export as txt'),
click: (e) => this.handleExportFolderClick(e, folder, 'txt') click: (e) => this.handleExportFolderClick(e, folder, 'txt')
}, },
{ {
label: 'Export as md', label: i18n.__('Export as md'),
click: (e) => this.handleExportFolderClick(e, folder, 'md') click: (e) => this.handleExportFolderClick(e, folder, 'md')
} }
] ]
@@ -117,7 +117,7 @@ class StorageItem extends React.Component {
type: 'separator' type: 'separator'
}, },
{ {
label: 'Delete Folder', label: i18n.__('Delete Folder'),
click: (e) => this.handleFolderDeleteClick(e, folder) click: (e) => this.handleFolderDeleteClick(e, folder)
} }
]) ])
@@ -136,8 +136,8 @@ class StorageItem extends React.Component {
handleExportFolderClick (e, folder, fileType) { handleExportFolderClick (e, folder, fileType) {
const options = { const options = {
properties: ['openDirectory', 'createDirectory'], properties: ['openDirectory', 'createDirectory'],
buttonLabel: 'Select directory', buttonLabel: i18n.__('Select directory'),
title: 'Select a folder to export the files to', title: i18n.__('Select a folder to export the files to'),
multiSelections: false multiSelections: false
} }
dialog.showOpenDialog(remote.getCurrentWindow(), options, dialog.showOpenDialog(remote.getCurrentWindow(), options,

View File

@@ -18,6 +18,7 @@ import PreferenceButton from './PreferenceButton'
import ListButton from './ListButton' import ListButton from './ListButton'
import TagButton from './TagButton' import TagButton from './TagButton'
import {SortableContainer} from 'react-sortable-hoc' import {SortableContainer} from 'react-sortable-hoc'
import i18n from 'browser/lib/i18n'
class SideNav extends React.Component { class SideNav extends React.Component {
// TODO: should not use electron stuff v0.7 // TODO: should not use electron stuff v0.7
@@ -115,7 +116,7 @@ class SideNav extends React.Component {
component = ( component = (
<div styleName='tabBody'> <div styleName='tabBody'>
<div styleName='tag-title'> <div styleName='tag-title'>
<p>Tags</p> <p>{i18n.__('Tags')}</p>
</div> </div>
<div styleName='tagList'> <div styleName='tagList'>
{this.tagListComponent(data)} {this.tagListComponent(data)}
@@ -179,7 +180,7 @@ class SideNav extends React.Component {
const { data } = this.props const { data } = this.props
const trashedNotes = data.trashedSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey)) const trashedNotes = data.trashedSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey))
const menu = Menu.buildFromTemplate([ const menu = Menu.buildFromTemplate([
{ label: 'Empty Trash', click: () => this.emptyTrash(trashedNotes) } { label: i18n.__('Empty Trash'), click: () => this.emptyTrash(trashedNotes) }
]) ])
menu.popup() menu.popup()
} }

View File

@@ -53,7 +53,8 @@ export const DEFAULT_CONFIG = {
latexBlockOpen: '$$', latexBlockOpen: '$$',
latexBlockClose: '$$', latexBlockClose: '$$',
scrollPastEnd: false, scrollPastEnd: false,
smartQuotes: true smartQuotes: true,
sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE'
}, },
blog: { blog: {
type: 'wordpress', // Available value: wordpress, add more types in the future plz type: 'wordpress', // Available value: wordpress, add more types in the future plz
@@ -149,6 +150,8 @@ function set (updates) {
i18n.setLocale('fr') i18n.setLocale('fr')
} else if (newConfig.ui.language === 'de') { } else if (newConfig.ui.language === 'de') {
i18n.setLocale('de') i18n.setLocale('de')
} else if (newConfig.ui.language === 'hu') {
i18n.setLocale('hu')
} else if (newConfig.ui.language === 'ja') { } else if (newConfig.ui.language === 'ja') {
i18n.setLocale('ja') i18n.setLocale('ja')
} else if (newConfig.ui.language === 'ko') { } else if (newConfig.ui.language === 'ko') {

View File

@@ -1,5 +1,4 @@
import ConfigManager from './ConfigManager' import ConfigManager from './ConfigManager'
import store from 'browser/main/store'
const nodeIpc = require('node-ipc') const nodeIpc = require('node-ipc')
const { remote, ipcRenderer } = require('electron') const { remote, ipcRenderer } = require('electron')

View File

@@ -7,6 +7,7 @@ import store from 'browser/main/store'
import consts from 'browser/lib/consts' import consts from 'browser/lib/consts'
import ModalEscButton from 'browser/components/ModalEscButton' import ModalEscButton from 'browser/components/ModalEscButton'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import i18n from 'browser/lib/i18n'
class CreateFolderModal extends React.Component { class CreateFolderModal extends React.Component {
constructor (props) { constructor (props) {
@@ -79,12 +80,12 @@ class CreateFolderModal extends React.Component {
onKeyDown={(e) => this.handleKeyDown(e)} onKeyDown={(e) => this.handleKeyDown(e)}
> >
<div styleName='header'> <div styleName='header'>
<div styleName='title'>Create new folder</div> <div styleName='title'>{i18n.__('Create new folder')}</div>
</div> </div>
<ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} /> <ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} />
<div styleName='control'> <div styleName='control'>
<div styleName='control-folder'> <div styleName='control-folder'>
<div styleName='control-folder-label'>Folder name</div> <div styleName='control-folder-label'>{i18n.__('Folder name')}</div>
<input styleName='control-folder-input' <input styleName='control-folder-input'
ref='name' ref='name'
value={this.state.name} value={this.state.name}

View File

@@ -111,7 +111,7 @@ class NewNoteModal extends React.Component {
onKeyDown={(e) => this.handleKeyDown(e)} onKeyDown={(e) => this.handleKeyDown(e)}
> >
<div styleName='header'> <div styleName='header'>
<div styleName='title'>Make a note</div> <div styleName='title'>{i18n.__('Make a note')}</div>
</div> </div>
<ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} /> <ModalEscButton handleEscButtonClick={(e) => this.handleCloseButtonClick(e)} />
<div styleName='control'> <div styleName='control'>

View File

@@ -43,7 +43,7 @@ class Blog extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({BlogAlert: { this.setState({BlogAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : 'Error occurs!' message: err.message != null ? err.message : i18n.__('Error occurs!')
}}) }})
} }
this.oldBlog = this.state.config.blog this.oldBlog = this.state.config.blog
@@ -70,7 +70,7 @@ class Blog extends React.Component {
this.props.haveToSave({ this.props.haveToSave({
tab: 'Blog', tab: 'Blog',
type: 'warning', type: 'warning',
message: 'You have to save!' message: i18n.__('You have to save!')
}) })
} }
} }
@@ -111,7 +111,7 @@ class Blog extends React.Component {
ref='typeDropdown' ref='typeDropdown'
onChange={(e) => this.handleBlogChange(e)} onChange={(e) => this.handleBlogChange(e)}
> >
<option value='wordpress' key='wordpress'>wordpress</option> <option value='wordpress' key='wordpress'>{i18n.__('wordpress')}</option>
</select> </select>
</div> </div>
</div> </div>

View File

@@ -6,6 +6,7 @@ import styles from './FolderList.styl'
import store from 'browser/main/store' import store from 'browser/main/store'
import FolderItem from './FolderItem' import FolderItem from './FolderItem'
import { SortableContainer } from 'react-sortable-hoc' import { SortableContainer } from 'react-sortable-hoc'
import i18n from 'browser/lib/i18n'
class FolderList extends React.Component { class FolderList extends React.Component {
render () { render () {
@@ -24,7 +25,7 @@ class FolderList extends React.Component {
<div styleName='folderList'> <div styleName='folderList'>
{folderList.length > 0 {folderList.length > 0
? folderList ? folderList
: <div styleName='folderList-empty'>No Folders</div> : <div styleName='folderList-empty'>{i18n.__('No Folders')}</div>
} }
</div> </div>
) )

View File

@@ -30,7 +30,7 @@ class HotkeyTab extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({keymapAlert: { this.setState({keymapAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : 'Error occurs!' message: err.message != null ? err.message : i18n.__('Error occurs!')
}}) }})
} }
this.oldHotkey = this.state.config.hotkey this.oldHotkey = this.state.config.hotkey

View File

@@ -15,7 +15,7 @@ function browseFolder () {
const defaultPath = remote.app.getPath('home') const defaultPath = remote.app.getPath('home')
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
dialog.showOpenDialog({ dialog.showOpenDialog({
title: 'Select Directory', title: i18n.__('Select Directory'),
defaultPath, defaultPath,
properties: ['openDirectory', 'createDirectory'] properties: ['openDirectory', 'createDirectory']
}, function (targetPaths) { }, function (targetPaths) {

View File

@@ -36,7 +36,7 @@ class UiTab extends React.Component {
this.handleSettingError = (err) => { this.handleSettingError = (err) => {
this.setState({UiAlert: { this.setState({UiAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : 'Error occurs!' message: err.message != null ? err.message : i18n.__('Error occurs!')
}}) }})
} }
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
@@ -93,7 +93,8 @@ class UiTab extends React.Component {
latexBlockOpen: this.refs.previewLatexBlockOpen.value, latexBlockOpen: this.refs.previewLatexBlockOpen.value,
latexBlockClose: this.refs.previewLatexBlockClose.value, latexBlockClose: this.refs.previewLatexBlockClose.value,
scrollPastEnd: this.refs.previewScrollPastEnd.checked, scrollPastEnd: this.refs.previewScrollPastEnd.checked,
smartQuotes: this.refs.previewSmartQuotes.checked smartQuotes: this.refs.previewSmartQuotes.checked,
sanitize: this.refs.previewSanitize.value
} }
} }
@@ -188,6 +189,7 @@ class UiTab extends React.Component {
<option value='en'>{i18n.__('English')}</option> <option value='en'>{i18n.__('English')}</option>
<option value='fr'>{i18n.__('French')}</option> <option value='fr'>{i18n.__('French')}</option>
<option value='de'>{i18n.__('German')}</option> <option value='de'>{i18n.__('German')}</option>
<option value='hu'>{i18n.__('Hungarian')}</option>
<option value='ja'>{i18n.__('Japanese')}</option> <option value='ja'>{i18n.__('Japanese')}</option>
<option value='ko'>{i18n.__('Korean')}</option> <option value='ko'>{i18n.__('Korean')}</option>
<option value='no'>{i18n.__('Norwegian')}</option> <option value='no'>{i18n.__('Norwegian')}</option>
@@ -472,6 +474,23 @@ class UiTab extends React.Component {
Enable smart quotes Enable smart quotes
</label> </label>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Sanitization')}
</div>
<div styleName='group-section-control'>
<select value={config.preview.sanitize}
ref='previewSanitize'
onChange={(e) => this.handleUIChange(e)}
>
<option value='STRICT'> {i18n.__('Only allow secure html tags (recommended)')}
</option>
<option value='ALLOW_STYLES'> {i18n.__('Allow styles')}</option>
<option value='NONE'> {i18n.__('Allow dangerous html tags')}</option>
</select>
</div>
</div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'> <div styleName='group-section-label'>
{i18n.__('LaTeX Inline Open Delimiter')} {i18n.__('LaTeX Inline Open Delimiter')}

View File

@@ -79,7 +79,7 @@ class RenameFolderModal extends React.Component {
<div styleName='control'> <div styleName='control'>
<input styleName='control-input' <input styleName='control-input'
placeholder='Folder Name' placeholder={i18n.__('Folder Name')}
ref='name' ref='name'
value={this.state.name} value={this.state.name}
onChange={(e) => this.handleChange(e)} onChange={(e) => this.handleChange(e)}

View File

@@ -69,6 +69,10 @@ ipc.on('update-app-confirm', function (event, msg) {
} }
}) })
app.on('window-all-closed', function () {
app.quit()
})
app.on('ready', function () { app.on('ready', function () {
mainWindow = require('./main-window') mainWindow = require('./main-window')

View File

@@ -56,11 +56,8 @@ if (process.platform === 'darwin' || process.env.DESKTOP_SESSION === 'cinnamon')
app.on('before-quit', function (e) { app.on('before-quit', function (e) {
mainWindow.removeAllListeners() mainWindow.removeAllListeners()
}) })
} else {
app.on('window-all-closed', function () {
app.quit()
})
} }
mainWindow.on('resize', _.throttle(storeWindowSize, 500)) mainWindow.on('resize', _.throttle(storeWindowSize, 500))
function storeWindowSize () { function storeWindowSize () {

View File

@@ -145,5 +145,9 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -147,5 +147,9 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -147,5 +147,9 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -145,5 +145,9 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,10 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

159
locales/hu.json Normal file
View File

@@ -0,0 +1,159 @@
{
"Notes": "Jegyzetek",
"Tags": "Címkék",
"Preferences": "Beállítások",
"Make a note": "Új jegyzet",
"Ctrl": "Ctrl",
"Ctrl(^)": "Ctrl",
"to create a new note": "hogy létrehozz egy jegyzetet",
"Toggle Mode": "Mód Váltás",
"Trash": "Lomtár",
"MODIFICATION DATE": "MÓDOSÍTÁS DÁTUMA",
"Words": "Szó",
"Letters": "Betű",
"STORAGE": "TÁROLÓ",
"FOLDER": "KÖNYVTÁR",
"CREATION DATE": "LÉTREHOZÁS DÁTUMA",
"NOTE LINK": "JEGYZET LINKJE",
".md": ".md",
".txt": ".txt",
".html": ".html",
"Print": "Nyomtatás",
"Your preferences for Boostnote": "Boostnote beállításaid",
"Storages": "Tárolók",
"Add Storage Location": "Tároló Hozzáadása",
"Add Folder": "Könyvtár Hozzáadása",
"Open Storage folder": "Tároló Megnyitása",
"Unlink": "Tároló Leválasztása",
"Edit": "Szerkesztés",
"Delete": "Törlés",
"Interface": "Felület",
"Interface Theme": "Felület Témája",
"Default": "Alapértelmezett",
"White": "Világos",
"Solarized Dark": "Solarized Dark",
"Dark": "Sötét",
"Show a confirmation dialog when deleting notes": "Kérjen megerősítést a jegyzetek törlése előtt",
"Editor Theme": "Szerkesztő Témája",
"Editor Font Size": "Szerkesztő Betűmérete",
"Editor Font Family": "Szerkesztő Betűtípusa",
"Editor Indent Style": "Szerkesztő Behúzása",
"Spaces": "Szóközök",
"Tabs": "Tabulátor karakterek",
"Switch to Preview": "Váltás Megtekintésre",
"When Editor Blurred": "Szerkesztő Elhagyásakor",
"When Editor Blurred, Edit On Double Click": "Szerkesztő Elhagyásakor, Szerkesztő Megnyitása Dupla Kattintással",
"On Right Click": "Jobb Egérgombbal",
"Editor Keymap": "Szerkesztő Billentyűzetkiosztása",
"default": "alapértelmezett",
"vim": "vim",
"emacs": "emacs",
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Kérlek, indítsd újra a programot a kiosztás megváltoztatása után",
"Show line numbers in the editor": "Mutatassa a sorszámokat a szerkesztőben",
"Allow editor to scroll past the last line": "A szerkesztőben az utolsó sor alá is lehessen görgetni",
"Bring in web page title when pasting URL on editor": "Weboldal főcímének lekérdezése URL cím beillesztésekor",
"Preview": "Megtekintés",
"Preview Font Size": "Megtekintés Betűmérete",
"Preview Font Family": "Megtekintés Betűtípusa",
"Code block Theme": "Kódblokk Témája",
"Allow preview to scroll past the last line": "Megtekintésben az utolsó sor alá is lehessen görgetni",
"Show line numbers for preview code blocks": "Mutatassa a sorszámokat a megtekintett kódblokkokban",
"LaTeX Inline Open Delimiter": "LaTeX Inline Nyitó Határolója",
"LaTeX Inline Close Delimiter": "LaTeX Inline Záró Határolója",
"LaTeX Block Open Delimiter": "LaTeX Blokk Nyitó Határolója",
"LaTeX Block Close Delimiter": "LaTeX Blokk Záró Határolója",
"Community": "Közösség",
"Subscribe to Newsletter": "Feliratkozás a Hírlevélre",
"GitHub": "GitHub",
"Blog": "Blog",
"Facebook Group": "Facebook Csoport",
"Twitter": "Twitter",
"About": "Névjegy",
"Boostnote": "Boostnote",
"An open source note-taking app made for programmers just like you.": "Nyílt forráskódú jegyzetkészítő program a hozzád hasonló programozóknak.",
"Website": "Weboldal",
"Development": "Fejlesztés",
" : Development configurations for Boostnote.": " : Információk a Boostnote fejlesztéséről.",
"Copyright (C) 2017 - 2018 BoostIO": "Szerzői jog (C) 2017 - 2018 BoostIO",
"License: GPL v3": "Licensz: GPL v3",
"Analytics": "Adatok elemzése",
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "A Boostnote névtelen adatokat gyűjt össze az alkalmazás tökéletesítése céljából, és szigorúan nem gyűjt semmilyen személyes adatot, például a jegyzetek tartalmát.",
"You can see how it works on ": "A működéséről további információkat itt találsz: ",
"You can choose to enable or disable this option.": "Kiválaszthatod, hogy engedélyezed, vagy tiltod ezt az opciót.",
"Enable analytics to help improve Boostnote": "Adatok elemzésének engedélyezése a Boostnote tökéletesítésének céljából",
"Crowdfunding": "Közösségi finanszírozás",
"Dear everyone,": "Kedves felhasználók!",
"Thank you for using Boostnote!": "Köszönjük, hogy a Boostnote-ot használjátok!",
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "A Boostnote-ot több, mint 200 ország és régió fantasztikus fejlesztői használják.",
"To continue supporting this growth, and to satisfy community expectations,": "Hogy folytathassuk ezt a fejlődést és kielégíthessük a felhasználói elvárásokat,",
"we would like to invest more time and resources in this project.": "több időt és erőforrást szeretnénk a projektbe fektetni.",
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Ha tetszik a projekt és hasznosnak találod, te is segíthetsz ebben az OpenCollective-en keresztül küldött támogatásoddal.",
"Thanks,": "Köszönjük!",
"Boostnote maintainers": "A Boostnote csapata",
"Support via OpenCollective": "Támogatás Küldése",
"Language": "Nyelv",
"English": "English",
"German": "German",
"French": "French",
"Show \"Saved to Clipboard\" notification when copying": "Mutassa a \"Vágólapra Másolva\" üzenetet másoláskor",
"All Notes": "Minden Jegyzet",
"Starred": "Kiemelt",
"Are you sure to ": "Biztos, hogy ",
" delete": " törölni",
"this folder?": "szeretnéd a könyvtárat?",
"Confirm": "Igen",
"Cancel": "Mégse",
"Markdown Note": "Markdown Jegyzet",
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ez a formátum szöveges dokumentumok készítésére használható. Jelölőnégyzeteket, kódblokkokat és Latex blokkokat is tartalmazhat.",
"Snippet Note": "Kód Jegyzet",
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ez a formátum kódrészletek készítésére használható. Több kódrészlet tárolására is alkalmas (pl. HTML + CSS).",
"Tab to switch format": "Formátum váltásához nyomd le a Tabulátor billentyűt!",
"Updated": "Módosítás",
"Created": "Létrehozás",
"Alphabetically": "Ábécé sorrendben",
"Default View": "Alapértelmezett Nézet",
"Compressed View": "Tömörített Nézet",
"Search": "Keresés",
"Blog Type": "Blog Típusa",
"Blog Address": "Blog Címe",
"Save": "Mentés",
"Auth": "Hitelesítés",
"Authentication Method": "Hitelesítési Módszer",
"JWT": "JWT",
"USER": "USER",
"Token": "Token",
"Storage": "Tároló",
"Hotkeys": "Gyorsbillentyűk",
"Show/Hide Boostnote": "Boostnote Megjelenítése/Elrejtése",
"Restore": "Visszaállítás",
"Permanent Delete": "Végleges Törlés",
"Confirm note deletion": "Törlés megerősítése",
"This will permanently remove this note.": "A jegyzet véglegesen törölve lesz.",
"Successfully applied!": "Sikeresen alkalmazva.",
"Albanian": "Albanian",
"Chinese (zh-CN)": "Chinese (zh-CN)",
"Chinese (zh-TW)": "Chinese (zh-TW)",
"Danish": "Danish",
"Japanese": "Japanese",
"Korean": "Korean",
"Norwegian": "Norwegian",
"Polish": "Polish",
"Portuguese": "Portuguese",
"Spanish": "Spanish",
"You have to save!": "Mentened kell!",
"UserName": "FelhasznaloNev",
"Password": "Jelszo",
"Russian": "Russian",
"Command(⌘)": "Command(⌘)",
"Hungarian": "Hungarian",
"Add Storage": "Tároló hozzáadása",
"Name": "Név",
"Type": "Típus",
"File System": "Fájlrendszer",
"Setting up 3rd-party cloud storage integration:": "Harmadik féltől származó felhőtárolási integráció beállítása:",
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
"Location": "Hely",
"Add": "Hozzáadás",
"Unlink Storage": "Tároló Leválasztása",
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "A leválasztás eltávolítja ezt a tárolót a Boostnote-ból. Az adatok nem lesznek törölve, kérlek manuálisan töröld a könyvtárat a merevlemezről, ha szükséges."
}

View File

@@ -145,5 +145,9 @@
"Command(⌘)": "Command(⌘)", "Command(⌘)": "Command(⌘)",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -151,5 +151,9 @@
"Hotkeys": "단축키", "Hotkeys": "단축키",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "허용 태그 범위",
"Only allow secure html tags (recommended)": "안전한 HTML 태그만 허용 (추천)",
"Allow styles": "style 태그, 속성까지 허용",
"Allow dangerous html tags": "모든 위험한 태그 허용"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }

View File

@@ -144,5 +144,9 @@
"Russian": "Russian", "Russian": "Russian",
"Editor Rulers": "Editor Rulers", "Editor Rulers": "Editor Rulers",
"Enable": "Enable", "Enable": "Enable",
"Disable": "Disable" "Disable": "Disable",
"Sanitization": "Sanitization",
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
"Allow styles": "Allow styles",
"Allow dangerous html tags": "Allow dangerous html tags"
} }