]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'master' into translations 234/head
authorDan Brown <redacted>
Sat, 31 Dec 2016 14:32:52 +0000 (14:32 +0000)
committerGitHub <redacted>
Sat, 31 Dec 2016 14:32:52 +0000 (14:32 +0000)
137 files changed:
app/Http/Controllers/AttachmentController.php
app/Http/Controllers/Auth/ForgotPasswordController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/ResetPasswordController.php
app/Http/Controllers/BookController.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/HomeController.php
app/Http/Controllers/ImageController.php
app/Http/Controllers/PageController.php
app/Http/Controllers/PermissionController.php
app/Http/Controllers/SearchController.php
app/Http/Controllers/SettingController.php
app/Http/Controllers/TagController.php
app/Http/Controllers/UserController.php
app/Notifications/ResetPassword.php
app/Repos/BookRepo.php
app/Repos/ChapterRepo.php
app/Repos/PageRepo.php
app/Repos/PermissionsRepo.php
app/Repos/TagRepo.php
app/Repos/UserRepo.php
app/Services/AttachmentService.php
app/Services/EmailConfirmationService.php
app/Services/ImageService.php
app/Services/LdapService.php
app/Services/SocialAuthService.php
config/setting-defaults.php
phpunit.xml
resources/assets/js/controllers.js
resources/assets/js/directives.js
resources/assets/js/global.js
resources/assets/js/pages/page-form.js
resources/assets/js/pages/page-show.js
resources/assets/js/translations.js [new file with mode: 0644]
resources/assets/sass/_components.scss
resources/assets/sass/_forms.scss
resources/assets/sass/_lists.scss
resources/assets/sass/_tables.scss
resources/assets/sass/_text.scss
resources/lang/de/settings.php
resources/lang/en/auth.php
resources/lang/en/common.php [new file with mode: 0644]
resources/lang/en/components.php [new file with mode: 0644]
resources/lang/en/entities.php [new file with mode: 0644]
resources/lang/en/errors.php
resources/lang/en/settings.php
resources/lang/en/validation.php
resources/views/auth/forms/login/ldap.blade.php
resources/views/auth/forms/login/standard.blade.php
resources/views/auth/login.blade.php
resources/views/auth/passwords/email.blade.php
resources/views/auth/passwords/reset.blade.php
resources/views/auth/register-confirm.blade.php
resources/views/auth/register.blade.php
resources/views/auth/user-unconfirmed.blade.php
resources/views/base.blade.php
resources/views/books/_breadcrumbs.blade.php [new file with mode: 0644]
resources/views/books/create.blade.php
resources/views/books/delete.blade.php
resources/views/books/edit.blade.php
resources/views/books/form.blade.php
resources/views/books/index.blade.php
resources/views/books/restrictions.blade.php
resources/views/books/show.blade.php
resources/views/books/sort.blade.php
resources/views/chapters/_breadcrumbs.blade.php [new file with mode: 0644]
resources/views/chapters/create.blade.php
resources/views/chapters/delete.blade.php
resources/views/chapters/edit.blade.php
resources/views/chapters/form.blade.php
resources/views/chapters/list-item.blade.php
resources/views/chapters/move.blade.php
resources/views/chapters/restrictions.blade.php
resources/views/chapters/show.blade.php
resources/views/components/entity-selector-popup.blade.php [moved from resources/views/partials/entity-selector-popup.blade.php with 63% similarity]
resources/views/components/entity-selector.blade.php [moved from resources/views/partials/entity-selector.blade.php with 66% similarity]
resources/views/components/image-manager.blade.php [moved from resources/views/partials/image-manager.blade.php with 70% similarity]
resources/views/components/image-picker.blade.php [new file with mode: 0644]
resources/views/components/toggle-switch.blade.php [new file with mode: 0644]
resources/views/errors/404.blade.php
resources/views/errors/500.blade.php
resources/views/errors/503.blade.php
resources/views/form/delete-button.blade.php
resources/views/form/restriction-form.blade.php
resources/views/home.blade.php
resources/views/pages/_breadcrumbs.blade.php [new file with mode: 0644]
resources/views/pages/delete.blade.php
resources/views/pages/edit.blade.php
resources/views/pages/export.blade.php
resources/views/pages/form-toolbox.blade.php
resources/views/pages/form.blade.php
resources/views/pages/guest-create.blade.php
resources/views/pages/list-item.blade.php
resources/views/pages/move.blade.php
resources/views/pages/pdf.blade.php
resources/views/pages/restrictions.blade.php
resources/views/pages/revision.blade.php
resources/views/pages/revisions.blade.php
resources/views/pages/show.blade.php
resources/views/pages/sidebar-tree-list.blade.php
resources/views/partials/_header-dropdown.blade.php [new file with mode: 0644]
resources/views/partials/activity-item.blade.php
resources/views/partials/activity-list.blade.php
resources/views/partials/custom-styles.blade.php
resources/views/partials/entity-list.blade.php
resources/views/partials/entity-meta.blade.php [new file with mode: 0644]
resources/views/public.blade.php
resources/views/search/all.blade.php
resources/views/search/book.blade.php
resources/views/search/entity-ajax-list.blade.php
resources/views/search/entity-search-list.blade.php
resources/views/settings/index.blade.php
resources/views/settings/navbar.blade.php
resources/views/settings/roles/create.blade.php
resources/views/settings/roles/delete.blade.php
resources/views/settings/roles/edit.blade.php
resources/views/settings/roles/form.blade.php
resources/views/settings/roles/index.blade.php
resources/views/users/create.blade.php
resources/views/users/delete.blade.php
resources/views/users/edit.blade.php
resources/views/users/forms/ldap.blade.php
resources/views/users/forms/standard.blade.php
resources/views/users/forms/system.blade.php
resources/views/users/index.blade.php
resources/views/users/profile.blade.php
resources/views/vendor/notifications/email-plain.blade.php
resources/views/vendor/notifications/email.blade.php
routes/web.php
tests/Auth/AuthTest.php
tests/Auth/LdapTest.php
tests/Entity/EntitySearchTest.php
tests/Entity/EntityTest.php
tests/Entity/SortTest.php
tests/Permissions/RolesTest.php
tests/PublicActionTest.php

index 62be0b852236f9109249e17834f32ae85ae7eaee..b5e7db41ee3aa89d76f37faee3eee3406c7dd056 100644 (file)
@@ -77,7 +77,7 @@ class AttachmentController extends Controller
         $this->checkOwnablePermission('attachment-create', $attachment);
         
         if (intval($pageId) !== intval($attachment->uploaded_to)) {
-            return $this->jsonError('Page mismatch during attached file update');
+            return $this->jsonError(trans('errors.attachment_page_mismatch'));
         }
 
         $uploadedFile = $request->file('file');
@@ -113,11 +113,11 @@ class AttachmentController extends Controller
         $this->checkOwnablePermission('attachment-create', $attachment);
 
         if (intval($pageId) !== intval($attachment->uploaded_to)) {
-            return $this->jsonError('Page mismatch during attachment update');
+            return $this->jsonError(trans('errors.attachment_page_mismatch'));
         }
 
         $attachment = $this->attachmentService->updateFile($attachment, $request->all());
-        return $attachment;
+        return response()->json($attachment);
     }
 
     /**
@@ -175,7 +175,7 @@ class AttachmentController extends Controller
 
         $attachments = $request->get('files');
         $this->attachmentService->updateFileOrderWithinPage($attachments, $pageId);
-        return response()->json(['message' => 'Attachment order updated']);
+        return response()->json(['message' => trans('entities.attachments_order_updated')]);
     }
 
     /**
@@ -210,6 +210,6 @@ class AttachmentController extends Controller
         $attachment = $this->attachment->findOrFail($attachmentId);
         $this->checkOwnablePermission('attachment-delete', $attachment);
         $this->attachmentService->deleteFile($attachment);
-        return response()->json(['message' => 'Attachment deleted']);
+        return response()->json(['message' => trans('entities.attachments_deleted')]);
     }
 }
index 45e40e6fe8371a5d8034ca2d5627f2ff63621acc..d1fbddc509593e347e8a5b789d2792c2d2abd071 100644 (file)
@@ -52,7 +52,7 @@ class ForgotPasswordController extends Controller
         );
 
         if ($response === Password::RESET_LINK_SENT) {
-            $message = 'A password reset link has been sent to ' . $request->get('email') . '.';
+            $message = trans('auth.reset_password_sent_success', ['email' => $request->get('email')]);
             session()->flash('success', $message);
             return back()->with('status', trans($response));
         }
index c9d6a5496ef8c99d3f2fd80feaa835641d22ec34..e7eeb9bc1629d2ed94441458f6435e0b22ff8982 100644 (file)
@@ -87,7 +87,7 @@ class LoginController extends Controller
             // Check for users with same email already
             $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0;
             if ($alreadyUser) {
-                throw new AuthException('A user with the email ' . $user->email . ' already exists but with different credentials.');
+                throw new AuthException(trans('errors.error_user_exists_different_creds', ['email' => $user->email]));
             }
 
             $user->save();
index d9bb500b448cdbfa230c614b414a7b8f5332f247..8b0ef309aeba8c61d156a4fd0692dbc94e2ba712 100644 (file)
@@ -3,6 +3,7 @@
 namespace BookStack\Http\Controllers\Auth;
 
 use BookStack\Exceptions\ConfirmationEmailException;
+use BookStack\Exceptions\SocialSignInException;
 use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Repos\UserRepo;
 use BookStack\Services\EmailConfirmationService;
@@ -82,7 +83,7 @@ class RegisterController extends Controller
     protected function checkRegistrationAllowed()
     {
         if (!setting('registration-enabled')) {
-            throw new UserRegistrationException('Registrations are currently disabled.', '/login');
+            throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
         }
     }
 
@@ -147,7 +148,7 @@ class RegisterController extends Controller
             $restrictedEmailDomains = explode(',', str_replace(' ', '', setting('registration-restrict')));
             $userEmailDomain = $domain = substr(strrchr($userData['email'], "@"), 1);
             if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
-                throw new UserRegistrationException('That email domain does not have access to this application', '/register');
+                throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), '/register');
             }
         }
 
@@ -169,7 +170,7 @@ class RegisterController extends Controller
         }
 
         auth()->login($newUser);
-        session()->flash('success', 'Thanks for signing up! You are now registered and signed in.');
+        session()->flash('success', trans('auth.register_success'));
         return redirect($this->redirectPath());
     }
 
@@ -262,7 +263,7 @@ class RegisterController extends Controller
                 return $this->socialRegisterCallback($socialDriver);
             }
         } else {
-            throw new SocialSignInException('No action defined', '/login');
+            throw new SocialSignInException(trans('errors.social_no_action_defined'), '/login');
         }
         return redirect()->back();
     }
index bd64793f9223078d375da6577af9a01cfd1a9fae..eb678503d80828e7a7e700e42f2f335d252a20f4 100644 (file)
@@ -41,7 +41,7 @@ class ResetPasswordController extends Controller
      */
     protected function sendResetResponse($response)
     {
-        $message = 'Your password has been successfully reset.';
+        $message = trans('auth.reset_password_success');
         session()->flash('success', $message);
         return redirect($this->redirectPath())
             ->with('status', trans($response));
index 8ada594335292b93c5ffb7a6d7a89dd5e440bdcb..80a6c24b3c40686e81b1a036fe636eb24ff8d8d9 100644 (file)
@@ -7,6 +7,7 @@ use BookStack\Http\Requests;
 use BookStack\Repos\BookRepo;
 use BookStack\Repos\ChapterRepo;
 use BookStack\Repos\PageRepo;
+use Illuminate\Http\Response;
 use Views;
 
 class BookController extends Controller
@@ -53,7 +54,7 @@ class BookController extends Controller
     public function create()
     {
         $this->checkPermission('book-create-all');
-        $this->setPageTitle('Create New Book');
+        $this->setPageTitle(trans('entities.books_create'));
         return view('books/create');
     }
 
@@ -99,7 +100,7 @@ class BookController extends Controller
     {
         $book = $this->bookRepo->getBySlug($slug);
         $this->checkOwnablePermission('book-update', $book);
-        $this->setPageTitle('Edit Book ' . $book->getShortName());
+        $this->setPageTitle(trans('entities.books_edit_named',['bookName'=>$book->getShortName()]));
         return view('books/edit', ['book' => $book, 'current' => $book]);
     }
 
@@ -131,7 +132,7 @@ class BookController extends Controller
     {
         $book = $this->bookRepo->getBySlug($bookSlug);
         $this->checkOwnablePermission('book-delete', $book);
-        $this->setPageTitle('Delete Book ' . $book->getShortName());
+        $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()]));
         return view('books/delete', ['book' => $book, 'current' => $book]);
     }
 
@@ -146,7 +147,7 @@ class BookController extends Controller
         $this->checkOwnablePermission('book-update', $book);
         $bookChildren = $this->bookRepo->getChildren($book, true);
         $books = $this->bookRepo->getAll(false);
-        $this->setPageTitle('Sort Book ' . $book->getShortName());
+        $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()]));
         return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]);
     }
 
@@ -264,7 +265,7 @@ class BookController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $book);
         $this->bookRepo->updateEntityPermissionsFromRequest($request, $book);
-        session()->flash('success', 'Book Restrictions Updated');
+        session()->flash('success', trans('entities.books_permissions_updated'));
         return redirect($book->getUrl());
     }
 }
index a3fb600fd037b82adb0850cf7549fe7fd74c0703..84983518514d8342f9fbba4aeb63a7a34bd82887 100644 (file)
@@ -3,9 +3,9 @@
 use Activity;
 use BookStack\Repos\UserRepo;
 use Illuminate\Http\Request;
-use BookStack\Http\Requests;
 use BookStack\Repos\BookRepo;
 use BookStack\Repos\ChapterRepo;
+use Illuminate\Http\Response;
 use Views;
 
 class ChapterController extends Controller
@@ -38,7 +38,7 @@ class ChapterController extends Controller
     {
         $book = $this->bookRepo->getBySlug($bookSlug);
         $this->checkOwnablePermission('chapter-create', $book);
-        $this->setPageTitle('Create New Chapter');
+        $this->setPageTitle(trans('entities.chapters_create'));
         return view('chapters/create', ['book' => $book, 'current' => $book]);
     }
 
@@ -99,7 +99,7 @@ class ChapterController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
         $this->checkOwnablePermission('chapter-update', $chapter);
-        $this->setPageTitle('Edit Chapter' . $chapter->getShortName());
+        $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()]));
         return view('chapters/edit', ['book' => $book, 'chapter' => $chapter, 'current' => $chapter]);
     }
 
@@ -136,7 +136,7 @@ class ChapterController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
         $this->checkOwnablePermission('chapter-delete', $chapter);
-        $this->setPageTitle('Delete Chapter' . $chapter->getShortName());
+        $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()]));
         return view('chapters/delete', ['book' => $book, 'chapter' => $chapter, 'current' => $chapter]);
     }
 
@@ -166,6 +166,7 @@ class ChapterController extends Controller
     public function showMove($bookSlug, $chapterSlug) {
         $book = $this->bookRepo->getBySlug($bookSlug);
         $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
+        $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()]));
         $this->checkOwnablePermission('chapter-update', $chapter);
         return view('chapters/move', [
             'chapter' => $chapter,
@@ -202,13 +203,13 @@ class ChapterController extends Controller
         }
 
         if ($parent === false || $parent === null) {
-            session()->flash('The selected Book was not found');
+            session()->flash('error', trans('errors.selected_book_not_found'));
             return redirect()->back();
         }
 
         $this->chapterRepo->changeBook($parent->id, $chapter, true);
         Activity::add($chapter, 'chapter_move', $chapter->book->id);
-        session()->flash('success', sprintf('Chapter moved to "%s"', $parent->name));
+        session()->flash('success', trans('entities.chapter_move_success', ['bookName' => $parent->name]));
 
         return redirect($chapter->getUrl());
     }
@@ -244,7 +245,7 @@ class ChapterController extends Controller
         $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
         $this->checkOwnablePermission('restrictions-manage', $chapter);
         $this->chapterRepo->updateEntityPermissionsFromRequest($request, $chapter);
-        session()->flash('success', 'Chapter Restrictions Updated');
+        session()->flash('success', trans('entities.chapters_permissions_success'));
         return redirect($chapter->getUrl());
     }
 }
index 2fc64b2368c9a59d3fa302b5f5d0ea44a6dc3fb9..e325b93229868c60bd7135068953f90b8603cd7d 100644 (file)
@@ -43,4 +43,39 @@ class HomeController extends Controller
         ]);
     }
 
+    /**
+     * Get a js representation of the current translations
+     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
+     */
+    public function getTranslations() {
+        $locale = trans()->getLocale();
+        $cacheKey = 'GLOBAL_TRANSLATIONS_' . $locale;
+        if (cache()->has($cacheKey) && config('app.env') !== 'development') {
+            $resp = cache($cacheKey);
+        } else {
+            $translations = [
+                // Get only translations which might be used in JS
+                'common' => trans('common'),
+                'components' => trans('components'),
+                'entities' => trans('entities'),
+                'errors' => trans('errors')
+            ];
+            if ($locale !== 'en') {
+                $enTrans = [
+                    'common' => trans('common', [], null, 'en'),
+                    'components' => trans('components', [], null, 'en'),
+                    'entities' => trans('entities', [], null, 'en'),
+                    'errors' => trans('errors', [], null, 'en')
+                ];
+                $translations = array_replace_recursive($enTrans, $translations);
+            }
+            $resp = 'window.translations = ' . json_encode($translations);
+            cache()->put($cacheKey, $resp, 120);
+        }
+
+        return response($resp, 200, [
+            'Content-Type' => 'application/javascript'
+        ]);
+    }
+
 }
index 621c23e85d576e1cf4a777c80eb07c1dc5b55ee6..f073bea0afbd7ea890fbaaee899e7597409cf669 100644 (file)
@@ -73,6 +73,7 @@ class ImageController extends Controller
      * @param $filter
      * @param int $page
      * @param Request $request
+     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
      */
     public function getGalleryFiltered($filter, $page = 0, Request $request)
     {
@@ -169,7 +170,7 @@ class ImageController extends Controller
         }
 
         $this->imageRepo->destroyImage($image);
-        return response()->json('Image Deleted');
+        return response()->json(trans('components.images_deleted'));
     }
 
 
index c2d8e257cb33297e28b49c448075017de8a0ad70..e40d7668a4fedd3fe46d747b3ab10e0830274a6f 100644 (file)
@@ -10,6 +10,7 @@ use BookStack\Http\Requests;
 use BookStack\Repos\BookRepo;
 use BookStack\Repos\ChapterRepo;
 use BookStack\Repos\PageRepo;
+use Illuminate\Http\Response;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Views;
 use GatherContent\Htmldiff\Htmldiff;
@@ -62,7 +63,7 @@ class PageController extends Controller
         }
 
         // Otherwise show edit view
-        $this->setPageTitle('Create New Page');
+        $this->setPageTitle(trans('entities.pages_new'));
         return view('pages/guest-create', ['parent' => $parent]);
     }
 
@@ -104,7 +105,7 @@ class PageController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $draft = $this->pageRepo->getById($pageId, true);
         $this->checkOwnablePermission('page-create', $book);
-        $this->setPageTitle('Edit Page Draft');
+        $this->setPageTitle(trans('entities.pages_edit_draft'));
 
         $draftsEnabled = $this->signedIn;
         return view('pages/edit', [
@@ -119,6 +120,7 @@ class PageController extends Controller
      * Store a new page by changing a draft into a page.
      * @param  Request $request
      * @param  string $bookSlug
+     * @param  int $pageId
      * @return Response
      */
     public function store(Request $request, $bookSlug, $pageId)
@@ -201,7 +203,7 @@ class PageController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
         $this->checkOwnablePermission('page-update', $page);
-        $this->setPageTitle('Editing Page ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_editing_named', ['pageName'=>$page->getShortName()]));
         $page->isDraft = false;
 
         // Check for active editing
@@ -265,7 +267,7 @@ class PageController extends Controller
         if (!$this->signedIn) {
             return response()->json([
                 'status' => 'error',
-                'message' => 'Guests cannot save drafts',
+                'message' => trans('errors.guests_cannot_save_drafts'),
             ], 500);
         }
 
@@ -279,7 +281,7 @@ class PageController extends Controller
         $utcUpdateTimestamp = $updateTime + Carbon::createFromTimestamp(0)->offset;
         return response()->json([
             'status'    => 'success',
-            'message'   => 'Draft saved at ',
+            'message'   => trans('entities.pages_edit_draft_save_at'),
             'timestamp' => $utcUpdateTimestamp
         ]);
     }
@@ -307,7 +309,7 @@ class PageController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
         $this->checkOwnablePermission('page-delete', $page);
-        $this->setPageTitle('Delete Page ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_delete_named', ['pageName'=>$page->getShortName()]));
         return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]);
     }
 
@@ -324,7 +326,7 @@ class PageController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $page = $this->pageRepo->getById($pageId, true);
         $this->checkOwnablePermission('page-update', $page);
-        $this->setPageTitle('Delete Draft Page ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName'=>$page->getShortName()]));
         return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]);
     }
 
@@ -341,7 +343,7 @@ class PageController extends Controller
         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
         $this->checkOwnablePermission('page-delete', $page);
         Activity::addMessage('page_delete', $book->id, $page->name);
-        session()->flash('success', 'Page deleted');
+        session()->flash('success', trans('entities.pages_delete_success'));
         $this->pageRepo->destroy($page);
         return redirect($book->getUrl());
     }
@@ -358,7 +360,7 @@ class PageController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $page = $this->pageRepo->getById($pageId, true);
         $this->checkOwnablePermission('page-update', $page);
-        session()->flash('success', 'Draft deleted');
+        session()->flash('success', trans('entities.pages_delete_draft_success'));
         $this->pageRepo->destroy($page);
         return redirect($book->getUrl());
     }
@@ -373,7 +375,7 @@ class PageController extends Controller
     {
         $book = $this->bookRepo->getBySlug($bookSlug);
         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
-        $this->setPageTitle('Revisions For ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName'=>$page->getShortName()]));
         return view('pages/revisions', ['page' => $page, 'book' => $book, 'current' => $page]);
     }
 
@@ -391,7 +393,7 @@ class PageController extends Controller
         $revision = $this->pageRepo->getRevisionById($revisionId);
 
         $page->fill($revision->toArray());
-        $this->setPageTitle('Page Revision For ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
         
         return view('pages/revision', [
             'page' => $page,
@@ -417,7 +419,7 @@ class PageController extends Controller
         $diff = (new Htmldiff)->diff($prevContent, $revision->html);
 
         $page->fill($revision->toArray());
-        $this->setPageTitle('Page Revision For ' . $page->getShortName());
+        $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
 
         return view('pages/revision', [
             'page' => $page,
@@ -503,7 +505,7 @@ class PageController extends Controller
     {
         $pages = $this->pageRepo->getRecentlyCreatedPaginated(20)->setPath(baseUrl('/pages/recently-created'));
         return view('pages/detailed-listing', [
-            'title' => 'Recently Created Pages',
+            'title' => trans('entities.recently_created_pages'),
             'pages' => $pages
         ]);
     }
@@ -516,7 +518,7 @@ class PageController extends Controller
     {
         $pages = $this->pageRepo->getRecentlyUpdatedPaginated(20)->setPath(baseUrl('/pages/recently-updated'));
         return view('pages/detailed-listing', [
-            'title' => 'Recently Updated Pages',
+            'title' => trans('entities.recently_updated_pages'),
             'pages' => $pages
         ]);
     }
@@ -589,13 +591,13 @@ class PageController extends Controller
         }
 
         if ($parent === false || $parent === null) {
-            session()->flash('The selected Book or Chapter was not found');
+            session()->flash(trans('entities.selected_book_chapter_not_found'));
             return redirect()->back();
         }
 
         $this->pageRepo->changePageParent($page, $parent);
         Activity::add($page, 'page_move', $page->book->id);
-        session()->flash('success', sprintf('Page moved to "%s"', $parent->name));
+        session()->flash('success', trans('entities.pages_move_success', ['parentName' => $parent->name]));
 
         return redirect($page->getUrl());
     }
@@ -613,7 +615,7 @@ class PageController extends Controller
         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
         $this->checkOwnablePermission('restrictions-manage', $page);
         $this->pageRepo->updateEntityPermissionsFromRequest($request, $page);
-        session()->flash('success', 'Page Permissions Updated');
+        session()->flash('success', trans('entities.pages_permissions_success'));
         return redirect($page->getUrl());
     }
 
index ed430c0b7194e09717e3b4d9aeb06f14aad4ad9d..cd064e7e80675e47188d0b02644926f94cfb8769 100644 (file)
@@ -2,9 +2,7 @@
 
 use BookStack\Exceptions\PermissionsException;
 use BookStack\Repos\PermissionsRepo;
-use BookStack\Services\PermissionService;
 use Illuminate\Http\Request;
-use BookStack\Http\Requests;
 
 class PermissionController extends Controller
 {
@@ -55,7 +53,7 @@ class PermissionController extends Controller
         ]);
 
         $this->permissionsRepo->saveNewRole($request->all());
-        session()->flash('success', 'Role successfully created');
+        session()->flash('success', trans('settings.role_create_success'));
         return redirect('/settings/roles');
     }
 
@@ -69,7 +67,7 @@ class PermissionController extends Controller
     {
         $this->checkPermission('user-roles-manage');
         $role = $this->permissionsRepo->getRoleById($id);
-        if ($role->hidden) throw new PermissionsException('This role cannot be edited');
+        if ($role->hidden) throw new PermissionsException(trans('errors.role_cannot_be_edited'));
         return view('settings/roles/edit', ['role' => $role]);
     }
 
@@ -88,7 +86,7 @@ class PermissionController extends Controller
         ]);
 
         $this->permissionsRepo->updateRole($id, $request->all());
-        session()->flash('success', 'Role successfully updated');
+        session()->flash('success', trans('settings.role_update_success'));
         return redirect('/settings/roles');
     }
 
@@ -103,7 +101,7 @@ class PermissionController extends Controller
         $this->checkPermission('user-roles-manage');
         $role = $this->permissionsRepo->getRoleById($id);
         $roles = $this->permissionsRepo->getAllRolesExcept($role);
-        $blankRole = $role->newInstance(['display_name' => 'Don\'t migrate users']);
+        $blankRole = $role->newInstance(['display_name' => trans('settings.role_delete_no_migration')]);
         $roles->prepend($blankRole);
         return view('settings/roles/delete', ['role' => $role, 'roles' => $roles]);
     }
@@ -126,7 +124,7 @@ class PermissionController extends Controller
             return redirect()->back();
         }
 
-        session()->flash('success', 'Role successfully deleted');
+        session()->flash('success', trans('settings.role_delete_success'));
         return redirect('/settings/roles');
     }
 }
index 58ad737c4b431afa7cc5f982d4ec5fc9ffc6211c..bb70b0f88cbc9e6ad07141cd49c51127af70c080 100644 (file)
@@ -1,11 +1,7 @@
-<?php
-
-namespace BookStack\Http\Controllers;
+<?php namespace BookStack\Http\Controllers;
 
 use BookStack\Services\ViewService;
 use Illuminate\Http\Request;
-
-use BookStack\Http\Requests;
 use BookStack\Repos\BookRepo;
 use BookStack\Repos\ChapterRepo;
 use BookStack\Repos\PageRepo;
@@ -49,7 +45,7 @@ class SearchController extends Controller
         $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
         $books = $this->bookRepo->getBySearch($searchTerm, 10, $paginationAppends);
         $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 10, $paginationAppends);
-        $this->setPageTitle('Search For ' . $searchTerm);
+        $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
         return view('search/all', [
             'pages'      => $pages,
             'books'      => $books,
@@ -70,10 +66,10 @@ class SearchController extends Controller
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
         $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
-        $this->setPageTitle('Page Search For ' . $searchTerm);
+        $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $pages,
-            'title'      => 'Page Search Results',
+            'title'      => trans('entities.search_results_page'),
             'searchTerm' => $searchTerm
         ]);
     }
@@ -90,10 +86,10 @@ class SearchController extends Controller
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
         $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 20, $paginationAppends);
-        $this->setPageTitle('Chapter Search For ' . $searchTerm);
+        $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $chapters,
-            'title'      => 'Chapter Search Results',
+            'title'      => trans('entities.search_results_chapter'),
             'searchTerm' => $searchTerm
         ]);
     }
@@ -110,10 +106,10 @@ class SearchController extends Controller
         $searchTerm = $request->get('term');
         $paginationAppends = $request->only('term');
         $books = $this->bookRepo->getBySearch($searchTerm, 20, $paginationAppends);
-        $this->setPageTitle('Book Search For ' . $searchTerm);
+        $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm]));
         return view('search/entity-search-list', [
             'entities'   => $books,
-            'title'      => 'Book Search Results',
+            'title'      => trans('entities.search_results_book'),
             'searchTerm' => $searchTerm
         ]);
     }
index 65135eda3816079eea164c229acd89d9e57fe9ad..70a12631a2929d43424149208a79350697caaa4b 100644 (file)
@@ -1,8 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Illuminate\Http\Request;
-
-use BookStack\Http\Requests;
+use Illuminate\Http\Response;
 use Setting;
 
 class SettingController extends Controller
@@ -39,7 +38,7 @@ class SettingController extends Controller
             Setting::put($key, $value);
         }
 
-        session()->flash('success', 'Settings Saved');
+        session()->flash('success', trans('settings.settings_save_success'));
         return redirect('/settings');
     }
 
index c8a35654108ca6bde5d3429515711d702342b8e2..24bdcdb1c1af2e173684215806c1fef5138b10b6 100644 (file)
@@ -2,7 +2,6 @@
 
 use BookStack\Repos\TagRepo;
 use Illuminate\Http\Request;
-use BookStack\Http\Requests;
 
 class TagController extends Controller
 {
@@ -16,12 +15,14 @@ class TagController extends Controller
     public function __construct(TagRepo $tagRepo)
     {
         $this->tagRepo = $tagRepo;
+        parent::__construct();
     }
 
     /**
      * Get all the Tags for a particular entity
      * @param $entityType
      * @param $entityId
+     * @return \Illuminate\Http\JsonResponse
      */
     public function getForEntity($entityType, $entityId)
     {
@@ -29,29 +30,10 @@ class TagController extends Controller
         return response()->json($tags);
     }
 
-    /**
-     * Update the tags for a particular entity.
-     * @param $entityType
-     * @param $entityId
-     * @param Request $request
-     * @return mixed
-     */
-    public function updateForEntity($entityType, $entityId, Request $request)
-    {
-        $entity = $this->tagRepo->getEntity($entityType, $entityId, 'update');
-        if ($entity === null) return $this->jsonError("Entity not found", 404);
-
-        $inputTags = $request->input('tags');
-        $tags = $this->tagRepo->saveTagsToEntity($entity, $inputTags);
-        return response()->json([
-            'tags' => $tags,
-            'message' => 'Tags successfully updated'
-        ]);
-    }
-
     /**
      * Get tag name suggestions from a given search term.
      * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
      */
     public function getNameSuggestions(Request $request)
     {
@@ -63,6 +45,7 @@ class TagController extends Controller
     /**
      * Get tag value suggestions from a given search term.
      * @param Request $request
+     * @return \Illuminate\Http\JsonResponse
      */
     public function getValueSuggestions(Request $request)
     {
index 18ef1a671844fc4943e7df9673f62de42bcc5cea..b5184c40acace93088c439b0b2eb3383ef4e8a56 100644 (file)
@@ -44,7 +44,7 @@ class UserController extends Controller
             'sort' => $request->has('sort') ? $request->get('sort') : 'name',
         ];
         $users = $this->userRepo->getAllUsersPaginatedAndSorted(20, $listDetails);
-        $this->setPageTitle('Users');
+        $this->setPageTitle(trans('settings.users'));
         $users->appends($listDetails);
         return view('users/index', ['users' => $users, 'listDetails' => $listDetails]);
     }
@@ -83,7 +83,6 @@ class UserController extends Controller
         }
         $this->validate($request, $validationRules);
 
-
         $user = $this->user->fill($request->all());
 
         if ($authMethod === 'standard') {
@@ -131,7 +130,7 @@ class UserController extends Controller
         $authMethod = ($user->system_name) ? 'system' : config('auth.method');
 
         $activeSocialDrivers = $socialAuthService->getActiveDrivers();
-        $this->setPageTitle('User Profile');
+        $this->setPageTitle(trans('settings.user_profile'));
         $roles = $this->userRepo->getAllRoles();
         return view('users/edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]);
     }
@@ -154,8 +153,6 @@ class UserController extends Controller
             'email'            => 'min:2|email|unique:users,email,' . $id,
             'password'         => 'min:5|required_with:password_confirm',
             'password-confirm' => 'same:password|required_with:password'
-        ], [
-            'password-confirm.required_with' => 'Password confirmation required'
         ]);
 
         $user = $this->user->findOrFail($id);
@@ -179,7 +176,7 @@ class UserController extends Controller
         }
 
         $user->save();
-        session()->flash('success', 'User successfully updated');
+        session()->flash('success', trans('settings.users_edit_success'));
 
         $redirectUrl = userCan('users-manage') ? '/settings/users' : '/settings/users/' . $user->id;
         return redirect($redirectUrl);
@@ -197,7 +194,7 @@ class UserController extends Controller
         });
 
         $user = $this->user->findOrFail($id);
-        $this->setPageTitle('Delete User ' . $user->name);
+        $this->setPageTitle(trans('settings.users_delete_named', ['userName' => $user->name]));
         return view('users/delete', ['user' => $user]);
     }
 
@@ -216,17 +213,17 @@ class UserController extends Controller
         $user = $this->userRepo->getById($id);
 
         if ($this->userRepo->isOnlyAdmin($user)) {
-            session()->flash('error', 'You cannot delete the only admin');
+            session()->flash('error', trans('errors.users_cannot_delete_only_admin'));
             return redirect($user->getEditUrl());
         }
 
         if ($user->system_name === 'public') {
-            session()->flash('error', 'You cannot delete the guest user');
+            session()->flash('error', trans('errors.users_cannot_delete_guest'));
             return redirect($user->getEditUrl());
         }
 
         $this->userRepo->destroy($user);
