Forráskód Böngészése

Merge remote-tracking branch 'upstream/devel' into devel

Xavier Priour 9 éve
szülő
commit
e304185c23
42 módosított fájl, 539 hozzáadás és 313 törlés
  1. 1 1
      client/components/boards/boardArchive.js
  2. 2 2
      client/components/boards/boardHeader.jade
  3. 2 2
      client/components/boards/boardHeader.js
  4. 9 0
      client/components/boards/boardsList.jade
  5. 1 1
      client/components/cards/cardDetails.jade
  6. 2 1
      client/components/cards/minicard.styl
  7. 7 2
      client/components/lists/listBody.js
  8. 0 9
      client/components/lists/listHeader.jade
  9. 0 19
      client/components/lists/listHeader.js
  10. 1 1
      client/components/main/editor.js
  11. 1 12
      client/components/main/header.jade
  12. 0 5
      client/components/main/header.js
  13. 8 0
      client/components/main/header.styl
  14. 19 0
      client/components/main/keyboardShortcuts.jade
  15. 0 11
      client/components/main/keyboardShortcuts.tpl.jade
  16. 1 0
      client/components/main/layouts.jade
  17. 3 0
      client/components/main/layouts.styl
  18. 4 8
      client/components/sidebar/sidebar.js
  19. 29 24
      client/components/sidebar/sidebarFilters.jade
  20. 9 0
      client/components/sidebar/sidebarFilters.js
  21. 17 5
      client/config/router.js
  22. 9 3
      client/lib/modal.js
  23. 35 4
      i18n/ar.i18n.json
  24. 35 4
      i18n/ca.i18n.json
  25. 35 4
      i18n/de.i18n.json
  26. 13 13
      i18n/en.i18n.json
  27. 2 4
      i18n/es.i18n.json
  28. 27 29
      i18n/fi.i18n.json
  29. 50 19
      i18n/fr.i18n.json
  30. 35 4
      i18n/it.i18n.json
  31. 2 4
      i18n/ja.i18n.json
  32. 2 4
      i18n/ko.i18n.json
  33. 2 4
      i18n/pt-BR.i18n.json
  34. 35 4
      i18n/ru.i18n.json
  35. 2 4
      i18n/tr.i18n.json
  36. 76 45
      i18n/zh-CN.i18n.json
  37. 27 32
      models/boards.js
  38. 2 6
      models/users.js
  39. 1 1
      sandstorm-pkgdef.capnp
  40. 29 17
      sandstorm.js
  41. 2 3
      server/lib/utils.js
  42. 2 2
      server/publications/boards.js

+ 1 - 1
client/components/boards/boardArchive.js

