diff --git a/server/libs/entries.js b/server/libs/entries.js index 35716e5e..cf6e9de5 100644 --- a/server/libs/entries.js +++ b/server/libs/entries.js @@ -155,7 +155,7 @@ module.exports = { return false } }).catch((err) => { // eslint-disable-line handle-callback-err - throw new Promise.OperationalError('Entry ' + entryPath + ' does not exist!') + throw new Promise.OperationalError(lang.t('errors:notexist', { path: entryPath })) }) }, @@ -184,11 +184,11 @@ module.exports = { } }) } else { - return Promise.reject(new Error('Parent entry is not a valid file.')) + return Promise.reject(new Error(lang.t('errors:parentinvalid'))) } }) } else { - return Promise.reject(new Error('Parent entry is root.')) + return Promise.reject(new Error(lang.t('errors:parentisroot'))) } }, @@ -212,11 +212,11 @@ module.exports = { }) }) } else { - return Promise.reject(new Error('Entry does not exist!')) + return Promise.reject(new Error(lang.t('errors:notexist', { path: entryPath })) } }).catch((err) => { winston.error(err) - return Promise.reject(new Error('Failed to save document.')) + return Promise.reject(new Error(lang.t('errors:savefailed'))) }) }, @@ -316,11 +316,11 @@ module.exports = { }) }) } else { - return Promise.reject(new Error('Entry already exists!')) + return Promise.reject(new Error(lang.t('errors:alreadyexists'))) } }).catch((err) => { winston.error(err) - return Promise.reject(new Error('Something went wrong.')) + return Promise.reject(new Error(lang.t('errors:generic'))) }) }, @@ -352,7 +352,7 @@ module.exports = { let self = this if (_.isEmpty(entryPath) || entryPath === 'home') { - return Promise.reject(new Error('Invalid path!')) + return Promise.reject(new Error(lang.t('errors:invalidpath'))) } return git.moveDocument(entryPath, newEntryPath).then(() => { diff --git a/server/libs/git.js b/server/libs/git.js index 64a512bf..422f99fc 100644 --- a/server/libs/git.js +++ b/server/libs/git.js @@ -206,7 +206,7 @@ module.exports = { let out = cProc.stdout.toString() return _.includes(out, gitFilePath) }).then((isTracked) => { - commitMsg = (isTracked) ? 'Updated ' + gitFilePath : 'Added ' + gitFilePath + commitMsg = (isTracked) ? lang.t('git:updated', { path: gitFilePath }) : lang.t('git:added', { path: gitFilePath }) return self._git.add(gitFilePath) }).then(() => { let commitUsr = securityHelper.sanitizeCommitUser(author) diff --git a/server/libs/local.js b/server/libs/local.js index e624d23a..9507419c 100644 --- a/server/libs/local.js +++ b/server/libs/local.js @@ -163,7 +163,7 @@ module.exports = { let fpath = path.resolve(this._uploadsPath, fld, f) return fs.statAsync(fpath).then((s) => { - throw new Error('File ' + f + ' already exists.') + throw new Error(lang.t('errors:fileexists', { path: f })) }).catch((err) => { if (err.code === 'ENOENT') { return f diff --git a/server/libs/uploads-agent.js b/server/libs/uploads-agent.js index e0356d37..426ca964 100644 --- a/server/libs/uploads-agent.js +++ b/server/libs/uploads-agent.js @@ -59,14 +59,14 @@ module.exports = { return self.processFile(pInfo.folder, pInfo.filename).then((mData) => { return db.UplFile.findByIdAndUpdate(mData._id, mData, { upsert: true }) }).then(() => { - return git.commitUploads('Uploaded ' + p) + return git.commitUploads(lang.t('git:uploaded', { path: p })) }) }) // -> Remove upload file self._watcher.on('unlink', (p) => { - return git.commitUploads('Deleted/Renamed ' + p) + return git.commitUploads(lang.t('git:deleted', { path: p })) }) }, diff --git a/server/libs/uploads.js b/server/libs/uploads.js index 57986eda..931d774b 100644 --- a/server/libs/uploads.js +++ b/server/libs/uploads.js @@ -168,7 +168,7 @@ module.exports = { return upl.validateUploadsFolder(destFolder).then((destFolderPath) => { if (!destFolderPath) { - return Promise.reject(new Error('Invalid Folder')) + return Promise.reject(new Error(lang.t('errors:invalidfolder'))) } return lcdata.validateUploadsFilename(fUrlFilename, destFolder).then((destFilename) => { @@ -192,7 +192,7 @@ module.exports = { rq.abort() destFileStream.destroy() fs.remove(destFilePath) - reject(new Error('Remote file is too large!')) + reject(new Error(lang.t('errors:remotetoolarge'))) } }).on('error', (err) => { destFileStream.destroy() @@ -243,7 +243,7 @@ module.exports = { // -> Check for invalid operations if (sourceFilePath === destFilePath) { - return Promise.reject(new Error('Invalid Operation!')) + return Promise.reject(new Error(lang.t('errors:invalidoperation'))) } // -> Delete DB entry @@ -271,7 +271,7 @@ module.exports = { }) }) } else { - return Promise.reject(new Error('Invalid Destination Folder')) + return Promise.reject(new Error(lang.t('errors:invaliddestfolder'))) } }) } diff --git a/server/locales/en/auth.json b/server/locales/en/auth.json index dd61603e..aaa89b94 100644 --- a/server/locales/en/auth.json +++ b/server/locales/en/auth.json @@ -12,7 +12,9 @@ "errors": { "invalidlogin": "Invalid Login", "invalidloginmsg": "The email or password is invalid.", + "invaliduseremail": "Invalid User Email", "loginerror": "Login error", + "notyetauthorized": "You have not been authorized to login to this site yet.", "toomanyattempts": "Too many attempts!", "toomanyattemptsmsg": "You've made too many failed attempts in a short period of time, please try again {{time}}.", "usernotfound": "User not found" diff --git a/server/locales/en/common.json b/server/locales/en/common.json index d088a86f..a0d212bc 100644 --- a/server/locales/en/common.json +++ b/server/locales/en/common.json @@ -1,11 +1,54 @@ { "wiki": "Wiki", - "headers": { - "overview": "Overview" + "header": { + "overview": "Overview", + "createdoc": "Create New Document" }, "footer": { "poweredby": "Powered by", "home": "Home", "top": "Return to top" + }, + "search": { + "placeholder": "Search...", + "results": "Search Results", + "nomatch": "No results matching your query", + "didyoumean": "Did you mean...?" + }, + "sidebar": { + "nav": "NAV", + "navigation": "Navigation", + "pagecontents": "Page Contents", + "pastversions": "Past Versions" + }, + "nav": { + "home": "Home", + "account": "Account", + "myprofile": "My Profile", + "stats": "Stats", + "syssettings": "System Settings", + "users": "Users", + "logout": "Logout", + "create": "Create", + "edit": "Edit", + "history": "History", + "source": "Source", + "move": "Move", + "allpages": "All Pages", + "login": "Login", + "normalview": "Normal View", + "viewlatest": "View Latest", + "discard": "Discard", + "savechanges": "Save Changes", + "savedocument": "Save Document" + }, + "welcome": { + "title": "Welcome to your wiki!", + "subtitle": "Let's get started and create the home page.", + "createhome": "Create Home Page" + }, + "loading": { + "source": "Loading source...", + "editor": "Loading editor..." } -} \ No newline at end of file +} diff --git a/server/locales/en/errors.json b/server/locales/en/errors.json index 6f7cbc01..bbad04b3 100644 --- a/server/locales/en/errors.json +++ b/server/locales/en/errors.json @@ -1,17 +1,25 @@ { "alreadyexists": "This entry already exists!", "debugmsg": "Detailed debug trail", + "fileexists": "File {{path}} already exists.", "forbidden": "Forbidden", "forbiddendetail": "Sorry, you don't have the necessary permissions to access this page.", "generic": "Oops, something went wrong", "invalidaction": "Invalid Action.", + "invaliddestfolder": "Invalid Destination Folder!", "invalidfiletype": "Invalid File Type.", "invalidfolder": "Invalid Folder.", + "invalidoperation": "Invalid Operation!", "invalidpath": "Invalid page path.", "invaliduserid": "Invalid User Id", "newpasswordtooshort": "New password is too short!", + "notexist": "Entry {{path}} does not exist!", "notexistdetail": "Would you like to create this entry?", + "parentinvalid": "Parent entry is not a valid file.", + "parentisroot": "Parent entry is root.", + "remotetoolarge": "Remote file is too large!", "reservedname": "You cannot create a document with this name as it is reserved by the system.", + "savefailed": "Failed to save document", "starterfailed": "Could not load starter content!", "unauthorized": "Unauthorized", "actions": { diff --git a/server/locales/en/git.json b/server/locales/en/git.json new file mode 100644 index 00000000..284c06f5 --- /dev/null +++ b/server/locales/en/git.json @@ -0,0 +1,6 @@ +{ + "added": "Added {{path}}", + "deleted": "Deleted/Renamed {{path}}", + "updated": "Updated {{path}}", + "uploaded": "Uplodated {{path}}" +} diff --git a/server/models/user.js b/server/models/user.js index 9d953e64..16fdba2b 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -55,7 +55,7 @@ userSchema.statics.processProfile = (profile) => { } else if (profile.user && profile.user.email && profile.user.email.length > 5) { primaryEmail = profile.user.email } else { - return Promise.reject(new Error('Invalid User Email')) + return Promise.reject(new Error(lang.t('auth:errors.invaliduseremail'))) } profile.provider = _.lowerCase(profile.provider) @@ -89,7 +89,7 @@ userSchema.statics.processProfile = (profile) => { } return db.User.create(nUsr) } - return user || Promise.reject(new Error('You have not been authorized to login to this site yet.')) + return user || Promise.reject(new Error(lang.t('auth:errors:notyetauthorized'))) }) } @@ -99,7 +99,7 @@ userSchema.statics.hashPassword = (rawPwd) => { userSchema.methods.validatePassword = function (rawPwd) { return bcrypt.compare(rawPwd, this.password).then((isValid) => { - return (isValid) ? true : Promise.reject(new Error('Invalid Login')) + return (isValid) ? true : Promise.reject(new Error(lang.t('auth:errors:invalidlogin'))) }) } diff --git a/server/views/common/header.pug b/server/views/common/header.pug index aede12f2..135328e0 100644 --- a/server/views/common/header.pug +++ b/server/views/common/header.pug @@ -11,7 +11,7 @@ block rootNavCenter .nav-item p.control(v-bind:class='{ "is-loading": searchload > 0 }') - input.input#search-input(type='text', v-model='searchq', @keyup.esc='closeSearch', @keyup.down='moveDownSearch', @keyup.up='moveUpSearch', @keyup.enter='moveSelectSearch', debounce='400', placeholder='Search...') + input.input#search-input(type='text', v-model='searchq', @keyup.esc='closeSearch', @keyup.down='moveDownSearch', @keyup.up='moveUpSearch', @keyup.enter='moveSelectSearch', debounce='400', placeholder=t('search.placeholder')) span.nav-toggle span span @@ -22,13 +22,13 @@ transition(name='searchresults-anim', enter-active-class='slideInDown', leave-active-class='fadeOutUp') .searchresults.animated(v-show='searchactive', v-cloak, style={'display':'none'}) - p.searchresults-label Search Results + p.searchresults-label= t('search.results') ul.searchresults-list li(v-if='searchres.length === 0') - a: em No results matching your query + a: em= t('search.nomatch') li(v-for='sres in searchres', v-bind:class='{ "is-active": searchmovekey === "res." + sres.entryPath }') a(v-bind:href='"/" + sres.entryPath') {{ sres.title }} - p.searchresults-label(v-if='searchsuggest.length > 0') Did you mean...? + p.searchresults-label(v-if='searchsuggest.length > 0')= t('search.didyoumean') ul.searchresults-list(v-if='searchsuggest.length > 0') li(v-for='sug in searchsuggest', v-bind:class='{ "is-active": searchmovekey === "sug." + sug }') a(v-on:click='useSuggestion(sug)') {{ sug }} diff --git a/server/views/pages/admin/_layout.pug b/server/views/pages/admin/_layout.pug index c2d6c90d..dfcac89b 100644 --- a/server/views/pages/admin/_layout.pug +++ b/server/views/pages/admin/_layout.pug @@ -1,14 +1,14 @@ extends ../../layout.pug block rootNavCenter - h2.nav-item Account + h2.nav-item= t('nav.account') block rootNavRight i.nav-item#notifload .nav-item a.button.btn-edit-discard(href='/') i.icon-home - span Home + span= t('nav.home') block content @@ -20,38 +20,38 @@ block content aside .sidebar-label - span Navigation + span= t('sidebar.navigation') ul.sidebar-menu li a(href='/') i.icon-home - span Home + span= t('nav.home') aside .sidebar-label - span Account + span= t('nav.account') ul.sidebar-menu li a(href='/admin/profile') i.icon-user - span My Profile + span= t('nav.myprofile') li a(href='/admin/stats') i.icon-bar-graph-2 - span Stats + span= t('nav.stats') if rights.manage li a(href='/admin/users') i.icon-users - span Users + span= t('nav.users') li a(href='/admin/settings') i.icon-cog - span System Settings + span= t('nav.syssettings') li a(href='/logout') i.icon-delete2 - span Logout + span= t('nav.logout') .column block adminContent diff --git a/server/views/pages/all.pug b/server/views/pages/all.pug index fff7daeb..a88a4f5f 100644 --- a/server/views/pages/all.pug +++ b/server/views/pages/all.pug @@ -10,22 +10,22 @@ block content .sidebar.is-collapsed aside .sidebar-label - span NAV + span= t('sidebar.nav') ul.sidebar-menu li a(href='/') i.icon-home - span Home + span= t('nav.home') if !isGuest li a(href='/admin') i.icon-head - span Account + span= t('nav.account') else li a(href='/login') i.icon-unlock - span Login + span= t('nav.login') ul.collapsable-nav(v-for='treeItem in tree', :class='{ "has-children": treeItem.hasChildren }', v-cloak) li(v-for='page in treeItem.pages', :class='{ "is-active": page.isActive }') a(v-on:click='mainAction(page)') @@ -34,7 +34,7 @@ block content span {{ page.title }} template(v-else) i.icon-home - span Home + span= t('nav.home') a.is-pagelink(v-if='page.isDirectory && page.isEntry', v-on:click='goto(page._id)') i.icon-file-text-o i.icon-arrow-right2 diff --git a/server/views/pages/create.pug b/server/views/pages/create.pug index 80b52695..b1355a7d 100644 --- a/server/views/pages/create.pug +++ b/server/views/pages/create.pug @@ -1,17 +1,17 @@ extends ../layout.pug block rootNavCenter - h2.nav-item Create New Document + h2.nav-item= t('header.createdoc') block rootNavRight i.nav-item#notifload span.nav-item a.button.is-outlined.btn-create-discard i.icon-cross - span Discard + span= t('nav.discard') a.button.btn-create-save i.icon-check - span Save Document + span= t('nav.savedocument') block content @@ -29,4 +29,4 @@ block content block outside #page-loader i - span Loading editor... + span= t('loading.editor') diff --git a/server/views/pages/edit.pug b/server/views/pages/edit.pug index afb70c64..38d808fa 100644 --- a/server/views/pages/edit.pug +++ b/server/views/pages/edit.pug @@ -8,10 +8,10 @@ block rootNavRight span.nav-item a.button.is-outlined.btn-edit-discard i.icon-cross - span Discard + span= t('nav.discard') a.button.btn-edit-save i.icon-check - span Save Changes + span= t('nav.savechanges') block content @@ -29,4 +29,4 @@ block content block outside #page-loader i - span Loading editor... + span= t('loading.editor') diff --git a/server/views/pages/history.pug b/server/views/pages/history.pug index e9c94cb6..cfa6dafb 100644 --- a/server/views/pages/history.pug +++ b/server/views/pages/history.pug @@ -5,7 +5,7 @@ block rootNavRight .nav-item a.button(href='/' + pageData.meta._id) i.icon-circle-check - span View Latest + span= t('nav.viewlatest') block content @@ -17,7 +17,7 @@ block content aside.stickyscroll .sidebar-label - span Past versions + span= t('sidebar.pastversions') ul.sidebar-menu each item, index in pageData.history - var itemDate = moment(item.date) diff --git a/server/views/pages/source.pug b/server/views/pages/source.pug index e98a6106..ac40729e 100644 --- a/server/views/pages/source.pug +++ b/server/views/pages/source.pug @@ -9,17 +9,17 @@ block rootNavRight if rights.write a.button.is-outlined.btn-move-prompt.is-hidden i.icon-shuffle - span Move + span= t('nav.move') a.button.is-outlined(href='/' + pageData.meta.path) i.icon-loader - span Normal View + span= t('nav.normalview') if rights.write a.button.is-orange(href='/edit/' + pageData.meta.path) i.fa.fa-edit - span Edit + span= t('nav.edit') a.button.is-blue.btn-create-prompt i.fa.fa-plus - span Create + span= t('nav.create') block content @@ -33,4 +33,4 @@ block content block outside #page-loader i - span Loading source... + span= t('loading.source') diff --git a/server/views/pages/view.pug b/server/views/pages/view.pug index 797206b9..b2782650 100644 --- a/server/views/pages/view.pug +++ b/server/views/pages/view.pug @@ -14,20 +14,20 @@ block rootNavRight if rights.write a.button.is-outlined.btn-move-prompt.is-hidden i.icon-shuffle - span Move + span= t('nav.move') a.button.is-outlined(href='/source/' + pageData.meta.path) i.icon-loader - span Source + span= t('nav.source') a.button.is-outlined(href='/hist/' + pageData.meta.path) i.icon-clock - span History + span= t('nav.history') if rights.write a.button(href='/edit/' + pageData.meta.path) i.icon-document-text - span Edit + span= t('nav.edit') a.button.btn-create-prompt i.icon-plus - span Create + span= t('nav.create') block content @@ -39,16 +39,16 @@ block content aside .sidebar-label - span Navigation + span= t('sidebar.navigation') ul.sidebar-menu li a(href='/') i.icon-home - span Home + span= t('nav.home') li a(href='/all') i.icon-paper - span All Pages + span= t('nav.allpages') if pageData.parent li a(href='/' + pageData.parent.path) @@ -58,15 +58,15 @@ block content li a(href='/admin') i.icon-head - span Account + span= t('nav.account') else li a(href='/login') i.icon-unlock - span Login + span= t('nav.login') aside.stickyscroll .sidebar-label - span Page Contents + span= t('sidebar.pagecontents') ul.sidebar-menu li.is-hidden-until-scroll: a(href='#root', title='Top of Page') i.icon-arrow-up2 diff --git a/server/views/pages/welcome.pug b/server/views/pages/welcome.pug index b597deb6..dfaf79f0 100644 --- a/server/views/pages/welcome.pug +++ b/server/views/pages/welcome.pug @@ -11,6 +11,6 @@ block content .container .welcome img(src='/images/logo.png', alt='Wiki.js') - h1 Welcome to your wiki! - h2 Let's get started and create the home page. - a.button.is-indigo(href='/create/home') Create Home Page + h1= t('welcome.title') + h2= t('welcome.subtitle') + a.button.is-indigo(href='/create/home')= t('welcome.createhome')