-        session()->flash('success', 'User successfully removed');
+        session()->flash('success', trans('settings.users_delete_success'));
 
         return redirect('/settings/users');
     }
index 646030a103f6f9ff648d602753ce807147ca91ca..affd8f07638330d2bc70acfbceb8e2c0150c2980 100644 (file)
@@ -43,8 +43,9 @@ class ResetPassword extends Notification
     public function toMail()
     {
         return (new MailMessage)
-            ->line('You are receiving this email because we received a password reset request for your account.')
-            ->action('Reset Password', baseUrl('password/reset/' . $this->token))
-            ->line('If you did not request a password reset, no further action is required.');
+            ->subject(trans('auth.email_reset_subject', ['appName' => setting('app-name')]))
+            ->line(trans('auth.email_reset_text'))
+            ->action(trans('auth.reset_password'), baseUrl('password/reset/' . $this->token))
+            ->line(trans('auth.email_reset_not_requested'));
     }
 }
index 7bb91f4723d84efe49d01897e5f3766520554a1b..b14cf0dabc205e24979e911b69df89fc9a000f88 100644 (file)
@@ -109,7 +109,7 @@ class BookRepo extends EntityRepo
     public function getBySlug($slug)
     {
         $book = $this->bookQuery()->where('slug', '=', $slug)->first();
-        if ($book === null) throw new NotFoundException('Book not found');
+        if ($book === null) throw new NotFoundException(trans('errors.book_not_found'));
         return $book;
     }
 
index 4c13b9aafd3c4c95d0c13367261629e43329cd3e..4106f93ee32e27ee7f3bfde0b759b11c02014a08 100644 (file)
@@ -69,7 +69,7 @@ class ChapterRepo extends EntityRepo
     public function getBySlug($slug, $bookId)
     {
         $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
-        if ($chapter === null) throw new NotFoundException('Chapter not found');
+        if ($chapter === null) throw new NotFoundException(trans('errors.chapter_not_found'));
         return $chapter;
     }
 
index e6d713f77c591f3451c38ff777d5060974946292..14463c12d191c8473ac26e7938ee0420c605cc21 100644 (file)
@@ -66,7 +66,7 @@ class PageRepo extends EntityRepo
     public function getBySlug($slug, $bookId)
     {
         $page = $this->pageQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
-        if ($page === null) throw new NotFoundException('Page not found');
+        if ($page === null) throw new NotFoundException(trans('errors.page_not_found'));
         return $page;
     }
 
@@ -134,7 +134,7 @@ class PageRepo extends EntityRepo
         $draftPage->draft = false;
 
         $draftPage->save();
-        $this->saveRevision($draftPage, 'Initial Publish');
+        $this->saveRevision($draftPage, trans('entities.pages_initial_revision'));
         
         return $draftPage;
     }
@@ -143,12 +143,12 @@ class PageRepo extends EntityRepo
      * Get a new draft page instance.
      * @param Book $book
      * @param Chapter|bool $chapter