@@ -1,4 +1,4 @@
-Template.headerTitle.events({
+Template.boardHeaderBar.events({
   'click .js-open-archived-board'() {
     Modal.open('archivedBoards');
   },

+ 2 - 2
client/components/boards/boardHeader.jade

@@ -1,4 +1,4 @@
-template(name="headerBoard")
+template(name="boardHeaderBar")
   h1.header-board-menu
     with currentBoard
       a(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}")
@@ -125,4 +125,4 @@ template(name="boardChangeTitlePopup")
 
 template(name="archiveBoardPopup")
   p {{_ 'close-board-pop'}}
-  button.js-confirm.negate.full(type="submit") {{_ 'close'}}
+  button.js-confirm.negate.full(type="submit") {{_ 'archive'}}

+ 2 - 2
client/components/boards/boardHeader.js

@@ -50,7 +50,7 @@ Template.boardChangeTitlePopup.events({
 
 BlazeComponent.extendComponent({
   template() {
-    return 'headerBoard';
+    return 'boardHeaderBar';
   },
 
   isStarred() {
@@ -94,7 +94,7 @@ BlazeComponent.extendComponent({
       },
     }];
   },
-}).register('headerBoard');
+}).register('boardHeaderBar');
 
 BlazeComponent.extendComponent({
   template() {

+ 9 - 0
client/components/boards/boardsList.jade

@@ -23,3 +23,12 @@ template(name="boardList")
                 p.board-list-item-desc= description
       li.js-add-board
         a.board-list-item.label {{_ 'add-board'}}
+
+
+template(name="boardListHeaderBar")
+  h1 {{_ 'my-boards'}}
+
+  .board-header-btns.right
+    a.board-header-btn.js-open-archived-board
+      i.fa.fa-archive
+      span {{_ 'archives'}}

+ 1 - 1
client/components/cards/cardDetails.jade

@@ -94,7 +94,7 @@ template(name="moveCardPopup")
 
 template(name="cardMembersPopup")
   ul.pop-over-list.js-card-member-list
-    each board.members
+    each board.activeMembers
       li.item(class="{{#if isCardMember}}active{{/if}}")
         a.name.js-select-member(href="#")
           +userAvatar(userId=user._id)

+ 2 - 1
client/components/cards/minicard.styl

@@ -133,5 +133,6 @@
       margin: 0
       padding: 0
       max-height: 162px
-      min-height: 54px
+      min-height: 36px
+      margin-bottom: 20px
       overflow-y: auto

+ 7 - 2
client/components/lists/listBody.js

@@ -57,6 +57,7 @@ BlazeComponent.extendComponent({
 
       // We keep the form opened, empty it, and scroll to it.
       textarea.val('').focus();
+      autosize.update(textarea);
       if (position === 'bottom') {
         this.scrollToBottom();
       }
@@ -180,13 +181,17 @@ BlazeComponent.extendComponent({
 
   onRendered() {
     const editor = this;
-    this.$('textarea').escapeableTextComplete([
+    const $textarea = this.$('textarea');
+
+    autosize($textarea);
+
+    $textarea.escapeableTextComplete([
       // User mentions
       {
         match: /\B@(\w*)$/,
         search(term, callback) {
           const currentBoard = Boards.findOne(Session.get('currentBoard'));
-          callback($.map(currentBoard.members, (member) => {
+          callback($.map(currentBoard.activeMembers(), (member) => {
             const user = Users.findOne(member.userId);
             return user.username.indexOf(term) === 0 ? user : null;
           }));

+ 0 - 9
client/components/lists/listHeader.jade

@@ -21,16 +21,11 @@ template(name="listActionPopup")
     li: a.js-add-card {{_ 'add-card'}}
     if cards.count
       li: a.js-select-cards {{_ 'list-select-cards'}}
-      li: a.js-move-cards {{_ 'list-move-cards'}}
-      li: a.js-archive-cards {{_ 'list-archive-cards'}}
   hr
   ul.pop-over-list
     li: a.js-import-card {{_ 'import-card'}}
     li: a.js-close-list {{_ 'archive-list'}}
 
-template(name="listMoveCardsPopup")
-  +boardLists
-
 template(name="boardLists")
   ul.pop-over-list
     each currentBoard.lists
@@ -39,7 +34,3 @@ template(name="boardLists")
           a.disabled {{title}} ({{_ 'current'}})
         else
           a.js-select-list= title
-
-template(name="listArchiveCardsPopup")
-  p {{_ 'list-archive-cards-pop'}}
-  input.js-confirm.negate.full(type="submit" value="{{_ 'archive-all'}}")

+ 0 - 19
client/components/lists/listHeader.js

@@ -34,28 +34,9 @@ Template.listActionPopup.events({
     Popup.close();
   },
   'click .js-import-card': Popup.open('listImportCard'),
-  'click .js-move-cards': Popup.open('listMoveCards'),
-  'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', function() {
-    this.allCards().forEach((card) => {
-      card.archive();
-    });
-    Popup.close();
-  }),
-
   'click .js-close-list'(evt) {
     evt.preventDefault();
     this.archive();
     Popup.close();
   },
 });
-
-Template.listMoveCardsPopup.events({
-  'click .js-select-list'() {
-    const fromList = Template.parentData(2).data;
-    const toList = this._id;
-    fromList.allCards().forEach((card) => {
-      card.move(toList);
-    });
-    Popup.close();
-  },
-});

+ 1 - 1
client/components/main/editor.js

@@ -28,7 +28,7 @@ Template.editor.onRendered(() => {
       match: /\B@(\w*)$/,
       search(term, callback) {
         const currentBoard = Boards.findOne(Session.get('currentBoard'));
-        callback(currentBoard.members.map((member) => {
+        callback(currentBoard.activeMembers().map((member) => {
           const username = Users.findOne(member.userId).username;
           return username.includes(term) ? username : null;
         }));

+ 1 - 12
client/components/main/header.jade

@@ -32,10 +32,7 @@ template(name="header")
       current page. This bar is contextual based.
       If the user is not connected we display "sign in" and "log in" buttons.
     #header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}")
-      if $.Session.get 'currentBoard'
-        +headerBoard
-      else if($eq currentRouteName 'home')
-        +headerTitle
+      +Template.dynamic(template=headerBar)
 
       //-
         On sandstorm, the logo shouldn't be clickable, because we only have one
@@ -47,11 +44,3 @@ template(name="header")
       else
         a.wekan-logo(href="{{pathFor 'home'}}" title="{{_ 'header-logo-title'}}")
           img(src="{{pathFor '/wekan-logo-header.png'}}" alt="Wekan")
-
-template(name="headerTitle")
-  h1 {{_ 'my-boards'}}
-
-  .board-header-btns.right
-    a.board-header-btn.js-open-archived-board
-      i.fa.fa-archive
-      span {{_ 'archives'}}

+ 0 - 5
client/components/main/header.js

@@ -1,9 +1,4 @@
 Template.header.helpers({
-  // Reactively set the color of the page from the color of the current board.
-  headerTemplate() {
-    return 'headerBoard';
-  },
-
   wrappedHeader() {
     return !Session.get('currentBoard');
   },

+ 8 - 0
client/components/main/header.styl

@@ -85,6 +85,14 @@
       float: left
       border-radius: 3px
 
+      a.fa, a i.fa
+        color: white
+
+      .back-btn
+        font-size: 0.9em
+        margin-right: 10px
+
+
     .wekan-logo
       display: block
       margin: 3px auto 0

+ 19 - 0
client/components/main/keyboardShortcuts.jade

@@ -0,0 +1,19 @@
+template(name="shortcutsHeaderBar")
+  h1
+    a.back-btn(href="{{pathFor 'home'}}")
+      i.fa.fa-chevron-left
+    | {{_ 'keyboard-shortcuts'}}
+
+template(name="shortcutsModalTitle")
+  h2
+    i.fa.fa-keyboard-o
+    | {{_ 'keyboard-shortcuts'}}
+
+template(name="keyboardShortcuts")
+  .wrapper.shortcuts-list
+    each mapping
+      .shortcuts-list-item
+        .shortcuts-list-item-keys
+          each keys
+            kbd= this
+        .shortcuts-list-item-action {{_ action}}

+ 0 - 11
client/components/main/keyboardShortcuts.tpl.jade

@@ -1,11 +0,0 @@
-.wrapper.shortcuts-list
-  h2
-    i.fa.fa-keyboard-o
-    | {{_ 'keyboard-shortcuts'}}
-
-  each mapping
-    .shortcuts-list-item
-      .shortcuts-list-item-keys
-        each keys
-          kbd= this
-      .shortcuts-list-item-action {{_ action}}

+ 1 - 0
client/components/main/layouts.jade

@@ -31,6 +31,7 @@ template(name="defaultLayout")
       .modal-content
         a.modal-close-btn.js-close-modal
           i.fa.fa-times-thin
+        +Template.dynamic(template=Modal.getHeaderName)
         +Template.dynamic(template=Modal.getTemplateName)
 
 template(name="notFound")

+ 3 - 0
client/components/main/layouts.styl

@@ -31,6 +31,9 @@ body
   .sk-spinner
     margin-top: 30vh
 
+  > .wrapper
+    margin-top: 25px
+
 #modal
   position: absolute
   top: 0

+ 4 - 8
client/components/sidebar/sidebar.js

@@ -279,7 +279,7 @@ BlazeComponent.extendComponent({
       'click .js-select-member'() {
         const userId = this.currentData()._id;
         const currentBoard = Boards.findOne(Session.get('currentBoard'));
-        if (currentBoard.memberIndex(userId)<0) {
+        if (!currentBoard.hasMember(userId)) {
           this.inviteUser(userId);
         }
       },
@@ -305,16 +305,12 @@ Template.changePermissionsPopup.events({
 
 Template.changePermissionsPopup.helpers({
   isAdmin() {
-    const user = Users.findOne(this.userId);
-    return user.isBoardAdmin();
+    const currentBoard = Boards.findOne(Session.get('currentBoard'));
+    return currentBoard.hasAdmin(this.userId);
   },
 
   isLastAdmin() {
-    const user = Users.findOne(this.userId);
-    if (!user.isBoardAdmin())
-      return false;
     const currentBoard = Boards.findOne(Session.get('currentBoard'));
-    const nbAdmins = _.where(currentBoard.members, { isAdmin: true }).length;
-    return nbAdmins === 1;
+    return currentBoard.hasAdmin(this.userId) && (currentBoard.activeAdmins() === 1);
   },
 });

+ 29 - 24
client/components/sidebar/sidebarFilters.jade

@@ -18,17 +18,16 @@ template(name="filterSidebar")
             i.fa.fa-check
   hr
   ul.sidebar-list
-    each currentBoard.members
-      if isActive
-        with getUser userId
-          li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
-            a.name.js-toggle-member-filter
-              +userAvatar(userId=this._id)
-              span.sidebar-list-item-description
-                = profile.fullname
-                | (<span class="username">{{ username }}</span>)
-              if Filter.members.isSelected _id
-                i.fa.fa-check
+    each currentBoard.activeMembers
+      with getUser userId
+        li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
+          a.name.js-toggle-member-filter
+            +userAvatar(userId=this._id)
+            span.sidebar-list-item-description
+              = profile.fullname
+              | (<span class="username">{{ username }}</span>)
+            if Filter.members.isSelected _id
+              i.fa.fa-check
   if Filter.isActive
     hr
     a.sidebar-btn.js-clear-all
@@ -55,20 +54,22 @@ template(name="multiselectionSidebar")
             i.fa.fa-ellipsis-h
   hr
   ul.sidebar-list
-    each currentBoard.members
-      if isActive
-        with getUser userId
-          li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
-            a.name.js-toggle-member-multiselection
-              +userAvatar(userId=this._id)
-              span.sidebar-list-item-description
-                = profile.fullname
-                | (<span class="username">{{ username }}</span>)
-              if allSelectedElementHave 'member' _id
-                i.fa.fa-check
-              else if someSelectedElementHave 'member' _id
-                i.fa.fa-ellipsis-h
+    each currentBoard.activeMembers
+      with getUser userId
+        li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
+          a.name.js-toggle-member-multiselection
+            +userAvatar(userId=this._id)
+            span.sidebar-list-item-description
+              = profile.fullname
+              | (<span class="username">{{ username }}</span>)
+            if allSelectedElementHave 'member' _id
+              i.fa.fa-check
+            else if someSelectedElementHave 'member' _id
+              i.fa.fa-ellipsis-h
   hr
+  a.sidebar-btn.js-move-selection
+    i.fa.fa-share
+    span {{_ 'move-selection'}}
   a.sidebar-btn.js-archive-selection
     i.fa.fa-archive
     span {{_ 'archive-selection'}}
@@ -82,3 +83,7 @@ template(name="disambiguateMultiMemberPopup")
   p {{_ 'what-to-do'}}
   button.wide.js-unassign-member {{_ 'unassign-member'}}
   button.wide.js-assign-member {{_ 'assign-member'}}
+
+template(name="moveSelectionPopup")
+  +boardLists
+

+ 9 - 0
client/components/sidebar/sidebarFilters.js

@@ -93,8 +93,10 @@ BlazeComponent.extendComponent({
           return popup.call(this.currentData(), evt);
         }
       },
+      'click .js-move-selection': Popup.open('moveSelection'),
       'click .js-archive-selection'() {
         mutateSelectedCards('archive');
+        EscapeActions.executeUpTo('multiselection');
       },
     }];
   },
@@ -121,3 +123,10 @@ Template.disambiguateMultiMemberPopup.events({
     Popup.close();
   },
 });
+
+Template.moveSelectionPopup.events({
+  'click .js-select-list'() {
+    mutateSelectedCards('move', this._id);
+    EscapeActions.executeUpTo('multiselection');
+  },
+});

+ 17 - 5
client/config/router.js

@@ -13,7 +13,10 @@ FlowRouter.route('/', {
     Filter.reset();
     EscapeActions.executeAll();
 
-    BlazeLayout.render('defaultLayout', { content: 'boardList' });
+    BlazeLayout.render('defaultLayout', {
+      headerBar: 'boardListHeaderBar',
+      content: 'boardList',
+    });
   },
 });
 
@@ -33,7 +36,10 @@ FlowRouter.route('/b/:id/:slug', {
       EscapeActions.executeUpTo('popup-close');
     }
 
-    BlazeLayout.render('defaultLayout', { content: 'board' });
+    BlazeLayout.render('defaultLayout', {
+      headerBar: 'boardHeaderBar',
+      content: 'board',
+    });
   },
 });
 
@@ -45,7 +51,10 @@ FlowRouter.route('/b/:boardId/:slug/:cardId', {
     Session.set('currentBoard', params.boardId);
     Session.set('currentCard', params.cardId);
 
-    BlazeLayout.render('defaultLayout', { content: 'board' });
+    BlazeLayout.render('defaultLayout', {
+      headerBar: 'boardHeaderBar',
+      content: 'board',
+    });
   },
 });
 
@@ -58,11 +67,14 @@ FlowRouter.route('/shortcuts', {
 
     if (previousPath) {
       Modal.open(shortcutsTemplate, {
+        header: 'shortcutsModalTitle',
         onCloseGoTo: previousPath,
       });
     } else {
-      // XXX There is currently no way to escape this page on Sandstorm
-      BlazeLayout.render('defaultLayout', { content: shortcutsTemplate });
+      BlazeLayout.render('defaultLayout', {
+        headerBar: 'shortcutsHeaderBar',
+        content: shortcutsTemplate,
+      });
     }
   },
 });

+ 9 - 3
client/lib/modal.js

@@ -6,8 +6,14 @@ window.Modal = new class {
     this._onCloseGoTo = '';
   }
 
+  getHeaderName() {
+    const currentModal = this._currentModal.get();
+    return currentModal && currentModal.header;
+  }
+
   getTemplateName() {
-    return this._currentModal.get();
+    const currentModal = this._currentModal.get();
+    return currentModal && currentModal.modalName;
   }
 
   isOpen() {
@@ -21,8 +27,8 @@ window.Modal = new class {
     }
   }
 
-  open(modalName, { onCloseGoTo = ''} = {}) {
-    this._currentModal.set(modalName);
+  open(modalName, { header = '', onCloseGoTo = ''} = {}) {
+    this._currentModal.set({ header, modalName });
     this._onCloseGoTo = onCloseGoTo;
   }
 };

+ 35 - 4
i18n/ar.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accept",
     "actions": "الإجراءات",
     "activities": "الأنشطة",
     "activity": "النشاط",
@@ -36,7 +37,7 @@
     "archive-card": "أرشف البطاقة",
     "archive-list": "أرشف هذه القائمة",
     "archive-selection": "أرشف المُحدّد",
-    "archiveBoardPopup-title": "غلق اللوحة ?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "عناصر في الأرشيف",
     "archives": "أرشيفات",
     "assign-member": "تعيين عضو",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "تعديل الصلاحيات",
     "click-to-star": "اضغط لإضافة اللوحة للمفضلة.",
     "click-to-unstar": "اضغط لحذف اللوحة من المفضلة.",
+    "clipboard": "Clipboard or drag & drop",
     "close": "غلق",
     "close-board": "غلق اللوحة",
-    "close-board-pop": "يمكنك إعادة فتح اللوحة بالنقر على  عنصر اللوحات من القائمة الفوقية، ثم اختيار -مشاهدة اللوحات المغلقة- ثم ستجد اللوحة و يمكنك إعادة فتحها",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "إنشاء لوحة",
     "createLabelPopup-title": "إنشاء علامة",
     "current": "الحالي",
+    "decline": "Decline",
     "default-avatar": "صورة شخصية افتراضية",
     "delete": "حذف",
     "deleteLabelPopup-title": "حذف العلامة ?",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "تحديد الإجراء على العلامة",
     "disambiguateMultiMemberPopup-title": "تحديد الإجراء على العضو",
     "discard": "التخلص منها",
+    "done": "Done",
     "download": "تنزيل",
     "edit": "تعديل",
     "edit-avatar": "تعديل الصورة الشخصية",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "تعديل العلامة",
     "editProfilePopup-title": "تعديل الملف الشخصي",
     "email": "البريد الإلكتروني",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "تصفية",
     "filter-cards": "تصفية البطاقات",
     "filter-clear": "مسح التصفية",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "معلومات",
     "initials": "أولية",
     "joined": "انضمّ",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "اختصار لوحة المفاتيح",
     "label-create": "إنشاء علامة جديدة",
     "label-default": "%s علامة (افتراضية)",
@@ -157,12 +182,12 @@
     "list-move-cards": "نقل بطاقات هذه القائمة",
     "list-select-cards": "تحديد بطاقات هذه القائمة",
     "listActionPopup-title": "قائمة الإجراءات",
-    "listArchiveCardsPopup-title": "أرشفة بطاقات القائمة ?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "نقل بطاقات القائمة",
     "lists": "القائمات",
     "log-out": "تسجيل الخروج",
     "loginPopup-title": "تسجيل الدخول",
+    "mapMembersPopup-title": "Map members",
+    "mapMembersAddPopup-title": "Select Wekan member",
     "memberMenuPopup-title": "أفضليات الأعضاء",
     "members": "أعضاء",
     "menu": "القائمة",
@@ -176,11 +201,16 @@
     "no-results": "لا توجد نتائج",
     "normal": "عادي",
     "normal-desc": "يمكن مشاهدة و تعديل  البطاقات. لا يمكن تغيير إعدادات الضبط.",
+    "not-accepted-yet": "Invitation not accepted yet",
     "optional": "اختياري",
     "or": "or",
     "page-maybe-private": "قدتكون هذه الصفحة خاصة . قد تستطيع مشاهدتها ب  <a href='%s'>تسجيل الدخول</a>.",
     "page-not-found": "صفحة غير موجودة",
     "password": "كلمة المرور",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "خاص",
     "private-desc": "هذه اللوحة خاصة . لا يسمح إلا للأعضاء .",
     "profile": "ملف شخصي",
@@ -220,6 +250,7 @@
     "title": "عنوان",
     "unassign-member": "إلغاء تعيين العضو",
     "unsaved-description": "لديك وصف غير محفوظ",
+    "upload": "Upload",
     "upload-avatar": "رفع صورة شخصية",
     "uploaded-avatar": "تم رفع الصورة الشخصية",
     "username": "اسم المستخدم",

+ 35 - 4
i18n/ca.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accept",
     "actions": "Accions",
     "activities": "Activitats",
     "activity": "Activitat",
@@ -36,7 +37,7 @@
     "archive-card": "Arxiva fitxa",
     "archive-list": "Arxiva aquesta llista",
     "archive-selection": "Arxiva selecció",
-    "archiveBoardPopup-title": "Tanca el tauler",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Elements arxivats",
     "archives": "Arxivats",
     "assign-member": "Assignar membre",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "Canvia permisos",
     "click-to-star": "Fes clic per destacar aquest tauler.",
     "click-to-unstar": "Fes clic per deixar de destacar aquest tauler.",
+    "clipboard": "Clipboard or drag & drop",
     "close": "Tanca",
     "close-board": "Tanca tauler",
-    "close-board-pop": "Podeu tornar a obrir el tauler fent clic al menú \"Taulers\" de la capçalera, seleccionar \"Veure Taulers Tancats \", cercar el tauler i fer clic a \"Tornar a obrir \".",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "Crea tauler",
     "createLabelPopup-title": "Crea etiqueta",
     "current": "Actual",
+    "decline": "Decline",
     "default-avatar": "Avatar per defecte",
     "delete": "Esborra",
     "deleteLabelPopup-title": "Esborra etiqueta",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Desfe l'ambigüitat en les etiquetes",
     "disambiguateMultiMemberPopup-title": "Desfe l'ambigüitat en els membres",
     "discard": "Descarta",
+    "done": "Done",
     "download": "Descarrega",
     "edit": "Edita",
     "edit-avatar": "Canvia Avatar",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "Canvia etiqueta",
     "editProfilePopup-title": "Edita teu Perfil",
     "email": "Correu electrònic",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "Filtre",
     "filter-cards": "Fitxes de filtre",
     "filter-clear": "Elimina filtre",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "Informacions",
     "initials": "Inicials",
     "joined": "s'ha unit",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "Dreceres de teclat",
     "label-create": "Crea una etiqueta nova",
     "label-default": "%s etiqueta (per defecte)",
@@ -157,12 +182,12 @@
     "list-move-cards": "Mou totes les fitxes d'aquesta llista",
     "list-select-cards": "Selecciona totes les fitxes d'aquesta llista",
     "listActionPopup-title": "Accions de la llista",
-    "listArchiveCardsPopup-title": "Arxivar totes les fitxes d'aquesta llista?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Moure totes les fitxes de la llista",
     "lists": "Llistes",
     "log-out": "Finalitza la  sessió",
     "loginPopup-title": "Inicia sessió",
+    "mapMembersPopup-title": "Map members",
+    "mapMembersAddPopup-title": "Select Wekan member",
     "memberMenuPopup-title": "Configura membres",
     "members": "Membres",
     "menu": "Menú",
@@ -176,11 +201,16 @@
     "no-results": "Sense resultats",
     "normal": "Normal",
     "normal-desc": "Podeu veure i editar fitxes. No podeu canviar la configuració.",
+    "not-accepted-yet": "Invitation not accepted yet",
     "optional": "opcional",
     "or": "or",
     "page-maybe-private": "Aquesta pàgina és privada. Per veure-la <a href='%s'> entra </a>.",
     "page-not-found": "Pàgina no trobada.",
     "password": "Contrasenya",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "Privat",
     "private-desc": "Aquest tauler és privat. Només les persones afegides al tauler poden veure´l i editar-lo.",
     "profile": "Perfil",
@@ -220,6 +250,7 @@
     "title": "Títol",
     "unassign-member": "Desassignar membre",
     "unsaved-description": "Tens una descripció sense desar.",
+    "upload": "Upload",
     "upload-avatar": "Actualitza avatar",
     "uploaded-avatar": "Avatar actualitzat",
     "username": "Nom d'Usuari",

+ 35 - 4
i18n/de.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accept",
     "actions": "Aktionen",
     "activities": "Aktivitäten",
     "activity": "Aktivität",
@@ -36,7 +37,7 @@
     "archive-card": "Karte archivieren",
     "archive-list": "Diese Liste archivieren",
     "archive-selection": "Auswahl archivieren",
-    "archiveBoardPopup-title": "Board schließen?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Archivierte Einträge",
     "archives": "Archive",
     "assign-member": "Mitglied zuweisen",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "Ändere Berechtigungen",
     "click-to-star": "Klicke, um dem Board einen Stern zu geben.",
     "click-to-unstar": "Klicke, um den Stern zu entfernen.",
+    "clipboard": "Clipboard or drag & drop",
     "close": "Schließen",
     "close-board": "Board schließen",
-    "close-board-pop": "Du kannst das Board wiederherstellen, indem du auf den \"Boards\" Menüeintrag im der Kopfleiste klickst, \"Zeige geschlossene Boards an\" auswählst, dein Board suchst und auf \"Wiederherstellen\" klickst.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "grün",
     "color-yellow": "gelb",
     "color-orange": "orange",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "Erstelle ein Board",
     "createLabelPopup-title": "Label erstellen",
     "current": "aktuell",
+    "decline": "Decline",
     "default-avatar": "Standard Profilbild",
     "delete": "Löschen",
     "deleteLabelPopup-title": "Label löschen?",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Labels vereinheitlichen",
     "disambiguateMultiMemberPopup-title": "Mitglieder vereinheitlichen",
     "discard": "Verwerfen",
+    "done": "Done",
     "download": "Download",
     "edit": "Bearbeiten",
     "edit-avatar": "Profilbild ändern",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "Ändere Label",
     "editProfilePopup-title": "Profil ändern",
     "email": "Email",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "Filter",
     "filter-cards": "Karten filtern",
     "filter-clear": "Filter entfernen",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "Informationen",
     "initials": "Initialien",
     "joined": "beigetreten",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "Tastaturkürzel",
     "label-create": "Neues Label erstellen.",
     "label-default": "%s Label (Standard)",
@@ -157,12 +182,12 @@
     "list-move-cards": "Alle Karten in dieser Liste verschieben",
     "list-select-cards": "Alle Karten in dieser Liste auswählen",
     "listActionPopup-title": "Listenaktionen",
-    "listArchiveCardsPopup-title": "Alle Karten in der Liste archivieren?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Verschiebe alle Karten in dieser Liste",
     "lists": "Listen",
     "log-out": "Ausloggen",
     "loginPopup-title": "Einloggen",
+    "mapMembersPopup-title": "Map members",
+    "mapMembersAddPopup-title": "Select Wekan member",
     "memberMenuPopup-title": "Nutzereinstellungen",
     "members": "Mitglied",
     "menu": "Menü",
@@ -176,11 +201,16 @@
     "no-results": "Keine Ergebnisse",
     "normal": "Normal",
     "normal-desc": "Kann Karten anschauen und bearbeiten, aber keine Einstellungen ändern.",
+    "not-accepted-yet": "Invitation not accepted yet",
     "optional": "optional",
     "or": "oder",
     "page-maybe-private": "Diese Seite könnte privat sein.  Vielleicht kannst du sie sehen, wenn du dich <a href='%s'>einloggst</a>.",
     "page-not-found": "Seite nicht gefunden.",
     "password": "Passwort",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "Privat",
     "private-desc": "Dieses Board ist privat. Nur Nutzer, die zu dem Board gehören, können es anschauen und bearbeiten.",
     "profile": "Profil",
@@ -220,6 +250,7 @@
     "title": "Titel",
     "unassign-member": "Mitglied abziehen",
     "unsaved-description": "Es gibt eine ungespeicherte Beschreibung.",
+    "upload": "Upload",
     "upload-avatar": "Profilbild hochladen",
     "uploaded-avatar": "Profilbild hochgeladen",
     "username": "Nutzername",

+ 13 - 13
i18n/en.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "Archive this list",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Archived Items",
     "archives": "Archives",
     "assign-member": "Assign member",
@@ -91,17 +91,17 @@
     "clipboard" : "Clipboard or drag & drop",
     "close": "Close",
     "close-board": "Close Board",
-    "close-board-pop": "You can re-open the board by clicking the “Boards” menu from the header, selecting “View Closed Boards”, finding the board and clicking “Re-open”.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
+    "color-black": "black",
+    "color-blue": "blue",
     "color-green": "green",
-    "color-yellow": "yellow",
+    "color-lime": "lime",
     "color-orange": "orange",
-    "color-red": "red",
+    "color-pink": "pink",
     "color-purple": "purple",
-    "color-blue": "blue",
+    "color-red": "red",
     "color-sky": "sky",
-    "color-lime": "lime",
-    "color-pink": "pink",
-    "color-black": "black",
+    "color-yellow": "yellow",
     "comment": "Comment",
     "comment-placeholder": "Write a comment",
     "computer": "Computer",
@@ -135,9 +135,9 @@
     "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.\n",
     "email-resetPassword-subject": "Reset your password on __url__",
     "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.\n",
+    "email-sent": "Email sent",
     "email-verifyEmail-subject": "Verify your email address on __url__",
     "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.\n",
-    "email-sent": "Email sent",
     "error-board-doesNotExist": "This board does not exist",
     "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
@@ -184,18 +184,18 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "List Actions",
-    "listArchiveCardsPopup-title": "Archive All Cards in this List?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Move All Cards in List",
     "lists": "Lists",
     "log-out": "Log Out",
     "loginPopup-title": "Log In",
-    "mapMembersPopup-title": "Map members",
     "mapMembersAddPopup-title": "Select Wekan member",
+    "mapMembersPopup-title": "Map members",
     "memberMenuPopup-title": "Member Settings",
     "members": "Members",
     "menu": "Menu",
+    "move-selection": "Move selection",
     "moveCardPopup-title": "Move Card",
+    "moveSelectionPopup-title": "Move selection",
     "multi-selection": "Multi-Selection",
     "multi-selection-on": "Multi-Selection is on",
     "my-boards": "My Boards",
@@ -214,8 +214,8 @@
     "password": "Password",
     "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
     "preview": "Preview",
-    "previewClipboardImagePopup-title": "Preview",
     "previewAttachedImagePopup-title": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
     "private": "Private",
     "private-desc": "This board is private. Only people added to the board can view and edit it.",
     "profile": "Profile",

+ 2 - 4
i18n/es.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "Archivar esta lista",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "¿Cerrar el tablero?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Items archivados",
     "archives": "Archives",
     "assign-member": "Assign member",
@@ -91,7 +91,7 @@
     "clipboard": "Clipboard or drag & drop",
     "close": "Cerrar",
     "close-board": "Cerrar el tablero",
-    "close-board-pop": "Para reabrir el tablero haz clic en el menú \"Tableros\" de la cabecera, selecciona \"Ver Tableros Cerrados\", busca el tablero  y haz clic en \"Reabrir\".",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -182,9 +182,7 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "Acciones de la lista",
-    "listArchiveCardsPopup-title": "¿Archivar todas las fichas de esta lista?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Trasladar todas las fichas de la lista",
     "lists": "Lists",
     "log-out": "Finalizar la sesion",
     "loginPopup-title": "Iniciar sesion",

+ 27 - 29
i18n/fi.i18n.json

@@ -1,5 +1,5 @@
 {
-    "accept": "Accept",
+    "accept": "Hyväksy",
     "actions": "Toimet",
     "activities": "Toimet",
     "activity": "Toiminta",
@@ -8,14 +8,14 @@
     "activity-attached": "liitetty %s kohteeseen %s",
     "activity-created": "luotu %s",
     "activity-excluded": "poistettu %s kohteesta %s",
-    "activity-imported": "imported %s into %s from %s",
-    "activity-imported-board": "imported %s from %s",
+    "activity-imported": "tuotu %s kohteeseen %s lähteestä %s",
+    "activity-imported-board": "tuotu %s lähteestä %s",
     "activity-joined": "liitytty kohteeseen %s",
     "activity-moved": "siirretty %s kohteesta %s kohteeseen %s",
     "activity-on": "kohteessa %s",
     "activity-removed": "poistettu %s kohteesta %s",
     "activity-sent": "lähetetty %s kohteeseen %s",
-    "activity-unjoined": "unjoined %s",
+    "activity-unjoined": "peruttu %s liityminen",
     "add": "Lisää",
     "add-attachment": "Lisää liitetiedosto",
     "add-board": "Lisää uusi taulu",
@@ -37,7 +37,7 @@
     "archive-card": "Arkistoi kortti",
     "archive-list": "Arkistoi tämä lista",
     "archive-selection": "Arkistoi valinta",
-    "archiveBoardPopup-title": "Sulje taulu?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Arkistoidut kohteet",
     "archives": "Arkistot",
     "assign-member": "Valitse jäsen",
@@ -56,7 +56,7 @@
     "boardChangeColorPopup-title": "Vaihda taulun tausta",
     "boardChangeTitlePopup-title": "Nimeä taulu uudelleen",
     "boardChangeVisibilityPopup-title": "Vaihda näkyvyyttä",
-    "boardImportBoardPopup-title": "Import board from Trello",
+    "boardImportBoardPopup-title": "Tuo taulu Trellosta",
     "boardMenuPopup-title": "Taulu valikko",
     "boards": "Taulut",
     "bucket-example": "Kuten “Laatikko lista” esimerkiksi",
@@ -78,7 +78,7 @@
     "cardMembersPopup-title": "Jäsenet",
     "cardMorePopup-title": "Lisää",
     "cards": "Kortit",
-    "change": "Change",
+    "change": "Muuta",
     "change-avatar": "Vaihda profiilikuva",
     "change-password": "Vaihda salasana",
     "change-permissions": "Muuta oikeuksia",
@@ -88,20 +88,20 @@
     "changePermissionsPopup-title": "Vaihda oikeuksia",
     "click-to-star": "Klikkaa merkataksesi tämä taulu tähdellä.",
     "click-to-unstar": "Klikkaa poistaaksesi tähtimerkintä taululta.",
-    "clipboard": "Clipboard or drag & drop",
+    "clipboard": "Leikepöytä tai raahaa ja pudota",
     "close": "Sulje",
     "close-board": "Sulje taulu",
-    "close-board-pop": "Voit uudelleenavata taulun klikkaamalla “Taulut” valikkoa ylätunnisteesta, valitsemalla “Näytä suljetut taulut”, löytämällä taulu ja klikkaamalla “Uudelleenavaa”.",
-    "color-green": "green",
-    "color-yellow": "yellow",
-    "color-orange": "orange",
-    "color-red": "red",
-    "color-purple": "purple",
-    "color-blue": "blue",
-    "color-sky": "sky",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
+    "color-green": "vihreä",
+    "color-yellow": "keltainen",
+    "color-orange": "oranssi",
+    "color-red": "punainen",
+    "color-purple": "violetti",
+    "color-blue": "sininen",
+    "color-sky": "taivas",
     "color-lime": "lime",
-    "color-pink": "pink",
-    "color-black": "black",
+    "color-pink": "vaaleanpunainen",
+    "color-black": "musta",
     "comment": "Kommentti",
     "comment-placeholder": "Kirjoita kommentti",
     "computer": "Tietokone",
@@ -109,7 +109,7 @@
     "createBoardPopup-title": "Luo taulu",
     "createLabelPopup-title": "Luo tunniste",
     "current": "nykyinen",
-    "decline": "Decline",
+    "decline": "Kieltäydy",
     "default-avatar": "Oletus profiilikuva",
     "delete": "Poista",
     "deleteLabelPopup-title": "Poista tunniste?",
@@ -117,7 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Yksikäsitteistä tunniste toiminta",
     "disambiguateMultiMemberPopup-title": "Yksikäsitteistä jäsen toiminta",
     "discard": "Hylkää",
-    "done": "Done",
+    "done": "Valmis",
     "download": "Lataa",
     "edit": "Muokkaa",
     "edit-avatar": "Vaihda profiilikuva",
@@ -125,13 +125,13 @@
     "editLabelPopup-title": "Vaihda tunniste",
     "editProfilePopup-title": "Muokkaa profiilia",
     "email": "Sähköposti",
-    "email-enrollAccount-subject": "An account created for you on __url__",
-    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
-    "email-fail": "Sending email failed",
-    "email-invalid": "Invalid email",
-    "email-invite": "Invite via Email",
-    "email-invite-subject": "__inviter__ sent you an invitation",
-    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-enrollAccount-subject": "Tili tehty sinulle osoitteessa __url__",
+    "email-enrollAccount-text": "Hei __user__,\n\nAlkaaksesi käyttämään palvelua, klikkaa vain allaolevaa linkkiä.\n\n__url__\n\nKiitos.",
+    "email-fail": "Sähköpostin lähettäminen epäonnistui",
+    "email-invalid": "Virheellinen sähköposti",
+    "email-invite": "Kutsu sähköpostilla",
+    "email-invite-subject": "__inviter__ lähetti sinulle kutsun",
+    "email-invite-text": "Hyvä __user__,\n\n__inviter__ kutsuu sinut liittymään taululle \"__board__\" yhteistyötä varten.\n\nOle hyvä ja seuraa allaolevaa linkkiä:\n\n__url__\n\nKiitos.",
     "email-resetPassword-subject": "Reset your password on __url__",
     "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
     "email-verifyEmail-subject": "Verify your email address on __url__",
@@ -182,9 +182,7 @@
     "list-move-cards": "Siirrä kaikki kortit tässä listassa",
     "list-select-cards": "Valitse kaikki kortit tässä listassa",
     "listActionPopup-title": "Listaa toimet",
-    "listArchiveCardsPopup-title": "Arkistoi kaikki kortit tässä listassa?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Siirrä kaikki listan kortit",
     "lists": "Listat",
     "log-out": "Kirjaudu ulos",
     "loginPopup-title": "Kirjaudu sisään",

+ 50 - 19
i18n/fr.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accepter",
     "actions": "Actions",
     "activities": "Activitées",
     "activity": "Activité",
@@ -7,8 +8,8 @@
     "activity-attached": "a attaché %s à %s",
     "activity-created": "a créé %s",
     "activity-excluded": "a exclu %s de %s",
-    "activity-imported": "imported %s into %s from %s",
-    "activity-imported-board": "imported %s from %s",
+    "activity-imported": "a importé %s vers %s depuis %s",
+    "activity-imported-board": "a importé %s depuis %s",
     "activity-joined": "a rejoint %s",
     "activity-moved": "a déplacé %s depuis %s vers %s",
     "activity-on": "sur %s",
@@ -36,7 +37,7 @@
     "archive-card": "Archiver la carte",
     "archive-list": "Archiver cette liste",
     "archive-selection": "Archiver la selection",
-    "archiveBoardPopup-title": "Fermer le tableau ?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Éléments archivés",
     "archives": "Archives",
     "assign-member": "Assigner un membre",
@@ -55,7 +56,7 @@
     "boardChangeColorPopup-title": "Change la fond du tableau",
     "boardChangeTitlePopup-title": "Renommer le tableau",
     "boardChangeVisibilityPopup-title": "Changer la visibilité",
-    "boardImportBoardPopup-title": "Import board from Trello",
+    "boardImportBoardPopup-title": "Importer le tableau depuis Trello",
     "boardMenuPopup-title": "Menu du tableau",
     "boards": "Tableaux",
     "bucket-example": "Comme « todo list » par exemple",
@@ -77,7 +78,7 @@
     "cardMembersPopup-title": "Membres",
     "cardMorePopup-title": "Plus",
     "cards": "Cartes",
-    "change": "Change",
+    "change": "Changer",
     "change-avatar": "Changer l'avatar",
     "change-password": "Changer le mot de passe",
     "change-permissions": "Changer les permissions",
@@ -87,19 +88,20 @@
     "changePermissionsPopup-title": "Changer les permissions",
     "click-to-star": "Cliquez pour ajouter ce tableau aux favoris.",
     "click-to-unstar": "Cliquez pour retirer ce tableau des favoris.",
+    "clipboard": "Clipboard or drag & drop",
     "close": "Fermer",
     "close-board": "Fermer le tableau",
-    "close-board-pop": "Vous pouvez ré-ouvrir le tableau en cliquant sur le menu « Tableau » dans la barre d'en-tête, puis en sélection « Voir les tableaux fermés », en trouvant le tableau désiré puis en cliquant sur « Ré-ouvrir ».",
-    "color-green": "green",
-    "color-yellow": "yellow",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
+    "color-green": "vert",
+    "color-yellow": "jaune",
     "color-orange": "orange",
-    "color-red": "red",
-    "color-purple": "purple",
-    "color-blue": "blue",
-    "color-sky": "sky",
-    "color-lime": "lime",
-    "color-pink": "pink",
-    "color-black": "black",
+    "color-red": "rouge",
+    "color-purple": "violet",
+    "color-blue": "bleu",
+    "color-sky": "ciel",
+    "color-lime": "citron vert",
+    "color-pink": "rose",
+    "color-black": "noir",
     "comment": "Commentaire",
     "comment-placeholder": "Rédiger un commentaire",
     "computer": "Ordinateur",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "Créer un tableau",
     "createLabelPopup-title": "Créer un étiquette",
     "current": "courant",
+    "decline": "Refuser",
     "default-avatar": "Avatar par défaut",
     "delete": "Supprimer",
     "deleteLabelPopup-title": "Supprimer l'étiquette ?",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Préciser l'action sur l'étiquette",
     "disambiguateMultiMemberPopup-title": "Préciser l'action sur le membre",
     "discard": "Mettre à la corbeille",
+    "done": "Fait",
     "download": "Télécharger",
     "edit": "Éditer",
     "edit-avatar": "Changer l'avatar",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "Changer l'étiquette",
     "editProfilePopup-title": "Éditer le profil",
     "email": "Email",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "Filtrer",
     "filter-cards": "Filtrer les cartes",
     "filter-clear": "Retirer les filtres",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "Infos",
     "initials": "Initiales",
     "joined": "a joint",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "Raccourcis clavier",
     "label-create": "Créer une nouvelle étiquette",
     "label-default": "%s label (default)",
@@ -157,18 +182,18 @@
     "list-move-cards": "Déplacer les cartes de cette liste",
     "list-select-cards": "Sélectionner les cartes de cette liste",
     "listActionPopup-title": "Liste des actions",
-    "listArchiveCardsPopup-title": "Archiver les cartes de la liste ?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Déplacer les cartes de la liste",
     "lists": "Listes",
     "log-out": "Déconnexion",
     "loginPopup-title": "Connexion",
+    "mapMembersPopup-title": "Associer les membres",
+    "mapMembersAddPopup-title": "Sélectioner le membre Wekan",
     "memberMenuPopup-title": "Préférence de membre",
     "members": "Membres",
     "menu": "Menu",
     "moveCardPopup-title": "Déplacer la carte",
     "multi-selection": "Sélection multiple",
-    "multi-selection-on": "Multi-Selection is on",
+    "multi-selection-on": "Multi-Selection active",
     "my-boards": "Mes tableaux",
     "name": "Nom",
     "no-archived-cards": "Pas de carte archivée.",
@@ -176,11 +201,16 @@
     "no-results": "Pas de résultats",
     "normal": "Normal",
     "normal-desc": "Peut voir et éditer les cartes. Ne peut pas changer les paramètres.",
+    "not-accepted-yet": "L’invitation n’a pas encore été acceptée",
     "optional": "optionnel",
-    "or": "or",
+    "or": "ou",
     "page-maybe-private": "Cette page est peut-être privée. Vous pourrez peut-être la voir en vous <a href='%s'>connectant</a>.",
     "page-not-found": "Page non trouvée",
     "password": "Mot de passe",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "Privé",
     "private-desc": "Ce tableau est privé. Seul les membres peuvent y accéder.",
     "profile": "Profil",
@@ -220,6 +250,7 @@
     "title": "Titre",
     "unassign-member": "Retirer le membre",
     "unsaved-description": "Vous avez une description non sauvegardée",
+    "upload": "Upload",
     "upload-avatar": "Télécharger un avatar",
     "uploaded-avatar": "Avatar téléchargé",
     "username": "Nom d'utilisateur",

+ 35 - 4
i18n/it.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accept",
     "actions": "Azioni",
     "activities": "Attività",
     "activity": "Attività",
@@ -36,7 +37,7 @@
     "archive-card": "Archivia scheda",
     "archive-list": "Archivia questa lista",
     "archive-selection": "Archivia selezione",
-    "archiveBoardPopup-title": "Chiudere la bacheca?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Elementi archiviati",
     "archives": "Archives",
     "assign-member": "Assegna membri",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "Change Permissions",
     "click-to-star": "Click to star this board.",
     "click-to-unstar": "Click to unstar this board.",
+    "clipboard": "Clipboard or drag & drop",
     "close": "Close",
     "close-board": "Close Board",
-    "close-board-pop": "You can re-open the board by clicking the “Boards” menu from the header, selecting “View Closed Boards”, finding the board and clicking “Re-open”.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "Create Board",
     "createLabelPopup-title": "Create Label",
     "current": "current",
+    "decline": "Decline",
     "default-avatar": "Default avatar",
     "delete": "Delete",
     "deleteLabelPopup-title": "Delete Label?",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
     "disambiguateMultiMemberPopup-title": "Disambiguate Member Action",
     "discard": "Discard",
+    "done": "Done",
     "download": "Download",
     "edit": "Edit",
     "edit-avatar": "Change Avatar",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "Change Label",
     "editProfilePopup-title": "Edit Profile",
     "email": "Email",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "Filter",
     "filter-cards": "Filter Cards",
     "filter-clear": "Clear filter",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "Infos",
     "initials": "Initials",
     "joined": "joined",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "Keyboard shortcuts",
     "label-create": "Create a new label",
     "label-default": "%s label (default)",
@@ -157,12 +182,12 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "List Actions",
-    "listArchiveCardsPopup-title": "Archive All Cards in this List?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Move All Cards in List",
     "lists": "Lists",
     "log-out": "Log Out",
     "loginPopup-title": "Log In",
+    "mapMembersPopup-title": "Map members",
+    "mapMembersAddPopup-title": "Select Wekan member",
     "memberMenuPopup-title": "Member Settings",
     "members": "Membr",
     "menu": "Menu",
@@ -176,11 +201,16 @@
     "no-results": "No results",
     "normal": "Normal",
     "normal-desc": "Can view and edit cards. Can't change settings.",
+    "not-accepted-yet": "Invitation not accepted yet",
     "optional": "optional",
     "or": "or",
     "page-maybe-private": "This page may be private. You may be able to view it by <a href='%s'>logging in</a>.",
     "page-not-found": "Page not found.",
     "password": "Password",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "Private",
     "private-desc": "This board is private. Only people added to the board can view and edit it.",
     "profile": "Profile",
@@ -220,6 +250,7 @@
     "title": "Title",
     "unassign-member": "Unassign member",
     "unsaved-description": "You have an unsaved description.",
+    "upload": "Upload",
     "upload-avatar": "Upload an avatar",
     "uploaded-avatar": "Uploaded an avatar",
     "username": "Username",

+ 2 - 4
i18n/ja.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "このリストをアーカイブ",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "ボードを閉じますか?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "アーカイブされたアイテム",
     "archives": "Archives",
     "assign-member": "Assign member",
@@ -91,7 +91,7 @@
     "clipboard": "Clipboard or drag & drop",
     "close": "閉じる",
     "close-board": "Close Board",
-    "close-board-pop": "ヘッダーの\"ボード\"メニューから\"閉じたボードを見る\"を選択し、そこでボードを選択して、\"ボードの再開\"をクリックすると、ボードを再度利用できるようになります。",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -182,9 +182,7 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "操作一覧",
-    "listArchiveCardsPopup-title": "このリスト内の善カードをアーカイブしますか?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "リスト内のすべてのカードを移動する",
     "lists": "Lists",
     "log-out": "ログアウト",
     "loginPopup-title": "ログイン",

+ 2 - 4
i18n/ko.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "이 목록 보관",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "보드를 닫습니까?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "보관된 아이템",
     "archives": "Archives",
     "assign-member": "Assign member",
@@ -91,7 +91,7 @@
     "clipboard": "Clipboard or drag & drop",
     "close": "닫기",
     "close-board": "Close Board",
-    "close-board-pop": "보드를 다시 열 수 있습니다. 상단 \"보드\" 메뉴를 클릭해 \"닫힌 보드 보기\"를 선택하여, 보드를 찾아 \"다시 열기\" 버튼을 클릭합니다.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -182,9 +182,7 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "동작 목록",
-    "listArchiveCardsPopup-title": "목록에서 모든 카드를 보관합니까?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "목록에서 모든 카드 이동",
     "lists": "Lists",
     "log-out": "로그아웃",
     "loginPopup-title": "로그인",

+ 2 - 4
i18n/pt-BR.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Arquivar Cartão",
     "archive-list": "Arquivar esta lista",
     "archive-selection": "Arquivar seleção",
-    "archiveBoardPopup-title": "Fechar Quadro?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Itens Arquivados",
     "archives": "Arquivos",
     "assign-member": "Atribuir Membro",
@@ -91,7 +91,7 @@
     "clipboard": "Clipboard or drag & drop",
     "close": "Fechar",
     "close-board": "Fechar Quadro",
-    "close-board-pop": "Você pode reabrir um quadro clicando em “Quadros” no menu no cabeçalho, selecionando “Exibir Quadros Fechados”, encontrando-o e clicando em “Reabrir”.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -182,9 +182,7 @@
     "list-move-cards": "Mover todos os cartões desta lista",
     "list-select-cards": "Selecionar todos os cartões nesta lista",
     "listActionPopup-title": "Listar Ações",
-    "listArchiveCardsPopup-title": "Arquivar Todos Os Cartões Nesta Lista?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Mover Todos Os Cartões Nesta Lista",
     "lists": "Listas",
     "log-out": "Sair",
     "loginPopup-title": "Entrar",

+ 35 - 4
i18n/ru.i18n.json

@@ -1,4 +1,5 @@
 {
+    "accept": "Accept",
     "actions": "Действия",
     "activities": "Activities",
     "activity": "Активность",
@@ -36,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "Архивировать список",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "Закрыть доску?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Объекты в архиве",
     "archives": "Archives",
     "assign-member": "Assign member",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "Изменить настройки доступа",
     "click-to-star": "Отметить как «Избранное»",
     "click-to-unstar": "Снять отметку",
+    "clipboard": "Clipboard or drag & drop",
     "close": "Закрыть",
     "close-board": "Close Board",
-    "close-board-pop": "Вы сможете снова открыть доску нажав кнопку \"Доски\" в верхнем меню и выбрав \"Показать скрытые доски\".",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -107,6 +109,7 @@
     "createBoardPopup-title": "Создать доску",
     "createLabelPopup-title": "Создать метку",
     "current": "current",
+    "decline": "Decline",
     "default-avatar": "Default avatar",
     "delete": "Удалить",
     "deleteLabelPopup-title": "Удалить метку?",
@@ -114,6 +117,7 @@
     "disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
     "disambiguateMultiMemberPopup-title": "Disambiguate Member Action",
     "discard": "Discard",
+    "done": "Done",
     "download": "Скачать",
     "edit": "Редактировать",
     "edit-avatar": "Изменить аватар",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "Редактирование метки",
     "editProfilePopup-title": "Edit Profile",
     "email": "Эл.почта",
+    "email-enrollAccount-subject": "An account created for you on __url__",
+    "email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-fail": "Sending email failed",
+    "email-invalid": "Invalid email",
+    "email-invite": "Invite via Email",
+    "email-invite-subject": "__inviter__ sent you an invitation",
+    "email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
+    "email-resetPassword-subject": "Reset your password on __url__",
+    "email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-verifyEmail-subject": "Verify your email address on __url__",
+    "email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
+    "email-sent": "Email sent",
+    "error-board-doesNotExist": "This board does not exist",
+    "error-board-notAdmin": "You need to be admin of this board to do that",
     "error-board-notAMember": "You need to be a member of this board to do that",
     "error-json-malformed": "Your text is not valid JSON",
     "error-json-schema": "Your JSON data does not include the proper information in the correct format",
     "error-list-doesNotExist": "This list does not exist",
+    "error-user-doesNotExist": "This user does not exist",
+    "error-user-notAllowSelf": "This action on self is not allowed",
+    "error-user-notCreated": "This user is not created",
     "filter": "Filter",
     "filter-cards": "Фильтр",
     "filter-clear": "Clear filter",
@@ -140,9 +161,13 @@
     "import-card": "Import a Trello card",
     "import-card-trello-instruction": "Go to a Trello card, select 'Share and more...' then 'Export JSON' and copy the resulting text",
     "import-json-placeholder": "Paste your valid JSON data here",
+    "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
+    "import-show-user-mapping": "Review members mapping",
+    "import-user-select": "Pick the Wekan user you want to use as this member",
     "info": "Информация",
     "initials": "Initials",
     "joined": "вступил",
+    "just-invited": "You are just invited to this board",
     "keyboard-shortcuts": "Keyboard shortcuts",
     "label-create": "Создать метку",
     "label-default": "%s",
@@ -157,12 +182,12 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "Список действий",
-    "listArchiveCardsPopup-title": "Архивировать все карточки в списке?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Перенос карточек",
     "lists": "Lists",
     "log-out": "Выйти",
     "loginPopup-title": "Войти",
+    "mapMembersPopup-title": "Map members",
+    "mapMembersAddPopup-title": "Select Wekan member",
     "memberMenuPopup-title": "Member Settings",
     "members": "Участники",
     "menu": "Меню",
@@ -176,11 +201,16 @@
     "no-results": "Ничего не найдено",
     "normal": "Обычный",
     "normal-desc": "Может редактировать карточки. Не может управлять настройками.",
+    "not-accepted-yet": "Invitation not accepted yet",
     "optional": "не обязательно",
     "or": "or",
     "page-maybe-private": "Возможно, эта страница скрыта от незарегистрированных пользователей. Попробуйте <a href='%s'>войти на сайт</a>.",
     "page-not-found": "Страница не найдена.",
     "password": "Пароль",
+    "paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
+    "preview": "Preview",
+    "previewClipboardImagePopup-title": "Preview",
+    "previewAttachedImagePopup-title": "Preview",
     "private": "Закрытая",
     "private-desc": "Эта доска с ограниченным доступом. Только участники могут работать с ней.",
     "profile": "Профиль",
@@ -220,6 +250,7 @@
     "title": "Название",
     "unassign-member": "Unassign member",
     "unsaved-description": "You have an unsaved description.",
+    "upload": "Upload",
     "upload-avatar": "Upload an avatar",
     "uploaded-avatar": "Uploaded an avatar",
     "username": "Имя пользователя",

+ 2 - 4
i18n/tr.i18n.json

@@ -37,7 +37,7 @@
     "archive-card": "Archive Card",
     "archive-list": "Bu listeyi arşivle",
     "archive-selection": "Archive selection",
-    "archiveBoardPopup-title": "Pano Kapatılsın mı?",
+    "archiveBoardPopup-title": "Archive Board?",
     "archived-items": "Arşivlenmiş Öğeler",
     "archives": "Arşiv",
     "assign-member": "Assign member",
@@ -91,7 +91,7 @@
     "clipboard": "Clipboard or drag & drop",
     "close": "Kapat",
     "close-board": "Close Board",
-    "close-board-pop": "You can re-open the board by clicking the “Boards” menu from the header, selecting “View Closed Boards”, finding the board and clicking “Re-open”.",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "green",
     "color-yellow": "yellow",
     "color-orange": "orange",
@@ -182,9 +182,7 @@
     "list-move-cards": "Move all cards in this list",
     "list-select-cards": "Select all cards in this list",
     "listActionPopup-title": "Liste İşlemleri",
-    "listArchiveCardsPopup-title": "Bu Listedeki Tüm Kartlar Taşınsın mı?",
     "listImportCardPopup-title": "Import a Trello card",
-    "listMoveCardsPopup-title": "Listedeki Tüm Kartları Taşıma",
     "lists": "Lists",
     "log-out": "Oturum Kapat",
     "loginPopup-title": "Oturum Aç",

+ 76 - 45
i18n/zh-CN.i18n.json

@@ -1,10 +1,11 @@
 {
-    "actions": "动作",
+    "accept": "接受",
+    "actions": "操作",
     "activities": "活动",
     "activity": "活动",
     "activity-added": "添加 %s 至 %s",
-    "activity-archived": "归档 %s",
-    "activity-attached": "附加 %s 至 %s",
+    "activity-archived": "删除 %s",
+    "activity-attached": "添加附件 %s 至 %s",
     "activity-created": "创建 %s",
     "activity-excluded": "排除 %s 从 %s",
     "activity-imported": "导入 %s 至 %s 从 %s 中",
@@ -21,28 +22,28 @@
     "add-card": "添加卡片",
     "add-cover": "添加封面",
     "add-label": "添加标签",
-    "add-list": "添加列表",
+    "add-list": "添加清单",
     "add-members": "添加成员",
     "added": "添加",
     "addMemberPopup-title": "成员",
     "admin": "管理员",
     "admin-desc": "可以浏览并编辑卡片,移除成员,并且更改该看板的设置",
     "all-boards": "全部看板",
-    "and-n-other-card": "和另外 __count__ 个卡片",
-    "and-n-other-card_plural": "和另外 __count__ 个卡片",
-    "archive": "归档",
-    "archive-all": "全部归档",
-    "archive-board": "归档看板",
-    "archive-card": "归档卡片",
-    "archive-list": "归档该列表",
-    "archive-selection": "归档选中内容",
-    "archiveBoardPopup-title": "关闭看板?",
-    "archived-items": "归档条目",
-    "archives": "归档",
-    "assign-member": "分配员",
+    "and-n-other-card": "和其他 __count__ 个卡片",
+    "and-n-other-card_plural": "和其他 __count__ 个卡片",
+    "archive": "删除",
+    "archive-all": "全部删除",
+    "archive-board": "删除看板",
+    "archive-card": "删除卡片",
+    "archive-list": "删除该清单",
+    "archive-selection": "删除所选内容",
+    "archiveBoardPopup-title": "Archive Board?",
+    "archived-items": "回收箱",
+    "archives": "回收箱",
+    "assign-member": "分配员",
     "attached": "附加",
     "attachment": "附件",
-    "attachment-delete-pop": "删除附件操作不可逆。",
+    "attachment-delete-pop": "删除附件操作不可逆。",
     "attachmentDeletePopup-title": "删除附件?",
     "attachments": "附件",
     "avatar-too-big": "头像太大 (最大 70 Kb)",
@@ -50,8 +51,8 @@
     "board-change-color": "更改颜色",
     "board-nb-stars": "%s 星标",
     "board-not-found": "看板不存在",
-    "board-private-info": "该看板将被 <strong>私有</strong>.",
-    "board-public-info": "该看板将 <strong>公开</strong>.",
+    "board-private-info": "该看板将被设为 <strong>私有</strong>.",
+    "board-public-info": "该看板将被设为 <strong>公开</strong>.",
     "boardChangeColorPopup-title": "修改看板背景",
     "boardChangeTitlePopup-title": "重命名看板",
     "boardChangeVisibilityPopup-title": "更改可视级别",
@@ -60,18 +61,18 @@
     "boards": "看板",
     "bucket-example": "例如 “目标清单”",
     "cancel": "取消",
-    "card-archived": "该卡片已被归档",
-    "card-comments-title": "该卡片有 %s 条评论",
-    "card-delete-notice": "删除操作不可恢复,你将会丢失该卡片的所有相关动作。",
+    "card-archived": "该卡片已被删除",
+    "card-comments-title": "该卡片有 %s 条评论",
+    "card-delete-notice": "彻底删除的操作不可恢复,你将会丢失该卡片相关的所有操作记录。",
     "card-delete-pop": "所有的动作将从活动动态中被移除且您将无法重新打开该卡片。此操作无法撤销。",
-    "card-delete-suggest-archive": "你可以通过归档一个卡片来将它从看板中移除且保留活动。",
+    "card-delete-suggest-archive": "你可以将卡片从看板中删除至回收箱,但保留相关活动。",
     "card-edit-attachments": "编辑附件",
     "card-edit-labels": "编辑标签",
     "card-edit-members": "编辑成员",
     "card-labels-title": "更改该卡片上的标签",
     "card-members-title": "在该卡片中添加或移除看板成员",
-    "cardAttachmentsPopup-title": "附件位置",
-    "cardDeletePopup-title": "删除卡片?",
+    "cardAttachmentsPopup-title": "附件来源",
+    "cardDeletePopup-title": "彻底删除卡片?",
     "cardDetailsActionsPopup-title": "卡片动作",
     "cardLabelsPopup-title": "标签",
     "cardMembersPopup-title": "成员",
@@ -87,9 +88,10 @@
     "changePermissionsPopup-title": "更改权限",
     "click-to-star": "点此来标记该看板",
     "click-to-unstar": "点此来去除该看板的标记",
+    "clipboard": "剪贴板或者拖放文件",
     "close": "关闭",
     "close-board": "关闭看板",
-    "close-board-pop": "你可以通过点击头部的\"看板\"菜单,选择\"浏览已关闭看板\",查找看板并且点击\"重开\"来重开看板。",
+    "close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
     "color-green": "绿色",
     "color-yellow": "黄色",
     "color-orange": "橙色",
@@ -107,13 +109,15 @@
     "createBoardPopup-title": "创建看板",
     "createLabelPopup-title": "创建标签",
     "current": "当前",
+    "decline": "拒绝",
     "default-avatar": "默认头像",
-    "delete": "删除",
+    "delete": "彻底删除",
     "deleteLabelPopup-title": "删除标签?",
     "description": "描述",
     "disambiguateMultiLabelPopup-title": "消除标签动作歧义",
     "disambiguateMultiMemberPopup-title": "消除会员动作歧义",
     "discard": "放弃",
+    "done": "完成",
     "download": "下载",
     "edit": "编辑",
     "edit-avatar": "更改头像",
@@ -121,10 +125,27 @@
     "editLabelPopup-title": "更改标签",
     "editProfilePopup-title": "编辑资料",
     "email": "邮箱",
-    "error-board-notAMember": "需要成为看板成员才能执行此动作",
+    "email-enrollAccount-subject": "已为您在 __url__ 创建帐号",
+    "email-enrollAccount-text": "尊敬的 __user__,\n\n点击下面的链接,即刻开始使用这项服务。\n\n__url__\n\n谢谢。",
+    "email-fail": "邮件发送失败",
+    "email-invalid": "邮件地址错误",
+    "email-invite": "发送邮件邀请",
+    "email-invite-subject": "__inviter__ 向您发出邀请",
+    "email-invite-text": "尊敬的 __user__,\n\n__inviter__ 邀请您加入看板 \"__board__\" 参与协作。\n\n请点击下面的链接访问看板:\n\n__url__\n\n谢谢。",
+    "email-resetPassword-subject": "重置您的 __url__ 密码",
+    "email-resetPassword-text": "尊敬的 __user__,\n\n点击下面的链接,重置您的密码:\n\n__url__\n\n谢谢。",
+    "email-verifyEmail-subject": "在 __url__ 验证您的邮件地址",
+    "email-verifyEmail-text": "尊敬的 __user__,\n\n点击下面的链接,验证您的邮件地址:\n\n__url__\n\n谢谢。",
+    "email-sent": "邮件已发送",
+    "error-board-doesNotExist": "该看板不存在",
+    "error-board-notAdmin": "需要成为管理员才能执行此操作",
+    "error-board-notAMember": "需要成为看板成员才能执行此操作",
     "error-json-malformed": "文本不是合法的 JSON",
     "error-json-schema": "JSON 数据没有用正确的格式包含合适的信息",
     "error-list-doesNotExist": "不存在此列表",
+    "error-user-doesNotExist": "该用户不存在",
+    "error-user-notAllowSelf": "不允许对自己执行此操作",
+    "error-user-notCreated": "该用户未能成功创建",
     "filter": "过滤",
     "filter-cards": "过滤卡片",
     "filter-clear": "清空过滤器",
@@ -140,9 +161,13 @@
     "import-card": "导入 Trello 卡片",
     "import-card-trello-instruction": "进入一个 Trello 卡片,选择“分享与更多”,然后选择 “导出为 JSON” 并且拷贝结果文本",
     "import-json-placeholder": "粘贴您有效的 JSON 数据至此",
+    "import-members-map": "您导入的看板有一些成员。请将您想导入的成员映射到 Wekan 用户。",
+    "import-show-user-mapping": "核对成员映射",
+    "import-user-select": "选择您想将此成员映射到的 Wekan 用户",
     "info": "信息",
-    "initials": "首字母",
+    "initials": "缩写",
     "joined": "关联",
+    "just-invited": "您刚刚被邀请加入此看板",
     "keyboard-shortcuts": "键盘快捷键",
     "label-create": "创建新标签",
     "label-default": "%s 标签 (默认)",
@@ -152,17 +177,17 @@
     "last-admin-desc": "你不能更改角色,因为至少需要一名管理员。",
     "leave-board": "离开面板",
     "link-card": "关联至该卡片",
-    "list-archive-cards": "归档列表中的所有卡片",
-    "list-archive-cards-pop": "这将会从本看板中移除该列表中的所有卡片。如果需要浏览已归档的卡片并且将其恢复至看板,请点击\"菜单\">\"归档项\"",
-    "list-move-cards": "移动列表中的所有卡片",
-    "list-select-cards": "选择列表中的所有卡片",
-    "listActionPopup-title": "列出动作",
-    "listArchiveCardsPopup-title": "归档该列表中的所有卡片?",
+    "list-archive-cards": "删除清单中的所有卡片",
+    "list-archive-cards-pop": "这将会从本看板中移除该清单中的所有卡片。如果需要浏览已删除的卡片并且将其恢复至看板,请点击\"菜单\">\"回收箱\"",
+    "list-move-cards": "移动清单中的所有卡片",
+    "list-select-cards": "选择清单中的所有卡片",
+    "listActionPopup-title": "清单操作",
     "listImportCardPopup-title": "导入 Trello 卡片",
-    "listMoveCardsPopup-title": "移动该列表的所有卡片",
-    "lists": "列表",
+    "lists": "清单",
     "log-out": "登出",
     "loginPopup-title": "登录",
+    "mapMembersPopup-title": "映射成员",
+    "mapMembersAddPopup-title": "选择 Wekan 成员",
     "memberMenuPopup-title": "成员设置",
     "members": "成员",
     "menu": "菜单",
@@ -171,28 +196,33 @@
     "multi-selection-on": "多选启用",
     "my-boards": "我的看板",
     "name": "名称",
-    "no-archived-cards": "无归档的卡片",
-    "no-archived-lists": "无归档的列表",
+    "no-archived-cards": "没有已删除的卡片",
+    "no-archived-lists": "没有已删除的清单",
     "no-results": "无结果",
     "normal": "普通",
     "normal-desc": "可以创建以及编辑卡片,无法更改设置。",
+    "not-accepted-yet": "邀请尚未接受",
     "optional": "可选",
     "or": "或",
     "page-maybe-private": "本页面被设为私有. 您必须 <a href='%s'>登录</a>以浏览其中内容。",
     "page-not-found": "页面不存在。",
     "password": "密码",
+    "paste-or-dragdrop": "从剪贴板粘贴,或者拖放文件到它上面 (仅限于图片)",
+    "preview": "预览",
+    "previewClipboardImagePopup-title": "预览",
+    "previewAttachedImagePopup-title": "预览",
     "private": "私有",
-    "private-desc": "该看板将被设为私有看板。只有该看板成员才可以进行查看和编辑。",
+    "private-desc": "该看板将被设为私有。只有该看板成员才可以进行查看和编辑。",
     "profile": "资料",
-    "public": "公共",
-    "public-desc": "该看板将被公共。任何人均可通过链接查看,并且将对Google和其他搜索引擎开放,只有添加至该看板的成员才可进行编辑。",
-    "quick-access-description": "星标一个看板导航条中添加一个快捷方式",
+    "public": "公",
+    "public-desc": "该看板将被公开。任何人均可通过链接查看,并且将对Google和其他搜索引擎开放。只有添加至该看板的成员才可进行编辑。",
+    "quick-access-description": "星标看板在导航条中添加快捷方式",
     "remove-cover": "移除封面",
     "remove-from-board": "从看板中删除",
     "remove-label": "移除标签",
     "remove-member": "移除成员",
     "remove-member-from-card": "从该卡片中移除",
-    "remove-member-pop": "欲从 __boardTitle__ 中移除 __name__ (__username__) ? 该成员将会从该看板的所有卡片中被移除,他将会收到一条提醒。",
+    "remove-member-pop": "确定从 __boardTitle__ 中移除 __name__ (__username__) 吗? 该成员将被从该看板的所有卡片中移除,同时他会收到一条提醒。",
     "removeMemberPopup-title": "删除成员?",
     "rename": "重命名",
     "rename-board": "重命名看板",
@@ -220,10 +250,11 @@
     "title": "标题",
     "unassign-member": "取消分配成员",
     "unsaved-description": "存在未保存的描述",
+    "upload": "上传",
     "upload-avatar": "上传头像",
     "uploaded-avatar": "头像已经上传",
     "username": "用户名",
     "view-it": "查看",
-    "warn-list-archived": "警告: 卡片位于一个归档列表",
+    "warn-list-archived": "警告: 该卡片位于已删除的清单中",
     "what-to-do": "要做什么?"
 }

+ 27 - 32
models/boards.js

@@ -142,6 +142,14 @@ Boards.helpers({
     return _.pluck(this.members, 'userId').indexOf(memberId);
   },
 
+  hasMember(memberId) {
+    return !!_.findWhere(this.members, {userId: memberId, isActive: true});
+  },
+
+  hasAdmin(memberId) {
+    return !!_.findWhere(this.members, {userId: memberId, isActive: true, isAdmin: true});
+  },
+
   absoluteUrl() {
     return FlowRouter.path('board', { id: this._id, slug: this.slug });
   },
@@ -213,34 +221,23 @@ Boards.mutations({
 
   addMember(memberId) {
     const memberIndex = this.memberIndex(memberId);
-    if (memberIndex === -1) {
-      const xIndex = this.memberIndex('x');
-      if (xIndex === -1) {
-        return {
-          $push: {
-            members: {
-              userId: memberId,
-              isAdmin: false,
-              isActive: true,
-            },
-          },
-        };
-      } else {
-        return {
-          $set: {
-            [`members.${xIndex}.userId`]: memberId,
-            [`members.${xIndex}.isActive`]: true,
-            [`members.${xIndex}.isAdmin`]: false,
-          },
-        };
-      }
-    } else {
+    if (memberIndex >= 0) {
       return {
         $set: {
           [`members.${memberIndex}.isActive`]: true,
         },
       };
     }
+
+    return {
+      $push: {
+        members: {
+          userId: memberId,
+          isAdmin: false,
+          isActive: true,
+        },
+      },
+    };
   },
 
   removeMember(memberId) {
@@ -248,22 +245,20 @@ Boards.mutations({
 
     // we do not allow the only one admin to be removed
     const allowRemove = (!this.members[memberIndex].isAdmin) || (this.activeAdmins().length > 1);
-
-    if (allowRemove) {
-      return {
-        $set: {
-          [`members.${memberIndex}.userId`]: 'x',
-          [`members.${memberIndex}.isActive`]: false,
-          [`members.${memberIndex}.isAdmin`]: false,
-        },
-      };
-    } else {
+    if (!allowRemove) {
       return {
         $set: {
           [`members.${memberIndex}.isActive`]: true,
         },
       };
     }
+
+    return {
+      $set: {
+        [`members.${memberIndex}.isActive`]: false,
+        [`members.${memberIndex}.isAdmin`]: false,
+      },
+    };
   },
 
   setMemberPermission(memberId, isAdmin) {

+ 2 - 6
models/users.js

@@ -12,16 +12,12 @@ if (Meteor.isClient) {
   Users.helpers({
     isBoardMember() {
       const board = Boards.findOne(Session.get('currentBoard'));
-      return board &&
-        _.contains(_.pluck(board.members, 'userId'), this._id) &&
-        _.where(board.members, {userId: this._id})[0].isActive;
+      return board && board.hasMember(this._id);
     },
 
     isBoardAdmin() {
       const board = Boards.findOne(Session.get('currentBoard'));
-      return board &&
-        this.isBoardMember(board) &&
-        _.where(board.members, {userId: this._id})[0].isAdmin;
+      return board && board.hasAdmin(this._id);
     },
   });
 }

+ 1 - 1
sandstorm-pkgdef.capnp

@@ -25,7 +25,7 @@ const pkgdef :Spk.PackageDefinition = (
     appVersion = 7,
     # Increment this for every release.
 
-    appMarketingVersion = (defaultText = "0.10.0-RC1"),
+    appMarketingVersion = (defaultText = "0.10-rc3"),
     # Human-readable presentation of the app version.
 
     minUpgradableAppVersion = 0,

+ 29 - 17
sandstorm.js

@@ -3,24 +3,24 @@
 const isSandstorm = Meteor.settings && Meteor.settings.public &&
                     Meteor.settings.public.sandstorm;
 
-if (isSandstorm && Meteor.isServer) {
-  // In sandstorm we only have one board per sandstorm instance. Since we want
-  // to keep most of our code unchanged, we simply hard-code a board `_id` and
-  // redirect the user to this particular board.
-  const sandstormBoard = {
-    _id: 'sandstorm',
-
-    // XXX Should be shared with the grain instance name.
-    title: 'Wekan',
-    slug: 'libreboard',
-    members: [],
-
-    // Board access security is handled by sandstorm, so in our point of view we
-    // can alway assume that the board is public (unauthorized users won't be
-    // able to access it anyway).
-    permission: 'public',
-  };
+// In sandstorm we only have one board per sandstorm instance. Since we want to
+// keep most of our code unchanged, we simply hard-code a board `_id` and
+// redirect the user to this particular board.
+const sandstormBoard = {
+  _id: 'sandstorm',
+
+  // XXX Should be shared with the grain instance name.
+  title: 'Wekan',
+  slug: 'libreboard',
+  members: [],
+
+  // Board access security is handled by sandstorm, so in our point of view we
+  // can alway assume that the board is public (unauthorized users won't be able
+  // to access it anyway).
+  permission: 'public',
+};
 
+if (isSandstorm && Meteor.isServer) {
   function updateUserPermissions(userId, permissions) {
     const isActive = permissions.indexOf('participate') > -1;
     const isAdmin = permissions.indexOf('configure') > -1;
@@ -142,6 +142,18 @@ if (isSandstorm && Meteor.isClient) {
     updateSandstormMetaData({ setTitle: DocHead.getTitle() });
   });
 
+  // Runtime redirection from the home page to the unique board -- since the
+  // home page contains a list of a single board it's not worth to display.
+  //
+  // XXX Hack. The home route is already defined at this point so we need to
+  // add the redirection trigger to the internal route object.
+  FlowRouter._routesMap.home._triggersEnter.push((context, redirect) => {
+    redirect(FlowRouter.path('board', {
+      id: sandstormBoard._id,
+      slug: sandstormBoard.slug,
+    }));
+  });
+
   // XXX Hack. `Meteor.absoluteUrl` doesn't work in Sandstorm, since every
   // session has a different URL whereas Meteor computes absoluteUrl based on
   // the ROOT_URL environment variable. So we overwrite this function on a

+ 2 - 3
server/lib/utils.js

@@ -1,8 +1,7 @@
 allowIsBoardAdmin = function(userId, board) {
-  const admins = _.pluck(_.where(board.members, {isAdmin: true}), 'userId');
-  return _.contains(admins, userId);
+  return board && board.hasAdmin(userId);
 };
 
 allowIsBoardMember = function(userId, board) {
-  return _.contains(_.pluck(board.members, 'userId'), userId);
+  return board && board.hasMember(userId);
 };

+ 2 - 2
server/publications/boards.js

@@ -16,7 +16,7 @@ Meteor.publish('boards', function() {
   return Boards.find({
     archived: false,
     $or: [
-      { 'members.userId': this.userId },
+      { members: { $elemMatch: { userId: this.userId, isActive: true }}},
       { _id: { $in: starredBoards } },
     ],
   }, {
@@ -66,7 +66,7 @@ Meteor.publishComposite('board', function(boardId) {
         // it.
         $or: [
           { permission: 'public' },
-          { 'members.userId': this.userId },
+          { members: { $elemMatch: { userId: this.userId, isActive: true }}},
         ],
       }, { limit: 1 });
     },