-     * @return static
+     * @return Page
      */
     public function getDraftPage(Book $book, $chapter = false)
     {
         $page = $this->page->newInstance();
-        $page->name = 'New Page';
+        $page->name = trans('entities.pages_initial_name');
         $page->created_by = user()->id;
         $page->updated_by = user()->id;
         $page->draft = true;
@@ -487,11 +487,9 @@ class PageRepo extends EntityRepo
      */
     public function getUserPageDraftMessage(PageRevision $draft)
     {
-        $message = 'You are currently editing a draft that was last saved ' . $draft->updated_at->diffForHumans() . '.';
-        if ($draft->page->updated_at->timestamp > $draft->updated_at->timestamp) {
-            $message .= "\n This page has been updated by since that time. It is recommended that you discard this draft.";
-        }
-        return $message;
+        $message = trans('entities.pages_editing_draft_notification', ['timeDiff' => $draft->updated_at->diffForHumans()]);
+        if ($draft->page->updated_at->timestamp <= $draft->updated_at->timestamp) return $message;
+        return $message . "\n" . trans('entities.pages_draft_edited_notification');
     }
 
     /**
@@ -519,10 +517,10 @@ class PageRepo extends EntityRepo
     public function getPageEditingActiveMessage(Page $page, $minRange = null)
     {
         $pageDraftEdits = $this->activePageEditingQuery($page, $minRange)->get();
-        $userMessage = $pageDraftEdits->count() > 1 ? $pageDraftEdits->count() . ' users have' : $pageDraftEdits->first()->createdBy->name . ' has';
-        $timeMessage = $minRange === null ? 'since the page was last updated' : 'in the last ' . $minRange . ' minutes';
-        $message = '%s started editing this page %s. Take care not to overwrite each other\'s updates!';
-        return sprintf($message, $userMessage, $timeMessage);
+
+        $userMessage = $pageDraftEdits->count() > 1 ? trans('entities.pages_draft_edit_active.start_a', ['count' => $pageDraftEdits->count()]): trans('entities.pages_draft_edit_active.start_b', ['userName' => $pageDraftEdits->first()->createdBy->name]);
+        $timeMessage = $minRange === null ? trans('entities.pages_draft_edit_active.time_a') : trans('entities.pages_draft_edit_active.time_b', ['minCount'=>$minRange]);
+        return trans('entities.pages_draft_edit_active.message', ['start' => $userMessage, 'time' => $timeMessage]);
     }
 
     /**
index 24497c91135fa036825bcb180e88df65ba099727..e1c6d87b12f3551ea28f2f0b4001c3ae222329e3 100644 (file)
@@ -133,9 +133,9 @@ class PermissionsRepo
 
         // Prevent deleting admin role or default registration role.
         if ($role->system_name && in_array($role->system_name, $this->systemRoles)) {
-            throw new PermissionsException('This role is a system role and cannot be deleted');
+            throw new PermissionsException(trans('errors.role_system_cannot_be_deleted'));
         } else if ($role->id == setting('registration-role')) {
-            throw new PermissionsException('This role cannot be deleted while set as the default registration role.');
+            throw new PermissionsException(trans('errors.role_registration_default_cannot_delete'));
         }
 
         if ($migrateRoleId) {
index 6d0857f8b234ead8a7b3cb0fbf4f34871f5ca4b6..6e422c4f476ae1de9601357d6f4a496528514d1f 100644 (file)
@@ -121,7 +121,7 @@ class TagRepo
     /**
      * Create a new Tag instance from user input.
      * @param $input
-     * @return static
+     * @return Tag
      */
     protected function newInstanceFromInput($input)
     {
index ab3716fca027b857de43f239691b931f6cb95b05..22c92f3cea1b8e16f18244eb417be8b040deeaf3 100644 (file)
@@ -3,7 +3,6 @@
 use BookStack\Role;
 use BookStack\User;
 use Exception;
-use Setting;
 
 class UserRepo
 {
index e0ee3a04d727fdf15f1215278518ad591cb34851..592d67e63b5f11ffbe8edc911dc7940a1e715373 100644 (file)
@@ -193,7 +193,7 @@ class AttachmentService extends UploadService
         try {
             $storage->put($attachmentStoragePath, $attachmentData);
         } catch (Exception $e) {
-            throw new FileUploadException('File path ' . $attachmentStoragePath . ' could not be uploaded to. Ensure it is writable to the server.');
+            throw new FileUploadException(trans('errors.path_not_writable', ['filePath' => $attachmentStoragePath]));
         }
         return $attachmentPath;
     }
index d4ec1e9760242a4b10b889c506a8690633eebfe0..8eb52708c9f567bbfafa57be73d7709b2c65a238 100644 (file)
@@ -33,7 +33,7 @@ class EmailConfirmationService
     public function sendConfirmation(User $user)
     {
         if ($user->email_confirmed) {
-            throw new ConfirmationEmailException('Email has already been confirmed, Try logging in.', '/login');
+            throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login');
         }
 
         $this->deleteConfirmationsByUser($user);
@@ -63,7 +63,7 @@ class EmailConfirmationService
      * Gets an email confirmation by looking up the token,
      * Ensures the token has not expired.
      * @param string $token
-     * @return EmailConfirmation
+     * @return array|null|\stdClass
      * @throws UserRegistrationException
      */
     public function getEmailConfirmationFromToken($token)
@@ -72,14 +72,14 @@ class EmailConfirmationService
 
         // If not found show error
         if ($emailConfirmation === null) {
-            throw new UserRegistrationException('This confirmation token is not valid or has already been used, Please try registering again.', '/register');
+            throw new UserRegistrationException(trans('errors.email_confirmation_invalid'), '/register');
         }
 
         // If more than a day old
         if (Carbon::now()->subDay()->gt(new Carbon($emailConfirmation->created_at))) {
             $user = $this->users->getById($emailConfirmation->user_id);
             $this->sendConfirmation($user);
-            throw new UserRegistrationException('The confirmation token has expired, A new confirmation email has been sent.', '/register/confirm');
+            throw new UserRegistrationException(trans('errors.email_confirmation_expired'), '/register/confirm');
         }
 
         $emailConfirmation->user = $this->users->getById($emailConfirmation->user_id);
index dfe2cf453705e07a7b311b73b0f2bffaa28bfb6a..e34b3fb2b7fb0d6a9db780badd849e6738ee7845 100644 (file)
@@ -59,7 +59,7 @@ class ImageService extends UploadService
     {
         $imageName = $imageName ? $imageName : basename($url);
         $imageData = file_get_contents($url);
-        if($imageData === false) throw new \Exception('Cannot get image from ' . $url);
+        if($imageData === false) throw new \Exception(trans('errors.cannot_get_image_from_url', ['url' => $url]));
         return $this->saveNew($imageName, $imageData, $type);
     }
 
@@ -93,7 +93,7 @@ class ImageService extends UploadService
             $storage->put($fullPath, $imageData);
             $storage->setVisibility($fullPath, 'public');
         } catch (Exception $e) {
-            throw new ImageUploadException('Image Path ' . $fullPath . ' is not writable by the server.');
+            throw new ImageUploadException(trans('errors.path_not_writable', ['filePath' => $fullPath]));
         }
 
         if ($this->isLocal()) $fullPath = str_replace_first('/public', '', $fullPath);
@@ -160,7 +160,7 @@ class ImageService extends UploadService
             $thumb = $this->imageTool->make($storage->get($imagePath));
         } catch (Exception $e) {
             if ($e instanceof \ErrorException || $e instanceof NotSupportedException) {
-                throw new ImageUploadException('The server cannot create thumbnails. Please check you have the GD PHP extension installed.');
+                throw new ImageUploadException(trans('errors.cannot_create_thumbs'));
             } else {
                 throw $e;
             }
index b7f101ad2c3a9088357941df9c042eb973081dcb..40b24f1419c06e60cc372dae0b57fd1e621fe70a 100644 (file)
@@ -94,7 +94,7 @@ class LdapService
             $ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
         }
 
-        if (!$ldapBind) throw new LdapException('LDAP access failed using ' . ($isAnonymous ? ' anonymous bind.' : ' given dn & pass details'));
+        if (!$ldapBind) throw new LdapException(($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans('errors.ldap_fail_authed')));
     }
 
     /**
@@ -109,7 +109,7 @@ class LdapService
 
         // Check LDAP extension in installed
         if (!function_exists('ldap_connect') && config('app.env') !== 'testing') {
-            throw new LdapException('LDAP PHP extension not installed');
+            throw new LdapException(trans('errors.ldap_extension_not_installed'));
         }
 
         // Get port from server string if specified.
@@ -117,7 +117,7 @@ class LdapService
         $ldapConnection = $this->ldap->connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389);
 
         if ($ldapConnection === false) {
-            throw new LdapException('Cannot connect to ldap server, Initial connection failed');
+            throw new LdapException(trans('errors.ldap_cannot_connect'));
         }
 
         // Set any required options
index d76a7231b8049396c1be994a16eea4b5c7500fb6..fe554b8d7e7b938f1ed3282f47db4771fb8b161a 100644 (file)
@@ -70,12 +70,12 @@ class SocialAuthService
 
         // Check social account has not already been used
         if ($this->socialAccount->where('driver_id', '=', $socialUser->getId())->exists()) {
-            throw new UserRegistrationException('This ' . $socialDriver . ' account is already in use, Try logging in via the ' . $socialDriver . ' option.', '/login');
+            throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount'=>$socialDriver]), '/login');
         }
 
         if ($this->userRepo->getByEmail($socialUser->getEmail())) {
             $email = $socialUser->getEmail();
-            throw new UserRegistrationException('The email ' . $email . ' is already in use. If you already have an account you can connect your ' . $socialDriver . ' account from your profile settings.', '/login');
+            throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount'=>$socialDriver, 'email' => $email]), '/login');
         }
 
         return $socialUser;
@@ -113,27 +113,26 @@ class SocialAuthService
         if ($isLoggedIn && $socialAccount === null) {
             $this->fillSocialAccount($socialDriver, $socialUser);
             $currentUser->socialAccounts()->save($this->socialAccount);
-            session()->flash('success', title_case($socialDriver) . ' account was successfully attached to your profile.');
+            session()->flash('success', trans('settings.users_social_connected', ['socialAccount' => title_case($socialDriver)]));
             return redirect($currentUser->getEditUrl());
         }
 
         // When a user is logged in and the social account exists and is already linked to the current user.
         if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) {
-            session()->flash('error', 'This ' . title_case($socialDriver) . ' account is already attached to your profile.');
+            session()->flash('error', trans('errors.social_account_existing', ['socialAccount' => title_case($socialDriver)]));
             return redirect($currentUser->getEditUrl());
         }
 
         // When a user is logged in, A social account exists but the users do not match.
-        // Change the user that the social account is assigned to.
         if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) {
-            session()->flash('success', 'This ' . title_case($socialDriver) . ' account is already used by another user.');
+            session()->flash('error', trans('errors.social_account_already_used_existing', ['socialAccount' => title_case($socialDriver)]));
             return redirect($currentUser->getEditUrl());
         }
 
         // Otherwise let the user know this social account is not used by anyone.
-        $message = 'This ' . $socialDriver . ' account is not linked to any users. Please attach it in your profile settings';
+        $message = trans('errors.social_account_not_used', ['socialAccount' => title_case($socialDriver)]);
         if (setting('registration-enabled')) {
-            $message .= ' or, If you do not yet have an account, You can register an account using the ' . $socialDriver . ' option';
+            $message .= trans('errors.social_account_register_instructions', ['socialAccount' => title_case($socialDriver)]);
         }
         
         throw new SocialSignInException($message . '.', '/login');
@@ -157,8 +156,8 @@ class SocialAuthService
     {
         $driver = trim(strtolower($socialDriver));
 
-        if (!in_array($driver, $this->validSocialDrivers)) abort(404, 'Social Driver Not Found');
-        if (!$this->checkDriverConfigured($driver)) throw new SocialDriverNotConfigured("Your {$driver} social settings are not configured correctly.");
+        if (!in_array($driver, $this->validSocialDrivers)) abort(404, trans('errors.social_driver_not_found'));
+        if (!$this->checkDriverConfigured($driver)) throw new SocialDriverNotConfigured(trans('errors.social_driver_not_configured', ['socialAccount' => title_case($socialDriver)]));
 
         return $driver;
     }
@@ -215,7 +214,7 @@ class SocialAuthService
     {
         session();
         user()->socialAccounts()->where('driver', '=', $socialDriver)->delete();
-        session()->flash('success', title_case($socialDriver) . ' account successfully detached');
+        session()->flash('success', trans('settings.users_social_disconnected', ['socialAccount' => title_case($socialDriver)]));
         return redirect(user()->getEditUrl());
     }
 
index c681bb7f55ddbe97e6ba73b29154373e18d2db55..db35023d5e727f926a63f7858d28cc64cb2a34b2 100644 (file)
@@ -6,6 +6,7 @@
 return [
 
     'app-name'        => 'BookStack',
+    'app-logo' => '',
     'app-name-header' => true,
     'app-editor'      => 'wysiwyg',
     'app-color'       => '#0288D1',
index 72e06a3fc53f0df5c07d39cf2ff2cd465681f6d9..2e07cdbf8debab4f1200077251d68146f24d05fc 100644 (file)
@@ -22,6 +22,7 @@
     <php>
         <env name="APP_ENV" value="testing"/>
         <env name="APP_DEBUG" value="false"/>
+        <env name="APP_LANG" value="en"/>
         <env name="CACHE_DRIVER" value="array"/>
         <env name="SESSION_DRIVER" value="array"/>
         <env name="QUEUE_DRIVER" value="sync"/>
index 9d7f7ad706d1037eef8beee41c075a6ce1fc0b45..0d57b09add8307f7284ceb9c417f7bd768751a1f 100644 (file)
@@ -2,6 +2,8 @@
 
 import moment from 'moment';
 import 'moment/locale/en-gb';
+import editorOptions from "./pages/page-form";
+
 moment.locale('en-gb');
 
 export default function (ngApp, events) {
@@ -23,14 +25,14 @@ export default function (ngApp, events) {
             $scope.searching = false;
             $scope.searchTerm = '';
 
-            var page = 0;
-            var previousClickTime = 0;
-            var previousClickImage = 0;
-            var dataLoaded = false;
-            var callback = false;
+            let page = 0;
+            let previousClickTime = 0;
+            let previousClickImage = 0;
+            let dataLoaded = false;
+            let callback = false;
 
-            var preSearchImages = [];
-            var preSearchHasMore = false;
+            let preSearchImages = [];
+            let preSearchHasMore = false;
 
             /**
              * Used by dropzone to get the endpoint to upload to.
@@ -62,7 +64,7 @@ export default function (ngApp, events) {
                 $scope.$apply(() => {
                     $scope.images.unshift(data);
                 });
-                events.emit('success', 'Image uploaded');
+                events.emit('success', trans('components.image_upload_success'));
             };
 
             /**
@@ -79,9 +81,9 @@ export default function (ngApp, events) {
              * @param image
              */
             $scope.imageSelect = function (image) {
-                var dblClickTime = 300;
-                var currentTime = Date.now();
-                var timeDiff = currentTime - previousClickTime;
+                let dblClickTime = 300;
+                let currentTime = Date.now();
+                let timeDiff = currentTime - previousClickTime;
 
                 if (timeDiff < dblClickTime && image.id === previousClickImage) {
                     // If double click
@@ -137,22 +139,21 @@ export default function (ngApp, events) {
                 $('#image-manager').find('.overlay').fadeOut(240);
             };
 
-            var baseUrl = window.baseUrl('/images/' + $scope.imageType + '/all/');
+            let baseUrl = window.baseUrl('/images/' + $scope.imageType + '/all/');
 
             /**
              * Fetch the list image data from the server.
              */
             function fetchData() {
-                var url = baseUrl + page + '?';
-                var components = {};
+                let url = baseUrl + page + '?';
+                let components = {};
                 if ($scope.uploadedTo) components['page_id'] = $scope.uploadedTo;
                 if ($scope.searching) components['term'] = $scope.searchTerm;
 
 
-                var urlQueryString = Object.keys(components).map((key) => {
+                url += Object.keys(components).map((key) => {
                     return key + '=' + encodeURIComponent(components[key]);
                 }).join('&');
-                url += urlQueryString;
 
                 $http.get(url).then((response) => {
                     $scope.images = $scope.images.concat(response.data.images);
@@ -205,13 +206,13 @@ export default function (ngApp, events) {
              */
             $scope.saveImageDetails = function (event) {
                 event.preventDefault();
-                var url = window.baseUrl('/images/update/' + $scope.selectedImage.id);
+                let url = window.baseUrl('/images/update/' + $scope.selectedImage.id);
                 $http.put(url, this.selectedImage).then(response => {
-                    events.emit('success', 'Image details updated');
+                    events.emit('success', trans('components.image_update_success'));
                 }, (response) => {
                     if (response.status === 422) {
-                        var errors = response.data;
-                        var message = '';
+                        let errors = response.data;
+                        let message = '';
                         Object.keys(errors).forEach((key) => {
                             message += errors[key].join('\n');
                         });
@@ -230,13 +231,13 @@ export default function (ngApp, events) {
              */
             $scope.deleteImage = function (event) {
                 event.preventDefault();
-                var force = $scope.dependantPages !== false;
-                var url = window.baseUrl('/images/' + $scope.selectedImage.id);
+                let force = $scope.dependantPages !== false;
+                let url = window.baseUrl('/images/' + $scope.selectedImage.id);
                 if (force) url += '?force=true';
                 $http.delete(url).then((response) => {
                     $scope.images.splice($scope.images.indexOf($scope.selectedImage), 1);
                     $scope.selectedImage = false;
-                    events.emit('success', 'Image successfully deleted');
+                    events.emit('success', trans('components.image_delete_success'));
                 }, (response) => {
                     // Pages failure
                     if (response.status === 400) {
@@ -266,11 +267,11 @@ export default function (ngApp, events) {
 
         $scope.searchBook = function (e) {
             e.preventDefault();
-            var term = $scope.searchTerm;
+            let term = $scope.searchTerm;
             if (term.length == 0) return;
             $scope.searching = true;
             $scope.searchResults = '';
-            var searchUrl = window.baseUrl('/search/book/' + $attrs.bookId);
+            let searchUrl = window.baseUrl('/search/book/' + $attrs.bookId);
             searchUrl += '?term=' + encodeURIComponent(term);
             $http.get(searchUrl).then((response) => {
                 $scope.searchResults = $sce.trustAsHtml(response.data);
@@ -294,27 +295,27 @@ export default function (ngApp, events) {
     ngApp.controller('PageEditController', ['$scope', '$http', '$attrs', '$interval', '$timeout', '$sce',
         function ($scope, $http, $attrs, $interval, $timeout, $sce) {
 
-        $scope.editorOptions = require('./pages/page-form');
+        $scope.editorOptions = editorOptions();
         $scope.editContent = '';
         $scope.draftText = '';
-        var pageId = Number($attrs.pageId);
-        var isEdit = pageId !== 0;
-        var autosaveFrequency = 30; // AutoSave interval in seconds.
-        var isMarkdown = $attrs.editorType === 'markdown';
+        let pageId = Number($attrs.pageId);
+        let isEdit = pageId !== 0;
+        let autosaveFrequency = 30; // AutoSave interval in seconds.
+        let isMarkdown = $attrs.editorType === 'markdown';
         $scope.draftsEnabled = $attrs.draftsEnabled === 'true';
         $scope.isUpdateDraft = Number($attrs.pageUpdateDraft) === 1;
         $scope.isNewPageDraft = Number($attrs.pageNewDraft) === 1;
 
         // Set initial header draft text
         if ($scope.isUpdateDraft || $scope.isNewPageDraft) {
-            $scope.draftText = 'Editing Draft'
+            $scope.draftText = trans('entities.pages_editing_draft');
         } else {
-            $scope.draftText = 'Editing Page'
+            $scope.draftText = trans('entities.pages_editing_page');
         }
 
-        var autoSave = false;
+        let autoSave = false;
 
-        var currentContent = {
+        let currentContent = {
             title: false,
             html: false
         };
@@ -351,8 +352,8 @@ export default function (ngApp, events) {
             autoSave = $interval(() => {
                 // Return if manually saved recently to prevent bombarding the server
                 if (Date.now() - lastSave < (1000*autosaveFrequency)/2) return;
-                var newTitle = $('#name').val();
-                var newHtml = $scope.editContent;
+                let newTitle = $('#name').val();
+                let newHtml = $scope.editContent;
 
                 if (newTitle !== currentContent.title || newHtml !== currentContent.html) {
                     currentContent.html = newHtml;
@@ -369,7 +370,7 @@ export default function (ngApp, events) {
          */
         function saveDraft() {
             if (!$scope.draftsEnabled) return;
-            var data = {
+            let data = {
                 name: $('#name').val(),
                 html: isMarkdown ? $sce.getTrustedHtml($scope.displayContent) : $scope.editContent
             };
@@ -379,14 +380,14 @@ export default function (ngApp, events) {
             let url = window.baseUrl('/ajax/page/' + pageId + '/save-draft');
             $http.put(url, data).then(responseData => {
                 draftErroring = false;
-                var updateTime = moment.utc(moment.unix(responseData.data.timestamp)).toDate();
+                let updateTime = moment.utc(moment.unix(responseData.data.timestamp)).toDate();
                 $scope.draftText = responseData.data.message + moment(updateTime).format('HH:mm');
                 if (!$scope.isNewPageDraft) $scope.isUpdateDraft = true;
                 showDraftSaveNotification();
                 lastSave = Date.now();
             }, errorRes => {
                 if (draftErroring) return;
-                events.emit('error', 'Failed to save draft. Ensure you have internet connection before saving this page.')
+                events.emit('error', trans('errors.page_draft_autosave_fail'));
                 draftErroring = true;
             });
         }
@@ -419,7 +420,7 @@ export default function (ngApp, events) {
             let url = window.baseUrl('/ajax/page/' + pageId);
             $http.get(url).then((responseData) => {
                 if (autoSave) $interval.cancel(autoSave);
-                $scope.draftText = 'Editing Page';
+                $scope.draftText = trans('entities.pages_editing_page');
                 $scope.isUpdateDraft = false;
                 $scope.$broadcast('html-update', responseData.data.html);
                 $scope.$broadcast('markdown-update', responseData.data.markdown || responseData.data.html);
@@ -427,7 +428,7 @@ export default function (ngApp, events) {
                 $timeout(() => {
                     startAutoSave();
                 }, 1000);
-                events.emit('success', 'Draft discarded, The editor has been updated with the current page content');
+                events.emit('success', trans('entities.pages_draft_discarded'));
             });
         };
 
@@ -505,20 +506,6 @@ export default function (ngApp, events) {
                 }
             };
 
-            /**
-             * Save the tags to the current page.
-             */
-            $scope.saveTags = function() {
-                setTagOrder();
-                let postData = {tags: $scope.tags};
-                let url = window.baseUrl('/ajax/tags/update/page/' + pageId);
-                $http.post(url, postData).then((responseData) => {
-                    $scope.tags = responseData.data.tags;
-                    addEmptyTag();
-                    events.emit('success', responseData.data.message);
-                })
-            };
-
             /**
              * Remove a tag from the current list.
              * @param tag
@@ -588,7 +575,7 @@ export default function (ngApp, events) {
              * Get files for the current page from the server.
              */
             function getFiles() {
-                let url = window.baseUrl(`/attachments/get/page/${pageId}`)
+                let url = window.baseUrl(`/attachments/get/page/${pageId}`);
                 $http.get(url).then(resp => {
                     $scope.files = resp.data;
                     currentOrder = resp.data.map(file => {return file.id}).join(':');
@@ -606,7 +593,7 @@ export default function (ngApp, events) {
                 $scope.$apply(() => {
                     $scope.files.push(data);
                 });
-                events.emit('success', 'File uploaded');
+                events.emit('success', trans('entities.attachments_file_uploaded'));
             };
 
             /**
@@ -624,7 +611,7 @@ export default function (ngApp, events) {
                         data.link = '';
                     }
                 });
-                events.emit('success', 'File updated');
+                events.emit('success', trans('entities.attachments_file_updated'));
             };
 
             /**
@@ -650,7 +637,7 @@ export default function (ngApp, events) {
                 file.uploaded_to = pageId;
                 $http.post(window.baseUrl('/attachments/link'), file).then(resp => {
                     $scope.files.push(resp.data);
-                    events.emit('success', 'Link attached');
+                    events.emit('success', trans('entities.attachments_link_attached'));
                     $scope.file = getCleanFile();
                 }, checkError('link'));
             };
@@ -684,7 +671,7 @@ export default function (ngApp, events) {
                         $scope.editFile.link = '';
                     }
                     $scope.editFile = false;
-                    events.emit('success', 'Attachment details updated');
+                    events.emit('success', trans('entities.attachments_updated_success'));
                 }, checkError('edit'));
             };
 
index 44d1a14e1a139a5bf794aef36a93062d8da9aa14..ef8bcd85c6c5ee8e80111a6303e1e7b2a3984d6d 100644 (file)
@@ -1,38 +1,8 @@
 "use strict";
-const DropZone = require('dropzone');
-const markdown = require('marked');
+import DropZone from "dropzone";
+import markdown from "marked";
 
-module.exports = function (ngApp, events) {
-
-    /**
-     * Toggle Switches
-     * Has basic on/off functionality.
-     * Use string values of 'true' & 'false' to dictate the current state.
-     */
-    ngApp.directive('toggleSwitch', function () {
-        return {
-            restrict: 'A',
-            template: `
-            <div class="toggle-switch" ng-click="switch()" ng-class="{'active': isActive}">
-                <input type="hidden" ng-attr-name="{{name}}" ng-attr-value="{{value}}"/>
-                <div class="switch-handle"></div>
-            </div>
-            `,
-            scope: true,
-            link: function (scope, element, attrs) {
-                scope.name = attrs.name;
-                scope.value = attrs.value;
-                scope.isActive = scope.value == true && scope.value != 'false';
-                scope.value = (scope.value == true && scope.value != 'false') ? 'true' : 'false';
-
-                scope.switch = function () {
-                    scope.isActive = !scope.isActive;
-                    scope.value = scope.isActive ? 'true' : 'false';
-                }
-
-            }
-        };
-    });
+export default function (ngApp, events) {
 
     /**
      * Common tab controls using simple jQuery functions.
@@ -65,7 +35,7 @@ module.exports = function (ngApp, events) {
     });
 
     /**
-     * Sub form component to allow inner-form sections to act like thier own forms.
+     * Sub form component to allow inner-form sections to act like their own forms.
      */
     ngApp.directive('subForm', function() {
         return {
@@ -80,96 +50,13 @@ module.exports = function (ngApp, events) {
                 element.find('button[type="submit"]').click(submitEvent);
 
                 function submitEvent(e) {
-                    e.preventDefault()
+                    e.preventDefault();
                     if (attrs.subForm) scope.$eval(attrs.subForm);
                 }
             }
         };
     });
 
-
-    /**
-     * Image Picker
-     * Is a simple front-end interface that connects to an ImageManager if present.
-     */
-    ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
-        return {
-            restrict: 'E',
-            template: `
-            <div class="image-picker">
-                <div>
-                    <img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
-                    <img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
-                </div>
-                <button class="button" type="button" ng-click="showImageManager()">Select Image</button>
-                <br>
-
-                <button class="text-button" ng-click="reset()" type="button">Reset</button>
-                <span ng-show="showRemove" class="sep">|</span>
-                <button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
-
-                <input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
-            </div>
-            `,
-            scope: {
-                name: '@',
-                resizeHeight: '@',
-                resizeWidth: '@',
-                resizeCrop: '@',
-                showRemove: '=',
-                currentImage: '@',
-                currentId: '@',
-                defaultImage: '@',
-                imageClass: '@'
-            },
-            link: function (scope, element, attrs) {
-                let usingIds = typeof scope.currentId !== 'undefined' || scope.currentId === 'false';
-                scope.image = scope.currentImage;
-                scope.value = scope.currentImage || '';
-                if (usingIds) scope.value = scope.currentId;
-
-                function setImage(imageModel, imageUrl) {
-                    scope.image = imageUrl;
-                    scope.value = usingIds ? imageModel.id : imageUrl;
-                }
-
-                scope.reset = function () {
-                    setImage({id: 0}, scope.defaultImage);
-                };
-
-                scope.remove = function () {
-                    scope.image = 'none';
-                    scope.value = 'none';
-                };
-
-                scope.showImageManager = function () {
-                    imageManagerService.show((image) => {
-                        scope.updateImageFromModel(image);
-                    });
-                };
-
-                scope.updateImageFromModel = function (model) {
-                    let isResized = scope.resizeWidth && scope.resizeHeight;
-
-                    if (!isResized) {
-                        scope.$apply(() => {
-                            setImage(model, model.url);
-                        });
-                        return;
-                    }
-
-                    let cropped = scope.resizeCrop ? 'true' : 'false';
-                    let requestString = '/images/thumb/' + model.id + '/' + scope.resizeWidth + '/' + scope.resizeHeight + '/' + cropped;
-                    requestString = window.baseUrl(requestString);
-                    $http.get(requestString).then((response) => {
-                        setImage(model, response.data.url);
-                    });
-                };
-
-            }
-        };
-    }]);
-
     /**
      * DropZone
      * Used for uploading images
@@ -179,25 +66,26 @@ module.exports = function (ngApp, events) {
             restrict: 'E',
             template: `
             <div class="dropzone-container">
-                <div class="dz-message">Drop files or click here to upload</div>
+                <div class="dz-message">{{message}}</div>
             </div>
             `,
             scope: {
                 uploadUrl: '@',
                 eventSuccess: '=',
                 eventError: '=',
-                uploadedTo: '@'
+                uploadedTo: '@',
             },
             link: function (scope, element, attrs) {
+                scope.message = attrs.message;
                 if (attrs.placeholder) element[0].querySelector('.dz-message').textContent = attrs.placeholder;
-                var dropZone = new DropZone(element[0].querySelector('.dropzone-container'), {
+                let dropZone = new DropZone(element[0].querySelector('.dropzone-container'), {
                     url: scope.uploadUrl,
                     init: function () {
-                        var dz = this;
+                        let dz = this;
                         dz.on('sending', function (file, xhr, data) {
-                            var token = window.document.querySelector('meta[name=token]').getAttribute('content');
+                            let token = window.document.querySelector('meta[name=token]').getAttribute('content');
                             data.append('_token', token);
-                            var uploadedTo = typeof scope.uploadedTo === 'undefined' ? 0 : scope.uploadedTo;
+                            let uploadedTo = typeof scope.uploadedTo === 'undefined' ? 0 : scope.uploadedTo;
                             data.append('uploaded_to', uploadedTo);
                         });
                         if (typeof scope.eventSuccess !== 'undefined') dz.on('success', scope.eventSuccess);
@@ -214,7 +102,7 @@ module.exports = function (ngApp, events) {
                                 $(file.previewElement).find('[data-dz-errormessage]').text(message);
                             }
 
-                            if (xhr.status === 413) setMessage('The server does not allow uploads of this size. Please try a smaller file.');
+                            if (xhr.status === 413) setMessage(trans('errors.server_upload_limit'));
                             if (errorMessage.file) setMessage(errorMessage.file[0]);
 
                         });
@@ -273,7 +161,7 @@ module.exports = function (ngApp, events) {
 
                 function tinyMceSetup(editor) {
                     editor.on('ExecCommand change NodeChange ObjectResized', (e) => {
-                        var content = editor.getContent();
+                        let content = editor.getContent();
                         $timeout(() => {
                             scope.mceModel = content;
                         });
@@ -301,9 +189,9 @@ module.exports = function (ngApp, events) {
                 // Custom tinyMCE plugins
                 tinymce.PluginManager.add('customhr', function (editor) {
                     editor.addCommand('InsertHorizontalRule', function () {
-                        var hrElem = document.createElement('hr');
-                        var cNode = editor.selection.getNode();
-                        var parentNode = cNode.parentNode;
+                        let hrElem = document.createElement('hr');
+                        let cNode = editor.selection.getNode();
+                        let parentNode = cNode.parentNode;
                         parentNode.insertBefore(hrElem, cNode);
                     });
 
@@ -373,15 +261,21 @@ module.exports = function (ngApp, events) {
             link: function (scope, element, attrs) {
 
                 // Elements
-                const input = element.find('[markdown-input] textarea').first();
-                const display = element.find('.markdown-display').first();
-                const insertImage = element.find('button[data-action="insertImage"]');
-                const insertEntityLink = element.find('button[data-action="insertEntityLink"]')
+                const $input = element.find('[markdown-input] textarea').first();
+                const $display = element.find('.markdown-display').first();
+                const $insertImage = element.find('button[data-action="insertImage"]');
+                const $insertEntityLink = element.find('button[data-action="insertEntityLink"]');
+
+                // Prevent markdown display link click redirect
+                $display.on('click', 'a', function(event) {
+                    event.preventDefault();
+                    window.open(this.getAttribute('href'));
+                });
 
                 let currentCaretPos = 0;
 
-                input.blur(event => {
-                    currentCaretPos = input[0].selectionStart;
+                $input.blur(event => {
+                    currentCaretPos = $input[0].selectionStart;
                 });
 
                 // Scroll sync
@@ -391,10 +285,10 @@ module.exports = function (ngApp, events) {
                     displayHeight;
 
                 function setScrollHeights() {
-                    inputScrollHeight = input[0].scrollHeight;
-                    inputHeight = input.height();
-                    displayScrollHeight = display[0].scrollHeight;
-                    displayHeight = display.height();
+                    inputScrollHeight = $input[0].scrollHeight;
+                    inputHeight = $input.height();
+                    displayScrollHeight = $display[0].scrollHeight;
+                    displayHeight = $display.height();
                 }
 
                 setTimeout(() => {
@@ -403,29 +297,29 @@ module.exports = function (ngApp, events) {
                 window.addEventListener('resize', setScrollHeights);
                 let scrollDebounceTime = 800;
                 let lastScroll = 0;
-                input.on('scroll', event => {
+                $input.on('scroll', event => {
                     let now = Date.now();
                     if (now - lastScroll > scrollDebounceTime) {
                         setScrollHeights()
                     }
-                    let scrollPercent = (input.scrollTop() / (inputScrollHeight - inputHeight));
+                    let scrollPercent = ($input.scrollTop() / (inputScrollHeight - inputHeight));
                     let displayScrollY = (displayScrollHeight - displayHeight) * scrollPercent;
-                    display.scrollTop(displayScrollY);
+                    $display.scrollTop(displayScrollY);
                     lastScroll = now;
                 });
 
                 // Editor key-presses
-                input.keydown(event => {
+                $input.keydown(event => {
                     // Insert image shortcut
                     if (event.which === 73 && event.ctrlKey && event.shiftKey) {
                         event.preventDefault();
-                        let caretPos = input[0].selectionStart;
-                        let currentContent = input.val();
+                        let caretPos = $input[0].selectionStart;
+                        let currentContent = $input.val();
                         const mdImageText = "![](http://)";
-                        input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
-                        input.focus();
-                        input[0].selectionStart = caretPos + ("![](".length);
-                        input[0].selectionEnd = caretPos + ('![](http://'.length);
+                        $input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
+                        $input.focus();
+                        $input[0].selectionStart = caretPos + ("![](".length);
+                        $input[0].selectionEnd = caretPos + ('![](http://'.length);
                         return;
                     }
 
@@ -440,48 +334,48 @@ module.exports = function (ngApp, events) {
                 });
 
                 // Insert image from image manager
-                insertImage.click(event => {
+                $insertImage.click(event => {
                     window.ImageManager.showExternal(image => {
                         let caretPos = currentCaretPos;
-                        let currentContent = input.val();
+                        let currentContent = $input.val();
                         let mdImageText = "![" + image.name + "](" + image.thumbs.display + ")";
-                        input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
-                        input.change();
+                        $input.val(currentContent.substring(0, caretPos) + mdImageText + currentContent.substring(caretPos));
+                        $input.change();
                     });
                 });
 
                 function showLinkSelector() {
                     window.showEntityLinkSelector((entity) => {
                         let selectionStart = currentCaretPos;
-                        let selectionEnd = input[0].selectionEnd;
+                        let selectionEnd = $input[0].selectionEnd;
                         let textSelected = (selectionEnd !== selectionStart);
-                        let currentContent = input.val();
+                        let currentContent = $input.val();
 
                         if (textSelected) {
                             let selectedText = currentContent.substring(selectionStart, selectionEnd);
                             let linkText = `[${selectedText}](${entity.link})`;
-                            input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionEnd));
+                            $input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionEnd));
                         } else {
                             let linkText = ` [${entity.name}](${entity.link}) `;
-                            input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart))
+                            $input.val(currentContent.substring(0, selectionStart) + linkText + currentContent.substring(selectionStart))
                         }
-                        input.change();
+                        $input.change();
                     });
                 }
-                insertEntityLink.click(showLinkSelector);
+                $insertEntityLink.click(showLinkSelector);
 
                 // Upload and insert image on paste
                 function editorPaste(e) {
                     e = e.originalEvent;
                     if (!e.clipboardData) return
-                    var items = e.clipboardData.items;
+                    let items = e.clipboardData.items;
                     if (!items) return;
-                    for (var i = 0; i < items.length; i++) {
+                    for (let i = 0; i < items.length; i++) {
                         uploadImage(items[i].getAsFile());
                     }
                 }
 
-                input.on('paste', editorPaste);
+                $input.on('paste', editorPaste);
 
                 // Handle image drop, Uploads images to BookStack.
                 function handleImageDrop(event) {
@@ -493,17 +387,17 @@ module.exports = function (ngApp, events) {
                     }
                 }
 
-                input.on('drop', handleImageDrop);
+                $input.on('drop', handleImageDrop);
 
                 // Handle image upload and add image into markdown content
                 function uploadImage(file) {
                     if (file.type.indexOf('image') !== 0) return;
-                    var formData = new FormData();
-                    var ext = 'png';
-                    var xhr = new XMLHttpRequest();
+                    let formData = new FormData();
+                    let ext = 'png';
+                    let xhr = new XMLHttpRequest();
 
                     if (file.name) {
-                        var fileNameMatches = file.name.match(/\.(.+)$/);
+                        let fileNameMatches = file.name.match(/\.(.+)$/);
                         if (fileNameMatches) {
                             ext = fileNameMatches[1];
                         }
@@ -511,17 +405,17 @@ module.exports = function (ngApp, events) {
 
                     // Insert image into markdown
                     let id = "image-" + Math.random().toString(16).slice(2);
-                    let selectStart = input[0].selectionStart;
-                    let selectEnd = input[0].selectionEnd;
-                    let content = input[0].value;
+                    let selectStart = $input[0].selectionStart;
+                    let selectEnd = $input[0].selectionEnd;
+                    let content = $input[0].value;
                     let selectText = content.substring(selectStart, selectEnd);
                     let placeholderImage = window.baseUrl(`/loading.gif#upload${id}`);
                     let innerContent = ((selectEnd > selectStart) ? `![${selectText}]` : '![]') + `(${placeholderImage})`;
-                    input[0].value = content.substring(0, selectStart) +  innerContent + content.substring(selectEnd);
+                    $input[0].value = content.substring(0, selectStart) +  innerContent + content.substring(selectEnd);
 
-                    input.focus();
-                    input[0].selectionStart = selectStart;
-                    input[0].selectionEnd = selectStart;
+                    $input.focus();
+                    $input[0].selectionStart = selectStart;
+                    $input[0].selectionEnd = selectStart;
 
                     let remoteFilename = "image-" + Date.now() + "." + ext;
                     formData.append('file', file, remoteFilename);
@@ -529,20 +423,20 @@ module.exports = function (ngApp, events) {
 
                     xhr.open('POST', window.baseUrl('/images/gallery/upload'));
                     xhr.onload = function () {
-                        let selectStart = input[0].selectionStart;
+                        let selectStart = $input[0].selectionStart;
                         if (xhr.status === 200 || xhr.status === 201) {
-                            var result = JSON.parse(xhr.responseText);
-                            input[0].value = input[0].value.replace(placeholderImage, result.thumbs.display);
-                            input.change();
+                            let result = JSON.parse(xhr.responseText);
+                            $input[0].value = $input[0].value.replace(placeholderImage, result.thumbs.display);
+                            $input.change();
                         } else {
-                            console.log('An error occurred uploading the image');
+                            console.log(trans('errors.image_upload_error'));
                             console.log(xhr.responseText);
-                            input[0].value = input[0].value.replace(innerContent, '');
-                            input.change();
+                            $input[0].value = $input[0].value.replace(innerContent, '');
+                            $input.change();
                         }
-                        input.focus();
-                        input[0].selectionStart = selectStart;
-                        input[0].selectionEnd = selectStart;
+                        $input.focus();
+                        $input[0].selectionStart = selectStart;
+                        $input[0].selectionEnd = selectStart;
                     };
                     xhr.send(formData);
                 }
@@ -680,8 +574,7 @@ module.exports = function (ngApp, events) {
                     }
                     // Enter or tab key
                     else if ((event.keyCode === 13 || event.keyCode === 9) && !event.shiftKey) {
-                        let text = suggestionElems[active].textContent;
-                        currentInput[0].value = text;
+                        currentInput[0].value = suggestionElems[active].textContent;
                         currentInput.focus();
                         $suggestionBox.hide();
                         isShowing = false;
@@ -732,14 +625,13 @@ module.exports = function (ngApp, events) {
                     // Build suggestions
                     $suggestionBox[0].innerHTML = '';
                     for (let i = 0; i < suggestions.length; i++) {
-                        var suggestion = document.createElement('li');
+                        let suggestion = document.createElement('li');
                         suggestion.textContent = suggestions[i];
                         suggestion.onclick = suggestionClick;
                         if (i === 0) {
-                            suggestion.className = 'active'
+                            suggestion.className = 'active';
                             active = 0;
                         }
-                        ;
                         $suggestionBox[0].appendChild(suggestion);
                     }
 
@@ -748,12 +640,11 @@ module.exports = function (ngApp, events) {
 
                 // Suggestion click event
                 function suggestionClick(event) {
-                    let text = this.textContent;
-                    currentInput[0].value = text;
+                    currentInput[0].value = this.textContent;
                     currentInput.focus();
                     $suggestionBox.hide();
                     isShowing = false;
-                };
+                }
 
                 // Get suggestions & cache
                 function getSuggestions(input, url) {
@@ -779,7 +670,7 @@ module.exports = function (ngApp, events) {
 
     ngApp.directive('entityLinkSelector', [function($http) {
         return {
-            restict: 'A',
+            restrict: 'A',
             link: function(scope, element, attrs) {
 
                 const selectButton = element.find('.entity-link-selector-confirm');
@@ -843,7 +734,7 @@ module.exports = function (ngApp, events) {
                 const input = element.find('[entity-selector-input]').first();
 
                 // Detect double click events
-                var lastClick = 0;
+                let lastClick = 0;
                 function isDoubleClick() {
                     let now = Date.now();
                     let answer = now - lastClick < 300;
index 9aa5dff527adcf04298e80dc28003f004080448f..94462ed6483de9ba64f2035c33facd642dda5308 100644 (file)
@@ -1,11 +1,11 @@
 "use strict";
 
 // AngularJS - Create application and load components
-var angular = require('angular');
-var ngResource = require('angular-resource');
-var ngAnimate = require('angular-animate');
-var ngSanitize = require('angular-sanitize');
-require('angular-ui-sortable');
+import angular from "angular";
+import "angular-resource";
+import "angular-animate";
+import "angular-sanitize";
+import "angular-ui-sortable";
 
 // Url retrieval function
 window.baseUrl = function(path) {
@@ -15,7 +15,13 @@ window.baseUrl = function(path) {
     return basePath + '/' + path;
 };
 
-var ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
+let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
+
+// Translation setup
+// Creates a global function with name 'trans' to be used in the same way as Laravel's translation system
+import Translations from "./translations"
+let translator = new Translations(window.translations);
+window.trans = translator.get.bind(translator);
 
 // Global Event System
 class EventManager {
@@ -25,9 +31,9 @@ class EventManager {
 
     emit(eventName, eventData) {
         if (typeof this.listeners[eventName] === 'undefined') return this;
-        var eventsToStart = this.listeners[eventName];
+        let eventsToStart = this.listeners[eventName];
         for (let i = 0; i < eventsToStart.length; i++) {
-            var event = eventsToStart[i];
+            let event = eventsToStart[i];
             event(eventData);
         }
         return this;
@@ -70,93 +76,83 @@ jQuery.expr[":"].contains = $.expr.createPseudo(function (arg) {
 });
 
 // Global jQuery Elements
-$(function () {
-
-    var notifications = $('.notification');
-    var successNotification = notifications.filter('.pos');
-    var errorNotification = notifications.filter('.neg');
-    var warningNotification = notifications.filter('.warning');
-    // Notification Events
-    window.Events.listen('success', function (text) {
-        successNotification.hide();
-        successNotification.find('span').text(text);
+let notifications = $('.notification');
+let successNotification = notifications.filter('.pos');
+let errorNotification = notifications.filter('.neg');
+let warningNotification = notifications.filter('.warning');
+// Notification Events
+window.Events.listen('success', function (text) {
+    successNotification.hide();
+    successNotification.find('span').text(text);
+    setTimeout(() => {
+        successNotification.show();
+    }, 1);
+});
+window.Events.listen('warning', function (text) {
+    warningNotification.find('span').text(text);
+    warningNotification.show();
+});
+window.Events.listen('error', function (text) {
+    errorNotification.find('span').text(text);
+    errorNotification.show();
+});
+
+// Notification hiding
+notifications.click(function () {
+    $(this).fadeOut(100);
+});
+
+// Chapter page list toggles
+$('.chapter-toggle').click(function (e) {
+    e.preventDefault();
+    $(this).toggleClass('open');
+    $(this).closest('.chapter').find('.inset-list').slideToggle(180);
+});
+
+// Back to top button
+$('#back-to-top').click(function() {
+     $('#header').smoothScrollTo();
+});
+let scrollTopShowing = false;
+let scrollTop = document.getElementById('back-to-top');
+let scrollTopBreakpoint = 1200;
+window.addEventListener('scroll', function() {
+    let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
+    if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) {
+        scrollTop.style.display = 'block';
+        scrollTopShowing = true;
         setTimeout(() => {
-            successNotification.show();
+            scrollTop.style.opacity = 0.4;
         }, 1);
-    });
-    window.Events.listen('warning', function (text) {
-        warningNotification.find('span').text(text);
-        warningNotification.show();
-    });
-    window.Events.listen('error', function (text) {
-        errorNotification.find('span').text(text);
-        errorNotification.show();
-    });
-
-    // Notification hiding
-    notifications.click(function () {
-        $(this).fadeOut(100);
-    });
-
-    // Chapter page list toggles
-    $('.chapter-toggle').click(function (e) {
-        e.preventDefault();
-        $(this).toggleClass('open');
-        $(this).closest('.chapter').find('.inset-list').slideToggle(180);
-    });
-
-    // Back to top button
-    $('#back-to-top').click(function() {
-         $('#header').smoothScrollTo();
-    });
-    var scrollTopShowing = false;
-    var scrollTop = document.getElementById('back-to-top');
-    var scrollTopBreakpoint = 1200;
-    window.addEventListener('scroll', function() {
-        let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
-        if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) {
-            scrollTop.style.display = 'block';
-            scrollTopShowing = true;
-            setTimeout(() => {
-                scrollTop.style.opacity = 0.4;
-            }, 1);
-        } else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) {
-            scrollTop.style.opacity = 0;
-            scrollTopShowing = false;
-            setTimeout(() => {
-                scrollTop.style.display = 'none';
-            }, 500);
-        }
-    });
-
-    // Common jQuery actions
-    $('[data-action="expand-entity-list-details"]').click(function() {
-        $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240);
-    });
-
-    // Popup close
-    $('.popup-close').click(function() {
-        $(this).closest('.overlay').fadeOut(240);
-    });
-    $('.overlay').click(function(event) {
-        if (!$(event.target).hasClass('overlay')) return;
-        $(this).fadeOut(240);
-    });
-
-    // Prevent markdown display link click redirect
-    $('.markdown-display').on('click', 'a', function(event) {
-        event.preventDefault();
-        window.open($(this).attr('href'));
-    });
-
-    // Detect IE for css
-    if(navigator.userAgent.indexOf('MSIE')!==-1
-        || navigator.appVersion.indexOf('Trident/') > 0
-        || navigator.userAgent.indexOf('Safari') !== -1){
-        $('body').addClass('flexbox-support');
+    } else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) {
+        scrollTop.style.opacity = 0;
+        scrollTopShowing = false;
+        setTimeout(() => {
+            scrollTop.style.display = 'none';
+        }, 500);
     }
+});
 
+// Common jQuery actions
+$('[data-action="expand-entity-list-details"]').click(function() {
+    $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240);
 });
 
+// Popup close
+$('.popup-close').click(function() {
+    $(this).closest('.overlay').fadeOut(240);
+});
+$('.overlay').click(function(event) {
+    if (!$(event.target).hasClass('overlay')) return;
+    $(this).fadeOut(240);
+});
+
+// Detect IE for css
+if(navigator.userAgent.indexOf('MSIE')!==-1
+    || navigator.appVersion.indexOf('Trident/') > 0
+    || navigator.userAgent.indexOf('Safari') !== -1){
+    $('body').addClass('flexbox-support');
+}
+
 // Page specific items
-require('./pages/page-show');
+import "./pages/page-show";
index 1fb8b915f91482941fd96d6ef48d234311be6ac2..e1c0cfe8f14c04345910be43c6aff3b13a732b9d 100644 (file)
@@ -60,108 +60,108 @@ function registerEditorShortcuts(editor) {
     editor.addShortcut('meta+shift+E', '', ['FormatBlock', false, 'code']);
 }
 
-var mceOptions = module.exports = {
-    selector: '#html-editor',
-    content_css: [
-        window.baseUrl('/css/styles.css'),
-        window.baseUrl('/libs/material-design-iconic-font/css/material-design-iconic-font.min.css')
-    ],
-    body_class: 'page-content',
-    relative_urls: false,
-    remove_script_host: false,
-    document_base_url: window.baseUrl('/'),
-    statusbar: false,
-    menubar: false,
-    paste_data_images: false,
-    extended_valid_elements: 'pre[*]',
-    automatic_uploads: false,
-    valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
-    plugins: "image table textcolor paste link fullscreen imagetools code customhr autosave lists",
-    imagetools_toolbar: 'imageoptions',
-    toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen",
-    content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
-    style_formats: [
-        {title: "Header Large", format: "h2"},
-        {title: "Header Medium", format: "h3"},
-        {title: "Header Small", format: "h4"},
-        {title: "Header Tiny", format: "h5"},
-        {title: "Paragraph", format: "p", exact: true, classes: ''},
-        {title: "Blockquote", format: "blockquote"},
-        {title: "Code Block", icon: "code", format: "pre"},
-        {title: "Inline Code", icon: "code", inline: "code"},
-        {title: "Callouts", items: [
-            {title: "Success", block: 'p', exact: true, attributes : {'class' : 'callout success'}},
-            {title: "Info", block: 'p', exact: true, attributes : {'class' : 'callout info'}},
-            {title: "Warning", block: 'p', exact: true, attributes : {'class' : 'callout warning'}},
-            {title: "Danger", block: 'p', exact: true, attributes : {'class' : 'callout danger'}}
-        ]}
-    ],
-    style_formats_merge: false,
-    formats: {
-        alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-left'},
-        aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-center'},
-        alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'},
-    },
-    file_browser_callback: function (field_name, url, type, win) {
-
-        if (type === 'file') {
-            window.showEntityLinkSelector(function(entity) {
-                let originalField = win.document.getElementById(field_name);
-                originalField.value = entity.link;
-                $(originalField).closest('.mce-form').find('input').eq(2).val(entity.name);
-            });
-        }
+export default function() {
+    let settings = {
+        selector: '#html-editor',
+        content_css: [
+            window.baseUrl('/css/styles.css'),
+            window.baseUrl('/libs/material-design-iconic-font/css/material-design-iconic-font.min.css')
+        ],
+        body_class: 'page-content',
+        relative_urls: false,
+        remove_script_host: false,
+        document_base_url: window.baseUrl('/'),
+        statusbar: false,
+        menubar: false,
+        paste_data_images: false,
+        extended_valid_elements: 'pre[*]',
+        automatic_uploads: false,
+        valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
+        plugins: "image table textcolor paste link fullscreen imagetools code customhr autosave lists",
+        imagetools_toolbar: 'imageoptions',
+        toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen",
+        content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
+        style_formats: [
+            {title: "Header Large", format: "h2"},
+            {title: "Header Medium", format: "h3"},
+            {title: "Header Small", format: "h4"},
+            {title: "Header Tiny", format: "h5"},
+            {title: "Paragraph", format: "p", exact: true, classes: ''},
+            {title: "Blockquote", format: "blockquote"},
+            {title: "Code Block", icon: "code", format: "pre"},
+            {title: "Inline Code", icon: "code", inline: "code"},
+            {title: "Callouts", items: [
+                {title: "Success", block: 'p', exact: true, attributes : {'class' : 'callout success'}},
+                {title: "Info", block: 'p', exact: true, attributes : {'class' : 'callout info'}},
+                {title: "Warning", block: 'p', exact: true, attributes : {'class' : 'callout warning'}},
+                {title: "Danger", block: 'p', exact: true, attributes : {'class' : 'callout danger'}}
+            ]}
+        ],
+        style_formats_merge: false,
+        formats: {
+            alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-left'},
+            aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-center'},
+            alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'align-right'},
+        },
+        file_browser_callback: function (field_name, url, type, win) {
+
+            if (type === 'file') {
+                window.showEntityLinkSelector(function(entity) {
+                    let originalField = win.document.getElementById(field_name);
+                    originalField.value = entity.link;
+                    $(originalField).closest('.mce-form').find('input').eq(2).val(entity.name);
+                });
+            }
 
-        if (type === 'image') {
-            // Show image manager
-            window.ImageManager.showExternal(function (image) {
-
-                // Set popover link input to image url then fire change event
-                // to ensure the new value sticks
-                win.document.getElementById(field_name).value = image.url;
-                if ("createEvent" in document) {
-                    let evt = document.createEvent("HTMLEvents");
-                    evt.initEvent("change", false, true);
-                    win.document.getElementById(field_name).dispatchEvent(evt);
-                } else {
-                    win.document.getElementById(field_name).fireEvent("onchange");
-                }
+            if (type === 'image') {
+                // Show image manager
+                window.ImageManager.showExternal(function (image) {
 
-                // Replace the actively selected content with the linked image
-                let html = `<a href="${image.url}" target="_blank">`;
-                html += `<img src="${image.thumbs.display}" alt="${image.name}">`;
-                html += '</a>';
-                win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html);
-            });
-        }
+                    // Set popover link input to image url then fire change event
+                    // to ensure the new value sticks
+                    win.document.getElementById(field_name).value = image.url;
+                    if ("createEvent" in document) {
+                        let evt = document.createEvent("HTMLEvents");
+                        evt.initEvent("change", false, true);
+                        win.document.getElementById(field_name).dispatchEvent(evt);
+                    } else {
+                        win.document.getElementById(field_name).fireEvent("onchange");
+                    }
+
+                    // Replace the actively selected content with the linked image
+                    let html = `<a href="${image.url}" target="_blank">`;
+                    html += `<img src="${image.thumbs.display}" alt="${image.name}">`;
+                    html += '</a>';
+                    win.tinyMCE.activeEditor.execCommand('mceInsertContent', false, html);
+                });
+            }
 
-    },
-    paste_preprocess: function (plugin, args) {
-        let content = args.content;
-        if (content.indexOf('<img src="file://') !== -1) {
-            args.content = '';
-        }
-    },
-    extraSetups: [],
-    setup: function (editor) {
-
-        // Run additional setup actions
-        // Used by the angular side of things
-        for (let i = 0; i < mceOptions.extraSetups.length; i++) {
-            mceOptions.extraSetups[i](editor);
-        }
+        },
+        paste_preprocess: function (plugin, args) {
+            let content = args.content;
+            if (content.indexOf('<img src="file://') !== -1) {
+                args.content = '';
+            }
+        },
+        extraSetups: [],
+        setup: function (editor) {
+
+            // Run additional setup actions
+            // Used by the angular side of things
+            for (let i = 0; i < settings.extraSetups.length; i++) {
+                settings.extraSetups[i](editor);
+            }
 
-        registerEditorShortcuts(editor);
+            registerEditorShortcuts(editor);
 
-        (function () {
-            var wrap;
+            let wrap;
 
             function hasTextContent(node) {
                 return node && !!( node.textContent || node.innerText );
             }
 
             editor.on('dragstart', function () {
-                var node = editor.selection.getNode();
+                let node = editor.selection.getNode();
 
                 if (node.nodeName !== 'IMG') return;
                 wrap = editor.dom.getParent(node, '.mceTemp');
@@ -172,7 +172,7 @@ var mceOptions = module.exports = {
             });
 
             editor.on('drop', function (event) {
-                var dom = editor.dom,
+                let dom = editor.dom,
                     rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint(event.clientX, event.clientY, editor.getDoc());
 
                 // Don't allow anything to be dropped in a captioned image.
@@ -190,26 +190,27 @@ var mceOptions = module.exports = {
 
                 wrap = null;
             });
-        })();
-
-        // Custom Image picker button
-        editor.addButton('image-insert', {
-            title: 'My title',
-            icon: 'image',
-            tooltip: 'Insert an image',
-            onclick: function () {
-                window.ImageManager.showExternal(function (image) {
-                    let html = `<a href="${image.url}" target="_blank">`;
-                    html += `<img src="${image.thumbs.display}" alt="${image.name}">`;
-                    html += '</a>';
-                    editor.execCommand('mceInsertContent', false, html);
-                });
-            }
-        });
 
-        // Paste image-uploads
-        editor.on('paste', function(event) {
-            editorPaste(event, editor);
-        });
-    }
-};
\ No newline at end of file
+            // Custom Image picker button
+            editor.addButton('image-insert', {
+                title: 'My title',
+                icon: 'image',
+                tooltip: 'Insert an image',
+                onclick: function () {
+                    window.ImageManager.showExternal(function (image) {
+                        let html = `<a href="${image.url}" target="_blank">`;
+                        html += `<img src="${image.thumbs.display}" alt="${image.name}">`;
+                        html += '</a>';
+                        editor.execCommand('mceInsertContent', false, html);
+                    });
+                }
+            });
+
+            // Paste image-uploads
+            editor.on('paste', function(event) {
+                editorPaste(event, editor);
+            });
+        }
+    };
+    return settings;
+}
\ No newline at end of file
index 41b92453f6cc785f1fb79c404b6c5eb071839fa7..0cdde790dcdbdad18b2fdea13c144202e8579717 100644 (file)
@@ -1,16 +1,13 @@
 "use strict";
 // Configure ZeroClipboard
-var zeroClipBoard = require('zeroclipboard');
-zeroClipBoard.config({
-    swfPath: window.baseUrl('/ZeroClipboard.swf')
-});
+import zeroClipBoard from "zeroclipboard";
 
-window.setupPageShow = module.exports = function (pageId) {
+export default window.setupPageShow = function (pageId) {
 
     // Set up pointer
-    var $pointer = $('#pointer').detach();
-    var $pointerInner = $pointer.children('div.pointer').first();
-    var isSelection = false;
+    let $pointer = $('#pointer').detach();
+    let $pointerInner = $pointer.children('div.pointer').first();
+    let isSelection = false;
 
     // Select all contents on input click
     $pointer.on('click', 'input', function (e) {
@@ -19,6 +16,9 @@ window.setupPageShow = module.exports = function (pageId) {
     });
 
     // Set up copy-to-clipboard
+    zeroClipBoard.config({
+        swfPath: window.baseUrl('/ZeroClipboard.swf')
+    });
     new zeroClipBoard($pointer.find('button').first()[0]);
 
     // Hide pointer when clicking away
@@ -31,11 +31,11 @@ window.setupPageShow = module.exports = function (pageId) {
     // Show pointer when selecting a single block of tagged content
     $('.page-content [id^="bkmrk"]').on('mouseup keyup', function (e) {
         e.stopPropagation();
-        var selection = window.getSelection();
+        let selection = window.getSelection();
         if (selection.toString().length === 0) return;
 
         // Show pointer and set link
-        var $elem = $(this);
+        let $elem = $(this);
         let link = window.baseUrl('/link/' + pageId + '#' + $elem.attr('id'));
         if (link.indexOf('http') !== 0) link = window.location.protocol + "//" + window.location.host + link;
         $pointer.find('input').val(link);
@@ -44,9 +44,9 @@ window.setupPageShow = module.exports = function (pageId) {
         $pointer.show();
 
         // Set pointer to sit near mouse-up position
-        var pointerLeftOffset = (e.pageX - $elem.offset().left - ($pointerInner.width() / 2));
+        let pointerLeftOffset = (e.pageX - $elem.offset().left - ($pointerInner.width() / 2));
         if (pointerLeftOffset < 0) pointerLeftOffset = 0;
-        var pointerLeftOffsetPercent = (pointerLeftOffset / $elem.width()) * 100;
+        let pointerLeftOffsetPercent = (pointerLeftOffset / $elem.width()) * 100;
         $pointerInner.css('left', pointerLeftOffsetPercent + '%');
 
         isSelection = true;
@@ -57,7 +57,7 @@ window.setupPageShow = module.exports = function (pageId) {
 
     // Go to, and highlight if necessary, the specified text.
     function goToText(text) {
-        var idElem = $('.page-content #' + text).first();
+        let idElem = $('.page-content #' + text).first();
         if (idElem.length !== 0) {
             idElem.smoothScrollTo();
             idElem.css('background-color', 'rgba(244, 249, 54, 0.25)');
@@ -68,19 +68,19 @@ window.setupPageShow = module.exports = function (pageId) {
 
     // Check the hash on load
     if (window.location.hash) {
-        var text = window.location.hash.replace(/\%20/g, ' ').substr(1);
+        let text = window.location.hash.replace(/\%20/g, ' ').substr(1);
         goToText(text);
     }
 
     // Make the book-tree sidebar stick in view on scroll
-    var $window = $(window);
-    var $bookTree = $(".book-tree");
-    var $bookTreeParent = $bookTree.parent();
+    let $window = $(window);
+    let $bookTree = $(".book-tree");
+    let $bookTreeParent = $bookTree.parent();
     // Check the page is scrollable and the content is taller than the tree
-    var pageScrollable = ($(document).height() > $window.height()) && ($bookTree.height() < $('.page-content').height());
+    let pageScrollable = ($(document).height() > $window.height()) && ($bookTree.height() < $('.page-content').height());
     // Get current tree's width and header height
-    var headerHeight = $("#header").height() + $(".toolbar").height();
-    var isFixed = $window.scrollTop() > headerHeight;
+    let headerHeight = $("#header").height() + $(".toolbar").height();
+    let isFixed = $window.scrollTop() > headerHeight;
     // Function to fix the tree as a sidebar
     function stickTree() {
         $bookTree.width($bookTreeParent.width() + 15);
@@ -95,7 +95,7 @@ window.setupPageShow = module.exports = function (pageId) {
     }
     // Checks if the tree stickiness state should change
     function checkTreeStickiness(skipCheck) {
-        var shouldBeFixed = $window.scrollTop() > headerHeight;
+        let shouldBeFixed = $window.scrollTop() > headerHeight;
         if (shouldBeFixed && (!isFixed || skipCheck)) {
             stickTree();
         } else if (!shouldBeFixed && (isFixed || skipCheck)) {
diff --git a/resources/assets/js/translations.js b/resources/assets/js/translations.js
new file mode 100644 (file)
index 0000000..306c696
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ *  Translation Manager
+ *  Handles the JavaScript side of translating strings
+ *  in a way which fits with Laravel.
+ */
+class Translator {
+
+    /**
+     * Create an instance, Passing in the required translations
+     * @param translations
+     */
+    constructor(translations) {
+        this.store = translations;
+    }
+
+    /**
+     * Get a translation, Same format as laravel's 'trans' helper
+     * @param key
+     * @param replacements
+     * @returns {*}
+     */
+    get(key, replacements) {
+        let splitKey = key.split('.');
+        let value = splitKey.reduce((a, b) => {
+            return a != undefined ? a[b] : a;
+        }, this.store);
+
+        if (value === undefined) {
+            console.log(`Translation with key "${key}" does not exist`);
+            value = key;
+        }
+
+        if (replacements === undefined) return value;
+
+        let replaceMatches = value.match(/:([\S]+)/g);
+        if (replaceMatches === null) return value;
+        replaceMatches.forEach(match => {
+            let key = match.substring(1);
+            if (typeof replacements[key] === 'undefined') return;
+            value = value.replace(match, replacements[key]);
+        });
+        return value;
+    }
+
+}
+
+export default Translator
index 2f9051a5258e94d9a821fd71c73aac30569c1501..c8fd8bcfabd56235bf392fed177898c830115d0b 100644 (file)
@@ -465,4 +465,8 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
       border-bottom-width: 3px;
     }
   }
+}
+
+.image-picker .none {
+  display: none;
 }
\ No newline at end of file
index 4e643dcdaa5ab9de5ec6be9ec8ef4c6881d34c07..62a7b400122cc37cdc1adef0251d5e10b5ebb39c 100644 (file)
@@ -267,9 +267,4 @@ input.outline {
 
 .image-picker img {
   background-color: #BBB;
-}
-
-div[toggle-switch] {
-  height: 18px;
-  width: 150px;
 }
\ No newline at end of file
index e98e5bfcdf7bd27a4050a123bdf5636659004381..6acc4746881a6d669d5f867e7cec1b2da8bbf7da 100644 (file)
@@ -322,6 +322,9 @@ ul.pagination {
     font-size: 0.75em;
     margin-top: $-xs;
   }
+  .text-muted p.text-muted {
+    margin-top: 0;
+  }
   .page.draft .text-page {
     color: $color-page-draft;
   }
index 37c61159db077488d7b7d9ed3988bf81a20aa7f2..21553b8394d01f76392132b1fbeb3b2c269bbeed 100644 (file)
@@ -35,6 +35,12 @@ table.table {
   tr:hover {
     background-color: #EEE;
   }
+  .text-right {
+    text-align: right;
+  }
+  .text-center {
+    text-align: center;
+  }
 }
 
 table.no-style {
index 9bad2e83d15aa2621b04ce27993124fe8dd7306b..dd2f32e1c2eb98e08d523ef95b464e8df79ebf60 100644 (file)
@@ -109,6 +109,9 @@ em, i, .italic {
 small, p.small, span.small, .text-small {
   font-size: 0.8em;
   color: lighten($text-dark, 20%);
+  small, p.small, span.small, .text-small {
+    font-size: 1em;
+  }
 }
 
 sup, .superscript {
index 183480faa1338110759f496a9c9c3d3e0faed8e5..0017acd1d2df801b84c548034fb1cef26bc359fe 100644 (file)
@@ -16,7 +16,7 @@ return [
     'app_name_desc' => 'Dieser Name wird im Header und E-Mails angezeigt.',
     'app_name_header' => 'Anwendungsname im Header anzeigen?',
     'app_public_viewing' => '&Ouml;ffentliche Ansicht erlauben?',
-    'app_secure_images' => 'Erh&oml;hte Sicherheit f&uuml;r Bilduploads aktivieren?',
+    'app_secure_images' => 'Erh&ouml;hte Sicherheit f&uuml;r Bilduploads aktivieren?',
     'app_secure_images_desc' => 'Aus Leistungsgr&uuml;nden sind alle Bilder &ouml;ffentlich sichtbar. Diese Option f&uuml;gt zuf&auml;llige, schwer zu eratene, Zeichenketten vor die Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnindexes deaktiviert sind, um einen einfachen Zugrif zu verhindern.',
     'app_editor' => 'Seiteneditor',
     'app_editor_desc' => 'W&auml;hlen sie den Editor aus, der von allen Benutzern genutzt werden soll, um Seiten zu editieren.',
index ffdb1cf45cfc6ef8359f4d23ef3076449db01690..b734828fc7d617675da040d25c954277f0139f4e 100644 (file)
@@ -14,7 +14,49 @@ return [
     'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
 
     /**
-     * Email Confirmation Text
+     * Login & Register
+     */
+    'sign_up' => 'Sign up',
+    'log_in' => 'Log in',
+    'logout' => 'Logout',
+
+    'name' => 'Name',
+    'username' => 'Username',
+    'email' => 'Email',
+    'password' => 'Password',
+    'password_confirm' => 'Confirm Password',
+    'password_hint' => 'Must be over 5 characters',
+    'forgot_password' => 'Forgot Password?',
+    'remember_me' => 'Remember Me',
+    'ldap_email_hint' => 'Please enter an email to use for this account.',
+    'create_account' => 'Create Account',
+    'social_login' => 'Social Login',
+    'social_registration' => 'Social Registration',
+    'social_registration_text' => 'Register and sign in using another service.',
+
+    'register_thanks' => 'Thanks for registering!',
+    'register_confirm' => 'Please check your email and click the confirmation button to access :appName.',
+    'registrations_disabled' => 'Registrations are currently disabled',
+    'registration_email_domain_invalid' => 'That email domain does not have access to this application',
+    'register_success' => 'Thanks for signing up! You are now registered and signed in.',
+
+
+    /**
+     * Password Reset
+     */
+    'reset_password' => 'Reset Password',
+    'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.',
+    'reset_password_send_button' => 'Send Reset Link',
+    'reset_password_sent_success' => 'A password reset link has been sent to :email.',
+    'reset_password_success' => 'Your password has been successfully reset.',
+
+    'email_reset_subject' => 'Reset your :appName password',
+    'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.',
+    'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.',
+
+
+    /**
+     * Email Confirmation
      */
     'email_confirm_subject' => 'Confirm your email on :appName',
     'email_confirm_greeting' => 'Thanks for joining :appName!',
@@ -23,4 +65,10 @@ return [
     'email_confirm_send_error' => 'Email confirmation required but the system could not send the email. Contact the admin to ensure email is set up correctly.',
     'email_confirm_success' => 'Your email has been confirmed!',
     'email_confirm_resent' => 'Confirmation email resent, Please check your inbox.',
+
+    'email_not_confirmed' => 'Email Address Not Confirmed',
+    'email_not_confirmed_text' => 'Your email address has not yet been confirmed.',
+    'email_not_confirmed_click_link' => 'Please click the link in the email that was sent shortly after you registered.',
+    'email_not_confirmed_resend' => 'If you cannot find the email you can re-send the confirmation email by submitting the form below.',
+    'email_not_confirmed_resend_button' => 'Resend Confirmation Email',
 ];
\ No newline at end of file
diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php
new file mode 100644 (file)
index 0000000..31ef42e
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+return [
+
+    /**
+     * Buttons
+     */
+    'cancel' => 'Cancel',
+    'confirm' => 'Confirm',
+    'back' => 'Back',
+    'save' => 'Save',
+    'continue' => 'Continue',
+    'select' => 'Select',
+
+    /**
+     * Form Labels
+     */
+    'name' => 'Name',
+    'description' => 'Description',
+    'role' => 'Role',
+
+    /**
+     * Actions
+     */
+    'actions' => 'Actions',
+    'view' => 'View',
+    'create' => 'Create',
+    'update' => 'Update',
+    'edit' => 'Edit',
+    'sort' => 'Sort',
+    'move' => 'Move',
+    'delete' => 'Delete',
+    'search' => 'Search',
+    'search_clear' => 'Clear Search',
+    'reset' => 'Reset',
+    'remove' => 'Remove',
+
+
+    /**
+     * Misc
+     */
+    'deleted_user' => 'Deleted User',
+    'no_activity' => 'No activity to show',
+    'no_items' => 'No items available',
+    'back_to_top' => 'Back to top',
+    'toggle_details' => 'Toggle Details',
+
+    /**
+     * Header
+     */
+    'view_profile' => 'View Profile',
+    'edit_profile' => 'Edit Profile',
+
+    /**
+     * Email Content
+     */
+    'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:',
+    'email_rights' => 'All rights reserved',
+];
\ No newline at end of file
diff --git a/resources/lang/en/components.php b/resources/lang/en/components.php
new file mode 100644 (file)
index 0000000..b910870
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+return [
+
+    /**
+     * Image Manager
+     */
+    'image_select' => 'Image Select',
+    'image_all' => 'All',
+    'image_all_title' => 'View all images',
+    'image_book_title' => 'View images uploaded to this book',
+    'image_page_title' => 'View images uploaded to this page',
+    'image_search_hint' => 'Search by image name',
+    'image_uploaded' => 'Uploaded :uploadedDate',
+    'image_load_more' => 'Load More',
+    'image_image_name' => 'Image Name',
+    'image_delete_confirm' => 'This image is used in the pages below, Click delete again to confirm you want to delete this image.',
+    'image_select_image' => 'Select Image',
+    'image_dropzone' => 'Drop images or click here to upload',
+    'images_deleted' => 'Images Deleted',
+    'image_preview' => 'Image Preview',
+    'image_upload_success' => 'Image uploaded successfully',
+    'image_update_success' => 'Image details successfully updated',
+    'image_delete_success' => 'Image successfully deleted'
+];
\ No newline at end of file
diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php
new file mode 100644 (file)
index 0000000..033d961
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+return [
+
+    /**
+     * Shared
+     */
+    'recently_created' => 'Recently Created',
+    'recently_created_pages' => 'Recently Created Pages',
+    'recently_updated_pages' => 'Recently Updated Pages',
+    'recently_created_chapters' => 'Recently Created Chapters',
+    'recently_created_books' => 'Recently Created Books',
+    'recently_update' => 'Recently Updated',
+    'recently_viewed' => 'Recently Viewed',
+    'recent_activity' => 'Recent Activity',
+    'create_now' => 'Create one now',
+    'revisions' => 'Revisions',
+    'meta_created' => 'Created :timeLength',
+    'meta_created_name' => 'Created :timeLength by :user',
+    'meta_updated' => 'Updated :timeLength',
+    'meta_updated_name' => 'Updated :timeLength by :user',
+    'x_pages' => ':count Pages',
+    'entity_select' => 'Entity Select',
+    'images' => 'Images',
+    'my_recent_drafts' => 'My Recent Drafts',
+    'my_recently_viewed' => 'My Recently Viewed',
+    'no_pages_viewed' => 'You have not viewed any pages',
+    'no_pages_recently_created' => 'No pages have been recently created',
+    'no_pages_recently_updated' => 'No pages have been recently updated',
+
+    /**
+     * Permissions and restrictions
+     */
+    'permissions' => 'Permissions',
+    'permissions_intro' => 'Once enabled, These permissions will take priority over any set role permissions.',
+    'permissions_enable' => 'Enable Custom Permissions',
+    'permissions_save' => 'Save Permissions',
+
+    /**
+     * Search
+     */
+    'search_results' => 'Search Results',
+    'search_results_page' => 'Page Search Results',
+    'search_results_chapter' => 'Chapter Search Results',
+    'search_results_book' => 'Book Search Results',
+    'search_clear' => 'Clear Search',
+    'search_view_pages' => 'View all matches pages',
+    'search_view_chapters' => 'View all matches chapters',
+    'search_view_books' => 'View all matches books',
+    'search_no_pages' => 'No pages matched this search',
+    'search_for_term' => 'Search for :term',
+    'search_page_for_term' => 'Page search for :term',
+    'search_chapter_for_term' => 'Chapter search for :term',
+    'search_book_for_term' => 'Books search for :term',
+
+    /**
+     * Books
+     */
+    'book' => 'Book',
+    'books' => 'Books',
+    'books_empty' => 'No books have been created',
+    'books_popular' => 'Popular Books',
+    'books_recent' => 'Recent Books',
+    'books_popular_empty' => 'The most popular books will appear here.',
+    'books_create' => 'Create New Book',
+    'books_delete' => 'Delete Book',
+    'books_delete_named' => 'Delete Book :bookName',
+    'books_delete_explain' => 'This will delete the book with the name \':bookName\', All pages and chapters will be removed.',
+    'books_delete_confirmation' => 'Are you sure you want to delete this book?',
+    'books_edit' => 'Edit Book',
+    'books_edit_named' => 'Edit Book :bookName',
+    'books_form_book_name' => 'Book Name',
+    'books_save' => 'Save Book',
+    'books_permissions' => 'Book Permissions',
+    'books_permissions_updated' => 'Book Permissions Updated',
+    'books_empty_contents' => 'No pages or chapters have been created for this book.',
+    'books_empty_create_page' => 'Create a new page',
+    'books_empty_or' => 'or',
+    'books_empty_sort_current_book' => 'Sort the current book',
+    'books_empty_add_chapter' => 'Add a chapter',
+    'books_permissions_active' => 'Book Permissions Active',
+    'books_search_this' => 'Search this book',
+    'books_navigation' => 'Book Navigation',
+    'books_sort' => 'Sort Book Contents',
+    'books_sort_named' => 'Sort Book :bookName',
+    'books_sort_show_other' => 'Show Other Books',
+    'books_sort_save' => 'Save New Order',
+
+    /**
+     * Chapters
+     */
+    'chapter' => 'Chapter',
+    'chapters_popular' => 'Popular Chapters',
+    'chapters_new' => 'New Chapter',
+    'chapters_create' => 'Create New Chapter',
+    'chapters_delete' => 'Delete Chapter',
+    'chapters_delete_named' => 'Delete Chapter :chapterName',
+    'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\', All pages will be removed
+        and added directly to the parent book.',
+    'chapters_delete_confirm' => 'Are you sure you want to delete this chapter?',
+    'chapters_edit' => 'Edit Chapter',
+    'chapters_edit_named' => 'Edit Chapter :chapterName',
+    'chapters_save' => 'Save Chapter',
+    'chapters_move' => 'Move Chapter',
+    'chapters_move_named' => 'Move Chapter :chapterName',
+    'chapter_move_success' => 'Chapter moved to :bookName',
+    'chapters_permissions' => 'Chapter Permissions',
+    'chapters_empty' => 'No pages are currently in this chapter.',
+    'chapters_permissions_active' => 'Chapter Permissions Active',
+    'chapters_permissions_success' => 'Chapter Permissions Updated',
+
+    /**
+     * Pages
+     */
+    'page' => 'Page',
+    'pages' => 'Pages',
+    'pages_popular' => 'Popular Pages',
+    'pages_new' => 'New Page',
+    'pages_attachments' => 'Attachments',
+    'pages_navigation' => 'Page Navigation',
+    'pages_delete' => 'Delete Page',
+    'pages_delete_named' => 'Delete Page :pageName',
+    'pages_delete_draft_named' => 'Delete Draft Page :pageName',
+    'pages_delete_draft' => 'Delete Draft Page',
+    'pages_delete_success' => 'Page deleted',
+    'pages_delete_draft_success' => 'Draft page deleted',
+    'pages_delete_confirm' => 'Are you sure you want to delete this page?',
+    'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?',
+    'pages_editing_named' => 'Editing Page :pageName',
+    'pages_edit_toggle_header' => 'Toggle header',
+    'pages_edit_save_draft' => 'Save Draft',
+    'pages_edit_draft' => 'Edit Page Draft',
+    'pages_editing_draft' => 'Editing Draft',
+    'pages_editing_page' => 'Editing Page',
+    'pages_edit_draft_save_at' => 'Draft saved at ',
+    'pages_edit_delete_draft' => 'Delete Draft',
+    'pages_edit_discard_draft' => 'Discard Draft',
+    'pages_edit_set_changelog' => 'Set Changelog',
+    'pages_edit_enter_changelog_desc' => 'Enter a brief description of the changes you\'ve made',
+    'pages_edit_enter_changelog' => 'Enter Changelog',
+    'pages_save' => 'Save Page',
+    'pages_title' => 'Page Title',
+    'pages_name' => 'Page Name',
+    'pages_md_editor' => 'Editor',
+    'pages_md_preview' => 'Preview',
+    'pages_md_insert_image' => 'Insert Image',
+    'pages_md_insert_link' => 'Insert Entity Link',
+    'pages_not_in_chapter' => 'Page is not in a chapter',
+    'pages_move' => 'Move Page',
+    'pages_move_success' => 'Page moved to ":parentName"',
+    'pages_permissions' => 'Page Permissions',
+    'pages_permissions_success' => 'Page permissions updated',
+    'pages_revisions' => 'Page Revisions',
+    'pages_revisions_named' => 'Page Revisions for :pageName',
+    'pages_revision_named' => 'Page Revision for :pageName',
+    'pages_revisions_created_by' => 'Created By',
+    'pages_revisions_date' => 'Revision Date',
+    'pages_revisions_changelog' => 'Changelog',
+    'pages_revisions_changes' => 'Changes',
+    'pages_revisions_current' => 'Current Version',
+    'pages_revisions_preview' => 'Preview',
+    'pages_revisions_restore' => 'Restore',
+    'pages_revisions_none' => 'This page has no revisions',
+    'pages_export' => 'Export',
+    'pages_export_html' => 'Contained Web File',
+    'pages_export_pdf' => 'PDF File',
+    'pages_export_text' => 'Plain Text File',
+    'pages_copy_link' => 'Copy Link',
+    'pages_permissions_active' => 'Page Permissions Active',
+    'pages_initial_revision' => 'Initial publish',
+    'pages_initial_name' => 'New Page',
+    'pages_editing_draft_notification' => 'You are currently editing a draft that was last saved :timeDiff.',
+    'pages_draft_edited_notification' => 'This page has been updated by since that time. It is recommended that you discard this draft.',
+    'pages_draft_edit_active' => [
+        'start_a' => ':count users have started editing this page',
+        'start_b' => ':userName has started editing this page',
+        'time_a' => 'since the pages was last updated',
+        'time_b' => 'in the last :minCount minutes',
+        'message' => ':start :time. Take care not to overwrite each other\'s updates!',
+    ],
+    'pages_draft_discarded' => 'Draft discarded, The editor has been updated with the current page content',
+
+    /**
+     * Editor sidebar
+     */
+    'page_tags' => 'Page Tags',
+    'tag' => 'Tag',
+    'tags' =>  '',
+    'tag_value' => 'Tag Value (Optional)',
+    'tags_explain' => "Add some tags to better categorise your content. \n You can assign a value to a tag for more in-depth organisation.",
+    'tags_add' => 'Add another tag',
+    'attachments' => 'Attachments',
+    'attachments_explain' => 'Upload some files or attach some link to display on your page. These are visible in the page sidebar.',
+    'attachments_explain_instant_save' => 'Changes here are saved instantly.',
+    'attachments_items' => 'Attached Items',
+    'attachments_upload' => 'Upload File',
+    'attachments_link' => 'Attach Link',
+    'attachments_set_link' => 'Set Link',
+    'attachments_delete_confirm' => 'Click delete again to confirm you want to delete this attachment.',
+    'attachments_dropzone' => 'Drop files or click here to attach a file',
+    'attachments_no_files' => 'No files have been uploaded',
+    'attachments_explain_link' => 'You can attach a link if you\'d prefer not to upload a file. This can be a link to another page or a link to a file in the cloud.',
+    'attachments_link_name' => 'Link Name',
+    'attachment_link' => 'Attachment link',
+    'attachments_link_url' => 'Link to file',
+    'attachments_link_url_hint' => 'Url of site or file',
+    'attach' => 'Attach',
+    'attachments_edit_file' => 'Edit File',
+    'attachments_edit_file_name' => 'File Name',
+    'attachments_edit_drop_upload' => 'Drop files or click here to upload and overwrite',
+    'attachments_order_updated' => 'Attachment order updated',
+    'attachments_updated_success' => 'Attachment details updated',
+    'attachments_deleted' => 'Attachment deleted',
+    'attachments_file_uploaded' => 'File successfully uploaded',
+    'attachments_file_updated' => 'File successfully updated',
+    'attachments_link_attached' => 'Link successfully attached to page',
+
+    /**
+     * Profile View
+     */
+    'profile_user_for_x' => 'User for :time',
+    'profile_created_content' => 'Created Content',
+    'profile_not_created_pages' => ':userName has not created any pages',
+    'profile_not_created_chapters' => ':userName has not created any chapters',
+    'profile_not_created_books' => ':userName has not created any books',
+];
\ No newline at end of file
index b1a252bf3a52a06c057d87ba94e818c3a6642f72..c4578a37a11d91c1eee8c03c3c1e4f3b08c99963 100644 (file)
@@ -6,7 +6,65 @@ return [
      * Error text strings.
      */
 
-    // Pages
+    // Permissions
     'permission' => 'You do not have permission to access the requested page.',
-    'permissionJson' => 'You do not have permission to perform the requested action.'
+    'permissionJson' => 'You do not have permission to perform the requested action.',
+
+    // Auth
+    'error_user_exists_different_creds' => 'A user with the email :email already exists but with different credentials.',
+    'email_already_confirmed' => 'Email has already been confirmed, Try logging in.',
+    'email_confirmation_invalid' => 'This confirmation token is not valid or has already been used, Please try registering again.',
+    'email_confirmation_expired' => 'The confirmation token has expired, A new confirmation email has been sent.',
+    'ldap_fail_anonymous' => 'LDAP access failed using anonymous bind',
+    'ldap_fail_authed' => 'LDAP access failed using given dn & password details',
+    'ldap_extension_not_installed' => 'LDAP PHP extension not installed',
+    'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed',
+    'social_no_action_defined' => 'No action defined',
+    'social_account_in_use' => 'This :socialAccount account is already in use, Try logging in via the :socialAccount option.',
+    'social_account_email_in_use' => 'The email :email is already in use. If you already have an account you can connect your :socialAccount account from your profile settings.',
+    'social_account_existing' => 'This :socialAccount is already attached to your profile.',
+    'social_account_already_used_existing' => 'This :socialAccount account is already used by another user.',
+    'social_account_not_used' => 'This :socialAccount account is not linked to any users. Please attach it in your profile settings. ',
+    'social_account_register_instructions' => 'If you do not yet have an account, You can register an account using the :socialAccount option.',
+    'social_driver_not_found' => 'Social driver not found',
+    'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.',
+
+    // System
+    'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.',
+    'cannot_get_image_from_url' => 'Cannot get image from :url',
+    'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.',
+    'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.',
+    'image_upload_error' => 'An error occurred uploading the image',
+
+    // Attachments
+    'attachment_page_mismatch' => 'Page mismatch during attachment update',
+
+    // Pages
+    'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page',
+
+    // Entities
+    'entity_not_found' => 'Entity not found',
+    'book_not_found' => 'Book not found',
+    'page_not_found' => 'Page not found',
+    'chapter_not_found' => 'Chapter not found',
+    'selected_book_not_found' => 'The selected book was not found',
+    'selected_book_chapter_not_found' => 'The selected Book or Chapter was not found',
+    'guests_cannot_save_drafts' => 'Guests cannot save drafts',
+
+    // Users
+    'users_cannot_delete_only_admin' => 'You cannot delete the only admin',
+    'users_cannot_delete_guest' => 'You cannot delete the guest user',
+
+    // Roles
+    'role_cannot_be_edited' => 'This role cannot be edited',
+    'role_system_cannot_be_deleted' => 'This role is a system role and cannot be deleted',
+    'role_registration_default_cannot_delete' => 'This role cannot be deleted while set as the default registration role',
+
+    // Error pages
+    '404_page_not_found' => 'Page Not Found',
+    'sorry_page_not_found' => 'Sorry, The page you were looking for could not be found.',
+    'return_home' => 'Return to home',
+    'error_occurred' => 'An Error Occurred',
+    'app_down' => ':appName is down right now',
+    'back_soon' => 'It will be back up soon.',
 ];
\ No newline at end of file
index 1b0bcad33414ab67660660e3d6fe4a21d810b9d9..e61df19d91172738d7ef1f3783c7bb847f2e1cf2 100644 (file)
@@ -10,7 +10,12 @@ return [
     
     'settings' => 'Settings',
     'settings_save' => 'Save Settings',
-    
+    'settings_save_success' => 'Settings saved',
+
+    /**
+     * App settings
+     */
+
     'app_settings' => 'App Settings',
     'app_name' => 'Application name',
     'app_name_desc' => 'This name is shown in the header and any emails.',
@@ -27,6 +32,10 @@ return [
     'app_primary_color' => 'Application primary color',
     'app_primary_color_desc' => 'This should be a hex value. <br>Leave empty to reset to the default color.',
 
+    /**
+     * Registration settings
+     */
+
     'reg_settings' => 'Registration Settings',
     'reg_allow' => 'Allow registration?',
     'reg_default_role' => 'Default user role after registration',
@@ -36,4 +45,96 @@ return [
     'reg_confirm_restrict_domain_desc' => 'Enter a comma separated list of email domains you would like to restrict registration to. Users will be sent an email to confirm their address before being allowed to interact with the application. <br> Note that users will be able to change their email addresses after successful registration.',
     'reg_confirm_restrict_domain_placeholder' => 'No restriction set',
 
-];
\ No newline at end of file
+    /**
+     * Role settings
+     */
+
+    'roles' => 'Roles',
+    'role_user_roles' => 'User Roles',
+    'role_create' => 'Create New Role',
+    'role_create_success' => 'Role successfully created',
+    'role_delete' => 'Delete Role',
+    'role_delete_confirm' => 'This will delete the role with the name \':roleName\'.',
+    'role_delete_users_assigned' => 'This role has :userCount users assigned to it. If you would like to migrate the users from this role select a new role below.',
+    'role_delete_no_migration' => "Don't migrate users",
+    'role_delete_sure' => 'Are you sure you want to delete this role?',
+    'role_delete_success' => 'Role successfully deleted',
+    'role_edit' => 'Edit Role',
+    'role_details' => 'Role Details',
+    'role_name' => 'Role Name',
+    'role_desc' => 'Short Description of Role',
+    'role_system' => 'System Permissions',
+    'role_manage_users' => 'Manage users',
+    'role_manage_roles' => 'Manage roles & role permissions',
+    'role_manage_entity_permissions' => 'Manage all book, chapter & page permissions',
+    'role_manage_own_entity_permissions' => 'Manage permissions on own book, chapter & pages',
+    'role_manage_settings' => 'Manage app settings',
+    'role_asset' => 'Asset Permissions',
+    'role_asset_desc' => 'These permissions control default access to the assets within the system. Permissions on Books, Chapters and Pages will override these permissions.',
+    'role_all' => 'All',
+    'role_own' => 'Own',
+    'role_controlled_by_asset' => 'Controlled by the asset they are uploaded to',
+    'role_save' => 'Save Role',
+    'role_update_success' => 'Role successfully updated',
+    'role_users' => 'Users in this role',
+    'role_users_none' => 'No users are currently assigned to this role',
+
+    /**
+     * Users
+     */
+
+    'users' => 'Users',
+    'user_profile' => 'User Profile',
+    'users_add_new' => 'Add New User',
+    'users_search' => 'Search Users',
+    'users_role' => 'User Roles',
+    'users_external_auth_id' => 'External Authentication ID',
+    'users_password_warning' => 'Only fill the below if you would like to change your password:',
+    'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.',
+    'users_delete' => 'Delete User',
+    'users_delete_named' => 'Delete ser :userName',
+    'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.',
+    'users_delete_confirm' => 'Are you sure you want to delete this user?',
+    'users_delete_success' => 'Users successfully removed',
+    'users_edit' => 'Edit User',
+    'users_edit_profile' => 'Edit Profile',
+    'users_edit_success' => 'User successfully updated',
+    'users_avatar' => 'User Avatar',
+    'users_avatar_desc' => 'This image should be approx 256px square.',
+    'users_social_accounts' => 'Social Accounts',
+    'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.',
+    'users_social_connect' => 'Connect Account',
+    'users_social_disconnect' => 'Disconnect Account',
+    'users_social_connected' => ':socialAccount account was successfully attached to your profile.',
+    'users_social_disconnected' => ':socialAccount account was successfully disconnected from your profile.',
+];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
index 20acc9a68e44b7b81003b04af347293c1e148c68..b75af7485ffb7baf86a2faaf46f6ab4107956a3d 100644 (file)
@@ -87,8 +87,8 @@ return [
     */
 
     'custom' => [
-        'attribute-name' => [
-            'rule-name' => 'custom-message',
+        'password-confirm' => [
+            'required_with' => 'Password confirmation required',
         ],
     ],
 
index 5230d43ca03086fde6fdab5c8ca925a0e2b4112c..b52b5f13e9148a497c79248f4e811885da5c7092 100644 (file)
@@ -1,19 +1,19 @@
 <div class="form-group">
-    <label for="username">Username</label>
+    <label for="username">{{ trans('auth.username') }}</label>
     @include('form/text', ['name' => 'username', 'tabindex' => 1])
 </div>
 
 @if(session('request-email', false) === true)
     <div class="form-group">
-        <label for="email">Email</label>
+        <label for="email">{{ trans('auth.email') }}</label>
         @include('form/text', ['name' => 'email', 'tabindex' => 1])
         <span class="text-neg">
-            Please enter an email to use for this account.
+            {{ trans('auth.ldap_email_hint') }}
         </span>
     </div>
 @endif
 
 <div class="form-group">
-    <label for="password">Password</label>
+    <label for="password">{{ trans('auth.password') }}</label>
     @include('form/password', ['name' => 'password', 'tabindex' => 2])
 </div>
\ No newline at end of file
index abefd21a1b6cc5e6064ff61ca0b29bfac5c65893..4ea1f35ba2b89c4ff8b34e8839cca16943feb16c 100644 (file)
@@ -1,10 +1,10 @@
 <div class="form-group">
-    <label for="email">Email</label>
+    <label for="email">{{ trans('auth.email') }}</label>
     @include('form/text', ['name' => 'email', 'tabindex' => 1])
 </div>
 
 <div class="form-group">
-    <label for="password">Password</label>
+    <label for="password">{{ trans('auth.password') }}</label>
     @include('form/password', ['name' => 'password', 'tabindex' => 2])
-    <span class="block small"><a href="{{ baseUrl('/password/email') }}">Forgot Password?</a></span>
+    <span class="block small"><a href="{{ baseUrl('/password/email') }}">{{ trans('auth.forgot_password') }}</a></span>
 </div>
\ No newline at end of file
index 4fa97c1d5bba0b0303c2ec56cf675ea0e890b2bb..295d1a801da8427945081288f8484ee73aa48e8f 100644 (file)
@@ -2,7 +2,7 @@
 
 @section('header-buttons')
     @if(setting('registration-enabled', false))
-        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>Sign up</a>
+        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>{{ trans('auth.sign_up') }}</a>
     @endif
 @stop
 
@@ -10,7 +10,7 @@
 
     <div class="text-center">
         <div class="center-box">
-            <h1>Log In</h1>
+            <h1>{{ title_case(trans('auth.log_in')) }}</h1>
 
             <form action="{{ baseUrl("/login") }}" method="POST" id="login-form">
                 {!! csrf_field() !!}
                 @include('auth/forms/login/' . $authMethod)
 
                 <div class="form-group">
-                    <label for="remember" class="inline">Remember Me</label>
+                    <label for="remember" class="inline">{{ trans('auth.remember_me') }}</label>
                     <input type="checkbox" id="remember" name="remember"  class="toggle-switch-checkbox">
                     <label for="remember" class="toggle-switch"></label>
                 </div>
 
 
                 <div class="from-group">
-                    <button class="button block pos" tabindex="3"><i class="zmdi zmdi-sign-in"></i> Sign In</button>
+                    <button class="button block pos" tabindex="3"><i class="zmdi zmdi-sign-in"></i> {{ title_case(trans('auth.log_in')) }}</button>
                 </div>
             </form>
 
             @if(count($socialDrivers) > 0)
                 <hr class="margin-top">
-                <h3 class="text-muted">Social Login</h3>
+                <h3 class="text-muted">{{ trans('auth.social_login') }}</h3>
                 @if(isset($socialDrivers['google']))
                     <a href="{{ baseUrl("/login/service/google") }}" style="color: #DC4E41;"><i class="zmdi zmdi-google-plus-box zmdi-hc-4x"></i></a>
                 @endif
index 115785ab2eb43893df69e64b3573c7aa3b3a9101..07bd2c3835e5ad200ed8d04e90a03b01647eab67 100644 (file)
@@ -1,9 +1,9 @@
 @extends('public')
 
 @section('header-buttons')
-    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>Sign in</a>
+    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>{{ trans('auth.log_in') }}</a>
     @if(setting('registration-enabled'))
-        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>Sign up</a>
+        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>{{ trans('auth.sign_up') }}</a>
     @endif
 @stop
 
 
     <div class="text-center">
         <div class="center-box text-left">
-            <h1>Reset Password</h1>
+            <h1>{{ trans('auth.reset_password') }}</h1>
 
-            <p class="muted small">Enter your email below and you will be sent an email with a password reset link.</p>
+            <p class="muted small">{{ trans('auth.reset_password_send_instructions') }}</p>
 
             <form action="{{ baseUrl("/password/email") }}" method="POST">
                 {!! csrf_field() !!}
 
                 <div class="form-group">
-                    <label for="email">Email</label>
+                    <label for="email">{{ trans('auth.email') }}</label>
                     @include('form/text', ['name' => 'email'])
                 </div>
 
                 <div class="from-group">
-                    <button class="button block pos">Send Reset Link</button>
+                    <button class="button block pos">{{ trans('auth.reset_password_send_button') }}</button>
                 </div>
             </form>
         </div>
index 612b50ff835eb069f54b77ae0bf8af91c8d09acf..a463eef45eeb717ff646ec5f29a24635e2ea3dd3 100644 (file)
@@ -1,9 +1,9 @@
 @extends('public')
 
 @section('header-buttons')
-    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>Sign in</a>
+    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>{{ trans('auth.log_in') }}</a>
     @if(setting('registration-enabled'))
-        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>Sign up</a>
+        <a href="{{ baseUrl("/register") }}"><i class="zmdi zmdi-account-add"></i>{{ trans('auth.sign_up') }}</a>
     @endif
 @stop
 
 
     <div class="text-center">
         <div class="center-box text-left">
-            <h1>Reset Password</h1>
+            <h1>{{ trans('auth.reset_password') }}</h1>
 
             <form action="{{ baseUrl("/password/reset") }}" method="POST">
                 {!! csrf_field() !!}
                 <input type="hidden" name="token" value="{{ $token }}">
 
                 <div class="form-group">
-                    <label for="email">Email</label>
+                    <label for="email">{{ trans('auth.email') }}</label>
                     @include('form/text', ['name' => 'email'])
                 </div>
 
                 <div class="form-group">
-                    <label for="password">Password</label>
+                    <label for="password">{{ trans('auth.password') }}</label>
                     @include('form/password', ['name' => 'password'])
                 </div>
 
                 <div class="form-group">
-                    <label for="password_confirmation">Confirm Password</label>
+                    <label for="password_confirmation">{{ trans('auth.password_confirm') }}</label>
                     @include('form/password', ['name' => 'password_confirmation'])
                 </div>
 
                 <div class="from-group">
-                    <button class="button block pos">Reset Password</button>
+                    <button class="button block pos">{{ trans('auth.reset_password') }}</button>
                 </div>
             </form>
         </div>
index 97fd65ab51238f3df8e6ceca5c0b9593dcc37b0f..364df92664182694c103ebea3757d46576491c13 100644 (file)
@@ -2,7 +2,7 @@
 
 @section('header-buttons')
     @if(!$signedIn)
-        <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>Sign in</a>
+        <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>{{ trans('auth.log_in') }}</a>
     @endif
 @stop
 
 
     <div class="text-center">
         <div class="center-box">
-            <h2>Thanks for registering!</h2>
-            <p>Please check your email and click the confirmation button to access {{ setting('app-name', 'BookStack') }}.</p>
+            <h2>{{ trans('auth.register_thanks') }}</h2>
+            <p>{{ trans('auth.register_confirm', ['appName' => setting('app-name')]) }}</p>
         </div>
     </div>
 
-
 @stop
index 8ae5fcf5067725e00c64d30867fd163db3dbf807..7a119ddba880f8ee8f14af1e2999babf6c9aed8d 100644 (file)
@@ -1,42 +1,42 @@
 @extends('public')
 
 @section('header-buttons')
-    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>Sign in</a>
+    <a href="{{ baseUrl("/login") }}"><i class="zmdi zmdi-sign-in"></i>{{ trans('auth.log_in') }}</a>
 @stop
 
 @section('content')
 
     <div class="text-center">
         <div class="center-box">
-            <h1>Sign Up</h1>
+            <h1>{{ title_case(trans('auth.sign_up')) }}</h1>
 
             <form action="{{ baseUrl("/register") }}" method="POST">
                 {!! csrf_field() !!}
 
                 <div class="form-group">
-                    <label for="email">Name</label>
+                    <label for="email">{{ trans('auth.name') }}</label>
                     @include('form/text', ['name' => 'name'])
                 </div>
 
                 <div class="form-group">
-                    <label for="email">Email</label>
+                    <label for="email">{{ trans('auth.email') }}</label>
                     @include('form/text', ['name' => 'email'])
                 </div>
 
                 <div class="form-group">
-                    <label for="password">Password</label>
-                    @include('form/password', ['name' => 'password', 'placeholder' => 'Must be over 5 characters'])
+                    <label for="password">{{ trans('auth.password') }}</label>
+                    @include('form/password', ['name' => 'password', 'placeholder' => trans('auth.password_hint')])
                 </div>
 
                 <div class="from-group">
-                    <button class="button block pos">Create Account</button>
+                    <button class="button block pos">{{ trans('auth.create_account') }}</button>
                 </div>
             </form>
 
             @if(count($socialDrivers) > 0)
                 <hr class="margin-top">
-                <h3 class="text-muted">Social Registration</h3>
-                <p class="text-small">Register and sign in using another service.</p>
+                <h3 class="text-muted">{{ trans('auth.social_registration') }}</h3>
+                <p class="text-small">{{ trans('auth.social_registration_text') }}</p>
                 @if(isset($socialDrivers['google']))
                     <a href="{{ baseUrl("/register/service/google") }}" style="color: #DC4E41;"><i class="zmdi zmdi-google-plus-box zmdi-hc-4x"></i></a>
                 @endif
index 08178e891a633b6af530601d9eb2d589f8e4dcee..13567b412817e1f20fbb6245fcdf6062b9e37f74 100644 (file)
@@ -4,16 +4,16 @@
 
     <div class="row">
         <div class="col-md-6 col-md-offset-3">
-            <h2>Email Address not confirmed</h2>
-            <p class="text-muted">Your email address has not yet been confirmed. <br>
-                Please click the link in the email that was sent shortly after you registered. <br>
-                If you cannot find the email you can re-send the confirmation email by submitting the form below.
+            <h2>{{ trans('auth.email_not_confirmed') }}</h2>
+            <p class="text-muted">{{ trans('auth.email_not_confirmed_text') }}<br>
+                {{ trans('auth.email_not_confirmed_click_link') }} <br>
+                {{ trans('auth.email_not_confirmed_resend') }}
             </p>
             <hr>
             <form action="{{ baseUrl("/register/confirm/resend") }}" method="POST">
                 {!! csrf_field() !!}
                 <div class="form-group">
-                    <label for="email">Email Address</label>
+                    <label for="email">{{ trans('auth.email') }}</label>
                     @if(auth()->check())
                         @include('form/text', ['name' => 'email', 'model' => auth()->user()])
                     @else
@@ -21,7 +21,7 @@
                     @endif
                 </div>
                 <div class="form-group">
-                    <button type="submit" class="button pos">Resend Confirmation Email</button>
+                    <button type="submit" class="button pos">{{ trans('auth.email_not_confirmed_resend_button') }}</button>
                 </div>
             </form>
         </div>
index 08acf725d95ea013b54fcd0742060d87e9d571ed..43f22d89a117cac1a6921058b2006c32292755b2 100644 (file)
@@ -17,6 +17,7 @@
     <!-- Scripts -->
     <script src="{{ baseUrl('/libs/jquery/jquery.min.js?version=2.1.4') }}"></script>
     <script src="{{ baseUrl('/libs/jquery/jquery-ui.min.js?version=1.11.4') }}"></script>
+    <script src="{{ baseUrl('/translations.js') }}"></script>
 
     @yield('head')
 
                 <div class="col-lg-4 col-sm-5">
                     <div class="float right">
                         <div class="links text-center">
-                            <a href="{{ baseUrl('/books') }}"><i class="zmdi zmdi-book"></i>Books</a>
+                            <a href="{{ baseUrl('/books') }}"><i class="zmdi zmdi-book"></i>{{ trans('entities.books') }}</a>
                             @if(isset($currentUser) && userCan('settings-manage'))
-                                <a href="{{ baseUrl('/settings') }}"><i class="zmdi zmdi-settings"></i>Settings</a>
+                                <a href="{{ baseUrl('/settings') }}"><i class="zmdi zmdi-settings"></i>{{ trans('settings.settings') }}</a>
                             @endif
                             @if(!isset($signedIn) || !$signedIn)
-                                <a href="{{ baseUrl('/login') }}"><i class="zmdi zmdi-sign-in"></i>Sign In</a>
+                                <a href="{{ baseUrl('/login') }}"><i class="zmdi zmdi-sign-in"></i>{{ trans('auth.log_in') }}</a>
                             @endif
                         </div>
                         @if(isset($signedIn) && $signedIn)
-                            <div class="dropdown-container" dropdown>
-                                <span class="user-name" dropdown-toggle>
-                                    <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
-                                    <span class="name" ng-non-bindable>{{ $currentUser->getShortName(9) }}</span> <i class="zmdi zmdi-caret-down"></i>
-                                </span>
-                                <ul>
-                                    <li>
-                                        <a href="{{ baseUrl("/user/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-account zmdi-hc-fw zmdi-hc-lg"></i>View Profile</a>
-                                    </li>
-                                    <li>
-                                        <a href="{{ baseUrl("/settings/users/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-edit zmdi-hc-fw zmdi-hc-lg"></i>Edit Profile</a>
-                                    </li>
-                                    <li>
-                                        <a href="{{ baseUrl('/logout') }}" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-fw zmdi-hc-lg"></i>Logout</a>
-                                    </li>
-                                </ul>
-                            </div>
+                            @include('partials._header-dropdown', ['currentUser' => $currentUser])
                         @endif
 
                     </div>
@@ -93,7 +78,7 @@
 
     <div id="back-to-top">
         <div class="inner">
-            <i class="zmdi zmdi-chevron-up"></i> <span>Back to top</span>
+            <i class="zmdi zmdi-chevron-up"></i> <span>{{ trans('common.back_to_top') }}</span>
         </div>
     </div>
 @yield('bottom')
diff --git a/resources/views/books/_breadcrumbs.blade.php b/resources/views/books/_breadcrumbs.blade.php
new file mode 100644 (file)
index 0000000..e588127
--- /dev/null
@@ -0,0 +1,3 @@
+<div class="breadcrumbs">
+    <a href="{{$book->getUrl()}}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
+</div>
\ No newline at end of file
index 60f4f65bde588e3c00037bc65cd8fd315a92ca6d..2c629e699622053940849dc207121cb4a201b21d 100644 (file)
@@ -3,7 +3,7 @@
 @section('content')
 
 <div class="container small" ng-non-bindable>
-    <h1>Create New Book</h1>
+    <h1>{{ trans('entities.books_create') }}</h1>
     <form action="{{ baseUrl("/books") }}" method="POST">
         @include('books/form')
     </form>
index 68f75513190cabe4e281e03cae4ed55d85a426fb..0b1e67d4acc7dc3dbd9c52dfcedf357a2c3d2444 100644 (file)
@@ -2,16 +2,26 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    @include('books._breadcrumbs', ['book' => $book])
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
-        <h1>Delete Book</h1>
-        <p>This will delete the book with the name '{{$book->name}}', All pages and chapters will be removed.</p>
-        <p class="text-neg">Are you sure you want to delete this book?</p>
+        <h1>{{ trans('entities.books_delete') }}</h1>
+        <p>{{ trans('entities.books_delete_explain', ['bookName' => $book->name]) }}</p>
+        <p class="text-neg">{{ trans('entities.books_delete_confirmation') }}</p>
 
         <form action="{{$book->getUrl()}}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="DELETE">
-            <a href="{{$book->getUrl()}}" class="button">Cancel</a>
-            <button type="submit" class="button neg">Confirm</button>
+            <a href="{{$book->getUrl()}}" class="button">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button neg">{{ trans('common.confirm') }}</button>
         </form>
     </div>
 
index e67e6f459844bb24f7632cf63581ea727fe87f1c..2419b68da807ab1a346293ee38ec694e67c1c25a 100644 (file)
@@ -2,8 +2,18 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    @include('books._breadcrumbs', ['book' => $book])
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
-        <h1>Edit Book</h1>
+        <h1>{{ trans('entities.books_edit') }}</h1>
         <form action="{{ $book->getUrl() }}" method="POST">
             <input type="hidden" name="_method" value="PUT">
             @include('books/form', ['model' => $book])
index dc0fd0a3fbc0490a02881d3ff507890d6c5972d6..514abf42cab9413e1c0011898dbf5f079cebfe51 100644 (file)
@@ -1,16 +1,16 @@
 
 {{ csrf_field() }}
 <div class="form-group title-input">
-    <label for="name">Book Name</label>
+    <label for="name">{{ trans('common.name') }}</label>
     @include('form/text', ['name' => 'name'])
 </div>
 
 <div class="form-group description-input">
-    <label for="description">Description</label>
+    <label for="description">{{ trans('common.description') }}</label>
     @include('form/textarea', ['name' => 'description'])
 </div>
 
 <div class="form-group">
-    <a href="{{ back()->getTargetUrl() }}" class="button muted">Cancel</a>
-    <button type="submit" class="button pos">Save Book</button>
+    <a href="{{ back()->getTargetUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button type="submit" class="button pos">{{ trans('entities.books_save') }}</button>
 </div>
\ No newline at end of file
index 91906e7b809650ec9c06cd49352155074cf5879a..c090a127e1dee9076020d9397ce46f7eaaf39804 100644 (file)
@@ -9,7 +9,7 @@
                 <div class="col-xs-11 faded">
                     <div class="action-buttons">
                         @if($currentUser->can('book-create-all'))
-                            <a href="{{ baseUrl("/books/create") }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>Add new book</a>
+                            <a href="{{ baseUrl("/books/create") }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>{{ trans('entities.books_create') }}</a>
                         @endif
                     </div>
                 </div>
@@ -21,7 +21,7 @@
     <div class="container" ng-non-bindable>
         <div class="row">
             <div class="col-sm-7">
-                <h1>Books</h1>
+                <h1>{{ trans('entities.books') }}</h1>
                 @if(count($books) > 0)
                     @foreach($books as $book)
                         @include('books/list-item', ['book' => $book])
                     @endforeach
                     {!! $books->render() !!}
                 @else
-                    <p class="text-muted">No books have been created.</p>
+                    <p class="text-muted">{{ trans('entities.books_empty') }}</p>
                     @if(userCan('books-create-all'))
-                        <a href="{{ baseUrl("/books/create") }}" class="text-pos"><i class="zmdi zmdi-edit"></i>Create one now</a>
+                        <a href="{{ baseUrl("/books/create") }}" class="text-pos"><i class="zmdi zmdi-edit"></i>{{ trans('entities.create_one_now') }}</a>
                     @endif
                 @endif
             </div>
             <div class="col-sm-4 col-sm-offset-1">
                 <div id="recents">
                     @if($recents)
-                        <div class="margin-top large">&nbsp;</div>
-                        <h3>Recently Viewed</h3>
+                        <div class="margin-top">&nbsp;</div>
+                        <h3>{{ trans('entities.recently_viewed') }}</h3>
                         @include('partials/entity-list', ['entities' => $recents])
                     @endif
                 </div>
                 <div class="margin-top large">&nbsp;</div>
                 <div id="popular">
-                    <h3>Popular Books</h3>
+                    <h3>{{ trans('entities.books_popular') }}</h3>
                     @if(count($popular) > 0)
                         @include('partials/entity-list', ['entities' => $popular])
                     @else
-                        <p class="text-muted">The most popular books will appear here.</p>
+                        <p class="text-muted">{{ trans('entities.books_popular_empty') }}</p>
                     @endif
                 </div>
             </div>
index 7fdd3abef855fc7820f8f756314334f8dec74f72..f558fdfce82c2952583cbfb90c9f943d79ed7fa5 100644 (file)
@@ -6,9 +6,7 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{$book->getUrl()}}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
-                    </div>
+                    @include('books._breadcrumbs', ['book' => $book])
                 </div>
             </div>
         </div>
@@ -16,7 +14,7 @@
 
 
     <div class="container" ng-non-bindable>
-        <h1>Book Permissions</h1>
+        <h1>{{ trans('entities.books_permissions') }}</h1>
         @include('form/restriction-form', ['model' => $book])
     </div>
 
index 129851d5e78ce2f725be11712c9b034b1928600e..6a18302bc3ac8a8dae53e45368cc5cd7555dc951 100644 (file)
@@ -5,29 +5,32 @@
     <div class="faded-small toolbar">
         <div class="container">
             <div class="row">
-                <div class="col-md-12">
+                <div class="col-md-6 faded">
+                    @include('books._breadcrumbs', ['book' => $book])
+                </div>
+                <div class="col-md-6">
                     <div class="action-buttons faded">
                         @if(userCan('page-create', $book))
-                            <a href="{{ $book->getUrl('/page/create') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i> New Page</a>
+                            <a href="{{ $book->getUrl('/page/create') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>{{ trans('entities.pages_new') }}</a>
                         @endif
                         @if(userCan('chapter-create', $book))
-                            <a href="{{ $book->getUrl('/chapter/create') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i> New Chapter</a>
+                            <a href="{{ $book->getUrl('/chapter/create') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>{{ trans('entities.chapters_new') }}</a>
                         @endif
                         @if(userCan('book-update', $book))
-                            <a href="{{$book->getEditUrl()}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
+                            <a href="{{$book->getEditUrl()}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>{{ trans('common.edit') }}</a>
                         @endif
                         @if(userCan('book-update', $book) || userCan('restrictions-manage', $book) || userCan('book-delete', $book))
                             <div dropdown class="dropdown-container">
                                 <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-more-vert"></i></a>
                                 <ul>
                                     @if(userCan('book-update', $book))
-                                        <li><a href="{{ $book->getUrl('/sort') }}" class="text-primary"><i class="zmdi zmdi-sort"></i>Sort</a></li>
+                                        <li><a href="{{ $book->getUrl('/sort') }}" class="text-primary"><i class="zmdi zmdi-sort"></i>{{ trans('common.sort') }}</a></li>
                                     @endif
                                     @if(userCan('restrictions-manage', $book))
-                                        <li><a href="{{ $book->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>Permissions</a></li>
+                                        <li><a href="{{ $book->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.permissions') }}</a></li>
                                     @endif
                                     @if(userCan('book-delete', $book))
-                                        <li><a href="{{ $book->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a></li>
+                                        <li><a href="{{ $book->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>{{ trans('common.delete') }}</a></li>
                                     @endif
                                 </ul>
                             </div>
                                 <hr>
                             @endforeach
                         @else
-                            <p class="text-muted">No pages or chapters have been created for this book.</p>
+                            <p class="text-muted">{{ trans('entities.books_empty_contents') }}</p>
                             <p>
-                                <a href="{{ $book->getUrl('/page/create') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>Create a new page</a>
-                                &nbsp;&nbsp;<em class="text-muted">-or-</em>&nbsp;&nbsp;&nbsp;
-                                <a href="{{ $book->getUrl('/chapter/create') }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>Add a chapter</a>
+                                <a href="{{ $book->getUrl('/page/create') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.books_empty_create_page') }}</a>
+                                &nbsp;&nbsp;<em class="text-muted">-{{ trans('entities.books_empty_or') }}-</em>&nbsp;&nbsp;&nbsp;
+                                <a href="{{ $book->getUrl('/chapter/create') }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>{{ trans('entities.books_empty_add_chapter') }}</a>
                             </p>
                             <hr>
                         @endif
-                        <p class="text-muted small">
-                            Created {{$book->created_at->diffForHumans()}} @if($book->createdBy) by <a href="{{ $book->createdBy->getProfileUrl() }}">{{$book->createdBy->name}}</a> @endif
-                            <br>
-                            Last Updated {{$book->updated_at->diffForHumans()}} @if($book->updatedBy) by <a href="{{ $book->updatedBy->getProfileUrl() }}">{{$book->updatedBy->name}}</a> @endif
-                        </p>
+                        @include('partials.entity-meta', ['entity' => $book])
                     </div>
                 </div>
                 <div class="search-results" ng-cloak ng-show="searching">
-                    <h3 class="text-muted">Search Results <a ng-if="searching" ng-click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>Clear Search</a></h3>
+                    <h3 class="text-muted">{{ trans('entities.search_results') }} <a ng-if="searching" ng-click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3>
                     <div ng-if="!searchResults">
                         @include('partials/loading-icon')
                     </div>
                 @if($book->restricted)
                     <p class="text-muted">
                         @if(userCan('restrictions-manage', $book))
-                            <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Book Permissions Active</a>
+                            <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}</a>
                         @else
-                            <i class="zmdi zmdi-lock-outline"></i>Book Permissions Active
+                            <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}
                         @endif
                     </p>
                 @endif
                 <div class="search-box">
                     <form ng-submit="searchBook($event)">
-                        <input ng-model="searchTerm" ng-change="checkSearchForm()" type="text" name="term" placeholder="Search This Book">
+                        <input ng-model="searchTerm" ng-change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.books_search_this') }}">
                         <button type="submit"><i class="zmdi zmdi-search"></i></button>
                         <button ng-if="searching" ng-click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button>
                     </form>
                 </div>
                 <div class="activity anim fadeIn">
-                    <h3>Recent Activity</h3>
+                    <h3>{{ trans('entities.recent_activity') }}</h3>
                     @include('partials/activity-list', ['activity' => Activity::entityActivity($book, 20, 0)])
                 </div>
             </div>
index 984db0ce68e5e8c67e8b508a96b63ae25079cc7f..d96f502f167c9127b5ecdefaab4c8031c197dcb6 100644 (file)
@@ -6,8 +6,18 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    @include('books._breadcrumbs', ['book' => $book])
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container" ng-non-bindable>
-        <h1>Sorting Pages & Chapters<span class="subheader">For {{ $book->name }}</span></h1>
+        <h1>{{ trans('entities.books_sort') }}</h1>
         <div class="row">
             <div class="col-md-8" id="sort-boxes">
 
@@ -17,7 +27,7 @@
 
             @if(count($books) > 1)
                 <div class="col-md-4">
-                    <h3>Show Other Books</h3>
+                    <h3>{{ trans('entities.books_sort_show_other') }}</h3>
                     <div id="additional-books">
                     @foreach($books as $otherBook)
                         @if($otherBook->id !== $book->id)
@@ -37,8 +47,8 @@
             <input type="hidden" name="_method" value="PUT">
             <input type="hidden" id="sort-tree-input" name="sort-tree">
             <div class="list">
-                <a href="{{ $book->getUrl() }}" class="button muted">Cancel</a>
-                <button class="button pos" type="submit">Save Order</button>
+                <a href="{{ $book->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+                <button class="button pos" type="submit">{{ trans('entities.books_sort_save') }}</button>
             </div>
         </form>
 
diff --git a/resources/views/chapters/_breadcrumbs.blade.php b/resources/views/chapters/_breadcrumbs.blade.php
new file mode 100644 (file)
index 0000000..9064cc7
--- /dev/null
@@ -0,0 +1,5 @@
+<div class="breadcrumbs">
+    <a href="{{ $chapter->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $chapter->book->getShortName() }}</a>
+    <span class="sep">&raquo;</span>
+    <a href="{{ $chapter->getUrl() }}" class="text-chapter text-button"><i class="zmdi zmdi-collection-bookmark"></i>{{$chapter->getShortName()}}</a>
+</div>
\ No newline at end of file
index b81cb15d7956054971fd7e32f307d8a7ad50837f..afdbfa99d058c8fd5ee2cca2f3f9377552d7d712 100644 (file)
@@ -3,7 +3,7 @@
 @section('content')
 
     <div class="container small" ng-non-bindable>
-        <h1>Create New Chapter</h1>
+        <h1>{{ trans('entities.chapters_create') }}</h1>
         <form action="{{ $book->getUrl('/chapter/create') }}" method="POST">
             @include('chapters/form')
         </form>
index e9573f22843820a87f775f0882817b5a716bf408..bacb8dca39df45ea72f83f8d702bfbde766f8958 100644 (file)
@@ -2,17 +2,26 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    @include('chapters._breadcrumbs', ['chapter' => $chapter])
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
-        <h1>Delete Chapter</h1>
-        <p>This will delete the chapter with the name '{{$chapter->name}}', All pages will be removed
-        and added directly to the book.</p>
-        <p class="text-neg">Are you sure you want to delete this chapter?</p>
+        <h1>{{ trans('entities.chapters_delete') }}</h1>
+        <p>{{ trans('entities.chapters_delete_explain', ['chapterName' => $chapter->name]) }}</p>
+        <p class="text-neg">{{ trans('entities.chapters_delete_confirm') }}</p>
 
         <form action="{{ $chapter->getUrl() }}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="DELETE">
-            <a href="{{ $chapter->getUrl() }}" class="button primary">Cancel</a>
-            <button type="submit" class="button neg">Confirm</button>
+            <a href="{{ $chapter->getUrl() }}" class="button primary">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button neg">{{ trans('common.confirm') }}</button>
         </form>
     </div>
 
index 0363da96d7817fc777641eb2380d27694cf7ca19..272543e67f9a6a6a8892c403fbf0af94fea9ddcc 100644 (file)
@@ -3,7 +3,7 @@
 @section('content')
 
     <div class="container small" ng-non-bindable>
-        <h1>Edit Chapter</h1>
+        <h1>{{ trans('entities.chapters_edit') }}</h1>
         <form action="{{  $chapter->getUrl() }}" method="POST">
             <input type="hidden" name="_method" value="PUT">
             @include('chapters/form', ['model' => $chapter])
index 70df4737a69aeb8832be9ff91adf7e493f6bab20..54722a58adc0c9094d0a8d1bd1ca3dfa55ec4a52 100644 (file)
@@ -2,16 +2,16 @@
 {!! csrf_field() !!}
 
 <div class="form-group title-input">
-    <label for="name">Chapter Name</label>
+    <label for="name">{{ trans('common.name') }}</label>
     @include('form/text', ['name' => 'name'])
 </div>
 
 <div class="form-group description-input">
-    <label for="description">Description</label>
+    <label for="description">{{ trans('common.description') }}</label>
     @include('form/textarea', ['name' => 'description'])
 </div>
 
 <div class="form-group">
-    <a href="{{ back()->getTargetUrl() }}" class="button muted">Cancel</a>
-    <button type="submit" class="button pos">Save Chapter</button>
+    <a href="{{ back()->getTargetUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button type="submit" class="button pos">{{ trans('entities.chapters_save') }}</button>
 </div>
index f70e592448f00068e554a9332f5ae5a3faf7f903..8487a63a3e5e4e4e20ce242b06aaeb6a192fc2ea 100644 (file)
@@ -17,7 +17,7 @@
     @endif
 
     @if(!isset($hidePages) && count($chapter->pages) > 0)
-        <p class="text-muted chapter-toggle"><i class="zmdi zmdi-caret-right"></i> <i class="zmdi zmdi-file-text"></i> <span>{{ count($chapter->pages) }} Pages</span></p>
+        <p class="text-muted chapter-toggle"><i class="zmdi zmdi-caret-right"></i> <i class="zmdi zmdi-file-text"></i> <span>{{ trans('entities.x_pages', ['count' => $chapter->pages->count()]) }}</span></p>
         <div class="inset-list">
             @foreach($chapter->pages as $page)
                 <h5 class="@if($page->draft) draft @endif"><a href="{{ $page->getUrl() }}" class="text-page @if($page->draft) draft @endif"><i class="zmdi zmdi-file-text"></i>{{$page->name}}</a></h5>
index 37d56d30dd0e243dae4ea94fc4fea6afac45bbef..9e6ddb52138b1aa165ba8d231bca5b807ffebfbf 100644 (file)
@@ -6,27 +6,23 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
-                        <span class="sep">&raquo;</span>
-                        <a href="{{ $chapter->getUrl() }}" class="text-chapter text-button"><i class="zmdi zmdi-collection-bookmark"></i>{{ $chapter->getShortName() }}</a>
-                    </div>
+                    @include('chapters._breadcrumbs', ['chapter' => $chapter])
                 </div>
             </div>
         </div>
     </div>
 
     <div class="container">
-        <h1>Move Chapter <small class="subheader">{{$chapter->name}}</small></h1>
+        <h1>{{ trans('entities.chapters_move') }}</h1>
 
         <form action="{{ $chapter->getUrl('/move') }}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="PUT">
 
-            @include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book'])
+            @include('components.entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book'])
 
-            <a href="{{ $chapter->getUrl() }}" class="button muted">Cancel</a>
-            <button type="submit" class="button pos">Move Chapter</button>
+            <a href="{{ $chapter->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button pos">{{ trans('entities.chapters_move') }}</button>
         </form>
     </div>
 
index 771665037f543492e45586683e9ead2eef97e136..7b908ee15d2144c927fb2b5a2673daf2a9ad5049 100644 (file)
@@ -6,18 +6,14 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $chapter->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $chapter->book->getShortName() }}</a>
-                        <span class="sep">&raquo;</span>
-                        <a href="{{ $chapter->getUrl() }}" class="text-chapter text-button"><i class="zmdi zmdi-collection-bookmark"></i>{{$chapter->getShortName()}}</a>
-                    </div>
+                    @include('chapters._breadcrumbs', ['chapter' => $chapter])
                 </div>
             </div>
         </div>
     </div>
 
     <div class="container" ng-non-bindable>
-        <h1>Chapter Permissions</h1>
+        <h1>{{ trans('entities.chapters_permissions') }}</h1>
         @include('form/restriction-form', ['model' => $chapter])
     </div>
 
index 70b09e9ce49266805d650dcd6c364b4ba695cd18..93eee6424c055bab1ec53dc4263310df215b631e 100644 (file)
@@ -6,30 +6,28 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-8 faded" ng-non-bindable>
-                    <div class="breadcrumbs">
-                        <a href="{{ $book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
-                    </div>
+                    @include('chapters._breadcrumbs', ['chapter' => $chapter])
                 </div>
                 <div class="col-sm-4 faded">
                     <div class="action-buttons">
                         @if(userCan('page-create', $chapter))
-                            <a href="{{ $chapter->getUrl('/create-page') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>New Page</a>
+                            <a href="{{ $chapter->getUrl('/create-page') }}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>{{ trans('entities.pages_new') }}</a>
                         @endif
                         @if(userCan('chapter-update', $chapter))
-                            <a href="{{ $chapter->getUrl('/edit') }}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
+                            <a href="{{ $chapter->getUrl('/edit') }}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>{{ trans('common.edit') }}</a>
                         @endif
                         @if(userCan('chapter-update', $chapter) || userCan('restrictions-manage', $chapter) || userCan('chapter-delete', $chapter))
                             <div dropdown class="dropdown-container">
                                 <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-more-vert"></i></a>
                                 <ul>
                                     @if(userCan('chapter-update', $chapter))
-                                        <li><a href="{{ $chapter->getUrl('/move') }}" class="text-primary"><i class="zmdi zmdi-folder"></i>Move</a></li>
+                                        <li><a href="{{ $chapter->getUrl('/move') }}" class="text-primary"><i class="zmdi zmdi-folder"></i>{{ trans('common.move') }}</a></li>
                                     @endif
                                     @if(userCan('restrictions-manage', $chapter))
-                                        <li><a href="{{ $chapter->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>Permissions</a></li>
+                                        <li><a href="{{ $chapter->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.permissions') }}</a></li>
                                     @endif
                                     @if(userCan('chapter-delete', $chapter))
-                                        <li><a href="{{ $chapter->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a></li>
+                                        <li><a href="{{ $chapter->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>{{ trans('common.delete') }}</a></li>
                                     @endif
                                 </ul>
                             </div>
                     </div>
                 @else
                     <hr>
-                    <p class="text-muted">No pages are currently in this chapter.</p>
+                    <p class="text-muted">{{ trans('entities.chapters_empty') }}</p>
                     <p>
                         @if(userCan('page-create', $chapter))
-                            <a href="{{ $chapter->getUrl('/create-page') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>Create a new page</a>
+                            <a href="{{ $chapter->getUrl('/create-page') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.books_empty_create_page') }}</a>
                         @endif
                         @if(userCan('page-create', $chapter) && userCan('book-update', $book))
-                            &nbsp;&nbsp;<em class="text-muted">-or-</em>&nbsp;&nbsp;&nbsp;
+                            &nbsp;&nbsp;<em class="text-muted">-{{ trans('entities.books_empty_or') }}-</em>&nbsp;&nbsp;&nbsp;
                         @endif
                         @if(userCan('book-update', $book))
-                            <a href="{{ $book->getUrl('/sort') }}" class="text-book"><i class="zmdi zmdi-book"></i>Sort the current book</a>
+                            <a href="{{ $book->getUrl('/sort') }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.books_empty_sort_current_book') }}</a>
                         @endif
                     </p>
                     <hr>
                 @endif
 
-                <p class="text-muted small">
-                    Created {{ $chapter->created_at->diffForHumans() }} @if($chapter->createdBy) by <a href="{{ $chapter->createdBy->getProfileUrl() }}">{{ $chapter->createdBy->name}}</a> @endif
-                    <br>
-                    Last Updated {{ $chapter->updated_at->diffForHumans() }} @if($chapter->updatedBy) by <a href="{{ $chapter->updatedBy->getProfileUrl() }}">{{  $chapter->updatedBy->name}}</a> @endif
-                </p>
+                @include('partials.entity-meta', ['entity' => $chapter])
             </div>
             <div class="col-md-3 col-md-offset-1">
                 <div class="margin-top large"></div>
                     <div class="text-muted">
 
                         @if($book->restricted)
-                            @if(userCan('restrictions-manage', $book))
-                                <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Book Permissions Active</a>
-                            @else
-                                <i class="zmdi zmdi-lock-outline"></i>Book Permissions Active
-                            @endif
-                                <br>
+                            <p class="text-muted">
+                                @if(userCan('restrictions-manage', $book))
+                                    <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}</a>
+                                @else
+                                    <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}
+                                @endif
+                            </p>
                         @endif
 
                         @if($chapter->restricted)
                             @if(userCan('restrictions-manage', $chapter))
-                                <a href="{{ $chapter->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Chapter Permissions Active</a>
+                                <a href="{{ $chapter->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.chapters_permissions_active') }}</a>
                             @else
-                                <i class="zmdi zmdi-lock-outline"></i>Chapter Permissions Active
+                                <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.chapters_permissions_active') }}
                             @endif
                         @endif
                     </div>
similarity index 63%
rename from resources/views/partials/entity-selector-popup.blade.php
rename to resources/views/components/entity-selector-popup.blade.php
index b9166896aad468c8e80880e1d5f51ea69a0693d1..1c4d1fadba9da58e41c8aa229ccfaab14e6f0c9b 100644 (file)
@@ -2,12 +2,12 @@
     <div class="overlay" entity-link-selector>
         <div class="popup-body small flex-child">
             <div class="popup-header primary-background">
-                <div class="popup-title">Entity Select</div>
+                <div class="popup-title">{{ trans('entities.entity_select') }}</div>
                 <button type="button" class="corner-button neg button popup-close">x</button>
             </div>
-            @include('partials/entity-selector', ['name' => 'entity-selector'])
+            @include('components.entity-selector', ['name' => 'entity-selector'])
             <div class="popup-footer">
-                <button type="button" disabled="true" class="button entity-link-selector-confirm pos corner-button">Select</button>
+                <button type="button" disabled="true" class="button entity-link-selector-confirm pos corner-button">{{ trans('common.select') }}</button>
             </div>
         </div>
     </div>
similarity index 66%
rename from resources/views/partials/entity-selector.blade.php
rename to resources/views/components/entity-selector.blade.php
index 59e1741559391da0d8f41aa445ec3a22a34fd8ce..8fb2187e6ff7395e8264c657813990fb79472baf 100644 (file)
@@ -1,8 +1,8 @@
 <div class="form-group">
     <div entity-selector class="entity-selector {{$selectorSize or ''}}" entity-types="{{ $entityTypes or 'book,chapter,page' }}">
         <input type="hidden" entity-selector-input name="{{$name}}" value="">
-        <input type="text" placeholder="Search" ng-model="search" ng-model-options="{debounce: 200}" ng-change="searchEntities()">
-        <div class="text-center loading" ng-show="loading">@include('partials/loading-icon')</div>
+        <input type="text" placeholder="{{ trans('common.search') }}" ng-model="search" ng-model-options="{debounce: 200}" ng-change="searchEntities()">
+        <div class="text-center loading" ng-show="loading">@include('partials.loading-icon')</div>
         <div ng-show="!loading" ng-bind-html="entityResults"></div>
     </div>
 </div>
\ No newline at end of file
similarity index 70%
rename from resources/views/partials/image-manager.blade.php
rename to resources/views/components/image-manager.blade.php
index 83625ad88d0ec665d68092e5062cb55d15e42b72..39f3bcd3c1a27f2072d7357a9f7a69bf705741b0 100644 (file)
@@ -3,7 +3,7 @@
         <div class="popup-body" ng-click="$event.stopPropagation()">
 
             <div class="popup-header primary-background">
-                <div class="popup-title">Image Select</div>
+                <div class="popup-title">{{ trans('components.image_select') }}</div>
                 <button class="popup-close neg corner-button button">x</button>
             </div>
 
                 <div class="image-manager-content">
                     <div ng-if="imageType === 'gallery'" class="container">
                         <div class="image-manager-header row faded-small nav-tabs">
-                            <div class="col-xs-4 tab-item" title="View all images" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> All</div>
-                            <div class="col-xs-4 tab-item" title="View images uploaded to this book" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> Book</div>
-                            <div class="col-xs-4 tab-item" title="View images uploaded to this page" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> Page</div>
+                            <div class="col-xs-4 tab-item" title="{{ trans('components.image_all_title') }}" ng-class="{selected: (view=='all')}" ng-click="setView('all')"><i class="zmdi zmdi-collection-image"></i> {{ trans('components.image_all') }}</div>
+                            <div class="col-xs-4 tab-item" title="{{ trans('components.image_book_title') }}" ng-class="{selected: (view=='book')}" ng-click="setView('book')"><i class="zmdi zmdi-book text-book"></i> {{ trans('entities.book') }}</div>
+                            <div class="col-xs-4 tab-item" title="{{ trans('components.image_page_title') }}" ng-class="{selected: (view=='page')}" ng-click="setView('page')"><i class="zmdi zmdi-file-text text-page"></i> {{ trans('entities.page') }}</div>
                         </div>
                     </div>
                     <div ng-show="view === 'all'" >
                         <form ng-submit="searchImages()" class="contained-search-box">
-                            <input type="text" placeholder="Search by image name" ng-model="searchTerm">
-                            <button ng-class="{active: searching}" title="Clear Search" type="button" ng-click="cancelSearch()" class="text-button cancel"><i class="zmdi zmdi-close-circle-o"></i></button>
-                            <button title="Search" class="text-button" type="submit"><i class="zmdi zmdi-search"></i></button>
+                            <input type="text" placeholder="{{ trans('components.image_search_hint') }}" ng-model="searchTerm">
+                            <button ng-class="{active: searching}" title="{{ trans('common.search_clear') }}" type="button" ng-click="cancelSearch()" class="text-button cancel"><i class="zmdi zmdi-close-circle-o"></i></button>
+                            <button title="{{ trans('common.search') }}" class="text-button" type="submit"><i class="zmdi zmdi-search"></i></button>
                         </form>
                     </div>
                     <div class="image-manager-list">
                                 <img ng-src="@{{image.thumbs.gallery}}" ng-attr-alt="@{{image.title}}" ng-attr-title="@{{image.name}}">
                                 <div class="image-meta">
                                     <span class="name" ng-bind="image.name"></span>
-                                    <span class="date">Uploaded @{{ getDate(image.created_at)  }}</span>
+                                    <span class="date">{{ trans('components.image_uploaded', ['uploadedDate' => "{{ getDate(image.created_at) }" . "}"]) }}</span>
                                 </div>
                             </div>
                         </div>
-                        <div class="load-more" ng-show="hasMore" ng-click="fetchData()">Load More</div>
+                        <div class="load-more" ng-show="hasMore" ng-click="fetchData()">{{ trans('components.image_load_more') }}</div>
                     </div>
                 </div>
 
                                     </a>
                                 </div>
                                 <div class="form-group">
-                                    <label for="name">Image Name</label>
+                                    <label for="name">{{ trans('components.image_image_name') }}</label>
                                     <input type="text" id="name" name="name" ng-model="selectedImage.name">
                                 </div>
                             </form>
 
                             <div ng-show="dependantPages">
                                 <p class="text-neg text-small">
-                                    This image is used in the pages below, Click delete again to confirm you want to delete
-                                    this image.
+                                    {{ trans('components.image_delete_confirm') }}
                                 </p>
                                 <ul class="text-neg">
                                     <li ng-repeat="page in dependantPages">
                                     <button class="button icon neg"><i class="zmdi zmdi-delete"></i></button>
                                 </form>
                                 <button class="button pos anim fadeIn float right" ng-show="selectedImage" ng-click="selectButtonClick()">
-                                    <i class="zmdi zmdi-square-right"></i>Select Image
+                                    <i class="zmdi zmdi-square-right"></i>{{ trans('components.image_select_image') }}
                                 </button>
                             </div>
 
                         </div>
 
-                        <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
+                        <drop-zone message="{{ trans('components.image_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
 
 
                     </div>
diff --git a/resources/views/components/image-picker.blade.php b/resources/views/components/image-picker.blade.php
new file mode 100644 (file)
index 0000000..47fb2b8
--- /dev/null
@@ -0,0 +1,66 @@
+<div class="image-picker" image-picker="{{$name}}" data-default-image="{{ $defaultImage }}" data-resize-height="{{ $resizeHeight }}" data-resize-width="{{ $resizeWidth }}" data-current-id="{{ $currentId or '' }}" data-resize-crop="{{ $resizeCrop or '' }}">
+
+    <div>
+        <img @if($currentImage && $currentImage !== 'none') src="{{$currentImage}}" @else src="{{$defaultImage}}" @endif  class="{{$imageClass}} @if($currentImage=== 'none') none @endif" alt="{{ trans('components.image_preview') }}">
+    </div>
+
+    <button class="button" type="button" data-action="show-image-manager">{{ trans('components.image_select_image') }}</button>
+    <br>
+    <button class="text-button" data-action="reset-image" type="button">{{ trans('common.reset') }}</button>
+
+    @if ($showRemove)
+        <span class="sep">|</span>
+        <button class="text-button neg" data-action="remove-image" type="button">{{ trans('common.remove') }}</button>
+    @endif
+
+    <input type="hidden" name="{{$name}}" id="{{$name}}" value="{{ isset($currentId) && ($currentId !== '' && $currentId !== false) ? $currentId : $currentImage}}">
+</div>
+
+<script>
+    (function(){
+
+        var picker = document.querySelector('[image-picker="{{$name}}"]');
+        picker.addEventListener('click', function(event) {
+            if (event.target.nodeName.toLowerCase() !== 'button') return;
+             var button = event.target;
+             var action = button.getAttribute('data-action');
+             var resize = picker.getAttribute('data-resize-height') && picker.getAttribute('data-resize-width');
+             var usingIds = picker.getAttribute('data-current-id') !== '';
+             var resizeCrop = picker.getAttribute('data-resize-crop') !== '';
+             var imageElem = picker.querySelector('img');
+             var input = picker.querySelector('input');
+
+             function setImage(image) {
+                 if (image === 'none') {
+                     imageElem.src = picker.getAttribute('data-default-image');
+                     imageElem.classList.add('none');
+                     input.value = 'none';
+                     return;
+                 }
+                 imageElem.src = image.url;
+                 input.value = usingIds ? image.id : image.url;
+                 imageElem.classList.remove('none');
+             }
+
+             if (action === 'show-image-manager') {
+                 window.ImageManager.showExternal((image) => {
+                     if (!resize) {
+                         setImage(image);
+                         return;
+                     }
+                     var requestString = '/images/thumb/' + image.id + '/' + picker.getAttribute('data-resize-width') + '/' + picker.getAttribute('data-resize-height') + '/' + (resizeCrop ? 'true' : 'false');
+                     $.get(window.baseUrl(requestString), resp => {
+                         image.url = resp.url;
+                         setImage(image);
+                     });
+                 });
+             } else if (action === 'reset-image') {
+                 setImage({id: 0, url: picker.getAttribute('data-default-image')});
+             } else if (action === 'remove-image') {
+                 setImage('none');
+             }
+
+            });
+
+    })();
+</script>
\ No newline at end of file
diff --git a/resources/views/components/toggle-switch.blade.php b/resources/views/components/toggle-switch.blade.php
new file mode 100644 (file)
index 0000000..ad54d5a
--- /dev/null
@@ -0,0 +1,15 @@
+<div toggle-switch="{{$name}}" class="toggle-switch @if($value) active @endif">
+    <input type="hidden" name="{{$name}}" value="{{$value?'true':'false'}}"/>
+    <div class="switch-handle"></div>
+</div>
+<script>
+    (function() {
+       var toggle = document.querySelector('[toggle-switch="{{$name}}"]');
+       var toggleInput = toggle.querySelector('input');
+       toggle.onclick = function(event) {
+           var checked = toggleInput.value !== 'true';
+           toggleInput.value = checked ? 'true' : 'false';
+           checked ? toggle.classList.add('active') : toggle.classList.remove('active');
+       };
+    })()
+</script>
\ No newline at end of file
index 19565bccbe534d13c469ecf63a8a7699211d681c..c9e600ceb7376489f6945f863b2b241da3037949 100644 (file)
@@ -4,9 +4,28 @@
 
 
 <div class="container">
-    <h1 class="text-muted">{{ $message or 'Page Not Found' }}</h1>
-    <p>Sorry, The page you were looking for could not be found.</p>
-    <a href="{{ baseUrl('/') }}" class="button">Return To Home</a>
+
+
+    <h1>{{ $message or trans('errors.404_page_not_found') }}</h1>
+    <p>{{ trans('errors.sorry_page_not_found') }}</p>
+    <p><a href="{{ baseUrl('/') }}" class="button">{{ trans('errors.return_home') }}</a></p>
+
+    <hr>
+
+    <div class="row">
+        <div class="col-md-4">
+            <h3 class="text-muted">{{ trans('entities.pages_popular') }}</h3>
+            @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Page::class]), 'style' => 'compact'])
+        </div>
+        <div class="col-md-4">
+            <h3 class="text-muted">{{ trans('entities.books_popular') }}</h3>
+            @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Book::class]), 'style' => 'compact'])
+        </div>
+        <div class="col-md-4">
+            <h3 class="text-muted">{{ trans('entities.chapters_popular') }}</h3>
+            @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Chapter::class]), 'style' => 'compact'])
+        </div>
+    </div>
 </div>
 
 @stop
\ No newline at end of file
index 2a58461ba324b7bdff3e14400ad3e7a23a12fbaf..6dd96cdcc98257f254cbe6d1f224c6658744f24d 100644 (file)
@@ -3,7 +3,7 @@
 @section('content')
 
     <div class="container">
-        <h1 class="text-muted">An Error Occurred</h1>
+        <h1 class="text-muted">{{ trans('errors.error_occurred') }}</h1>
         <p>{{ $message }}</p>
     </div>
 
index c79d0f68b8d877aade1b659b5904c5e6ea9c58c4..1ea39a7b8f1b3c59a9756d654ac22b97b43feadf 100644 (file)
@@ -3,8 +3,8 @@
 @section('content')
 
     <div class="container">
-        <h1 class="text-muted">{{ setting('app-name') }} is down right now</h1>
-        <p>It will be back up soon.</p>
+        <h1 class="text-muted">{{ trans('errors.app_down', ['appName' => setting('app-name')]) }}</h1>
+        <p>{{ trans('errors.back_soon') }}</p>
     </div>
 
 @stop
\ No newline at end of file
index a5b1f2809ecdb4d7058c39601f3e62c58410c4d7..6c53effae0e1712ea37b238ace006c71ad1ba716 100644 (file)
@@ -1,5 +1,5 @@
 <form action="{{$url}}" method="POST" class="inline">
     {{ csrf_field() }}
     <input type="hidden" name="_method" value="DELETE">
-    <button type="submit" class="button neg">{{ isset($text) ? $text : 'Delete' }}</button>
+    <button type="submit" class="button neg">{{ isset($text) ? $text : trans('common.delete') }}</button>
 </form>
\ No newline at end of file
index 7472fe65ebd1f4cbcbaf35664998ca74ce101bd9..7a1605197b7a6dd5896cd420fc8288e5b3daf686 100644 (file)
@@ -2,31 +2,31 @@
     {!! csrf_field() !!}
     <input type="hidden" name="_method" value="PUT">
 
-    <p>Once enabled, These permissions will take priority over any set role permissions.</p>
+    <p>{{ trans('entities.permissions_intro') }}</p>
 
     <div class="form-group">
-        @include('form/checkbox', ['name' => 'restricted', 'label' => 'Enable custom permissions'])
+        @include('form/checkbox', ['name' => 'restricted', 'label' => trans('entities.permissions_enable')])
     </div>
 
 
     <table class="table">
         <tr>
-            <th>Role</th>
-            <th @if($model->isA('page')) colspan="3" @else colspan="4" @endif>Actions</th>
+            <th>{{ trans('common.role') }}</th>
+            <th @if($model->isA('page')) colspan="3" @else colspan="4" @endif>{{ trans('common.actions') }}</th>
         </tr>
         @foreach($roles as $role)
             <tr>
                 <td>{{ $role->display_name }}</td>
-                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'View', 'action' => 'view'])</td>
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.view'), 'action' => 'view'])</td>
                 @if(!$model->isA('page'))
-                    <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Create', 'action' => 'create'])</td>
+                    <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.create'), 'action' => 'create'])</td>
                 @endif
-                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Update', 'action' => 'update'])</td>
-                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Delete', 'action' => 'delete'])</td>
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.update'), 'action' => 'update'])</td>
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.delete'), 'action' => 'delete'])</td>
             </tr>
         @endforeach
     </table>
 
-    <a href="{{ $model->getUrl() }}" class="button muted">Cancel</a>
-    <button type="submit" class="button pos">Save Permissions</button>
+    <a href="{{ $model->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button type="submit" class="button pos">{{ trans('entities.permissions_save') }}</button>
 </form>
\ No newline at end of file
index 2fb4ac85597cca57cc0f26d6e86bde9a55efb881..0d97a6a4b4434ccb5a11fb203a8309d466c09941 100644 (file)
@@ -5,14 +5,9 @@
     <div class="faded-small toolbar">
         <div class="container">
             <div class="row">
-                <div class="col-sm-4 faded">
+                <div class="col-sm-6 faded">
                     <div class="action-buttons text-left">
-                        <a data-action="expand-entity-list-details" class="text-primary text-button"><i class="zmdi zmdi-wrap-text"></i>Toggle Details</a>
-                    </div>
-                </div>
-                <div class="col-sm-8 faded">
-                    <div class="action-buttons">
-
+                        <a data-action="expand-entity-list-details" class="text-primary text-button"><i class="zmdi zmdi-wrap-text"></i>{{ trans('common.toggle_details') }}</a>
                     </div>
                 </div>
             </div>
             <div class="col-sm-4">
                 <div id="recent-drafts">
                     @if(count($draftPages) > 0)
-                        <h4>My Recent Drafts</h4>
+                        <h4>{{ trans('entities.my_recent_drafts') }}</h4>
                         @include('partials/entity-list', ['entities' => $draftPages, 'style' => 'compact'])
                     @endif
                 </div>
                 @if($signedIn)
-                    <h4>My Recently Viewed</h4>
+                    <h4>{{ trans('entities.my_recently_viewed') }}</h4>
                 @else
-                    <h4>Recent Books</h4>
+                    <h4>{{ trans('entities.books_recent') }}</h4>
                 @endif
                 @include('partials/entity-list', [
                 'entities' => $recents,
                 'style' => 'compact',
-                'emptyText' => $signedIn ? 'You have not viewed any pages' : 'No books have been created'
+                'emptyText' => $signedIn ? trans('entities.no_pages_viewed') : trans('entities.books_empty')
                 ])
             </div>
 
             <div class="col-sm-4">
-                <h4><a class="no-color" href="{{ baseUrl("/pages/recently-created") }}">Recently Created Pages</a></h4>
+                <h4><a class="no-color" href="{{ baseUrl("/pages/recently-created") }}">{{ trans('entities.recently_created_pages') }}</a></h4>
                 <div id="recently-created-pages">
                     @include('partials/entity-list', [
                     'entities' => $recentlyCreatedPages,
                     'style' => 'compact',
-                    'emptyText' => 'No pages have been recently created'
+                    'emptyText' => trans('entities.no_pages_recently_created')
                     ])
                 </div>
 
-                <h4><a class="no-color" href="{{ baseUrl("/pages/recently-updated") }}">Recently Updated Pages</a></h4>
+                <h4><a class="no-color" href="{{ baseUrl("/pages/recently-updated") }}">{{ trans('entities.recently_updated_pages') }}</a></h4>
                 <div id="recently-updated-pages">
                     @include('partials/entity-list', [
                     'entities' => $recentlyUpdatedPages,
                     'style' => 'compact',
-                    'emptyText' => 'No pages have been recently updated'
+                    'emptyText' => trans('entites.no_pages_recently_updated')
                     ])
                 </div>
             </div>
 
             <div class="col-sm-4" id="recent-activity">
-                <h4>Recent Activity</h4>
+                <h4>{{ trans('entities.recent_activity') }}</h4>
                 @include('partials/activity-list', ['activity' => $activity])
             </div>
 
diff --git a/resources/views/pages/_breadcrumbs.blade.php b/resources/views/pages/_breadcrumbs.blade.php
new file mode 100644 (file)
index 0000000..0d2a61a
--- /dev/null
@@ -0,0 +1,12 @@
+<div class="breadcrumbs">
+    <a href="{{ $page->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName() }}</a>
+    @if($page->hasChapter())
+        <span class="sep">&raquo;</span>
+        <a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
+            <i class="zmdi zmdi-collection-bookmark"></i>
+            {{ $page->chapter->getShortName() }}
+        </a>
+    @endif
+    <span class="sep">&raquo;</span>
+    <a href="{{ $page->getUrl() }}" class="text-page text-button"><i class="zmdi zmdi-file"></i>{{ $page->getShortName() }}</a>
+</div>
\ No newline at end of file
index 57cc86054f3837dc70a4ee3159e136260b4f4dcd..f94a614fb2f32201ac9af475be6ccaa9b0f1cd61 100644 (file)
@@ -2,15 +2,25 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    @include('pages._breadcrumbs', ['page' => $page])
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
-        <h1>Delete {{ $page->draft ? 'Draft' : '' }} Page</h1>
-        <p class="text-neg">Are you sure you want to delete this {{ $page->draft ? 'draft' : '' }} page?</p>
+        <h1>{{ $page->draft ? trans('entities.pages_delete_draft') : trans('entities.pages_delete') }}</h1>
+        <p class="text-neg">{{ $page->draft ? trans('entities.pages_delete_draft_confirm'): trans('entities.pages_delete_confirm') }}</p>
 
         <form action="{{ $page->getUrl() }}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="DELETE">
-            <a href="{{ $page->getUrl() }}" class="button primary">Cancel</a>
-            <button type="submit" class="button neg">Confirm</button>
+            <a href="{{ $page->getUrl() }}" class="button primary">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button neg">{{ trans('common.confirm') }}</button>
         </form>
     </div>
 
index e50cc7c5bb2dea098b3d1c2f7f5685e62fd2da30..e1c0a169d6f4661f9a6205091594bd9c2429b287 100644 (file)
@@ -20,7 +20,7 @@
 
     </div>
     
-    @include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
-    @include('partials/entity-selector-popup')
+    @include('components.image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
+    @include('components.entity-selector-popup')
 
 @stop
\ No newline at end of file
index 96f06290e30272b8407924eb0259aff5c3c8c81a..19a6355637c74db5c132a9b21a14529ed2d1c158 100644 (file)
         <div class="col-md-8 col-md-offset-2">
             <div class="page-content">
 
-                @include('pages/page-display')
+                @include('pages.page-display')
 
                 <hr>
 
-                <p class="text-muted small">
-                    Created {{$page->created_at->toDayDateTimeString()}} @if($page->createdBy) by {{$page->createdBy->name}} @endif
-                    <br>
-                    Last Updated {{$page->updated_at->toDayDateTimeString()}} @if($page->updatedBy) by {{$page->updatedBy->name}} @endif
-                </p>
+                @include('partials.entity-meta', ['entity' => $page])
 
             </div>
         </div>
index a6e66a24a13f3e778924634faea57ce4af24fd69..ecf7619b766c29e99ea3ffb503e978cd7fe6a9c2 100644 (file)
@@ -3,22 +3,22 @@
 
     <div class="tabs primary-background-light">
         <span toolbox-toggle><i class="zmdi zmdi-caret-left-circle"></i></span>
-        <span toolbox-tab-button="tags" title="Page Tags" class="active"><i class="zmdi zmdi-tag"></i></span>
+        <span toolbox-tab-button="tags" title="{{ trans('entities.page_tags') }}" class="active"><i class="zmdi zmdi-tag"></i></span>
         @if(userCan('attachment-create-all'))
-            <span toolbox-tab-button="files" title="Attachments"><i class="zmdi zmdi-attachment"></i></span>
+            <span toolbox-tab-button="files" title="{{ trans('entities.attachments') }}"><i class="zmdi zmdi-attachment"></i></span>
         @endif
     </div>
 
     <div toolbox-tab-content="tags" ng-controller="PageTagController" page-id="{{ $page->id or 0 }}">
-        <h4>Page Tags</h4>
+        <h4>{{ trans('entities.page_tags') }}</h4>
         <div class="padded tags">
-            <p class="muted small">Add some tags to better categorise your content. <br> You can assign a value to a tag for more in-depth organisation.</p>
+            <p class="muted small">{!! nl2br(e(trans('entities.tags_explain'))) !!}</p>
             <table class="no-style" tag-autosuggestions style="width: 100%;">
                 <tbody ui-sortable="sortOptions" ng-model="tags" >
                     <tr ng-repeat="tag in tags track by $index">
                         <td width="20" ><i class="handle zmdi zmdi-menu"></i></td>
-                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/names') }}" autosuggest-type="name" class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag"></td>
-                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/values') }}" autosuggest-type="value" class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag Value (Optional)"></td>
+                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/names') }}" autosuggest-type="name" class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="{{ trans('entities.tag') }}"></td>
+                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/values') }}" autosuggest-type="value" class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="{{ trans('entities.tag_value') }}"></td>
                         <td width="10" ng-show="tags.length != 1" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td>
                     </tr>
                 </tbody>
@@ -28,7 +28,7 @@
                 <tr class="unsortable">
                     <td  width="34"></td>
                     <td ng-click="addEmptyTag()">
-                        <button type="button" class="text-button">Add another tag</button>
+                        <button type="button" class="text-button">{{ trans('entities.tags_add') }}</button>
                     </td>
                     <td></td>
                 </tr>
 
     @if(userCan('attachment-create-all'))
         <div toolbox-tab-content="files" ng-controller="PageAttachmentController" page-id="{{ $page->id or 0 }}">
-            <h4>Attachments</h4>
+            <h4>{{ trans('entities.attachments') }}</h4>
             <div class="padded files">
 
                 <div id="file-list" ng-show="!editFile">
-                    <p class="muted small">Upload some files or attach some link to display on your page. These are visible in the page sidebar. <span class="secondary">Changes here are saved instantly.</span></p>
+                    <p class="muted small">{{ trans('entities.attachments_explain') }} <span class="secondary">{{ trans('entities.attachments_explain_instant_save') }}</span></p>
 
                     <div tab-container>
                         <div class="nav-tabs">
-                            <div tab-button="list" class="tab-item">Attached Items</div>
-                            <div tab-button="file" class="tab-item">Upload File</div>
-                            <div tab-button="link" class="tab-item">Attach Link</div>
+                            <div tab-button="list" class="tab-item">{{ trans('entities.attachments_items') }}</div>
+                            <div tab-button="file" class="tab-item">{{ trans('entities.attachments_upload') }}</div>
+                            <div tab-button="link" class="tab-item">{{ trans('entities.attachments_link') }}</div>
                         </div>
                         <div tab-content="list">
                             <table class="file-table" style="width: 100%;">
@@ -59,9 +59,9 @@
                                     <td>
                                         <a ng-href="@{{getFileUrl(file)}}" target="_blank" ng-bind="file.name"></a>
                                         <div ng-if="file.deleting">
-                                            <span class="neg small">Click delete again to confirm you want to delete this attachment.</span>
+                                            <span class="neg small">{{ trans('entities.attachments_delete_confirm') }}</span>
                                             <br>
-                                            <span class="text-primary small" ng-click="file.deleting=false;">Cancel</span>
+                                            <span class="text-primary small" ng-click="file.deleting=false;">{{ trans('common.cancel') }}</span>
                                         </div>
                                     </td>
                                     <td width="10" ng-click="startEdit(file)" class="text-center text-primary" style="padding: 0;"><i class="zmdi zmdi-edit"></i></td>
                                 </tbody>
                             </table>
                             <p class="small muted" ng-if="files.length == 0">
-                                No files have been uploaded.
+                                {{ trans('entities.attachments_no_files') }}
                             </p>
                         </div>
                         <div tab-content="file">
-                            <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
+                            <drop-zone message="{{ trans('entities.attachments_dropzone') }}" upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
                         </div>
                         <div tab-content="link" sub-form="attachLinkSubmit(file)">
-                            <p class="muted small">You can attach a link if you'd prefer not to upload a file. This can be a link to another page or a link to a file in the cloud.</p>
+                            <p class="muted small">{{ trans('entities.attachments_explain_link') }}</p>
                             <div class="form-group">
-                                <label for="attachment-via-link">Link Name</label>
-                                <input type="text" placeholder="Link name" ng-model="file.name">
+                                <label for="attachment-via-link">{{ trans('entities.attachments_link_name') }}</label>
+                                <input type="text" placeholder="{{ trans('entities.attachments_link_name') }}" ng-model="file.name">
                                 <p class="small neg" ng-repeat="error in errors.link.name" ng-bind="error"></p>
                             </div>
                             <div class="form-group">
-                                <label for="attachment-via-link">Link to file</label>
-                                <input type="text" placeholder="Url of site or file" ng-model="file.link">
+                                <label for="attachment-via-link">{{ trans('entities.attachments_link_url') }}</label>
+                                <input type="text" placeholder="{{ trans('entities.attachments_link_url_hint') }}" ng-model="file.link">
                                 <p class="small neg" ng-repeat="error in errors.link.link" ng-bind="error"></p>
                             </div>
-                            <button type="submit" class="button pos">Attach</button>
+                            <button type="submit" class="button pos">{{ trans('entities.attach') }}</button>
 
                         </div>
                     </div>
                 </div>
 
                 <div id="file-edit" ng-if="editFile" sub-form="updateFile(editFile)">
-                    <h5>Edit File</h5>
+                    <h5>{{ trans('entities.attachments_edit_file') }}</h5>
 
                     <div class="form-group">
-                        <label for="attachment-name-edit">File Name</label>
-                        <input type="text" id="attachment-name-edit" placeholder="File name" ng-model="editFile.name">
+                        <label for="attachment-name-edit">{{ trans('entities.attachments_edit_file_name') }}</label>
+                        <input type="text" id="attachment-name-edit" placeholder="{{ trans('entities.attachments_edit_file_name') }}" ng-model="editFile.name">
                         <p class="small neg" ng-repeat="error in errors.edit.name" ng-bind="error"></p>
                     </div>
 
                     <div tab-container="@{{ editFile.external ? 'link' : 'file' }}">
                         <div class="nav-tabs">
-                            <div tab-button="file" class="tab-item">Upload File</div>
-                            <div tab-button="link" class="tab-item">Set Link</div>
+                            <div tab-button="file" class="tab-item">{{ trans('entities.attachments_upload') }}</div>
+                            <div tab-button="link" class="tab-item">{{ trans('entities.attachments_set_link') }}</div>
                         </div>
                         <div tab-content="file">
-                            <drop-zone upload-url="@{{getUploadUrl(editFile)}}" uploaded-to="@{{uploadedTo}}" placeholder="Drop files or click here to upload and overwrite" event-success="uploadSuccessUpdate"></drop-zone>
+                            <drop-zone upload-url="@{{getUploadUrl(editFile)}}" uploaded-to="@{{uploadedTo}}" placeholder="{{ trans('entities.attachments_edit_drop_upload') }}" event-success="uploadSuccessUpdate"></drop-zone>
                             <br>
                         </div>
                         <div tab-content="link">
                             <div class="form-group">
-                                <label for="attachment-link-edit">Link to file</label>
-                                <input type="text" id="attachment-link-edit" placeholder="Attachment link" ng-model="editFile.link">
+                                <label for="attachment-link-edit">{{ trans('entities.attachments_link_url') }}</label>
+                                <input type="text" id="attachment-link-edit" placeholder="{{ trans('entities.attachment_link') }}" ng-model="editFile.link">
                                 <p class="small neg" ng-repeat="error in errors.edit.link" ng-bind="error"></p>
                             </div>
                         </div>
                     </div>
 
-                    <button type="button" class="button" ng-click="cancelEdit()">Back</button>
-                    <button type="submit" class="button pos">Save</button>
+                    <button type="button" class="button" ng-click="cancelEdit()">{{ trans('common.back') }}</button>
+                    <button type="submit" class="button pos">{{ trans('common.save') }}</button>
                 </div>
 
             </div>
index c4baf38f75b352046eb8181b4873c1e624c82169..eb5ebb0bdde4b807928f3de5741270f54d48697f 100644 (file)
@@ -9,8 +9,8 @@
             <div class="row">
                 <div class="col-sm-4 faded">
                     <div class="action-buttons text-left">
-                        <a href="{{ back()->getTargetUrl() }}" class="text-button text-primary"><i class="zmdi zmdi-arrow-left"></i>Back</a>
-                        <a onclick="$('body>header').slideToggle();" class="text-button text-primary"><i class="zmdi zmdi-swap-vertical"></i>Toggle Header</a>
+                        <a href="{{ back()->getTargetUrl() }}" class="text-button text-primary"><i class="zmdi zmdi-arrow-left"></i>{{ trans('common.back') }}</a>
+                        <a onclick="$('body>header').slideToggle();" class="text-button text-primary"><i class="zmdi zmdi-swap-vertical"></i>{{ trans('entities.pages_edit_toggle_header') }}</a>
                     </div>
                 </div>
                 <div class="col-sm-4 faded text-center">
                         <i class="zmdi zmdi-check-circle text-pos draft-notification" ng-class="{visible: draftUpdated}"></i>
                         <ul>
                             <li>
-                                <a ng-click="forceDraftSave()" class="text-pos"><i class="zmdi zmdi-save"></i>Save Draft</a>
+                                <a ng-click="forceDraftSave()" class="text-pos"><i class="zmdi zmdi-save"></i>{{ trans('entities.pages_edit_save_draft') }}</a>
                             </li>
                             <li ng-if="isNewPageDraft">
-                                <a href="{{ $model->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete Draft</a>
+                                <a href="{{ $model->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>{{ trans('entities.pages_edit_delete_draft') }}</a>
                             </li>
                             <li>
-                                <a type="button" ng-if="isUpdateDraft" ng-click="discardDraft()" class="text-neg"><i class="zmdi zmdi-close-circle"></i>Discard Draft</a>
+                                <a type="button" ng-if="isUpdateDraft" ng-click="discardDraft()" class="text-neg"><i class="zmdi zmdi-close-circle"></i>{{ trans('entities.pages_edit_discard_draft') }}</a>
                             </li>
                         </ul>
                     </div>
                 <div class="col-sm-4 faded">
                     <div class="action-buttons" ng-cloak>
                         <div dropdown class="dropdown-container">
-                            <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-edit"></i> @{{(changeSummary | limitTo:16) + (changeSummary.length>16?'...':'') || 'Set Changelog'}}</a>
+                            <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-edit"></i> <span ng-bind="(changeSummary | limitTo:16) + (changeSummary.length>16?'...':'') || '{{ trans('entities.pages_edit_set_changelog') }}'"></span></a>
                             <ul class="wide">
                                 <li class="padded">
-                                    <p class="text-muted">Enter a brief description of the changes you've made</p>
-                                    <input name="summary" id="summary-input" type="text" placeholder="Enter Changelog" ng-model="changeSummary" />
+                                    <p class="text-muted">{{ trans('entities.pages_edit_enter_changelog_desc') }}</p>
+                                    <input name="summary" id="summary-input" type="text" placeholder="{{ trans('entities.pages_edit_enter_changelog') }}" ng-model="changeSummary" />
                                 </li>
                             </ul>
                         </div>
 
-                        <button type="submit" id="save-button" class="text-button text-pos"><i class="zmdi zmdi-floppy"></i>Save Page</button>
+                        <button type="submit" id="save-button" class="text-button text-pos"><i class="zmdi zmdi-floppy"></i>{{ trans('entities.pages_save') }}</button>
                     </div>
                 </div>
             </div>
@@ -53,7 +53,7 @@
     {{--Title input--}}
     <div class="title-input page-title clearfix" ng-non-bindable>
         <div class="input">
-            @include('form/text', ['name' => 'name', 'placeholder' => 'Page Title'])
+            @include('form/text', ['name' => 'name', 'placeholder' => trans('entities.pages_title')])
         </div>
     </div>
 
 
                 <div class="markdown-editor-wrap">
                     <div class="editor-toolbar">
-                        <span class="float left">Editor</span>
+                        <span class="float left">{{ trans('entities.pages_md_editor') }}</span>
                         <div class="float right buttons">
-                            <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>Insert Image</button>
+                            <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>{{ trans('entities.pages_md_insert_image') }}</button>
                             &nbsp;|&nbsp;
-                            <button class="text-button" type="button" data-action="insertEntityLink"><i class="zmdi zmdi-link"></i>Insert Entity Link</button>
+                            <button class="text-button" type="button" data-action="insertEntityLink"><i class="zmdi zmdi-link"></i>{{ trans('entities.pages_md_insert_link') }}</button>
                         </div>
                     </div>
 
                     <div markdown-input md-change="editorChange" md-model="editContent" class="flex flex-fill">
                         <textarea ng-non-bindable id="markdown-editor-input"  name="markdown" rows="5"
-                                  @if($errors->has('markdown')) class="neg" @endif>@if(isset($model) || old('markdown')){{htmlspecialchars( old('markdown') ? old('markdown') : ($model->markdown === '' ? $model->html : $model->markdown))}}@endif</textarea>
+                            @if($errors->has('markdown')) class="neg" @endif>@if(isset($model) || old('markdown')){{htmlspecialchars( old('markdown') ? old('markdown') : ($model->markdown === '' ? $model->html : $model->markdown))}}@endif</textarea>
                     </div>
 
                 </div>
 
                 <div class="markdown-editor-wrap">
                     <div class="editor-toolbar">
-                        <div class="">Preview</div>
+                        <div class="">{{ trans('entities.pages_md_preview') }}</div>
                     </div>
                     <div class="markdown-display">
                         <div class="page-content" ng-bind-html="displayContent"></div>
index 00d9f55605d3d97f15e9c8186ae1a951c3768b26..10e16cb97e3fd80f1aa3f042ae38e4f888a88e0a 100644 (file)
@@ -3,19 +3,19 @@
 @section('content')
 
     <div class="container small" ng-non-bindable>
-        <h1>Create Page</h1>
+        <h1>{{ trans('entities.pages_new') }}</h1>
         <form action="{{  $parent->getUrl('/page/create/guest') }}" method="POST">
 
             {!! csrf_field() !!}
 
             <div class="form-group title-input">
-                <label for="name">Page Name</label>
+                <label for="name">{{ trans('entities.pages_name') }}</label>
                 @include('form/text', ['name' => 'name'])
             </div>
 
             <div class="form-group">
-                <a href="{{ $parent->getUrl() }}" class="button muted">Cancel</a>
-                <button type="submit" class="button pos">Continue</button>
+                <a href="{{ $parent->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+                <button type="submit" class="button pos">{{ trans('common.continue') }}</button>
             </div>
 
         </form>
index 7aa5d7933fb6661968fdb38aa12e0f1fea2259fe..70b309e7d7446b91b4996c0d104a89b706d6078c 100644 (file)
@@ -12,8 +12,7 @@
     @if(isset($style) && $style === 'detailed')
         <div class="row meta text-muted text-small">
             <div class="col-md-6">
-                Created {{$page->created_at->diffForHumans()}} @if($page->createdBy)by {{$page->createdBy->name}}@endif <br>
-                Last updated {{ $page->updated_at->diffForHumans() }} @if($page->updatedBy)by {{$page->updatedBy->name}} @endif
+                @include('partials.entity-meta', ['entity' => $page])
             </div>
             <div class="col-md-6">
                 <a class="text-book" href="{{ $page->book->getUrl() }}"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName(30) }}</a>
@@ -21,7 +20,7 @@
                 @if($page->chapter)
                     <a class="text-chapter" href="{{ $page->chapter->getUrl() }}"><i class="zmdi zmdi-collection-bookmark"></i>{{ $page->chapter->getShortName(30) }}</a>
                 @else
-                    <i class="zmdi zmdi-collection-bookmark"></i> Page is not in a chapter
+                    <i class="zmdi zmdi-collection-bookmark"></i> {{ trans('entities.pages_not_in_chapter') }}
                 @endif
             </div>
         </div>
index d0fae60ca4a466fc46bca89350314f02836ce891..a9b6d69d7b4454b012b24856afe322a78abd4182 100644 (file)
@@ -6,34 +6,23 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
-                        @if($page->hasChapter())
-                            <span class="sep">&raquo;</span>
-                            <a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
-                                <i class="zmdi zmdi-collection-bookmark"></i>
-                                {{ $page->chapter->getShortName() }}
-                            </a>
-                        @endif
-                        <span class="sep">&raquo;</span>
-                        <a href="{{ $page->getUrl() }}" class="text-page text-button"><i class="zmdi zmdi-file-text"></i>{{ $page->getShortName() }}</a>
-                    </div>
+                    @include('pages._breadcrumbs', ['page' => $page])
                 </div>
             </div>
         </div>
     </div>
 
     <div class="container">
-        <h1>Move Page <small class="subheader">{{$page->name}}</small></h1>
+        <h1>{{ trans('entities.pages_move') }}</h1>
 
         <form action="{{ $page->getUrl('/move') }}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="PUT">
 
-            @include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book,chapter'])
+            @include('components.entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book,chapter'])
 
-            <a href="{{ $page->getUrl() }}" class="button muted">Cancel</a>
-            <button type="submit" class="button pos">Move Page</button>
+            <a href="{{ $page->getUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button pos">{{ trans('entities.pages_move') }}</button>
         </form>
     </div>
 
index 5c9fd5eea8707fad42b2ea5b982f3b78266a5f1c..7e43c5e1a6e0a0a2ad314cb6a146d2b8f81d67a2 100644 (file)
@@ -36,6 +36,5 @@
             max-width: none;
             display: none;
         }
-
     </style>
 @stop
\ No newline at end of file
index bd88919dfa83c23571e723dca0bcdd1d74ef99c9..cfef2ed21a8f2cd994829a8f179f4ab579a2e281 100644 (file)
@@ -6,26 +6,15 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $page->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName() }}</a>
-                        @if($page->hasChapter())
-                            <span class="sep">&raquo;</span>
-                            <a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
-                                <i class="zmdi zmdi-collection-bookmark"></i>
-                                {{ $page->chapter->getShortName() }}
-                            </a>
-                        @endif
-                        <span class="sep">&raquo;</span>
-                        <a href="{{ $page->getUrl() }}" class="text-page text-button"><i class="zmdi zmdi-file"></i>{{ $page->getShortName() }}</a>
-                    </div>
+                    @include('pages._breadcrumbs', ['page' => $page])
                 </div>
             </div>
         </div>
     </div>
 
     <div class="container" ng-non-bindable>
-        <h1>Page Permissions</h1>
-        @include('form/restriction-form', ['model' => $page])
+        <h1>{{ trans('entities.pages_permissions') }}</h1>
+        @include('form.restriction-form', ['model' => $page])
     </div>
 
 @stop
index bc054ef83fcde5f646f13d0bf5169a81898ead2b..fe0dd9511a72839336a201f580fc51a99e77c449 100644 (file)
@@ -7,14 +7,12 @@
         <div class="row">
             <div class="col-md-9">
                 <div class="page-content anim fadeIn">
-                    @include('pages/page-display')
+                    @include('pages.page-display')
                 </div>
             </div>
         </div>
     </div>
 
 
-
-    @include('partials/highlight')
-
+    @include('partials.highlight')
 @stop
index 720e34fea4efd76c4187e4f5b37b29e9b65e3a57..3549f5f05cea7914173c644b846f69a830350218 100644 (file)
@@ -6,37 +6,24 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-12 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $page->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName() }}</a>
-                        @if($page->hasChapter())
-                            <span class="sep">&raquo;</span>
-                            <a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
-                                <i class="zmdi zmdi-collection-bookmark"></i>
-                                {{ $page->chapter->getShortName() }}
-                            </a>
-                        @endif
-                        <span class="sep">&raquo;</span>
-                        <a href="{{ $page->getUrl() }}" class="text-page text-button"><i class="zmdi zmdi-file"></i>{{ $page->getShortName() }}</a>
-                    </div>
+                    @include('pages._breadcrumbs', ['page' => $page])
                 </div>
             </div>
         </div>
     </div>
 
-
-
     <div class="container" ng-non-bindable>
-        <h1>Page Revisions <span class="subheader">For "{{ $page->name }}"</span></h1>
+        <h1>{{ trans('entities.pages_revisions') }}</h1>
 
         @if(count($page->revisions) > 0)
 
             <table class="table">
                 <tr>
-                    <th width="23%">Name</th>
-                    <th colspan="2" width="8%">Created By</th>
-                    <th width="15%">Revision Date</th>
-                    <th width="25%">Changelog</th>
-                    <th width="20%">Actions</th>
+                    <th width="23%">{{ trans('entities.pages_name') }}</th>
+                    <th colspan="2" width="8%">{{ trans('entities.pages_revisions_created_by') }}</th>
+                    <th width="15%">{{ trans('entities.pages_revisions_date') }}</th>
+                    <th width="25%">{{ trans('entities.pages_revisions_changelog') }}</th>
+                    <th width="20%">{{ trans('common.actions') }}</th>
                 </tr>
                 @foreach($page->revisions as $index => $revision)
                     <tr>
                                 <img class="avatar" src="{{ $revision->createdBy->getAvatar(30) }}" alt="{{ $revision->createdBy->name }}">
                             @endif
                         </td>
-                        <td> @if($revision->createdBy) {{ $revision->createdBy->name }} @else Deleted User @endif</td>
+                        <td> @if($revision->createdBy) {{ $revision->createdBy->name }} @else {{ trans('common.deleted_user') }} @endif</td>
                         <td><small>{{ $revision->created_at->format('jS F, Y H:i:s') }} <br> ({{ $revision->created_at->diffForHumans() }})</small></td>
                         <td>{{ $revision->summary }}</td>
                         <td>
-                            <a href="{{ $revision->getUrl('changes') }}" target="_blank">Changes</a>
+                            <a href="{{ $revision->getUrl('changes') }}" target="_blank">{{ trans('entities.pages_revisions_changes') }}</a>
                             <span class="text-muted">&nbsp;|&nbsp;</span>
 
                             @if ($index === 0)
-                                <a target="_blank" href="{{ $page->getUrl() }}"><i>Current Version</i></a>
+                                <a target="_blank" href="{{ $page->getUrl() }}"><i>{{ trans('entities.pages_revisions_current') }}</i></a>
                             @else
-                                <a href="{{ $revision->getUrl() }}" target="_blank">Preview</a>
+                                <a href="{{ $revision->getUrl() }}" target="_blank">{{ trans('entities.pages_revisions_preview') }}</a>
                                 <span class="text-muted">&nbsp;|&nbsp;</span>
-                                <a href="{{ $revision->getUrl('restore') }}" target="_blank">Restore</a>
+                                <a href="{{ $revision->getUrl('restore') }}" target="_blank">{{ trans('entities.pages_revisions_restore') }}</a>
                             @endif
                         </td>
                     </tr>
@@ -66,7 +53,7 @@
             </table>
 
         @else
-            <p>This page has no revisions.</p>
+            <p>{{ trans('entities.pages_revisions_none') }}</p>
         @endif
 
     </div>
index 50c6f5d2c2eb4da7bdf90d9649a756551546971c..a734b1b9526bb75525fbc0d71e5c148c71637824 100644 (file)
@@ -6,43 +6,34 @@
         <div class="container">
             <div class="row">
                 <div class="col-sm-6 faded">
-                    <div class="breadcrumbs">
-                        <a href="{{ $book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->getShortName() }}</a>
-                        @if($page->hasChapter())
-                            <span class="sep">&raquo;</span>
-                            <a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
-                                <i class="zmdi zmdi-collection-bookmark"></i>
-                                {{ $page->chapter->getShortName() }}
-                            </a>
-                        @endif
-                    </div>
+                    @include('pages._breadcrumbs', ['page' => $page])
                 </div>
                 <div class="col-sm-6 faded">
                     <div class="action-buttons">
                         <span dropdown class="dropdown-container">
-                            <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>Export</div>
+                            <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.pages_export') }}</div>
                             <ul class="wide">
-                                <li><a href="{{ $page->getUrl('/export/html') }}" target="_blank">Contained Web File <span class="text-muted float right">.html</span></a></li>
-                                <li><a href="{{ $page->getUrl('/export/pdf') }}" target="_blank">PDF File <span class="text-muted float right">.pdf</span></a></li>
-                                <li><a href="{{ $page->getUrl('/export/plaintext') }}" target="_blank">Plain Text File <span class="text-muted float right">.txt</span></a></li>
+                                <li><a href="{{ $page->getUrl('/export/html') }}" target="_blank">{{ trans('entities.pages_export_html') }} <span class="text-muted float right">.html</span></a></li>
+                                <li><a href="{{ $page->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.pages_export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
+                                <li><a href="{{ $page->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.pages_export_text') }} <span class="text-muted float right">.txt</span></a></li>
                             </ul>
                         </span>
                         @if(userCan('page-update', $page))
-                            <a href="{{ $page->getUrl('/edit') }}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a>
+                            <a href="{{ $page->getUrl('/edit') }}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>{{ trans('common.edit') }}</a>
                         @endif
                         @if(userCan('page-update', $page) || userCan('restrictions-manage', $page) || userCan('page-delete', $page))
                             <div dropdown class="dropdown-container">
                                 <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-more-vert"></i></a>
                                 <ul>
                                     @if(userCan('page-update', $page))
-                                        <li><a href="{{ $page->getUrl('/move') }}" class="text-primary" ><i class="zmdi zmdi-folder"></i>Move</a></li>
-                                        <li><a href="{{ $page->getUrl('/revisions') }}" class="text-primary"><i class="zmdi zmdi-replay"></i>Revisions</a></li>
+                                        <li><a href="{{ $page->getUrl('/move') }}" class="text-primary" ><i class="zmdi zmdi-folder"></i>{{ trans('common.move') }}</a></li>
+                                        <li><a href="{{ $page->getUrl('/revisions') }}" class="text-primary"><i class="zmdi zmdi-replay"></i>{{ trans('entities.revisions') }}</a></li>
                                     @endif
                                     @if(userCan('restrictions-manage', $page))
-                                        <li><a href="{{ $page->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>Permissions</a></li>
+                                        <li><a href="{{ $page->getUrl('/permissions') }}" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.permissions') }}</a></li>
                                     @endif
                                     @if(userCan('page-delete', $page))
-                                        <li><a href="{{ $page->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a></li>
+                                        <li><a href="{{ $page->getUrl('/delete') }}" class="text-neg"><i class="zmdi zmdi-delete"></i>{{ trans('common.delete') }}</a></li>
                                     @endif
                                 </ul>
                             </div>
@@ -64,7 +55,7 @@
                         <div class="pointer anim">
                             <i class="zmdi zmdi-link"></i>
                             <input readonly="readonly" type="text" placeholder="url">
-                            <button class="button icon" title="Copy Link" data-clipboard-text=""><i class="zmdi zmdi-copy"></i></button>
+                            <button class="button icon" title="{{ trans('entities.pages_copy_link') }}" data-clipboard-text=""><i class="zmdi zmdi-copy"></i></button>
                         </div>
                     </div>
 
 
                     <hr>
 
-                    <p class="text-muted small">
-                        Created {{ $page->created_at->diffForHumans() }} @if($page->createdBy) by <a href="{{ $page->createdBy->getProfileUrl() }}">{{$page->createdBy->name}}</a> @endif
-                        <br>
-                        Last Updated {{ $page->updated_at->diffForHumans() }} @if($page->updatedBy) by <a href="{{ $page->updatedBy->getProfileUrl() }}">{{$page->updatedBy->name}}</a> @endif
-                    </p>
+                    @include('partials.entity-meta', ['entity' => $page])
 
                 </div>
             </div>
 
                         @if($book->restricted)
                             @if(userCan('restrictions-manage', $book))
-                                <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Book Permissions Active</a>
+                                <a href="{{ $book->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}</a>
                             @else
-                                <i class="zmdi zmdi-lock-outline"></i>Book Permissions Active
+                                <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.books_permissions_active') }}
                             @endif
                             <br>
                         @endif
 
                         @if($page->chapter && $page->chapter->restricted)
                             @if(userCan('restrictions-manage', $page->chapter))
-                                <a href="{{ $page->chapter->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Chapter Permissions Active</a>
+                                <a href="{{ $page->chapter->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.chapters_permissions_active') }}</a>
                             @else
-                                <i class="zmdi zmdi-lock-outline"></i>Chapter Permissions Active
+                                <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.chapters_permissions_active') }}
                             @endif
                             <br>
                         @endif
 
                         @if($page->restricted)
                             @if(userCan('restrictions-manage', $page))
-                                <a href="{{ $page->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>Page Permissions Active</a>
+                                <a href="{{ $page->getUrl('/permissions') }}"><i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.pages_permissions_active') }}</a>
                             @else
-                                <i class="zmdi zmdi-lock-outline"></i>Page Permissions Active
+                                <i class="zmdi zmdi-lock-outline"></i>{{ trans('entities.pages_permissions_active') }}
                             @endif
                             <br>
                         @endif
index 5309cb7748aa452f0651a7a03ae0332100f78cdf..87eebed493a038b35dfe67f2be9f97ccf2c7d0f7 100644 (file)
     @endif
 
     @if (isset($page) && $page->attachments->count() > 0)
-        <h6 class="text-muted">Attachments</h6>
+        <h6 class="text-muted">{{ trans('entities.pages_attachments') }}</h6>
         @foreach($page->attachments as $attachment)
             <div class="attachment">
-                <a href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif><i class="zmdi zmdi-{{ $attachment->external ? 'open-in-new' : 'file' }}"></i> {{ $attachment->name }}</a>
+                <a href="{{ $attachment->getUrl() }}" @if($attachment->external) target="_blank" @endif><i class="zmdi zmdi-{{ $attachment->external ? 'open-in-new' : 'file' }}"></i>{{ $attachment->name }}</a>
             </div>
         @endforeach
     @endif
 
     @if (isset($pageNav) && $pageNav)
-        <h6 class="text-muted">Page Navigation</h6>
+        <h6 class="text-muted">{{ trans('entities.pages_navigation') }}</h6>
         <div class="sidebar-page-nav menu">
             @foreach($pageNav as $navItem)
                 <li class="page-nav-item {{ $navItem['nodeName'] }}">
@@ -37,7 +37,7 @@
         </div>
     @endif
 
-    <h6 class="text-muted">Book Navigation</h6>
+    <h6 class="text-muted">{{ trans('entities.books_navigation') }}</h6>
     <ul class="sidebar-page-list menu">
         <li class="book-header"><a href="{{ $book->getUrl() }}" class="book {{ $current->matches($book)? 'selected' : '' }}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></li>
 
@@ -50,7 +50,7 @@
 
                 @if($bookChild->isA('chapter') && count($bookChild->pages) > 0)
                     <p class="text-muted chapter-toggle @if($bookChild->matchesOrContains($current)) open @endif">
-                        <i class="zmdi zmdi-caret-right"></i> <i class="zmdi zmdi-file-text"></i> <span>{{ count($bookChild->pages) }} Pages</span>
+                        <i class="zmdi zmdi-caret-right"></i> <i class="zmdi zmdi-file-text"></i> <span>{{ trans('entities.x_pages', ['count' => $bookChild->pages->count()]) }}</span>
                     </p>
                     <ul class="menu sub-menu inset-list @if($bookChild->matchesOrContains($current)) open @endif">
                         @foreach($bookChild->pages as $childPage)
diff --git a/resources/views/partials/_header-dropdown.blade.php b/resources/views/partials/_header-dropdown.blade.php
new file mode 100644 (file)
index 0000000..1c839c9
--- /dev/null
@@ -0,0 +1,17 @@
+<div class="dropdown-container" dropdown>
+    <span class="user-name" dropdown-toggle>
+        <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
+        <span class="name" ng-non-bindable>{{ $currentUser->getShortName(9) }}</span> <i class="zmdi zmdi-caret-down"></i>
+    </span>
+    <ul>
+        <li>
+            <a href="{{ baseUrl("/user/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-account zmdi-hc-fw zmdi-hc-lg"></i>{{ trans('common.view_profile') }}</a>
+        </li>
+        <li>
+            <a href="{{ baseUrl("/settings/users/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-edit zmdi-hc-fw zmdi-hc-lg"></i>{{ trans('common.edit_profile') }}</a>
+        </li>
+        <li>
+            <a href="{{ baseUrl('/logout') }}" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-fw zmdi-hc-lg"></i>{{ trans('auth.logout') }}</a>
+        </li>
+    </ul>
+</div>
\ No newline at end of file
index c45ca6c7a8252dc253174770a7137099715b4355..3f162e0bd87f283029bc603f1bb1788b8e2ba1bb 100644 (file)
@@ -11,7 +11,7 @@
     @if($activity->user)
         <a href="{{ $activity->user->getProfileUrl() }}">{{ $activity->user->name }}</a>
     @else
-        A deleted user
+        {{ trans('common.deleted_user') }}
     @endif
 
     {{ $activity->getText() }}
index de72f5051e4644e4af7a0f75eff8782b7ebf4547..0dc38091e6161e940ed6ec5bf3273489661bf0f8 100644 (file)
@@ -8,5 +8,5 @@
         @endforeach
     </div>
 @else
-    <p class="text-muted">No activity to show</p>
+    <p class="text-muted">{{ trans('common.no_activity') }}</p>
 @endif
\ No newline at end of file
index 885cc2729c9c1a2386fe65e69a89c37a14be4ee8..62bcc881fc3206f005f3bdad614cdf87e4235aa1 100644 (file)
@@ -1,4 +1,4 @@
-<style>
+<style id="custom-styles" data-color="{{ setting('app-color') }}" data-color-light="{{ setting('app-color-light') }}">
     header, #back-to-top, .primary-background {
         background-color: {{ setting('app-color') }} !important;
     }
index 412d3be8f00ca981d1c36862a210c25693253070..95ebfcd4f2f3970730699009a7f1687cf3489260 100644 (file)
@@ -17,7 +17,7 @@
         @endforeach
     @else
         <p class="text-muted empty-text">
-            {{ $emptyText or 'No items available' }}
+            {{ $emptyText or trans('common.no_items') }}
         </p>
     @endif
 </div>
\ No newline at end of file
diff --git a/resources/views/partials/entity-meta.blade.php b/resources/views/partials/entity-meta.blade.php
new file mode 100644 (file)
index 0000000..2a74274
--- /dev/null
@@ -0,0 +1,13 @@
+<p class="text-muted small">
+    @if ($entity->createdBy)
+        {!! trans('entities.meta_created_name', ['timeLength' => $entity->created_at->diffForHumans(), 'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".htmlentities($entity->createdBy->name). "</a>"]) !!}
+    @else
+        {{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}
+    @endif
+    <br>
+    @if ($entity->updatedBy)
+        {!! trans('entities.meta_updated_name', ['timeLength' => $entity->updated_at->diffForHumans(), 'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".htmlentities($entity->updatedBy->name). "</a>"]) !!}
+    @else
+        {{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}
+    @endif
+</p>
\ No newline at end of file
index 16aebe2bb74fcede0efea22af753c41ec920b46b..05cf043fd69a4a9855d21e32b53b3fb645849b73 100644 (file)
@@ -25,7 +25,7 @@
 </head>
 <body class="@yield('body-class')" ng-app="bookStack">
 
-@include('partials/notifications')
+@include('partials.notifications')
 
 <header id="header">
     <div class="container">
                         @yield('header-buttons')
                     </div>
                     @if(isset($signedIn) && $signedIn)
-                        <div class="dropdown-container" dropdown>
-                            <span class="user-name" dropdown-toggle>
-                                <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
-                                <span class="name" ng-non-bindable>{{ $currentUser->getShortName(9) }}</span> <i class="zmdi zmdi-caret-down"></i>
-                            </span>
-                            <ul>
-                                <li>
-                                    <a href="{{ baseUrl("/user/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-account zmdi-hc-fw zmdi-hc-lg"></i>View Profile</a>
-                                </li>
-                                <li>
-                                    <a href="{{ baseUrl("/settings/users/{$currentUser->id}") }}" class="text-primary"><i class="zmdi zmdi-edit zmdi-hc-fw zmdi-hc-lg"></i>Edit Profile</a>
-                                </li>
-                                <li>
-                                    <a href="{{ baseUrl('/logout') }}" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-fw zmdi-hc-lg"></i>Logout</a>
-                                </li>
-                            </ul>
-                        </div>
+                        @include('partials._header-dropdown', ['currentUser' => $currentUser])
                     @endif
                 </div>
             </div>
index fcfb2c902472ae627c69250f33fb44ba86b03bd8..d4053752f4dee40f167a6c57a9f6c0b5b7a198f6 100644 (file)
@@ -2,49 +2,55 @@
 
 @section('content')
 
-    <div class="container anim fadeIn" ng-non-bindable>
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    <div class="breadcrumbs">
+                        <a href="{{ baseUrl("/search/all?term={$searchTerm}") }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ $searchTerm }}</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
 
-        <h1>Search Results&nbsp;&nbsp;&nbsp; <span class="text-muted">{{ $searchTerm }}</span></h1>
 
-        <p>
+    <div class="container" ng-non-bindable>
 
+        <h1>{{ trans('entities.search_results') }}</h1>
+
+        <p>
             @if(count($pages) > 0)
-                <a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="text-page"><i class="zmdi zmdi-file-text"></i>View all matched pages</a>
+                <a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.search_view_pages') }}</a>
             @endif
 
-
             @if(count($chapters) > 0)
                 &nbsp; &nbsp;&nbsp;
-                <a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>View all matched chapters</a>
+                <a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>{{ trans('entities.search_view_chapters') }}</a>
             @endif
 
             @if(count($books) > 0)
                 &nbsp; &nbsp;&nbsp;
-                <a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="text-book"><i class="zmdi zmdi-book"></i>View all matched books</a>
+                <a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.search_view_books') }}</a>
             @endif
         </p>
-        <div class="row">
 
+        <div class="row">
             <div class="col-md-6">
-                <h3><a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="no-color">Matching Pages</a></h3>
+                <h3><a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="no-color">{{ trans('entities.pages') }}</a></h3>
                 @include('partials/entity-list', ['entities' => $pages, 'style' => 'detailed'])
             </div>
-
             <div class="col-md-5 col-md-offset-1">
-
                 @if(count($books) > 0)
-                    <h3><a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="no-color">Matching Books</a></h3>
+                    <h3><a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="no-color">{{ trans('entities.books') }}</a></h3>
                     @include('partials/entity-list', ['entities' => $books])
                 @endif
 
                 @if(count($chapters) > 0)
-                    <h3><a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="no-color">Matching Chapters</a></h3>
+                    <h3><a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="no-color">{{ trans('entities.chapters') }}</a></h3>
                     @include('partials/entity-list', ['entities' => $chapters])
                 @endif
-
             </div>
-
-
         </div>
 
 
index 5af2c4d063c74104f86ac6cbd6afec486b6a52ab..0b9119cd51584bad7dd1061621051b9ea430655c 100644 (file)
@@ -7,7 +7,7 @@
             </div>
         @endforeach
     @else
-        <p class="text-muted">No pages matched this search</p>
+        <p class="text-muted">{{ trans('entities.search_no_pages') }}</p>
     @endif
 </div>
 
index 97d5e4da71de4bf9e869f23535de2e8ada4e586a..93f2633aac12a73772fc3441f91eb56ebaf7c52f 100644 (file)
@@ -16,7 +16,7 @@
         @endforeach
     @else
         <p class="text-muted">
-            No items available
+            {{ trans('common.no_items') }}
         </p>
     @endif
 </div>
\ No newline at end of file
index dd9c6a5090d740923817f241d831f27b7f456f8a..4e743f6bdc4ba7b9815d9308781d59a48d7738f0 100644 (file)
@@ -2,17 +2,27 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    <div class="breadcrumbs">
+                        <a href="{{ baseUrl("/search/all?term={$searchTerm}") }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ $searchTerm }}</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container">
         <div class="row">
 
             <div class="col-sm-7">
-                <h1>{{ $title }} <small>{{ $searchTerm }}</small></h1>
+                <h1>{{ $title }}</h1>
                 @include('partials.entity-list', ['entities' => $entities, 'style' => 'detailed'])
                 {!! $entities->links() !!}
             </div>
 
-            <div class="col-sm-4 col-sm-offset-1"></div>
-
         </div>
     </div>
 @stop
\ No newline at end of file
index ac25eb3b55e8a40bc33f885fb86cf5fcef16947c..c736bc24eb9520fce4089c51f2c5610d5c6c761f 100644 (file)
@@ -8,10 +8,10 @@
 
     <h1>{{ trans('settings.settings') }}</h1>
 
-    <form action="{{ baseUrl("/settings") }}" method="POST" ng-cloak>
+    <form action="{{ baseUrl("/settings") }}" method="POST">
         {!! csrf_field() !!}
 
-        <h3>App Settings</h3>
+        <h3>{{ trans('settings.app_settings') }}</h3>
 
         <div class="row">
 
                 </div>
                 <div class="form-group">
                     <label>{{ trans('settings.app_name_header') }}</label>
-                    <div toggle-switch name="setting-app-name-header" value="{{ setting('app-name-header') }}"></div>
+                    @include('components.toggle-switch', ['name' => 'setting-app-name-header', 'value' => setting('app-name-header')])
                 </div>
                 <div class="form-group">
                     <label for="setting-app-public">{{ trans('settings.app_public_viewing') }}</label>
-                    <div toggle-switch name="setting-app-public" value="{{ setting('app-public') }}"></div>
+                    @include('components.toggle-switch', ['name' => 'setting-app-public', 'value' => setting('app-public')])
                 </div>
                 <div class="form-group">
                     <label>{{ trans('settings.app_secure_images') }}</label>
                     <p class="small">{{ trans('settings.app_secure_images_desc') }}</p>
-                    <div toggle-switch name="setting-app-secure-images" value="{{ setting('app-secure-images') }}"></div>
+                    @include('components.toggle-switch', ['name' => 'setting-app-secure-images', 'value' => setting('app-secure-images')])
                 </div>
                 <div class="form-group">
                     <label for="setting-app-editor">{{ trans('settings.app_editor') }}</label>
                 <div class="form-group" id="logo-control">
                     <label for="setting-app-logo">{{ trans('settings.app_logo') }}</label>
                     <p class="small">{!! trans('settings.app_logo_desc') !!}</p>
-                    <image-picker resize-height="43" show-remove="true" resize-width="200" current-image="{{ setting('app-logo', '') }}" default-image="{{ baseUrl('/logo.png') }}" name="setting-app-logo" image-class="logo-image"></image-picker>
+
+                    @include('components.image-picker', [
+                        'resizeHeight' => '43',
+                        'resizeWidth' => '200',
+                        'showRemove' => true,
+                        'defaultImage' => baseUrl('/logo.png'),
+                        'currentImage' => setting('app-logo'),
+                        'name' => 'setting-app-logo',
+                        'imageClass' => 'logo-image',
+                        'currentId' => false
+                    ])
+
                 </div>
                 <div class="form-group" id="color-control">
                     <label for="setting-app-color">{{ trans('settings.app_primary_color') }}</label>
@@ -74,7 +85,7 @@
             <div class="col-md-6">
                 <div class="form-group">
                     <label for="setting-registration-enabled">{{ trans('settings.reg_allow') }}</label>
-                    <div toggle-switch name="setting-registration-enabled" value="{{ setting('registration-enabled') }}"></div>
+                    @include('components.toggle-switch', ['name' => 'setting-registration-enabled', 'value' => setting('registration-enabled')])
                 </div>
                 <div class="form-group">
                     <label for="setting-registration-role">{{ trans('settings.reg_default_role') }}</label>
                 <div class="form-group">
                     <label for="setting-registration-confirmation">{{ trans('settings.reg_confirm_email') }}</label>
                     <p class="small">{{ trans('settings.reg_confirm_email_desc') }}</p>
-                    <div toggle-switch name="setting-registration-confirmation" value="{{ setting('registration-confirmation') }}"></div>
+                    @include('components.toggle-switch', ['name' => 'setting-registration-confirmation', 'value' => setting('registration-confirmation')])
                 </div>
             </div>
             <div class="col-md-6">
 
 </div>
 
-@include('partials/image-manager', ['imageType' => 'system'])
+@include('components.image-manager', ['imageType' => 'system'])
 
 @stop
 
                 var isEmpty = $.trim($elm.val()).length === 0;
                 if (!isEmpty) $elm.val(hexVal);
                 $('#setting-app-color-light').val(isEmpty ? '' : rgbLightVal);
-                // Set page elements to provide preview
-                $('#header, .image-picker .button').attr('style', 'background-color:'+ hexVal+'!important;');
-                $('.faded-small').css('background-color', rgbLightVal);
-                $('.setting-nav a.selected').css('border-bottom-color', hexVal  + '!important');
+
+                var customStyles = document.getElementById('custom-styles');
+                var oldColor = customStyles.getAttribute('data-color');
+                var oldColorLight = customStyles.getAttribute('data-color-light');
+
+                customStyles.innerHTML = customStyles.innerHTML.split(oldColor).join(hexVal);
+                customStyles.innerHTML = customStyles.innerHTML.split(oldColorLight).join(rgbLightVal);
+
+                customStyles.setAttribute('data-color', hexVal);
+                customStyles.setAttribute('data-color-light', rgbLightVal);
             }
         });
     </script>
index f4526b4c8b450f8771fb10dbd2640a6613b09b82..15000b1cf81578dd8f16fa7bebb6f455fed925b6 100644 (file)
@@ -4,13 +4,13 @@
         <div class="row">
             <div class="col-md-12 setting-nav nav-tabs">
                 @if($currentUser->can('settings-manage'))
-                    <a href="{{ baseUrl('/settings') }}" @if($selected == 'settings') class="selected text-button" @endif><i class="zmdi zmdi-settings"></i>Settings</a>
+                    <a href="{{ baseUrl('/settings') }}" @if($selected == 'settings') class="selected text-button" @endif><i class="zmdi zmdi-settings"></i>{{ trans('settings.settings') }}</a>
                 @endif
                 @if($currentUser->can('users-manage'))
-                    <a href="{{ baseUrl('/settings/users') }}" @if($selected == 'users') class="selected text-button" @endif><i class="zmdi zmdi-accounts"></i>Users</a>
+                    <a href="{{ baseUrl('/settings/users') }}" @if($selected == 'users') class="selected text-button" @endif><i class="zmdi zmdi-accounts"></i>{{ trans('settings.users') }}</a>
                 @endif
                 @if($currentUser->can('user-roles-manage'))
-                    <a href="{{ baseUrl('/settings/roles') }}" @if($selected == 'roles') class="selected text-button" @endif><i class="zmdi zmdi-lock-open"></i>Roles</a>
+                    <a href="{{ baseUrl('/settings/roles') }}" @if($selected == 'roles') class="selected text-button" @endif><i class="zmdi zmdi-lock-open"></i>{{ trans('settings.roles') }}</a>
                 @endif
             </div>
         </div>
index 6a59c0c54c8281ebd6756e007a9dcd2e27a4e056..bae42540ce21423c6efb74b3f38076ab3914285d 100644 (file)
@@ -5,7 +5,7 @@
     @include('settings/navbar', ['selected' => 'roles'])
 
     <div class="container">
-        <h1>Create New Role</h1>
+        <h1>{{ trans('settings.role_create') }}</h1>
 
         <form action="{{ baseUrl("/settings/roles/new") }}" method="POST">
             @include('settings/roles/form')
index 1377d07aeb7857528d1ae72ca0d48e506cbb2c2f..0b8e1626fdb854ba14161ee77bf3cac893b9f1ed 100644 (file)
@@ -5,8 +5,8 @@
     @include('settings/navbar', ['selected' => 'roles'])
 
     <div class="container small" ng-non-bindable>
-        <h1>Delete Role</h1>
-        <p>This will delete the role with the name '{{ $role->display_name }}'.</p>
+        <h1>{{ trans('settings.role_delete') }}</h1>
+        <p>{{ trans('settings.role_delete_confirm', ['roleName' => $role->display_name]) }}</p>
 
         <form action="{{ baseUrl("/settings/roles/delete/{$role->id}") }}" method="POST">
             {!! csrf_field() !!}
 
             @if($role->users->count() > 0)
             <div class="form-group">
-                    <p>This role has {{$role->users->count()}} users assigned to it. If you would like to migrate the users from this role select a new role below.</p>
+                    <p>{{ trans('settings.role_delete_users_assigned', ['userCount' => $role->users->count()]) }}</p>
                     @include('form/role-select', ['options' => $roles, 'name' => 'migration_role_id'])
             </div>
             @endif
 
-            <p class="text-neg">Are you sure you want to delete this role?</p>
-            <a href="{{ baseUrl("/settings/roles/{$role->id}") }}" class="button">Cancel</a>
-            <button type="submit" class="button neg">Confirm</button>
+            <p class="text-neg">{{ trans('settings.role_delete_sure') }}</p>
+            <a href="{{ baseUrl("/settings/roles/{$role->id}") }}" class="button muted">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button neg">{{ trans('common.confirm') }}</button>
         </form>
     </div>
 
index 7e186e8980e6069910fa6c73d01648b0e6362432..b46b646635f18417f390dd0bf83b30cd2f9da163 100644 (file)
@@ -7,11 +7,11 @@
     <div class="container">
         <div class="row">
             <div class="col-sm-6">
-                <h1>Edit Role <small> {{ $role->display_name }}</small></h1>
+                <h1>{{ trans('settings.role_edit') }}</h1>
             </div>
             <div class="col-sm-6">
                 <p></p>
-                <a href="{{ baseUrl("/settings/roles/delete/{$role->id}") }}" class="button neg float right">Delete Role</a>
+                <a href="{{ baseUrl("/settings/roles/delete/{$role->id}") }}" class="button neg float right">{{ trans('settings.role_delete') }}</a>
             </div>
         </div>
 
index 78e9e15333091fc0e2bbf99fd5443766edc8376b..319f3a2df9dea8bed1310a5d0e7b3db9847c8d13 100644 (file)
     <div class="col-md-9">
         <div class="row">
             <div class="col-md-5">
-                <h3>Role Details</h3>
+                <h3>{{ trans('settings.role_details') }}</h3>
                 <div class="form-group">
-                    <label for="name">Role Name</label>
+                    <label for="name">{{ trans('settings.role_name') }}</label>
                     @include('form/text', ['name' => 'display_name'])
                 </div>
                 <div class="form-group">
-                    <label for="name">Short Role Description</label>
+                    <label for="name">{{ trans('settings.role_desc') }}</label>
                     @include('form/text', ['name' => 'description'])
                 </div>
-                <h3>System Permissions</h3>
-                <label>@include('settings/roles/checkbox', ['permission' => 'users-manage']) Manage users</label>
-                <label>@include('settings/roles/checkbox', ['permission' => 'user-roles-manage']) Manage roles & role permissions</label>
-                <label>@include('settings/roles/checkbox', ['permission' => 'restrictions-manage-all']) Manage all Book, Chapter & Page permissions</label>
-                <label>@include('settings/roles/checkbox', ['permission' => 'permissions']) Manage permissions on own Book, Chapter & Pages</label>
-                <label>@include('settings/roles/checkbox', ['permission' => 'settings-manage']) Manage app settings</label>
+                <h3>{{ trans('settings.role_system') }}</h3>
+                <label>@include('settings/roles/checkbox', ['permission' => 'users-manage']) {{ trans('settings.role_manage_users') }}</label>
+                <label>@include('settings/roles/checkbox', ['permission' => 'user-roles-manage']) {{ trans('settings.role_manage_roles') }}</label>
+                <label>@include('settings/roles/checkbox', ['permission' => 'restrictions-manage-all']) {{ trans('settings.role_manage_entity_permissions') }}</label>
+                <label>@include('settings/roles/checkbox', ['permission' => 'permissions']) {{ trans('settings.role_manage_own_entity_permissions') }}</label>
+                <label>@include('settings/roles/checkbox', ['permission' => 'settings-manage']) {{ trans('settings.role_manage_settings') }}</label>
             </div>
 
             <div class="col-md-6">
 
-                <h3>Asset Permissions</h3>
-                <p>
-                    These permissions control default access to the assets within the system.
-                    Permissions on Books, Chapters and Pages will override these permissions.
-                </p>
+                <h3>{{ trans('settings.role_asset') }}</h3>
+                <p>{{ trans('settings.role_asset_desc') }}</p>
+
                 <table class="table">
                     <tr>
                         <th width="20%"></th>
-                        <th width="20%">Create</th>
-                        <th width="20%">View</th>
-                        <th width="20%">Edit</th>
-                        <th width="20%">Delete</th>
+                        <th width="20%">{{ trans('common.create') }}</th>
+                        <th width="20%">{{ trans('common.view') }}</th>
+                        <th width="20%">{{ trans('common.edit') }}</th>
+                        <th width="20%">{{ trans('common.delete') }}</th>
                     </tr>
                     <tr>
-                        <td>Books</td>
+                        <td>{{ trans('entities.books') }}</td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-create-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-create-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-view-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-view-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-view-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-view-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-update-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-update-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-update-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-update-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-delete-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'book-delete-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-delete-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'book-delete-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                     </tr>
                     <tr>
-                        <td>Chapters</td>
+                        <td>{{ trans('entities.chapters') }}</td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-create-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-create-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-create-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-create-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-view-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-view-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-view-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-view-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-update-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-update-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-update-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-update-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-delete-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-delete-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-delete-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'chapter-delete-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                     </tr>
                     <tr>
-                        <td>Pages</td>
+                        <td>{{ trans('entities.pages') }}</td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-create-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-create-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-create-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-create-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-view-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-view-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-view-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-view-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-update-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-update-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-update-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-update-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-delete-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'page-delete-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-delete-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'page-delete-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                     </tr>
                     <tr>
-                        <td>Images</td>
+                        <td>{{ trans('entities.images') }}</td>
                         <td>@include('settings/roles/checkbox', ['permission' => 'image-create-all'])</td>
-                        <td style="line-height:1.2;"><small class="faded">Controlled by the asset they are uploaded to</small></td>
+                        <td style="line-height:1.2;"><small class="faded">{{ trans('settings.role_controlled_by_asset') }}</small></td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'image-update-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'image-update-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'image-update-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'image-update-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'image-delete-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'image-delete-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'image-delete-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'image-delete-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                     </tr>
                     <tr>
-                        <td>Attachments</td>
+                        <td>{{ trans('entities.attachments') }}</td>
                         <td>@include('settings/roles/checkbox', ['permission' => 'attachment-create-all'])</td>
-                        <td style="line-height:1.2;"><small class="faded">Controlled by the asset they are uploaded to</small></td>
+                        <td style="line-height:1.2;"><small class="faded">{{ trans('settings.role_controlled_by_asset') }}</small></td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-update-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-update-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-update-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-update-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                         <td>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-delete-own']) Own</label>
-                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-delete-all']) All</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-delete-own']) {{ trans('settings.role_own') }}</label>
+                            <label>@include('settings/roles/checkbox', ['permission' => 'attachment-delete-all']) {{ trans('settings.role_all') }}</label>
                         </td>
                     </tr>
                 </table>
             </div>
         </div>
-        <a href="{{ baseUrl("/settings/roles") }}" class="button muted">Cancel</a>
-        <button type="submit" class="button pos">Save Role</button>
+        <a href="{{ baseUrl("/settings/roles") }}" class="button muted">{{ trans('common.cancel') }}</a>
+        <button type="submit" class="button pos">{{ trans('settings.role_save') }}</button>
     </div>
     <div class="col-md-3">
-        <h3>Users in this role</h3>
+        <h3>{{ trans('settings.role_users') }}</h3>
 
         @if(isset($role) && count($role->users) > 0)
         <table class="list-table">
         </table>
         @else
             <p class="text-muted">
-                No users currently in this role.
+                {{ trans('settings.role_users_none') }}
             </p>
         @endif
 
index 2c905ae22c336aa0ebf102d63437ef9fea867633..c24254946d6fc34f6b974439219c8acb741d32d6 100644 (file)
@@ -8,25 +8,25 @@
 
         <div class="row action-header">
             <div class="col-sm-8">
-                <h1>User Roles</h1>
+                <h1>{{ trans('settings.role_user_roles') }}</h1>
             </div>
             <div class="col-sm-4">
                 <p></p>
-                <a href="{{ baseUrl("/settings/roles/new") }}" class="button float right pos"><i class="zmdi zmdi-lock-open"></i>Add new role</a>
+                <a href="{{ baseUrl("/settings/roles/new") }}" class="button float right pos"><i class="zmdi zmdi-lock-open"></i>{{ trans('settings.role_create') }}</a>
             </div>
         </div>
 
         <table class="table">
             <tr>
-                <th>Role Name</th>
+                <th>{{ trans('settings.role_name') }}</th>
                 <th></th>
-                <th class="text-right">Users</th>
+                <th class="text-center">{{ trans('settings.users') }}</th>
             </tr>
             @foreach($roles as $role)
                 <tr>
                     <td><a href="{{ baseUrl("/settings/roles/{$role->id}") }}">{{ $role->display_name }}</a></td>
                     <td>{{ $role->description }}</td>
-                    <td class="text-right">{{ $role->users->count() }}</td>
+                    <td class="text-center">{{ $role->users->count() }}</td>
                 </tr>
             @endforeach
         </table>
index b25f2ee8aa10d6df97786da231456e75a21d2f78..bff79820a664ede3b7f5fb3e51a0a19d1500f58f 100644 (file)
@@ -3,6 +3,18 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    <div class="breadcrumbs">
+                        <a href="{{ baseUrl('/settings/users') }}" class="text-button"><i class="zmdi zmdi-accounts"></i>Users</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
         <h1>Create User</h1>
 
index 74b993b3c681e80ecb17d8280c1add4bd4fadab1..135231a32bf2325650643f8cc8a86db5e9d44ec9 100644 (file)
@@ -2,16 +2,30 @@
 
 @section('content')
 
+    <div class="faded-small toolbar">
+        <div class="container">
+            <div class="row">
+                <div class="col-sm-12 faded">
+                    <div class="breadcrumbs">
+                        <a href="{{ baseUrl("/settings/users") }}" class="text-button"><i class="zmdi zmdi-accounts"></i>Users</a>
+                        <span class="sep">&raquo;</span>
+                        <a href="{{ baseUrl("/settings/users/{$user->id}") }}" class="text-button"><i class="zmdi zmdi-account"></i>{{ $user->name }}</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div class="container small" ng-non-bindable>
-        <h1>Delete User</h1>
-        <p>This will fully delete this user with the name '<span class="text-neg">{{ $user->name }}</span>' from the system.</p>
-        <p class="text-neg">Are you sure you want to delete this user?</p>
+        <h1>{{ trans('settings.users_delete') }}</h1>
+        <p>{{ trans('settings.users_delete_warning', ['userName' => $user->name]) }}</p>
+        <p class="text-neg">{{ trans('settings.users_delete_confirm') }}</p>
 
         <form action="{{ baseUrl("/settings/users/{$user->id}") }}" method="POST">
             {!! csrf_field() !!}
             <input type="hidden" name="_method" value="DELETE">
-            <a href="{{ baseUrl("/settings/users/{$user->id}") }}" class="button muted">Cancel</a>
-            <button type="submit" class="button neg">Confirm</button>
+            <a href="{{ baseUrl("/settings/users/{$user->id}") }}" class="button muted">{{ trans('common.cancel') }}</a>
+            <button type="submit" class="button neg">{{ trans('common.confirm') }}</button>
         </form>
     </div>
 
index 6cbbdb7f7ec879a776e3ec0087f13618c8a836c0..4db00e31f932fb8157fa63d8c085b25ead1a2b24 100644 (file)
         <form action="{{ baseUrl("/settings/users/{$user->id}") }}" method="post">
             <div class="row">
                 <div class="col-sm-8">
-                    <h1>Edit {{ $user->id === $currentUser->id ? 'Profile' : 'User' }}</h1>
+                    <h1>{{ $user->id === $currentUser->id ? trans('settings.users_edit_profile') : trans('settings.users_edit') }}</h1>
                 </div>
                 <div class="col-sm-4">
                     <p></p>
                     @if($authMethod !== 'system')
-                        <a href="{{ baseUrl("/settings/users/{$user->id}/delete") }}" class="neg button float right">Delete User</a>
+                        <a href="{{ baseUrl("/settings/users/{$user->id}/delete") }}" class="neg button float right">{{ trans('settings.users_delete') }}</a>
                     @endif
                 </div>
             </div>
             </div>
             <div class="col-md-6">
                 <div class="form-group" id="logo-control">
-                    <label for="user-avatar">User Avatar</label>
-                    <p class="small">This image should be approx 256px square.</p>
-                    <image-picker resize-height="512" resize-width="512" current-image="{{ $user->getAvatar(80) }}" current-id="{{ $user->image_id }}" default-image="{{ baseUrl("/user_avatar.png") }}" name="image_id" show-remove="false" image-class="['avatar' ,'large']"></image-picker>
+                    <label for="user-avatar">{{ trans('settings.users_avatar') }}</label>
+                    <p class="small">{{ trans('settings.users_avatar_desc') }}</p>
+
+                    @include('components.image-picker', [
+                          'resizeHeight' => '512',
+                          'resizeWidth' => '512',
+                          'showRemove' => false,
+                          'defaultImage' => baseUrl('/user_avatar.png'),
+                          'currentImage' => $user->getAvatar(80),
+                          'currentId' => $user->image_id,
+                          'name' => 'image_id',
+                          'imageClass' => 'avatar large'
+                      ])
+
                 </div>
             </div>
         </div>
         <hr class="margin-top large">
 
         @if($currentUser->id === $user->id && count($activeSocialDrivers) > 0)
-            <h3>Social Accounts</h3>
-            <p class="text-muted">
-                Here you can connect your other accounts for quicker and easier login. <br>
-                Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.
-            </p>
+            <h3>{{ trans('settings.users_social_accounts') }}</h3>
+            <p class="text-muted">{{ trans('settings.users_social_accounts_info') }}</p>
             <div class="row">
                 @if(isset($activeSocialDrivers['google']))
                     <div class="col-md-3 text-center">
                         <div><i class="zmdi zmdi-google-plus-box zmdi-hc-4x" style="color: #DC4E41;"></i></div>
                         <div>
                             @if($user->hasSocialAccount('google'))
-                                <a href="{{ baseUrl("/login/service/google/detach") }}" class="button neg">Disconnect Account</a>
+                                <a href="{{ baseUrl("/login/service/google/detach") }}" class="button neg">{{ trans('settings.users_social_disconnect') }}</a>
                             @else
-                                <a href="{{ baseUrl("/login/service/google") }}" class="button pos">Attach Account</a>
+                                <a href="{{ baseUrl("/login/service/google") }}" class="button pos">{{ trans('settings.users_social_connect') }}</a>
                             @endif
                         </div>
                     </div>
@@ -63,9 +71,9 @@
                         <div><i class="zmdi zmdi-github zmdi-hc-4x" style="color: #444;"></i></div>
                         <div>
                             @if($user->hasSocialAccount('github'))
-                                <a href="{{ baseUrl("/login/service/github/detach") }}" class="button neg">Disconnect Account</a>
+                                <a href="{{ baseUrl("/login/service/github/detach") }}" class="button neg">{{ trans('settings.users_social_disconnect') }}</a>
                             @else
-                                <a href="{{ baseUrl("/login/service/github") }}" class="button pos">Attach Account</a>
+                                <a href="{{ baseUrl("/login/service/github") }}" class="button pos">{{ trans('settings.users_social_connect') }}</a>
                             @endif
                         </div>
                     </div>
@@ -77,5 +85,5 @@
     </div>
 
     <p class="margin-top large"><br></p>
-    @include('partials/image-manager', ['imageType' => 'user'])
+    @include('components.image-manager', ['imageType' => 'user'])
 @stop
index 6e4d2a5fd3c8de7402021955ba9cf1b40c1a6ed9..0a6cf79ae1d26163283a480f550daa255cb58142 100644 (file)
@@ -1,30 +1,30 @@
 <div class="form-group">
-    <label for="name">Name</label>
+    <label for="name">{{ trans('auth.name') }}</label>
     @include('form.text', ['name' => 'name'])
 </div>
 
 @if(userCan('users-manage'))
 <div class="form-group">
-    <label for="email">Email</label>
+    <label for="email">{{ trans('auth.email') }}</label>
     @include('form.text', ['name' => 'email'])
 </div>
 @endif
 
 @if(userCan('users-manage'))
     <div class="form-group">
-        <label for="role">User Role</label>
+        <label for="role">{{ trans('settings.users_role') }}</label>
         @include('form/role-checkboxes', ['name' => 'roles', 'roles' => $roles])
     </div>
 @endif
 
 @if(userCan('users-manage'))
     <div class="form-group">
-        <label for="external_auth_id">External Authentication ID</label>
+        <label for="external_auth_id">{{ trans('settings.users_external_auth_id') }}</label>
         @include('form.text', ['name' => 'external_auth_id'])
     </div>
 @endif
 
 <div class="form-group">
-    <a href="{{ baseUrl("/settings/users") }}" class="button muted">Cancel</a>
-    <button class="button pos" type="submit">Save</button>
+    <a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button class="button pos" type="submit">{{ trans('common.save') }}</button>
 </div>
\ No newline at end of file
index d902c5b2cf2955046e68b713e6c43b03122a02fe..39ae4c7703d923e7300688a41616e107067525d8 100644 (file)
@@ -1,16 +1,16 @@
 <div class="form-group">
-    <label for="name">Name</label>
+    <label for="name">{{ trans('auth.name') }}</label>
     @include('form.text', ['name' => 'name'])
 </div>
 
 <div class="form-group">
-    <label for="email">Email</label>
+    <label for="email">{{ trans('auth.email') }}</label>
     @include('form.text', ['name' => 'email'])
 </div>
 
 @if(userCan('users-manage'))
     <div class="form-group">
-        <label for="role">User Role</label>
+        <label for="role">{{ trans('settings.users_role') }}</label>
         @include('form/role-checkboxes', ['name' => 'roles', 'roles' => $roles])
     </div>
 @endif
 @if(isset($model))
     <div class="form-group">
         <span class="text-muted">
-            Only fill the below if you would like <br>to change your password:
+            {{ trans('settings.users_password_warning') }}
         </span>
     </div>
 @endif
 
 <div class="form-group">
-    <label for="password">Password</label>
+    <label for="password">{{ trans('auth.password') }}</label>
     @include('form.password', ['name' => 'password'])
 </div>
 
 <div class="form-group">
-    <label for="password-confirm">Confirm Password</label>
+    <label for="password-confirm">{{ trans('auth.password_confirm') }}</label>
     @include('form.password', ['name' => 'password-confirm'])
 </div>
 
 <div class="form-group">
-    <a href="{{ baseUrl("/settings/users") }}" class="button muted">Cancel</a>
-    <button class="button pos" type="submit">Save</button>
+    <a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button class="button pos" type="submit">{{ trans('common.save') }}</button>
 </div>
 
index 3ee5f6409dc756313be973343fbffff87b7580b3..868dad854061b6c73e7db7927f82121e5a69cc83 100644 (file)
@@ -1,25 +1,26 @@
 @if($user->system_name == 'public')
-    <p>This user represents any guest users that visit your instance. It cannot be used for logins but is assigned&nbsp;automatically.</p>
+    <p>{{ trans('settings.users_system_public') }}</p>
 @endif
 
 <div class="form-group">
-    <label for="name">Name</label>
+    <label for="name">{{ trans('auth.name') }}</label>
     @include('form.text', ['name' => 'name'])
 </div>
 
 <div class="form-group">
-    <label for="email">Email</label>
+    <label for="email">{{ trans('auth.email') }}</label>
     @include('form.text', ['name' => 'email'])
 </div>
 
 @if(userCan('users-manage'))
     <div class="form-group">
-        <label for="role">User Role</label>
+        <label for="role">{{ trans('settings.users_role') }}</label>
         @include('form/role-checkboxes', ['name' => 'roles', 'roles' => $roles])
     </div>
 @endif
 
 <div class="form-group">
-    <a href="{{ baseUrl("/settings/users") }}" class="button muted">Cancel</a>
-    <button class="button pos" type="submit">Save</button>
+    <a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
+    <button class="button pos" type="submit">{{ trans('common.save') }}</button>
 </div>
+
index 105fddb5ba55d232cd69fd684006dd6070dab0ae..3ea5a03f7fa377b9582ead6be0fd11b077669170 100644 (file)
@@ -9,12 +9,12 @@
     <div class="container small" ng-non-bindable>
         <div class="row action-header">
             <div class="col-sm-8">
-                <h1>Users</h1>
+                <h1>{{ trans('settings.users') }}</h1>
             </div>
             <div class="col-sm-4">
                 <p></p>
                 @if(userCan('users-manage'))
-                    <a href="{{ baseUrl("/settings/users/create") }}" class="pos button float right"><i class="zmdi zmdi-account-add"></i>Add new user</a>
+                    <a href="{{ baseUrl("/settings/users/create") }}" class="pos button float right"><i class="zmdi zmdi-account-add"></i>{{ trans('settings.users_add_new') }}</a>
                 @endif
             </div>
         </div>
                     @foreach(collect($listDetails)->except('search') as $name => $val)
                         <input type="hidden" name="{{ $name }}" value="{{ $val }}">
                     @endforeach
-                    <input type="text" name="search" placeholder="Search Users" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
+                    <input type="text" name="search" placeholder="{{ trans('settings.users_search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
                 </form>
             </div>
         </div>
-        <div class="text-center">
-
-        </div>
 
         <table class="table">
             <tr>
                 <th></th>
-                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'name']) }}">Name</a></th>
-                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'email']) }}">Email</a></th>
-                <th>User Roles</th>
+                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'name']) }}">{{ trans('auth.name') }}</a></th>
+                <th><a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'email']) }}">{{ trans('auth.email') }}</a></th>
+                <th>{{ trans('settings.role_user_roles') }}</th>
             </tr>
             @foreach($users as $user)
                 <tr>
index 1ae869979d1aa1c44f67fdffba57ad65f23fa167..10bd0ec633a0c44cee7a3ac2c92c08446e23367a 100644 (file)
                             <div>
                                 <h3 style="margin-top: 0;">{{ $user->name }}</h3>
                                 <p class="text-muted">
-                                    User for {{ $user->created_at->diffForHumans(null, true) }}
+                                    {{ trans('entities.profile_user_for_x', ['time' => $user->created_at->diffForHumans(null, true)]) }}
                                 </p>
                             </div>
                         </div>
                     </div>
                     <div class="col-md-5 text-bigger" id="content-counts">
-                        <div class="text-muted">Created Content</div>
+                        <div class="text-muted">{{ trans('entities.profile_created_content') }}</div>
                         <div class="text-book">
-                            <i class="zmdi zmdi-book zmdi-hc-fw"></i> {{ $assetCounts['books'] }} {{ str_plural('Book', $assetCounts['books']) }}
+                            <i class="zmdi zmdi-book zmdi-hc-fw"></i> {{ $assetCounts['books'] }} {{ str_plural(trans('entities.book'), $assetCounts['books']) }}
                         </div>
                         <div class="text-chapter">
-                            <i class="zmdi zmdi-collection-bookmark zmdi-hc-fw"></i> {{ $assetCounts['chapters'] }} {{ str_plural('Chapter', $assetCounts['chapters']) }}
+                            <i class="zmdi zmdi-collection-bookmark zmdi-hc-fw"></i> {{ $assetCounts['chapters'] }} {{ str_plural(trans('entities.chapter'), $assetCounts['chapters']) }}
                         </div>
                         <div class="text-page">
-                            <i class="zmdi zmdi-file-text zmdi-hc-fw"></i> {{ $assetCounts['pages'] }} {{ str_plural('Page', $assetCounts['pages']) }}
+                            <i class="zmdi zmdi-file-text zmdi-hc-fw"></i> {{ $assetCounts['pages'] }} {{ str_plural(trans('entities.page'), $assetCounts['pages']) }}
                         </div>
                     </div>
                 </div>
 
                 <hr class="even">
 
-                <h3>Recently Created Pages</h3>
+                <h3>{{ trans('entities.recently_created_pages') }}</h3>
                 @if (count($recentlyCreated['pages']) > 0)
                     @include('partials/entity-list', ['entities' => $recentlyCreated['pages']])
                 @else
-                    <p class="text-muted">{{ $user->name }} has not created any pages</p>
+                    <p class="text-muted">{{ trans('entities.profile_not_created_pages', ['userName' => $user->name]) }}</p>
                 @endif
 
                 <hr class="even">
 
-                <h3>Recently Created Chapters</h3>
+                <h3>{{ trans('entities.recently_created_chapters') }}</h3>
                 @if (count($recentlyCreated['chapters']) > 0)
                     @include('partials/entity-list', ['entities' => $recentlyCreated['chapters']])
                 @else
-                    <p class="text-muted">{{ $user->name }} has not created any chapters</p>
+                    <p class="text-muted">{{ trans('entities.profile_not_created_chapters', ['userName' => $user->name]) }}</p>
                 @endif
 
                 <hr class="even">
 
-                <h3>Recently Created Books</h3>
+                <h3>{{ trans('entities.recently_created_books') }}</h3>
                 @if (count($recentlyCreated['books']) > 0)
                     @include('partials/entity-list', ['entities' => $recentlyCreated['books']])
                 @else
-                    <p class="text-muted">{{ $user->name }} has not created any books</p>
+                    <p class="text-muted">{{ trans('entities.profile_not_created_books', ['userName' => $user->name]) }}</p>
                 @endif
             </div>
 
             <div class="col-sm-4 col-sm-offset-1" id="recent-activity">
-                <h3>Recent Activity</h3>
+                <h3>{{ trans('entities.recent_activity') }}</h3>
                 @include('partials/activity-list', ['activity' => $activity])
             </div>
 
index acefa652383d18d49dc722e2e7342f28ea543590..7ca1dc8d0312206acc205135560c6dff02443abd 100644 (file)
@@ -18,5 +18,5 @@ if (! empty($outroLines)) {
     echo implode("\n", $outroLines), "\n\n";
 }
 
-echo 'Regards,', "\n";
-echo config('app.name'), "\n";
+echo "\n";
+echo setting('app-name'), "\n";
index 297c6be0553a6143ec7a58262633f3b687e54ff9..3e02cbba9ceb15e7dacc4cac74b3db58ca02fc57 100644 (file)
@@ -159,8 +159,7 @@ $style = [
                                                             <tr>
                                                                 <td style="{{ $fontFamily }}">
                                                                     <p style="{{ $style['paragraph-sub'] }}">
-                                                                        If you’re having trouble clicking the "{{ $actionText }}" button,
-                                                                        copy and paste the URL below into your web browser:
+                                                                        {{ trans('common.email_action_help', ['actionText' => $actionText]) }}
                                                                     </p>
 
                                                                     <p style="{{ $style['paragraph-sub'] }}">
@@ -188,7 +187,7 @@ $style = [
                                                     <p style="{{ $style['paragraph-sub'] }}">
                                                         &copy; {{ date('Y') }}
                                                         <a style="{{ $style['anchor'] }}" href="{{ baseUrl('/') }}" target="_blank">{{ setting('app-name') }}</a>.
-                                                        All rights reserved.
+                                                        {{ trans('common.email_rights') }}
                                                     </p>
                                                 </td>
                                             </tr>
index d179c28a52d2671a8a36b9ff437e1ed4e3d843a5..076ffb94f133e648a0298a4e9e588ea3634aba95 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+Route::get('/translations.js', 'HomeController@getTranslations');
+
 // Authenticated routes...
 Route::group(['middleware' => 'auth'], function () {
 
@@ -107,7 +109,6 @@ Route::group(['middleware' => 'auth'], function () {
         Route::get('/get/{entityType}/{entityId}', 'TagController@getForEntity');
         Route::get('/suggest/names', 'TagController@getNameSuggestions');
         Route::get('/suggest/values', 'TagController@getValueSuggestions');
-        Route::post('/update/{entityType}/{entityId}', 'TagController@updateForEntity');
     });
 
     Route::get('/ajax/search/entities', 'SearchController@searchEntitiesAjax');
index 0d2e4ac170a660e3ed0925f65df404e915a1c398..664ec297a0bff766368b4d5c92d1ec6bb11fee42 100644 (file)
@@ -24,7 +24,7 @@ class AuthTest extends TestCase
         $settings->put('app-public', 'true');
         $this->visit('/')
             ->seePageIs('/')
-            ->see('Sign In');
+            ->see('Log In');
     }
 
     public function test_registration_showing()
@@ -132,7 +132,7 @@ class AuthTest extends TestCase
 
         $this->asAdmin()
             ->visit('/settings/users')
-            ->click('Add new user')
+            ->click('Add New User')
             ->type($user->name, '#name')
             ->type($user->email, '#email')
             ->check('roles[admin]')
@@ -245,7 +245,7 @@ class AuthTest extends TestCase
     {
         $this->setSettings(['registration-enabled' => 'true']);
         $this->visit('/password/email')
-            ->seeLink('Sign in')
+            ->seeLink('Log in')
             ->seeLink('Sign up');
     }
 
@@ -260,6 +260,6 @@ class AuthTest extends TestCase
         return $this->visit('/login')
             ->type($email, '#email')
             ->type($password, '#password')
-            ->press('Sign In');
+            ->press('Log In');
     }
 }
index 9573321fba98e5c3bb6fbf06630ddafbfb5a0221..45e46fe81796b1a2051691c7d08db87470a1ff79 100644 (file)
@@ -36,11 +36,11 @@ class LdapTest extends \TestCase
             ->see('Username')
             ->type($this->mockUser->name, '#username')
             ->type($this->mockUser->password, '#password')
-            ->press('Sign In')
+            ->press('Log In')
             ->seePageIs('/login')->see('Please enter an email to use for this account.');
 
         $this->type($this->mockUser->email, '#email')
-            ->press('Sign In')
+            ->press('Log In')
             ->seePageIs('/')
             ->see($this->mockUser->name)
             ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name]);
@@ -64,7 +64,7 @@ class LdapTest extends \TestCase
             ->see('Username')
             ->type($this->mockUser->name, '#username')
             ->type($this->mockUser->password, '#password')
-            ->press('Sign In')
+            ->press('Log In')
             ->seePageIs('/')
             ->see($this->mockUser->name)
             ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $ldapDn]);
@@ -87,7 +87,7 @@ class LdapTest extends \TestCase
             ->see('Username')
             ->type($this->mockUser->name, '#username')
             ->type($this->mockUser->password, '#password')
-            ->press('Sign In')
+            ->press('Log In')
             ->seePageIs('/login')->see('These credentials do not match our records.')
             ->dontSeeInDatabase('users', ['external_auth_id' => $this->mockUser->name]);
     }
index 60b5ceebd4a8fe783d3eda3f7e9d7cd009b83fa5..3f60f9c36126b559b027a0d84f39cda03a5080b6 100644 (file)
@@ -15,8 +15,8 @@ class EntitySearchTest extends TestCase
             ->type($page->name, 'term')
             ->press('header-search-box-button')
             ->see('Search Results')
-            ->see($page->name)
-            ->click($page->name)
+            ->seeInElement('.entity-list', $page->name)
+            ->clickInElement('.entity-list', $page->name)
             ->seePageIs($page->getUrl());
     }
 
index 20721968f9a88c933d41cfa9efbb60c5cc652437..79e574cbd48d444670ccbd1dda90f84e71e44ee6 100644 (file)
@@ -136,7 +136,7 @@ class EntityTest extends TestCase
         $this->asAdmin()
             ->visit('/books')
             // Choose to create a book
-            ->click('Add new book')
+            ->click('Create New Book')
             ->seePageIs('/books/create')
             // Fill out form & save
             ->type($book->name, '#name')
index 80783912a46f79e9ef93a8aad43574bc1772e4a7..d78b9447973751103fdf659b9149ea8693a1655e 100644 (file)
@@ -28,7 +28,7 @@ class SortTest extends TestCase
         $currentBook = $page->book;
         $newBook = \BookStack\Book::where('id', '!=', $currentBook->id)->first();
         $this->asAdmin()->visit($page->getUrl() . '/move')
-            ->see('Move Page')->see($page->name)
+            ->see('Move Page')
             ->type('book:' . $newBook->id, 'entity_selection')->press('Move Page');
 
         $page = \BookStack\Page::find($page->id);
@@ -48,7 +48,7 @@ class SortTest extends TestCase
         $newBook = \BookStack\Book::where('id', '!=', $currentBook->id)->first();
 
         $this->asAdmin()->visit($chapter->getUrl() . '/move')
-            ->see('Move Chapter')->see($chapter->name)
+            ->see('Move Chapter')
             ->type('book:' . $newBook->id, 'entity_selection')->press('Move Chapter');
 
         $chapter = \BookStack\Chapter::find($chapter->id);
index 7a0515fd939795ea5732326cfc016a770a37d009..500dd3b6772f5d4d2b62ff93bacea80eb34722fa 100644 (file)
@@ -81,7 +81,7 @@ class RolesTest extends TestCase
         $this->asAdmin()->visit('/settings')
             ->click('Roles')
             ->seePageIs('/settings/roles')
-            ->click('Add new role')
+            ->click('Create New Role')
             ->type('Test Role', 'display_name')
             ->type('A little test description', 'description')
             ->press('Save Role')
@@ -211,7 +211,7 @@ class RolesTest extends TestCase
         $this->checkAccessPermission('book-create-all', [
             '/books/create'
         ], [
-            '/books' => 'Add new book'
+            '/books' => 'Create New Book'
         ]);
 
         $this->visit('/books/create')
index 685146423d80f54b6ce2d466ce7e8fc8e30fb417..2ea5fbfed428e89a3f02cfac45b73a8a9ec90257 100644 (file)
@@ -64,7 +64,7 @@ class PublicActionTest extends TestCase
         $this->visit($chapter->book->getUrl());
         $this->visit($chapter->getUrl())
             ->click('New Page')
-            ->see('Create Page')
+            ->see('New Page')
             ->seePageIs($chapter->getUrl('/create-page'));
 
         $this->submitForm('Continue', [