{{#each permission}}
- {{_id}}
+ {{_ permissionName}} [{{_id}}]
{{#each role}}
diff --git a/packages/rocketchat-authorization/client/views/permissions.js b/packages/rocketchat-authorization/client/views/permissions.js
new file mode 100644
index 0000000000000..6205927af5a1c
--- /dev/null
+++ b/packages/rocketchat-authorization/client/views/permissions.js
@@ -0,0 +1,75 @@
+/* globals ChatPermissions */
+
+Template.permissions.helpers({
+ role() {
+ return Template.instance().roles.get();
+ },
+
+ permission() {
+ return ChatPermissions.find({}, {
+ sort: {
+ _id: 1
+ }
+ });
+ },
+
+ granted(roles) {
+ if (roles) {
+ if (roles.indexOf(this._id) !== -1) {
+ return 'checked';
+ }
+ }
+ },
+
+ permissionName() {
+ return `${ this._id }`;
+ },
+
+ permissionDescription() {
+ return `${ this._id }_description`;
+ },
+
+ hasPermission() {
+ return RocketChat.authz.hasAllPermission('access-permissions');
+ }
+});
+
+Template.permissions.events({
+ 'click .role-permission'(e, instance) {
+ const permission = e.currentTarget.getAttribute('data-permission');
+ const role = e.currentTarget.getAttribute('data-role');
+
+ if (instance.permissionByRole[permission].indexOf(role) === -1) {
+ return Meteor.call('authorization:addPermissionToRole', permission, role);
+ } else {
+ return Meteor.call('authorization:removeRoleFromPermission', permission, role);
+ }
+ }
+});
+
+Template.permissions.onCreated(function() {
+ this.roles = new ReactiveVar([]);
+ this.permissionByRole = {};
+ this.actions = {
+ added: {},
+ removed: {}
+ };
+
+ Tracker.autorun(() => {
+ this.roles.set(RocketChat.models.Roles.find().fetch());
+ });
+
+ Tracker.autorun(() => {
+ ChatPermissions.find().observeChanges({
+ added: (id, fields) => {
+ this.permissionByRole[id] = fields.roles;
+ },
+ changed: (id, fields) => {
+ this.permissionByRole[id] = fields.roles;
+ },
+ removed: (id) => {
+ delete this.permissionByRole[id];
+ }
+ });
+ });
+});
diff --git a/packages/rocketchat-authorization/client/views/permissionsRole.coffee b/packages/rocketchat-authorization/client/views/permissionsRole.coffee
deleted file mode 100644
index ea4b351b7002d..0000000000000
--- a/packages/rocketchat-authorization/client/views/permissionsRole.coffee
+++ /dev/null
@@ -1,190 +0,0 @@
-import toastr from 'toastr'
-Template.permissionsRole.helpers
- role: ->
- return RocketChat.models.Roles.findOne({ _id: FlowRouter.getParam('name') }) or {}
-
- userInRole: ->
- return Template.instance().usersInRole.get()
-
- editing: ->
- return FlowRouter.getParam('name')?
-
- emailAddress: ->
- if @emails?.length > 0
- return @emails[0].address
-
- hasPermission: ->
- return RocketChat.authz.hasAllPermission 'access-permissions'
-
- protected: ->
- return @protected
-
- editable: ->
- return @_id? and not @protected
-
- hasUsers: ->
- return Template.instance().usersInRole.get() && Template.instance().usersInRole.get().count() > 0
-
- hasMore: ->
- return Template.instance().limit?.get() <= Template.instance().usersInRole.get().count()
-
- isLoading: ->
- return 'btn-loading' unless Template.instance().ready?.get()
-
- searchRoom: ->
- return Template.instance().searchRoom.get()
-
- autocompleteChannelSettings: ->
- return {
- limit: 10
- # inputDelay: 300
- rules: [
- {
- collection: 'CachedChannelList'
- subscription: 'channelAndPrivateAutocomplete'
- field: 'name'
- template: Template.roomSearch
- noMatchTemplate: Template.roomSearchEmpty
- matchAll: true
- sort: 'name'
- selector: (match) ->
- return { name: match }
- }
- ]
- }
-
- autocompleteUsernameSettings: ->
- return {
- limit: 10
- rules: [
- {
- collection: 'CachedUserList'
- subscription: 'userAutocomplete'
- field: 'username'
- template: Template.userSearch
- noMatchTemplate: Template.userSearchEmpty
- matchAll: true
- filter:
- exceptions: Template.instance().usersInRole.get()?.fetch()
- selector: (match) ->
- return { term: match }
- sort: 'username'
- }
- ]
- }
-
-Template.permissionsRole.events
-
- 'click .remove-user': (e, instance) ->
- e.preventDefault()
-
- swal
- title: t('Are_you_sure')
- type: 'warning'
- showCancelButton: true
- confirmButtonColor: '#DD6B55'
- confirmButtonText: t('Yes')
- cancelButtonText: t('Cancel')
- closeOnConfirm: false
- html: false
- , =>
- Meteor.call 'authorization:removeUserFromRole', FlowRouter.getParam('name'), @username, instance.searchRoom.get(), (error, result) ->
- if error
- return handleError(error)
-
- swal
- title: t('Removed')
- text: t('User_removed')
- type: 'success'
- timer: 1000
- showConfirmButton: false
-
- 'submit #form-role': (e, instance) ->
- e.preventDefault()
-
- oldBtnValue = e.currentTarget.elements['save'].value
-
- e.currentTarget.elements['save'].value = t('Saving')
-
- roleData =
- description: e.currentTarget.elements['description'].value
- scope: e.currentTarget.elements['scope'].value
-
- if @_id
- roleData.name = @_id
- else
- roleData.name = e.currentTarget.elements['name'].value
-
-
- Meteor.call 'authorization:saveRole', roleData, (error, result) =>
- e.currentTarget.elements['save'].value = oldBtnValue
- if error
- return handleError(error)
-
- toastr.success t('Saved')
-
- if not @_id?
- FlowRouter.go 'admin-permissions-edit', { name: roleData.name }
-
-
- 'submit #form-users': (e, instance) ->
- e.preventDefault()
-
- if e.currentTarget.elements['username'].value.trim() is ''
- return toastr.error t('Please_fill_a_username')
-
- oldBtnValue = e.currentTarget.elements['add'].value
-
- e.currentTarget.elements['add'].value = t('Saving')
-
- Meteor.call 'authorization:addUserToRole', FlowRouter.getParam('name'), e.currentTarget.elements['username'].value, instance.searchRoom.get(), (error, result) =>
- e.currentTarget.elements['add'].value = oldBtnValue
- if error
- return handleError(error)
-
- instance.subscribe 'usersInRole', FlowRouter.getParam('name'), instance.searchRoom.get()
- toastr.success t('User_added')
- e.currentTarget.reset()
-
- 'submit #form-search-room': (e) ->
- e.preventDefault()
-
- 'click .delete-role': (e, instance) ->
- e.preventDefault()
-
- if @protected
- return toastr.error t('error-delete-protected-role')
-
- Meteor.call 'authorization:deleteRole', @_id, (error, result) ->
- if error
- return handleError(error)
-
- toastr.success t('Role_removed')
-
- FlowRouter.go 'admin-permissions'
-
- 'click .load-more': (e, t) ->
- e.preventDefault()
- e.stopPropagation()
- t.limit.set t.limit.get() + 50
-
- 'autocompleteselect input[name=room]': (event, template, doc) ->
- template.searchRoom.set(doc._id)
-
-Template.permissionsRole.onCreated ->
- @searchRoom = new ReactiveVar
- @searchUsername = new ReactiveVar
- @usersInRole = new ReactiveVar
- @limit = new ReactiveVar 50
- @ready = new ReactiveVar true
-
- @subscribe 'roles', FlowRouter.getParam('name')
-
- @autorun =>
- if @searchRoom.get()
- @subscribe 'roomSubscriptionsByRole', @searchRoom.get(), FlowRouter.getParam('name')
-
- limit = @limit.get()
- subscription = @subscribe 'usersInRole', FlowRouter.getParam('name'), @searchRoom.get(), limit
- @ready.set subscription.ready()
- @usersInRole.set(RocketChat.models.Roles.findUsersInRole(FlowRouter.getParam('name'), @searchRoom.get(), { sort: { username: 1 } }))
diff --git a/packages/rocketchat-authorization/client/views/permissionsRole.js b/packages/rocketchat-authorization/client/views/permissionsRole.js
new file mode 100644
index 0000000000000..5424614393335
--- /dev/null
+++ b/packages/rocketchat-authorization/client/views/permissionsRole.js
@@ -0,0 +1,238 @@
+import toastr from 'toastr';
+
+Template.permissionsRole.helpers({
+ role() {
+ return RocketChat.models.Roles.findOne({
+ _id: FlowRouter.getParam('name')
+ }) || {};
+ },
+
+ userInRole() {
+ return Template.instance().usersInRole.get();
+ },
+
+ editing() {
+ return FlowRouter.getParam('name') != null;
+ },
+
+ emailAddress() {
+ if (this.emails && this.emails.length > 0) {
+ return this.emails[0].address;
+ }
+ },
+
+ hasPermission() {
+ return RocketChat.authz.hasAllPermission('access-permissions');
+ },
+
+ protected() {
+ return this.protected;
+ },
+
+ editable() {
+ return this._id && !this.protected;
+ },
+
+ hasUsers() {
+ return Template.instance().usersInRole.get() && Template.instance().usersInRole.get().count() > 0;
+ },
+
+ hasMore() {
+ const instance = Template.instance();
+ return instance.limit && instance.limit.get() <= instance.usersInRole.get().count();
+ },
+
+ isLoading() {
+ const instance = Template.instance();
+ if (!instance.ready || !instance.ready.get()) {
+ return 'btn-loading';
+ }
+ },
+
+ searchRoom() {
+ return Template.instance().searchRoom.get();
+ },
+
+ autocompleteChannelSettings() {
+ return {
+ limit: 10,
+ rules: [
+ {
+ collection: 'CachedChannelList',
+ subscription: 'channelAndPrivateAutocomplete',
+ field: 'name',
+ template: Template.roomSearch,
+ noMatchTemplate: Template.roomSearchEmpty,
+ matchAll: true,
+ sort: 'name',
+ selector(match) {
+ return {
+ name: match
+ };
+ }
+ }
+ ]
+ };
+ },
+
+ autocompleteUsernameSettings() {
+ const instance = Template.instance();
+ return {
+ limit: 10,
+ rules: [
+ {
+ collection: 'CachedUserList',
+ subscription: 'userAutocomplete',
+ field: 'username',
+ template: Template.userSearch,
+ noMatchTemplate: Template.userSearchEmpty,
+ matchAll: true,
+ filter: {
+ exceptions: instance.usersInRole.get() && instance.usersInRole.get().fetch()
+ },
+ selector(match) {
+ return {
+ term: match
+ };
+ },
+ sort: 'username'
+ }
+ ]
+ };
+ }
+});
+
+Template.permissionsRole.events({
+ 'click .remove-user'(e, instance) {
+ e.preventDefault();
+ modal.open({
+ title: t('Are_you_sure'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, () => {
+ Meteor.call('authorization:removeUserFromRole', FlowRouter.getParam('name'), this.username, instance.searchRoom.get(), function(error/*, result*/) {
+ if (error) {
+ return handleError(error);
+ }
+
+ modal.open({
+ title: t('Removed'),
+ text: t('User_removed'),
+ type: 'success',
+ timer: 1000,
+ showConfirmButton: false
+ });
+ });
+ });
+ },
+
+ 'submit #form-role'(e/*, instance*/) {
+ e.preventDefault();
+ const oldBtnValue = e.currentTarget.elements['save'].value;
+ e.currentTarget.elements['save'].value = t('Saving');
+ const roleData = {
+ description: e.currentTarget.elements['description'].value,
+ scope: e.currentTarget.elements['scope'].value
+ };
+
+ if (this._id) {
+ roleData.name = this._id;
+ } else {
+ roleData.name = e.currentTarget.elements['name'].value;
+ }
+
+ Meteor.call('authorization:saveRole', roleData, (error/*, result*/) => {
+ e.currentTarget.elements['save'].value = oldBtnValue;
+ if (error) {
+ return handleError(error);
+ }
+
+ toastr.success(t('Saved'));
+
+ if (!this._id) {
+ return FlowRouter.go('admin-permissions-edit', {
+ name: roleData.name
+ });
+ }
+ });
+ },
+
+ 'submit #form-users'(e, instance) {
+ e.preventDefault();
+ if (e.currentTarget.elements['username'].value.trim() === '') {
+ return toastr.error(t('Please_fill_a_username'));
+ }
+ const oldBtnValue = e.currentTarget.elements['add'].value;
+ e.currentTarget.elements['add'].value = t('Saving');
+
+ Meteor.call('authorization:addUserToRole', FlowRouter.getParam('name'), e.currentTarget.elements['username'].value, instance.searchRoom.get(), (error/*, result*/) => {
+ e.currentTarget.elements['add'].value = oldBtnValue;
+ if (error) {
+ return handleError(error);
+ }
+ instance.subscribe('usersInRole', FlowRouter.getParam('name'), instance.searchRoom.get());
+ toastr.success(t('User_added'));
+ e.currentTarget.reset();
+ });
+ },
+
+ 'submit #form-search-room'(e) {
+ return e.preventDefault();
+ },
+
+ 'click .delete-role'(e/*, instance*/) {
+ e.preventDefault();
+ if (this.protected) {
+ return toastr.error(t('error-delete-protected-role'));
+ }
+
+ Meteor.call('authorization:deleteRole', this._id, function(error/*, result*/) {
+ if (error) {
+ return handleError(error);
+ }
+ toastr.success(t('Role_removed'));
+ FlowRouter.go('admin-permissions');
+ });
+ },
+
+ 'click .load-more'(e, t) {
+ e.preventDefault();
+ e.stopPropagation();
+ t.limit.set(t.limit.get() + 50);
+ },
+
+ 'autocompleteselect input[name=room]'(event, template, doc) {
+ template.searchRoom.set(doc._id);
+ }
+});
+
+Template.permissionsRole.onCreated(function() {
+ this.searchRoom = new ReactiveVar;
+ this.searchUsername = new ReactiveVar;
+ this.usersInRole = new ReactiveVar;
+ this.limit = new ReactiveVar(50);
+ this.ready = new ReactiveVar(true);
+ this.subscribe('roles', FlowRouter.getParam('name'));
+
+ this.autorun(() => {
+ if (this.searchRoom.get()) {
+ this.subscribe('roomSubscriptionsByRole', this.searchRoom.get(), FlowRouter.getParam('name'));
+ }
+
+ const limit = this.limit.get();
+
+ const subscription = this.subscribe('usersInRole', FlowRouter.getParam('name'), this.searchRoom.get(), limit);
+ this.ready.set(subscription.ready());
+
+ this.usersInRole.set(RocketChat.models.Roles.findUsersInRole(FlowRouter.getParam('name'), this.searchRoom.get(), {
+ sort: {
+ username: 1
+ }
+ }));
+ });
+});
diff --git a/packages/rocketchat-authorization/lib/rocketchat.coffee b/packages/rocketchat-authorization/lib/rocketchat.coffee
deleted file mode 100644
index a8c5e45883456..0000000000000
--- a/packages/rocketchat-authorization/lib/rocketchat.coffee
+++ /dev/null
@@ -1 +0,0 @@
-RocketChat.authz = {}
diff --git a/packages/rocketchat-authorization/lib/rocketchat.js b/packages/rocketchat-authorization/lib/rocketchat.js
new file mode 100644
index 0000000000000..6445a1b8b5f09
--- /dev/null
+++ b/packages/rocketchat-authorization/lib/rocketchat.js
@@ -0,0 +1 @@
+RocketChat.authz = {};
diff --git a/packages/rocketchat-authorization/package.js b/packages/rocketchat-authorization/package.js
index 6838b9aeed6b9..1f8de7d298ea0 100644
--- a/packages/rocketchat-authorization/package.js
+++ b/packages/rocketchat-authorization/package.js
@@ -9,68 +9,65 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'coffeescript',
- 'underscore',
- 'rocketchat:lib',
- 'less'
+ 'rocketchat:lib'
]);
api.use('mongo', ['client', 'server']);
api.use('kadira:flow-router', 'client');
- api.use('less', 'client');
api.use('tracker', 'client');
api.use('templating', 'client');
- api.addFiles('lib/rocketchat.coffee', ['server', 'client']);
+ api.addFiles('lib/rocketchat.js', ['server', 'client']);
- api.addFiles('client/lib/ChatPermissions.coffee', ['client']);
- api.addFiles('client/lib/models/Roles.coffee', ['client']);
+ api.addFiles('client/lib/ChatPermissions.js', ['client']);
+ api.addFiles('client/lib/models/Roles.js', ['client']);
api.addFiles('client/lib/models/Users.js', ['client']);
api.addFiles('client/lib/models/Subscriptions.js', ['client']);
- api.addFiles('client/startup.coffee', ['client']);
- api.addFiles('client/hasPermission.coffee', ['client']);
- api.addFiles('client/hasRole.coffee', ['client']);
+ api.addFiles('client/startup.js', ['client']);
+ api.addFiles('client/hasPermission.js', ['client']);
+ api.addFiles('client/hasRole.js', ['client']);
api.addFiles('client/requiresPermission.html', ['client']);
- api.addFiles('client/route.coffee', ['client']);
+ api.addFiles('client/route.js', ['client']);
+ api.addFiles('client/usersNameChanged.js', ['client']);
// views
api.addFiles('client/views/permissions.html', ['client']);
- api.addFiles('client/views/permissions.coffee', ['client']);
+ api.addFiles('client/views/permissions.js', ['client']);
api.addFiles('client/views/permissionsRole.html', ['client']);
- api.addFiles('client/views/permissionsRole.coffee', ['client']);
+ api.addFiles('client/views/permissionsRole.js', ['client']);
// stylesheets
- api.addFiles('client/stylesheets/permissions.less', 'client');
+ api.addFiles('client/stylesheets/permissions.css', 'client');
- api.addFiles('server/models/Permissions.coffee', ['server']);
- api.addFiles('server/models/Roles.coffee', ['server']);
+ api.addFiles('server/models/Permissions.js', ['server']);
+ api.addFiles('server/models/Roles.js', ['server']);
api.addFiles('server/models/Base.js', ['server']);
api.addFiles('server/models/Users.js', ['server']);
api.addFiles('server/models/Subscriptions.js', ['server']);
- api.addFiles('server/functions/addUserRoles.coffee', ['server']);
+ api.addFiles('server/functions/addUserRoles.js', ['server']);
api.addFiles('server/functions/canAccessRoom.js', ['server']);
- api.addFiles('server/functions/getRoles.coffee', ['server']);
- api.addFiles('server/functions/getUsersInRole.coffee', ['server']);
- api.addFiles('server/functions/hasPermission.coffee', ['server']);
- api.addFiles('server/functions/hasRole.coffee', ['server']);
- api.addFiles('server/functions/removeUserFromRoles.coffee', ['server']);
+ api.addFiles('server/functions/getRoles.js', ['server']);
+ api.addFiles('server/functions/getUsersInRole.js', ['server']);
+ api.addFiles('server/functions/hasPermission.js', ['server']);
+ api.addFiles('server/functions/hasRole.js', ['server']);
+ api.addFiles('server/functions/removeUserFromRoles.js', ['server']);
// publications
api.addFiles('server/publications/permissions.js', 'server');
- api.addFiles('server/publications/roles.coffee', 'server');
- api.addFiles('server/publications/usersInRole.coffee', 'server');
+ api.addFiles('server/publications/roles.js', 'server');
+ api.addFiles('server/publications/usersInRole.js', 'server');
// methods
- api.addFiles('server/methods/addUserToRole.coffee', 'server');
- api.addFiles('server/methods/deleteRole.coffee', 'server');
- api.addFiles('server/methods/removeUserFromRole.coffee', 'server');
- api.addFiles('server/methods/saveRole.coffee', 'server');
- api.addFiles('server/methods/addPermissionToRole.coffee', 'server');
- api.addFiles('server/methods/removeRoleFromPermission.coffee', 'server');
+ api.addFiles('server/methods/addUserToRole.js', 'server');
+ api.addFiles('server/methods/deleteRole.js', 'server');
+ api.addFiles('server/methods/removeUserFromRole.js', 'server');
+ api.addFiles('server/methods/saveRole.js', 'server');
+ api.addFiles('server/methods/addPermissionToRole.js', 'server');
+ api.addFiles('server/methods/removeRoleFromPermission.js', 'server');
- api.addFiles('server/startup.coffee', ['server']);
+ api.addFiles('server/startup.js', ['server']);
});
diff --git a/packages/rocketchat-authorization/server/functions/addUserRoles.coffee b/packages/rocketchat-authorization/server/functions/addUserRoles.coffee
deleted file mode 100644
index 626b1769f235c..0000000000000
--- a/packages/rocketchat-authorization/server/functions/addUserRoles.coffee
+++ /dev/null
@@ -1,19 +0,0 @@
-RocketChat.authz.addUserRoles = (userId, roleNames, scope) ->
- if not userId or not roleNames
- return false
-
- user = RocketChat.models.Users.db.findOneById(userId)
- if not user
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { function: 'RocketChat.authz.addUserRoles' }
-
- roleNames = [].concat roleNames
-
- existingRoleNames = _.pluck(RocketChat.authz.getRoles(), '_id')
- invalidRoleNames = _.difference(roleNames, existingRoleNames)
- unless _.isEmpty(invalidRoleNames)
- for role in invalidRoleNames
- RocketChat.models.Roles.createOrUpdate role
-
- RocketChat.models.Roles.addUserRoles(userId, roleNames, scope)
-
- return true
diff --git a/packages/rocketchat-authorization/server/functions/addUserRoles.js b/packages/rocketchat-authorization/server/functions/addUserRoles.js
new file mode 100644
index 0000000000000..7568f44e70e65
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/addUserRoles.js
@@ -0,0 +1,28 @@
+import _ from 'underscore';
+
+RocketChat.authz.addUserRoles = function(userId, roleNames, scope) {
+ if (!userId || !roleNames) {
+ return false;
+ }
+
+ const user = RocketChat.models.Users.db.findOneById(userId);
+ if (!user) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ function: 'RocketChat.authz.addUserRoles'
+ });
+ }
+
+ roleNames = [].concat(roleNames);
+ const existingRoleNames = _.pluck(RocketChat.authz.getRoles(), '_id');
+ const invalidRoleNames = _.difference(roleNames, existingRoleNames);
+
+ if (!_.isEmpty(invalidRoleNames)) {
+ for (const role of invalidRoleNames) {
+ RocketChat.models.Roles.createOrUpdate(role);
+ }
+ }
+
+ RocketChat.models.Roles.addUserRoles(userId, roleNames, scope);
+
+ return true;
+};
diff --git a/packages/rocketchat-authorization/server/functions/canAccessRoom.js b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
index 5e41811e28f8a..092dd4b080854 100644
--- a/packages/rocketchat-authorization/server/functions/canAccessRoom.js
+++ b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
@@ -1,21 +1,27 @@
/* globals RocketChat */
RocketChat.authz.roomAccessValidators = [
- function(room, user) {
- const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
- if (subscription) {
- return subscription._room;
- }
- },
- function(room, user) {
+ function(room, user = {}) {
if (room.t === 'c') {
+ if (!user._id && RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) {
+ return true;
+ }
+
return RocketChat.authz.hasPermission(user._id, 'view-c-room');
}
+ },
+ function(room, user = {}) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
+ if (subscription) {
+ // XXX ??
+ // return subscription._room;
+ return RocketChat.authz.hasPermission(user._id, 'view-d-room');
+ }
}
];
-RocketChat.authz.canAccessRoom = function(room, user) {
+RocketChat.authz.canAccessRoom = function(room, user, extraData) {
return RocketChat.authz.roomAccessValidators.some((validator) => {
- return validator.call(this, room, user);
+ return validator.call(this, room, user, extraData);
});
};
diff --git a/packages/rocketchat-authorization/server/functions/getRoles.coffee b/packages/rocketchat-authorization/server/functions/getRoles.coffee
deleted file mode 100644
index 895dcc532c191..0000000000000
--- a/packages/rocketchat-authorization/server/functions/getRoles.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.authz.getRoles = ->
- return RocketChat.models.Roles.find().fetch()
diff --git a/packages/rocketchat-authorization/server/functions/getRoles.js b/packages/rocketchat-authorization/server/functions/getRoles.js
new file mode 100644
index 0000000000000..7fe235157f3ec
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getRoles.js
@@ -0,0 +1,3 @@
+RocketChat.authz.getRoles = function() {
+ return RocketChat.models.Roles.find().fetch();
+};
diff --git a/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee b/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee
deleted file mode 100644
index b8fc11a51fbae..0000000000000
--- a/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.authz.getUsersInRole = (roleName, scope, options) ->
- return RocketChat.models.Roles.findUsersInRole(roleName, scope, options)
diff --git a/packages/rocketchat-authorization/server/functions/getUsersInRole.js b/packages/rocketchat-authorization/server/functions/getUsersInRole.js
new file mode 100644
index 0000000000000..40d6aedbd95e9
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getUsersInRole.js
@@ -0,0 +1,3 @@
+RocketChat.authz.getUsersInRole = function(roleName, scope, options) {
+ return RocketChat.models.Roles.findUsersInRole(roleName, scope, options);
+};
diff --git a/packages/rocketchat-authorization/server/functions/hasPermission.coffee b/packages/rocketchat-authorization/server/functions/hasPermission.coffee
deleted file mode 100644
index 5797a5f446e61..0000000000000
--- a/packages/rocketchat-authorization/server/functions/hasPermission.coffee
+++ /dev/null
@@ -1,27 +0,0 @@
-atLeastOne = (userId, permissions, scope) ->
- return _.some permissions, (permissionId) ->
- permission = RocketChat.models.Permissions.findOne permissionId
- RocketChat.models.Roles.isUserInRoles(userId, permission.roles, scope)
-
-all = (userId, permissions, scope) ->
- return _.every permissions, (permissionId) ->
- permission = RocketChat.models.Permissions.findOne permissionId
- RocketChat.models.Roles.isUserInRoles(userId, permission.roles, scope)
-
-hasPermission = (userId, permissions, scope, strategy) ->
- unless userId
- return false
-
- permissions = [].concat permissions
-
- return strategy(userId, permissions, scope)
-
-
-
-RocketChat.authz.hasAllPermission = (userId, permissions, scope) ->
- return hasPermission(userId, permissions, scope, all)
-
-RocketChat.authz.hasPermission = RocketChat.authz.hasAllPermission
-
-RocketChat.authz.hasAtLeastOnePermission = (userId, permissions, scope) ->
- return hasPermission(userId, permissions, scope, atLeastOne)
diff --git a/packages/rocketchat-authorization/server/functions/hasPermission.js b/packages/rocketchat-authorization/server/functions/hasPermission.js
new file mode 100644
index 0000000000000..7c11f9c8447df
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/hasPermission.js
@@ -0,0 +1,32 @@
+function atLeastOne(userId, permissions = [], scope) {
+ return permissions.some((permissionId) => {
+ const permission = RocketChat.models.Permissions.findOne(permissionId);
+ return RocketChat.models.Roles.isUserInRoles(userId, permission.roles, scope);
+ });
+}
+
+function all(userId, permissions = [], scope) {
+ return permissions.every((permissionId) => {
+ const permission = RocketChat.models.Permissions.findOne(permissionId);
+ return RocketChat.models.Roles.isUserInRoles(userId, permission.roles, scope);
+ });
+}
+
+function hasPermission(userId, permissions, scope, strategy) {
+ if (!userId) {
+ return false;
+ }
+
+ permissions = [].concat(permissions);
+ return strategy(userId, permissions, scope);
+}
+
+RocketChat.authz.hasAllPermission = function(userId, permissions, scope) {
+ return hasPermission(userId, permissions, scope, all);
+};
+
+RocketChat.authz.hasPermission = RocketChat.authz.hasAllPermission;
+
+RocketChat.authz.hasAtLeastOnePermission = function(userId, permissions, scope) {
+ return hasPermission(userId, permissions, scope, atLeastOne);
+};
diff --git a/packages/rocketchat-authorization/server/functions/hasRole.coffee b/packages/rocketchat-authorization/server/functions/hasRole.coffee
deleted file mode 100644
index aff335e48b2fd..0000000000000
--- a/packages/rocketchat-authorization/server/functions/hasRole.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.authz.hasRole = (userId, roleNames, scope) ->
- roleNames = [].concat roleNames
- return RocketChat.models.Roles.isUserInRoles(userId, roleNames, scope) # true if user is in ANY role
diff --git a/packages/rocketchat-authorization/server/functions/hasRole.js b/packages/rocketchat-authorization/server/functions/hasRole.js
new file mode 100644
index 0000000000000..858662b46c68e
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/hasRole.js
@@ -0,0 +1,4 @@
+RocketChat.authz.hasRole = function(userId, roleNames, scope) {
+ roleNames = [].concat(roleNames);
+ return RocketChat.models.Roles.isUserInRoles(userId, roleNames, scope);
+};
diff --git a/packages/rocketchat-authorization/server/functions/removeUserFromRoles.coffee b/packages/rocketchat-authorization/server/functions/removeUserFromRoles.coffee
deleted file mode 100644
index df363f76260bf..0000000000000
--- a/packages/rocketchat-authorization/server/functions/removeUserFromRoles.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-RocketChat.authz.removeUserFromRoles = (userId, roleNames, scope) ->
- if not userId or not roleNames
- return false
-
- user = RocketChat.models.Users.findOneById(userId)
- if not user?
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { function: 'RocketChat.authz.removeUserFromRoles' }
-
- roleNames = [].concat roleNames
-
- existingRoleNames = _.pluck(RocketChat.authz.getRoles(), '_id')
- invalidRoleNames = _.difference(roleNames, existingRoleNames)
- unless _.isEmpty(invalidRoleNames)
- throw new Meteor.Error 'error-invalid-role', 'Invalid role', { function: 'RocketChat.authz.removeUserFromRoles' }
-
- RocketChat.models.Roles.removeUserRoles(userId, roleNames, scope)
-
- return true
diff --git a/packages/rocketchat-authorization/server/functions/removeUserFromRoles.js b/packages/rocketchat-authorization/server/functions/removeUserFromRoles.js
new file mode 100644
index 0000000000000..566d46a8190c5
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/removeUserFromRoles.js
@@ -0,0 +1,29 @@
+import _ from 'underscore';
+
+RocketChat.authz.removeUserFromRoles = function(userId, roleNames, scope) {
+ if (!userId || !roleNames) {
+ return false;
+ }
+
+ const user = RocketChat.models.Users.findOneById(userId);
+
+ if (!user) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ function: 'RocketChat.authz.removeUserFromRoles'
+ });
+ }
+
+ roleNames = [].concat(roleNames);
+ const existingRoleNames = _.pluck(RocketChat.authz.getRoles(), '_id');
+ const invalidRoleNames = _.difference(roleNames, existingRoleNames);
+
+ if (!_.isEmpty(invalidRoleNames)) {
+ throw new Meteor.Error('error-invalid-role', 'Invalid role', {
+ function: 'RocketChat.authz.removeUserFromRoles'
+ });
+ }
+
+ RocketChat.models.Roles.removeUserRoles(userId, roleNames, scope);
+
+ return true;
+};
diff --git a/packages/rocketchat-authorization/server/methods/addPermissionToRole.coffee b/packages/rocketchat-authorization/server/methods/addPermissionToRole.coffee
deleted file mode 100644
index 3b4b51384f770..0000000000000
--- a/packages/rocketchat-authorization/server/methods/addPermissionToRole.coffee
+++ /dev/null
@@ -1,6 +0,0 @@
-Meteor.methods
- 'authorization:addPermissionToRole': (permission, role) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error 'error-action-not-allowed', 'Adding permission is not allowed', { method: 'authorization:addPermissionToRole', action: 'Adding_permission' }
-
- RocketChat.models.Permissions.addRole permission, role
diff --git a/packages/rocketchat-authorization/server/methods/addPermissionToRole.js b/packages/rocketchat-authorization/server/methods/addPermissionToRole.js
new file mode 100644
index 0000000000000..bae94f4d3dc82
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/addPermissionToRole.js
@@ -0,0 +1,12 @@
+Meteor.methods({
+ 'authorization:addPermissionToRole'(permission, role) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Adding permission is not allowed', {
+ method: 'authorization:addPermissionToRole',
+ action: 'Adding_permission'
+ });
+ }
+
+ return RocketChat.models.Permissions.addRole(permission, role);
+ }
+});
diff --git a/packages/rocketchat-authorization/server/methods/addUserToRole.coffee b/packages/rocketchat-authorization/server/methods/addUserToRole.coffee
deleted file mode 100644
index 051984f157ae1..0000000000000
--- a/packages/rocketchat-authorization/server/methods/addUserToRole.coffee
+++ /dev/null
@@ -1,22 +0,0 @@
-Meteor.methods
- 'authorization:addUserToRole': (roleName, username, scope) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error "error-action-not-allowed", "Accessing permissions is not allowed", { method: 'authorization:addUserToRole', action: 'Accessing_permissions' }
-
- if not roleName or not _.isString(roleName) or not username or not _.isString(username)
- throw new Meteor.Error 'error-invalid-arguments', 'Invalid arguments', { method: 'authorization:addUserToRole' }
-
- if roleName is 'admin' and not RocketChat.authz.hasPermission Meteor.userId(), 'assign-admin-role'
- throw new Meteor.Error 'error-action-not-allowed', 'Assigning admin is not allowed', { method: 'insertOrUpdateUser', action: 'Assign_admin' }
-
- user = RocketChat.models.Users.findOneByUsername username, { fields: { _id: 1 } }
-
- if not user?._id?
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'authorization:addUserToRole' }
-
- add = RocketChat.models.Roles.addUserRoles user._id, roleName, scope
-
- if RocketChat.settings.get('UI_DisplayRoles')
- RocketChat.Notifications.notifyLogged('roles-change', { type: 'added', _id: roleName, u: { _id: user._id, username: username }, scope: scope });
-
- return add
diff --git a/packages/rocketchat-authorization/server/methods/addUserToRole.js b/packages/rocketchat-authorization/server/methods/addUserToRole.js
new file mode 100644
index 0000000000000..21e7ddfdaad7a
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/addUserToRole.js
@@ -0,0 +1,53 @@
+import _ from 'underscore';
+
+Meteor.methods({
+ 'authorization:addUserToRole'(roleName, username, scope) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Accessing permissions is not allowed', {
+ method: 'authorization:addUserToRole',
+ action: 'Accessing_permissions'
+ });
+ }
+
+ if (!roleName || !_.isString(roleName) || !username || !_.isString(username)) {
+ throw new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {
+ method: 'authorization:addUserToRole'
+ });
+ }
+
+ if (roleName === 'admin' && !RocketChat.authz.hasPermission(Meteor.userId(), 'assign-admin-role')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Assigning admin is not allowed', {
+ method: 'authorization:addUserToRole',
+ action: 'Assign_admin'
+ });
+ }
+
+ const user = RocketChat.models.Users.findOneByUsername(username, {
+ fields: {
+ _id: 1
+ }
+ });
+
+ if (!user || !user._id) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'authorization:addUserToRole'
+ });
+ }
+
+ const add = RocketChat.models.Roles.addUserRoles(user._id, roleName, scope);
+
+ if (RocketChat.settings.get('UI_DisplayRoles')) {
+ RocketChat.Notifications.notifyLogged('roles-change', {
+ type: 'added',
+ _id: roleName,
+ u: {
+ _id: user._id,
+ username
+ },
+ scope
+ });
+ }
+
+ return add;
+ }
+});
diff --git a/packages/rocketchat-authorization/server/methods/deleteRole.coffee b/packages/rocketchat-authorization/server/methods/deleteRole.coffee
deleted file mode 100644
index 16a50603aa083..0000000000000
--- a/packages/rocketchat-authorization/server/methods/deleteRole.coffee
+++ /dev/null
@@ -1,19 +0,0 @@
-Meteor.methods
- 'authorization:deleteRole': (roleName) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error 'error-action-not-allowed', 'Accessing permissions is not allowed', { method: 'authorization:deleteRole', action: 'Accessing_permissions' }
-
- role = RocketChat.models.Roles.findOne roleName
- if not role?
- throw new Meteor.Error 'error-invalid-role', 'Invalid role', { method: 'authorization:deleteRole' }
-
- if role.protected
- throw new Meteor.Error 'error-delete-protected-role', 'Cannot delete a protected role', { method: 'authorization:deleteRole' }
-
- roleScope = role.scope or 'Users'
- existingUsers = RocketChat.models[roleScope]?.findUsersInRoles?(roleName)
-
- if existingUsers?.count() > 0
- throw new Meteor.Error 'error-role-in-use', 'Cannot delete role because it\'s in use', { method: 'authorization:deleteRole' }
-
- return RocketChat.models.Roles.remove role.name
diff --git a/packages/rocketchat-authorization/server/methods/deleteRole.js b/packages/rocketchat-authorization/server/methods/deleteRole.js
new file mode 100644
index 0000000000000..474525d3afbe8
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/deleteRole.js
@@ -0,0 +1,35 @@
+Meteor.methods({
+ 'authorization:deleteRole'(roleName) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Accessing permissions is not allowed', {
+ method: 'authorization:deleteRole',
+ action: 'Accessing_permissions'
+ });
+ }
+
+ const role = RocketChat.models.Roles.findOne(roleName);
+ if (!role) {
+ throw new Meteor.Error('error-invalid-role', 'Invalid role', {
+ method: 'authorization:deleteRole'
+ });
+ }
+
+ if (role.protected) {
+ throw new Meteor.Error('error-delete-protected-role', 'Cannot delete a protected role', {
+ method: 'authorization:deleteRole'
+ });
+ }
+
+ const roleScope = role.scope || 'Users';
+ const model = RocketChat.models[roleScope];
+ const existingUsers = model && model.findUsersInRoles && model.findUsersInRoles(roleName);
+
+ if (existingUsers && existingUsers.count() > 0) {
+ throw new Meteor.Error('error-role-in-use', 'Cannot delete role because it\'s in use', {
+ method: 'authorization:deleteRole'
+ });
+ }
+
+ return RocketChat.models.Roles.remove(role.name);
+ }
+});
diff --git a/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.coffee b/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.coffee
deleted file mode 100644
index fe7b71f13b611..0000000000000
--- a/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.coffee
+++ /dev/null
@@ -1,6 +0,0 @@
-Meteor.methods
- 'authorization:removeRoleFromPermission': (permission, role) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error "error-action-not-allowed", "Accessing permissions is not allowed", { method: 'authorization:removeRoleFromPermission', action: 'Accessing_permissions' }
-
- RocketChat.models.Permissions.removeRole permission, role
diff --git a/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.js b/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.js
new file mode 100644
index 0000000000000..0602d1e3437b2
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/removeRoleFromPermission.js
@@ -0,0 +1,12 @@
+Meteor.methods({
+ 'authorization:removeRoleFromPermission'(permission, role) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Accessing permissions is not allowed', {
+ method: 'authorization:removeRoleFromPermission',
+ action: 'Accessing_permissions'
+ });
+ }
+
+ return RocketChat.models.Permissions.removeRole(permission, role);
+ }
+});
diff --git a/packages/rocketchat-authorization/server/methods/removeUserFromRole.coffee b/packages/rocketchat-authorization/server/methods/removeUserFromRole.coffee
deleted file mode 100644
index 434140286acac..0000000000000
--- a/packages/rocketchat-authorization/server/methods/removeUserFromRole.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-Meteor.methods
- 'authorization:removeUserFromRole': (roleName, username, scope) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error "error-action-not-allowed", 'Access permissions is not allowed', { method: 'authorization:removeUserFromRole', action: 'Accessing_permissions' }
-
- if not roleName or not _.isString(roleName) or not username or not _.isString(username)
- throw new Meteor.Error 'error-invalid-arguments', 'Invalid arguments', { method: 'authorization:removeUserFromRole' }
-
- user = Meteor.users.findOne { username: username }, { fields: { _id: 1, roles: 1 } }
-
- if not user?._id?
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'authorization:removeUserFromRole' }
-
- # prevent removing last user from admin role
- if roleName is 'admin'
- adminCount = Meteor.users.find({ roles: { $in: ['admin'] } }).count()
- userIsAdmin = user.roles.indexOf('admin') > -1
- if adminCount is 1 and userIsAdmin
- throw new Meteor.Error 'error-action-not-allowed', 'Leaving the app without admins is not allowed', { method: 'removeUserFromRole', action: 'Remove_last_admin' }
-
- remove = RocketChat.models.Roles.removeUserRoles user._id, roleName, scope
-
- if RocketChat.settings.get('UI_DisplayRoles')
- RocketChat.Notifications.notifyLogged('roles-change', { type: 'removed', _id: roleName, u: { _id: user._id, username: username }, scope: scope });
-
- return remove
diff --git a/packages/rocketchat-authorization/server/methods/removeUserFromRole.js b/packages/rocketchat-authorization/server/methods/removeUserFromRole.js
new file mode 100644
index 0000000000000..163c672ac39f9
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/removeUserFromRole.js
@@ -0,0 +1,65 @@
+import _ from 'underscore';
+
+Meteor.methods({
+ 'authorization:removeUserFromRole'(roleName, username, scope) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Access permissions is not allowed', {
+ method: 'authorization:removeUserFromRole',
+ action: 'Accessing_permissions'
+ });
+ }
+
+ if (!roleName || !_.isString(roleName) || !username || !_.isString(username)) {
+ throw new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {
+ method: 'authorization:removeUserFromRole'
+ });
+ }
+
+ const user = Meteor.users.findOne({
+ username
+ }, {
+ fields: {
+ _id: 1,
+ roles: 1
+ }
+ });
+
+ if (!user || !user._id) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'authorization:removeUserFromRole'
+ });
+ }
+
+ // prevent removing last user from admin role
+ if (roleName === 'admin') {
+ const adminCount = Meteor.users.find({
+ roles: {
+ $in: ['admin']
+ }
+ }).count();
+
+ const userIsAdmin = user.roles.indexOf('admin') > -1;
+ if (adminCount === 1 && userIsAdmin) {
+ throw new Meteor.Error('error-action-not-allowed', 'Leaving the app without admins is not allowed', {
+ method: 'removeUserFromRole',
+ action: 'Remove_last_admin'
+ });
+ }
+ }
+
+ const remove = RocketChat.models.Roles.removeUserRoles(user._id, roleName, scope);
+ if (RocketChat.settings.get('UI_DisplayRoles')) {
+ RocketChat.Notifications.notifyLogged('roles-change', {
+ type: 'removed',
+ _id: roleName,
+ u: {
+ _id: user._id,
+ username
+ },
+ scope
+ });
+ }
+
+ return remove;
+ }
+});
diff --git a/packages/rocketchat-authorization/server/methods/saveRole.coffee b/packages/rocketchat-authorization/server/methods/saveRole.coffee
deleted file mode 100644
index b90239ec581ef..0000000000000
--- a/packages/rocketchat-authorization/server/methods/saveRole.coffee
+++ /dev/null
@@ -1,17 +0,0 @@
-Meteor.methods
- 'authorization:saveRole': (roleData) ->
- if not Meteor.userId() or not RocketChat.authz.hasPermission Meteor.userId(), 'access-permissions'
- throw new Meteor.Error "error-action-not-allowed", 'Accessing permissions is not allowed', { method: 'authorization:saveRole', action: 'Accessing_permissions' }
-
- if not roleData.name?
- throw new Meteor.Error 'error-role-name-required', 'Role name is required', { method: 'authorization:saveRole' }
-
- if roleData.scope not in ['Users', 'Subscriptions']
- roleData.scope = 'Users'
-
- update = RocketChat.models.Roles.createOrUpdate roleData.name, roleData.scope, roleData.description
-
- if RocketChat.settings.get('UI_DisplayRoles')
- RocketChat.Notifications.notifyLogged('roles-change', { type: 'changed', _id: roleData.name });
-
- return update
diff --git a/packages/rocketchat-authorization/server/methods/saveRole.js b/packages/rocketchat-authorization/server/methods/saveRole.js
new file mode 100644
index 0000000000000..d4223351d2447
--- /dev/null
+++ b/packages/rocketchat-authorization/server/methods/saveRole.js
@@ -0,0 +1,30 @@
+Meteor.methods({
+ 'authorization:saveRole'(roleData) {
+ if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'access-permissions')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Accessing permissions is not allowed', {
+ method: 'authorization:saveRole',
+ action: 'Accessing_permissions'
+ });
+ }
+
+ if (!roleData.name) {
+ throw new Meteor.Error('error-role-name-required', 'Role name is required', {
+ method: 'authorization:saveRole'
+ });
+ }
+
+ if (['Users', 'Subscriptions'].includes(roleData.scope) === false) {
+ roleData.scope = 'Users';
+ }
+
+ const update = RocketChat.models.Roles.createOrUpdate(roleData.name, roleData.scope, roleData.description);
+ if (RocketChat.settings.get('UI_DisplayRoles')) {
+ RocketChat.Notifications.notifyLogged('roles-change', {
+ type: 'changed',
+ _id: roleData.name
+ });
+ }
+
+ return update;
+ }
+});
diff --git a/packages/rocketchat-authorization/server/models/Base.js b/packages/rocketchat-authorization/server/models/Base.js
index 2f41acdc394d5..ea2da8071f271 100644
--- a/packages/rocketchat-authorization/server/models/Base.js
+++ b/packages/rocketchat-authorization/server/models/Base.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
RocketChat.models._Base.prototype.roleBaseQuery = function(/*userId, scope*/) {
return;
};
@@ -34,7 +36,7 @@ RocketChat.models._Base.prototype.removeRolesByUserId = function(userId, roles,
const query = this.roleBaseQuery(userId, scope);
const update = {
$pullAll: {
- roles: roles
+ roles
}
};
return this.update(query, update);
diff --git a/packages/rocketchat-authorization/server/models/Permissions.coffee b/packages/rocketchat-authorization/server/models/Permissions.coffee
deleted file mode 100644
index 3da9a835bef94..0000000000000
--- a/packages/rocketchat-authorization/server/models/Permissions.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-class ModelPermissions extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
-
- # FIND
- findByRole: (role, options) ->
- query =
- roles: role
-
- return @find query, options
-
- findOneById: (_id) ->
- return @findOne _id
-
- createOrUpdate: (name, roles) ->
- @upsert { _id: name }, { $set: { roles: roles } }
-
- addRole: (permission, role) ->
- @update({ _id: permission }, { $addToSet: { roles: role } })
-
- removeRole: (permission, role) ->
- @update({ _id: permission }, { $pull: { roles: role } })
-
-
-RocketChat.models.Permissions = new ModelPermissions('permissions', true)
-RocketChat.models.Permissions.cache.load()
diff --git a/packages/rocketchat-authorization/server/models/Permissions.js b/packages/rocketchat-authorization/server/models/Permissions.js
new file mode 100644
index 0000000000000..a82e0411fca0d
--- /dev/null
+++ b/packages/rocketchat-authorization/server/models/Permissions.js
@@ -0,0 +1,33 @@
+class ModelPermissions extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+ }
+
+ // FIND
+ findByRole(role, options) {
+ const query = {
+ roles: role
+ };
+
+ return this.find(query, options);
+ }
+
+ findOneById(_id) {
+ return this.findOne(_id);
+ }
+
+ createOrUpdate(name, roles) {
+ this.upsert({ _id: name }, { $set: { roles } });
+ }
+
+ addRole(permission, role) {
+ this.update({ _id: permission }, { $addToSet: { roles: role } });
+ }
+
+ removeRole(permission, role) {
+ this.update({ _id: permission }, { $pull: { roles: role } });
+ }
+}
+
+RocketChat.models.Permissions = new ModelPermissions('permissions', true);
+RocketChat.models.Permissions.cache.load();
diff --git a/packages/rocketchat-authorization/server/models/Roles.coffee b/packages/rocketchat-authorization/server/models/Roles.coffee
deleted file mode 100644
index 2759b399c9ab0..0000000000000
--- a/packages/rocketchat-authorization/server/models/Roles.coffee
+++ /dev/null
@@ -1,46 +0,0 @@
-class ModelRoles extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
- @tryEnsureIndex { 'name': 1 }
- @tryEnsureIndex { 'scope': 1 }
-
- findUsersInRole: (name, scope, options) ->
- role = @findOne name
- roleScope = role?.scope or 'Users'
- RocketChat.models[roleScope]?.findUsersInRoles?(name, scope, options)
-
- isUserInRoles: (userId, roles, scope) ->
- roles = [].concat roles
- _.some roles, (roleName) =>
- role = @findOne roleName
- roleScope = role?.scope or 'Users'
- return RocketChat.models[roleScope]?.isUserInRole?(userId, roleName, scope)
-
- createOrUpdate: (name, scope, description, protectedRole) ->
- scope ?= 'Users'
- updateData = {}
- updateData.name = name
- updateData.scope = scope
- if description?
- updateData.description = description
- if protectedRole?
- updateData.protected = protectedRole
-
- @upsert { _id: name }, { $set: updateData }
-
- addUserRoles: (userId, roles, scope) ->
- roles = [].concat roles
- for roleName in roles
- role = @findOne roleName
- roleScope = role?.scope or 'Users'
- RocketChat.models[roleScope]?.addRolesByUserId?(userId, roleName, scope)
-
- removeUserRoles: (userId, roles, scope) ->
- roles = [].concat roles
- for roleName in roles
- role = @findOne roleName
- roleScope = role?.scope or 'Users'
- RocketChat.models[roleScope]?.removeRolesByUserId?(userId, roleName, scope)
-
-RocketChat.models.Roles = new ModelRoles('roles', true)
-RocketChat.models.Roles.cache.load()
diff --git a/packages/rocketchat-authorization/server/models/Roles.js b/packages/rocketchat-authorization/server/models/Roles.js
new file mode 100644
index 0000000000000..8c5f1fed85fac
--- /dev/null
+++ b/packages/rocketchat-authorization/server/models/Roles.js
@@ -0,0 +1,69 @@
+class ModelRoles extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+ this.tryEnsureIndex({ 'name': 1 });
+ this.tryEnsureIndex({ 'scope': 1 });
+ }
+
+ findUsersInRole(name, scope, options) {
+ const role = this.findOne(name);
+ const roleScope = (role && role.scope) || 'Users';
+ const model = RocketChat.models[roleScope];
+
+ return model && model.findUsersInRoles && model.findUsersInRoles(name, scope, options);
+ }
+
+ isUserInRoles(userId, roles, scope) {
+ roles = [].concat(roles);
+ return roles.some((roleName) => {
+ const role = this.findOne(roleName);
+ const roleScope = (role && role.scope) || 'Users';
+ const model = RocketChat.models[roleScope];
+
+ return model && model.isUserInRole && model.isUserInRole(userId, roleName, scope);
+ });
+ }
+
+ createOrUpdate(name, scope = 'Users', description, protectedRole) {
+ const updateData = {};
+ updateData.name = name;
+ updateData.scope = scope;
+
+ if (description != null) {
+ updateData.description = description;
+ }
+
+ if (protectedRole) {
+ updateData.protected = protectedRole;
+ }
+
+ this.upsert({ _id: name }, { $set: updateData });
+ }
+
+ addUserRoles(userId, roles, scope) {
+ roles = [].concat(roles);
+ for (const roleName of roles) {
+ const role = this.findOne(roleName);
+ const roleScope = (role && role.scope) || 'Users';
+ const model = RocketChat.models[roleScope];
+
+ model && model.addRolesByUserId && model.addRolesByUserId(userId, roleName, scope);
+ }
+ return true;
+ }
+
+ removeUserRoles(userId, roles, scope) {
+ roles = [].concat(roles);
+ for (const roleName of roles) {
+ const role = this.findOne(roleName);
+ const roleScope = (role && role.scope) || 'Users';
+ const model = RocketChat.models[roleScope];
+
+ model && model.removeRolesByUserId && model.removeRolesByUserId(userId, roleName, scope);
+ }
+ return true;
+ }
+}
+
+RocketChat.models.Roles = new ModelRoles('roles', true);
+RocketChat.models.Roles.cache.load();
diff --git a/packages/rocketchat-authorization/server/models/Subscriptions.js b/packages/rocketchat-authorization/server/models/Subscriptions.js
index 06a0f62e2221c..2fc269e4e8731 100644
--- a/packages/rocketchat-authorization/server/models/Subscriptions.js
+++ b/packages/rocketchat-authorization/server/models/Subscriptions.js
@@ -1,9 +1,11 @@
+import _ from 'underscore';
+
RocketChat.models.Subscriptions.roleBaseQuery = function(userId, scope) {
if (scope == null) {
return;
}
- var query = { 'u._id': userId };
+ const query = { 'u._id': userId };
if (!_.isUndefined(scope)) {
query.rid = scope;
}
@@ -13,7 +15,7 @@ RocketChat.models.Subscriptions.roleBaseQuery = function(userId, scope) {
RocketChat.models.Subscriptions.findUsersInRoles = function(roles, scope, options) {
roles = [].concat(roles);
- var query = {
+ const query = {
roles: { $in: roles }
};
@@ -21,9 +23,9 @@ RocketChat.models.Subscriptions.findUsersInRoles = function(roles, scope, option
query.rid = scope;
}
- var subscriptions = this.find(query).fetch();
+ const subscriptions = this.find(query).fetch();
- var users = _.compact(_.map(subscriptions, function(subscription) {
+ const users = _.compact(_.map(subscriptions, function(subscription) {
if ('undefined' !== typeof subscription.u && 'undefined' !== typeof subscription.u._id) {
return subscription.u._id;
}
diff --git a/packages/rocketchat-authorization/server/models/Users.js b/packages/rocketchat-authorization/server/models/Users.js
index efb3849b5ce61..f47dff1e13655 100644
--- a/packages/rocketchat-authorization/server/models/Users.js
+++ b/packages/rocketchat-authorization/server/models/Users.js
@@ -5,7 +5,7 @@ RocketChat.models.Users.roleBaseQuery = function(userId) {
RocketChat.models.Users.findUsersInRoles = function(roles, scope, options) {
roles = [].concat(roles);
- var query = {
+ const query = {
roles: { $in: roles }
};
diff --git a/packages/rocketchat-authorization/server/publications/roles.coffee b/packages/rocketchat-authorization/server/publications/roles.coffee
deleted file mode 100644
index b3eafb56d3e50..0000000000000
--- a/packages/rocketchat-authorization/server/publications/roles.coffee
+++ /dev/null
@@ -1,6 +0,0 @@
-Meteor.publish 'roles', ->
- unless @userId
- return @ready()
-
- return RocketChat.models.Roles.find()
-
diff --git a/packages/rocketchat-authorization/server/publications/roles.js b/packages/rocketchat-authorization/server/publications/roles.js
new file mode 100644
index 0000000000000..a7e8625c9f239
--- /dev/null
+++ b/packages/rocketchat-authorization/server/publications/roles.js
@@ -0,0 +1,7 @@
+Meteor.publish('roles', function() {
+ if (!this.userId) {
+ return this.ready();
+ }
+
+ return RocketChat.models.Roles.find();
+});
diff --git a/packages/rocketchat-authorization/server/publications/usersInRole.coffee b/packages/rocketchat-authorization/server/publications/usersInRole.coffee
deleted file mode 100644
index 99f45244f8c7c..0000000000000
--- a/packages/rocketchat-authorization/server/publications/usersInRole.coffee
+++ /dev/null
@@ -1,13 +0,0 @@
-Meteor.publish 'usersInRole', (roleName, scope, limit = 50) ->
- unless @userId
- return @ready()
-
- if not RocketChat.authz.hasPermission @userId, 'access-permissions'
- return @error new Meteor.Error "error-not-allowed", 'Not allowed', { publish: 'usersInRole' }
-
- options =
- limit: limit
- sort:
- name: 1
-
- return RocketChat.authz.getUsersInRole roleName, scope, options
diff --git a/packages/rocketchat-authorization/server/publications/usersInRole.js b/packages/rocketchat-authorization/server/publications/usersInRole.js
new file mode 100644
index 0000000000000..2093798661705
--- /dev/null
+++ b/packages/rocketchat-authorization/server/publications/usersInRole.js
@@ -0,0 +1,20 @@
+Meteor.publish('usersInRole', function(roleName, scope, limit = 50) {
+ if (!this.userId) {
+ return this.ready();
+ }
+
+ if (!RocketChat.authz.hasPermission(this.userId, 'access-permissions')) {
+ return this.error(new Meteor.Error('error-not-allowed', 'Not allowed', {
+ publish: 'usersInRole'
+ }));
+ }
+
+ const options = {
+ limit,
+ sort: {
+ name: 1
+ }
+ };
+
+ return RocketChat.authz.getUsersInRole(roleName, scope, options);
+});
diff --git a/packages/rocketchat-authorization/server/startup.coffee b/packages/rocketchat-authorization/server/startup.coffee
deleted file mode 100644
index 1037dcaf5e8c7..0000000000000
--- a/packages/rocketchat-authorization/server/startup.coffee
+++ /dev/null
@@ -1,75 +0,0 @@
-Meteor.startup ->
-
- # Note:
- # 1.if we need to create a role that can only edit channel message, but not edit group message
- # then we can define edit--message instead of edit-message
- # 2. admin, moderator, and user roles should not be deleted as they are referened in the code.
- permissions = [
- { _id: 'access-permissions', roles : ['admin'] }
- { _id: 'add-oauth-service', roles : ['admin'] }
- { _id: 'add-user-to-room', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'archive-room', roles : ['admin', 'owner'] }
- { _id: 'assign-admin-role', roles : ['admin'] }
- { _id: 'ban-user', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'bulk-create-c', roles : ['admin'] }
- { _id: 'bulk-register-user', roles : ['admin'] }
- { _id: 'create-c', roles : ['admin', 'user', 'bot'] }
- { _id: 'create-d', roles : ['admin', 'user', 'bot'] }
- { _id: 'create-p', roles : ['admin', 'user', 'bot'] }
- { _id: 'create-user', roles : ['admin'] }
- { _id: 'clean-channel-history', roles : ['admin'] } # special permission to bulk delete a channel's mesages
- { _id: 'delete-c', roles : ['admin'] }
- { _id: 'delete-d', roles : ['admin'] }
- { _id: 'delete-message', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'delete-p', roles : ['admin'] }
- { _id: 'delete-user', roles : ['admin'] }
- { _id: 'edit-message', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'edit-other-user-active-status', roles : ['admin'] }
- { _id: 'edit-other-user-info', roles : ['admin'] }
- { _id: 'edit-other-user-password', roles : ['admin'] }
- { _id: 'edit-privileged-setting', roles : ['admin'] }
- { _id: 'edit-room', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'manage-assets', roles : ['admin'] }
- { _id: 'manage-emoji', roles : ['admin'] }
- { _id: 'manage-integrations', roles : ['admin'] }
- { _id: 'manage-own-integrations', roles : ['admin', 'bot'] }
- { _id: 'manage-oauth-apps', roles : ['admin'] }
- { _id: 'mention-all', roles : ['admin', 'owner', 'moderator', 'user'] }
- { _id: 'mute-user', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'remove-user', roles : ['admin', 'owner', 'moderator'] }
- { _id: 'run-import', roles : ['admin'] }
- { _id: 'run-migration', roles : ['admin'] }
- { _id: 'set-moderator', roles : ['admin', 'owner'] }
- { _id: 'set-owner', roles : ['admin', 'owner'] }
- { _id: 'unarchive-room', roles : ['admin'] }
- { _id: 'view-c-room', roles : ['admin', 'user', 'bot'] }
- { _id: 'view-d-room', roles : ['admin', 'user', 'bot'] }
- { _id: 'view-full-other-user-info', roles : ['admin'] }
- { _id: 'view-history', roles : ['admin', 'user'] }
- { _id: 'view-joined-room', roles : ['guest', 'bot'] }
- { _id: 'view-join-code', roles : ['admin'] }
- { _id: 'view-logs', roles : ['admin'] }
- { _id: 'view-other-user-channels', roles : ['admin'] }
- { _id: 'view-p-room', roles : ['admin', 'user'] }
- { _id: 'view-privileged-setting', roles : ['admin'] }
- { _id: 'view-room-administration', roles : ['admin'] }
- { _id: 'view-statistics', roles : ['admin'] }
- { _id: 'view-user-administration', roles : ['admin'] }
- { _id: 'preview-c-room', roles : ['admin', 'user'] }
- ]
-
- for permission in permissions
- unless RocketChat.models.Permissions.findOneById( permission._id)?
- RocketChat.models.Permissions.upsert( permission._id, {$set: permission })
-
- defaultRoles = [
- { name: 'admin', scope: 'Users', description: 'Admin' }
- { name: 'moderator', scope: 'Subscriptions', description: 'Moderator' }
- { name: 'owner', scope: 'Subscriptions', description: 'Owner' }
- { name: 'user', scope: 'Users', description: '' }
- { name: 'bot', scope: 'Users', description: '' }
- { name: 'guest', scope: 'Users', description: '' }
- ]
-
- for role in defaultRoles
- RocketChat.models.Roles.upsert { _id: role.name }, { $setOnInsert: { scope: role.scope, description: role.description || '', protected: true } }
diff --git a/packages/rocketchat-authorization/server/startup.js b/packages/rocketchat-authorization/server/startup.js
new file mode 100644
index 0000000000000..10b8846b01e20
--- /dev/null
+++ b/packages/rocketchat-authorization/server/startup.js
@@ -0,0 +1,91 @@
+/* eslint no-multi-spaces: 0 */
+
+Meteor.startup(function() {
+ // Note:
+ // 1.if we need to create a role that can only edit channel message, but not edit group message
+ // then we can define edit--message instead of edit-message
+ // 2. admin, moderator, and user roles should not be deleted as they are referened in the code.
+ const permissions = [
+ { _id: 'access-permissions', roles : ['admin'] },
+ { _id: 'add-oauth-service', roles : ['admin'] },
+ { _id: 'add-user-to-joined-room', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'add-user-to-any-c-room', roles : ['admin'] },
+ { _id: 'add-user-to-any-p-room', roles : [] },
+ { _id: 'archive-room', roles : ['admin', 'owner'] },
+ { _id: 'assign-admin-role', roles : ['admin'] },
+ { _id: 'ban-user', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'bulk-create-c', roles : ['admin'] },
+ { _id: 'bulk-register-user', roles : ['admin'] },
+ { _id: 'create-c', roles : ['admin', 'user', 'bot'] },
+ { _id: 'create-d', roles : ['admin', 'user', 'bot'] },
+ { _id: 'create-p', roles : ['admin', 'user', 'bot'] },
+ { _id: 'create-user', roles : ['admin'] },
+ { _id: 'clean-channel-history', roles : ['admin'] }, // special permission to bulk delete a channel's mesages
+ { _id: 'delete-c', roles : ['admin'] },
+ { _id: 'delete-d', roles : ['admin'] },
+ { _id: 'delete-message', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'delete-p', roles : ['admin'] },
+ { _id: 'delete-user', roles : ['admin'] },
+ { _id: 'edit-message', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'edit-other-user-active-status', roles : ['admin'] },
+ { _id: 'edit-other-user-info', roles : ['admin'] },
+ { _id: 'edit-other-user-password', roles : ['admin'] },
+ { _id: 'edit-privileged-setting', roles : ['admin'] },
+ { _id: 'edit-room', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'force-delete-message', roles : ['admin', 'owner'] },
+ { _id: 'join-without-join-code', roles : ['admin', 'bot'] },
+ { _id: 'manage-assets', roles : ['admin'] },
+ { _id: 'manage-emoji', roles : ['admin'] },
+ { _id: 'manage-integrations', roles : ['admin'] },
+ { _id: 'manage-own-integrations', roles : ['admin', 'bot'] },
+ { _id: 'manage-oauth-apps', roles : ['admin'] },
+ { _id: 'mention-all', roles : ['admin', 'owner', 'moderator', 'user'] },
+ { _id: 'mention-here', roles : ['admin', 'owner', 'moderator', 'user'] },
+ { _id: 'mute-user', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'remove-user', roles : ['admin', 'owner', 'moderator'] },
+ { _id: 'run-import', roles : ['admin'] },
+ { _id: 'run-migration', roles : ['admin'] },
+ { _id: 'set-moderator', roles : ['admin', 'owner'] },
+ { _id: 'set-owner', roles : ['admin', 'owner'] },
+ { _id: 'send-many-messages', roles : ['admin', 'bot'] },
+ { _id: 'set-leader', roles : ['admin', 'owner'] },
+ { _id: 'unarchive-room', roles : ['admin'] },
+ { _id: 'view-c-room', roles : ['admin', 'user', 'bot', 'anonymous'] },
+ { _id: 'user-generate-access-token', roles : ['admin'] },
+ { _id: 'view-d-room', roles : ['admin', 'user', 'bot'] },
+ { _id: 'view-full-other-user-info', roles : ['admin'] },
+ { _id: 'view-history', roles : ['admin', 'user', 'anonymous'] },
+ { _id: 'view-joined-room', roles : ['guest', 'bot', 'anonymous'] },
+ { _id: 'view-join-code', roles : ['admin'] },
+ { _id: 'view-logs', roles : ['admin'] },
+ { _id: 'view-other-user-channels', roles : ['admin'] },
+ { _id: 'view-p-room', roles : ['admin', 'user', 'anonymous'] },
+ { _id: 'view-privileged-setting', roles : ['admin'] },
+ { _id: 'view-room-administration', roles : ['admin'] },
+ { _id: 'view-statistics', roles : ['admin'] },
+ { _id: 'view-user-administration', roles : ['admin'] },
+ { _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] },
+ { _id: 'view-outside-room', roles : ['admin', 'owner', 'moderator', 'user'] }
+ ];
+
+ for (const permission of permissions) {
+ if (!RocketChat.models.Permissions.findOneById(permission._id)) {
+ RocketChat.models.Permissions.upsert(permission._id, {$set: permission });
+ }
+ }
+
+ const defaultRoles = [
+ { name: 'admin', scope: 'Users', description: 'Admin' },
+ { name: 'moderator', scope: 'Subscriptions', description: 'Moderator' },
+ { name: 'leader', scope: 'Subscriptions', description: 'Leader' },
+ { name: 'owner', scope: 'Subscriptions', description: 'Owner' },
+ { name: 'user', scope: 'Users', description: '' },
+ { name: 'bot', scope: 'Users', description: '' },
+ { name: 'guest', scope: 'Users', description: '' },
+ { name: 'anonymous', scope: 'Users', description: '' }
+ ];
+
+ for (const role of defaultRoles) {
+ RocketChat.models.Roles.upsert({ _id: role.name }, { $setOnInsert: { scope: role.scope, description: role.description || '', protected: true } });
+ }
+});
diff --git a/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 469351e76fd8e..0000000000000
--- a/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "dependencies": {
- "autolinker": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.4.0.tgz",
- "from": "autolinker@1.4.0"
- }
- }
-}
diff --git a/packages/rocketchat-autolinker/client.js b/packages/rocketchat-autolinker/client.js
deleted file mode 100644
index fc4d3fe335421..0000000000000
--- a/packages/rocketchat-autolinker/client.js
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// AutoLinker is a named function that will replace links on messages
-// @param {Object} message - The message object
-//
-
-import Autolinker from 'autolinker';
-
-function AutoLinker(message) {
- if (_.trim(message.html)) {
- const regUrls = new RegExp(RocketChat.settings.get('AutoLinker_UrlsRegExp'));
-
- const autolinker = new Autolinker({
- stripPrefix: RocketChat.settings.get('AutoLinker_StripPrefix'),
- urls: {
- schemeMatches: RocketChat.settings.get('AutoLinker_Urls_Scheme'),
- wwwMatches: RocketChat.settings.get('AutoLinker_Urls_www'),
- tldMatches: RocketChat.settings.get('AutoLinker_Urls_TLD')
- },
- email: RocketChat.settings.get('AutoLinker_Email'),
- phone: RocketChat.settings.get('AutoLinker_Phone'),
- twitter: false,
- replaceFn(match) {
- if (match.getType() === 'url') {
- if (regUrls.test(match.matchedText)) {
- if (match.matchedText.indexOf(Meteor.absoluteUrl()) === 0) {
- const tag = match.buildTag(); // returns an `Autolinker.HtmlTag` instance for an tag
- tag.setAttr('target', ''); // sets target to empty, instead of _blank
- return tag;
- }
-
- return true;
- }
- }
-
- return null;
- }
- });
-
- let regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)/;
- if (RocketChat.settings.get('Katex_Enabled')) {
- regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)|(\\\(\w*[\n ]?[\s\S]*?\\\)+?)/;
- }
-
- // Separate text in code blocks and non code blocks
- const msgParts = message.html.split(regNonAutoLink);
-
- msgParts.forEach((part, index) => {
- if (part && part.length > 0) {
- // Verify if this part is code
- const codeMatch = part.match(regNonAutoLink);
- if (!codeMatch) {
- msgParts[index] = autolinker.link(part);
- }
- }
- });
-
- // Re-mount message
- message.html = msgParts.join('');
- }
-
- return message;
-}
-
-RocketChat.callbacks.add('renderMessage', AutoLinker);
diff --git a/packages/rocketchat-autolinker/client/client.js b/packages/rocketchat-autolinker/client/client.js
new file mode 100644
index 0000000000000..60c18123d0073
--- /dev/null
+++ b/packages/rocketchat-autolinker/client/client.js
@@ -0,0 +1,73 @@
+import s from 'underscore.string';
+
+//
+// AutoLinker is a named function that will replace links on messages
+// @param {Object} message - The message object
+//
+
+import Autolinker from 'autolinker';
+
+function AutoLinker(message) {
+ if (RocketChat.settings.get('AutoLinker') !== true) {
+ return message;
+ }
+
+ if (s.trim(message.html)) {
+ const regUrls = new RegExp(RocketChat.settings.get('AutoLinker_UrlsRegExp'));
+
+ const autolinker = new Autolinker({
+ stripPrefix: RocketChat.settings.get('AutoLinker_StripPrefix'),
+ urls: {
+ schemeMatches: RocketChat.settings.get('AutoLinker_Urls_Scheme'),
+ wwwMatches: RocketChat.settings.get('AutoLinker_Urls_www'),
+ tldMatches: RocketChat.settings.get('AutoLinker_Urls_TLD')
+ },
+ email: RocketChat.settings.get('AutoLinker_Email'),
+ phone: RocketChat.settings.get('AutoLinker_Phone'),
+ twitter: false,
+ stripTrailingSlash: false,
+ replaceFn(match) {
+ if (match.getType() === 'url') {
+ if (regUrls.test(match.matchedText)) {
+ if (match.matchedText.indexOf(Meteor.absoluteUrl()) === 0) {
+ // returns an `Autolinker.HtmlTag` instance for an tag
+ const tag = match.buildTag();
+ // sets target to empty, instead of _blank
+ tag.setAttr('target', '');
+ return tag;
+ }
+
+ return true;
+ }
+ }
+
+ return null;
+ }
+ });
+
+ let regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)/;
+ if (RocketChat.settings.get('Katex_Enabled')) {
+ regNonAutoLink = /(```\w*[\n ]?[\s\S]*?```+?)|(`(?:[^`]+)`)|(\\\(\w*[\n ]?[\s\S]*?\\\)+?)/;
+ }
+
+ // Separate text in code blocks and non code blocks
+ const msgParts = message.html.split(regNonAutoLink);
+
+ msgParts.forEach((part, index) => {
+ if (part && part.length > 0) {
+ // Verify if this part is code
+ const codeMatch = part.match(regNonAutoLink);
+ if (!codeMatch) {
+ msgParts[index] = autolinker.link(part);
+ }
+ }
+ });
+
+ // Re-mount message
+ message.html = msgParts.join('');
+ }
+
+ return message;
+}
+
+RocketChat.callbacks.add('renderMessage', AutoLinker);
diff --git a/packages/rocketchat-autolinker/package.js b/packages/rocketchat-autolinker/package.js
index 5ce89297d45c8..62a9f26ec9fa6 100644
--- a/packages/rocketchat-autolinker/package.js
+++ b/packages/rocketchat-autolinker/package.js
@@ -5,15 +5,11 @@ Package.describe({
git: ''
});
-Npm.depends({
- autolinker: '1.4.0'
-});
-
Package.onUse(function(api) {
api.use('ecmascript');
api.use('rocketchat:lib');
- api.addFiles('client.js', 'client');
+ api.addFiles('client/client.js', 'client');
- api.addFiles('settings.js', 'server');
+ api.addFiles('server/settings.js', 'server');
});
diff --git a/packages/rocketchat-autolinker/server/settings.js b/packages/rocketchat-autolinker/server/settings.js
new file mode 100644
index 0000000000000..06edeee4055d4
--- /dev/null
+++ b/packages/rocketchat-autolinker/server/settings.js
@@ -0,0 +1,16 @@
+Meteor.startup(function() {
+ const enableQuery = {
+ _id: 'AutoLinker',
+ value: true
+ };
+
+ RocketChat.settings.add('AutoLinker', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, i18nLabel: 'Enabled'});
+
+ RocketChat.settings.add('AutoLinker_StripPrefix', false, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, i18nDescription: 'AutoLinker_StripPrefix_Description', enableQuery});
+ RocketChat.settings.add('AutoLinker_Urls_Scheme', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, enableQuery});
+ RocketChat.settings.add('AutoLinker_Urls_www', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, enableQuery});
+ RocketChat.settings.add('AutoLinker_Urls_TLD', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, enableQuery});
+ RocketChat.settings.add('AutoLinker_UrlsRegExp', '(://|www\\.).+', {type: 'string', group: 'Message', section: 'AutoLinker', public: true, enableQuery});
+ RocketChat.settings.add('AutoLinker_Email', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, enableQuery});
+ RocketChat.settings.add('AutoLinker_Phone', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, i18nDescription: 'AutoLinker_Phone_Description', enableQuery});
+});
diff --git a/packages/rocketchat-autolinker/settings.js b/packages/rocketchat-autolinker/settings.js
deleted file mode 100644
index 72205b5547aba..0000000000000
--- a/packages/rocketchat-autolinker/settings.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Meteor.startup(function() {
- RocketChat.settings.add('AutoLinker_StripPrefix', false, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, i18nDescription: 'AutoLinker_StripPrefix_Description'});
- RocketChat.settings.add('AutoLinker_Urls_Scheme', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true});
- RocketChat.settings.add('AutoLinker_Urls_www', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true});
- RocketChat.settings.add('AutoLinker_Urls_TLD', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true});
- RocketChat.settings.add('AutoLinker_UrlsRegExp', '(://|www\\.).+', {type: 'string', group: 'Message', section: 'AutoLinker', public: true});
- RocketChat.settings.add('AutoLinker_Email', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true});
- RocketChat.settings.add('AutoLinker_Phone', true, {type: 'boolean', group: 'Message', section: 'AutoLinker', public: true, i18nDescription: 'AutoLinker_Phone_Description'});
-});
diff --git a/packages/rocketchat-autotranslate/README.md b/packages/rocketchat-autotranslate/README.md
new file mode 100644
index 0000000000000..41921fb0cd80f
--- /dev/null
+++ b/packages/rocketchat-autotranslate/README.md
@@ -0,0 +1,5 @@
+# Rocket.Chat Auto Translate
+
+Rocket.Chat supports auto translate through Google Cloud Translation API
+Through this you will be able to read messages in your native languages
+regardless of language the message was written on.
diff --git a/packages/rocketchat-autotranslate/client/lib/actionButton.js b/packages/rocketchat-autotranslate/client/lib/actionButton.js
new file mode 100644
index 0000000000000..e8289f61dd825
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/lib/actionButton.js
@@ -0,0 +1,34 @@
+Meteor.startup(function() {
+ Tracker.autorun(function() {
+ if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) {
+ RocketChat.MessageAction.addButton({
+ id: 'toggle-language',
+ icon: 'icon-language',
+ label: 'Toggle_original_translated',
+ context: [
+ 'message',
+ 'message-mobile'
+ ],
+ action() {
+ const message = this._arguments[1];
+ const language = RocketChat.AutoTranslate.getLanguage(message.rid);
+ if ((!message.translations || !message.translations[language])) { //} && !_.find(message.attachments, attachment => { return attachment.translations && attachment.translations[language]; })) {
+ RocketChat.AutoTranslate.messageIdsToWait[message._id] = true;
+ RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } });
+ Meteor.call('autoTranslate.translateMessage', message, language);
+ } else if (message.autoTranslateShowInverse) {
+ RocketChat.models.Messages.update({ _id: message._id }, { $unset: { autoTranslateShowInverse: true } });
+ } else {
+ RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowInverse: true } });
+ }
+ },
+ condition(message) {
+ return message && message.u && message.u._id !== Meteor.userId();
+ },
+ order: 90
+ });
+ } else {
+ RocketChat.MessageAction.removeButton('toggle-language');
+ }
+ });
+});
diff --git a/packages/rocketchat-autotranslate/client/lib/autotranslate.js b/packages/rocketchat-autotranslate/client/lib/autotranslate.js
new file mode 100644
index 0000000000000..3d8066eba0550
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/lib/autotranslate.js
@@ -0,0 +1,94 @@
+import _ from 'underscore';
+
+RocketChat.AutoTranslate = {
+ messageIdsToWait: {},
+ supportedLanguages: [],
+
+ getLanguage(rid) {
+ let subscription = {};
+ if (rid) {
+ subscription = RocketChat.models.Subscriptions.findOne({ rid }, { fields: { autoTranslateLanguage: 1 } });
+ }
+ const language = subscription && subscription.autoTranslateLanguage || Meteor.user().language || window.defaultUserLanguage();
+ if (language.indexOf('-') !== -1) {
+ if (!_.findWhere(this.supportedLanguages, { language })) {
+ return language.substr(0, 2);
+ }
+ }
+ return language;
+ },
+
+ translateAttachments(attachments, language) {
+ for (const attachment of attachments) {
+ if (attachment.author_name !== Meteor.user().username) {
+ if (attachment.text && attachment.translations && attachment.translations[language]) {
+ attachment.text = attachment.translations[language];
+ }
+
+ if (attachment.description && attachment.translations && attachment.translations[language]) {
+ attachment.description = attachment.translations[language];
+ }
+
+ if (attachment.attachments && attachment.attachments.length > 0) {
+ attachment.attachments = this.translateAttachments(attachment.attachments, language);
+ }
+ }
+ }
+ return attachments;
+ },
+
+ init() {
+ Meteor.call('autoTranslate.getSupportedLanguages', 'en', (err, languages) => {
+ this.supportedLanguages = languages || [];
+ });
+
+ Tracker.autorun(() => {
+ if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) {
+ RocketChat.callbacks.add('renderMessage', (message) => {
+ const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1 } });
+ const autoTranslateLanguage = this.getLanguage(message.rid);
+ if (message.u && message.u._id !== Meteor.userId()) {
+ if (!message.translations) {
+ message.translations = {};
+ }
+ if (subscription && subscription.autoTranslate !== message.autoTranslateShowInverse) {
+ message.translations['original'] = message.html;
+ if (message.translations[autoTranslateLanguage]) {
+ message.html = message.translations[autoTranslateLanguage];
+ }
+
+ if (message.attachments && message.attachments.length > 0) {
+ message.attachments = this.translateAttachments(message.attachments, autoTranslateLanguage);
+ }
+ }
+ } else if (message.attachments && message.attachments.length > 0) {
+ message.attachments = this.translateAttachments(message.attachments, autoTranslateLanguage);
+ }
+ return message;
+ }, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate');
+
+ RocketChat.callbacks.add('streamMessage', (message) => {
+ if (message.u && message.u._id !== Meteor.userId()) {
+ const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1 } });
+ const language = this.getLanguage(message.rid);
+ if (subscription && subscription.autoTranslate === true && ((message.msg && (!message.translations || !message.translations[language])))) { // || (message.attachments && !_.find(message.attachments, attachment => { return attachment.translations && attachment.translations[language]; }))
+ RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } });
+ } else if (this.messageIdsToWait[message._id] !== undefined && subscription && subscription.autoTranslate !== true) {
+ RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowInverse: true }, $unset: { autoTranslateFetching: true } });
+ delete this.messageIdsToWait[message._id];
+ } else if (message.autoTranslateFetching === true) {
+ RocketChat.models.Messages.update({ _id: message._id }, { $unset: { autoTranslateFetching: true } });
+ }
+ }
+ }, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate-stream');
+ } else {
+ RocketChat.callbacks.remove('renderMessage', 'autotranslate');
+ RocketChat.callbacks.remove('streamMessage', 'autotranslate-stream');
+ }
+ });
+ }
+};
+
+Meteor.startup(function() {
+ RocketChat.AutoTranslate.init();
+});
diff --git a/packages/rocketchat-autotranslate/client/lib/tabBar.js b/packages/rocketchat-autotranslate/client/lib/tabBar.js
new file mode 100644
index 0000000000000..20afbe1a3a778
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/lib/tabBar.js
@@ -0,0 +1,16 @@
+Meteor.startup(function() {
+ Tracker.autorun(function() {
+ if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) {
+ RocketChat.TabBar.addButton({
+ groups: ['channel', 'group', 'direct'],
+ id: 'autotranslate',
+ i18nTitle: 'Auto_Translate',
+ icon: 'language',
+ template: 'autoTranslateFlexTab',
+ order: 20
+ });
+ } else {
+ RocketChat.TabBar.removeButton('autotranslate');
+ }
+ });
+});
diff --git a/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.css b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.css
new file mode 100644
index 0000000000000..480502c4371e3
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.css
@@ -0,0 +1,63 @@
+.flex-tab {
+ & .autotranslate {
+ & ul {
+ & li {
+ margin-bottom: 20px;
+ }
+ }
+
+ & form {
+ & label {
+ display: block;
+
+ margin-bottom: 5px;
+
+ font-weight: bold;
+ }
+
+ & div span {
+ font-size: 14px;
+
+ & i.icon-pencil {
+ margin-left: 3px;
+
+ font-size: 12px;
+ }
+ }
+ }
+
+ & .submit {
+ margin-top: 30px;
+
+ text-align: center;
+ }
+
+ & [data-edit] {
+ cursor: pointer;
+ }
+ }
+}
+
+.message {
+ & .translated {
+ margin-left: 3px;
+ padding-left: 3px;
+
+ border-left: 1px dotted;
+
+ & i.icon-language.loading {
+ display: inline-block;
+
+ animation: spinh 2000ms infinite linear;
+ }
+ }
+
+ &.sequential {
+ & .translated {
+ position: absolute;
+ left: 5px;
+
+ border-left: 0;
+ }
+ }
+}
diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html
new file mode 100644
index 0000000000000..5e5d74daeabad
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html
@@ -0,0 +1,45 @@
+
+
+ {{#requiresPermission 'auto-translate'}}
+
+
+
{{_ "Auto_Translate"}}
+
+
+
+ {{/requiresPermission}}
+
+
diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js
new file mode 100644
index 0000000000000..7778b73456343
--- /dev/null
+++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js
@@ -0,0 +1,167 @@
+/* globals ChatSubscription */
+import _ from 'underscore';
+import toastr from 'toastr';
+
+Template.autoTranslateFlexTab.helpers({
+ autoTranslate() {
+ const sub = ChatSubscription.findOne({
+ rid: Template.instance().rid
+ }, {
+ fields: {
+ autoTranslate: 1
+ }
+ });
+ return sub && sub.autoTranslate ? true : false;
+ },
+
+ autoTranslateValue() {
+ const sub = ChatSubscription.findOne({
+ rid: Template.instance().rid
+ }, {
+ fields: {
+ autoTranslate: 1
+ }
+ });
+ return sub && sub.autoTranslate ? t('True') : t('False');
+ },
+
+ autoTranslateLanguage() {
+ const sub = ChatSubscription.findOne({
+ rid: Template.instance().rid
+ }, {
+ fields: {
+ autoTranslateLanguage: 1
+ }
+ });
+ const autoTranslateLanguage = sub && sub.autoTranslateLanguage || Meteor.user().language || window.defaultUserLanguage() || '';
+ const supportedLanguages = Template.instance().supportedLanguages.get();
+ let language = _.findWhere(supportedLanguages, { language: autoTranslateLanguage });
+ if (language) {
+ return language.language;
+ } else if (autoTranslateLanguage.indexOf('-') !== -1) {
+ language = _.findWhere(supportedLanguages, { language: autoTranslateLanguage.substr(0, 2) });
+ return language && language.language;
+ }
+ },
+
+ editing(field) {
+ return Template.instance().editing.get() === field;
+ },
+
+ supportedLanguages() {
+ return Template.instance().supportedLanguages.get();
+ },
+
+ languageName(targetLanguage) {
+ if (targetLanguage) {
+ const supportedLanguages = Template.instance().supportedLanguages.get();
+ let language = _.findWhere(supportedLanguages, { language: targetLanguage });
+ if (language) {
+ return language.name;
+ } else if (targetLanguage.indexOf('-') !== -1) {
+ language = _.findWhere(supportedLanguages, { language: targetLanguage.substr(0, 2) });
+ return language && language.name;
+ }
+ }
+ }
+});
+
+Template.autoTranslateFlexTab.onCreated(function() {
+ this.rid = Template.currentData().rid;
+ this.editing = new ReactiveVar();
+ this.supportedLanguages = new ReactiveVar([]);
+ const userLanguage = Meteor.user().language || window.defaultUserLanguage();
+ Meteor.call('autoTranslate.getSupportedLanguages', userLanguage, (err, languages) => {
+ this.supportedLanguages.set(languages || []);
+ });
+
+ this.validateSetting = (field) => {
+ let value;
+ switch (field) {
+ case 'autoTranslate':
+ return true;
+ case 'autoTranslateLanguage':
+ value = this.$(`select[name=${ field }]`).val();
+ if (!_.findWhere(this.supportedLanguages.get(), { language: value })) {
+ toastr.error(t('Invalid_setting_s', value || ''));
+ return false;
+ }
+ return true;
+ }
+ };
+
+ this.saveSetting = () => {
+ const field = this.editing.get();
+ const subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid, 'u._id': Meteor.userId() });
+ const previousLanguage = subscription.autoTranslateLanguage;
+ let value;
+ switch (field) {
+ case 'autoTranslate':
+ value = this.$(`input[name=${ field }]`).prop('checked') ? '1' : '0';
+ break;
+ case 'autoTranslateLanguage':
+ value = this.$(`select[name=${ field }]`).val();
+ break;
+ }
+
+ if (this.validateSetting(field)) {
+ Meteor.call('autoTranslate.saveSettings', this.data.rid, field, value, { defaultLanguage: Meteor.user().language || window.defaultUserLanguage() }, (err/*, result*/) => {
+ if (err) {
+ return handleError(err);
+ }
+
+ const query = { rid: this.data.rid, 'u._id': { $ne: Meteor.userId() } };
+ if (field === 'autoTranslateLanguage') {
+ query.$or = [ { [`translations.${ previousLanguage }`]: { $exists: 1 } }, { [`translations.${ value }`]: { $exists: 1 } }, { [`attachments.translations.${ previousLanguage }`]: { $exists: 1 } }, { [`attachments.translations.${ value }`]: { $exists: 1 } } ];
+ } else {
+ query.$or = [ { [`translations.${ subscription.autoTranslateLanguage }`]: { $exists: 1 } }, { [`attachments.translations.${ subscription.autoTranslateLanguage }`]: { $exists: 1 } } ];
+ }
+
+ if (field === 'autoTranslate' && value === '0') {
+ RocketChat.models.Messages.update(query, { $unset: { autoTranslateShowInverse: 1 } }, { multi: true });
+ }
+
+ const display = field === 'autoTranslate' ? true : subscription && subscription.autoTranslate;
+ if (display) {
+ query.autoTranslateShowInverse = { $ne: true };
+ } else {
+ query.autoTranslateShowInverse = true;
+ }
+
+ RocketChat.models.Messages.update(query, { $set: { random: Random.id() } }, { multi: true });
+
+ this.editing.set();
+ });
+ }
+ };
+});
+
+Template.autoTranslateFlexTab.events({
+ 'keydown input[type=text]'(e, instance) {
+ if (e.keyCode === 13) {
+ e.preventDefault();
+ instance.saveSetting();
+ }
+ },
+
+ 'click [data-edit]'(e, instance) {
+ e.preventDefault();
+ instance.editing.set($(e.currentTarget).data('edit'));
+ setTimeout(function() { instance.$('input.editing').focus().select(); }, 100);
+ },
+
+ 'change [type=checkbox]'(e, instance) {
+ instance.editing.set($(e.currentTarget).attr('name'));
+ instance.saveSetting();
+ },
+
+ 'click .cancel'(e, instance) {
+ e.preventDefault();
+ instance.editing.set();
+ },
+
+ 'click .save'(e, instance) {
+ e.preventDefault();
+ instance.saveSetting();
+ }
+});
diff --git a/packages/rocketchat-autotranslate/package.js b/packages/rocketchat-autotranslate/package.js
new file mode 100644
index 0000000000000..5724f020580f1
--- /dev/null
+++ b/packages/rocketchat-autotranslate/package.js
@@ -0,0 +1,36 @@
+Package.describe({
+ name: 'rocketchat:autotranslate',
+ version: '0.0.1',
+ summary: 'Rocket.Chat automatic translations',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'ddp-rate-limiter',
+ 'rocketchat:lib'
+ ]);
+
+ api.use('templating', 'client');
+
+ api.addFiles([
+ 'client/stylesheets/autotranslate.css',
+ 'client/lib/autotranslate.js',
+ 'client/lib/actionButton.js',
+ 'client/lib/tabBar.js',
+ 'client/views/autoTranslateFlexTab.html',
+ 'client/views/autoTranslateFlexTab.js'
+ ], 'client');
+
+ api.addFiles([
+ 'server/settings.js',
+ 'server/autotranslate.js',
+ 'server/permissions.js',
+ 'server/models/Messages.js',
+ 'server/models/Subscriptions.js',
+ 'server/methods/saveSettings.js',
+ 'server/methods/translateMessage.js',
+ 'server/methods/getSupportedLanguages.js'
+ ], 'server');
+});
diff --git a/packages/rocketchat-autotranslate/server/autotranslate.js b/packages/rocketchat-autotranslate/server/autotranslate.js
new file mode 100644
index 0000000000000..9e163592314c4
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/autotranslate.js
@@ -0,0 +1,257 @@
+import _ from 'underscore';
+import s from 'underscore.string';
+
+class AutoTranslate {
+ constructor() {
+ this.languages = [];
+ this.enabled = RocketChat.settings.get('AutoTranslate_Enabled');
+ this.apiKey = RocketChat.settings.get('AutoTranslate_GoogleAPIKey');
+ this.supportedLanguages = {};
+ RocketChat.callbacks.add('afterSaveMessage', this.translateMessage.bind(this), RocketChat.callbacks.priority.MEDIUM, 'AutoTranslate');
+
+ RocketChat.settings.get('AutoTranslate_Enabled', (key, value) => {
+ this.enabled = value;
+ });
+ RocketChat.settings.get('AutoTranslate_GoogleAPIKey', (key, value) => {
+ this.apiKey = value;
+ });
+ }
+
+ tokenize(message) {
+ if (!message.tokens || !Array.isArray(message.tokens)) {
+ message.tokens = [];
+ }
+ message = this.tokenizeEmojis(message);
+ message = this.tokenizeCode(message);
+ message = this.tokenizeURLs(message);
+ message = this.tokenizeMentions(message);
+ return message;
+ }
+
+ tokenizeEmojis(message) {
+ let count = message.tokens.length;
+ message.msg = message.msg.replace(/:[+\w\d]+:/g, function(match) {
+ const token = `{${ count++ }} `;
+ message.tokens.push({
+ token,
+ text: match
+ });
+ return token;
+ });
+
+ return message;
+ }
+
+ tokenizeURLs(message) {
+ let count = message.tokens.length;
+
+ const schemes = RocketChat.settings.get('Markdown_SupportSchemesForLink').split(',').join('|');
+
+ // Support  and [text](http://link)
+ message.msg = message.msg.replace(new RegExp(`(!?\\[)([^\\]]+)(\\]\\((?:${ schemes }):\\/\\/[^\\)]+\\))`, 'gm'), function(match, pre, text, post) {
+ const pretoken = `{${ count++ }} `;
+ message.tokens.push({
+ token: pretoken,
+ text: pre
+ });
+
+ const posttoken = `{${ count++ }} `;
+ message.tokens.push({
+ token: posttoken,
+ text: post
+ });
+
+ return pretoken + text + posttoken;
+ });
+
+ // Support
+ message.msg = message.msg.replace(new RegExp(`((?:<|<)(?:${ schemes }):\\/\\/[^\\|]+\\|)(.+?)(?=>|>)((?:>|>))`, 'gm'), function(match, pre, text, post) {
+ const pretoken = `{${ count++ }} `;
+ message.tokens.push({
+ token: pretoken,
+ text: pre
+ });
+
+ const posttoken = `{${ count++ }} `;
+ message.tokens.push({
+ token: posttoken,
+ text: post
+ });
+
+ return pretoken + text + posttoken;
+ });
+
+ return message;
+ }
+
+ tokenizeCode(message) {
+ let count = message.tokens.length;
+
+ message.html = message.msg;
+ message = RocketChat.Markdown.parseMessageNotEscaped(message);
+ message.msg = message.html;
+
+ for (const tokenIndex in message.tokens) {
+ if (message.tokens.hasOwnProperty(tokenIndex)) {
+ const token = message.tokens[tokenIndex].token;
+ if (token.indexOf('notranslate') === -1) {
+ const newToken = `{${ count++ }} `;
+ message.msg = message.msg.replace(token, newToken);
+ message.tokens[tokenIndex].token = newToken;
+ }
+ }
+ }
+
+ return message;
+ }
+
+ tokenizeMentions(message) {
+ let count = message.tokens.length;
+
+ if (message.mentions && message.mentions.length > 0) {
+ message.mentions.forEach(mention => {
+ message.msg = message.msg.replace(new RegExp(`(@${ mention.username })`, 'gm'), match => {
+ const token = `{${ count++ }} `;
+ message.tokens.push({
+ token,
+ text: match
+ });
+ return token;
+ });
+ });
+ }
+
+ if (message.channels && message.channels.length > 0) {
+ message.channels.forEach(channel => {
+ message.msg = message.msg.replace(new RegExp(`(#${ channel.name })`, 'gm'), match => {
+ const token = `{${ count++ }} `;
+ message.tokens.push({
+ token,
+ text: match
+ });
+ return token;
+ });
+ });
+ }
+
+ return message;
+ }
+
+ deTokenize(message) {
+ if (message.tokens && message.tokens.length > 0) {
+ for (const {token, text, noHtml} of message.tokens) {
+ message.msg = message.msg.replace(token, () => noHtml ? noHtml : text);
+ }
+ }
+ return message.msg;
+ }
+
+ translateMessage(message, room, targetLanguage) {
+ if (this.enabled && this.apiKey) {
+ let targetLanguages;
+ if (targetLanguage) {
+ targetLanguages = [ targetLanguage ];
+ } else {
+ targetLanguages = RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoomAndNotUser(room._id, message.u && message.u._id);
+ }
+ if (message.msg) {
+ Meteor.defer(() => {
+ const translations = {};
+ let targetMessage = Object.assign({}, message);
+
+ targetMessage.html = s.escapeHTML(String(targetMessage.msg));
+ targetMessage = this.tokenize(targetMessage);
+
+ let msgs = targetMessage.msg.split('\n');
+ msgs = msgs.map(msg => encodeURIComponent(msg));
+ const query = `q=${ msgs.join('&q=') }`;
+
+ const supportedLanguages = this.getSupportedLanguages('en');
+ targetLanguages.forEach(language => {
+ if (language.indexOf('-') !== -1 && !_.findWhere(supportedLanguages, { language })) {
+ language = language.substr(0, 2);
+ }
+ let result;
+ try {
+ result = HTTP.get('https://translation.googleapis.com/language/translate/v2', { params: { key: this.apiKey, target: language }, query });
+ } catch (e) {
+ console.log('Error translating message', e);
+ return message;
+ }
+ if (result.statusCode === 200 && result.data && result.data.data && result.data.data.translations && Array.isArray(result.data.data.translations) && result.data.data.translations.length > 0) {
+ const txt = result.data.data.translations.map(translation => translation.translatedText).join('\n');
+ translations[language] = this.deTokenize(Object.assign({}, targetMessage, { msg: txt }));
+ }
+ });
+ if (!_.isEmpty(translations)) {
+ RocketChat.models.Messages.addTranslations(message._id, translations);
+ }
+ });
+ }
+
+ if (message.attachments && message.attachments.length > 0) {
+ Meteor.defer(() => {
+ for (const index in message.attachments) {
+ if (message.attachments.hasOwnProperty(index)) {
+ const attachment = message.attachments[index];
+ const translations = {};
+ if (attachment.description || attachment.text) {
+ const query = `q=${ encodeURIComponent(attachment.description || attachment.text) }`;
+ const supportedLanguages = this.getSupportedLanguages('en');
+ targetLanguages.forEach(language => {
+ if (language.indexOf('-') !== -1 && !_.findWhere(supportedLanguages, { language })) {
+ language = language.substr(0, 2);
+ }
+ const result = HTTP.get('https://translation.googleapis.com/language/translate/v2', { params: { key: this.apiKey, target: language }, query });
+ if (result.statusCode === 200 && result.data && result.data.data && result.data.data.translations && Array.isArray(result.data.data.translations) && result.data.data.translations.length > 0) {
+ const txt = result.data.data.translations.map(translation => translation.translatedText).join('\n');
+ translations[language] = txt;
+ }
+ });
+ if (!_.isEmpty(translations)) {
+ RocketChat.models.Messages.addAttachmentTranslations(message._id, index, translations);
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+ return message;
+ }
+
+ getSupportedLanguages(target) {
+ if (this.enabled && this.apiKey) {
+ if (this.supportedLanguages[target]) {
+ return this.supportedLanguages[target];
+ }
+
+ let result;
+ const params = { key: this.apiKey };
+ if (target) {
+ params.target = target;
+ }
+
+ try {
+ result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params });
+ } catch (e) {
+ if (e.response && e.response.statusCode === 400 && e.response.data && e.response.data.error && e.response.data.error.status === 'INVALID_ARGUMENT') {
+ params.target = 'en';
+ target = 'en';
+ if (!this.supportedLanguages[target]) {
+ result = HTTP.get('https://translation.googleapis.com/language/translate/v2/languages', { params });
+ }
+ }
+ } finally {
+ if (this.supportedLanguages[target]) {
+ return this.supportedLanguages[target];
+ } else {
+ this.supportedLanguages[target || 'en'] = result && result.data && result.data.data && result.data.data.languages;
+ return this.supportedLanguages[target || 'en'];
+ }
+ }
+ }
+ }
+}
+
+RocketChat.AutoTranslate = new AutoTranslate;
diff --git a/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js b/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js
new file mode 100644
index 0000000000000..841a30268f854
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/methods/getSupportedLanguages.js
@@ -0,0 +1,17 @@
+Meteor.methods({
+ 'autoTranslate.getSupportedLanguages'(targetLanguage) {
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'auto-translate')) {
+ throw new Meteor.Error('error-action-now-allowed', 'Auto-Translate is not allowed', { method: 'autoTranslate.saveSettings'});
+ }
+
+ return RocketChat.AutoTranslate.getSupportedLanguages(targetLanguage);
+ }
+});
+
+DDPRateLimiter.addRule({
+ type: 'method',
+ name: 'autoTranslate.getSupportedLanguages',
+ userId(/*userId*/) {
+ return true;
+ }
+}, 5, 60000);
diff --git a/packages/rocketchat-autotranslate/server/methods/saveSettings.js b/packages/rocketchat-autotranslate/server/methods/saveSettings.js
new file mode 100644
index 0000000000000..1030436bcddad
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/methods/saveSettings.js
@@ -0,0 +1,38 @@
+Meteor.methods({
+ 'autoTranslate.saveSettings'(rid, field, value, options) {
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'saveAutoTranslateSettings' });
+ }
+
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'auto-translate')) {
+ throw new Meteor.Error('error-action-now-allowed', 'Auto-Translate is not allowed', { method: 'autoTranslate.saveSettings'});
+ }
+
+ check(rid, String);
+ check(field, String);
+ check(value, String);
+
+ if (['autoTranslate', 'autoTranslateLanguage'].indexOf(field) === -1) {
+ throw new Meteor.Error('error-invalid-settings', 'Invalid settings field', { method: 'saveAutoTranslateSettings' });
+ }
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, Meteor.userId());
+ if (!subscription) {
+ throw new Meteor.Error('error-invalid-subscription', 'Invalid subscription', { method: 'saveAutoTranslateSettings' });
+ }
+
+ switch (field) {
+ case 'autoTranslate':
+ RocketChat.models.Subscriptions.updateAutoTranslateById(subscription._id, value === '1' ? true : false);
+ if (!subscription.autoTranslateLanguage && options.defaultLanguage) {
+ RocketChat.models.Subscriptions.updateAutoTranslateLanguageById(subscription._id, options.defaultLanguage);
+ }
+ break;
+ case 'autoTranslateLanguage':
+ RocketChat.models.Subscriptions.updateAutoTranslateLanguageById(subscription._id, value);
+ break;
+ }
+
+ return true;
+ }
+});
diff --git a/packages/rocketchat-autotranslate/server/methods/translateMessage.js b/packages/rocketchat-autotranslate/server/methods/translateMessage.js
new file mode 100644
index 0000000000000..90d2e07616747
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/methods/translateMessage.js
@@ -0,0 +1,8 @@
+Meteor.methods({
+ 'autoTranslate.translateMessage'(message, targetLanguage) {
+ const room = RocketChat.models.Rooms.findOneById(message && message.rid);
+ if (message && room && RocketChat.AutoTranslate) {
+ return RocketChat.AutoTranslate.translateMessage(message, room, targetLanguage);
+ }
+ }
+});
diff --git a/packages/rocketchat-autotranslate/server/models/Messages.js b/packages/rocketchat-autotranslate/server/models/Messages.js
new file mode 100644
index 0000000000000..5297e722ca5db
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/models/Messages.js
@@ -0,0 +1,17 @@
+RocketChat.models.Messages.addTranslations = function(messageId, translations) {
+ const updateObj = {};
+ Object.keys(translations).forEach((key) => {
+ const translation = translations[key];
+ updateObj[`translations.${ key }`] = translation;
+ });
+ return this.update({ _id: messageId }, { $set: updateObj });
+};
+
+RocketChat.models.Messages.addAttachmentTranslations = function(messageId, attachmentIndex, translations) {
+ const updateObj = {};
+ Object.keys(translations).forEach((key) => {
+ const translation = translations[key];
+ updateObj[`attachments.${ attachmentIndex }.translations.${ key }`] = translation;
+ });
+ return this.update({ _id: messageId }, { $set: updateObj });
+};
diff --git a/packages/rocketchat-autotranslate/server/models/Subscriptions.js b/packages/rocketchat-autotranslate/server/models/Subscriptions.js
new file mode 100644
index 0000000000000..85482e6173c80
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/models/Subscriptions.js
@@ -0,0 +1,47 @@
+RocketChat.models.Subscriptions.updateAutoTranslateById = function(_id, autoTranslate) {
+ const query = {
+ _id
+ };
+
+ let update;
+ if (autoTranslate) {
+ update = {
+ $set: {
+ autoTranslate
+ }
+ };
+ } else {
+ update = {
+ $unset: {
+ autoTranslate: 1
+ }
+ };
+ }
+
+ return this.update(query, update);
+};
+
+RocketChat.models.Subscriptions.updateAutoTranslateLanguageById = function(_id, autoTranslateLanguage) {
+ const query = {
+ _id
+ };
+
+ const update = {
+ $set: {
+ autoTranslateLanguage
+ }
+ };
+
+ return this.update(query, update);
+};
+
+RocketChat.models.Subscriptions.getAutoTranslateLanguagesByRoomAndNotUser = function(rid, userId) {
+ const subscriptionsRaw = RocketChat.models.Subscriptions.model.rawCollection();
+ const distinct = Meteor.wrapAsync(subscriptionsRaw.distinct, subscriptionsRaw);
+ const query = {
+ rid,
+ 'u._id': { $ne: userId },
+ autoTranslate: true
+ };
+ return distinct('autoTranslateLanguage', query);
+};
diff --git a/packages/rocketchat-autotranslate/server/permissions.js b/packages/rocketchat-autotranslate/server/permissions.js
new file mode 100644
index 0000000000000..03c306e2e2ecf
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/permissions.js
@@ -0,0 +1,7 @@
+Meteor.startup(() => {
+ if (RocketChat.models && RocketChat.models.Permissions) {
+ if (!RocketChat.models.Permissions.findOne({ _id: 'auto-translate' })) {
+ RocketChat.models.Permissions.insert({ _id: 'auto-translate', roles: ['admin'] });
+ }
+ }
+});
diff --git a/packages/rocketchat-autotranslate/server/settings.js b/packages/rocketchat-autotranslate/server/settings.js
new file mode 100644
index 0000000000000..4eccb5f825a75
--- /dev/null
+++ b/packages/rocketchat-autotranslate/server/settings.js
@@ -0,0 +1,4 @@
+Meteor.startup(function() {
+ RocketChat.settings.add('AutoTranslate_Enabled', false, { type: 'boolean', group: 'Message', section: 'AutoTranslate', public: true });
+ RocketChat.settings.add('AutoTranslate_GoogleAPIKey', '', { type: 'string', group: 'Message', section: 'AutoTranslate', enableQuery: { _id: 'AutoTranslate_Enabled', value: true } });
+});
diff --git a/packages/rocketchat-bot-helpers/package.js b/packages/rocketchat-bot-helpers/package.js
index cd57b74f65111..560b7f9ff748a 100644
--- a/packages/rocketchat-bot-helpers/package.js
+++ b/packages/rocketchat-bot-helpers/package.js
@@ -7,7 +7,6 @@ Package.describe({
Package.onUse(function(api) {
api.use('ecmascript');
- api.use('underscore');
api.use('rocketchat:lib');
api.use('accounts-base');
// api.mainModule('server/index.js', 'server'); // when 1.3
diff --git a/packages/rocketchat-bot-helpers/server/index.js b/packages/rocketchat-bot-helpers/server/index.js
index 98fe5e9951f57..0c3a45b4d670a 100644
--- a/packages/rocketchat-bot-helpers/server/index.js
+++ b/packages/rocketchat-bot-helpers/server/index.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
/**
* BotHelpers helps bots
* "private" properties use meteor collection cursors, so they stay reactive
@@ -20,8 +22,8 @@ class BotHelpers {
fieldsSetting.forEach((n) => {
this.userFields[n.trim()] = 1;
});
- this._allUsers = Meteor.users.find(this.queries.users, { fields: this.userFields });
- this._onlineUsers = Meteor.users.find({ $and: [this.queries.users, this.queries.online] }, { fields: this.userFields });
+ this._allUsers = RocketChat.models.Users.find(this.queries.users, { fields: this.userFields });
+ this._onlineUsers = RocketChat.models.Users.find({ $and: [this.queries.users, this.queries.online] }, { fields: this.userFields });
}
// request methods or props as arguments to Meteor.call
@@ -44,25 +46,25 @@ class BotHelpers {
}
addUserToRoom(userName, room) {
- let foundRoom = RocketChat.models.Rooms.findOneByIdOrName(room);
+ const foundRoom = RocketChat.models.Rooms.findOneByIdOrName(room);
if (!_.isObject(foundRoom)) {
throw new Meteor.Error('invalid-channel');
}
- let data = {};
+ const data = {};
data.rid = foundRoom._id;
data.username = userName;
Meteor.call('addUserToRoom', data);
}
removeUserFromRoom(userName, room) {
- let foundRoom = RocketChat.models.Rooms.findOneByIdOrName(room);
+ const foundRoom = RocketChat.models.Rooms.findOneByIdOrName(room);
if (!_.isObject(foundRoom)) {
throw new Meteor.Error('invalid-channel');
}
- let data = {};
+ const data = {};
data.rid = foundRoom._id;
data.username = userName;
Meteor.call('removeUserFromRoom', data);
@@ -155,7 +157,7 @@ RocketChat.settings.get('BotHelpers_userFields', function(settingKey, settingVal
Meteor.methods({
botRequest: (...args) => {
- let userID = Meteor.userId();
+ const userID = Meteor.userId();
if (userID && RocketChat.authz.hasRole(userID, 'bot')) {
return botHelpers.request(...args);
} else {
diff --git a/packages/rocketchat-cas/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-cas/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index a309abf87b30b..0000000000000
--- a/packages/rocketchat-cas/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,113 +0,0 @@
-{
- "dependencies": {
- "boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "from": "boolbase@>=1.0.0 <1.1.0"
- },
- "cas": {
- "version": "0.0.5",
- "resolved": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62",
- "from": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62"
- },
- "cheerio": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz",
- "from": "cheerio@0.19.0"
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "from": "core-util-is@>=1.0.0 <1.1.0"
- },
- "css-select": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz",
- "from": "css-select@>=1.0.0 <1.1.0"
- },
- "css-what": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz",
- "from": "css-what@>=1.0.0 <1.1.0"
- },
- "dom-serializer": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
- "from": "dom-serializer@>=0.1.0 <0.2.0",
- "dependencies": {
- "domelementtype": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
- "from": "domelementtype@>=1.1.1 <1.2.0"
- }
- }
- },
- "domelementtype": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
- "from": "domelementtype@>=1.0.0 <2.0.0"
- },
- "domhandler": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
- "from": "domhandler@>=2.3.0 <2.4.0"
- },
- "domutils": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz",
- "from": "domutils@>=1.4.0 <1.5.0"
- },
- "entities": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
- "from": "entities@>=1.1.1 <1.2.0"
- },
- "htmlparser2": {
- "version": "3.8.3",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
- "from": "htmlparser2@>=3.8.1 <3.9.0",
- "dependencies": {
- "domutils": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
- "from": "domutils@>=1.5.0 <1.6.0"
- },
- "entities": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
- "from": "entities@>=1.0.0 <1.1.0"
- }
- }
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "from": "inherits@>=2.0.1 <2.1.0"
- },
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "from": "isarray@0.0.1"
- },
- "lodash": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
- "from": "lodash@>=3.2.0 <4.0.0"
- },
- "nth-check": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
- "from": "nth-check@>=1.0.0 <1.1.0"
- },
- "readable-stream": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
- "from": "readable-stream@>=1.1.0 <1.2.0"
- },
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "from": "string_decoder@>=0.10.0 <0.11.0"
- }
- }
-}
diff --git a/packages/rocketchat-cas/cas_client.js b/packages/rocketchat-cas/cas_client.js
deleted file mode 100644
index 1d80e1df37e72..0000000000000
--- a/packages/rocketchat-cas/cas_client.js
+++ /dev/null
@@ -1,86 +0,0 @@
-var openCenteredPopup = function(url, width, height) {
-
- var screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft;
- var screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop;
- var outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth;
- var outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
- // XXX what is the 22?
-
- // Use `outerWidth - width` and `outerHeight - height` for help in
- // positioning the popup centered relative to the current window
- var left = screenX + (outerWidth - width) / 2;
- var top = screenY + (outerHeight - height) / 2;
- var features = ('width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',scrollbars=yes');
-
- var newwindow = window.open(url, 'Login', features);
- if (newwindow.focus) {
- newwindow.focus();
- }
-
- return newwindow;
-};
-
-Meteor.loginWithCas = function(options, callback) {
- options = options || {};
-
- var credentialToken = Random.id();
- var login_url = RocketChat.settings.get('CAS_login_url');
- var popup_width = RocketChat.settings.get('CAS_popup_width');
- var popup_height = RocketChat.settings.get('CAS_popup_height');
-
- if (!login_url) {
- return;
- }
-
- var appUrl = Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
- var loginUrl = login_url + '?service=' + appUrl + '/_cas/' + credentialToken;
-
- var popup = openCenteredPopup(
- loginUrl,
- popup_width || 800,
- popup_height || 600
- );
-
- // Fix for #3200: monitor the popup differently if it's Cordova
- if (Meteor.isCordova) {
- // Check the URL when each page finishes loading, and if the URL contains "ticket", then close the popup because CAS has finished
- popup.addEventListener('loadstop', function(e) {
- if (e.url.indexOf('?ticket=') !== -1) {
- popup.close();
- }
- });
- popup.addEventListener('exit', function() {
- // check auth on server.
- Accounts.callLoginMethod({
- methodArguments: [{ cas: { credentialToken: credentialToken } }],
- userCallback: callback
- });
- });
- } else {
- var checkPopupOpen = setInterval(function() {
- var popupClosed;
- try {
- // Fix for #328 - added a second test criteria (popup.closed === undefined)
- // to humour this Android quirk:
- // http://code.google.com/p/android/issues/detail?id=21061
- popupClosed = popup.closed || popup.closed === undefined;
- } catch (e) {
- // For some unknown reason, IE9 (and others?) sometimes (when
- // the popup closes too quickly?) throws "SCRIPT16386: No such
- // interface supported" when trying to read 'popup.closed'. Try
- // again in 100ms.
- return;
- }
-
- if (popupClosed) {
- clearInterval(checkPopupOpen);
-
- // check auth on server.
- Accounts.callLoginMethod({
- methodArguments: [{ cas: { credentialToken: credentialToken } }],
- userCallback: callback
- });
- }
- }, 100);
- }
-};
diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js
deleted file mode 100644
index 555fa638307cf..0000000000000
--- a/packages/rocketchat-cas/cas_server.js
+++ /dev/null
@@ -1,261 +0,0 @@
-/* globals RoutePolicy, logger */
-/* jshint newcap: false */
-
-var fiber = Npm.require('fibers');
-var url = Npm.require('url');
-var CAS = Npm.require('cas');
-
-var _casCredentialTokens = {};
-
-RoutePolicy.declare('/_cas/', 'network');
-
-var closePopup = function(res) {
- res.writeHead(200, {'Content-Type': 'text/html'});
- var content = '';
- res.end(content, 'utf-8');
-};
-
-var casTicket = function(req, token, callback) {
-
- // get configuration
- if (!RocketChat.settings.get('CAS_enabled')) {
- logger.error('Got ticket validation request, but CAS is not enabled');
- callback();
- }
-
- // get ticket and validate.
- var parsedUrl = url.parse(req.url, true);
- var ticketId = parsedUrl.query.ticket;
- var baseUrl = RocketChat.settings.get('CAS_base_url');
- var cas_version = parseFloat(RocketChat.settings.get('CAS_version'));
- var appUrl = Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
- logger.debug('Using CAS_base_url: ' + baseUrl);
-
- var cas = new CAS({
- base_url: baseUrl,
- version: cas_version,
- service: appUrl + '/_cas/' + token
- });
-
- cas.validate(ticketId, function(err, status, username, details) {
- if (err) {
- logger.error('error when trying to validate: ' + err.message);
- } else if (status) {
- logger.info('Validated user: ' + username);
- var user_info = { username: username };
-
- // CAS 2.0 attributes handling
- if (details && details.attributes) {
- _.extend(user_info, { attributes: details.attributes });
- }
- _casCredentialTokens[token] = user_info;
- } else {
- logger.error('Unable to validate ticket: ' + ticketId);
- }
- //logger.debug("Receveied response: " + JSON.stringify(details, null , 4));
-
- callback();
- });
-
- return;
-};
-
-var middleware = function(req, res, next) {
- // Make sure to catch any exceptions because otherwise we'd crash
- // the runner
- try {
- var barePath = req.url.substring(0, req.url.indexOf('?'));
- var splitPath = barePath.split('/');
-
- // Any non-cas request will continue down the default
- // middlewares.
- if (splitPath[1] !== '_cas') {
- next();
- return;
- }
-
- // get auth token
- var credentialToken = splitPath[2];
- if (!credentialToken) {
- closePopup(res);
- return;
- }
-
- // validate ticket
- casTicket(req, credentialToken, function() {
- closePopup(res);
- });
-
- } catch (err) {
- logger.error('Unexpected error : ' + err.message);
- closePopup(res);
- }
-};
-
-// Listen to incoming OAuth http requests
-WebApp.connectHandlers.use(function(req, res, next) {
- // Need to create a fiber since we're using synchronous http calls and nothing
- // else is wrapping this in a fiber automatically
- fiber(function() {
- middleware(req, res, next);
- }).run();
-});
-
-var _hasCredential = function(credentialToken) {
- return _.has(_casCredentialTokens, credentialToken);
-};
-
-/*
- * Retrieve token and delete it to avoid replaying it.
- */
-var _retrieveCredential = function(credentialToken) {
- var result = _casCredentialTokens[credentialToken];
- delete _casCredentialTokens[credentialToken];
- return result;
-};
-
-/*
- * Register a server-side login handle.
- * It is call after Accounts.callLoginMethod() is call from client.
- *
- */
-Accounts.registerLoginHandler(function(options) {
-
- if (!options.cas) {
- return undefined;
- }
-
- if (!_hasCredential(options.cas.credentialToken)) {
- throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
- 'no matching login attempt found');
- }
-
- var result = _retrieveCredential(options.cas.credentialToken);
- var syncUserDataFieldMap = RocketChat.settings.get('CAS_Sync_User_Data_FieldMap').trim();
- var cas_version = parseFloat(RocketChat.settings.get('CAS_version'));
- var sync_enabled = RocketChat.settings.get('CAS_Sync_User_Data_Enabled');
-
- // We have these
- var ext_attrs = {
- username: result.username
- };
-
- // We need these
- var int_attrs = {
- email: undefined,
- name: undefined,
- username: undefined,
- rooms: undefined
- };
-
- // Import response attributes
- if (cas_version >= 2.0) {
- // Clean & import external attributes
- _.each(result.attributes, function(value, ext_name) {
- if (value) {
- ext_attrs[ext_name] = value[0];
- }
- });
- }
-
- // Source internal attributes
- if (syncUserDataFieldMap) {
-
- // Our mapping table: key(int_attr) -> value(ext_attr)
- // Spoken: Source this internal attribute from these external attributes
- const attr_map = JSON.parse(syncUserDataFieldMap);
-
- _.each(attr_map, function(source, int_name) {
- // Source is our String to interpolate
- if (_.isString(source)) {
- _.each(ext_attrs, function(value, ext_name) {
- source = source.replace('%' + ext_name + '%', ext_attrs[ext_name]);
- });
-
- int_attrs[int_name] = source;
- logger.debug('Sourced internal attribute: ' + int_name + ' = ' + source);
- }
- });
- }
-
- // Search existing user by its external service id
- logger.debug('Looking up user by id: ' + result.username);
- var user = Meteor.users.findOne({ 'services.cas.external_id': result.username });
-
- if (user) {
- logger.debug('Using existing user for \'' + result.username + '\' with id: ' + user._id);
- if (sync_enabled) {
- logger.debug('Syncing user attributes');
- // Update name
- if (int_attrs.name) {
- Meteor.users.update(user, { $set: { name: int_attrs.name }});
- }
-
- // Update email
- if (int_attrs.email) {
- Meteor.users.update(user, { $set: { emails: [{ address: int_attrs.email, verified: true }] }});
- }
- }
- } else {
-
- // Define new user
- var newUser = {
- username: result.username,
- active: true,
- globalRoles: ['user'],
- emails: [],
- services: {
- cas: {
- external_id: result.username,
- version: cas_version,
- attrs: int_attrs
- }
- }
- };
-
- // Add User.name
- if (int_attrs.name) {
- _.extend(newUser, {
- name: int_attrs.name
- });
- }
-
- // Add email
- if (int_attrs.email) {
- _.extend(newUser, {
- emails: [{ address: int_attrs.email, verified: true }]
- });
- }
-
- // Create the user
- logger.debug('User "' + result.username + '" does not exist yet, creating it');
- var userId = Accounts.insertUserDoc({}, newUser);
-
- // Fetch and use it
- user = Meteor.users.findOne(userId);
- logger.debug('Created new user for \'' + result.username + '\' with id: ' + user._id);
- //logger.debug(JSON.stringify(user, undefined, 4));
-
- logger.debug('Joining user to attribute channels: ' + int_attrs.rooms);
- if (int_attrs.rooms) {
- _.each(int_attrs.rooms.split(','), function(room_name) {
- if (room_name) {
- var room = RocketChat.models.Rooms.findOneByNameAndType(room_name, 'c');
- if (!room) {
- room = RocketChat.models.Rooms.createWithIdTypeAndName(Random.id(), 'c', room_name);
- }
- RocketChat.models.Rooms.addUsernameByName(room_name, result.username);
- RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
- ts: new Date(),
- open: true,
- alert: true,
- unread: 1
- });
- }
- });
- }
-
- }
-
- return { userId: user._id };
-});
diff --git a/packages/rocketchat-cas/client/cas_client.js b/packages/rocketchat-cas/client/cas_client.js
new file mode 100644
index 0000000000000..b0521fdba3835
--- /dev/null
+++ b/packages/rocketchat-cas/client/cas_client.js
@@ -0,0 +1,88 @@
+const openCenteredPopup = function(url, width, height) {
+
+ const screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft;
+ const screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop;
+ const outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth;
+ const outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
+ // XXX what is the 22?
+
+ // Use `outerWidth - width` and `outerHeight - height` for help in
+ // positioning the popup centered relative to the current window
+ const left = screenX + (outerWidth - width) / 2;
+ const top = screenY + (outerHeight - height) / 2;
+ const features = (`width=${ width },height=${ height },left=${ left },top=${ top },scrollbars=yes`);
+
+ const newwindow = window.open(url, 'Login', features);
+ if (newwindow.focus) {
+ newwindow.focus();
+ }
+
+ return newwindow;
+};
+
+Meteor.loginWithCas = function(options, callback) {
+ options = options || {};
+
+ const credentialToken = Random.id();
+ const login_url = RocketChat.settings.get('CAS_login_url');
+ const popup_width = RocketChat.settings.get('CAS_popup_width');
+ const popup_height = RocketChat.settings.get('CAS_popup_height');
+
+ if (!login_url) {
+ return;
+ }
+
+ const appUrl = Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
+ // check if the provided CAS URL already has some parameters
+ const delim = (login_url.split('?').length > 1) ? '&' : '?';
+ const loginUrl = `${ login_url }${ delim }service=${ appUrl }/_cas/${ credentialToken }`;
+
+ const popup = openCenteredPopup(
+ loginUrl,
+ popup_width || 800,
+ popup_height || 600
+ );
+
+ // Fix for #3200: monitor the popup differently if it's Cordova
+ if (Meteor.isCordova) {
+ // Check the URL when each page finishes loading, and if the URL contains "ticket", then close the popup because CAS has finished
+ popup.addEventListener('loadstop', function(e) {
+ if (e.url.indexOf('?ticket=') !== -1) {
+ popup.close();
+ }
+ });
+ popup.addEventListener('exit', function() {
+ // check auth on server.
+ Accounts.callLoginMethod({
+ methodArguments: [{ cas: { credentialToken } }],
+ userCallback: callback
+ });
+ });
+ } else {
+ const checkPopupOpen = setInterval(function() {
+ let popupClosed;
+ try {
+ // Fix for #328 - added a second test criteria (popup.closed === undefined)
+ // to humour this Android quirk:
+ // http://code.google.com/p/android/issues/detail?id=21061
+ popupClosed = popup.closed || popup.closed === undefined;
+ } catch (e) {
+ // For some unknown reason, IE9 (and others?) sometimes (when
+ // the popup closes too quickly?) throws "SCRIPT16386: No such
+ // interface supported" when trying to read 'popup.closed'. Try
+ // again in 100ms.
+ return;
+ }
+
+ if (popupClosed) {
+ clearInterval(checkPopupOpen);
+
+ // check auth on server.
+ Accounts.callLoginMethod({
+ methodArguments: [{ cas: { credentialToken } }],
+ userCallback: callback
+ });
+ }
+ }, 100);
+ }
+};
diff --git a/packages/rocketchat-cas/package.js b/packages/rocketchat-cas/package.js
index b584f5f9a92d5..35e64deee3489 100644
--- a/packages/rocketchat-cas/package.js
+++ b/packages/rocketchat-cas/package.js
@@ -14,18 +14,13 @@ Package.onUse(function(api) {
api.use('webapp', 'server');
api.use('accounts-base', 'server');
- api.use('underscore');
api.use('ecmascript');
// Server files
- api.add_files('cas_rocketchat.js', 'server');
- api.add_files('cas_server.js', 'server');
+ api.add_files('server/cas_rocketchat.js', 'server');
+ api.add_files('server/cas_server.js', 'server');
+ api.add_files('server/models/CredentialTokens.js', 'server');
// Client files
- api.add_files('cas_client.js', 'client');
-
-});
-
-Npm.depends({
- cas: 'https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62'
+ api.add_files('client/cas_client.js', 'client');
});
diff --git a/packages/rocketchat-cas/cas_rocketchat.js b/packages/rocketchat-cas/server/cas_rocketchat.js
similarity index 95%
rename from packages/rocketchat-cas/cas_rocketchat.js
rename to packages/rocketchat-cas/server/cas_rocketchat.js
index ebdb12f635a12..7e2d35e4e0ceb 100644
--- a/packages/rocketchat-cas/cas_rocketchat.js
+++ b/packages/rocketchat-cas/server/cas_rocketchat.js
@@ -9,14 +9,14 @@ Meteor.startup(function() {
this.add('CAS_login_url', '', { type: 'string', group: 'CAS', public: true });
this.add('CAS_version', '1.0', { type: 'select', values: [{ key: '1.0', i18nLabel: '1.0'}, { key: '2.0', i18nLabel: '2.0'}], group: 'CAS' });
- this.section('Attribute handling', function() {
+ this.section('Attribute_handling', function() {
// Enable/disable sync
this.add('CAS_Sync_User_Data_Enabled', true, { type: 'boolean' });
// Attribute mapping table
this.add('CAS_Sync_User_Data_FieldMap', '{}', { type: 'string' });
});
- this.section('CAS Login Layout', function() {
+ this.section('CAS_Login_Layout', function() {
this.add('CAS_popup_width', '810', { type: 'string', group: 'CAS', public: true });
this.add('CAS_popup_height', '610', { type: 'string', group: 'CAS', public: true });
this.add('CAS_button_label_text', 'CAS', { type: 'string', group: 'CAS'});
@@ -27,7 +27,7 @@ Meteor.startup(function() {
});
});
-var timer;
+let timer;
function updateServices(/*record*/) {
if (typeof timer !== 'undefined') {
@@ -35,7 +35,7 @@ function updateServices(/*record*/) {
}
timer = Meteor.setTimeout(function() {
- var data = {
+ const data = {
// These will pe passed to 'node-cas' as options
enabled: RocketChat.settings.get('CAS_enabled'),
base_url: RocketChat.settings.get('CAS_base_url'),
diff --git a/packages/rocketchat-cas/server/cas_server.js b/packages/rocketchat-cas/server/cas_server.js
new file mode 100644
index 0000000000000..ca89e1f0f6a89
--- /dev/null
+++ b/packages/rocketchat-cas/server/cas_server.js
@@ -0,0 +1,250 @@
+/* globals RoutePolicy, logger */
+/* jshint newcap: false */
+import _ from 'underscore';
+
+import fiber from 'fibers';
+import url from 'url';
+import CAS from 'cas';
+
+RoutePolicy.declare('/_cas/', 'network');
+
+const closePopup = function(res) {
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ const content = '';
+ res.end(content, 'utf-8');
+};
+
+const casTicket = function(req, token, callback) {
+
+ // get configuration
+ if (!RocketChat.settings.get('CAS_enabled')) {
+ logger.error('Got ticket validation request, but CAS is not enabled');
+ callback();
+ }
+
+ // get ticket and validate.
+ const parsedUrl = url.parse(req.url, true);
+ const ticketId = parsedUrl.query.ticket;
+ const baseUrl = RocketChat.settings.get('CAS_base_url');
+ const cas_version = parseFloat(RocketChat.settings.get('CAS_version'));
+ const appUrl = Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
+ logger.debug(`Using CAS_base_url: ${ baseUrl }`);
+
+ const cas = new CAS({
+ base_url: baseUrl,
+ version: cas_version,
+ service: `${ appUrl }/_cas/${ token }`
+ });
+
+ cas.validate(ticketId, Meteor.bindEnvironment(function(err, status, username, details) {
+ if (err) {
+ logger.error(`error when trying to validate: ${ err.message }`);
+ } else if (status) {
+ logger.info(`Validated user: ${ username }`);
+ const user_info = { username };
+
+ // CAS 2.0 attributes handling
+ if (details && details.attributes) {
+ _.extend(user_info, { attributes: details.attributes });
+ }
+ RocketChat.models.CredentialTokens.create(token, user_info);
+ } else {
+ logger.error(`Unable to validate ticket: ${ ticketId }`);
+ }
+ //logger.debug("Receveied response: " + JSON.stringify(details, null , 4));
+
+ callback();
+ }));
+
+ return;
+};
+
+const middleware = function(req, res, next) {
+ // Make sure to catch any exceptions because otherwise we'd crash
+ // the runner
+ try {
+ const barePath = req.url.substring(0, req.url.indexOf('?'));
+ const splitPath = barePath.split('/');
+
+ // Any non-cas request will continue down the default
+ // middlewares.
+ if (splitPath[1] !== '_cas') {
+ next();
+ return;
+ }
+
+ // get auth token
+ const credentialToken = splitPath[2];
+ if (!credentialToken) {
+ closePopup(res);
+ return;
+ }
+
+ // validate ticket
+ casTicket(req, credentialToken, function() {
+ closePopup(res);
+ });
+
+ } catch (err) {
+ logger.error(`Unexpected error : ${ err.message }`);
+ closePopup(res);
+ }
+};
+
+// Listen to incoming OAuth http requests
+WebApp.connectHandlers.use(function(req, res, next) {
+ // Need to create a fiber since we're using synchronous http calls and nothing
+ // else is wrapping this in a fiber automatically
+ fiber(function() {
+ middleware(req, res, next);
+ }).run();
+});
+
+/*
+ * Register a server-side login handle.
+ * It is call after Accounts.callLoginMethod() is call from client.
+ *
+ */
+Accounts.registerLoginHandler(function(options) {
+
+ if (!options.cas) {
+ return undefined;
+ }
+
+ const credentials = RocketChat.models.CredentialTokens.findOneById(options.cas.credentialToken);
+ if (credentials === undefined) {
+ throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
+ 'no matching login attempt found');
+ }
+
+ const result = credentials.userInfo;
+ const syncUserDataFieldMap = RocketChat.settings.get('CAS_Sync_User_Data_FieldMap').trim();
+ const cas_version = parseFloat(RocketChat.settings.get('CAS_version'));
+ const sync_enabled = RocketChat.settings.get('CAS_Sync_User_Data_Enabled');
+
+ // We have these
+ const ext_attrs = {
+ username: result.username
+ };
+
+ // We need these
+ const int_attrs = {
+ email: undefined,
+ name: undefined,
+ username: undefined,
+ rooms: undefined
+ };
+
+ // Import response attributes
+ if (cas_version >= 2.0) {
+ // Clean & import external attributes
+ _.each(result.attributes, function(value, ext_name) {
+ if (value) {
+ ext_attrs[ext_name] = value[0];
+ }
+ });
+ }
+
+ // Source internal attributes
+ if (syncUserDataFieldMap) {
+
+ // Our mapping table: key(int_attr) -> value(ext_attr)
+ // Spoken: Source this internal attribute from these external attributes
+ const attr_map = JSON.parse(syncUserDataFieldMap);
+
+ _.each(attr_map, function(source, int_name) {
+ // Source is our String to interpolate
+ if (_.isString(source)) {
+ _.each(ext_attrs, function(value, ext_name) {
+ source = source.replace(`%${ ext_name }%`, ext_attrs[ext_name]);
+ });
+
+ int_attrs[int_name] = source;
+ logger.debug(`Sourced internal attribute: ${ int_name } = ${ source }`);
+ }
+ });
+ }
+
+ // Search existing user by its external service id
+ logger.debug(`Looking up user by id: ${ result.username }`);
+ let user = Meteor.users.findOne({ 'services.cas.external_id': result.username });
+
+ if (user) {
+ logger.debug(`Using existing user for '${ result.username }' with id: ${ user._id }`);
+ if (sync_enabled) {
+ logger.debug('Syncing user attributes');
+ // Update name
+ if (int_attrs.name) {
+ RocketChat._setRealName(user._id, int_attrs.name);
+ }
+
+ // Update email
+ if (int_attrs.email) {
+ Meteor.users.update(user, { $set: { emails: [{ address: int_attrs.email, verified: true }] }});
+ }
+ }
+ } else {
+
+ // Define new user
+ const newUser = {
+ username: result.username,
+ active: true,
+ globalRoles: ['user'],
+ emails: [],
+ services: {
+ cas: {
+ external_id: result.username,
+ version: cas_version,
+ attrs: int_attrs
+ }
+ }
+ };
+
+ // Add User.name
+ if (int_attrs.name) {
+ _.extend(newUser, {
+ name: int_attrs.name
+ });
+ }
+
+ // Add email
+ if (int_attrs.email) {
+ _.extend(newUser, {
+ emails: [{ address: int_attrs.email, verified: true }]
+ });
+ }
+
+ // Create the user
+ logger.debug(`User "${ result.username }" does not exist yet, creating it`);
+ const userId = Accounts.insertUserDoc({}, newUser);
+
+ // Fetch and use it
+ user = Meteor.users.findOne(userId);
+ logger.debug(`Created new user for '${ result.username }' with id: ${ user._id }`);
+ //logger.debug(JSON.stringify(user, undefined, 4));
+
+ logger.debug(`Joining user to attribute channels: ${ int_attrs.rooms }`);
+ if (int_attrs.rooms) {
+ _.each(int_attrs.rooms.split(','), function(room_name) {
+ if (room_name) {
+ let room = RocketChat.models.Rooms.findOneByNameAndType(room_name, 'c');
+ if (!room) {
+ room = RocketChat.models.Rooms.createWithIdTypeAndName(Random.id(), 'c', room_name);
+ }
+ RocketChat.models.Rooms.addUsernameByName(room_name, result.username);
+ RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
+ ts: new Date(),
+ open: true,
+ alert: true,
+ unread: 1,
+ userMentions: 1,
+ groupMentions: 0
+ });
+ }
+ });
+ }
+
+ }
+
+ return { userId: user._id };
+});
diff --git a/packages/rocketchat-cas/server/models/CredentialTokens.js b/packages/rocketchat-cas/server/models/CredentialTokens.js
new file mode 100644
index 0000000000000..499725f2357d2
--- /dev/null
+++ b/packages/rocketchat-cas/server/models/CredentialTokens.js
@@ -0,0 +1,28 @@
+RocketChat.models.CredentialTokens = new class extends RocketChat.models._Base {
+ constructor() {
+ super('credential_tokens');
+
+ this.tryEnsureIndex({ 'expireAt': 1 }, { sparse: 1, expireAfterSeconds: 0 });
+ }
+
+ create(_id, userInfo) {
+ const validForMilliseconds = 60000; // Valid for 60 seconds
+ const token = {
+ _id,
+ userInfo,
+ expireAt: new Date(Date.now() + validForMilliseconds)
+ };
+
+ this.insert(token);
+ return token;
+ }
+
+ findOneById(_id) {
+ const query = {
+ _id,
+ expireAt: { $gt: new Date() }
+ };
+
+ return this.findOne(query);
+ }
+};
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.coffee b/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.coffee
deleted file mode 100644
index c55e6956b7b20..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.coffee
+++ /dev/null
@@ -1,13 +0,0 @@
-Meteor.startup ->
- RocketChat.ChannelSettings.addOption
- id: 'mail-messages'
- template: 'channelSettingsMailMessages'
- validation: ->
- return RocketChat.authz.hasAllPermission('mail-messages')
-
- RocketChat.callbacks.add 'roomExit', (mainNode) ->
- messagesBox = $('.messages-box')
- if messagesBox.get(0)?
- instance = Blaze.getView(messagesBox.get(0))?.templateInstance()
- instance?.resetSelection(false)
- , RocketChat.callbacks.priority.MEDIUM, 'room-exit-mail-messages'
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.js b/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.js
new file mode 100644
index 0000000000000..25c60346ec82e
--- /dev/null
+++ b/packages/rocketchat-channel-settings-mail-messages/client/lib/startup.js
@@ -0,0 +1,15 @@
+// import resetSelection from '../resetSelection';
+Meteor.startup(() => {
+ RocketChat.TabBar.addButton({
+ groups: ['channel', 'group', 'direct'],
+ id: 'mail-messages',
+ anonymous: true,
+ i18nTitle: 'Mail_Messages',
+ icon: 'mail',
+ template: 'mailMessagesInstructions',
+ order: 10,
+ condition: () => RocketChat.authz.hasAllPermission('mail-messages')
+ });
+
+ // RocketChat.callbacks.add('roomExit', () => resetSelection(false), RocketChat.callbacks.priority.MEDIUM, 'room-exit-mail-messages');
+});
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/resetSelection.js b/packages/rocketchat-channel-settings-mail-messages/client/resetSelection.js
new file mode 100644
index 0000000000000..2dab2fcc6dc11
--- /dev/null
+++ b/packages/rocketchat-channel-settings-mail-messages/client/resetSelection.js
@@ -0,0 +1,11 @@
+export default function resetSelection(reset) {
+ const [el] = $('.messages-box');
+ if (!el) {
+ return;
+ }
+ const view = Blaze.getView(el);
+ if (view && typeof view.templateInstance === 'function') {
+ const {resetSelection} = view.templateInstance();
+ typeof resetSelection === 'function' && resetSelection(reset);
+ }
+}
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/stylesheets/mail-messages.less b/packages/rocketchat-channel-settings-mail-messages/client/stylesheets/mail-messages.less
deleted file mode 100644
index bca0df25b490e..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/client/stylesheets/mail-messages.less
+++ /dev/null
@@ -1,19 +0,0 @@
-.flex-tab {
- .mail-message {
- form {
- margin-top: 20px;
-
- .input-line.double-col {
- margin-bottom: 20px;
-
- label {
- line-height: 15px;
- }
-
- div {
- line-height: 15px;
- }
- }
- }
- }
-}
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.coffee b/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.coffee
deleted file mode 100644
index 686b868560829..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
-Template.channelSettingsMailMessages.helpers
- canSendEmail: ->
- return FlowRouter.getRouteName() isnt 'admin-rooms'
-
-Template.channelSettingsMailMessages.events
- 'click button.mail-messages': (e, t) ->
- Session.set 'channelSettingsMailMessages', Session.get('openedRoom')
- @tabBar.setTemplate('mailMessagesInstructions')
- view = Blaze.getView($('.messages-box')[0])
- view?.templateInstance?().resetSelection?(true)
-
-Template.channelSettingsMailMessages.onCreated ->
- view = Blaze.getView($('.messages-box')[0])
- view?.templateInstance?().resetSelection?(false)
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.html b/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.html
deleted file mode 100644
index 318c54ab66cc3..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
- {{#if canSendEmail}}
-
- {{_ "Mail_Messages"}}
-
- {{_ "Choose_messages"}}
-
-
- {{/if}}
-
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.coffee b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.coffee
deleted file mode 100644
index 4c959da860180..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.coffee
+++ /dev/null
@@ -1,126 +0,0 @@
-import toastr from 'toastr'
-Template.mailMessagesInstructions.helpers
- name: ->
- return Meteor.user().name
- email: ->
- return Meteor.user().emails?[0]?.address
- roomName: ->
- return ChatRoom.findOne(Session.get('openedRoom'))?.name
- erroredEmails: ->
- return Template.instance()?.erroredEmails.get().join(', ')
- autocompleteSettings: ->
- return {
- limit: 10
- # inputDelay: 300
- rules: [
- {
- # @TODO maybe change this 'collection' and/or template
- collection: 'CachedChannelList'
- subscription: 'userAutocomplete'
- field: 'username'
- template: Template.userSearch
- noMatchTemplate: Template.userSearchEmpty
- matchAll: true
- filter:
- exceptions: Template.instance().selectedUsers.get()
- selector: (match) ->
- return { term: match }
- sort: 'username'
- }
- ]
- }
- selectedUsers: ->
- return Template.instance().selectedUsers.get()
-
-Template.mailMessagesInstructions.events
- 'click .cancel': (e, t) ->
- t.reset()
-
- 'click .send': (e, t) ->
- t.$('.error').hide()
- $btn = t.$('button.send')
- oldBtnValue = $btn.html()
- $btn.html(TAPi18n.__('Sending'))
-
- selectedMessages = $('.messages-box .message.selected')
-
- error = false
- if selectedMessages.length is 0
- t.$('.error-select').show()
- error = true
-
- if t.$('input[name=to_emails]').val().trim()
- rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(?:>?)$/
- emails = t.$('input[name=to_emails]').val().trim().split(',')
- erroredEmails = []
- for email in emails
- unless rfcMailPatternWithName.test email.trim()
- erroredEmails.push email.trim()
-
- t.erroredEmails.set erroredEmails
- if erroredEmails.length > 0
- t.$('.error-invalid-emails').show()
- error = true
- else if not t.selectedUsers.get().length
- t.$('.error-missing-to').show()
- error = true
-
- if error
- $btn.html(oldBtnValue)
- else
- data =
- rid: Session.get('openedRoom')
- to_users: t.selectedUsers.get()
- to_emails: t.$('input[name=to_emails]').val().trim()
- subject: t.$('input[name=subject]').val().trim()
- messages: selectedMessages.map((i, message) -> return message.id).toArray()
- language: localStorage.getItem('userLanguage')
-
- Meteor.call 'mailMessages', data, (err, result) ->
- $btn.html(oldBtnValue)
- if err?
- return handleError(err)
-
- console.log(result)
- toastr.success(TAPi18n.__('Your_email_has_been_queued_for_sending'))
- t.reset()
-
- 'click .select-all': (e, t) ->
- t.$('.error-select').hide()
-
- view = Blaze.getView($('.messages-box')[0])
- view?.templateInstance?().selectedMessages = _.pluck(ChatMessage.find({rid: Session.get('openedRoom')})?.fetch(), '_id')
- $(".messages-box .message").addClass('selected')
-
- 'autocompleteselect #to_users': (event, instance, doc) ->
- instance.selectedUsers.set instance.selectedUsers.get().concat doc.username
- event.currentTarget.value = ''
- event.currentTarget.focus()
-
- 'click .remove-to-user': (e, instance) ->
- self = @
-
- users = Template.instance().selectedUsers.get()
- users = _.reject Template.instance().selectedUsers.get(), (_id) ->
- return _id is self.valueOf()
-
- Template.instance().selectedUsers.set(users)
-
- $('#to_users').focus()
-
-Template.mailMessagesInstructions.onCreated ->
- @autoCompleteCollection = new Mongo.Collection null
- @selectedUsers = new ReactiveVar []
- @erroredEmails = new ReactiveVar []
-
- currentData = Template.currentData()
-
- @reset = =>
- @selectedUsers.set []
- currentData.tabBar.setTemplate('channelSettings')
- view = Blaze.getView($('.messages-box')[0])
- view?.templateInstance?().resetSelection?(false)
-
- @autorun =>
- if Session.get('channelSettingsMailMessages') isnt Session.get('openedRoom')
- this.reset()
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
index 50c148705a456..ed3edac139931 100644
--- a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
+++ b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
@@ -1,9 +1,91 @@
+
+ {{#if selectedMessages}}
+
+
+ {{> icon block="mail-messages__instructions-icon" icon="modal-success"}}
+
+ {{selectedMessages.length}} Messages selected
+ Click here to clear the selection
+
+
+
+ {{else}}
+
+
+ {{> icon block="mail-messages__instructions-icon" icon="hand-pointer"}}
+
+ Click the messages you would like to send by e-mail
+
+
+
+ {{/if}}
+
+
+
+
+ {{#if errorMessage}}
+
+ {{/if}}
+
+
+ {{_ 'Cancel'}}
+ {{_ 'Send'}}
+
+ {{#if false}}
-
-
{{_ "Mail_Messages"}}
-
{{_ "Mail_Messages_Instructions"}}
- {{_ "Cancel"}}
- {{_ "Send"}}
+ {{_ 'Cancel'}}
+ {{_ 'Send'}}
+ {{/if}}
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.js b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.js
new file mode 100644
index 0000000000000..d81a56fda523c
--- /dev/null
+++ b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.js
@@ -0,0 +1,306 @@
+/* global AutoComplete Deps */
+import toastr from 'toastr';
+import resetSelection from '../resetSelection';
+
+/*
+ * Code from https://github.com/dleitee/valid.js
+ * Checks for email
+ * @params email
+ * @return boolean
+ */
+const isEmail = email => {
+ const sQtext = '[^\\x0d\\x22\\x5c]';
+ const sDtext = '[^\\x0d\\x5b-\\x5d]';
+ const sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d]+';
+ const sQuotedPair = '\\x5c[\\x00-\\x7f]';
+ const sDomainLiteral = `\\x5b(${ sDtext }|${ sQuotedPair })*\\x5d`;
+ const sQuotedString = `\\x22(${ sQtext }|${ sQuotedPair })*\\x22`;
+ const sDomainRef = sAtom;
+ const sSubDomain = `(${ sDomainRef }|${ sDomainLiteral })`;
+ const sWord = `(${ sAtom }|${ sQuotedString })`;
+ const sDomain = `${ sSubDomain }(\\x2e${ sSubDomain })*`;
+ const sLocalPart = `${ sWord }(\\x2e${ sWord })*`;
+ const sAddrSpec = `${ sLocalPart }\\x40${ sDomain }`;
+ const sValidEmail = `^${ sAddrSpec }$`;
+ const reg = new RegExp(sValidEmail);
+ return reg.test(email);
+};
+
+const filterNames = (old) => {
+ const reg = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
+ return [...old.replace(' ', '').toLocaleLowerCase()].filter(f => reg.test(f)).join('');
+};
+
+Template.mailMessagesInstructions.helpers({
+ name() {
+ return Meteor.user().name;
+ },
+ email() {
+ const {emails} = Meteor.user();
+ return emails && emails[0] && emails[0].address;
+ },
+ roomName() {
+ const room = ChatRoom.findOne(Session.get('openedRoom'));
+ return room && room.name;
+ },
+ erroredEmails() {
+ const instance = Template.instance();
+ return instance && instance.erroredEmails.get().join(', ');
+ },
+ autocompleteSettings() {
+ return {
+ limit: 10,
+ rules: [
+ {
+ collection: 'CachedChannelList',
+ subscription: 'userAutocomplete',
+ field: 'username',
+ template: Template.userSearch,
+ noMatchTemplate: Template.userSearchEmpty,
+ matchAll: true,
+ filter: {
+ exceptions: Template.instance().selectedUsers.get()
+ },
+ selector(match) {
+ return {
+ term: match
+ };
+ },
+ sort: 'username'
+ }
+ ]
+ };
+ },
+ selectedUsers() {
+ return Template.instance().selectedUsers.get();
+ },
+ selectedEmails() {
+ return Template.instance().selectedEmails.get();
+ },
+ selectedMessages() {
+ return Template.instance().selectedMessages.get();
+ },
+ config() {
+ const filter = Template.instance().userFilter;
+ return {
+ filter: filter.get(),
+ noMatchTemplate: 'userSearchEmpty',
+ modifier(text) {
+ const f = filter.get();
+ return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), function(part) {
+ return `${ part } `;
+ }) }`;
+ }
+ };
+ },
+ autocomplete(key) {
+ const instance = Template.instance();
+ const param = instance.ac[key];
+ return typeof param === 'function' ? param.apply(instance.ac): param;
+ },
+ items() {
+ return Template.instance().ac.filteredList();
+ },
+ errorMessage() {
+ return Template.instance().errorMessage.get();
+ }
+});
+
+Template.mailMessagesInstructions.events({
+ 'click .js-cancel, click .mail-messages__instructions--selected'(e, t) {
+ t.reset(true);
+ },
+ 'click .js-send'(e, instance) {
+ const selectedUsers = instance.selectedUsers;
+ const selectedEmails = instance.selectedEmails;
+ const $emailsInput = instance.$('[name="emails"]');
+ const selectedMessages = instance.selectedMessages;
+ const subject = instance.$('[name="subject"]').val();
+
+ if (!selectedUsers.get().length && !selectedEmails.get().length && $emailsInput.val().trim() === '') {
+ instance.errorMessage.set(t('Mail_Message_Missing_to'));
+ return false;
+ }
+
+ if ($emailsInput.val() !== '') {
+ if (isEmail($emailsInput.val())) {
+ const emailsArr = selectedEmails.get();
+ emailsArr.push({text: $emailsInput.val()});
+ $('[name="emails"]').val('');
+ selectedEmails.set(emailsArr);
+ } else {
+ instance.errorMessage.set(t('Mail_Message_Invalid_emails', $emailsInput.val()));
+ return false;
+ }
+ }
+
+ if (!selectedMessages.get().length) {
+ instance.errorMessage.set(t('Mail_Message_No_messages_selected_select_all'));
+ return false;
+ }
+
+ const data = {
+ rid: Session.get('openedRoom'),
+ to_users: selectedUsers.get().map(user => user.username),
+ to_emails: selectedEmails.get().map(email => email.text).toString(),
+ subject,
+ messages: selectedMessages.get(),
+ language: localStorage.getItem('userLanguage')
+ };
+
+ Meteor.call('mailMessages', data, function(err, result) {
+ if (err != null) {
+ return handleError(err);
+ }
+ console.log(result);
+ toastr.success(t('Your_email_has_been_queued_for_sending'));
+ instance.reset(true);
+ });
+ },
+ 'click .rc-input--usernames .rc-tags__tag'({target}, t) {
+ const {username} = Blaze.getData(target);
+ t.selectedUsers.set(t.selectedUsers.get().filter(user => user.username !== username));
+ },
+ 'click .rc-input--usernames .rc-tags__tag-icon'(e, t) {
+ const {username} = Blaze.getData(t.find('.rc-tags__tag-text'));
+ t.selectedUsers.set(t.selectedUsers.get().filter(user => user.username !== username));
+ },
+ 'click .rc-input--emails .rc-tags__tag'({target}, t) {
+ const {text} = Blaze.getData(target);
+ t.selectedEmails.set(t.selectedEmails.get().filter(email => email.text !== text));
+ },
+ 'click .rc-input--emails .rc-tags__tag-icon'(e, t) {
+ const {text} = Blaze.getData(t.find('.rc-tags__tag-text'));
+ t.selectedEmails.set(t.selectedEmails.get().filter(email => email.text !== text));
+ },
+ 'click .rc-popup-list__item'(e, t) {
+ t.ac.onItemClick(this, e);
+ },
+ 'input [name="users"]'(e, t) {
+ const input = e.target;
+ const position = input.selectionEnd || input.selectionStart;
+ const length = input.value.length;
+ const modified = filterNames(input.value);
+ input.value = modified;
+ document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length);
+
+ t.userFilter.set(modified);
+ },
+ 'keydown [name="emails"]'(e, t) {
+ const input = e.target;
+ if ([9, 13, 188].includes(e.keyCode) && isEmail(input.value)) {
+ e.preventDefault();
+ const emails = t.selectedEmails;
+ const emailsArr = emails.get();
+ emailsArr.push({text: input.value});
+ input.value = '';
+ return emails.set(emailsArr);
+ }
+
+ if ([8, 46].includes(e.keyCode) && input.value === '') {
+ const emails = t.selectedEmails;
+ const emailsArr = emails.get();
+ emailsArr.pop();
+ return emails.set(emailsArr);
+ }
+ },
+ 'keydown [name="users"]'(e, t) {
+ if ([8, 46].includes(e.keyCode) && e.target.value === '') {
+ const users = t.selectedUsers;
+ const usersArr = users.get();
+ usersArr.pop();
+ return users.set(usersArr);
+ }
+
+ t.ac.onKeyDown(e);
+ },
+ 'keyup [name="users"]'(e, t) {
+ t.ac.onKeyUp(e);
+ },
+ 'focus [name="users"]'(e, t) {
+ t.ac.onFocus(e);
+ },
+ 'blur [name="users"]'(e, t) {
+ t.ac.onBlur(e);
+ }
+});
+
+Template.mailMessagesInstructions.onRendered(function() {
+ const users = this.selectedUsers;
+
+ this.firstNode.querySelector('[name="users"]').focus();
+ this.ac.element = this.firstNode.querySelector('[name="users"]');
+ this.ac.$element = $(this.ac.element);
+ this.ac.$element.on('autocompleteselect', function(e, {item}) {
+ const usersArr = users.get();
+ usersArr.push(item);
+ users.set(usersArr);
+ });
+
+ const selectedMessages = this.selectedMessages;
+
+ $('.messages-box .message').on('click', function() {
+ const id = this.id;
+ const messages = selectedMessages.get();
+
+ if ($(this).hasClass('selected')) {
+ selectedMessages.set(messages.filter(message => message !== id));
+ } else {
+ selectedMessages.set(messages.concat(id));
+ }
+ });
+});
+
+Template.mailMessagesInstructions.onCreated(function() {
+ resetSelection(true);
+
+ this.selectedEmails = new ReactiveVar([]);
+ this.selectedMessages = new ReactiveVar([]);
+ this.errorMessage = new ReactiveVar('');
+ this.selectedUsers = new ReactiveVar([]);
+ this.userFilter = new ReactiveVar('');
+
+ const filter = {exceptions :[Meteor.user().username].concat(this.selectedUsers.get().map(u => u.username))};
+ Deps.autorun(() => {
+ filter.exceptions = [Meteor.user().username].concat(this.selectedUsers.get().map(u => u.username));
+ });
+
+ this.ac = new AutoComplete(
+ {
+ selector:{
+ item: '.rc-popup-list__item',
+ container: '.rc-popup-list__list'
+ },
+
+ limit: 10,
+ inputDelay: 300,
+ rules: [
+ {
+ collection: 'UserAndRoom',
+ subscription: 'userAutocomplete',
+ field: 'username',
+ matchAll: true,
+ filter,
+ doNotChangeWidth: false,
+ selector(match) {
+ return { term: match };
+ },
+ sort: 'username'
+ }
+ ]
+
+ });
+ this.ac.tmplInst = this;
+
+ this.reset = (bool) => {
+ this.selectedUsers.set([]);
+ this.selectedEmails.set([]);
+ this.selectedMessages.set([]);
+ this.errorMessage.set('');
+ resetSelection(bool);
+ };
+});
+
+Template.mailMessagesInstructions.onDestroyed(function() {
+ Template.instance().reset(false);
+});
diff --git a/packages/rocketchat-channel-settings-mail-messages/package.js b/packages/rocketchat-channel-settings-mail-messages/package.js
index 4892a7a8bc320..a13a746c0df59 100644
--- a/packages/rocketchat-channel-settings-mail-messages/package.js
+++ b/packages/rocketchat-channel-settings-mail-messages/package.js
@@ -8,26 +8,23 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'coffeescript',
'templating',
'reactive-var',
'less',
'rocketchat:lib',
- 'rocketchat:channel-settings'
+ 'rocketchat:channel-settings',
+ 'mongo'
]);
api.addFiles([
- 'client/lib/startup.coffee',
- 'client/stylesheets/mail-messages.less',
- 'client/views/channelSettingsMailMessages.html',
- 'client/views/channelSettingsMailMessages.coffee',
+ 'client/lib/startup.js',
'client/views/mailMessagesInstructions.html',
- 'client/views/mailMessagesInstructions.coffee'
+ 'client/views/mailMessagesInstructions.js'
], 'client');
api.addFiles([
- 'server/lib/startup.coffee',
- 'server/methods/mailMessages.coffee'
+ 'server/lib/startup.js',
+ 'server/methods/mailMessages.js'
], 'server');
});
diff --git a/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.coffee b/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.coffee
deleted file mode 100644
index 0a30dd195e498..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.startup ->
- permission = { _id: 'mail-messages', roles : [ 'admin' ] }
- RocketChat.models.Permissions.upsert( permission._id, { $setOnInsert : permission })
diff --git a/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.js b/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.js
new file mode 100644
index 0000000000000..d724f92af0509
--- /dev/null
+++ b/packages/rocketchat-channel-settings-mail-messages/server/lib/startup.js
@@ -0,0 +1,9 @@
+Meteor.startup(function() {
+ const permission = {
+ _id: 'mail-messages',
+ roles: ['admin']
+ };
+ return RocketChat.models.Permissions.upsert(permission._id, {
+ $setOnInsert: permission
+ });
+});
diff --git a/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.coffee b/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.coffee
deleted file mode 100644
index b02642efb0515..0000000000000
--- a/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.coffee
+++ /dev/null
@@ -1,65 +0,0 @@
-import moment from 'moment'
-
-Meteor.methods
- 'mailMessages': (data) ->
- if not Meteor.userId()
- throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'mailMessages' })
-
- check(data, Match.ObjectIncluding({ rid: String, to_users: [ String ], to_emails: String, subject: String, messages: [ String ], language: String }))
-
- room = Meteor.call 'canAccessRoom', data.rid, Meteor.userId()
- unless room
- throw new Meteor.Error('error-invalid-room', "Invalid room", { method: 'mailMessages' })
-
- unless RocketChat.authz.hasPermission(Meteor.userId(), 'mail-messages')
- throw new Meteor.Error 'error-action-not-allowed', 'Mailing is not allowed', { method: 'mailMessages', action: 'Mailing' }
-
- rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(?:>?)$/
-
- emails = _.compact(data.to_emails.trim().split(','))
- missing = []
- if data.to_users.length > 0
- for username in data.to_users
- user = RocketChat.models.Users.findOneByUsername(username)
- if user?.emails?[0]?.address
- emails.push user.emails[0].address
- else
- missing.push username
-
- console.log 'Sending messages to e-mails: ', emails
-
- for email in emails
- unless rfcMailPatternWithName.test email.trim()
- throw new Meteor.Error('error-invalid-email', "Invalid email #{email}", { method: 'mailMessages', email: email })
-
- user = Meteor.user()
- name = user.name
- email = user.emails?[0]?.address
-
- data.language = data.language.split('-').shift().toLowerCase()
-
- if data.language isnt 'en'
- localeFn = Meteor.call 'loadLocale', data.language
- if localeFn
- Function(localeFn)()
-
- html = ""
-
- header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || "")
- footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || "")
-
- RocketChat.models.Messages.findByRoomIdAndMessageIds(data.rid, data.messages, { sort: { ts: 1 } }).forEach (message) ->
- dateTime = moment(message.ts).locale(data.language).format('L LT')
- html += "#{message.u.username} #{dateTime} " + RocketChat.Message.parse(message, data.language) + "
"
-
- Meteor.defer ->
- Email.send
- to: emails
- from: RocketChat.settings.get('From_Email')
- replyTo: email
- subject: data.subject
- html: header + html + footer
-
- console.log 'Sending email to ' + emails.join(', ')
-
- return { success: true, missing: missing }
diff --git a/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.js b/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.js
new file mode 100644
index 0000000000000..5fd366f5bb955
--- /dev/null
+++ b/packages/rocketchat-channel-settings-mail-messages/server/methods/mailMessages.js
@@ -0,0 +1,88 @@
+import _ from 'underscore';
+import moment from 'moment';
+
+Meteor.methods({
+ 'mailMessages'(data) {
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'mailMessages'
+ });
+ }
+ check(data, Match.ObjectIncluding({
+ rid: String,
+ to_users: [String],
+ to_emails: String,
+ subject: String,
+ messages: [String],
+ language: String
+ }));
+ const room = Meteor.call('canAccessRoom', data.rid, Meteor.userId());
+ if (!room) {
+ throw new Meteor.Error('error-invalid-room', 'Invalid room', {
+ method: 'mailMessages'
+ });
+ }
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'mail-messages')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Mailing is not allowed', {
+ method: 'mailMessages',
+ action: 'Mailing'
+ });
+ }
+ const rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(?:>?)$/;
+ const emails = _.compact(data.to_emails.trim().split(','));
+ const missing = [];
+ if (data.to_users.length > 0) {
+ _.each(data.to_users, (username) => {
+ const user = RocketChat.models.Users.findOneByUsername(username);
+ if (user && user.emails && user.emails[0] && user.emails[0].address) {
+ emails.push(user.emails[0].address);
+ } else {
+ missing.push(username);
+ }
+ });
+ }
+ console.log('Sending messages to e-mails: ', emails);
+ _.each(emails, (email) => {
+ if (!rfcMailPatternWithName.test(email.trim())) {
+ throw new Meteor.Error('error-invalid-email', `Invalid email ${ email }`, {
+ method: 'mailMessages',
+ email
+ });
+ }
+ });
+ const user = Meteor.user();
+ const email = user.emails && user.emails[0] && user.emails[0].address;
+ data.language = data.language.split('-').shift().toLowerCase();
+ if (data.language !== 'en') {
+ const localeFn = Meteor.call('loadLocale', data.language);
+ if (localeFn) {
+ Function(localeFn).call({moment});
+ moment.locale(data.language);
+ }
+ }
+
+ const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
+ const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
+ const html = RocketChat.models.Messages.findByRoomIdAndMessageIds(data.rid, data.messages, {
+ sort: { ts: 1 }
+ }).map(function(message) {
+ const dateTime = moment(message.ts).locale(data.language).format('L LT');
+ return `${ message.u.username } ${ dateTime } ${ RocketChat.Message.parse(message, data.language) }
`;
+ }).join('');
+
+ Meteor.defer(function() {
+ Email.send({
+ to: emails,
+ from: RocketChat.settings.get('From_Email'),
+ replyTo: email,
+ subject: data.subject,
+ html: header + html + footer
+ });
+ return console.log(`Sending email to ${ emails.join(', ') }`);
+ });
+ return {
+ success: true,
+ missing
+ };
+ }
+});
diff --git a/packages/rocketchat-channel-settings/client/lib/ChannelSettings.coffee b/packages/rocketchat-channel-settings/client/lib/ChannelSettings.coffee
deleted file mode 100644
index 57e23f6b457ac..0000000000000
--- a/packages/rocketchat-channel-settings/client/lib/ChannelSettings.coffee
+++ /dev/null
@@ -1,30 +0,0 @@
-RocketChat.ChannelSettings = new class
- options = new ReactiveVar {}
-
- ###
- # Adds an option in Channel Settings
- # @config (object)
- # id: option id (required)
- # template (string): template name to render (required)
- # validation (function): if option should be displayed
- ###
- addOption = (config) ->
- unless config?.id
- return false
-
- Tracker.nonreactive ->
- opts = options.get()
- opts[config.id] = config
- options.set opts
-
- getOptions = (currentData) ->
- allOptions = _.toArray options.get()
- allowedOptions = _.compact _.map allOptions, (option) ->
- if not option.validation? or option.validation()
- option.data = Object.assign (option.data or {}), currentData
- return option
-
- return _.sortBy allowedOptions, 'order'
-
- addOption: addOption
- getOptions: getOptions
diff --git a/packages/rocketchat-channel-settings/client/lib/ChannelSettings.js b/packages/rocketchat-channel-settings/client/lib/ChannelSettings.js
new file mode 100644
index 0000000000000..164d5f240a347
--- /dev/null
+++ b/packages/rocketchat-channel-settings/client/lib/ChannelSettings.js
@@ -0,0 +1,38 @@
+import _ from 'underscore';
+RocketChat.ChannelSettings = new class {
+ constructor() {
+ this.options = new ReactiveVar({});
+ }
+
+ /*
+ * Adds an option in Channel Settings
+ * @config (object)
+ * id: option id (required)
+ * template (string): template name to render (required)
+ * validation (function): if option should be displayed
+ */
+ addOption(config) {
+ if (config == null || config.id == null) {
+ return false;
+ }
+ return Tracker.nonreactive(() => {
+ const opts = this.options.get();
+ opts[config.id] = config;
+ return this.options.set(opts);
+ });
+ }
+
+ getOptions(currentData = {}, group) {
+ const allOptions = _.toArray(this.options.get());
+ const allowedOptions = _.compact(_.map(allOptions, function(option) {
+ const ret = {...option};
+ if (option.validation == null || option.validation(currentData)) {
+ ret.data = Object.assign({}, typeof option.data === 'function' ? option.data() : option.data, currentData);
+ return ret;
+ }
+ })).filter(function(option) {
+ return !group || !option.group || option.group.includes(group);
+ });
+ return _.sortBy(allowedOptions, 'order');
+ }
+};
diff --git a/packages/rocketchat-channel-settings/client/startup/messageTypes.coffee b/packages/rocketchat-channel-settings/client/startup/messageTypes.coffee
deleted file mode 100644
index 6d34cd8c9397e..0000000000000
--- a/packages/rocketchat-channel-settings/client/startup/messageTypes.coffee
+++ /dev/null
@@ -1,28 +0,0 @@
-Meteor.startup ->
- RocketChat.MessageTypes.registerType
- id: 'room_changed_privacy'
- system: true
- message: 'room_changed_privacy'
- data: (message) ->
- return {
- user_by: message.u?.username
- room_type: message.msg
- }
-
- RocketChat.MessageTypes.registerType
- id: 'room_changed_topic'
- system: true
- message: 'room_changed_topic'
- data: (message) ->
- return {
- user_by: message.u?.username
- room_topic: message.msg
- }
-
- RocketChat.MessageTypes.registerType
- id: 'room_changed_description'
- system: true
- message: 'room_changed_description'
- data: (message) ->
- user_by: message.u?.username
- room_description: message.msg
diff --git a/packages/rocketchat-channel-settings/client/startup/messageTypes.js b/packages/rocketchat-channel-settings/client/startup/messageTypes.js
new file mode 100644
index 0000000000000..d29a7f9bc3c45
--- /dev/null
+++ b/packages/rocketchat-channel-settings/client/startup/messageTypes.js
@@ -0,0 +1,49 @@
+Meteor.startup(function() {
+ RocketChat.MessageTypes.registerType({
+ id: 'room_changed_privacy',
+ system: true,
+ message: 'room_changed_privacy',
+ data(message) {
+ return {
+ user_by: message.u && message.u.username,
+ room_type: t(message.msg)
+ };
+ }
+ });
+
+ RocketChat.MessageTypes.registerType({
+ id: 'room_changed_topic',
+ system: true,
+ message: 'room_changed_topic',
+ data(message) {
+ return {
+ user_by: message.u && message.u.username,
+ room_topic: message.msg
+ };
+ }
+ });
+
+ RocketChat.MessageTypes.registerType({
+ id: 'room_changed_announcement',
+ system: true,
+ message: 'room_changed_announcement',
+ data(message) {
+ return {
+ user_by: message.u && message.u.username,
+ room_announcement: message.msg
+ };
+ }
+ });
+
+ RocketChat.MessageTypes.registerType({
+ id: 'room_changed_description',
+ system: true,
+ message: 'room_changed_description',
+ data(message) {
+ return {
+ user_by: message.u && message.u.username,
+ room_description: message.msg
+ };
+ }
+ });
+});
diff --git a/packages/rocketchat-channel-settings/client/startup/tabBar.coffee b/packages/rocketchat-channel-settings/client/startup/tabBar.coffee
deleted file mode 100644
index 52245c27b6a63..0000000000000
--- a/packages/rocketchat-channel-settings/client/startup/tabBar.coffee
+++ /dev/null
@@ -1,8 +0,0 @@
-Meteor.startup ->
- RocketChat.TabBar.addButton
- groups: ['channel', 'group', 'direct']
- id: 'channel-settings'
- i18nTitle: 'Room_Info'
- icon: 'icon-info-circled'
- template: 'channelSettings'
- order: 0
diff --git a/packages/rocketchat-channel-settings/client/startup/tabBar.js b/packages/rocketchat-channel-settings/client/startup/tabBar.js
new file mode 100644
index 0000000000000..8fa4e08348b06
--- /dev/null
+++ b/packages/rocketchat-channel-settings/client/startup/tabBar.js
@@ -0,0 +1,11 @@
+Meteor.startup(() => {
+ RocketChat.TabBar.addButton({
+ groups: ['channel', 'group', 'direct'],
+ id: 'channel-settings',
+ anonymous: true,
+ i18nTitle: 'Room_Info',
+ icon: 'info-circled',
+ template: 'channelSettings',
+ order: 0
+ });
+});
diff --git a/packages/rocketchat-channel-settings/client/startup/trackSettingsChange.js b/packages/rocketchat-channel-settings/client/startup/trackSettingsChange.js
index 121550e8e1b0e..8df8addd789fb 100644
--- a/packages/rocketchat-channel-settings/client/startup/trackSettingsChange.js
+++ b/packages/rocketchat-channel-settings/client/startup/trackSettingsChange.js
@@ -1,13 +1,13 @@
Meteor.startup(function() {
- let roomSettingsChangedCallback = (msg) => {
+ const roomSettingsChangedCallback = (msg) => {
Tracker.nonreactive(() => {
if (msg.t === 'room_changed_privacy') {
if (Session.get('openedRoom') === msg.rid) {
- let type = FlowRouter.current().route.name === 'channel' ? 'c' : 'p';
+ const type = FlowRouter.current().route.name === 'channel' ? 'c' : 'p';
RoomManager.close(type + FlowRouter.getParam('name'));
const subscription = ChatSubscription.findOne({ rid: msg.rid });
- let route = subscription.t === 'c' ? 'channel' : 'group';
+ const route = subscription.t === 'c' ? 'channel' : 'group';
FlowRouter.go(route, { name: subscription.name }, FlowRouter.current().queryParams);
}
}
@@ -18,13 +18,15 @@ Meteor.startup(function() {
RocketChat.callbacks.add('streamMessage', roomSettingsChangedCallback, RocketChat.callbacks.priority.HIGH, 'room-settings-changed');
- let roomNameChangedCallback = (msg) => {
+ const roomNameChangedCallback = (msg) => {
Tracker.nonreactive(() => {
if (msg.t === 'r') {
if (Session.get('openedRoom') === msg.rid) {
- let type = FlowRouter.current().route.name === 'channel' ? 'c' : 'p';
- RoomManager.close(type + FlowRouter.getParam('name'));
- FlowRouter.go(FlowRouter.current().route.name, { name: msg.msg }, FlowRouter.current().queryParams);
+ const room = ChatRoom.findOne(msg.rid);
+ if (room.name !== FlowRouter.getParam('name')) {
+ RoomManager.close(room.t + FlowRouter.getParam('name'));
+ RocketChat.roomTypes.openRouteLink(room.t, room, FlowRouter.current().queryParams);
+ }
}
}
});
diff --git a/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.css b/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.css
new file mode 100644
index 0000000000000..92842a79ea8e9
--- /dev/null
+++ b/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.css
@@ -0,0 +1,130 @@
+html.rtl .flex-tab {
+ direction: rtl;
+
+ & .channel-settings {
+ & .editing {
+ padding-right: 8px;
+ padding-left: 80px;
+ }
+ & .buttons {
+ right: auto;
+ left: 1px;
+ border-radius: 4px 0 0 4px;
+ }
+ }
+}
+
+.flex-tab {
+ & .channel-settings {
+ & ul {
+ & li {
+ margin-bottom: 20px;
+ }
+ }
+
+ & label {
+ display: block;
+
+ margin-bottom: 5px;
+
+ font-size: 14px;
+ font-weight: bold;
+ }
+
+ & .current-setting {
+ display: inline-block;
+
+ width: calc(100% - 38px);
+ min-height: 20px;
+ margin-top: 3px;
+
+ cursor: pointer;
+ vertical-align: middle;
+ word-wrap: break-word;
+
+ font-size: 14px;
+
+ &[data-edit="false"] {
+ cursor: inherit;
+ user-select: initial;
+ }
+ }
+
+ & .editing {
+ padding-right: 80px;
+ font-size: 14px;
+ }
+
+ & .buttons {
+ position: absolute;
+ top: -1px;
+ right: 10px;
+
+ border-radius: 0 4px 4px 0;
+
+ & .button {
+ padding: 8px;
+ }
+ }
+
+ & .button {
+ display: inline-block;
+ visibility: hidden;
+
+ padding: 8px;
+
+ vertical-align: middle;
+
+ font-size: 12px;
+ }
+
+ & .submit {
+ margin-top: 30px;
+
+ text-align: center;
+ }
+
+ & .boolean {
+ font-size: 0;
+
+ & > label {
+ display: inline-block;
+
+ width: calc(100% - 45px);
+
+ vertical-align: middle;
+ }
+
+ & .setting-block {
+ display: inline-block;
+
+ width: 40px;
+ margin-left: -5px;
+
+ vertical-align: middle;
+ }
+ }
+
+ & .setting-block {
+ position: relative;
+
+ font-size: 0;
+
+ display: flex;
+
+ & .loading-animation {
+ top: 30px;
+ }
+
+ &:hover {
+ & .button {
+ visibility: visible;
+ }
+ }
+ }
+
+ & nav {
+ text-align: right;
+ }
+ }
+}
diff --git a/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less b/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less
deleted file mode 100644
index 5bfe3351fd9b6..0000000000000
--- a/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less
+++ /dev/null
@@ -1,98 +0,0 @@
-.flex-tab {
- .channel-settings {
- ul {
- li {
- margin-bottom: 20px;
- }
- }
-
- label {
- display: block;
- font-weight: bold;
- margin-bottom: 5px;
- font-size: 14px;
- }
-
- .current-setting {
- font-size: 14px;
- width: calc(~"100% - 38px");
- display: inline-block;
- vertical-align: middle;
- min-height: 20px;
- cursor: pointer;
- margin-top: 3px;
-
- &[data-edit="false"] {
- cursor: inherit;
- user-select: initial;
- }
- }
-
- .editing {
- padding-right: 80px;
- font-size: 14px;
- margin: -2px 0 -1px -9px;
- }
-
- .buttons {
- position: absolute;
- top: -1px;
- bottom: 0;
- right: 10px;
- border-radius: 0 4px 4px 0;
-
- .button {
- padding: 8px;
- }
- }
-
- .button.edit {
- padding: 8px;
- font-size: 12px;
- vertical-align: middle;
- display: inline-block;
- visibility: hidden;
- }
-
- .submit {
- margin-top: 30px;
- text-align: center;
- }
-
- .boolean {
- font-size: 0;
-
- > label {
- width: calc(~"100% - 45px");
- display: inline-block;
- vertical-align: middle;
- }
-
- .setting-block {
- width: 40px;
- display: inline-block;
- vertical-align: middle;
- margin-left: -5px;
- }
- }
-
- .setting-block {
- position: relative;
- font-size: 0;
-
- .loading-animation {
- top: 30px;
- }
-
- &:hover {
- .button.edit {
- visibility: visible;
- }
- }
- }
-
- nav {
- text-align: right;
- }
- }
-}
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.coffee b/packages/rocketchat-channel-settings/client/views/channelSettings.coffee
deleted file mode 100644
index 630e7517898f4..0000000000000
--- a/packages/rocketchat-channel-settings/client/views/channelSettings.coffee
+++ /dev/null
@@ -1,266 +0,0 @@
-import toastr from 'toastr'
-Template.channelSettings.helpers
- toArray: (obj) ->
- arr = []
- for key, value of obj
- arr.push
- $key: key
- $value: value
- return arr
-
- valueOf: (obj, key) ->
- if key is 't'
- if obj[key] is 'c'
- return false
-
- return true
- return obj?[key]
-
- showSetting: (setting, room) ->
- if setting.showInDirect is false
- return room.t isnt 'd'
- return true
-
- settings: ->
- return Template.instance().settings
-
- getRoom: ->
- return ChatRoom.findOne(@rid)
-
- editing: (field) ->
- return Template.instance().editing.get() is field
-
- isDisabled: (field, room) ->
- return Template.instance().settings[field].processing.get() or !RocketChat.authz.hasAllPermission('edit-room', room._id)
-
- channelSettings: ->
- return RocketChat.ChannelSettings.getOptions(Template.currentData())
-
- unscape: (value) ->
- return s.unescapeHTML value
-
- canDeleteRoom: ->
- roomType = ChatRoom.findOne(@rid, { fields: { t: 1 }})?.t
- return roomType? and RocketChat.authz.hasAtLeastOnePermission("delete-#{roomType}", @rid)
-
- readOnly: ->
- return ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
-
- readOnlyDescription: ->
- readOnly = ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
- if readOnly is true
- return t('True')
- else
- return t('False')
-
-
-
-Template.channelSettings.events
- 'click .delete': ->
- swal {
- title: t('Are_you_sure')
- text: t('Delete_Room_Warning')
- type: 'warning'
- showCancelButton: true
- confirmButtonColor: '#DD6B55'
- confirmButtonText: t('Yes_delete_it')
- cancelButtonText: t('Cancel')
- closeOnConfirm: false
- html: false
- }, =>
- swal.disableButtons()
-
- Meteor.call 'eraseRoom', @rid, (error, result) ->
- if error
- handleError(error)
- swal.enableButtons()
- else
- swal
- title: t('Deleted')
- text: t('Room_has_been_deleted')
- type: 'success'
- timer: 2000
- showConfirmButton: false
-
- 'keydown input[type=text]': (e, t) ->
- if e.keyCode is 13
- e.preventDefault()
- t.saveSetting()
-
- 'click [data-edit]': (e, t) ->
- e.preventDefault()
- if $(e.currentTarget).data('edit')
- t.editing.set($(e.currentTarget).data('edit'))
- setTimeout (-> t.$('input.editing').focus().select()), 100
-
- 'change [type="radio"]': (e, t) ->
- t.editing.set($(e.currentTarget).attr('name'))
-
- 'change [type="checkbox"]': (e, t) ->
- t.editing.set($(e.currentTarget).attr('name'))
- t.saveSetting()
-
- 'click .cancel': (e, t) ->
- e.preventDefault()
- t.editing.set()
-
- 'click .save': (e, t) ->
- e.preventDefault()
- t.saveSetting()
-
-Template.channelSettings.onCreated ->
- @editing = new ReactiveVar
-
- @settings =
- name:
- type: 'text'
- label: 'Name'
- canView: (room) => room.t isnt 'd'
- canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
- save: (value, room) ->
- if not RocketChat.authz.hasAllPermission('edit-room', room._id) or room.t not in ['c', 'p']
- return toastr.error t('error-not-allowed')
-
- try
- nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$'
- catch
- nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$'
-
- if not nameValidation.test value
- return toastr.error t('error-invalid-room-name', { room_name: name: value })
-
- RocketChat.callbacks.run 'roomNameChanged', { _id: room._id, name: value }
- Meteor.call 'saveRoomSettings', room._id, 'roomName', value, (err, result) ->
- return handleError err if err
- toastr.success TAPi18n.__ 'Room_name_changed_successfully'
-
- topic:
- type: 'markdown'
- label: 'Topic'
- canView: (room) => true
- canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
- save: (value, room) ->
- Meteor.call 'saveRoomSettings', room._id, 'roomTopic', value, (err, result) ->
- return handleError err if err
- toastr.success TAPi18n.__ 'Room_topic_changed_successfully'
- RocketChat.callbacks.run 'roomTopicChanged', room
-
- description:
- type: 'text'
- label: 'Description'
- canView: (room) => room.t isnt 'd'
- canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
- save: (value, room) ->
- Meteor.call 'saveRoomSettings', room._id, 'roomDescription', value, (err, result) ->
- return handleError err if err
- toastr.success TAPi18n.__ 'Room_description_changed_successfully'
-
- t:
- type: 'boolean'
- label: 'Private'
- isToggle: true
- processing: new ReactiveVar(false)
- canView: (room) ->
- if room.t not in ['c', 'p']
- return false
- else if room.t is 'p' and not RocketChat.authz.hasAllPermission('create-c')
- return false
- else if room.t is 'c' and not RocketChat.authz.hasAllPermission('create-p')
- return false
- return true
- canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
- save: (value, room) ->
- @processing.set(true)
- value = if value then 'p' else 'c'
- RocketChat.callbacks.run 'roomTypeChanged', room
- Meteor.call 'saveRoomSettings', room._id, 'roomType', value, (err, result) =>
- return handleError err if err
- @processing.set(false)
- toastr.success TAPi18n.__ 'Room_type_changed_successfully'
-
- ro:
- type: 'boolean'
- label: 'Read_only'
- isToggle: true
- processing: new ReactiveVar(false)
- canView: (room) => room.t isnt 'd'
- canEdit: (room) => RocketChat.authz.hasAllPermission('set-readonly', room._id)
- save: (value, room) ->
- @processing.set(true)
- Meteor.call 'saveRoomSettings', room._id, 'readOnly', value, (err, result) =>
- return handleError err if err
- @processing.set(false)
- toastr.success TAPi18n.__ 'Read_only_changed_successfully'
-
- reactWhenReadOnly:
- type: 'boolean'
- label: 'React_when_read_only'
- canView: (room) => room.t isnt 'd' and room.ro
- canEdit: (room) => RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id)
- save: (value, room) ->
- Meteor.call 'saveRoomSettings', room._id, 'reactWhenReadOnly', value, (err, result) ->
- return handleError err if err
- toastr.success TAPi18n.__ 'React_when_read_only_changed_successfully'
-
- archived:
- type: 'boolean'
- label: 'Room_archivation_state_true'
- isToggle: true,
- processing: new ReactiveVar(false)
- canView: (room) => room.t isnt 'd'
- canEdit: (room) => RocketChat.authz.hasAtLeastOnePermission(['archive-room', 'unarchive-room'], room._id)
- save: (value, room) =>
- swal {
- title: t('Are_you_sure')
- type: 'warning'
- showCancelButton: true
- confirmButtonColor: '#DD6B55'
- confirmButtonText: if value then t('Yes_archive_it') else t('Yes_unarchive_it')
- cancelButtonText: t('Cancel')
- closeOnConfirm: false
- html: false
- }, (confirmed) =>
- swal.disableButtons()
- if (confirmed)
- action = if value then 'archiveRoom' else 'unarchiveRoom'
- Meteor.call action, room._id, (err, results) =>
- if err
- swal.enableButtons()
- handleError err
- swal
- title: if value then t('Room_archived') else t('Room_has_been_archived')
- text: if value then t('Room_has_been_archived') else t('Room_has_been_unarchived')
- type: 'success'
- timer: 2000
- showConfirmButton: false
- RocketChat.callbacks.run action, room
- else
- $(".channel-settings form [name='archived']").prop('checked', room.archived)
-
- joinCode:
- type: 'text'
- label: 'Code'
- canView: (room) => room.t is 'c' and RocketChat.authz.hasAllPermission('edit-room', room._id)
- canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
- save: (value, room) ->
- Meteor.call 'saveRoomSettings', room._id, 'joinCode', value, (err, result) ->
- return handleError err if err
- toastr.success TAPi18n.__ 'Room_code_changed_successfully'
- RocketChat.callbacks.run 'roomCodeChanged', room
-
-
- @saveSetting = =>
- room = ChatRoom.findOne @data?.rid
- field = @editing.get()
-
- if @settings[field].type is 'select'
- value = @$(".channel-settings form [name=#{field}]:checked").val()
- else if @settings[field].type is 'boolean'
- value = @$(".channel-settings form [name=#{field}]").is(":checked")
- else
- value = @$(".channel-settings form [name=#{field}]").val()
-
- if value isnt room[field]
- @settings[field].save(value, room)
-
- @editing.set()
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.html b/packages/rocketchat-channel-settings/client/views/channelSettings.html
index 562590be0c786..735b947029ec3 100644
--- a/packages/rocketchat-channel-settings/client/views/channelSettings.html
+++ b/packages/rocketchat-channel-settings/client/views/channelSettings.html
@@ -1,95 +1,252 @@
-
-
-
-
{{_ "Room_Info"}}
+ {{#if editing}}
+ {{> channelSettingsEditing}}
+ {{else}}
+ {{> channelSettingsInfo}}
+ {{/if}}
+
+
+
+
+
+ {{_ 'Cancel'}}
+ {{_ 'Reset'}}
+ {{_ 'Save'}}
+
+
{{#if canDeleteRoom}}
-
-
-
+ {{> icon icon='trash'}}{{_ 'Delete'}}
{{/if}}
+
+
+ {{# with settings=settings}}
+ {{#unless isDirectMessage}}
+
+
+ {{#if archived}}
+
+ {{_ "Room_archived"}}
+
+ {{/if}}
+ {{> avatar username=channelName}}
+
+
{{> icon block="rc-header__icon" icon=channelIcon}}{{ unscape name}}
+ {{#if password}}
+
+ {{_ "Room_archived"}}
+
+ {{/if}}
+
+
+ {{_ "Description"}}
+
+ {{unscape description}}
+
+
+ {{/unless}}
+
+ {{_ "Announcement"}}
+
+ {{unscape announcement}}
+
+
+
+ {{_ "Topic"}}
+
+ {{unscape topic}}
+
+
+
+ {{/with}}
+ {{#each channelSettings}}
+
+ {{> Template.dynamic template=template data=data}}
+
+ {{/each}}
+
+
+
+ {{#if canEditRoom}}
+ {{> icon icon='edit'}}{{_ "Edit"}}
+ {{/if}}
+ {{> icon icon='eye-off'}}{{_ "Hide"}}
+ {{#if canLeaveRoom}}
+ {{> icon icon='sign-out'}}{{_ 'Leave'}}
+ {{/if}}
+
+
+
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.js b/packages/rocketchat-channel-settings/client/views/channelSettings.js
new file mode 100644
index 0000000000000..3e13b3e067770
--- /dev/null
+++ b/packages/rocketchat-channel-settings/client/views/channelSettings.js
@@ -0,0 +1,477 @@
+import toastr from 'toastr';
+import s from 'underscore.string';
+import { call, erase, hide, leave, RocketChat, RoomSettingsEnum } from 'meteor/rocketchat:lib';
+const common = {
+ canLeaveRoom() {
+ const { cl: canLeave, t: roomType } = Template.instance().room;
+ return roomType !== 'd' && canLeave !== false;
+ },
+ canDeleteRoom() {
+ const room = ChatRoom.findOne(this.rid, {
+ fields: {
+ t: 1
+ }
+ });
+
+ const roomType = room && room.t;
+ return roomType && RocketChat.roomTypes.roomTypes[room.t].canBeDeleted(room);
+ },
+ canEditRoom() {
+ const { _id } = Template.instance().room;
+ return RocketChat.authz.hasAllPermission('edit-room', _id);
+ },
+ isDirectMessage() {
+ const { room } = Template.instance();
+ return room.t === 'd';
+ }
+};
+
+Template.channelSettingsEditing.events({
+ 'input .js-input'(e) {
+ this.value.set(e.currentTarget.value);
+ },
+ 'change .js-input-check'(e) {
+ this.value.set(e.currentTarget.checked);
+ },
+ 'click .js-reset'(e, t) {
+ const { settings } = t;
+ Object.keys(settings).forEach(key => settings[key].value.set(settings[key].default.get()));
+ },
+ async 'click .js-save'(e, t) {
+ const { settings } = t;
+ Object.keys(settings).forEach(async name => {
+ const setting = settings[name];
+ const value = setting.value.get();
+ if (setting.default.get() !== value) {
+ await setting.save(value).then(() => {
+ setting.default.set(value);
+ setting.value.set(value);
+ }, console.log);
+ }
+ });
+ }
+});
+
+Template.channelSettingsEditing.onCreated(function() {
+ const room = this.room = ChatRoom.findOne(this.data && this.data.rid);
+ this.settings = {
+ name: {
+ type: 'text',
+ label: 'Name',
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.NAME);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ getValue() {
+ if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ return room.fname || room.name;
+ }
+
+ return room.name;
+ },
+ save(value) {
+ let nameValidation;
+
+ if (!RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ try {
+ nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
+ } catch (error1) {
+ nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
+ }
+
+ if (!nameValidation.test(value)) {
+ return Promise.reject(toastr.error(t('error-invalid-room-name', {
+ room_name: {
+ name: value
+ }
+ })));
+ }
+ }
+ return call('saveRoomSettings', room._id, RoomSettingsEnum.NAME, value).then(function() {
+ RocketChat.callbacks.run('roomNameChanged', {
+ _id: room._id,
+ name: value
+ });
+
+ return toastr.success(TAPi18n.__('Room_name_changed_successfully'));
+ });
+ }
+ },
+ topic: {
+ type: 'markdown',
+ label: 'Topic',
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.TOPIC);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, RoomSettingsEnum.TOPIC, value).then(function() {
+ toastr.success(TAPi18n.__('Room_topic_changed_successfully'));
+ return RocketChat.callbacks.run('roomTopicChanged', room);
+ });
+ }
+ },
+ announcement: {
+ type: 'markdown',
+ label: 'Announcement',
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.ANNOUNCEMENT);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, RoomSettingsEnum.ANNOUNCEMENT, value).then(() => {
+ toastr.success(TAPi18n.__('Room_announcement_changed_successfully'));
+ return RocketChat.callbacks.run('roomAnnouncementChanged', room);
+ });
+ }
+ },
+ description: {
+ type: 'text',
+ label: 'Description',
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.DESCRIPTION);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, RoomSettingsEnum.DESCRIPTION, value).then(function() {
+ return toastr.success(TAPi18n.__('Room_description_changed_successfully'));
+ });
+ }
+ },
+ t: {
+ type: 'boolean',
+ // label() {
+ // return ;
+ // },
+ isToggle: true,
+ processing: new ReactiveVar(false),
+ getValue() {
+ return room.t === 'p';
+ },
+ disabled() {
+ return room['default'] && !RocketChat.authz.hasRole(Meteor.userId(), 'admin');
+ },
+ message() {
+ if (RocketChat.authz.hasAllPermission('edit-room', room._id) && room['default']) {
+ if (!RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
+ return 'Room_type_of_default_rooms_cant_be_changed';
+ }
+ }
+ },
+ canView() {
+ if (!['c', 'p'].includes(room.t)) {
+ return false;
+ } else if (room.t === 'p' && !RocketChat.authz.hasAllPermission('create-c')) {
+ return false;
+ } else if (room.t === 'c' && !RocketChat.authz.hasAllPermission('create-p')) {
+ return false;
+ }
+ return true;
+ },
+ canEdit() {
+ return (RocketChat.authz.hasAllPermission('edit-room', room._id) && !room['default']) || RocketChat.authz.hasRole(Meteor.userId(), 'admin');
+ },
+ save(value) {
+ const saveRoomSettings = () => {
+ value = value ? 'p' : 'c';
+ RocketChat.callbacks.run('roomTypeChanged', room);
+ return call('saveRoomSettings', room._id, 'roomType', value).then(() => {
+ return toastr.success(TAPi18n.__('Room_type_changed_successfully'));
+ });
+ };
+ if (room['default']) {
+ if (RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
+ return new Promise((resolve, reject) => {
+ modal.open({
+ title: t('Room_default_change_to_private_will_be_default_no_more'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: true,
+ html: false
+ }, function(confirmed) {
+ if (confirmed) {
+ return resolve(saveRoomSettings());
+ }
+ return reject();
+ });
+
+ });
+ }
+ // return $('.channel-settings form [name=\'t\']').prop('checked', !!room.type === 'p');
+ }
+ return saveRoomSettings();
+ }
+ },
+ ro: {
+ type: 'boolean',
+ label: 'Read_only',
+ isToggle: true,
+ processing: new ReactiveVar(false),
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.READ_ONLY);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('set-readonly', room._id);
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, RoomSettingsEnum.READ_ONLY, value).then(() => toastr.success(TAPi18n.__('Read_only_changed_successfully')));
+ }
+ },
+ reactWhenReadOnly: {
+ type: 'boolean',
+ label: 'React_when_read_only',
+ isToggle: true,
+ processing: new ReactiveVar(false),
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.REACT_WHEN_READ_ONLY) && room.ro;
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id);
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, 'reactWhenReadOnly', value).then(() => {
+ toastr.success(TAPi18n.__('React_when_read_only_changed_successfully'));
+ });
+ }
+ },
+ archived: {
+ type: 'boolean',
+ label: 'Room_archivation_state_true',
+ isToggle: true,
+ processing: new ReactiveVar(false),
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAtLeastOnePermission(['archive-room', 'unarchive-room'], room._id);
+ },
+ save(value) {
+ return new Promise((resolve, reject) => {
+ modal.open({
+ title: t('Are_you_sure'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: value ? t('Yes_archive_it') : t('Yes_unarchive_it'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, function(confirmed) {
+ if (confirmed) {
+ const action = value ? 'archiveRoom' : 'unarchiveRoom';
+ return resolve(call(action, room._id).then(() => {
+ modal.open({
+ title: value ? t('Room_archived') : t('Room_has_been_archived'),
+ text: value ? t('Room_has_been_archived') : t('Room_has_been_unarchived'),
+ type: 'success',
+ timer: 2000,
+ showConfirmButton: false
+ });
+ return RocketChat.callbacks.run(action, room);
+ }));
+ }
+ return reject();
+ });
+ });
+ }
+ },
+ joinCode: {
+ type: 'text',
+ label: 'Password',
+ showingValue: new ReactiveVar(false),
+ realValue: null,
+ canView() {
+ return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.JOIN_CODE) && RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ canEdit() {
+ return RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ getValue() {
+ if (this.showingValue.get()) {
+ return this.realValue;
+ }
+ return room.joinCodeRequired ? '*****' : '';
+ },
+ showHideValue() {
+ return room.joinCodeRequired;
+ },
+ cancelEditing() {
+ this.showingValue.set(false);
+ this.realValue = null;
+ },
+ async showValue(_room, forceShow = false) {
+ if (this.showingValue.get()) {
+ if (forceShow) {
+ return;
+ }
+ this.showingValue.set(false);
+ this.realValue = null;
+
+ return null;
+ }
+ return call('getRoomJoinCode', room._id).then(result => {
+ this.realValue = result;
+ this.showingValue.set(true);
+ });
+ },
+ save(value) {
+ return call('saveRoomSettings', room._id, 'joinCode', value).then(function() {
+ toastr.success(TAPi18n.__('Room_password_changed_successfully'));
+ return RocketChat.callbacks.run('roomCodeChanged', room);
+ });
+ }
+ }
+ };
+ Object.keys(this.settings).forEach(key => {
+ const setting = this.settings[key];
+ const def = setting.getValue ? setting.getValue(this.room) : this.room[key];
+ setting.default = new ReactiveVar(def || false);
+ setting.value = new ReactiveVar(def || false);
+ });
+});
+
+Template.channelSettingsEditing.helpers({
+ ...common,
+ value() {
+ return this.value.get();
+ },
+ default() {
+ return this.default.get();
+ },
+ disabled() {
+ return !this.canEdit();
+ },
+ checked() {
+ return this.value.get();// ? '' : 'checked';
+ },
+ modified(text = '') {
+ const { settings } = Template.instance();
+ return !Object.keys(settings).some(key => settings[key].default.get() !== settings[key].value.get()) ? text : '';
+ },
+ equal(text = '', text2 = '', ret = '*') {
+ return text === text2 ? '' : ret;
+ },
+ getIcon(room) {
+ const roomType = RocketChat.models.Rooms.findOne(room._id).t;
+ switch (roomType) {
+ case 'd':
+ return 'at';
+ case 'p':
+ return 'lock';
+ case 'c':
+ return 'hashtag';
+ case 'l':
+ return 'livechat';
+ default:
+ return null;
+ }
+ },
+ settings() {
+ return Template.instance().settings;
+ },
+ editing(field) {
+ return Template.instance().editing.get() === field;
+ },
+ isDisabled(field, room) {
+ const setting = Template.instance().settings[field];
+ return (typeof setting.disabled === 'function' && setting.disabled(room)) || setting.processing.get() || !RocketChat.authz.hasAllPermission('edit-room', room._id);
+ },
+ unscape(value) {
+ return s.unescapeHTML(value);
+ }
+});
+
+Template.channelSettings.helpers({
+ editing() {
+ return Template.instance().editing.get();
+ }
+});
+
+Template.channelSettings.onCreated(function() {
+ this.room = ChatRoom.findOne(this.data && this.data.rid);
+ this.editing = new ReactiveVar(false);
+});
+
+Template.channelSettings.events({
+ 'click .js-edit'(e, t) {
+ t.editing.set(true);
+ },
+ 'click .js-leave'(e, instance) {
+ const { name, t: type } = instance.room;
+ const rid = instance.room._id;
+ leave(type, rid, name);
+ },
+ 'click .js-hide'(e, instance) {
+ const { name, t: type } = instance.room;
+ const rid = instance.room._id;
+ hide(type, rid, name);
+ },
+ 'click .js-cancel'(e, t) {
+ t.editing.set(false);
+ },
+ 'click .js-delete'() {
+ return erase(this.rid);
+ }
+});
+
+Template.channelSettingsInfo.onCreated(function() {
+ this.room = ChatRoom.findOne(this.data && this.data.rid);
+});
+
+Template.channelSettingsInfo.helpers({
+ ...common,
+ channelName() {
+ return `@${ Template.instance().room.name }`;
+ },
+ archived() {
+ return Template.instance().room.archived;
+ },
+ unscape(value) {
+ return s.unescapeHTML(value);
+ },
+ channelSettings() {
+ return RocketChat.ChannelSettings.getOptions(Template.currentData(), 'room');
+ },
+ name() {
+ return Template.instance().room.name;
+ },
+ description() {
+ return Template.instance().room.description;
+ },
+ announcement() {
+ return Template.instance().room.announcement;
+ },
+ topic() {
+ return Template.instance().room.topic;
+ },
+ users() {
+ return Template.instance().room.usernames;
+ },
+
+ channelIcon() {
+ const roomType = Template.instance().room.t;
+ switch (roomType) {
+ case 'd':
+ return 'at';
+ case 'p':
+ return 'lock';
+ case 'c':
+ return 'hashtag';
+ case 'l':
+ return 'livechat';
+ default:
+ return null;
+ }
+ }
+});
diff --git a/packages/rocketchat-channel-settings/package.js b/packages/rocketchat-channel-settings/package.js
index 3f42e734af3ff..3f35a159bb407 100644
--- a/packages/rocketchat-channel-settings/package.js
+++ b/packages/rocketchat-channel-settings/package.js
@@ -7,36 +7,35 @@ Package.describe({
Package.onUse(function(api) {
api.use([
- 'coffeescript',
'ecmascript',
'reactive-var',
'tracker',
'templating',
- 'less',
'rocketchat:lib'
]);
api.addFiles([
- 'client/lib/ChannelSettings.coffee',
- 'client/startup/messageTypes.coffee',
- 'client/startup/tabBar.coffee',
+ 'client/lib/ChannelSettings.js',
+ 'client/startup/messageTypes.js',
+ 'client/startup/tabBar.js',
'client/startup/trackSettingsChange.js',
'client/views/channelSettings.html',
- 'client/views/channelSettings.coffee',
- 'client/stylesheets/channel-settings.less'
+ 'client/views/channelSettings.js',
+ 'client/stylesheets/channel-settings.css'
], 'client');
api.addFiles([
'server/functions/saveReactWhenReadOnly.js',
- 'server/functions/saveRoomType.coffee',
- 'server/functions/saveRoomTopic.coffee',
- 'server/functions/saveRoomName.coffee',
- 'server/functions/saveRoomReadOnly.coffee',
- 'server/functions/saveRoomDescription.coffee',
- 'server/functions/saveRoomSystemMessages.coffee',
- 'server/methods/saveRoomSettings.coffee',
- 'server/models/Messages.coffee',
- 'server/models/Rooms.coffee',
+ 'server/functions/saveRoomType.js',
+ 'server/functions/saveRoomTopic.js',
+ 'server/functions/saveRoomAnnouncement.js',
+ 'server/functions/saveRoomName.js',
+ 'server/functions/saveRoomReadOnly.js',
+ 'server/functions/saveRoomDescription.js',
+ 'server/functions/saveRoomSystemMessages.js',
+ 'server/methods/saveRoomSettings.js',
+ 'server/models/Messages.js',
+ 'server/models/Rooms.js',
'server/startup.js'
], 'server');
});
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomAnnouncement.js b/packages/rocketchat-channel-settings/server/functions/saveRoomAnnouncement.js
new file mode 100644
index 0000000000000..0ddf386030d35
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomAnnouncement.js
@@ -0,0 +1,15 @@
+import s from 'underscore.string';
+
+RocketChat.saveRoomAnnouncement = function(rid, roomAnnouncement, user, sendMessage=true) {
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomAnnouncement' });
+ }
+
+ roomAnnouncement = s.escapeHTML(roomAnnouncement);
+ const updated = RocketChat.models.Rooms.setAnnouncementById(rid, roomAnnouncement);
+ if (updated && sendMessage) {
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_announcement', rid, roomAnnouncement, user);
+ }
+
+ return updated;
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.coffee
deleted file mode 100644
index ef63d1715a950..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-RocketChat.saveRoomDescription = (rid, roomDescription, user) ->
- unless Match.test rid, String
- throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomDescription' }
-
- roomDescription = s.escapeHTML(roomDescription)
-
- update = RocketChat.models.Rooms.setDescriptionById rid, roomDescription
-
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_description', rid, roomDescription, user
-
- return update
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.js b/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.js
new file mode 100644
index 0000000000000..cd0bd0bf12441
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomDescription.js
@@ -0,0 +1,14 @@
+import s from 'underscore.string';
+
+RocketChat.saveRoomDescription = function(rid, roomDescription, user) {
+
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', {
+ 'function': 'RocketChat.saveRoomDescription'
+ });
+ }
+ const escapedRoomDescription = s.escapeHTML(roomDescription);
+ const update = RocketChat.models.Rooms.setDescriptionById(rid, escapedRoomDescription);
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_description', rid, escapedRoomDescription, user);
+ return update;
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee
deleted file mode 100644
index 6af72ac445dde..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee
+++ /dev/null
@@ -1,29 +0,0 @@
-RocketChat.saveRoomName = (rid, name, user, sendMessage=true) ->
- room = RocketChat.models.Rooms.findOneById rid
-
- if room.t not in ['c', 'p']
- throw new Meteor.Error 'error-not-allowed', 'Not allowed', { function: 'RocketChat.saveRoomName' }
-
- try
- nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$'
- catch
- nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$'
-
- if not nameValidation.test name
- throw new Meteor.Error 'error-invalid-room-name', name + ' is not a valid room name. Use only letters, numbers, hyphens and underscores', { function: 'RocketChat.saveRoomName', room_name: name }
-
-
- # name = _.slugify name
-
- if name is room.name
- return
-
- # avoid duplicate names
- if RocketChat.models.Rooms.findOneByName name
- throw new Meteor.Error 'error-duplicate-channel-name', 'A channel with name \'' + name + '\' exists', { function: 'RocketChat.saveRoomName', channel_name: name }
-
- update = RocketChat.models.Rooms.setNameById(rid, name) and RocketChat.models.Subscriptions.updateNameAndAlertByRoomId(rid, name)
- if update and sendMessage
- RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser rid, name, user
-
- return name
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomName.js b/packages/rocketchat-channel-settings/server/functions/saveRoomName.js
new file mode 100644
index 0000000000000..9d0210f2ec24c
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomName.js
@@ -0,0 +1,21 @@
+
+RocketChat.saveRoomName = function(rid, serverId, displayName, user, sendMessage = true) {
+ const room = RocketChat.models.Rooms.findOneById(rid);
+ if (RocketChat.roomTypes.roomTypes[room.t].preventRenaming()) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', {
+ 'function': 'RocketChat.saveRoomdisplayName'
+ });
+ }
+ if (displayName === room.name) {
+ return;
+ }
+
+ const slugifiedRoomName = RocketChat.getValidRoomName(displayName, serverId, rid);
+
+ const update = RocketChat.models.Rooms.setNameById(rid, slugifiedRoomName, displayName) && RocketChat.models.Subscriptions.updateNameAndAlertByRoomId(rid, slugifiedRoomName, displayName);
+
+ if (update && sendMessage) {
+ RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(rid, displayName, user);
+ }
+ return displayName;
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.coffee
deleted file mode 100644
index 08f3ae7af69d5..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-RocketChat.saveRoomReadOnly = (rid, readOnly, user) ->
- unless Match.test rid, String
- throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomReadOnly' }
-
- update = RocketChat.models.Rooms.setReadOnlyById rid, readOnly
-
- return update
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.js b/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.js
new file mode 100644
index 0000000000000..35d8ccbd138d9
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.js
@@ -0,0 +1,8 @@
+RocketChat.saveRoomReadOnly = function(rid, readOnly) {
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', {
+ 'function': 'RocketChat.saveRoomReadOnly'
+ });
+ }
+ return RocketChat.models.Rooms.setReadOnlyById(rid, readOnly);
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.coffee
deleted file mode 100644
index 3b27991e09a19..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-RocketChat.saveRoomSystemMessages = (rid, systemMessages, user) ->
- unless Match.test rid, String
- throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomSystemMessages' }
-
- update = RocketChat.models.Rooms.setSystemMessagesById rid, systemMessages
-
- return update
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.js b/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.js
new file mode 100644
index 0000000000000..930531793fc83
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.js
@@ -0,0 +1,8 @@
+RocketChat.saveRoomSystemMessages = function(rid, systemMessages) {
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', {
+ 'function': 'RocketChat.saveRoomSystemMessages'
+ });
+ }
+ return RocketChat.models.Rooms.setSystemMessagesById(rid, systemMessages);
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.coffee
deleted file mode 100644
index ec27c79d4f78e..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.coffee
+++ /dev/null
@@ -1,12 +0,0 @@
-RocketChat.saveRoomTopic = (rid, roomTopic, user, sendMessage=true) ->
- unless Match.test rid, String
- throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomTopic' }
-
- roomTopic = s.escapeHTML(roomTopic)
-
- update = RocketChat.models.Rooms.setTopicById(rid, roomTopic)
-
- if update and sendMessage
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', rid, roomTopic, user
-
- return update
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.js b/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.js
new file mode 100644
index 0000000000000..0ba1b4894e519
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomTopic.js
@@ -0,0 +1,15 @@
+import s from 'underscore.string';
+
+RocketChat.saveRoomTopic = function(rid, roomTopic, user, sendMessage = true) {
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', {
+ 'function': 'RocketChat.saveRoomTopic'
+ });
+ }
+ roomTopic = s.escapeHTML(roomTopic);
+ const update = RocketChat.models.Rooms.setTopicById(rid, roomTopic);
+ if (update && sendMessage) {
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', rid, roomTopic, user);
+ }
+ return update;
+};
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomType.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomType.coffee
deleted file mode 100644
index 51c78b8282b08..0000000000000
--- a/packages/rocketchat-channel-settings/server/functions/saveRoomType.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-RocketChat.saveRoomType = (rid, roomType, user, sendMessage=true) ->
- unless Match.test rid, String
- throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomType' }
-
- if roomType not in ['c', 'p']
- throw new Meteor.Error 'error-invalid-room-type', 'error-invalid-room-type', { type: roomType }
-
- result = RocketChat.models.Rooms.setTypeById(rid, roomType) and RocketChat.models.Subscriptions.updateTypeByRoomId(rid, roomType)
-
- if result and sendMessage
- if roomType is 'c'
- message = TAPi18n.__('Channel', { lng: user?.language || RocketChat.settings.get('language') || 'en' })
- else
- message = TAPi18n.__('Private_Group', { lng: user?.language || RocketChat.settings.get('language') || 'en' })
-
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_privacy', rid, message, user
-
- return result
diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomType.js b/packages/rocketchat-channel-settings/server/functions/saveRoomType.js
new file mode 100644
index 0000000000000..18a03ec80106a
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveRoomType.js
@@ -0,0 +1,41 @@
+
+RocketChat.saveRoomType = function(rid, roomType, user, sendMessage = true) {
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('invalid-room', 'Invalid room', {
+ 'function': 'RocketChat.saveRoomType'
+ });
+ }
+ if (roomType !== 'c' && roomType !== 'p') {
+ throw new Meteor.Error('error-invalid-room-type', 'error-invalid-room-type', {
+ 'function': 'RocketChat.saveRoomType',
+ type: roomType
+ });
+ }
+ const room = RocketChat.models.Rooms.findOneById(rid);
+ if (room == null) {
+ throw new Meteor.Error('error-invalid-room', 'error-invalid-room', {
+ 'function': 'RocketChat.saveRoomType',
+ _id: rid
+ });
+ }
+ if (room.t === 'd') {
+ throw new Meteor.Error('error-direct-room', 'Can\'t change type of direct rooms', {
+ 'function': 'RocketChat.saveRoomType'
+ });
+ }
+ const result = RocketChat.models.Rooms.setTypeById(rid, roomType) && RocketChat.models.Subscriptions.updateTypeByRoomId(rid, roomType);
+ if (result && sendMessage) {
+ let message;
+ if (roomType === 'c') {
+ message = TAPi18n.__('Channel', {
+ lng: user && user.language || RocketChat.settings.get('language') || 'en'
+ });
+ } else {
+ message = TAPi18n.__('Private_Group', {
+ lng: user && user.language || RocketChat.settings.get('language') || 'en'
+ });
+ }
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_privacy', rid, message, user);
+ }
+ return result;
+};
diff --git a/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee b/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
deleted file mode 100644
index f51a06949452d..0000000000000
--- a/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
+++ /dev/null
@@ -1,52 +0,0 @@
-Meteor.methods
- saveRoomSettings: (rid, setting, value) ->
- if not Meteor.userId()
- throw new Meteor.Error('error-invalid-user', "Invalid user", { function: 'RocketChat.saveRoomName' })
-
- unless Match.test rid, String
- throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'saveRoomSettings' }
-
- if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode']
- throw new Meteor.Error 'error-invalid-settings', 'Invalid settings provided', { method: 'saveRoomSettings' }
-
- unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)
- throw new Meteor.Error 'error-action-not-allowed', 'Editing room is not allowed', { method: 'saveRoomSettings', action: 'Editing_room' }
-
- if setting is 'default' and not RocketChat.authz.hasPermission(@userId, 'view-room-administration')
- throw new Meteor.Error 'error-action-not-allowed', 'Viewing room administration is not allowed', { method: 'saveRoomSettings', action: 'Viewing_room_administration' }
-
- room = RocketChat.models.Rooms.findOneById rid
- if room?
- if setting is 'roomType' and value isnt room.t and value is 'c' and not RocketChat.authz.hasPermission(@userId, 'create-c')
- throw new Meteor.Error 'error-action-not-allowed', 'Changing a private group to a public channel is not allowed', { method: 'saveRoomSettings', action: 'Change_Room_Type' }
-
- if setting is 'roomType' and value isnt room.t and value is 'p' and not RocketChat.authz.hasPermission(@userId, 'create-p')
- throw new Meteor.Error 'error-action-not-allowed', 'Changing a public channel to a private room is not allowed', { method: 'saveRoomSettings', action: 'Change_Room_Type' }
-
- switch setting
- when 'roomName'
- name = RocketChat.saveRoomName rid, value, Meteor.user()
- when 'roomTopic'
- if value isnt room.topic
- RocketChat.saveRoomTopic(rid, value, Meteor.user())
- when 'roomDescription'
- if value isnt room.description
- RocketChat.saveRoomDescription rid, value, Meteor.user()
- when 'roomType'
- if value isnt room.t
- RocketChat.saveRoomType(rid, value, Meteor.user())
- when 'readOnly'
- if value isnt room.ro
- RocketChat.saveRoomReadOnly rid, value, Meteor.user()
- when 'reactWhenReadOnly'
- if value isnt room.reactWhenReadOnly
- RocketChat.saveReactWhenReadOnly rid, value, Meteor.user()
- when 'systemMessages'
- if value isnt room.sysMes
- RocketChat.saveRoomSystemMessages rid, value, Meteor.user()
- when 'joinCode'
- RocketChat.models.Rooms.setJoinCodeById rid, String(value)
- when 'default'
- RocketChat.models.Rooms.saveDefaultById rid, value
-
- return { result: true, rid: room._id }
diff --git a/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.js b/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.js
new file mode 100644
index 0000000000000..ea80b3d63844f
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.js
@@ -0,0 +1,133 @@
+const fields = ['roomName', 'roomTopic', 'roomAnnouncement', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions'];
+Meteor.methods({
+ saveRoomSettings(rid, settings, value, serverId) {
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ 'function': 'RocketChat.saveRoomName'
+ });
+ }
+ if (!Match.test(rid, String)) {
+ throw new Meteor.Error('error-invalid-room', 'Invalid room', {
+ method: 'saveRoomSettings'
+ });
+ }
+
+ if (typeof settings !== 'object') {
+ settings = {
+ [settings] : value
+ };
+ }
+
+ if (!Object.keys(settings).every(key => fields.includes(key))) {
+ throw new Meteor.Error('error-invalid-settings', 'Invalid settings provided', {
+ method: 'saveRoomSettings'
+ });
+ }
+
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)) {
+ throw new Meteor.Error('error-action-not-allowed', 'Editing room is not allowed', {
+ method: 'saveRoomSettings',
+ action: 'Editing_room'
+ });
+ }
+
+
+ const room = RocketChat.models.Rooms.findOneById(rid);
+ if (!room) {
+ throw new Meteor.Error('error-invalid-room', 'Invalid room', {
+ method: 'saveRoomSettings'
+ });
+ }
+
+ const user = Meteor.user();
+
+ Object.keys(settings).forEach(setting => {
+ const value = settings[setting];
+ if (settings === 'default' && !RocketChat.authz.hasPermission(this.userId, 'view-room-administration')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Viewing room administration is not allowed', {
+ method: 'saveRoomSettings',
+ action: 'Viewing_room_administration'
+ });
+ }
+ if (setting === 'roomType' && value !== room.t && value === 'c' && !RocketChat.authz.hasPermission(this.userId, 'create-c')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Changing a private group to a public channel is not allowed', {
+ method: 'saveRoomSettings',
+ action: 'Change_Room_Type'
+ });
+ }
+ if (setting === 'roomType' && value !== room.t && value === 'p' && !RocketChat.authz.hasPermission(this.userId, 'create-p')) {
+ throw new Meteor.Error('error-action-not-allowed', 'Changing a public channel to a private room is not allowed', {
+ method: 'saveRoomSettings',
+ action: 'Change_Room_Type'
+ });
+ }
+ });
+
+ Object.keys(settings).forEach(setting => {
+ const value = settings[setting];
+ switch (setting) {
+ case 'roomName':
+ RocketChat.saveRoomName(rid, serverId, value, user);
+ break;
+ case 'roomTopic':
+ if (value !== room.topic) {
+ RocketChat.saveRoomTopic(rid, value, user);
+ }
+ break;
+ case 'roomAnnouncement':
+ if (value !== room.announcement) {
+ RocketChat.saveRoomAnnouncement(rid, value, user);
+ }
+ break;
+ case 'roomDescription':
+ if (value !== room.description) {
+ RocketChat.saveRoomDescription(rid, value, user);
+ }
+ break;
+ case 'roomType':
+ if (value !== room.t) {
+ RocketChat.saveRoomType(rid, value, user);
+ }
+ break;
+ case 'tokenpass':
+ check(value, {
+ require: String,
+ tokens: [{
+ token: String,
+ balance: String
+ }]
+ });
+ RocketChat.saveRoomTokenpass(rid, value);
+ break;
+ case 'streamingOptions':
+ RocketChat.saveStreamingOptions(rid, value);
+ break;
+ case 'readOnly':
+ if (value !== room.ro) {
+ RocketChat.saveRoomReadOnly(rid, value, user);
+ }
+ break;
+ case 'reactWhenReadOnly':
+ if (value !== room.reactWhenReadOnly) {
+ RocketChat.saveReactWhenReadOnly(rid, value, user);
+ }
+ break;
+ case 'systemMessages':
+ if (value !== room.sysMes) {
+ RocketChat.saveRoomSystemMessages(rid, value, user);
+ }
+ break;
+ case 'joinCode':
+ RocketChat.models.Rooms.setJoinCodeById(rid, String(value));
+ break;
+ case 'default':
+ RocketChat.models.Rooms.saveDefaultById(rid, value);
+ }
+ });
+
+ return {
+ result: true,
+ rid: room._id
+ };
+ }
+});
diff --git a/packages/rocketchat-channel-settings/server/models/Messages.coffee b/packages/rocketchat-channel-settings/server/models/Messages.coffee
deleted file mode 100644
index 9a72fcd32bb0d..0000000000000
--- a/packages/rocketchat-channel-settings/server/models/Messages.coffee
+++ /dev/null
@@ -1,5 +0,0 @@
-RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser = (type, roomId, message, user, extraData) ->
- return @createWithTypeRoomIdMessageAndUser type, roomId, message, user, extraData
-
-RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser = (roomId, roomName, user, extraData) ->
- return @createWithTypeRoomIdMessageAndUser 'r', roomId, roomName, user, extraData
diff --git a/packages/rocketchat-channel-settings/server/models/Messages.js b/packages/rocketchat-channel-settings/server/models/Messages.js
new file mode 100644
index 0000000000000..6f4e473375b3f
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/models/Messages.js
@@ -0,0 +1,7 @@
+RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser = function(type, roomId, message, user, extraData) {
+ return this.createWithTypeRoomIdMessageAndUser(type, roomId, message, user, extraData);
+};
+
+RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser = function(roomId, roomName, user, extraData) {
+ return this.createWithTypeRoomIdMessageAndUser('r', roomId, roomName, user, extraData);
+};
diff --git a/packages/rocketchat-channel-settings/server/models/Rooms.coffee b/packages/rocketchat-channel-settings/server/models/Rooms.coffee
deleted file mode 100644
index d277959fe7546..0000000000000
--- a/packages/rocketchat-channel-settings/server/models/Rooms.coffee
+++ /dev/null
@@ -1,55 +0,0 @@
-RocketChat.models.Rooms.setDescriptionById = (_id, description) ->
- query =
- _id: _id
-
- update =
- $set:
- description: description
-
- return @update query, update
-
-RocketChat.models.Rooms.setReadOnlyById = (_id, readOnly) ->
- query =
- _id: _id
-
- update =
- $set:
- ro: readOnly
-
- if readOnly
- # we want to mute all users without the post-readonly permission
-
- RocketChat.models.Subscriptions.findByRoomId(_id).forEach (subscription) ->
- if not subscription._user?
- return
-
- user = subscription._user
- if RocketChat.authz.hasPermission(user._id, 'post-readonly') is false
- # create a new array if necessary
- update.$set.muted = [] if !update.$set.muted
- update.$set.muted.push user.username
- else
- # remove the muted user array
- update.$unset = {muted: ""}
-
- return @update query, update
-
-RocketChat.models.Rooms.setAllowReactingWhenReadOnlyById = (_id, allowReacting) ->
- query =
- _id: _id
-
- update =
- $set:
- reactWhenReadOnly: allowReacting
-
- return @update query, update
-
-RocketChat.models.Rooms.setSystemMessagesById = (_id, systemMessages) ->
- query =
- _id: _id
-
- update =
- $set:
- sysMes: systemMessages
-
- return @update query, update
diff --git a/packages/rocketchat-channel-settings/server/models/Rooms.js b/packages/rocketchat-channel-settings/server/models/Rooms.js
new file mode 100644
index 0000000000000..07e81e5ff17fe
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/models/Rooms.js
@@ -0,0 +1,65 @@
+RocketChat.models.Rooms.setDescriptionById = function(_id, description) {
+ const query = {
+ _id
+ };
+ const update = {
+ $set: {
+ description
+ }
+ };
+ return this.update(query, update);
+};
+
+RocketChat.models.Rooms.setReadOnlyById = function(_id, readOnly) {
+ const query = {
+ _id
+ };
+ const update = {
+ $set: {
+ ro: readOnly
+ }
+ };
+ if (readOnly) {
+ RocketChat.models.Subscriptions.findByRoomId(_id).forEach(function(subscription) {
+ if (subscription._user == null) {
+ return;
+ }
+ const user = subscription._user;
+ if (RocketChat.authz.hasPermission(user._id, 'post-readonly') === false) {
+ if (!update.$set.muted) {
+ update.$set.muted = [];
+ }
+ return update.$set.muted.push(user.username);
+ }
+ });
+ } else {
+ update.$unset = {
+ muted: ''
+ };
+ }
+ return this.update(query, update);
+};
+
+RocketChat.models.Rooms.setAllowReactingWhenReadOnlyById = function(_id, allowReacting) {
+ const query = {
+ _id
+ };
+ const update = {
+ $set: {
+ reactWhenReadOnly: allowReacting
+ }
+ };
+ return this.update(query, update);
+};
+
+RocketChat.models.Rooms.setSystemMessagesById = function(_id, systemMessages) {
+ const query = {
+ _id
+ };
+ const update = {
+ $set: {
+ sysMes: systemMessages
+ }
+ };
+ return this.update(query, update);
+};
diff --git a/packages/rocketchat-channel-settings/server/startup.js b/packages/rocketchat-channel-settings/server/startup.js
index b63c0fabf67fc..2587779ad769c 100644
--- a/packages/rocketchat-channel-settings/server/startup.js
+++ b/packages/rocketchat-channel-settings/server/startup.js
@@ -1,5 +1,5 @@
Meteor.startup(function() {
- RocketChat.models.Permissions.upsert('post-readonly', {$set: { roles: ['admin', 'owner', 'moderator'] } });
- RocketChat.models.Permissions.upsert('set-readonly', {$set: { roles: ['admin', 'owner'] } });
- RocketChat.models.Permissions.upsert('set-react-when-readonly', {$set: { roles: ['admin', 'owner'] }});
+ RocketChat.models.Permissions.upsert('post-readonly', {$setOnInsert: { roles: ['admin', 'owner', 'moderator'] } });
+ RocketChat.models.Permissions.upsert('set-readonly', {$setOnInsert: { roles: ['admin', 'owner'] } });
+ RocketChat.models.Permissions.upsert('set-react-when-readonly', {$setOnInsert: { roles: ['admin', 'owner'] }});
});
diff --git a/packages/rocketchat-chatops/client/startup.coffee b/packages/rocketchat-chatops/client/startup.coffee
deleted file mode 100644
index 7cf93fd6620ec..0000000000000
--- a/packages/rocketchat-chatops/client/startup.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.startup ->
- console.log('startup hooked')
- GoogleMaps.load()
diff --git a/packages/rocketchat-chatops/client/tabBar.coffee b/packages/rocketchat-chatops/client/tabBar.coffee
deleted file mode 100644
index 3a85a7d535183..0000000000000
--- a/packages/rocketchat-chatops/client/tabBar.coffee
+++ /dev/null
@@ -1,24 +0,0 @@
-Meteor.startup ->
- Tracker.autorun ->
- if RocketChat.settings.get('Chatops_Enabled')
- console.log 'Adding chatops to tabbar'
- RocketChat.TabBar.addButton
- groups: ['channel', 'group', 'direct']
- id: 'chatops-button2'
- i18nTitle: 'rocketchat-chatops:Chatops_Title'
- icon: 'icon-hubot'
- template: 'chatops-dynamicUI'
- order: 4
-
- console.log 'Adding chatops to tabbar'
- RocketChat.TabBar.addButton
- groups: ['channel', 'group', 'direct']
- id: 'chatops-button3'
- i18nTitle: 'rocketchat-chatops:Chatops_Title'
- icon: 'icon-inbox'
- template: 'chatops_droneflight'
- width: 675
- order: 5
- else
- RocketChat.TabBar.removeButton 'chatops-button2'
- RocketChat.TabBar.removeButton 'chatops-button3'
diff --git a/packages/rocketchat-chatops/client/views/chatops.coffee b/packages/rocketchat-chatops/client/views/chatops.coffee
deleted file mode 100644
index b7508fc8d86be..0000000000000
--- a/packages/rocketchat-chatops/client/views/chatops.coffee
+++ /dev/null
@@ -1 +0,0 @@
-Template.chatops.helpers
diff --git a/packages/rocketchat-chatops/client/views/chatops.html b/packages/rocketchat-chatops/client/views/chatops.html
deleted file mode 100644
index d1a90aaad0b71..0000000000000
--- a/packages/rocketchat-chatops/client/views/chatops.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- {{_ "Loading..."}}
-
diff --git a/packages/rocketchat-chatops/client/views/codemirror.coffee b/packages/rocketchat-chatops/client/views/codemirror.coffee
deleted file mode 100644
index 9ebc0f95ed6c4..0000000000000
--- a/packages/rocketchat-chatops/client/views/codemirror.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-Template.chatops_codemirror.helpers
- editorOptions: ->
- return {lineNumbers: true, mode:"javascript"}
-
- editorCode: ->
- return "# This is a full featured, syntax highlighted editor\n# BOTs can fetch, edit, commit, and save source code\n#\n\nvar express = require('express');\nvar app = express();\n// respond with \"hello world\" when a GET request is made to the homepage
- +\napp.get('/', function(req, res) {\nres.send('hello world');\n});";
diff --git a/packages/rocketchat-chatops/client/views/codemirror.html b/packages/rocketchat-chatops/client/views/codemirror.html
deleted file mode 100644
index 6333d8416805f..0000000000000
--- a/packages/rocketchat-chatops/client/views/codemirror.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
- {{> CodeMirror id="flyineditor" name="flyineditor" options=editorOptions code=editorCode }}
-
-
- {{_ "Save"}}
- {{_ "Commit"}}
- {{_ "Cancel"}}
-
-
-
-
-
diff --git a/packages/rocketchat-chatops/client/views/droneflight.coffee b/packages/rocketchat-chatops/client/views/droneflight.coffee
deleted file mode 100644
index de3c9feb04e30..0000000000000
--- a/packages/rocketchat-chatops/client/views/droneflight.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-
-Template.chatops_droneflight.helpers
- flightMapOptions: ->
- if GoogleMaps.loaded()
- console.log('helper run')
- return {center: new google.maps.LatLng(35.6609285,-78.8456125), zoom: 17}
-
-
-Template.chatops_droneflight.onCreated () ->
- GoogleMaps.ready 'flightMap', (map) ->
- console.log('ready')
- redicon = { path: google.maps.SymbolPath.CIRCLE, fillColor: "red", fillOpacity: 0.8, strokeColor: "gold", strokeWeight: 2, scale: 10}
- greenicon = {path: google.maps.SymbolPath.CIRCLE, fillColor: "green", fillOpacity: 0.8, strokeColor: "gold", strokeWeight: 2, scale: 10}
-
- marker = new google.maps.Marker({position: new google.maps.LatLng(35.661848,-78.843165), icon: redicon, map: map.instance})
- marker.setLabel('1')
- marker2 = new google.maps.Marker({position: new google.maps.LatLng(35.660537,-78.846959), icon: greenicon, map: map.instance})
- marker2.setLabel('2')
diff --git a/packages/rocketchat-chatops/client/views/droneflight.html b/packages/rocketchat-chatops/client/views/droneflight.html
deleted file mode 100644
index 9f6957ef90f57..0000000000000
--- a/packages/rocketchat-chatops/client/views/droneflight.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
Drone 1: mission A3 waypoint 7 fuel 30%
-
Drone 2: mission A7 waypoint 2 fuel 100%
-
-
-
-
- {{> googleMap name="flightMap" options=flightMapOptions }}
-
-
-
- {{_ "Return to base"}}
- {{_ "Cancel"}}
-
-
-
-
-
diff --git a/packages/rocketchat-chatops/client/views/dynamicUI.html b/packages/rocketchat-chatops/client/views/dynamicUI.html
deleted file mode 100644
index af941df7bfd35..0000000000000
--- a/packages/rocketchat-chatops/client/views/dynamicUI.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
Bot Controlled UI
-
- UI is dynamically generated based on DSL message from BOT. DSL also specifies command sent back.
-
-
-
-
-
-
-
-
-
-
- {{_ "Get Gist"}}
-
-
-
- {{_ "Show history"}}
-
-
- {{_ "Blame"}}
-
-
-
-
diff --git a/packages/rocketchat-chatops/client/views/stylesheets/chatops.css b/packages/rocketchat-chatops/client/views/stylesheets/chatops.css
deleted file mode 100644
index 5c439017ffa2e..0000000000000
--- a/packages/rocketchat-chatops/client/views/stylesheets/chatops.css
+++ /dev/null
@@ -1,15 +0,0 @@
-
-.map-container {
- width: 670px;
- max-width: 100%;
- height: 500px;
- padding: 5px, 5px, 5px 5px;
-}
-
-.red {
- color: red;
-}
-
-.green {
- color: green;
-}
\ No newline at end of file
diff --git a/packages/rocketchat-chatops/package.js b/packages/rocketchat-chatops/package.js
deleted file mode 100644
index 3f2bcb83f655f..0000000000000
--- a/packages/rocketchat-chatops/package.js
+++ /dev/null
@@ -1,34 +0,0 @@
-Package.describe({
- name: 'rocketchat:chatops',
- version: '0.0.1',
- summary: 'Chatops Panel',
- git: ''
-});
-
-Package.onUse(function(api) {
- api.use([
- 'coffeescript',
- 'ecmascript',
- 'rocketchat:lib',
- 'dburles:google-maps@1.1.5'
- ]);
-
- api.use('templating', 'client');
-
- api.addFiles([
- 'client/startup.coffee',
- 'client/tabBar.coffee',
- 'client/views/chatops.html',
- 'client/views/chatops.coffee',
- 'client/views/codemirror.html',
- 'client/views/codemirror.coffee',
- 'client/views/droneflight.html',
- 'client/views/droneflight.coffee',
- 'client/views/dynamicUI.html',
- 'client/views/stylesheets/chatops.css'
- ], 'client');
-
- api.addFiles([
- 'server/settings.coffee'
- ], 'server');
-});
diff --git a/packages/rocketchat-chatops/server/settings.coffee b/packages/rocketchat-chatops/server/settings.coffee
deleted file mode 100644
index 2753900494da9..0000000000000
--- a/packages/rocketchat-chatops/server/settings.coffee
+++ /dev/null
@@ -1,4 +0,0 @@
-Meteor.startup ->
- RocketChat.settings.addGroup 'Chatops'
- RocketChat.settings.add 'Chatops_Enabled', false, { type: 'boolean', group: 'Chatops', public: true }
- RocketChat.settings.add 'Chatops_Username', false, { type: 'string', group: 'Chatops', public: true }
diff --git a/packages/rocketchat-colors/client.js b/packages/rocketchat-colors/client.js
deleted file mode 100644
index ee2eeef06b52c..0000000000000
--- a/packages/rocketchat-colors/client.js
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// HexColorPreview is a named function that will process Colors
-// @param {Object} message - The message object
-//
-
-function HexColorPreview(message) {
- var msg;
- if (_.trim(message.html) && RocketChat.settings.get('HexColorPreview_Enabled')) {
- msg = message.html;
- msg = msg.replace(/(?:^|\s|\n)(#[A-Fa-f0-9]{3}([A-Fa-f0-9]{3})?)\b/g, function(match, completeColor) {
- return match.replace(completeColor, '
' + (completeColor.toUpperCase()) + '
');
- });
- message.html = msg;
- }
- return message;
-}
-
-RocketChat.callbacks.add('renderMessage', HexColorPreview, RocketChat.callbacks.priority.MEDIUM);
diff --git a/packages/rocketchat-colors/client/client.js b/packages/rocketchat-colors/client/client.js
new file mode 100644
index 0000000000000..608599ecf771b
--- /dev/null
+++ b/packages/rocketchat-colors/client/client.js
@@ -0,0 +1,20 @@
+import s from 'underscore.string';
+
+//
+// HexColorPreview is a named function that will process Colors
+// @param {Object} message - The message object
+//
+
+function HexColorPreview(message) {
+ let msg;
+ if (s.trim(message.html) && RocketChat.settings.get('HexColorPreview_Enabled')) {
+ msg = message.html;
+ msg = msg.replace(/(?:^|\s|\n)(#[A-Fa-f0-9]{3}([A-Fa-f0-9]{3})?)\b/g, function(match, completeColor) {
+ return match.replace(completeColor, `
${ completeColor.toUpperCase() }
`);
+ });
+ message.html = msg;
+ }
+ return message;
+}
+
+RocketChat.callbacks.add('renderMessage', HexColorPreview, RocketChat.callbacks.priority.MEDIUM);
diff --git a/packages/rocketchat-colors/style.css b/packages/rocketchat-colors/client/style.css
similarity index 84%
rename from packages/rocketchat-colors/style.css
rename to packages/rocketchat-colors/client/style.css
index 303346a873e6c..a67db45d28154 100644
--- a/packages/rocketchat-colors/style.css
+++ b/packages/rocketchat-colors/client/style.css
@@ -1,16 +1,20 @@
.message-color {
display: inline-block;
+
font-weight: 100;
}
.message-color-sample {
+ position: relative;
+ top: 2px;
+
+ display: inline-block;
+
width: 14px;
height: 14px;
- display: inline-block;
- border-radius: 3px;
margin-right: 3px;
margin-left: 2px;
- border: 1px solid rgba(0, 0, 0, .2);
- position: relative;
- top: 2px;
+
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 3px;
}
diff --git a/packages/rocketchat-colors/package.js b/packages/rocketchat-colors/package.js
index 4722436cb39ae..2c15bd0739512 100644
--- a/packages/rocketchat-colors/package.js
+++ b/packages/rocketchat-colors/package.js
@@ -6,10 +6,10 @@ Package.describe({
});
Package.onUse(function(api) {
- api.use([
- 'rocketchat:lib'
- ]);
- api.addFiles('client.js', ['client']);
- api.addFiles('style.css', ['client']);
- api.addFiles('settings.js', ['server']);
+ api.use('rocketchat:lib');
+ api.use('ecmascript');
+
+ api.addFiles('client/client.js', 'client');
+ api.addFiles('client/style.css', 'client');
+ api.addFiles('server/settings.js', 'server');
});
diff --git a/packages/rocketchat-colors/server/settings.js b/packages/rocketchat-colors/server/settings.js
new file mode 100644
index 0000000000000..cd20585ab3a93
--- /dev/null
+++ b/packages/rocketchat-colors/server/settings.js
@@ -0,0 +1,7 @@
+RocketChat.settings.add('HexColorPreview_Enabled', true, {
+ type: 'boolean',
+ i18nLabel: 'Enabled',
+ group: 'Message',
+ section: 'Hex_Color_Preview',
+ public: true
+});
diff --git a/packages/rocketchat-colors/settings.js b/packages/rocketchat-colors/settings.js
deleted file mode 100644
index fb27f64cb51a5..0000000000000
--- a/packages/rocketchat-colors/settings.js
+++ /dev/null
@@ -1,7 +0,0 @@
-RocketChat.settings.add('HexColorPreview_Enabled', true, {
- type: 'boolean',
- i18nLabel: 'Enabled',
- group: 'Message',
- section: 'Hex Color Preview',
- public: true
-});
diff --git a/packages/rocketchat-cors/common.js b/packages/rocketchat-cors/common.js
index 7f79abf550f26..3c90f3d1896c1 100644
--- a/packages/rocketchat-cors/common.js
+++ b/packages/rocketchat-cors/common.js
@@ -1,5 +1,5 @@
Meteor.startup(function() {
- return RocketChat.settings.onload('Force_SSL', function(key, value) {
- return Meteor.absoluteUrl.defaultOptions.secure = value;
+ RocketChat.settings.onload('Force_SSL', function(key, value) {
+ Meteor.absoluteUrl.defaultOptions.secure = value;
});
});
diff --git a/packages/rocketchat-cors/cors.js b/packages/rocketchat-cors/cors.js
index b35d22e171724..5e45911acc9bf 100644
--- a/packages/rocketchat-cors/cors.js
+++ b/packages/rocketchat-cors/cors.js
@@ -1,8 +1,21 @@
/* globals WebAppInternals */
+import _ from 'underscore';
import url from 'url';
-WebApp.rawConnectHandlers.use(function(req, res, next) {
+import { Mongo } from 'meteor/mongo';
+import tls from 'tls';
+// FIX For TLS error see more here https://github.com/RocketChat/Rocket.Chat/issues/9316
+// TODO: Remove after NodeJS fix it, more information https://github.com/nodejs/node/issues/16196 https://github.com/nodejs/node/pull/16853
+tls.DEFAULT_ECDH_CURVE = 'auto';
+
+// Revert change from Meteor 1.6.1 who set ignoreUndefined: true
+// more information https://github.com/meteor/meteor/pull/9444
+Mongo.setConnectionOptions({
+ ignoreUndefined: false
+});
+
+WebApp.rawConnectHandlers.use(Meteor.bindEnvironment(function(req, res, next) {
if (req._body) {
return next();
}
@@ -12,7 +25,7 @@ WebApp.rawConnectHandlers.use(function(req, res, next) {
if (req.headers['content-type'] !== '' && req.headers['content-type'] !== undefined) {
return next();
}
- if (req.url.indexOf('/ufs/') === 0) {
+ if (req.url.indexOf(`${ __meteor_runtime_config__.ROOT_URL_PATH_PREFIX }/ufs/`) === 0) {
return next();
}
@@ -36,7 +49,7 @@ WebApp.rawConnectHandlers.use(function(req, res, next) {
return next();
});
-});
+}));
WebApp.rawConnectHandlers.use(function(req, res, next) {
if (/^\/(api|_timesync|sockjs|tap-i18n|__cordova)(\/|$)/.test(req.url)) {
@@ -97,7 +110,7 @@ WebApp.httpServer.addListener('request', function(req, res) {
let host = req.headers['host'] || url.parse(Meteor.absoluteUrl()).hostname;
host = host.replace(/:\d+$/, '');
res.writeHead(302, {
- 'Location': 'https://' + host + req.url
+ 'Location': `https://${ host }${ req.url }`
});
res.end();
return;
diff --git a/packages/rocketchat-cors/package.js b/packages/rocketchat-cors/package.js
index 9959f7e153946..3863a9acd73f8 100644
--- a/packages/rocketchat-cors/package.js
+++ b/packages/rocketchat-cors/package.js
@@ -8,7 +8,8 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'webapp'
+ 'webapp',
+ 'mongo'
]);
api.addFiles('cors.js', 'server');
diff --git a/packages/rocketchat-crowd/.npm/package/.gitignore b/packages/rocketchat-crowd/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-crowd/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-crowd/.npm/package/README b/packages/rocketchat-crowd/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-crowd/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-crowd/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-crowd/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 40dc6b34ec554..0000000000000
--- a/packages/rocketchat-crowd/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "dependencies": {
- "atlassian-crowd": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/atlassian-crowd/-/atlassian-crowd-0.5.0.tgz",
- "from": "atlassian-crowd@0.5.0"
- }
- }
-}
diff --git a/packages/rocketchat-crowd/client/loginHelper.js b/packages/rocketchat-crowd/client/loginHelper.js
index 362a6a99f4155..e337b07edc679 100644
--- a/packages/rocketchat-crowd/client/loginHelper.js
+++ b/packages/rocketchat-crowd/client/loginHelper.js
@@ -1,20 +1,20 @@
Meteor.loginWithCrowd = function(username, password, callback) {
// Retrieve arguments as array
- var args = [];
- for (var i = 0; i < arguments.length; i++) {
+ const args = [];
+ for (let i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
// Pull username and password
username = args.shift();
password = args.shift();
- var loginRequest = {
+ const loginRequest = {
crowd: true,
- username: username,
+ username,
crowdPassword: password
};
Accounts.callLoginMethod({
methodArguments: [loginRequest],
- userCallback: function(error) {
+ userCallback(error) {
if (error) {
if (callback) {
callback(error);
diff --git a/packages/rocketchat-crowd/package.js b/packages/rocketchat-crowd/package.js
index c02187121db9f..0315c1426e83b 100644
--- a/packages/rocketchat-crowd/package.js
+++ b/packages/rocketchat-crowd/package.js
@@ -22,7 +22,3 @@ Package.onUse(function(api) {
api.export('CROWD', 'server');
});
-
-Npm.depends({
- 'atlassian-crowd': '0.5.0'
-});
diff --git a/packages/rocketchat-crowd/server/crowd.js b/packages/rocketchat-crowd/server/crowd.js
index 65c6f5427260f..b717a532bb894 100644
--- a/packages/rocketchat-crowd/server/crowd.js
+++ b/packages/rocketchat-crowd/server/crowd.js
@@ -5,7 +5,7 @@ const logger = new Logger('CROWD', {});
function fallbackDefaultAccountSystem(bind, username, password) {
if (typeof username === 'string') {
if (username.indexOf('@') === -1) {
- username = {username: username};
+ username = {username};
} else {
username = {email: username};
}
@@ -26,10 +26,9 @@ function fallbackDefaultAccountSystem(bind, username, password) {
const CROWD = class CROWD {
constructor() {
- const AtlassianCrowd = Npm.require('atlassian-crowd');
-
+ const AtlassianCrowd = require('atlassian-crowd');
let url = RocketChat.settings.get('CROWD_URL');
- let urlLastChar = url.slice(-1);
+ const urlLastChar = url.slice(-1);
if (urlLastChar !== '/') {
url += '/';
@@ -76,7 +75,7 @@ const CROWD = class CROWD {
displayname: userResponse['display-name'],
username: userResponse.name,
email: userResponse.email,
- password: password,
+ password,
active: userResponse.active
};
@@ -85,7 +84,6 @@ const CROWD = class CROWD {
syncDataToUser(crowdUser, id) {
const user = {
- name: crowdUser.displayname,
username: crowdUser.username,
emails: [{
address : crowdUser.email,
@@ -95,6 +93,10 @@ const CROWD = class CROWD {
active: crowdUser.active
};
+ if (crowdUser.displayname) {
+ RocketChat._setRealName(id, crowdUser.displayname);
+ }
+
Meteor.users.update(id, {
$set: user
});
@@ -105,7 +107,7 @@ const CROWD = class CROWD {
return;
}
- var self = this;
+ const self = this;
logger.info('Sync started');
const users = RocketChat.models.Users.findCrowdUsers();
@@ -129,7 +131,7 @@ const CROWD = class CROWD {
}
addNewUser(crowdUser) {
- var userQuery = {
+ const userQuery = {
crowd: true,
username: crowdUser.username
};
@@ -222,7 +224,7 @@ RocketChat.settings.get('CROWD_Sync_User_Data', function(key, value) {
});
Meteor.methods({
- crowd_test_connection:function() {
+ crowd_test_connection() {
const user = Meteor.user();
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'crowd_test_connection' });
@@ -236,7 +238,7 @@ Meteor.methods({
throw new Meteor.Error('crowd_disabled');
}
- let crowd = new CROWD();
+ const crowd = new CROWD();
try {
crowd.checkConnection();
diff --git a/packages/rocketchat-crowd/server/settings.js b/packages/rocketchat-crowd/server/settings.js
index 418fddff92634..6a83a6abac82a 100644
--- a/packages/rocketchat-crowd/server/settings.js
+++ b/packages/rocketchat-crowd/server/settings.js
@@ -2,11 +2,11 @@ Meteor.startup(function() {
RocketChat.settings.addGroup('AtlassianCrowd', function() {
const enableQuery = {_id: 'CROWD_Enable', value: true};
this.add('CROWD_Enable', false, { type: 'boolean', public: true, i18nLabel: 'Enabled' });
- this.add('CROWD_URL', '', { type: 'string', enableQuery: enableQuery, i18nLabel: 'URL' });
- this.add('CROWD_Reject_Unauthorized', true, { type: 'boolean', enableQuery: enableQuery });
- this.add('CROWD_APP_USERNAME', '', { type: 'string', enableQuery: enableQuery, i18nLabel: 'Username' });
- this.add('CROWD_APP_PASSWORD', '', { type: 'password', enableQuery: enableQuery, i18nLabel: 'Password' });
- this.add('CROWD_Sync_User_Data', false, { type: 'boolean', enableQuery: enableQuery, i18nLabel: 'Sync_Users' });
+ this.add('CROWD_URL', '', { type: 'string', enableQuery, i18nLabel: 'URL' });
+ this.add('CROWD_Reject_Unauthorized', true, { type: 'boolean', enableQuery });
+ this.add('CROWD_APP_USERNAME', '', { type: 'string', enableQuery, i18nLabel: 'Username' });
+ this.add('CROWD_APP_PASSWORD', '', { type: 'password', enableQuery, i18nLabel: 'Password' });
+ this.add('CROWD_Sync_User_Data', false, { type: 'boolean', enableQuery, i18nLabel: 'Sync_Users' });
this.add('CROWD_Test_Connection', 'crowd_test_connection', { type: 'action', actionText: 'Test_Connection', i18nLabel: 'Test_Connection' });
});
});
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_client.js b/packages/rocketchat-custom-oauth/client/custom_oauth_client.js
similarity index 81%
rename from packages/rocketchat-custom-oauth/custom_oauth_client.js
rename to packages/rocketchat-custom-oauth/client/custom_oauth_client.js
index b3c88e9955d8a..5a74495d4a6cb 100644
--- a/packages/rocketchat-custom-oauth/custom_oauth_client.js
+++ b/packages/rocketchat-custom-oauth/client/custom_oauth_client.js
@@ -1,4 +1,6 @@
/*globals OAuth*/
+import s from 'underscore.string';
+
// Request custom OAuth credentials for the user
// @param options {optional}
// @param credentialRequestCompleteCallback {Function} Callback function to call on
@@ -46,7 +48,7 @@ export class CustomOAuth {
}
configureLogin() {
- const loginWithService = 'loginWith' + s.capitalize(this.name);
+ const loginWithService = `loginWith${ s.capitalize(this.name) }`;
Meteor[loginWithService] = (options, callback) => {
// support a callback without options
@@ -78,19 +80,21 @@ export class CustomOAuth {
const credentialToken = Random.secret();
const loginStyle = OAuth._loginStyle(this.name, config, options);
- const loginUrl = this.authorizePath +
- '?client_id=' + config.clientId +
- '&redirect_uri=' + OAuth._redirectUri(this.name, config) +
- '&response_type=code' +
- '&state=' + OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl) +
- '&scope=' + this.scope;
+ const separator = this.authorizePath.indexOf('?') !== -1 ? '&' : '?';
+
+ const loginUrl = `${ this.authorizePath
+ }${ separator }client_id=${ config.clientId
+ }&redirect_uri=${ OAuth._redirectUri(this.name, config)
+ }&response_type=code` +
+ `&state=${ OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl)
+ }&scope=${ this.scope }`;
OAuth.launchLogin({
loginService: this.name,
- loginStyle: loginStyle,
- loginUrl: loginUrl,
- credentialRequestCompleteCallback: credentialRequestCompleteCallback,
- credentialToken: credentialToken,
+ loginStyle,
+ loginUrl,
+ credentialRequestCompleteCallback,
+ credentialToken,
popupOptions: {
width: 900,
height: 450
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_server.js b/packages/rocketchat-custom-oauth/custom_oauth_server.js
deleted file mode 100644
index 6517b3891e4e4..0000000000000
--- a/packages/rocketchat-custom-oauth/custom_oauth_server.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/*globals OAuth*/
-
-const logger = new Logger('CustomOAuth');
-
-const Services = {};
-const BeforeUpdateOrCreateUserFromExternalService = [];
-
-export class CustomOAuth {
- constructor(name, options) {
- logger.debug('Init CustomOAuth', name, options);
-
- this.name = name;
- if (!Match.test(this.name, String)) {
- throw new Meteor.Error('CustomOAuth: Name is required and must be String');
- }
-
- if (Services[this.name]) {
- Services[this.name].configure(options);
- return;
- }
-
- Services[this.name] = this;
-
- this.configure(options);
-
- this.userAgent = 'Meteor';
- if (Meteor.release) {
- this.userAgent += '/' + Meteor.release;
- }
-
- Accounts.oauth.registerService(this.name);
- this.registerService();
- this.addHookToProcessUser();
- }
-
- configure(options) {
- if (!Match.test(options, Object)) {
- throw new Meteor.Error('CustomOAuth: Options is required and must be Object');
- }
-
- if (!Match.test(options.serverURL, String)) {
- throw new Meteor.Error('CustomOAuth: Options.serverURL is required and must be String');
- }
-
- if (!Match.test(options.tokenPath, String)) {
- options.tokenPath = '/oauth/token';
- }
-
- if (!Match.test(options.identityPath, String)) {
- options.identityPath = '/me';
- }
-
- this.serverURL = options.serverURL;
- this.tokenPath = options.tokenPath;
- this.identityPath = options.identityPath;
- this.tokenSentVia = options.tokenSentVia;
- this.usernameField = (options.usernameField || '').trim();
- this.mergeUsers = options.mergeUsers;
-
- if (!/^https?:\/\/.+/.test(this.tokenPath)) {
- this.tokenPath = this.serverURL + this.tokenPath;
- }
-
- if (!/^https?:\/\/.+/.test(this.identityPath)) {
- this.identityPath = this.serverURL + this.identityPath;
- }
-
- if (Match.test(options.addAutopublishFields, Object)) {
- Accounts.addAutopublishFields(options.addAutopublishFields);
- }
- }
-
- getAccessToken(query) {
- const config = ServiceConfiguration.configurations.findOne({service: this.name});
- if (!config) {
- throw new ServiceConfiguration.ConfigError();
- }
-
- let response = undefined;
- try {
- response = HTTP.post(this.tokenPath, {
- auth: config.clientId + ':' + OAuth.openSecret(config.secret),
- headers: {
- Accept: 'application/json',
- 'User-Agent': this.userAgent
- },
- params: {
- code: query.code,
- client_id: config.clientId,
- client_secret: OAuth.openSecret(config.secret),
- redirect_uri: OAuth._redirectUri(this.name, config),
- grant_type: 'authorization_code',
- state: query.state
- }
- });
- } catch (err) {
- const error = new Error(`Failed to complete OAuth handshake with ${this.name} at ${this.tokenPath}. ${err.message}`);
- throw _.extend(error, {response: err.response});
- }
-
- if (response.data.error) { //if the http response was a json object with an error attribute
- throw new Error(`Failed to complete OAuth handshake with ${this.name} at ${this.tokenPath}. ${response.data.error}`);
- } else {
- return response.data.access_token;
- }
- }
-
- getIdentity(accessToken) {
- const params = {};
- const headers = {
- 'User-Agent': this.userAgent // http://doc.gitlab.com/ce/api/users.html#Current-user
- };
-
- if (this.tokenSentVia === 'header') {
- headers['Authorization'] = 'Bearer ' + accessToken;
- } else {
- params['access_token'] = accessToken;
- }
-
- try {
- const response = HTTP.get(this.identityPath, {
- headers: headers,
- params: params
- });
-
- let data;
-
- if (response.data) {
- data = response.data;
- } else {
- data = JSON.parse(response.content);
- }
-
- logger.debug('Identity response', JSON.stringify(data, null, 2));
-
- return data;
- } catch (err) {
- const error = new Error(`Failed to fetch identity from ${this.name} at ${this.identityPath}. ${err.message}`);
- throw _.extend(error, {response: err.response});
- }
- }
-
- registerService() {
- const self = this;
- OAuth.registerService(this.name, 2, null, (query) => {
- const accessToken = self.getAccessToken(query);
- // console.log 'at:', accessToken
-
- let identity = self.getIdentity(accessToken);
-
- if (identity) {
- // Set 'id' to '_id' for any sources that provide it
- if (identity._id && !identity.id) {
- identity.id = identity._id;
- }
-
- // Fix for Reddit
- if (identity.result) {
- identity = identity.result;
- }
-
- // Fix WordPress-like identities having 'ID' instead of 'id'
- if (identity.ID && !identity.id) {
- identity.id = identity.ID;
- }
-
- // Fix Auth0-like identities having 'user_id' instead of 'id'
- if (identity.user_id && !identity.id) {
- identity.id = identity.user_id;
- }
-
- if (identity.CharacterID && !identity.id) {
- identity.id = identity.CharacterID;
- }
-
- // Fix Dataporten having 'user.userid' instead of 'id'
- if (identity.user && identity.user.userid && !identity.id) {
- identity.id = identity.user.userid;
- identity.email = identity.user.email;
- }
-
- // Fix general 'phid' instead of 'id' from phabricator
- if (identity.phid && !identity.id) {
- identity.id = identity.phid;
- }
-
- // Fix Keycloak-like identities having 'sub' instead of 'id'
- if (identity.sub && !identity.id) {
- identity.id = identity.sub;
- }
-
- // Fix general 'userid' instead of 'id' from provider
- if (identity.userid && !identity.id) {
- identity.id = identity.userid;
- }
- }
-
- // console.log 'id:', JSON.stringify identity, null, ' '
-
- const serviceData = {
- _OAuthCustom: true,
- accessToken: accessToken
- };
-
- _.extend(serviceData, identity);
-
- const data = {
- serviceData: serviceData,
- options: {
- profile: {
- name: identity.name || identity.username || identity.nickname || identity.CharacterName || identity.userName || identity.preferred_username || (identity.user && identity.user.name)
- }
- }
- };
-
- // console.log data
-
- return data;
- });
- }
-
- retrieveCredential(credentialToken, credentialSecret) {
- return OAuth.retrieveCredential(credentialToken, credentialSecret);
- }
-
- getUsername(data) {
- let username = '';
-
- if (this.usernameField.indexOf('#{') > -1) {
- username = this.usernameField.replace(/#{(.+?)}/g, function(match, field) {
- if (!data[field]) {
- throw new Meteor.Error('field_not_found', `Username template item "${field}" not found in data`, data);
- }
- return data[field];
- });
- } else {
- username = data[this.usernameField];
- if (!username) {
- throw new Meteor.Error('field_not_found', `Username field "${this.usernameField}" not found in data`, data);
- }
- }
-
- return username;
- }
-
- addHookToProcessUser() {
- BeforeUpdateOrCreateUserFromExternalService.push((serviceName, serviceData/*, options*/) => {
- if (serviceName !== this.name) {
- return;
- }
-
- if (this.usernameField) {
- const username = this.getUsername(serviceData);
-
- const user = RocketChat.models.Users.findOneByUsername(username);
- if (!user) {
- return;
- }
-
- // User already created or merged
- if (user.services && user.services[serviceName] && user.services[serviceName].id === serviceData.id) {
- return;
- }
-
- if (this.mergeUsers !== true) {
- throw new Meteor.Error('CustomOAuth', `User with username ${user.username} already exists`);
- }
-
- const serviceIdKey = `services.${serviceName}.id`;
- const update = {
- $set: {
- [serviceIdKey]: serviceData.id
- }
- };
-
- RocketChat.models.Users.update({_id: user._id}, update);
- }
- });
-
- Accounts.validateNewUser((user) => {
- if (!user.services || !user.services[this.name] || !user.services[this.name].id) {
- return true;
- }
-
- if (this.usernameField) {
- user.username = this.getUsername(user.services[this.name]);
- }
-
- return true;
- });
-
- }
-}
-
-
-const updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService;
-Accounts.updateOrCreateUserFromExternalService = function(/*serviceName, serviceData, options*/) {
- for (const hook of BeforeUpdateOrCreateUserFromExternalService) {
- hook.apply(this, arguments);
- }
-
- return updateOrCreateUserFromExternalService.apply(this, arguments);
-};
diff --git a/packages/rocketchat-custom-oauth/package.js b/packages/rocketchat-custom-oauth/package.js
index e4a397f479e8e..ded98241a8a16 100644
--- a/packages/rocketchat-custom-oauth/package.js
+++ b/packages/rocketchat-custom-oauth/package.js
@@ -9,20 +9,18 @@ Package.onUse(function(api) {
api.use('check');
api.use('oauth');
api.use('oauth2');
- api.use('underscore');
api.use('ecmascript');
api.use('accounts-oauth');
api.use('service-configuration');
- api.use('underscorestring:underscore.string');
api.use('templating', 'client');
api.use('http', 'server');
- api.mainModule('custom_oauth_client.js', 'client');
+ api.mainModule('client/custom_oauth_client.js', 'client');
- api.mainModule('custom_oauth_server.js', 'server');
+ api.mainModule('server/custom_oauth_server.js', 'server');
api.export('CustomOAuth');
});
diff --git a/packages/rocketchat-custom-oauth/server/custom_oauth_server.js b/packages/rocketchat-custom-oauth/server/custom_oauth_server.js
new file mode 100644
index 0000000000000..f78b9e57edb8c
--- /dev/null
+++ b/packages/rocketchat-custom-oauth/server/custom_oauth_server.js
@@ -0,0 +1,329 @@
+/*globals OAuth*/
+import _ from 'underscore';
+
+const logger = new Logger('CustomOAuth');
+
+const Services = {};
+const BeforeUpdateOrCreateUserFromExternalService = [];
+
+export class CustomOAuth {
+ constructor(name, options) {
+ logger.debug('Init CustomOAuth', name, options);
+
+ this.name = name;
+ if (!Match.test(this.name, String)) {
+ throw new Meteor.Error('CustomOAuth: Name is required and must be String');
+ }
+
+ if (Services[this.name]) {
+ Services[this.name].configure(options);
+ return;
+ }
+
+ Services[this.name] = this;
+
+ this.configure(options);
+
+ this.userAgent = 'Meteor';
+ if (Meteor.release) {
+ this.userAgent += `/${ Meteor.release }`;
+ }
+
+ Accounts.oauth.registerService(this.name);
+ this.registerService();
+ this.addHookToProcessUser();
+ }
+
+ configure(options) {
+ if (!Match.test(options, Object)) {
+ throw new Meteor.Error('CustomOAuth: Options is required and must be Object');
+ }
+
+ if (!Match.test(options.serverURL, String)) {
+ throw new Meteor.Error('CustomOAuth: Options.serverURL is required and must be String');
+ }
+
+ if (!Match.test(options.tokenPath, String)) {
+ options.tokenPath = '/oauth/token';
+ }
+
+ if (!Match.test(options.identityPath, String)) {
+ options.identityPath = '/me';
+ }
+
+ this.serverURL = options.serverURL;
+ this.tokenPath = options.tokenPath;
+ this.identityPath = options.identityPath;
+ this.tokenSentVia = options.tokenSentVia;
+ this.identityTokenSentVia = options.identityTokenSentVia;
+ this.usernameField = (options.usernameField || '').trim();
+ this.mergeUsers = options.mergeUsers;
+
+ if (this.identityTokenSentVia == null || this.identityTokenSentVia === 'default') {
+ this.identityTokenSentVia = this.tokenSentVia;
+ }
+
+ if (!/^https?:\/\/.+/.test(this.tokenPath)) {
+ this.tokenPath = this.serverURL + this.tokenPath;
+ }
+
+ if (!/^https?:\/\/.+/.test(this.identityPath)) {
+ this.identityPath = this.serverURL + this.identityPath;
+ }
+
+ if (Match.test(options.addAutopublishFields, Object)) {
+ Accounts.addAutopublishFields(options.addAutopublishFields);
+ }
+ }
+
+ getAccessToken(query) {
+ const config = ServiceConfiguration.configurations.findOne({service: this.name});
+ if (!config) {
+ throw new ServiceConfiguration.ConfigError();
+ }
+
+ let response = undefined;
+
+ const allOptions = {
+ headers: {
+ 'User-Agent': this.userAgent, // http://doc.gitlab.com/ce/api/users.html#Current-user
+ Accept: 'application/json'
+ },
+ params: {
+ code: query.code,
+ redirect_uri: OAuth._redirectUri(this.name, config),
+ grant_type: 'authorization_code',
+ state: query.state
+ }
+ };
+
+ // Only send clientID / secret once on header or payload.
+ if (this.tokenSentVia === 'header') {
+ allOptions['auth'] = `${ config.clientId }:${ OAuth.openSecret(config.secret) }`;
+ } else {
+ allOptions['params']['client_secret'] = OAuth.openSecret(config.secret);
+ allOptions['params']['client_id'] = config.clientId;
+ }
+
+ try {
+ response = HTTP.post(this.tokenPath, allOptions);
+ } catch (err) {
+ const error = new Error(`Failed to complete OAuth handshake with ${ this.name } at ${ this.tokenPath }. ${ err.message }`);
+ throw _.extend(error, {response: err.response});
+ }
+
+ let data;
+ if (response.data) {
+ data = response.data;
+ } else {
+ data = JSON.parse(response.content);
+ }
+
+ if (data.error) { //if the http response was a json object with an error attribute
+ throw new Error(`Failed to complete OAuth handshake with ${ this.name } at ${ this.tokenPath }. ${ data.error }`);
+ } else {
+ return data.access_token;
+ }
+ }
+
+ getIdentity(accessToken) {
+ const params = {};
+ const headers = {
+ 'User-Agent': this.userAgent // http://doc.gitlab.com/ce/api/users.html#Current-user
+ };
+
+ if (this.identityTokenSentVia === 'header') {
+ headers['Authorization'] = `Bearer ${ accessToken }`;
+ } else {
+ params['access_token'] = accessToken;
+ }
+
+ try {
+ const response = HTTP.get(this.identityPath, {
+ headers,
+ params
+ });
+
+ let data;
+
+ if (response.data) {
+ data = response.data;
+ } else {
+ data = JSON.parse(response.content);
+ }
+
+ logger.debug('Identity response', JSON.stringify(data, null, 2));
+
+ return data;
+ } catch (err) {
+ const error = new Error(`Failed to fetch identity from ${ this.name } at ${ this.identityPath }. ${ err.message }`);
+ throw _.extend(error, {response: err.response});
+ }
+ }
+
+ registerService() {
+ const self = this;
+ OAuth.registerService(this.name, 2, null, (query) => {
+ const accessToken = self.getAccessToken(query);
+ // console.log 'at:', accessToken
+
+ let identity = self.getIdentity(accessToken);
+
+ if (identity) {
+ // Set 'id' to '_id' for any sources that provide it
+ if (identity._id && !identity.id) {
+ identity.id = identity._id;
+ }
+
+ // Fix for Reddit
+ if (identity.result) {
+ identity = identity.result;
+ }
+
+ // Fix WordPress-like identities having 'ID' instead of 'id'
+ if (identity.ID && !identity.id) {
+ identity.id = identity.ID;
+ }
+
+ // Fix Auth0-like identities having 'user_id' instead of 'id'
+ if (identity.user_id && !identity.id) {
+ identity.id = identity.user_id;
+ }
+
+ if (identity.CharacterID && !identity.id) {
+ identity.id = identity.CharacterID;
+ }
+
+ // Fix Dataporten having 'user.userid' instead of 'id'
+ if (identity.user && identity.user.userid && !identity.id) {
+ if (identity.user.userid_sec && identity.user.userid_sec[0]) {
+ identity.id = identity.user.userid_sec[0];
+ } else {
+ identity.id = identity.user.userid;
+ }
+ identity.email = identity.user.email;
+ }
+ // Fix for Xenforo [BD]API plugin for 'user.user_id; instead of 'id'
+ if (identity.user && identity.user.user_id && !identity.id) {
+ identity.id = identity.user.user_id;
+ identity.email = identity.user.user_email;
+ }
+ // Fix general 'phid' instead of 'id' from phabricator
+ if (identity.phid && !identity.id) {
+ identity.id = identity.phid;
+ }
+
+ // Fix Keycloak-like identities having 'sub' instead of 'id'
+ if (identity.sub && !identity.id) {
+ identity.id = identity.sub;
+ }
+
+ // Fix general 'userid' instead of 'id' from provider
+ if (identity.userid && !identity.id) {
+ identity.id = identity.userid;
+ }
+
+ // Fix when authenticating from a meteor app with 'emails' field
+ if (!identity.email && (identity.emails && Array.isArray(identity.emails) && identity.emails.length >= 1)) {
+ identity.email = identity.emails[0].address ? identity.emails[0].address : undefined;
+ }
+ }
+
+ // console.log 'id:', JSON.stringify identity, null, ' '
+
+ const serviceData = {
+ _OAuthCustom: true,
+ accessToken
+ };
+
+ _.extend(serviceData, identity);
+
+ const data = {
+ serviceData,
+ options: {
+ profile: {
+ name: identity.name || identity.username || identity.nickname || identity.CharacterName || identity.userName || identity.preferred_username || (identity.user && identity.user.name)
+ }
+ }
+ };
+
+ // console.log data
+
+ return data;
+ });
+ }
+
+ retrieveCredential(credentialToken, credentialSecret) {
+ return OAuth.retrieveCredential(credentialToken, credentialSecret);
+ }
+
+ getUsername(data) {
+ let username = '';
+
+ username = this.usernameField.split('.').reduce(function(prev, curr) {
+ return prev ? prev[curr] : undefined;
+ }, data);
+ if (!username) {
+ throw new Meteor.Error('field_not_found', `Username field "${ this.usernameField }" not found in data`, data);
+ }
+ return username;
+ }
+
+ addHookToProcessUser() {
+ BeforeUpdateOrCreateUserFromExternalService.push((serviceName, serviceData/*, options*/) => {
+ if (serviceName !== this.name) {
+ return;
+ }
+
+ if (this.usernameField) {
+ const username = this.getUsername(serviceData);
+
+ const user = RocketChat.models.Users.findOneByUsername(username);
+ if (!user) {
+ return;
+ }
+
+ // User already created or merged
+ if (user.services && user.services[serviceName] && user.services[serviceName].id === serviceData.id) {
+ return;
+ }
+
+ if (this.mergeUsers !== true) {
+ throw new Meteor.Error('CustomOAuth', `User with username ${ user.username } already exists`);
+ }
+
+ const serviceIdKey = `services.${ serviceName }.id`;
+ const update = {
+ $set: {
+ [serviceIdKey]: serviceData.id
+ }
+ };
+
+ RocketChat.models.Users.update({_id: user._id}, update);
+ }
+ });
+
+ Accounts.validateNewUser((user) => {
+ if (!user.services || !user.services[this.name] || !user.services[this.name].id) {
+ return true;
+ }
+
+ if (this.usernameField) {
+ user.username = this.getUsername(user.services[this.name]);
+ }
+
+ return true;
+ });
+
+ }
+}
+
+
+const updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService;
+Accounts.updateOrCreateUserFromExternalService = function(/*serviceName, serviceData, options*/) {
+ for (const hook of BeforeUpdateOrCreateUserFromExternalService) {
+ hook.apply(this, arguments);
+ }
+
+ return updateOrCreateUserFromExternalService.apply(this, arguments);
+};
diff --git a/packages/rocketchat-custom-sounds/assets/stylesheets/customSoundsAdmin.css b/packages/rocketchat-custom-sounds/assets/stylesheets/customSoundsAdmin.css
new file mode 100644
index 0000000000000..c96075a621e0a
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/assets/stylesheets/customSoundsAdmin.css
@@ -0,0 +1,111 @@
+.sound-info {
+ & .icon-play-circled {
+ cursor: pointer;
+ }
+}
+
+.sound-view {
+ z-index: 15;
+
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ & .thumb {
+ width: 100%;
+ height: 350px;
+ padding: 20px;
+ }
+
+ & nav {
+ padding: 0 20px;
+ }
+
+ & .info {
+ padding: 0 20px;
+
+ white-space: normal;
+
+ & h3 {
+ overflow: hidden;
+
+ width: 100%;
+ margin: 8px 0;
+
+ user-select: text;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ font-size: 24px;
+ line-height: 27px;
+
+ & i::after {
+ display: inline-block;
+
+ width: 8px;
+ height: 8px;
+
+ content: " ";
+ vertical-align: middle;
+
+ border-radius: 4px;
+ }
+ }
+
+ & p {
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ -ms-user-select: text;
+ user-select: text;
+
+ font-size: 12px;
+ font-weight: 300;
+ line-height: 18px;
+ }
+ }
+
+ & .edit-form {
+ padding: 20px 20px 0;
+
+ white-space: normal;
+
+ & h3 {
+ margin-bottom: 8px;
+
+ font-size: 24px;
+ line-height: 22px;
+ }
+
+ & p {
+ font-size: 12px;
+ font-weight: 300;
+ line-height: 18px;
+ }
+
+ & > .input-line {
+ margin-top: 20px;
+ }
+
+ & nav {
+ padding: 0;
+
+ &.buttons {
+ margin-top: 2em;
+ }
+ }
+
+ & .form-divisor {
+ height: 9px;
+ margin: 2em 0;
+
+ text-align: center;
+
+ & > span {
+ padding: 0 1em;
+ }
+ }
+ }
+
+ & .room-info-content > div {
+ margin: 0 0 20px;
+ }
+}
diff --git a/packages/rocketchat-custom-sounds/client/admin/adminSoundEdit.html b/packages/rocketchat-custom-sounds/client/admin/adminSoundEdit.html
new file mode 100644
index 0000000000000..c6f4ef42f9bf9
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/adminSoundEdit.html
@@ -0,0 +1,7 @@
+
+
+
+ {{> soundEdit .}}
+
+
+
diff --git a/packages/rocketchat-custom-sounds/client/admin/adminSoundInfo.html b/packages/rocketchat-custom-sounds/client/admin/adminSoundInfo.html
new file mode 100644
index 0000000000000..f9676c22303ac
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/adminSoundInfo.html
@@ -0,0 +1,7 @@
+
+
+
+ {{> soundInfo .}}
+
+
+
diff --git a/packages/rocketchat-custom-sounds/client/admin/adminSounds.html b/packages/rocketchat-custom-sounds/client/admin/adminSounds.html
new file mode 100644
index 0000000000000..dc63f2a640ae0
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/adminSounds.html
@@ -0,0 +1,49 @@
+
+
+
+ {{> header sectionName="Custom_Sounds"}}
+
+ {{#requiresPermission 'manage-sounds'}}
+
+
+ {{{_ "Showing_results" customsounds.length}}}
+
+
+
+
+
+ {{_ "Name"}}
+
+
+
+ {{#each customsounds}}
+
+ {{name}}
+
+ {{/each}}
+
+
+ {{#if hasMore}}
+
{{_ "Load_more"}}
+ {{/if}}
+
+ {{/requiresPermission}}
+
+
+ {{#with flexData}}
+ {{> flexTabBar}}
+ {{/with}}
+
+
diff --git a/packages/rocketchat-custom-sounds/client/admin/adminSounds.js b/packages/rocketchat-custom-sounds/client/admin/adminSounds.js
new file mode 100644
index 0000000000000..bfa46f96a908b
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/adminSounds.js
@@ -0,0 +1,135 @@
+import s from 'underscore.string';
+
+import { RocketChatTabBar } from 'meteor/rocketchat:lib';
+
+Template.adminSounds.helpers({
+ isReady() {
+ if (Template.instance().ready != null) {
+ return Template.instance().ready.get();
+ }
+ return undefined;
+ },
+ customsounds() {
+ return Template.instance().customsounds();
+ },
+ isLoading() {
+ if (Template.instance().ready != null) {
+ if (!Template.instance().ready.get()) {
+ return 'btn-loading';
+ }
+ }
+ },
+ hasMore() {
+ if (Template.instance().limit != null) {
+ if (typeof Template.instance().customsounds === 'function') {
+ return Template.instance().limit.get() === Template.instance().customsounds().length;
+ }
+ }
+ return false;
+ },
+ flexData() {
+ return {
+ tabBar: Template.instance().tabBar,
+ data: Template.instance().tabBarData.get()
+ };
+ }
+});
+
+Template.adminSounds.onCreated(function() {
+ const instance = this;
+ this.limit = new ReactiveVar(50);
+ this.filter = new ReactiveVar('');
+ this.ready = new ReactiveVar(false);
+
+ this.tabBar = new RocketChatTabBar();
+ this.tabBar.showGroup(FlowRouter.current().route.name);
+ this.tabBarData = new ReactiveVar();
+
+ RocketChat.TabBar.addButton({
+ groups: ['custom-sounds', 'custom-sounds-selected'],
+ id: 'add-sound',
+ i18nTitle: 'Custom_Sound_Add',
+ icon: 'plus',
+ template: 'adminSoundEdit',
+ openClick(/*e, t*/) {
+ instance.tabBarData.set();
+ return true;
+ },
+ order: 1
+ });
+
+ RocketChat.TabBar.addButton({
+ groups: ['custom-sounds-selected'],
+ id: 'admin-sound-info',
+ i18nTitle: 'Custom_Sound_Info',
+ icon: 'customize',
+ template: 'adminSoundInfo',
+ order: 2
+ });
+
+ this.autorun(function() {
+ const limit = (instance.limit != null) ? instance.limit.get() : 0;
+ const subscription = instance.subscribe('customSounds', '', limit);
+ instance.ready.set(subscription.ready());
+ });
+
+ this.customsounds = function() {
+ const filter = (instance.filter != null) ? s.trim(instance.filter.get()) : '';
+
+ let query = {};
+
+ if (filter) {
+ const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
+ query = { name: filterReg };
+ }
+
+ const limit = (instance.limit != null) ? instance.limit.get() : 0;
+
+ return RocketChat.models.CustomSounds.find(query, { limit, sort: { name: 1 }}).fetch();
+ };
+});
+
+Template.adminSounds.onRendered(() =>
+ Tracker.afterFlush(function() {
+ SideNav.setFlex('adminFlex');
+ SideNav.openFlex();
+ })
+);
+
+Template.adminSounds.events({
+ 'keydown #sound-filter'(e) {
+ //stop enter key
+ if (e.which === 13) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ },
+
+ 'keyup #sound-filter'(e, t) {
+ e.stopPropagation();
+ e.preventDefault();
+ t.filter.set(e.currentTarget.value);
+ },
+
+ 'click .sound-info'(e, instance) {
+ e.preventDefault();
+ instance.tabBarData.set(RocketChat.models.CustomSounds.findOne({_id: this._id}));
+ instance.tabBar.showGroup('custom-sounds-selected');
+ instance.tabBar.open('admin-sound-info');
+ },
+
+ 'click .load-more'(e, t) {
+ e.preventDefault();
+ e.stopPropagation();
+ t.limit.set(t.limit.get() + 50);
+ },
+
+ 'click .icon-play-circled'(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ const $audio = $(`audio#${ this._id }`);
+ if ($audio && $audio[0] && $audio[0].play) {
+ $audio[0].play();
+ }
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/client/admin/route.js b/packages/rocketchat-custom-sounds/client/admin/route.js
new file mode 100644
index 0000000000000..de66f932b2835
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/route.js
@@ -0,0 +1,9 @@
+FlowRouter.route('/admin/custom-sounds', {
+ name: 'custom-sounds',
+ subscriptions(/*params, queryParams*/) {
+ this.register('customSounds', Meteor.subscribe('customSounds'));
+ },
+ action(/*params*/) {
+ BlazeLayout.render('main', {center: 'adminSounds'});
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/client/admin/soundEdit.html b/packages/rocketchat-custom-sounds/client/admin/soundEdit.html
new file mode 100644
index 0000000000000..3c25ca522b0d8
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/soundEdit.html
@@ -0,0 +1,25 @@
+
+ {{#requiresPermission 'manage-sounds'}}
+
+ {{/requiresPermission}}
+
diff --git a/packages/rocketchat-custom-sounds/client/admin/soundEdit.js b/packages/rocketchat-custom-sounds/client/admin/soundEdit.js
new file mode 100644
index 0000000000000..4e431b187ac37
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/soundEdit.js
@@ -0,0 +1,150 @@
+import toastr from 'toastr';
+import s from 'underscore.string';
+
+Template.soundEdit.helpers({
+ sound() {
+ return Template.instance().sound;
+ },
+
+ name() {
+ return this.name || this._id;
+ }
+});
+
+Template.soundEdit.events({
+ 'click .cancel'(e, t) {
+ e.stopPropagation();
+ e.preventDefault();
+ delete Template.instance().soundFile;
+ t.cancel(t.find('form'));
+ },
+
+ 'submit form'(e, t) {
+ e.stopPropagation();
+ e.preventDefault();
+ t.save(e.currentTarget);
+ },
+
+ 'change input[type=file]'(ev) {
+ const e = (ev.originalEvent != null) ? ev.originalEvent : ev;
+ let files = e.target.files;
+ if (e.target.files == null || files.length === 0) {
+ if (e.dataTransfer.files != null) {
+ files = e.dataTransfer.files;
+ } else {
+ files = [];
+ }
+ }
+
+ //using let x of y here seems to have incompatibility with some phones
+ for (const file in files) {
+ if (files.hasOwnProperty(file)) {
+ Template.instance().soundFile = files[file];
+ }
+ }
+ }
+});
+
+Template.soundEdit.onCreated(function() {
+ if (this.data != null) {
+ this.sound = this.data.sound;
+ } else {
+ this.sound = undefined;
+ this.data.tabBar.showGroup('custom-sounds');
+ }
+
+ this.cancel = (form, name) => {
+ form.reset();
+ this.data.tabBar.close();
+ if (this.sound) {
+ this.data.back(name);
+ }
+ };
+
+ this.getSoundData = () => {
+ const soundData = {};
+ if (this.sound != null) {
+ soundData._id = this.sound._id;
+ soundData.previousName = this.sound.name;
+ soundData.extension = this.sound.extension;
+ soundData.previousExtension = this.sound.extension;
+ }
+ soundData.name = s.trim(this.$('#name').val());
+ soundData.newFile = false;
+ return soundData;
+ };
+
+ this.validate = () => {
+ const soundData = this.getSoundData();
+
+ const errors = [];
+ if (!soundData.name) {
+ errors.push('Name');
+ }
+
+ if (!soundData._id) {
+ if (!this.soundFile) {
+ errors.push('Sound_File_mp3');
+ }
+ }
+
+ for (const error of errors) {
+ toastr.error(TAPi18n.__('error-the-field-is-required', { field: TAPi18n.__(error) }));
+ }
+
+ if (this.soundFile) {
+ if (!/audio\/mp3/.test(this.soundFile.type)) {
+ errors.push('FileType');
+ toastr.error(TAPi18n.__('error-invalid-file-type'));
+ }
+ }
+
+ return errors.length === 0;
+ };
+
+ this.save = (form) => {
+ if (this.validate()) {
+ const soundData = this.getSoundData();
+
+ if (this.soundFile) {
+ soundData.newFile = true;
+ soundData.extension = this.soundFile.name.split('.').pop();
+ soundData.type = this.soundFile.type;
+ }
+
+ Meteor.call('insertOrUpdateSound', soundData, (error, result) => {
+ if (result) {
+ soundData._id = result;
+ soundData.random = Math.round(Math.random() * 1000);
+
+ if (this.soundFile) {
+ toastr.info(TAPi18n.__('Uploading_file'));
+
+ const reader = new FileReader();
+ reader.readAsBinaryString(this.soundFile);
+ reader.onloadend = () => {
+ Meteor.call('uploadCustomSound', reader.result, this.soundFile.type, soundData, (uploadError/*, data*/) => {
+ if (uploadError != null) {
+ handleError(uploadError);
+ console.log(uploadError);
+ return;
+ }
+ }
+ );
+ delete this.soundFile;
+ toastr.success(TAPi18n.__('File_uploaded'));
+ };
+ }
+
+ toastr.success(t('Custom_Sound_Saved_Successfully'));
+
+ this.cancel(form, soundData.name);
+ }
+
+ if (error) {
+ handleError(error);
+ }
+ });
+ }
+ };
+});
diff --git a/packages/rocketchat-custom-sounds/client/admin/soundInfo.html b/packages/rocketchat-custom-sounds/client/admin/soundInfo.html
new file mode 100644
index 0000000000000..09374f00609a9
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/soundInfo.html
@@ -0,0 +1,19 @@
+
+ {{#if editingSound}}
+ {{> soundEdit (soundToEdit)}}
+ {{else}}
+ {{#with sound}}
+
+ {{/with}}
+
+ {{#if hasPermission 'manage-sounds'}}
+ {{_ "Delete"}}
+ {{_ "Edit"}}
+ {{/if}}
+
+ {{/if}}
+
diff --git a/packages/rocketchat-custom-sounds/client/admin/soundInfo.js b/packages/rocketchat-custom-sounds/client/admin/soundInfo.js
new file mode 100644
index 0000000000000..81fe003aba48f
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/soundInfo.js
@@ -0,0 +1,109 @@
+Template.soundInfo.helpers({
+ name() {
+ const sound = Template.instance().sound.get();
+ return sound.name;
+ },
+
+ sound() {
+ return Template.instance().sound.get();
+ },
+
+ editingSound() {
+ return Template.instance().editingSound.get();
+ },
+
+ soundToEdit() {
+ const instance = Template.instance();
+ return {
+ tabBar: instance.data.tabBar,
+ data: instance.data.data,
+ sound: instance.sound.get(),
+ back(name) {
+ instance.editingSound.set();
+
+ if (name != null) {
+ const sound = instance.sound.get();
+ if (sound.name != null && sound.name !== name) {
+ return instance.loadedName.set(name);
+ }
+ }
+ }
+ };
+ }
+});
+
+Template.soundInfo.events({
+ 'click .delete'(e, instance) {
+ e.stopPropagation();
+ e.preventDefault();
+ const sound = instance.sound.get();
+ if (sound != null) {
+ const _id = sound._id;
+ modal.open({
+ title: t('Are_you_sure'),
+ text: t('Custom_Sound_Delete_Warning'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes_delete_it'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, function() {
+ Meteor.call('deleteCustomSound', _id, (error/*, result*/) => {
+ if (error) {
+ handleError(error);
+ } else {
+ modal.open({
+ title: t('Deleted'),
+ text: t('Custom_Sound_Has_Been_Deleted'),
+ type: 'success',
+ timer: 2000,
+ showConfirmButton: false
+ });
+
+ instance.data.tabBar.showGroup('custom-sounds');
+ instance.data.tabBar.close();
+ }
+ });
+ });
+ }
+ },
+
+ 'click .edit-sound'(e, instance) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ instance.editingSound.set(instance.sound.get()._id);
+ }
+});
+
+Template.soundInfo.onCreated(function() {
+ this.sound = new ReactiveVar();
+
+ this.editingSound = new ReactiveVar();
+
+ this.loadedName = new ReactiveVar();
+
+ this.autorun(() => {
+ const data = Template.currentData();
+ if (data && data.clear != null) {
+ this.clear = data.clear;
+ }
+ });
+
+ this.autorun(() => {
+ const data = Template.currentData();
+ const sound = this.sound.get();
+ if (sound && sound.name != null) {
+ this.loadedName.set(sound.name);
+ } else if (data.name != null) {
+ this.loadedName.set(data.name);
+ }
+ });
+
+ this.autorun(() => {
+ const data = Template.currentData();
+ this.sound.set(data);
+ });
+});
diff --git a/packages/rocketchat-custom-sounds/client/admin/startup.js b/packages/rocketchat-custom-sounds/client/admin/startup.js
new file mode 100644
index 0000000000000..20ca6ef931754
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/admin/startup.js
@@ -0,0 +1,8 @@
+RocketChat.AdminBox.addOption({
+ href: 'custom-sounds',
+ i18nLabel: 'Custom_Sounds',
+ icon: 'volume',
+ permissionGranted() {
+ return RocketChat.authz.hasAtLeastOnePermission(['manage-sounds']);
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/client/lib/CustomSounds.js b/packages/rocketchat-custom-sounds/client/lib/CustomSounds.js
new file mode 100644
index 0000000000000..fd9f8ac2bddee
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/lib/CustomSounds.js
@@ -0,0 +1,70 @@
+import _ from 'underscore';
+
+class CustomSounds {
+ constructor() {
+ this.list = new ReactiveVar({});
+ this.add({ _id: 'beep', name: 'Beep', extension: 'mp3', src: 'sounds/beep.mp3' });
+ this.add({ _id: 'chelle', name: 'Chelle', extension: 'mp3', src: 'sounds/chelle.mp3' });
+ this.add({ _id: 'ding', name: 'Ding', extension: 'mp3', src: 'sounds/ding.mp3' });
+ this.add({ _id: 'droplet', name: 'Droplet', extension: 'mp3', src: 'sounds/droplet.mp3' });
+ this.add({ _id: 'highbell', name: 'Highbell', extension: 'mp3', src: 'sounds/highbell.mp3' });
+ this.add({ _id: 'seasons', name: 'Seasons', extension: 'mp3', src: 'sounds/seasons.mp3' });
+ }
+
+ add(sound) {
+ if (Meteor.isCordova) {
+ return;
+ }
+
+ if (!sound.src) {
+ sound.src = this.getURL(sound);
+ }
+ const audio = $('
', { id: sound._id, preload: true }).append(
+ $('
', { src: sound.src })
+ );
+ const list = this.list.get();
+ list[sound._id] = sound;
+ this.list.set(list);
+ $('body').append(audio);
+ }
+
+ remove(sound) {
+ const list = this.list.get();
+ delete list[sound._id];
+ this.list.set(list);
+ $(`#${ sound._id }`).remove();
+ }
+
+ update(sound) {
+ const audio = $(`#${ sound._id }`);
+ if (audio && audio[0]) {
+ const list = this.list.get();
+ list[sound._id] = sound;
+ this.list.set(list);
+ $('source', audio).attr('src', this.getURL(sound));
+ audio[0].load();
+ } else {
+ this.add(sound);
+ }
+ }
+
+ getURL(sound) {
+ const path = (Meteor.isCordova) ? Meteor.absoluteUrl().replace(/\/$/, '') : __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
+ return `${ path }/custom-sounds/${ sound._id }.${ sound.extension }?_dc=${ sound.random || 0 }`;
+ }
+
+ getList() {
+ const list = Object.values(this.list.get());
+ return _.sortBy(list, 'name');
+ }
+}
+
+RocketChat.CustomSounds = new CustomSounds;
+
+Meteor.startup(() =>
+ Meteor.call('listCustomSounds', (error, result) => {
+ for (const sound of result) {
+ RocketChat.CustomSounds.add(sound);
+ }
+ })
+);
diff --git a/packages/rocketchat-custom-sounds/client/models/CustomSounds.js b/packages/rocketchat-custom-sounds/client/models/CustomSounds.js
new file mode 100644
index 0000000000000..59c847dd1b79f
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/models/CustomSounds.js
@@ -0,0 +1,8 @@
+class CustomSounds extends RocketChat.models._Base {
+ constructor() {
+ super();
+ this._initModel('custom_sounds');
+ }
+}
+
+RocketChat.models.CustomSounds = new CustomSounds();
diff --git a/packages/rocketchat-custom-sounds/client/notifications/deleteCustomSound.js b/packages/rocketchat-custom-sounds/client/notifications/deleteCustomSound.js
new file mode 100644
index 0000000000000..81323dabc7607
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/notifications/deleteCustomSound.js
@@ -0,0 +1,3 @@
+Meteor.startup(() =>
+ RocketChat.Notifications.onAll('deleteCustomSound', data => RocketChat.CustomSounds.remove(data.soundData))
+);
diff --git a/packages/rocketchat-custom-sounds/client/notifications/updateCustomSound.js b/packages/rocketchat-custom-sounds/client/notifications/updateCustomSound.js
new file mode 100644
index 0000000000000..73b16ae4aa96d
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/client/notifications/updateCustomSound.js
@@ -0,0 +1,3 @@
+Meteor.startup(() =>
+ RocketChat.Notifications.onAll('updateCustomSound', data => RocketChat.CustomSounds.update(data.soundData))
+);
diff --git a/packages/rocketchat-custom-sounds/package.js b/packages/rocketchat-custom-sounds/package.js
new file mode 100644
index 0000000000000..52adff9ee0754
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/package.js
@@ -0,0 +1,51 @@
+Package.describe({
+ name: 'rocketchat:custom-sounds',
+ version: '1.0.0',
+ summary: 'Custom sounds',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'rocketchat:file',
+ 'rocketchat:lib',
+ 'templating',
+ 'reactive-var',
+ 'webapp'
+ ]);
+
+ api.use('kadira:flow-router', 'client');
+
+ api.addFiles('server/startup/custom-sounds.js', 'server');
+ api.addFiles('server/startup/permissions.js', 'server');
+ api.addFiles('server/startup/settings.js', 'server');
+
+ api.addFiles('server/models/CustomSounds.js', 'server');
+ api.addFiles('server/publications/customSounds.js', 'server');
+
+ api.addFiles([
+ 'server/methods/deleteCustomSound.js',
+ 'server/methods/insertOrUpdateSound.js',
+ 'server/methods/listCustomSounds.js',
+ 'server/methods/uploadCustomSound.js'
+ ], 'server');
+
+ api.addFiles('assets/stylesheets/customSoundsAdmin.css', 'client');
+
+ api.addFiles('client/admin/startup.js', 'client');
+ api.addFiles('client/admin/adminSounds.html', 'client');
+ api.addFiles('client/admin/adminSounds.js', 'client');
+ api.addFiles('client/admin/adminSoundEdit.html', 'client');
+ api.addFiles('client/admin/adminSoundInfo.html', 'client');
+ api.addFiles('client/admin/soundEdit.html', 'client');
+ api.addFiles('client/admin/soundEdit.js', 'client');
+ api.addFiles('client/admin/soundInfo.html', 'client');
+ api.addFiles('client/admin/soundInfo.js', 'client');
+ api.addFiles('client/admin/route.js', 'client');
+
+ api.addFiles('client/lib/CustomSounds.js', 'client');
+ api.addFiles('client/models/CustomSounds.js', 'client');
+ api.addFiles('client/notifications/updateCustomSound.js', 'client');
+ api.addFiles('client/notifications/deleteCustomSound.js', 'client');
+});
diff --git a/packages/rocketchat-custom-sounds/server/methods/deleteCustomSound.js b/packages/rocketchat-custom-sounds/server/methods/deleteCustomSound.js
new file mode 100644
index 0000000000000..f02eecab3070c
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/methods/deleteCustomSound.js
@@ -0,0 +1,22 @@
+/* globals RocketChatFileCustomSoundsInstance */
+Meteor.methods({
+ deleteCustomSound(_id) {
+ let sound = null;
+
+ if (RocketChat.authz.hasPermission(this.userId, 'manage-sounds')) {
+ sound = RocketChat.models.CustomSounds.findOneByID(_id);
+ } else {
+ throw new Meteor.Error('not_authorized');
+ }
+
+ if (sound == null) {
+ throw new Meteor.Error('Custom_Sound_Error_Invalid_Sound', 'Invalid sound', { method: 'deleteCustomSound' });
+ }
+
+ RocketChatFileCustomSoundsInstance.deleteFile(`${ sound._id }.${ sound.extension }`);
+ RocketChat.models.CustomSounds.removeByID(_id);
+ RocketChat.Notifications.notifyAll('deleteCustomSound', {soundData: sound});
+
+ return true;
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/server/methods/insertOrUpdateSound.js b/packages/rocketchat-custom-sounds/server/methods/insertOrUpdateSound.js
new file mode 100644
index 0000000000000..f4deae43df9db
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/methods/insertOrUpdateSound.js
@@ -0,0 +1,64 @@
+/* globals RocketChatFileCustomSoundsInstance */
+import s from 'underscore.string';
+
+Meteor.methods({
+ insertOrUpdateSound(soundData) {
+ if (!RocketChat.authz.hasPermission(this.userId, 'manage-sounds')) {
+ throw new Meteor.Error('not_authorized');
+ }
+
+ if (!s.trim(soundData.name)) {
+ throw new Meteor.Error('error-the-field-is-required', 'The field Name is required', { method: 'insertOrUpdateSound', field: 'Name' });
+ }
+
+ //let nameValidation = new RegExp('^[0-9a-zA-Z-_+;.]+$');
+
+ //allow all characters except colon, whitespace, comma, >, <, &, ", ', /, \, (, )
+ //more practical than allowing specific sets of characters; also allows foreign languages
+ const nameValidation = /[\s,:><&"'\/\\\(\)]/;
+
+ //silently strip colon; this allows for uploading :soundname: as soundname
+ soundData.name = soundData.name.replace(/:/g, '');
+
+ if (nameValidation.test(soundData.name)) {
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${ soundData.name } is not a valid name`, { method: 'insertOrUpdateSound', input: soundData.name, field: 'Name' });
+ }
+
+ let matchingResults = [];
+
+ if (soundData._id) {
+ matchingResults = RocketChat.models.CustomSounds.findByNameExceptID(soundData.name, soundData._id).fetch();
+ } else {
+ matchingResults = RocketChat.models.CustomSounds.findByName(soundData.name).fetch();
+ }
+
+ if (matchingResults.length > 0) {
+ throw new Meteor.Error('Custom_Sound_Error_Name_Already_In_Use', 'The custom sound name is already in use', { method: 'insertOrUpdateSound' });
+ }
+
+ if (!soundData._id) {
+ //insert sound
+ const createSound = {
+ name: soundData.name,
+ extension: soundData.extension
+ };
+
+ const _id = RocketChat.models.CustomSounds.create(createSound);
+ createSound._id = _id;
+
+ return _id;
+ } else {
+ //update sound
+ if (soundData.newFile) {
+ RocketChatFileCustomSoundsInstance.deleteFile(`${ soundData._id }.${ soundData.previousExtension }`);
+ }
+
+ if (soundData.name !== soundData.previousName) {
+ RocketChat.models.CustomSounds.setName(soundData._id, soundData.name);
+ RocketChat.Notifications.notifyAll('updateCustomSound', {soundData});
+ }
+
+ return soundData._id;
+ }
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/server/methods/listCustomSounds.js b/packages/rocketchat-custom-sounds/server/methods/listCustomSounds.js
new file mode 100644
index 0000000000000..e16afd389f97e
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/methods/listCustomSounds.js
@@ -0,0 +1,5 @@
+Meteor.methods({
+ listCustomSounds() {
+ return RocketChat.models.CustomSounds.find({}).fetch();
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/server/methods/uploadCustomSound.js b/packages/rocketchat-custom-sounds/server/methods/uploadCustomSound.js
new file mode 100644
index 0000000000000..7d904ddd81265
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/methods/uploadCustomSound.js
@@ -0,0 +1,19 @@
+/* globals RocketChatFileCustomSoundsInstance */
+Meteor.methods({
+ uploadCustomSound(binaryContent, contentType, soundData) {
+ if (!RocketChat.authz.hasPermission(this.userId, 'manage-sounds')) {
+ throw new Meteor.Error('not_authorized');
+ }
+
+ const file = new Buffer(binaryContent, 'binary');
+
+ const rs = RocketChatFile.bufferToStream(file);
+ RocketChatFileCustomSoundsInstance.deleteFile(`${ soundData._id }.${ soundData.extension }`);
+ const ws = RocketChatFileCustomSoundsInstance.createWriteStream(`${ soundData._id }.${ soundData.extension }`, contentType);
+ ws.on('end', Meteor.bindEnvironment(() =>
+ Meteor.setTimeout(() => RocketChat.Notifications.notifyAll('updateCustomSound', {soundData}), 500)
+ ));
+
+ rs.pipe(ws);
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/server/models/CustomSounds.js b/packages/rocketchat-custom-sounds/server/models/CustomSounds.js
new file mode 100644
index 0000000000000..25e7bf27b4bc7
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/models/CustomSounds.js
@@ -0,0 +1,54 @@
+class CustomSounds extends RocketChat.models._Base {
+ constructor() {
+ super('custom_sounds');
+
+ this.tryEnsureIndex({ 'name': 1 });
+ }
+
+ //find one
+ findOneByID(_id, options) {
+ return this.findOne(_id, options);
+ }
+
+ //find
+ findByName(name, options) {
+ const query = {
+ name
+ };
+
+ return this.find(query, options);
+ }
+
+ findByNameExceptID(name, except, options) {
+ const query = {
+ _id: { $nin: [ except ] },
+ name
+ };
+
+ return this.find(query, options);
+ }
+
+ //update
+ setName(_id, name) {
+ const update = {
+ $set: {
+ name
+ }
+ };
+
+ return this.update({_id}, update);
+ }
+
+ // INSERT
+ create(data) {
+ return this.insert(data);
+ }
+
+
+ // REMOVE
+ removeByID(_id) {
+ return this.remove(_id);
+ }
+}
+
+RocketChat.models.CustomSounds = new CustomSounds();
diff --git a/packages/rocketchat-custom-sounds/server/publications/customSounds.js b/packages/rocketchat-custom-sounds/server/publications/customSounds.js
new file mode 100644
index 0000000000000..edbc5e5b35850
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/publications/customSounds.js
@@ -0,0 +1,27 @@
+import s from 'underscore.string';
+
+Meteor.publish('customSounds', function(filter, limit) {
+ if (!this.userId) {
+ return this.ready();
+ }
+
+ const fields = {
+ name: 1,
+ extension: 1
+ };
+
+ filter = s.trim(filter);
+
+ const options = {
+ fields,
+ limit,
+ sort: { name: 1 }
+ };
+
+ if (filter) {
+ const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
+ return RocketChat.models.CustomSounds.findByName(filterReg, options);
+ }
+
+ return RocketChat.models.CustomSounds.find({}, options);
+});
diff --git a/packages/rocketchat-custom-sounds/server/startup/custom-sounds.js b/packages/rocketchat-custom-sounds/server/startup/custom-sounds.js
new file mode 100644
index 0000000000000..155d3434fee75
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/startup/custom-sounds.js
@@ -0,0 +1,78 @@
+/* globals RocketChatFileCustomSoundsInstance */
+import _ from 'underscore';
+
+Meteor.startup(function() {
+ let storeType = 'GridFS';
+
+ if (RocketChat.settings.get('CustomSounds_Storage_Type')) {
+ storeType = RocketChat.settings.get('CustomSounds_Storage_Type');
+ }
+
+ const RocketChatStore = RocketChatFile[storeType];
+
+ if (RocketChatStore == null) {
+ throw new Error(`Invalid RocketChatStore type [${ storeType }]`);
+ }
+
+ console.log(`Using ${ storeType } for custom sounds storage`.green);
+
+ let path = '~/uploads';
+ if (RocketChat.settings.get('CustomSounds_FileSystemPath') != null) {
+ if (RocketChat.settings.get('CustomSounds_FileSystemPath').trim() !== '') {
+ path = RocketChat.settings.get('CustomSounds_FileSystemPath');
+ }
+ }
+
+ this.RocketChatFileCustomSoundsInstance = new RocketChatStore({
+ name: 'custom_sounds',
+ absolutePath: path
+ });
+
+ self = this;
+
+ return WebApp.connectHandlers.use('/custom-sounds/', Meteor.bindEnvironment(function(req, res/*, next*/) {
+ const params =
+ { sound: decodeURIComponent(req.url.replace(/^\//, '').replace(/\?.*$/, '')) };
+
+ if (_.isEmpty(params.sound)) {
+ res.writeHead(403);
+ res.write('Forbidden');
+ res.end();
+ return;
+ }
+
+ const file = RocketChatFileCustomSoundsInstance.getFileWithReadStream(params.sound);
+ if (!file) {
+ return;
+ }
+
+ res.setHeader('Content-Disposition', 'inline');
+
+ let fileUploadDate = undefined;
+ if (file.uploadDate != null) {
+ fileUploadDate = file.uploadDate.toUTCString();
+ }
+
+ const reqModifiedHeader = req.headers['if-modified-since'];
+ if (reqModifiedHeader != null) {
+ if (reqModifiedHeader === fileUploadDate) {
+ res.setHeader('Last-Modified', reqModifiedHeader);
+ res.writeHead(304);
+ res.end();
+ return;
+ }
+ }
+
+ res.setHeader('Cache-Control', 'public, max-age=0');
+ res.setHeader('Expires', '-1');
+ if (fileUploadDate != null) {
+ res.setHeader('Last-Modified', fileUploadDate);
+ } else {
+ res.setHeader('Last-Modified', new Date().toUTCString());
+ }
+ res.setHeader('Content-Type', 'audio/mpeg');
+ res.setHeader('Content-Length', file.length);
+
+ file.readStream.pipe(res);
+ }));
+});
diff --git a/packages/rocketchat-custom-sounds/server/startup/permissions.js b/packages/rocketchat-custom-sounds/server/startup/permissions.js
new file mode 100644
index 0000000000000..c86644103c97e
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/startup/permissions.js
@@ -0,0 +1,5 @@
+Meteor.startup(() => {
+ if (RocketChat.models && RocketChat.models.Permissions) {
+ RocketChat.models.Permissions.createOrUpdate('manage-sounds', ['admin']);
+ }
+});
diff --git a/packages/rocketchat-custom-sounds/server/startup/settings.js b/packages/rocketchat-custom-sounds/server/startup/settings.js
new file mode 100644
index 0000000000000..78acd4c187689
--- /dev/null
+++ b/packages/rocketchat-custom-sounds/server/startup/settings.js
@@ -0,0 +1,22 @@
+RocketChat.settings.addGroup('CustomSoundsFilesystem', function() {
+ this.add('CustomSounds_Storage_Type', 'GridFS', {
+ type: 'select',
+ values: [{
+ key: 'GridFS',
+ i18nLabel: 'GridFS'
+ }, {
+ key: 'FileSystem',
+ i18nLabel: 'FileSystem'
+ }],
+ i18nLabel: 'FileUpload_Storage_Type'
+ });
+
+ this.add('CustomSounds_FileSystemPath', '', {
+ type: 'string',
+ enableQuery: {
+ _id: 'CustomSounds_Storage_Type',
+ value: 'FileSystem'
+ },
+ i18nLabel: 'FileUpload_FileSystemPath'
+ });
+});
diff --git a/packages/rocketchat-dolphin/common.js b/packages/rocketchat-dolphin/common.js
new file mode 100644
index 0000000000000..6399f813265c4
--- /dev/null
+++ b/packages/rocketchat-dolphin/common.js
@@ -0,0 +1,63 @@
+// Dolphin OAuth2
+/* globals CustomOAuth */
+
+const config = {
+ serverURL: '',
+ authorizePath: '/m/oauth2/auth/',
+ tokenPath: '/m/oauth2/token/',
+ identityPath: '/m/oauth2/api/me/',
+ scope: 'basic',
+ addAutopublishFields: {
+ forLoggedInUser: ['services.dolphin'],
+ forOtherUsers: ['services.dolphin.name']
+ }
+};
+
+const Dolphin = new CustomOAuth('dolphin', config);
+
+function DolphinOnCreateUser(options, user) {
+ if (user && user.services && user.services.dolphin && user.services.dolphin.NickName) {
+ user.username = user.services.dolphin.NickName;
+ }
+ return user;
+}
+
+if (Meteor.isServer) {
+ Meteor.startup(() =>
+ RocketChat.models.Settings.find({ _id: 'Accounts_OAuth_Dolphin_URL' }).observe({
+ added() {
+ config.serverURL = RocketChat.settings.get('Accounts_OAuth_Dolphin_URL');
+ return Dolphin.configure(config);
+ },
+ changed() {
+ config.serverURL = RocketChat.settings.get('Accounts_OAuth_Dolphin_URL');
+ return Dolphin.configure(config);
+ }
+ })
+ );
+
+ if (RocketChat.settings.get('Accounts_OAuth_Dolphin_URL')) {
+ const data = {
+ buttonLabelText: RocketChat.settings.get('Accounts_OAuth_Dolphin_button_label_text'),
+ buttonColor: RocketChat.settings.get('Accounts_OAuth_Dolphin_button_color'),
+ buttonLabelColor: RocketChat.settings.get('Accounts_OAuth_Dolphin_button_label_color'),
+ clientId: RocketChat.settings.get('Accounts_OAuth_Dolphin_id'),
+ secret: RocketChat.settings.get('Accounts_OAuth_Dolphin_secret'),
+ serverURL: RocketChat.settings.get('Accounts_OAuth_Dolphin_URL'),
+ loginStyle: RocketChat.settings.get('Accounts_OAuth_Dolphin_login_style')
+ };
+
+ ServiceConfiguration.configurations.upsert({service: 'dolphin'}, {$set: data});
+ }
+
+ RocketChat.callbacks.add('beforeCreateUser', DolphinOnCreateUser, RocketChat.callbacks.priority.HIGH);
+} else {
+ Meteor.startup(() =>
+ Tracker.autorun(function() {
+ if (RocketChat.settings.get('Accounts_OAuth_Dolphin_URL')) {
+ config.serverURL = RocketChat.settings.get('Accounts_OAuth_Dolphin_URL');
+ return Dolphin.configure(config);
+ }
+ })
+ );
+}
diff --git a/packages/rocketchat-dolphin/login-button.css b/packages/rocketchat-dolphin/login-button.css
new file mode 100644
index 0000000000000..b511270b27f1f
--- /dev/null
+++ b/packages/rocketchat-dolphin/login-button.css
@@ -0,0 +1,16 @@
+.icon-dolphin {
+ display: inline-block;
+
+ width: 30px;
+ height: 20px;
+
+ vertical-align: middle;
+
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDMwIDQzMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxnIGlkPSJzaWduLWluIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgMCAwIDAuNSAwIDApIj4NCjxwYXRoIGZpbGw9IiNmZmZmZmYiIGQ9Ik02NjAuNjcyIDUwMC4wMzJxMCAxNC41MDggLTEwLjYwMiAyNS4xMWwtMzAzLjU1MiAzMDMuNTUycS0xMC42MDIgMTAuNjAyIC0yNS4xMSAxMC42MDJ0LTI1LjExIC0xMC42MDIgLTEwLjYwMiAtMjUuMTF2LTE2MC43MDRoLTI0OS45ODRxLTE0LjUwOCAwIC0yNS4xMSAtMTAuNjAydC0xMC42MDIgLTI1LjExdi0yMTQuMjcycTAgLTE0LjUwOCAxMC42MDIgLTI1LjExdDI1LjExIC0xMC42MDJoMjQ5Ljk4NHYtMTYwLjcwNHEwIC0xNC41MDggMTAuNjAyIC0yNS4xMXQyNS4xMSAtMTAuNjAyIDI1LjExIDEwLjYwMmwzMDMuNTUyIDMwMy41NTJxMTAuNjAyIDEwLjYwMiAxMC42MDIgMjUuMTF6bTE5Ni40MTYgLTE5Ni40MTZ2MzkyLjgzMnEwIDY2LjQwMiAtNDcuMTUxIDExMy41NTN0LTExMy41NTMgNDcuMTUxaC0xNzguNTZxLTcuMjU0IDAgLTEyLjU1NSAtNS4zMDF0LTUuMzAxIC0xMi41NTVxMCAtMi4yMzIgLS41NTggLTExLjE2dC0uMjc5IC0xNC43ODcgMS42NzQgLTEzLjExMyA1LjU4IC0xMC44ODEgMTEuNDM5IC0zLjYyN2gxNzguNTZxMzYuODI4IDAgNjMuMDU0IC0yNi4yMjZ0MjYuMjI2IC02My4wNTR2LTM5Mi44MzJxMCAtMzYuODI4IC0yNi4yMjYgLTYzLjA1NHQtNjMuMDU0IC0yNi4yMjZoLTE3NC4wOTZ0LTYuNDE3IC0uNTU4IC02LjQxNyAtMS42NzQgLTQuNDY0IC0zLjA2OSAtMy45MDYgLTUuMDIyIC0xLjExNiAtNy41MzNxMCAtMi4yMzIgLS41NTggLTExLjE2dC0uMjc5IC0xNC43ODcgMS42NzQgLTEzLjExMyA1LjU4IC0xMC44ODEgMTEuNDM5IC0zLjYyN2gxNzguNTZxNjYuNDAyIDAgMTEzLjU1MyA0Ny4xNTF0NDcuMTUxIDExMy41NTN6Ii8+DQo8L2c+DQo8L3N2Zz4=);
+ background-repeat: no-repeat;
+}
+
+.icon-dolphin ~ .icon-spin,
+.icon-dolphin ~ span {
+ vertical-align: middle;
+}
diff --git a/packages/rocketchat-dolphin/package.js b/packages/rocketchat-dolphin/package.js
new file mode 100644
index 0000000000000..f87605fb35743
--- /dev/null
+++ b/packages/rocketchat-dolphin/package.js
@@ -0,0 +1,19 @@
+// Original: https://github.com/boonex/rocket.chat/blob/master/packages/rocketchat-dolphin/package.js
+Package.describe({
+ name: 'rocketchat:dolphin',
+ version: '0.0.2',
+ summary: 'RocketChat settings for Dolphin Oauth'
+});
+
+Package.onUse(function(api) {
+ api.versionsFrom('1.0');
+ api.use('ecmascript');
+ api.use('service-configuration');
+ api.use('rocketchat:lib@0.0.1');
+ api.use('rocketchat:custom-oauth');
+ api.addFiles('common.js');
+ api.addFiles('login-button.css', 'client');
+ api.addFiles('startup.js', 'server');
+
+ api.use('templating', 'client');
+});
diff --git a/packages/rocketchat-dolphin/startup.js b/packages/rocketchat-dolphin/startup.js
new file mode 100644
index 0000000000000..7ea94df35d531
--- /dev/null
+++ b/packages/rocketchat-dolphin/startup.js
@@ -0,0 +1,8 @@
+RocketChat.settings.add('Accounts_OAuth_Dolphin_URL', '', { type: 'string', group: 'OAuth', public: true, section: 'Dolphin', i18nLabel: 'URL' });
+RocketChat.settings.add('Accounts_OAuth_Dolphin', false, { type: 'boolean', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Enable' });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_id', '', { type: 'string', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_id' });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_secret', '', { type: 'string', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Secret' });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_login_style', 'redirect', { type: 'select', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Login_Style', persistent: true, values: [ { key: 'redirect', i18nLabel: 'Redirect' }, { key: 'popup', i18nLabel: 'Popup' }, { key: '', i18nLabel: 'Default' } ] });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_button_label_text', '', { type: 'string', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text', persistent: true });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_button_label_color', '#FFFFFF', { type: 'string', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color', persistent: true });
+RocketChat.settings.add('Accounts_OAuth_Dolphin_button_color', '#13679A', { type: 'string', group: 'OAuth', section: 'Dolphin', i18nLabel: 'Accounts_OAuth_Custom_Button_Color', persistent: true });
diff --git a/packages/rocketchat-drupal/README.md b/packages/rocketchat-drupal/README.md
new file mode 100644
index 0000000000000..be85fc7ae2fba
--- /dev/null
+++ b/packages/rocketchat-drupal/README.md
@@ -0,0 +1,23 @@
+#Drupal oAuth Integration module.
+This module works in conjunction with the [Rocket.Chat+ Module for Drupal](https://www.drupal.org/project/rocket_chat)
+Version 7.x-1.1 or later.
+
+A full set of instructions for how to connect the 2 are present in the drupal module's documentation.
+
+Basically to connect the 2 you first setup the oAuth server connection in your drupal, with the proper permissions
+("Use OAuth2 Server" => "Anonymous User" = Checked).
+
+In the Rocket chat you have to do the following:
+- fill in the 'Client ID'.
+ Bear in mind that the Client ID should not be guessable,but is seen in the URL when doing the login.
+- fill in the 'Client Secret'.
+ This should be treated as a Secret Key (like the Secret Key of a TLS certificate). it __must not__ be guesable or
+ derivable, and is best a Alphanumerical sequence between 16 and 48 cahracters long (longer would be better but longer
+ than 48 characters can be problem with long URI's)
+- fill in the Drupal's BaseURL.
+- on the Drupal use the "Restrict redirect URIs" Setting to limit possible exploits. and set the Redirect URI's to
+ whatever is in the Callback URL (like `https://Rocketchat.example.com/_oauth/drupal` and possibly also the
+ `https://Rocketchat.example.com/_oauth/drupal?close` URI.).
+- Lastly do not forget to Enable the Drupal OAuth and `SAVE CHANGES`.
+
+When all is a Blue Button with a drupal like logo will apear on the login page of Rocket.Chat+
diff --git a/packages/rocketchat-drupal/common.js b/packages/rocketchat-drupal/common.js
new file mode 100644
index 0000000000000..a7a7d9e67a5e7
--- /dev/null
+++ b/packages/rocketchat-drupal/common.js
@@ -0,0 +1,39 @@
+/* global CustomOAuth */
+
+// Drupal Server CallBack URL needs to be http(s)://{rocketchat.server}[:port]/_oauth/drupal
+// In RocketChat -> Administration the URL needs to be http(s)://{drupal.server}/
+
+const config = {
+ serverURL: '',
+ identityPath: '/oauth2/UserInfo',
+ authorizePath: '/oauth2/authorize',
+ tokenPath: '/oauth2/token',
+ scope: 'openid email profile offline_access',
+ tokenSentVia: 'payload',
+ usernameField: 'preferred_username',
+ mergeUsers: true,
+ addAutopublishFields: {
+ forLoggedInUser: ['services.drupal'],
+ forOtherUsers: ['services.drupal.name']
+ }
+};
+
+const Drupal = new CustomOAuth('drupal', config);
+
+if (Meteor.isServer) {
+ Meteor.startup(function() {
+ RocketChat.settings.get('API_Drupal_URL', function(key, value) {
+ config.serverURL = value;
+ Drupal.configure(config);
+ });
+ });
+} else {
+ Meteor.startup(function() {
+ Tracker.autorun(function() {
+ if (RocketChat.settings.get('API_Drupal_URL')) {
+ config.serverURL = RocketChat.settings.get('API_Drupal_URL');
+ Drupal.configure(config);
+ }
+ });
+ });
+}
diff --git a/packages/rocketchat-drupal/login-button.css b/packages/rocketchat-drupal/login-button.css
new file mode 100644
index 0000000000000..2cda29b8c62e5
--- /dev/null
+++ b/packages/rocketchat-drupal/login-button.css
@@ -0,0 +1,13 @@
+.icon-drupal.service-icon {
+ display: inline-block;
+
+ width: 21px;
+ height: 28px;
+
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAACOGPReAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAcNJREFUSMetlbFrFFEQh7/dJnhpDHcx6SyiRLhLkUKDsRZB8S9IWi2Syj8iVooQ0FLBNlqJRpNO8Br7FLkoRDBooQHhNCr6WTjB48zd7d7uNI+d+c333pt9bx5kNPVGVm1WYF39rTbKhD7zr62XBVwI4MsYF4sCZ9S2uq6mMbbVmWGBx9WW+kGdCN+J+G6pY3mBo2pT/ape6IrNx2qb6mhW4Ii6qf5Ur/TQXI74pjoyCJioa3F8FgdoF0K3pib9hLfiDy9l3NVS6G/3EiyH4GbO+q9E3nJ3oKF+Vx/33Urvkj2K/EZn4JW6l/uY/MsfU9+rzUPHXCz/+jDADvC14Myhrqpf1EpB6LHgrCbqa+BzkiSXikAD/ByopcAUsFUUGLYFTKVABWiXBG0DlRTYB8ZLgo4D+ynQAuolQevAdgq8AM6rk0Vo0R7ngQ3UU+qvvNfzCOhKcE4fOu6r39TpIYHT0XsfdDon45puq7WcwFrk7f1XQvVsdPS3Wd+geMPeRN65XqJZdVf9od5Tz/TZ7t3Q7aqzg2avqnfUg2gQO+pT9WGMO+E/CF21m5H0gU8AV4GLwEmgCnwC3gEbwJMkST4elfsHJbIReGbv9uUAAAAASUVORK5CYII=);
+ background-repeat: no-repeat;
+}
+
+.button.external-login.drupal {
+ background-color: #0f85b6;
+}
diff --git a/packages/rocketchat-drupal/package.js b/packages/rocketchat-drupal/package.js
new file mode 100644
index 0000000000000..76a586de6cdb4
--- /dev/null
+++ b/packages/rocketchat-drupal/package.js
@@ -0,0 +1,22 @@
+Package.describe({
+ name: 'rocketchat:drupal',
+ version: '0.0.1',
+ summary: 'RocketChat settings for Drupal oAuth2'
+});
+
+Package.onUse(function(api) {
+ api.versionsFrom('1.0');
+ api.use('ecmascript');
+ api.use('service-configuration');
+ api.use('rocketchat:lib@0.0.1');
+ api.use('rocketchat:custom-oauth');
+
+ // api.use('templating', 'client');
+
+ api.addFiles('common.js');
+ api.addFiles('login-button.css', 'client');
+ api.addFiles('startup.js', 'server');
+
+ api.use('templating', 'client');
+});
+
diff --git a/packages/rocketchat-drupal/startup.js b/packages/rocketchat-drupal/startup.js
new file mode 100644
index 0000000000000..c0923d8f826a8
--- /dev/null
+++ b/packages/rocketchat-drupal/startup.js
@@ -0,0 +1,14 @@
+RocketChat.settings.addGroup('OAuth', function() {
+ this.section('Drupal', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Drupal',
+ value: true
+ };
+
+ this.add('Accounts_OAuth_Drupal', false, { type: 'boolean' });
+ this.add('API_Drupal_URL', '', { type: 'string', public: true, enableQuery, i18nDescription: 'API_Drupal_URL_Description' });
+ this.add('Accounts_OAuth_Drupal_id', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_Drupal_secret', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_Drupal_callback_url', '_oauth/drupal', { type: 'relativeUrl', readonly: true, force: true, enableQuery });
+ });
+});
diff --git a/packages/rocketchat-emoji-custom/admin/adminEmoji.html b/packages/rocketchat-emoji-custom/admin/adminEmoji.html
index 164f27a4cd99b..362abe9f85533 100644
--- a/packages/rocketchat-emoji-custom/admin/adminEmoji.html
+++ b/packages/rocketchat-emoji-custom/admin/adminEmoji.html
@@ -1,22 +1,23 @@
-
- {{> burger}}
-
- {{_ "Custom_Emoji"}}
-
-
+ {{> header sectionName="Custom_emoji"}}
{{#unless hasPermission 'manage-emoji'}}
{{_ "You_are_not_authorized_to_view_this_page"}}
{{else}}
{{{_ "Showing_results" customemoji.length}}}
diff --git a/packages/rocketchat-emoji-custom/admin/adminEmoji.js b/packages/rocketchat-emoji-custom/admin/adminEmoji.js
index d0eee23f2f3dc..de717033411be 100644
--- a/packages/rocketchat-emoji-custom/admin/adminEmoji.js
+++ b/packages/rocketchat-emoji-custom/admin/adminEmoji.js
@@ -1,7 +1,10 @@
-/* globals isSetNotNull, RocketChatTabBar */
+import s from 'underscore.string';
+
+import { RocketChatTabBar } from 'meteor/rocketchat:lib';
+
Template.adminEmoji.helpers({
isReady() {
- if (isSetNotNull(() => Template.instance().ready)) {
+ if (Template.instance().ready != null) {
return Template.instance().ready.get();
}
return undefined;
@@ -10,14 +13,14 @@ Template.adminEmoji.helpers({
return Template.instance().customemoji();
},
isLoading() {
- if (isSetNotNull(() => Template.instance().ready)) {
+ if (Template.instance().ready != null) {
if (!Template.instance().ready.get()) {
return 'btn-loading';
}
}
},
hasMore() {
- if (isSetNotNull(() => Template.instance().limit)) {
+ if (Template.instance().limit != null) {
if (typeof Template.instance().customemoji === 'function') {
return Template.instance().limit.get() === Template.instance().customemoji().length;
}
@@ -33,7 +36,7 @@ Template.adminEmoji.helpers({
});
Template.adminEmoji.onCreated(function() {
- let instance = this;
+ const instance = this;
this.limit = new ReactiveVar(50);
this.filter = new ReactiveVar('');
this.ready = new ReactiveVar(false);
@@ -46,7 +49,7 @@ Template.adminEmoji.onCreated(function() {
groups: ['emoji-custom'],
id: 'add-emoji',
i18nTitle: 'Custom_Emoji_Add',
- icon: 'icon-plus',
+ icon: 'plus',
template: 'adminEmojiEdit',
order: 1
});
@@ -55,30 +58,30 @@ Template.adminEmoji.onCreated(function() {
groups: ['emoji-custom'],
id: 'admin-emoji-info',
i18nTitle: 'Custom_Emoji_Info',
- icon: 'icon-cog',
+ icon: 'customize',
template: 'adminEmojiInfo',
order: 2
});
this.autorun(function() {
- let limit = (isSetNotNull(() => instance.limit))? instance.limit.get() : 0;
- let subscription = instance.subscribe('fullEmojiData', '', limit);
+ const limit = (instance.limit != null) ? instance.limit.get() : 0;
+ const subscription = instance.subscribe('fullEmojiData', '', limit);
instance.ready.set(subscription.ready());
});
this.customemoji = function() {
- let filter = (isSetNotNull(() => instance.filter))? _.trim(instance.filter.get()) : '';
+ const filter = (instance.filter != null) ? s.trim(instance.filter.get()) : '';
let query = {};
if (filter) {
- let filterReg = new RegExp(s.escapeRegExp(filter), 'i');
+ const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
query = { $or: [ { name: filterReg }, {aliases: filterReg } ] };
}
- let limit = (isSetNotNull(() => instance.limit))? instance.limit.get() : 0;
+ const limit = (instance.limit != null) ? instance.limit.get() : 0;
- return RocketChat.models.EmojiCustom.find(query, { limit: limit, sort: { name: 1 }}).fetch();
+ return RocketChat.models.EmojiCustom.find(query, { limit, sort: { name: 1 }}).fetch();
};
});
@@ -90,7 +93,7 @@ Template.adminEmoji.onRendered(() =>
);
Template.adminEmoji.events({
- ['keydown #emoji-filter'](e) {
+ 'keydown #emoji-filter'(e) {
//stop enter key
if (e.which === 13) {
e.stopPropagation();
@@ -98,19 +101,19 @@ Template.adminEmoji.events({
}
},
- ['keyup #emoji-filter'](e, t) {
+ 'keyup #emoji-filter'(e, t) {
e.stopPropagation();
e.preventDefault();
t.filter.set(e.currentTarget.value);
},
- ['click .emoji-info'](e, instance) {
+ 'click .emoji-info'(e, instance) {
e.preventDefault();
instance.tabBarData.set(RocketChat.models.EmojiCustom.findOne({_id: this._id}));
instance.tabBar.open('admin-emoji-info');
},
- ['click .load-more'](e, t) {
+ 'click .load-more'(e, t) {
e.preventDefault();
e.stopPropagation();
t.limit.set(t.limit.get() + 50);
diff --git a/packages/rocketchat-emoji-custom/admin/emojiEdit.js b/packages/rocketchat-emoji-custom/admin/emojiEdit.js
index 266dcd83135fd..8f66b42e2b704 100644
--- a/packages/rocketchat-emoji-custom/admin/emojiEdit.js
+++ b/packages/rocketchat-emoji-custom/admin/emojiEdit.js
@@ -1,5 +1,6 @@
import toastr from 'toastr';
-/* globals isSetNotNull */
+import s from 'underscore.string';
+
Template.emojiEdit.helpers({
emoji() {
return Template.instance().emoji;
@@ -11,24 +12,24 @@ Template.emojiEdit.helpers({
});
Template.emojiEdit.events({
- ['click .cancel'](e, t) {
+ 'click .cancel'(e, t) {
e.stopPropagation();
e.preventDefault();
delete Template.instance().emojiFile;
t.cancel(t.find('form'));
},
- ['submit form'](e, t) {
+ 'submit form'(e, t) {
e.stopPropagation();
e.preventDefault();
t.save(e.currentTarget);
},
- ['change input[type=file]'](ev) {
- let e = (isSetNotNull(() => ev.originalEvent)) ? ev.originalEvent : ev;
+ 'change input[type=file]'(ev) {
+ const e = ev.originalEvent != null ? ev.originalEvent : ev;
let files = e.target.files;
- if (!isSetNotNull(() => e.target.files) || files.length === 0) {
- if (isSetNotNull(() => e.dataTransfer.files)) {
+ if (files == null || files.length === 0) {
+ if (e.dataTransfer != null && e.dataTransfer.files != null) {
files = e.dataTransfer.files;
} else {
files = [];
@@ -36,7 +37,7 @@ Template.emojiEdit.events({
}
//using let x of y here seems to have incompatibility with some phones
- for (let file in files) {
+ for (const file in files) {
if (files.hasOwnProperty(file)) {
Template.instance().emojiFile = files[file];
}
@@ -45,7 +46,7 @@ Template.emojiEdit.events({
});
Template.emojiEdit.onCreated(function() {
- if (isSetNotNull(() => this.data)) {
+ if (this.data != null) {
this.emoji = this.data.emoji;
} else {
this.emoji = undefined;
@@ -62,8 +63,8 @@ Template.emojiEdit.onCreated(function() {
};
this.getEmojiData = () => {
- let emojiData = {};
- if (isSetNotNull(() => this.emoji)) {
+ const emojiData = {};
+ if (this.emoji != null) {
emojiData._id = this.emoji._id;
emojiData.previousName = this.emoji.name;
emojiData.extension = this.emoji.extension;
@@ -76,9 +77,9 @@ Template.emojiEdit.onCreated(function() {
};
this.validate = () => {
- let emojiData = this.getEmojiData();
+ const emojiData = this.getEmojiData();
- let errors = [];
+ const errors = [];
if (!emojiData.name) {
errors.push('Name');
}
@@ -89,7 +90,7 @@ Template.emojiEdit.onCreated(function() {
}
}
- for (let error of errors) {
+ for (const error of errors) {
toastr.error(TAPi18n.__('error-the-field-is-required', { field: TAPi18n.__(error) }));
}
@@ -105,7 +106,7 @@ Template.emojiEdit.onCreated(function() {
this.save = (form) => {
if (this.validate()) {
- let emojiData = this.getEmojiData();
+ const emojiData = this.getEmojiData();
if (this.emojiFile) {
emojiData.newFile = true;
@@ -117,7 +118,7 @@ Template.emojiEdit.onCreated(function() {
if (this.emojiFile) {
toastr.info(TAPi18n.__('Uploading_file'));
- let reader = new FileReader();
+ const reader = new FileReader();
reader.readAsBinaryString(this.emojiFile);
reader.onloadend = () => {
Meteor.call('uploadEmojiCustom', reader.result, this.emojiFile.type, emojiData, (uploadError/*, data*/) => {
diff --git a/packages/rocketchat-emoji-custom/admin/emojiInfo.js b/packages/rocketchat-emoji-custom/admin/emojiInfo.js
index a9dfbf410ec10..5758043bb5e7b 100644
--- a/packages/rocketchat-emoji-custom/admin/emojiInfo.js
+++ b/packages/rocketchat-emoji-custom/admin/emojiInfo.js
@@ -1,12 +1,11 @@
-/* globals isSetNotNull */
Template.emojiInfo.helpers({
name() {
- let emoji = Template.instance().emoji.get();
+ const emoji = Template.instance().emoji.get();
return emoji.name;
},
aliases() {
- let emoji = Template.instance().emoji.get();
+ const emoji = Template.instance().emoji.get();
return emoji.aliases;
},
@@ -19,16 +18,16 @@ Template.emojiInfo.helpers({
},
emojiToEdit() {
- let instance = Template.instance();
+ const instance = Template.instance();
return {
tabBar: this.tabBar,
emoji: instance.emoji.get(),
back(name) {
instance.editingEmoji.set();
- if (isSetNotNull(() => name)) {
- let emoji = instance.emoji.get();
- if (isSetNotNull(() => emoji.name) && emoji.name !== name) {
+ if (name != null) {
+ const emoji = instance.emoji.get();
+ if (emoji != null && emoji.name != null && emoji.name !== name) {
return instance.loadedName.set(name);
}
}
@@ -38,17 +37,17 @@ Template.emojiInfo.helpers({
});
Template.emojiInfo.events({
- ['click .thumb'](e) {
+ 'click .thumb'(e) {
$(e.currentTarget).toggleClass('bigger');
},
- ['click .delete'](e, instance) {
+ 'click .delete'(e, instance) {
e.stopPropagation();
e.preventDefault();
- let emoji = instance.emoji.get();
- if (isSetNotNull(() => emoji)) {
- let _id = emoji._id;
- swal({
+ const emoji = instance.emoji.get();
+ if (emoji != null) {
+ const _id = emoji._id;
+ modal.open({
title: t('Are_you_sure'),
text: t('Custom_Emoji_Delete_Warning'),
type: 'warning',
@@ -59,14 +58,11 @@ Template.emojiInfo.events({
closeOnConfirm: false,
html: false
}, function() {
- swal.disableButtons();
-
Meteor.call('deleteEmojiCustom', _id, (error/*, result*/) => {
if (error) {
- handleError(error);
- swal.enableButtons();
+ return handleError(error);
} else {
- swal({
+ modal.open({
title: t('Deleted'),
text: t('Custom_Emoji_Has_Been_Deleted'),
type: 'success',
@@ -81,7 +77,7 @@ Template.emojiInfo.events({
}
},
- ['click .edit-emoji'](e, instance) {
+ 'click .edit-emoji'(e, instance) {
e.stopPropagation();
e.preventDefault();
@@ -99,24 +95,24 @@ Template.emojiInfo.onCreated(function() {
this.tabBar = Template.currentData().tabBar;
this.autorun(() => {
- let data = Template.currentData();
- if (isSetNotNull(() => data.clear)) {
+ const data = Template.currentData();
+ if (data != null && data.clear != null) {
this.clear = data.clear;
}
});
this.autorun(() => {
- let data = Template.currentData();
- let emoji = this.emoji.get();
- if (isSetNotNull(() => emoji.name)) {
+ const data = Template.currentData();
+ const emoji = this.emoji.get();
+ if (emoji != null && emoji.name != null) {
this.loadedName.set(emoji.name);
- } else if (isSetNotNull(() => data.name)) {
+ } else if (data != null && data.name != null) {
this.loadedName.set(data.name);
}
});
this.autorun(() => {
- let data = Template.currentData();
+ const data = Template.currentData();
this.emoji.set(data);
});
});
diff --git a/packages/rocketchat-emoji-custom/admin/startup.js b/packages/rocketchat-emoji-custom/admin/startup.js
index 3cfaa4b825ad2..71f27f95ec420 100644
--- a/packages/rocketchat-emoji-custom/admin/startup.js
+++ b/packages/rocketchat-emoji-custom/admin/startup.js
@@ -1,6 +1,7 @@
RocketChat.AdminBox.addOption({
href: 'emoji-custom',
i18nLabel: 'Custom_Emoji',
+ icon: 'emoji',
permissionGranted() {
return RocketChat.authz.hasAtLeastOnePermission(['manage-emoji']);
}
diff --git a/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.css b/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.css
new file mode 100644
index 0000000000000..30fb4da03c2fe
--- /dev/null
+++ b/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.css
@@ -0,0 +1,132 @@
+.emojiAdminPreview {
+ position: relative;
+
+ overflow: hidden;
+
+ width: 100%;
+ height: 100%;
+
+ border-radius: 4px;
+
+ & .emojiAdminPreview-image {
+ position: relative;
+
+ display: block;
+
+ width: 100%;
+ min-width: 20px;
+ height: 100%;
+ min-height: 20px;
+
+ border-radius: 4px;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+ }
+}
+
+.emoji-view {
+ z-index: 15;
+
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ & .thumb {
+ width: 100%;
+ height: 350px;
+ padding: 20px;
+ }
+
+ & nav {
+ padding: 0 20px;
+ }
+
+ & .info {
+ padding: 0 20px;
+
+ white-space: normal;
+
+ & h3 {
+ overflow: hidden;
+
+ width: 100%;
+ margin: 8px 0;
+
+ user-select: text;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ font-size: 24px;
+ line-height: 27px;
+
+ & i::after {
+ display: inline-block;
+
+ width: 8px;
+ height: 8px;
+
+ content: " ";
+ vertical-align: middle;
+
+ border-radius: 4px;
+ }
+ }
+
+ & p {
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ -ms-user-select: text;
+ user-select: text;
+
+ font-size: 12px;
+ font-weight: 300;
+ line-height: 18px;
+ }
+ }
+
+ & .edit-form {
+ padding: 20px 20px 0;
+
+ white-space: normal;
+
+ & h3 {
+ margin-bottom: 8px;
+
+ font-size: 24px;
+ line-height: 22px;
+ }
+
+ & p {
+ font-size: 12px;
+ font-weight: 300;
+ line-height: 18px;
+ }
+
+ & > .input-line {
+ margin-top: 20px;
+ }
+
+ & nav {
+ padding: 0;
+
+ &.buttons {
+ margin-top: 2em;
+ }
+ }
+
+ & .form-divisor {
+ height: 9px;
+ margin: 2em 0;
+
+ text-align: center;
+
+ & > span {
+ padding: 0 1em;
+ }
+ }
+ }
+
+ & .room-info-content > div {
+ margin: 0 0 20px;
+ }
+}
diff --git a/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less b/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less
deleted file mode 100644
index 1eb732ff8e505..0000000000000
--- a/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less
+++ /dev/null
@@ -1,117 +0,0 @@
-.emojiAdminPreview {
- height: 100%;
- width: 100%;
- overflow: hidden;
- position: relative;
- border-radius: 4px;
-
- .emojiAdminPreview-image {
- height: 100%;
- width: 100%;
- min-height: 20px;
- min-width: 20px;
- display: block;
- position: relative;
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center;
- border-radius: 4px;
- }
-}
-
-.emoji-view {
- z-index: 15;
- overflow-y: auto;
- overflow-x: hidden;
-
- .thumb {
- width: 100%;
- height: 350px;
- padding: 20px;
- }
-
- nav {
- padding: 0 20px;
- }
-
- .info {
- white-space: normal;
- padding: 0 20px;
-
- h3 {
- -webkit-user-select: text;
- -moz-user-select: text;
- -ms-user-select: text;
- user-select: text;
- font-size: 24px;
- margin: 8px 0;
- line-height: 27px;
- text-overflow: ellipsis;
- width: 100%;
- overflow: hidden;
- white-space: nowrap;
-
- i::after {
- content: " ";
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 4px;
- vertical-align: middle;
- }
- }
-
- p {
- -webkit-user-select: text;
- -moz-user-select: text;
- -ms-user-select: text;
- user-select: text;
- line-height: 18px;
- font-size: 12px;
- font-weight: 300;
- }
- }
-
- .edit-form {
- padding: 20px 20px 0;
- white-space: normal;
-
- h3 {
- font-size: 24px;
- margin-bottom: 8px;
- line-height: 22px;
- }
-
- p {
- line-height: 18px;
- font-size: 12px;
- font-weight: 300;
- }
-
- > .input-line {
- margin-top: 20px;
- }
-
- nav {
- padding: 0;
-
- &.buttons {
- margin-top: 2em;
- }
- }
-
- .form-divisor {
- text-align: center;
- margin: 2em 0;
- height: 9px;
-
- > span {
- padding: 0 1em;
- }
- }
- }
-
- .room-info-content > div {
- margin: 0 0 20px;
- }
-}
diff --git a/packages/rocketchat-emoji-custom/client/lib/emojiCustom.js b/packages/rocketchat-emoji-custom/client/lib/emojiCustom.js
index 29e64e3f15f74..50bc7d342fffa 100644
--- a/packages/rocketchat-emoji-custom/client/lib/emojiCustom.js
+++ b/packages/rocketchat-emoji-custom/client/lib/emojiCustom.js
@@ -1,11 +1,11 @@
/* globals getEmojiUrlFromName:true, updateEmojiCustom:true, deleteEmojiCustom:true, isSetNotNull */
RocketChat.emoji.packages.emojiCustom = {
- emojiCategories: { rocket: TAPi18n.__('Custom') },
+ emojiCategories: { rocket: 'Custom' },
toneList: {},
list: [],
- render: function(html) {
- let regShortNames = new RegExp('
]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(' + RocketChat.emoji.packages.emojiCustom.list.join('|') + ')', 'gi');
+ render(html) {
+ const regShortNames = new RegExp(`]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(${ RocketChat.emoji.packages.emojiCustom.list.join('|') })`, 'gi');
// replace regular shortnames first
html = html.replace(regShortNames, function(shortname) {
@@ -19,10 +19,10 @@ RocketChat.emoji.packages.emojiCustom = {
let dataCheck = RocketChat.emoji.list[shortname];
if (dataCheck.hasOwnProperty('aliasOf')) {
emojiAlias = dataCheck['aliasOf'];
- dataCheck = RocketChat.emoji.list[`:${emojiAlias}:`];
+ dataCheck = RocketChat.emoji.list[`:${ emojiAlias }:`];
}
- return `${shortname} `;
+ return `${ shortname } `;
}
});
@@ -33,7 +33,7 @@ RocketChat.emoji.packages.emojiCustom = {
getEmojiUrlFromName = function(name, extension) {
Session.get;
- let key = `emoji_random_${name}`;
+ const key = `emoji_random_${ name }`;
let random = 0;
if (isSetNotNull(() => Session.keys[key])) {
@@ -43,55 +43,45 @@ getEmojiUrlFromName = function(name, extension) {
if (name == null) {
return;
}
- let path = (Meteor.isCordova) ? Meteor.absoluteUrl().replace(/\/$/, '') : __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
- return `${path}/emoji-custom/${encodeURIComponent(name)}.${extension}?_dc=${random}`;
+ const path = (Meteor.isCordova) ? Meteor.absoluteUrl().replace(/\/$/, '') : __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
+ return `${ path }/emoji-custom/${ encodeURIComponent(name) }.${ extension }?_dc=${ random }`;
};
Blaze.registerHelper('emojiUrlFromName', getEmojiUrlFromName);
-function updateEmojiPickerList() {
- let html = '';
- for (let entry of RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket) {
- let renderedEmoji = RocketChat.emoji.packages.emojiCustom.render(`:${entry}:`);
- html += `${renderedEmoji} `;
- }
- $('.rocket.emoji-list').empty().append(html);
- RocketChat.EmojiPicker.updateRecent();
-}
-
deleteEmojiCustom = function(emojiData) {
- delete RocketChat.emoji.list[`:${emojiData.name}:`];
- let arrayIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.name);
+ delete RocketChat.emoji.list[`:${ emojiData.name }:`];
+ const arrayIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.name);
if (arrayIndex !== -1) {
RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.splice(arrayIndex, 1);
}
- let arrayIndexList = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${emojiData.name}:`);
+ const arrayIndexList = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${ emojiData.name }:`);
if (arrayIndexList !== -1) {
RocketChat.emoji.packages.emojiCustom.list.splice(arrayIndexList, 1);
}
if (isSetNotNull(() => emojiData.aliases)) {
- for (let alias of emojiData.aliases) {
- delete RocketChat.emoji.list[`:${alias}:`];
- let aliasIndex = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${alias}:`);
+ for (const alias of emojiData.aliases) {
+ delete RocketChat.emoji.list[`:${ alias }:`];
+ const aliasIndex = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${ alias }:`);
if (aliasIndex !== -1) {
RocketChat.emoji.packages.emojiCustom.list.splice(aliasIndex, 1);
}
}
}
- updateEmojiPickerList();
+ RocketChat.EmojiPicker.updateRecent();
};
updateEmojiCustom = function(emojiData) {
- let key = `emoji_random_${emojiData.name}`;
+ let key = `emoji_random_${ emojiData.name }`;
Session.set(key, Math.round(Math.random() * 1000));
- let previousExists = isSetNotNull(() => emojiData.previousName);
- let currentAliases = isSetNotNull(() => emojiData.aliases);
+ const previousExists = isSetNotNull(() => emojiData.previousName);
+ const currentAliases = isSetNotNull(() => emojiData.aliases);
- if (previousExists && isSetNotNull(() => RocketChat.emoji.list[`:${emojiData.previousName}:`].aliases)) {
- for (let alias of RocketChat.emoji.list[`:${emojiData.previousName}:`].aliases) {
- delete RocketChat.emoji.list[`:${alias}:`];
- let aliasIndex = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${alias}:`);
+ if (previousExists && isSetNotNull(() => RocketChat.emoji.list[`:${ emojiData.previousName }:`].aliases)) {
+ for (const alias of RocketChat.emoji.list[`:${ emojiData.previousName }:`].aliases) {
+ delete RocketChat.emoji.list[`:${ alias }:`];
+ const aliasIndex = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${ alias }:`);
if (aliasIndex !== -1) {
RocketChat.emoji.packages.emojiCustom.list.splice(aliasIndex, 1);
}
@@ -99,75 +89,75 @@ updateEmojiCustom = function(emojiData) {
}
if (previousExists && emojiData.name !== emojiData.previousName) {
- let arrayIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.previousName);
+ const arrayIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.previousName);
if (arrayIndex !== -1) {
RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.splice(arrayIndex, 1);
}
- let arrayIndexList = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${emojiData.previousName}:`);
+ const arrayIndexList = RocketChat.emoji.packages.emojiCustom.list.indexOf(`:${ emojiData.previousName }:`);
if (arrayIndexList !== -1) {
RocketChat.emoji.packages.emojiCustom.list.splice(arrayIndexList, 1);
}
- delete RocketChat.emoji.list[`:${emojiData.previousName}:`];
+ delete RocketChat.emoji.list[`:${ emojiData.previousName }:`];
}
- let categoryIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(`${emojiData.name}`);
+ const categoryIndex = RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(`${ emojiData.name }`);
if (categoryIndex === -1) {
- RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.push(`${emojiData.name}`);
- RocketChat.emoji.packages.emojiCustom.list.push(`:${emojiData.name}:`);
+ RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.push(`${ emojiData.name }`);
+ RocketChat.emoji.packages.emojiCustom.list.push(`:${ emojiData.name }:`);
}
- RocketChat.emoji.list[`:${emojiData.name}:`] = Object.assign({ emojiPackage: 'emojiCustom' }, RocketChat.emoji.list[`:${emojiData.name}:`], emojiData);
+ RocketChat.emoji.list[`:${ emojiData.name }:`] = Object.assign({ emojiPackage: 'emojiCustom' }, RocketChat.emoji.list[`:${ emojiData.name }:`], emojiData);
if (currentAliases) {
- for (let alias of emojiData.aliases) {
- RocketChat.emoji.packages.emojiCustom.list.push(`:${alias}:`);
- RocketChat.emoji.list[`:${alias}:`] = {};
- RocketChat.emoji.list[`:${alias}:`].emojiPackage = 'emojiCustom';
- RocketChat.emoji.list[`:${alias}:`].aliasOf = emojiData.name;
+ for (const alias of emojiData.aliases) {
+ RocketChat.emoji.packages.emojiCustom.list.push(`:${ alias }:`);
+ RocketChat.emoji.list[`:${ alias }:`] = {};
+ RocketChat.emoji.list[`:${ alias }:`].emojiPackage = 'emojiCustom';
+ RocketChat.emoji.list[`:${ alias }:`].aliasOf = emojiData.name;
}
}
- let url = getEmojiUrlFromName(emojiData.name, emojiData.extension);
+ const url = getEmojiUrlFromName(emojiData.name, emojiData.extension);
//update in admin interface
if (previousExists && emojiData.name !== emojiData.previousName) {
- $(document).find(`.emojiAdminPreview-image[data-emoji='${emojiData.previousName}']`).css('background-image', `url('${url})'`).attr('data-emoji', `${emojiData.name}`);
+ $(document).find(`.emojiAdminPreview-image[data-emoji='${ emojiData.previousName }']`).css('background-image', `url('${ url })'`).attr('data-emoji', `${ emojiData.name }`);
} else {
- $(document).find(`.emojiAdminPreview-image[data-emoji='${emojiData.name}']`).css('background-image', `url('${url}')`);
+ $(document).find(`.emojiAdminPreview-image[data-emoji='${ emojiData.name }']`).css('background-image', `url('${ url }')`);
}
//update in picker
if (previousExists && emojiData.name !== emojiData.previousName) {
- $(document).find(`li[data-emoji='${emojiData.previousName}'] span`).css('background-image', `url('${url}')`).attr('data-emoji', `${emojiData.name}`);
- $(document).find(`li[data-emoji='${emojiData.previousName}']`).attr('data-emoji', `${emojiData.name}`).attr('class', `emoji-${emojiData.name}`);
+ $(document).find(`li[data-emoji='${ emojiData.previousName }'] span`).css('background-image', `url('${ url }')`).attr('data-emoji', `${ emojiData.name }`);
+ $(document).find(`li[data-emoji='${ emojiData.previousName }']`).attr('data-emoji', `${ emojiData.name }`).attr('class', `emoji-${ emojiData.name }`);
} else {
- $(document).find(`li[data-emoji='${emojiData.name}'] span`).css('background-image', `url('${url}')`);
+ $(document).find(`li[data-emoji='${ emojiData.name }'] span`).css('background-image', `url('${ url }')`);
}
//update in picker and opened rooms
for (key in RoomManager.openedRooms) {
if (RoomManager.openedRooms.hasOwnProperty(key)) {
- let room = RoomManager.openedRooms[key];
+ const room = RoomManager.openedRooms[key];
if (previousExists && emojiData.name !== emojiData.previousName) {
- $(room.dom).find(`span[data-emoji='${emojiData.previousName}']`).css('background-image', `url('${url}')`).attr('data-emoji', `${emojiData.name}`);
+ $(room.dom).find(`span[data-emoji='${ emojiData.previousName }']`).css('background-image', `url('${ url }')`).attr('data-emoji', `${ emojiData.name }`);
} else {
- $(room.dom).find(`span[data-emoji='${emojiData.name}']`).css('background-image', `url('${url}')`);
+ $(room.dom).find(`span[data-emoji='${ emojiData.name }']`).css('background-image', `url('${ url }')`);
}
}
}
- updateEmojiPickerList();
+ RocketChat.EmojiPicker.updateRecent();
};
Meteor.startup(() =>
Meteor.call('listEmojiCustom', (error, result) => {
RocketChat.emoji.packages.emojiCustom.emojisByCategory = { rocket: [] };
- for (let emoji of result) {
+ for (const emoji of result) {
RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket.push(emoji.name);
- RocketChat.emoji.packages.emojiCustom.list.push(`:${emoji.name}:`);
- RocketChat.emoji.list[`:${emoji.name}:`] = emoji;
- RocketChat.emoji.list[`:${emoji.name}:`].emojiPackage = 'emojiCustom';
- for (let alias of emoji['aliases']) {
- RocketChat.emoji.packages.emojiCustom.list.push(`:${alias}:`);
- RocketChat.emoji.list[`:${alias}:`] = {
+ RocketChat.emoji.packages.emojiCustom.list.push(`:${ emoji.name }:`);
+ RocketChat.emoji.list[`:${ emoji.name }:`] = emoji;
+ RocketChat.emoji.list[`:${ emoji.name }:`].emojiPackage = 'emojiCustom';
+ for (const alias of emoji['aliases']) {
+ RocketChat.emoji.packages.emojiCustom.list.push(`:${ alias }:`);
+ RocketChat.emoji.list[`:${ alias }:`] = {
emojiPackage: 'emojiCustom',
aliasOf: emoji.name
};
diff --git a/packages/rocketchat-emoji-custom/function-isSet.js b/packages/rocketchat-emoji-custom/function-isSet.js
index 9bd663ba5c08b..de7bdf3827f12 100644
--- a/packages/rocketchat-emoji-custom/function-isSet.js
+++ b/packages/rocketchat-emoji-custom/function-isSet.js
@@ -1,7 +1,7 @@
/* globals isSet:true, isSetNotNull:true */
//http://stackoverflow.com/a/26990347 function isSet() from Gajus
isSet = function(fn) {
- var value;
+ let value;
try {
value = fn();
} catch (e) {
@@ -12,7 +12,7 @@ isSet = function(fn) {
};
isSetNotNull = function(fn) {
- var value;
+ let value;
try {
value = fn();
} catch (e) {
diff --git a/packages/rocketchat-emoji-custom/package.js b/packages/rocketchat-emoji-custom/package.js
index e79b67ca85977..aae39b27fcbd4 100644
--- a/packages/rocketchat-emoji-custom/package.js
+++ b/packages/rocketchat-emoji-custom/package.js
@@ -8,12 +8,10 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'less',
'rocketchat:emoji',
'rocketchat:file',
'rocketchat:lib',
'templating',
- 'underscore',
'webapp'
]);
@@ -34,7 +32,7 @@ Package.onUse(function(api) {
'server/methods/uploadEmojiCustom.js'
], 'server');
- api.addFiles('assets/stylesheets/emojiCustomAdmin.less', 'client');
+ api.addFiles('assets/stylesheets/emojiCustomAdmin.css', 'client');
api.addFiles([
'admin/startup.js',
diff --git a/packages/rocketchat-emoji-custom/server/methods/deleteEmojiCustom.js b/packages/rocketchat-emoji-custom/server/methods/deleteEmojiCustom.js
index bcfebb41dd719..4a36eccf7d4fd 100644
--- a/packages/rocketchat-emoji-custom/server/methods/deleteEmojiCustom.js
+++ b/packages/rocketchat-emoji-custom/server/methods/deleteEmojiCustom.js
@@ -1,4 +1,4 @@
-/* globals isSetNotNull, RocketChatFileEmojiCustomInstance */
+/* globals RocketChatFileEmojiCustomInstance */
Meteor.methods({
deleteEmojiCustom(emojiID) {
let emoji = null;
@@ -9,11 +9,11 @@ Meteor.methods({
throw new Meteor.Error('not_authorized');
}
- if (!isSetNotNull(() => emoji)) {
+ if (emoji == null) {
throw new Meteor.Error('Custom_Emoji_Error_Invalid_Emoji', 'Invalid emoji', { method: 'deleteEmojiCustom' });
}
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emoji.name}.${emoji.extension}`));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emoji.name }.${ emoji.extension }`));
RocketChat.models.EmojiCustom.removeByID(emojiID);
RocketChat.Notifications.notifyLogged('deleteEmojiCustom', {emojiData: emoji});
diff --git a/packages/rocketchat-emoji-custom/server/methods/insertOrUpdateEmoji.js b/packages/rocketchat-emoji-custom/server/methods/insertOrUpdateEmoji.js
index e3e830ef3fc32..6a6d844fd268d 100644
--- a/packages/rocketchat-emoji-custom/server/methods/insertOrUpdateEmoji.js
+++ b/packages/rocketchat-emoji-custom/server/methods/insertOrUpdateEmoji.js
@@ -1,4 +1,7 @@
/* globals RocketChatFileEmojiCustomInstance */
+import _ from 'underscore';
+import s from 'underscore.string';
+
Meteor.methods({
insertOrUpdateEmoji(emojiData) {
if (!RocketChat.authz.hasPermission(this.userId, 'manage-emoji')) {
@@ -9,25 +12,22 @@ Meteor.methods({
throw new Meteor.Error('error-the-field-is-required', 'The field Name is required', { method: 'insertOrUpdateEmoji', field: 'Name' });
}
- //let nameValidation = new RegExp('^[0-9a-zA-Z-_+;.]+$');
- //let aliasValidation = new RegExp('^[0-9a-zA-Z-_+;., ]+$');
-
//allow all characters except colon, whitespace, comma, >, <, &, ", ', /, \, (, )
//more practical than allowing specific sets of characters; also allows foreign languages
- let nameValidation = /[\s,:><&"'\/\\\(\)]/;
- let aliasValidation = /[:><&"'\/\\\(\)]/;
+ const nameValidation = /[\s,:><&"'\/\\\(\)]/;
+ const aliasValidation = /[:><&\|"'\/\\\(\)]/;
//silently strip colon; this allows for uploading :emojiname: as emojiname
emojiData.name = emojiData.name.replace(/:/g, '');
emojiData.aliases = emojiData.aliases.replace(/:/g, '');
if (nameValidation.test(emojiData.name)) {
- throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.name} is not a valid name`, { method: 'insertOrUpdateEmoji', input: emojiData.name, field: 'Name' });
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${ emojiData.name } is not a valid name`, { method: 'insertOrUpdateEmoji', input: emojiData.name, field: 'Name' });
}
if (emojiData.aliases) {
if (aliasValidation.test(emojiData.aliases)) {
- throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.aliases} is not a valid alias set`, { method: 'insertOrUpdateEmoji', input: emojiData.aliases, field: 'Alias_Set' });
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${ emojiData.aliases } is not a valid alias set`, { method: 'insertOrUpdateEmoji', input: emojiData.aliases, field: 'Alias_Set' });
}
emojiData.aliases = emojiData.aliases.split(/[\s,]/);
emojiData.aliases = emojiData.aliases.filter(Boolean);
@@ -40,12 +40,12 @@ Meteor.methods({
if (emojiData._id) {
matchingResults = RocketChat.models.EmojiCustom.findByNameOrAliasExceptID(emojiData.name, emojiData._id).fetch();
- for (let alias of emojiData.aliases) {
+ for (const alias of emojiData.aliases) {
matchingResults = matchingResults.concat(RocketChat.models.EmojiCustom.findByNameOrAliasExceptID(alias, emojiData._id).fetch());
}
} else {
matchingResults = RocketChat.models.EmojiCustom.findByNameOrAlias(emojiData.name).fetch();
- for (let alias of emojiData.aliases) {
+ for (const alias of emojiData.aliases) {
matchingResults = matchingResults.concat(RocketChat.models.EmojiCustom.findByNameOrAlias(alias).fetch());
}
}
@@ -56,13 +56,13 @@ Meteor.methods({
if (!emojiData._id) {
//insert emoji
- let createEmoji = {
+ const createEmoji = {
name: emojiData.name,
aliases: emojiData.aliases,
extension: emojiData.extension
};
- let _id = RocketChat.models.EmojiCustom.create(createEmoji);
+ const _id = RocketChat.models.EmojiCustom.create(createEmoji);
RocketChat.Notifications.notifyLogged('updateEmojiCustom', {emojiData: createEmoji});
@@ -70,20 +70,20 @@ Meteor.methods({
} else {
//update emoji
if (emojiData.newFile) {
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`));
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.extension}`));
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.name }.${ emojiData.extension }`));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.name }.${ emojiData.previousExtension }`));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.previousName }.${ emojiData.extension }`));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.previousName }.${ emojiData.previousExtension }`));
RocketChat.models.EmojiCustom.setExtension(emojiData._id, emojiData.extension);
} else if (emojiData.name !== emojiData.previousName) {
- let rs = RocketChatFileEmojiCustomInstance.getFileWithReadStream(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`));
+ const rs = RocketChatFileEmojiCustomInstance.getFileWithReadStream(encodeURIComponent(`${ emojiData.previousName }.${ emojiData.previousExtension }`));
if (rs !== null) {
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
- let ws = RocketChatFileEmojiCustomInstance.createWriteStream(encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`), rs.contentType);
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.name }.${ emojiData.extension }`));
+ const ws = RocketChatFileEmojiCustomInstance.createWriteStream(encodeURIComponent(`${ emojiData.name }.${ emojiData.previousExtension }`), rs.contentType);
ws.on('end', Meteor.bindEnvironment(() =>
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`))
- ));
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.previousName }.${ emojiData.previousExtension }`))
+ ));
rs.readStream.pipe(ws);
}
}
diff --git a/packages/rocketchat-emoji-custom/server/methods/uploadEmojiCustom.js b/packages/rocketchat-emoji-custom/server/methods/uploadEmojiCustom.js
index 76da1f81e58b3..3aa1d7278b97a 100644
--- a/packages/rocketchat-emoji-custom/server/methods/uploadEmojiCustom.js
+++ b/packages/rocketchat-emoji-custom/server/methods/uploadEmojiCustom.js
@@ -7,14 +7,13 @@ Meteor.methods({
//delete aliases for notification purposes. here, it is a string rather than an array
delete emojiData.aliases;
- let file = new Buffer(binaryContent, 'binary');
+ const file = new Buffer(binaryContent, 'binary');
- let rs = RocketChatFile.bufferToStream(file);
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
- let ws = RocketChatFileEmojiCustomInstance.createWriteStream(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`), contentType);
+ const rs = RocketChatFile.bufferToStream(file);
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emojiData.name }.${ emojiData.extension }`));
+ const ws = RocketChatFileEmojiCustomInstance.createWriteStream(encodeURIComponent(`${ emojiData.name }.${ emojiData.extension }`), contentType);
ws.on('end', Meteor.bindEnvironment(() =>
- Meteor.setTimeout(() => RocketChat.Notifications.notifyLogged('updateEmojiCustom', {emojiData})
- , 500)
+ Meteor.setTimeout(() => RocketChat.Notifications.notifyLogged('updateEmojiCustom', {emojiData}), 500)
));
rs.pipe(ws);
diff --git a/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js b/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js
index 6c3845ad3d496..f1d004dfd4f45 100644
--- a/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js
+++ b/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js
@@ -14,7 +14,7 @@ class EmojiCustom extends RocketChat.models._Base {
//find
findByNameOrAlias(name, options) {
- let query = {
+ const query = {
$or: [
{name},
{aliases: name}
@@ -25,7 +25,7 @@ class EmojiCustom extends RocketChat.models._Base {
}
findByNameOrAliasExceptID(name, except, options) {
- let query = {
+ const query = {
_id: { $nin: [ except ] },
$or: [
{name},
@@ -39,7 +39,7 @@ class EmojiCustom extends RocketChat.models._Base {
//update
setName(_id, name) {
- let update = {
+ const update = {
$set: {
name
}
@@ -49,7 +49,7 @@ class EmojiCustom extends RocketChat.models._Base {
}
setAliases(_id, aliases) {
- let update = {
+ const update = {
$set: {
aliases
}
@@ -59,7 +59,7 @@ class EmojiCustom extends RocketChat.models._Base {
}
setExtension(_id, extension) {
- let update = {
+ const update = {
$set: {
extension
}
diff --git a/packages/rocketchat-emoji-custom/server/publications/fullEmojiData.js b/packages/rocketchat-emoji-custom/server/publications/fullEmojiData.js
index 040cc0da91be2..1bfe145545944 100644
--- a/packages/rocketchat-emoji-custom/server/publications/fullEmojiData.js
+++ b/packages/rocketchat-emoji-custom/server/publications/fullEmojiData.js
@@ -1,9 +1,11 @@
+import s from 'underscore.string';
+
Meteor.publish('fullEmojiData', function(filter, limit) {
if (!this.userId) {
return this.ready();
}
- let fields = {
+ const fields = {
name: 1,
aliases: 1,
extension: 1
@@ -11,14 +13,14 @@ Meteor.publish('fullEmojiData', function(filter, limit) {
filter = s.trim(filter);
- let options = {
+ const options = {
fields,
limit,
sort: { name: 1 }
};
if (filter) {
- let filterReg = new RegExp(s.escapeRegExp(filter), 'i');
+ const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
return RocketChat.models.EmojiCustom.findByNameOrAlias(filterReg, options);
}
diff --git a/packages/rocketchat-emoji-custom/server/startup/emoji-custom.js b/packages/rocketchat-emoji-custom/server/startup/emoji-custom.js
index 262a30cdfd484..595fc4f80187a 100644
--- a/packages/rocketchat-emoji-custom/server/startup/emoji-custom.js
+++ b/packages/rocketchat-emoji-custom/server/startup/emoji-custom.js
@@ -1,4 +1,6 @@
-/* globals isSetNotNull, RocketChatFileEmojiCustomInstance */
+/* globals RocketChatFileEmojiCustomInstance */
+import _ from 'underscore';
+
Meteor.startup(function() {
let storeType = 'GridFS';
@@ -6,16 +8,16 @@ Meteor.startup(function() {
storeType = RocketChat.settings.get('EmojiUpload_Storage_Type');
}
- let RocketChatStore = RocketChatFile[storeType];
+ const RocketChatStore = RocketChatFile[storeType];
- if (!isSetNotNull(() => RocketChatStore)) {
- throw new Error(`Invalid RocketChatStore type [${storeType}]`);
+ if (RocketChatStore == null) {
+ throw new Error(`Invalid RocketChatStore type [${ storeType }]`);
}
- console.log(`Using ${storeType} for custom emoji storage`.green);
+ console.log(`Using ${ storeType } for custom emoji storage`.green);
let path = '~/uploads';
- if (isSetNotNull(() => RocketChat.settings.get('EmojiUpload_FileSystemPath'))) {
+ if (RocketChat.settings.get('EmojiUpload_FileSystemPath') != null) {
if (RocketChat.settings.get('EmojiUpload_FileSystemPath').trim() !== '') {
path = RocketChat.settings.get('EmojiUpload_FileSystemPath');
}
@@ -27,7 +29,7 @@ Meteor.startup(function() {
});
return WebApp.connectHandlers.use('/emoji-custom/', Meteor.bindEnvironment(function(req, res/*, next*/) {
- let params =
+ const params =
{emoji: decodeURIComponent(req.url.replace(/^\//, '').replace(/\?.*$/, ''))};
if (_.isEmpty(params.emoji)) {
@@ -37,18 +39,18 @@ Meteor.startup(function() {
return;
}
- let file = RocketChatFileEmojiCustomInstance.getFileWithReadStream(encodeURIComponent(params.emoji));
+ const file = RocketChatFileEmojiCustomInstance.getFileWithReadStream(encodeURIComponent(params.emoji));
res.setHeader('Content-Disposition', 'inline');
- if (!isSetNotNull(() => file)) {
+ if (file == null) {
//use code from username initials renderer until file upload is complete
res.setHeader('Content-Type', 'image/svg+xml');
res.setHeader('Cache-Control', 'public, max-age=0');
res.setHeader('Expires', '-1');
res.setHeader('Last-Modified', 'Thu, 01 Jan 2015 00:00:00 GMT');
- let reqModifiedHeader = req.headers['if-modified-since'];
+ const reqModifiedHeader = req.headers['if-modified-since'];
if (reqModifiedHeader != null) {
if (reqModifiedHeader === 'Thu, 01 Jan 2015 00:00:00 GMT') {
res.writeHead(304);
@@ -57,13 +59,13 @@ Meteor.startup(function() {
}
}
- let color = '#000';
- let initials = '?';
+ const color = '#000';
+ const initials = '?';
- let svg = `
-
+ const svg = `
+
- ${initials}
+ ${ initials }
`;
@@ -73,12 +75,12 @@ Meteor.startup(function() {
}
let fileUploadDate = undefined;
- if (isSetNotNull(() => file.uploadDate)) {
+ if (file.uploadDate != null) {
fileUploadDate = file.uploadDate.toUTCString();
}
- let reqModifiedHeader = req.headers['if-modified-since'];
- if (isSetNotNull(() => reqModifiedHeader)) {
+ const reqModifiedHeader = req.headers['if-modified-since'];
+ if (reqModifiedHeader != null) {
if (reqModifiedHeader === fileUploadDate) {
res.setHeader('Last-Modified', reqModifiedHeader);
res.writeHead(304);
@@ -89,7 +91,7 @@ Meteor.startup(function() {
res.setHeader('Cache-Control', 'public, max-age=0');
res.setHeader('Expires', '-1');
- if (isSetNotNull(() => fileUploadDate)) {
+ if (fileUploadDate != null) {
res.setHeader('Last-Modified', fileUploadDate);
} else {
res.setHeader('Last-Modified', new Date().toUTCString());
diff --git a/packages/rocketchat-emoji-emojione/client/sprites.css b/packages/rocketchat-emoji-emojione/client/sprites.css
new file mode 100644
index 0000000000000..476c0ee6e4840
--- /dev/null
+++ b/packages/rocketchat-emoji-emojione/client/sprites.css
@@ -0,0 +1,7356 @@
+.emojione {
+ position: relative;
+
+ display: inline-block;
+ overflow: hidden;
+
+ width: 22px;
+ height: 22px;
+ margin: 0 0.15em;
+
+ vertical-align: middle;
+ white-space: nowrap;
+ text-indent: 100%;
+
+ background-image: url("/packages/emojione_emojione/assets/sprites/emojione.sprites.png");
+ background-repeat: no-repeat;
+ background-size: 4365.625% 4365.625%;
+
+ font-size: inherit;
+ line-height: normal;
+ image-rendering: -webkit-optimize-contrast;
+ image-rendering: optimizeQuality;
+}
+
+.emojione.big {
+ width: 44px;
+ height: 44px;
+}
+
+.emojione-0023-20e3 {
+ background-position: 2.38095% 0%;
+}
+
+.emojione-0023 {
+ background-position: 50% 66.66667%;
+}
+
+.emojione-002a-20e3 {
+ background-position: 0% 2.38095%;
+}
+
+.emojione-002a {
+ background-position: 2.38095% 2.38095%;
+}
+
+.emojione-0030-20e3 {
+ background-position: 4.7619% 0%;
+}
+
+.emojione-0030 {
+ background-position: 4.7619% 2.38095%;
+}
+
+.emojione-0031-20e3 {
+ background-position: 0% 4.7619%;
+}
+
+.emojione-0031 {
+ background-position: 2.38095% 4.7619%;
+}
+
+.emojione-0032-20e3 {
+ background-position: 4.7619% 4.7619%;
+}
+
+.emojione-0032 {
+ background-position: 7.14286% 0%;
+}
+
+.emojione-0033-20e3 {
+ background-position: 7.14286% 2.38095%;
+}
+
+.emojione-0033 {
+ background-position: 7.14286% 4.7619%;
+}
+
+.emojione-0034-20e3 {
+ background-position: 0% 7.14286%;
+}
+
+.emojione-0034 {
+ background-position: 2.38095% 7.14286%;
+}
+
+.emojione-0035-20e3 {
+ background-position: 4.7619% 7.14286%;
+}
+
+.emojione-0035 {
+ background-position: 7.14286% 7.14286%;
+}
+
+.emojione-0036-20e3 {
+ background-position: 9.52381% 0%;
+}
+
+.emojione-0036 {
+ background-position: 9.52381% 2.38095%;
+}
+
+.emojione-0037-20e3 {
+ background-position: 9.52381% 4.7619%;
+}
+
+.emojione-0037 {
+ background-position: 9.52381% 7.14286%;
+}
+
+.emojione-0038-20e3 {
+ background-position: 0% 9.52381%;
+}
+
+.emojione-0038 {
+ background-position: 2.38095% 9.52381%;
+}
+
+.emojione-0039-20e3 {
+ background-position: 4.7619% 9.52381%;
+}
+
+.emojione-0039 {
+ background-position: 7.14286% 9.52381%;
+}
+
+.emojione-00a9 {
+ background-position: 9.52381% 9.52381%;
+}
+
+.emojione-00ae {
+ background-position: 11.90476% 0%;
+}
+
+.emojione-1f004 {
+ background-position: 11.90476% 2.38095%;
+}
+
+.emojione-1f0cf {
+ background-position: 11.90476% 4.7619%;
+}
+
+.emojione-1f170 {
+ background-position: 11.90476% 7.14286%;
+}
+
+.emojione-1f171 {
+ background-position: 11.90476% 9.52381%;
+}
+
+.emojione-1f17e {
+ background-position: 0% 11.90476%;
+}
+
+.emojione-1f17f {
+ background-position: 2.38095% 11.90476%;
+}
+
+.emojione-1f18e {
+ background-position: 4.7619% 11.90476%;
+}
+
+.emojione-1f191 {
+ background-position: 7.14286% 11.90476%;
+}
+
+.emojione-1f192 {
+ background-position: 9.52381% 11.90476%;
+}
+
+.emojione-1f193 {
+ background-position: 11.90476% 11.90476%;
+}
+
+.emojione-1f194 {
+ background-position: 14.28571% 0%;
+}
+
+.emojione-1f195 {
+ background-position: 14.28571% 2.38095%;
+}
+
+.emojione-1f196 {
+ background-position: 14.28571% 4.7619%;
+}
+
+.emojione-1f197 {
+ background-position: 14.28571% 7.14286%;
+}
+
+.emojione-1f198 {
+ background-position: 14.28571% 9.52381%;
+}
+
+.emojione-1f199 {
+ background-position: 14.28571% 11.90476%;
+}
+
+.emojione-1f19a {
+ background-position: 0% 14.28571%;
+}
+
+.emojione-1f1e6-1f1e8 {
+ background-position: 2.38095% 14.28571%;
+}
+
+.emojione-1f1e6-1f1e9 {
+ background-position: 4.7619% 14.28571%;
+}
+
+.emojione-1f1e6-1f1ea {
+ background-position: 7.14286% 14.28571%;
+}
+
+.emojione-1f1e6-1f1eb {
+ background-position: 9.52381% 14.28571%;
+}
+
+.emojione-1f1e6-1f1ec {
+ background-position: 11.90476% 14.28571%;
+}
+
+.emojione-1f1e6-1f1ee {
+ background-position: 14.28571% 14.28571%;
+}
+
+.emojione-1f1e6-1f1f1 {
+ background-position: 16.66667% 0%;
+}
+
+.emojione-1f1e6-1f1f2 {
+ background-position: 16.66667% 2.38095%;
+}
+
+.emojione-1f1e6-1f1f4 {
+ background-position: 16.66667% 4.7619%;
+}
+
+.emojione-1f1e6-1f1f6 {
+ background-position: 16.66667% 7.14286%;
+}
+
+.emojione-1f1e6-1f1f7 {
+ background-position: 16.66667% 9.52381%;
+}
+
+.emojione-1f1e6-1f1f8 {
+ background-position: 16.66667% 11.90476%;
+}
+
+.emojione-1f1e6-1f1f9 {
+ background-position: 16.66667% 14.28571%;
+}
+
+.emojione-1f1e6-1f1fa {
+ background-position: 0% 16.66667%;
+}
+
+.emojione-1f1e6-1f1fc {
+ background-position: 2.38095% 16.66667%;
+}
+
+.emojione-1f1e6-1f1fd {
+ background-position: 4.7619% 16.66667%;
+}
+
+.emojione-1f1e6-1f1ff {
+ background-position: 7.14286% 16.66667%;
+}
+
+.emojione-1f1e6 {
+ background-position: 9.52381% 16.66667%;
+}
+
+.emojione-1f1e7-1f1e6 {
+ background-position: 11.90476% 16.66667%;
+}
+
+.emojione-1f1e7-1f1e7 {
+ background-position: 14.28571% 16.66667%;
+}
+
+.emojione-1f1e7-1f1e9 {
+ background-position: 16.66667% 16.66667%;
+}
+
+.emojione-1f1e7-1f1ea {
+ background-position: 19.04762% 0%;
+}
+
+.emojione-1f1e7-1f1eb {
+ background-position: 19.04762% 2.38095%;
+}
+
+.emojione-1f1e7-1f1ec {
+ background-position: 19.04762% 4.7619%;
+}
+
+.emojione-1f1e7-1f1ed {
+ background-position: 19.04762% 7.14286%;
+}
+
+.emojione-1f1e7-1f1ee {
+ background-position: 19.04762% 9.52381%;
+}
+
+.emojione-1f1e7-1f1ef {
+ background-position: 19.04762% 11.90476%;
+}
+
+.emojione-1f1e7-1f1f1 {
+ background-position: 19.04762% 14.28571%;
+}
+
+.emojione-1f1e7-1f1f2 {
+ background-position: 19.04762% 16.66667%;
+}
+
+.emojione-1f1e7-1f1f3 {
+ background-position: 0% 19.04762%;
+}
+
+.emojione-1f1e7-1f1f4 {
+ background-position: 2.38095% 19.04762%;
+}
+
+.emojione-1f1e7-1f1f6 {
+ background-position: 4.7619% 19.04762%;
+}
+
+.emojione-1f1e7-1f1f7 {
+ background-position: 7.14286% 19.04762%;
+}
+
+.emojione-1f1e7-1f1f8 {
+ background-position: 9.52381% 19.04762%;
+}
+
+.emojione-1f1e7-1f1f9 {
+ background-position: 11.90476% 19.04762%;
+}
+
+.emojione-1f1e7-1f1fb {
+ background-position: 14.28571% 19.04762%;
+}
+
+.emojione-1f1e7-1f1fc {
+ background-position: 16.66667% 19.04762%;
+}
+
+.emojione-1f1e7-1f1fe {
+ background-position: 19.04762% 19.04762%;
+}
+
+.emojione-1f1e7-1f1ff {
+ background-position: 21.42857% 0%;
+}
+
+.emojione-1f1e7 {
+ background-position: 21.42857% 2.38095%;
+}
+
+.emojione-1f1e8-1f1e6 {
+ background-position: 21.42857% 4.7619%;
+}
+
+.emojione-1f1e8-1f1e8 {
+ background-position: 21.42857% 7.14286%;
+}
+
+.emojione-1f1e8-1f1e9 {
+ background-position: 21.42857% 9.52381%;
+}
+
+.emojione-1f1e8-1f1eb {
+ background-position: 21.42857% 11.90476%;
+}
+
+.emojione-1f1e8-1f1ec {
+ background-position: 21.42857% 14.28571%;
+}
+
+.emojione-1f1e8-1f1ed {
+ background-position: 21.42857% 16.66667%;
+}
+
+.emojione-1f1e8-1f1ee {
+ background-position: 21.42857% 19.04762%;
+}
+
+.emojione-1f1e8-1f1f0 {
+ background-position: 0% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f1 {
+ background-position: 2.38095% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f2 {
+ background-position: 4.7619% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f3 {
+ background-position: 7.14286% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f4 {
+ background-position: 9.52381% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f5 {
+ background-position: 11.90476% 21.42857%;
+}
+
+.emojione-1f1e8-1f1f7 {
+ background-position: 14.28571% 21.42857%;
+}
+
+.emojione-1f1e8-1f1fa {
+ background-position: 16.66667% 21.42857%;
+}
+
+.emojione-1f1e8-1f1fb {
+ background-position: 19.04762% 21.42857%;
+}
+
+.emojione-1f1e8-1f1fc {
+ background-position: 21.42857% 21.42857%;
+}
+
+.emojione-1f1e8-1f1fd {
+ background-position: 23.80952% 0%;
+}
+
+.emojione-1f1e8-1f1fe {
+ background-position: 23.80952% 2.38095%;
+}
+
+.emojione-1f1e8-1f1ff {
+ background-position: 23.80952% 4.7619%;
+}
+
+.emojione-1f1e8 {
+ background-position: 23.80952% 7.14286%;
+}
+
+.emojione-1f1e9-1f1ea {
+ background-position: 23.80952% 9.52381%;
+}
+
+.emojione-1f1e9-1f1ec {
+ background-position: 23.80952% 11.90476%;
+}
+
+.emojione-1f1e9-1f1ef {
+ background-position: 23.80952% 14.28571%;
+}
+
+.emojione-1f1e9-1f1f0 {
+ background-position: 23.80952% 16.66667%;
+}
+
+.emojione-1f1e9-1f1f2 {
+ background-position: 23.80952% 19.04762%;
+}
+
+.emojione-1f1e9-1f1f4 {
+ background-position: 23.80952% 21.42857%;
+}
+
+.emojione-1f1e9-1f1ff {
+ background-position: 0% 23.80952%;
+}
+
+.emojione-1f1e9 {
+ background-position: 2.38095% 23.80952%;
+}
+
+.emojione-1f1ea-1f1e6 {
+ background-position: 4.7619% 23.80952%;
+}
+
+.emojione-1f1ea-1f1e8 {
+ background-position: 7.14286% 23.80952%;
+}
+
+.emojione-1f1ea-1f1ea {
+ background-position: 9.52381% 23.80952%;
+}
+
+.emojione-1f1ea-1f1ec {
+ background-position: 11.90476% 23.80952%;
+}
+
+.emojione-1f1ea-1f1ed {
+ background-position: 14.28571% 23.80952%;
+}
+
+.emojione-1f1ea-1f1f7 {
+ background-position: 16.66667% 23.80952%;
+}
+
+.emojione-1f1ea-1f1f8 {
+ background-position: 19.04762% 23.80952%;
+}
+
+.emojione-1f1ea-1f1f9 {
+ background-position: 21.42857% 23.80952%;
+}
+
+.emojione-1f1ea-1f1fa {
+ background-position: 23.80952% 23.80952%;
+}
+
+.emojione-1f1ea {
+ background-position: 26.19048% 0%;
+}
+
+.emojione-1f1eb-1f1ee {
+ background-position: 26.19048% 2.38095%;
+}
+
+.emojione-1f1eb-1f1ef {
+ background-position: 26.19048% 4.7619%;
+}
+
+.emojione-1f1eb-1f1f0 {
+ background-position: 26.19048% 7.14286%;
+}
+
+.emojione-1f1eb-1f1f2 {
+ background-position: 26.19048% 9.52381%;
+}
+
+.emojione-1f1eb-1f1f4 {
+ background-position: 26.19048% 11.90476%;
+}
+
+.emojione-1f1eb-1f1f7 {
+ background-position: 26.19048% 14.28571%;
+}
+
+.emojione-1f1eb {
+ background-position: 26.19048% 16.66667%;
+}
+
+.emojione-1f1ec-1f1e6 {
+ background-position: 26.19048% 19.04762%;
+}
+
+.emojione-1f1ec-1f1e7 {
+ background-position: 26.19048% 21.42857%;
+}
+
+.emojione-1f1ec-1f1e9 {
+ background-position: 26.19048% 23.80952%;
+}
+
+.emojione-1f1ec-1f1ea {
+ background-position: 0% 26.19048%;
+}
+
+.emojione-1f1ec-1f1eb {
+ background-position: 2.38095% 26.19048%;
+}
+
+.emojione-1f1ec-1f1ec {
+ background-position: 4.7619% 26.19048%;
+}
+
+.emojione-1f1ec-1f1ed {
+ background-position: 7.14286% 26.19048%;
+}
+
+.emojione-1f1ec-1f1ee {
+ background-position: 9.52381% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f1 {
+ background-position: 11.90476% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f2 {
+ background-position: 14.28571% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f3 {
+ background-position: 16.66667% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f5 {
+ background-position: 19.04762% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f6 {
+ background-position: 21.42857% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f7 {
+ background-position: 23.80952% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f8 {
+ background-position: 26.19048% 26.19048%;
+}
+
+.emojione-1f1ec-1f1f9 {
+ background-position: 28.57143% 0%;
+}
+
+.emojione-1f1ec-1f1fa {
+ background-position: 28.57143% 2.38095%;
+}
+
+.emojione-1f1ec-1f1fc {
+ background-position: 28.57143% 4.7619%;
+}
+
+.emojione-1f1ec-1f1fe {
+ background-position: 28.57143% 7.14286%;
+}
+
+.emojione-1f1ec {
+ background-position: 28.57143% 9.52381%;
+}
+
+.emojione-1f1ed-1f1f0 {
+ background-position: 28.57143% 11.90476%;
+}
+
+.emojione-1f1ed-1f1f2 {
+ background-position: 28.57143% 14.28571%;
+}
+
+.emojione-1f1ed-1f1f3 {
+ background-position: 28.57143% 16.66667%;
+}
+
+.emojione-1f1ed-1f1f7 {
+ background-position: 28.57143% 19.04762%;
+}
+
+.emojione-1f1ed-1f1f9 {
+ background-position: 28.57143% 21.42857%;
+}
+
+.emojione-1f1ed-1f1fa {
+ background-position: 28.57143% 23.80952%;
+}
+
+.emojione-1f1ed {
+ background-position: 28.57143% 26.19048%;
+}
+
+.emojione-1f1ee-1f1e8 {
+ background-position: 0% 28.57143%;
+}
+
+.emojione-1f1ee-1f1e9 {
+ background-position: 2.38095% 28.57143%;
+}
+
+.emojione-1f1ee-1f1ea {
+ background-position: 4.7619% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f1 {
+ background-position: 7.14286% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f2 {
+ background-position: 9.52381% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f3 {
+ background-position: 11.90476% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f4 {
+ background-position: 14.28571% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f6 {
+ background-position: 16.66667% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f7 {
+ background-position: 19.04762% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f8 {
+ background-position: 21.42857% 28.57143%;
+}
+
+.emojione-1f1ee-1f1f9 {
+ background-position: 23.80952% 28.57143%;
+}
+
+.emojione-1f1ee {
+ background-position: 26.19048% 28.57143%;
+}
+
+.emojione-1f1ef-1f1ea {
+ background-position: 28.57143% 28.57143%;
+}
+
+.emojione-1f1ef-1f1f2 {
+ background-position: 30.95238% 0%;
+}
+
+.emojione-1f1ef-1f1f4 {
+ background-position: 30.95238% 2.38095%;
+}
+
+.emojione-1f1ef-1f1f5 {
+ background-position: 30.95238% 4.7619%;
+}
+
+.emojione-1f1ef {
+ background-position: 30.95238% 7.14286%;
+}
+
+.emojione-1f1f0-1f1ea {
+ background-position: 30.95238% 9.52381%;
+}
+
+.emojione-1f1f0-1f1ec {
+ background-position: 30.95238% 11.90476%;
+}
+
+.emojione-1f1f0-1f1ed {
+ background-position: 30.95238% 14.28571%;
+}
+
+.emojione-1f1f0-1f1ee {
+ background-position: 30.95238% 16.66667%;
+}
+
+.emojione-1f1f0-1f1f2 {
+ background-position: 30.95238% 19.04762%;
+}
+
+.emojione-1f1f0-1f1f3 {
+ background-position: 30.95238% 21.42857%;
+}
+
+.emojione-1f1f0-1f1f5 {
+ background-position: 30.95238% 23.80952%;
+}
+
+.emojione-1f1f0-1f1f7 {
+ background-position: 30.95238% 26.19048%;
+}
+
+.emojione-1f1f0-1f1fc {
+ background-position: 30.95238% 28.57143%;
+}
+
+.emojione-1f1f0-1f1fe {
+ background-position: 0% 30.95238%;
+}
+
+.emojione-1f1f0-1f1ff {
+ background-position: 2.38095% 30.95238%;
+}
+
+.emojione-1f1f0 {
+ background-position: 4.7619% 30.95238%;
+}
+
+.emojione-1f1f1-1f1e6 {
+ background-position: 7.14286% 30.95238%;
+}
+
+.emojione-1f1f1-1f1e7 {
+ background-position: 9.52381% 30.95238%;
+}
+
+.emojione-1f1f1-1f1e8 {
+ background-position: 11.90476% 30.95238%;
+}
+
+.emojione-1f1f1-1f1ee {
+ background-position: 14.28571% 30.95238%;
+}
+
+.emojione-1f1f1-1f1f0 {
+ background-position: 16.66667% 30.95238%;
+}
+
+.emojione-1f1f1-1f1f7 {
+ background-position: 19.04762% 30.95238%;
+}
+
+.emojione-1f1f1-1f1f8 {
+ background-position: 21.42857% 30.95238%;
+}
+
+.emojione-1f1f1-1f1f9 {
+ background-position: 23.80952% 30.95238%;
+}
+
+.emojione-1f1f1-1f1fa {
+ background-position: 26.19048% 30.95238%;
+}
+
+.emojione-1f1f1-1f1fb {
+ background-position: 28.57143% 30.95238%;
+}
+
+.emojione-1f1f1-1f1fe {
+ background-position: 30.95238% 30.95238%;
+}
+
+.emojione-1f1f1 {
+ background-position: 33.33333% 0%;
+}
+
+.emojione-1f1f2-1f1e6 {
+ background-position: 33.33333% 2.38095%;
+}
+
+.emojione-1f1f2-1f1e8 {
+ background-position: 33.33333% 4.7619%;
+}
+
+.emojione-1f1f2-1f1e9 {
+ background-position: 33.33333% 7.14286%;
+}
+
+.emojione-1f1f2-1f1ea {
+ background-position: 33.33333% 9.52381%;
+}
+
+.emojione-1f1f2-1f1eb {
+ background-position: 33.33333% 11.90476%;
+}
+
+.emojione-1f1f2-1f1ec {
+ background-position: 33.33333% 14.28571%;
+}
+
+.emojione-1f1f2-1f1ed {
+ background-position: 33.33333% 16.66667%;
+}
+
+.emojione-1f1f2-1f1f0 {
+ background-position: 33.33333% 19.04762%;
+}
+
+.emojione-1f1f2-1f1f1 {
+ background-position: 33.33333% 21.42857%;
+}
+
+.emojione-1f1f2-1f1f2 {
+ background-position: 33.33333% 23.80952%;
+}
+
+.emojione-1f1f2-1f1f3 {
+ background-position: 33.33333% 26.19048%;
+}
+
+.emojione-1f1f2-1f1f4 {
+ background-position: 33.33333% 28.57143%;
+}
+
+.emojione-1f1f2-1f1f5 {
+ background-position: 33.33333% 30.95238%;
+}
+
+.emojione-1f1f2-1f1f6 {
+ background-position: 0% 33.33333%;
+}
+
+.emojione-1f1f2-1f1f7 {
+ background-position: 2.38095% 33.33333%;
+}
+
+.emojione-1f1f2-1f1f8 {
+ background-position: 4.7619% 33.33333%;
+}
+
+.emojione-1f1f2-1f1f9 {
+ background-position: 7.14286% 33.33333%;
+}
+
+.emojione-1f1f2-1f1fa {
+ background-position: 9.52381% 33.33333%;
+}
+
+.emojione-1f1f2-1f1fb {
+ background-position: 11.90476% 33.33333%;
+}
+
+.emojione-1f1f2-1f1fc {
+ background-position: 14.28571% 33.33333%;
+}
+
+.emojione-1f1f2-1f1fd {
+ background-position: 16.66667% 33.33333%;
+}
+
+.emojione-1f1f2-1f1fe {
+ background-position: 19.04762% 33.33333%;
+}
+
+.emojione-1f1f2-1f1ff {
+ background-position: 21.42857% 33.33333%;
+}
+
+.emojione-1f1f2 {
+ background-position: 23.80952% 33.33333%;
+}
+
+.emojione-1f1f3-1f1e6 {
+ background-position: 26.19048% 33.33333%;
+}
+
+.emojione-1f1f3-1f1e8 {
+ background-position: 28.57143% 33.33333%;
+}
+
+.emojione-1f1f3-1f1ea {
+ background-position: 30.95238% 33.33333%;
+}
+
+.emojione-1f1f3-1f1eb {
+ background-position: 33.33333% 33.33333%;
+}
+
+.emojione-1f1f3-1f1ec {
+ background-position: 35.71429% 0%;
+}
+
+.emojione-1f1f3-1f1ee {
+ background-position: 35.71429% 2.38095%;
+}
+
+.emojione-1f1f3-1f1f1 {
+ background-position: 35.71429% 4.7619%;
+}
+
+.emojione-1f1f3-1f1f4 {
+ background-position: 35.71429% 7.14286%;
+}
+
+.emojione-1f1f3-1f1f5 {
+ background-position: 35.71429% 9.52381%;
+}
+
+.emojione-1f1f3-1f1f7 {
+ background-position: 35.71429% 11.90476%;
+}
+
+.emojione-1f1f3-1f1fa {
+ background-position: 35.71429% 14.28571%;
+}
+
+.emojione-1f1f3-1f1ff {
+ background-position: 35.71429% 16.66667%;
+}
+
+.emojione-1f1f3 {
+ background-position: 35.71429% 19.04762%;
+}
+
+.emojione-1f1f4-1f1f2 {
+ background-position: 35.71429% 21.42857%;
+}
+
+.emojione-1f1f4 {
+ background-position: 35.71429% 23.80952%;
+}
+
+.emojione-1f1f5-1f1e6 {
+ background-position: 35.71429% 26.19048%;
+}
+
+.emojione-1f1f5-1f1ea {
+ background-position: 35.71429% 28.57143%;
+}
+
+.emojione-1f1f5-1f1eb {
+ background-position: 35.71429% 30.95238%;
+}
+
+.emojione-1f1f5-1f1ec {
+ background-position: 35.71429% 33.33333%;
+}
+
+.emojione-1f1f5-1f1ed {
+ background-position: 0% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f0 {
+ background-position: 2.38095% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f1 {
+ background-position: 4.7619% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f2 {
+ background-position: 7.14286% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f3 {
+ background-position: 9.52381% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f7 {
+ background-position: 11.90476% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f8 {
+ background-position: 14.28571% 35.71429%;
+}
+
+.emojione-1f1f5-1f1f9 {
+ background-position: 16.66667% 35.71429%;
+}
+
+.emojione-1f1f5-1f1fc {
+ background-position: 19.04762% 35.71429%;
+}
+
+.emojione-1f1f5-1f1fe {
+ background-position: 21.42857% 35.71429%;
+}
+
+.emojione-1f1f5 {
+ background-position: 23.80952% 35.71429%;
+}
+
+.emojione-1f1f6-1f1e6 {
+ background-position: 26.19048% 35.71429%;
+}
+
+.emojione-1f1f6 {
+ background-position: 28.57143% 35.71429%;
+}
+
+.emojione-1f1f7-1f1ea {
+ background-position: 30.95238% 35.71429%;
+}
+
+.emojione-1f1f7-1f1f4 {
+ background-position: 33.33333% 35.71429%;
+}
+
+.emojione-1f1f7-1f1f8 {
+ background-position: 35.71429% 35.71429%;
+}
+
+.emojione-1f1f7-1f1fa {
+ background-position: 38.09524% 0%;
+}
+
+.emojione-1f1f7-1f1fc {
+ background-position: 38.09524% 2.38095%;
+}
+
+.emojione-1f1f7 {
+ background-position: 38.09524% 4.7619%;
+}
+
+.emojione-1f1f8-1f1e6 {
+ background-position: 38.09524% 7.14286%;
+}
+
+.emojione-1f1f8-1f1e7 {
+ background-position: 38.09524% 9.52381%;
+}
+
+.emojione-1f1f8-1f1e8 {
+ background-position: 38.09524% 11.90476%;
+}
+
+.emojione-1f1f8-1f1e9 {
+ background-position: 38.09524% 14.28571%;
+}
+
+.emojione-1f1f8-1f1ea {
+ background-position: 38.09524% 16.66667%;
+}
+
+.emojione-1f1f8-1f1ec {
+ background-position: 38.09524% 19.04762%;
+}
+
+.emojione-1f1f8-1f1ed {
+ background-position: 38.09524% 21.42857%;
+}
+
+.emojione-1f1f8-1f1ee {
+ background-position: 38.09524% 23.80952%;
+}
+
+.emojione-1f1f8-1f1ef {
+ background-position: 38.09524% 26.19048%;
+}
+
+.emojione-1f1f8-1f1f0 {
+ background-position: 38.09524% 28.57143%;
+}
+
+.emojione-1f1f8-1f1f1 {
+ background-position: 38.09524% 30.95238%;
+}
+
+.emojione-1f1f8-1f1f2 {
+ background-position: 38.09524% 33.33333%;
+}
+
+.emojione-1f1f8-1f1f3 {
+ background-position: 38.09524% 35.71429%;
+}
+
+.emojione-1f1f8-1f1f4 {
+ background-position: 0% 38.09524%;
+}
+
+.emojione-1f1f8-1f1f7 {
+ background-position: 2.38095% 38.09524%;
+}
+
+.emojione-1f1f8-1f1f8 {
+ background-position: 4.7619% 38.09524%;
+}
+
+.emojione-1f1f8-1f1f9 {
+ background-position: 7.14286% 38.09524%;
+}
+
+.emojione-1f1f8-1f1fb {
+ background-position: 9.52381% 38.09524%;
+}
+
+.emojione-1f1f8-1f1fd {
+ background-position: 11.90476% 38.09524%;
+}
+
+.emojione-1f1f8-1f1fe {
+ background-position: 14.28571% 38.09524%;
+}
+
+.emojione-1f1f8-1f1ff {
+ background-position: 16.66667% 38.09524%;
+}
+
+.emojione-1f1f8 {
+ background-position: 19.04762% 38.09524%;
+}
+
+.emojione-1f1f9-1f1e6 {
+ background-position: 21.42857% 38.09524%;
+}
+
+.emojione-1f1f9-1f1e8 {
+ background-position: 23.80952% 38.09524%;
+}
+
+.emojione-1f1f9-1f1e9 {
+ background-position: 26.19048% 38.09524%;
+}
+
+.emojione-1f1f9-1f1eb {
+ background-position: 28.57143% 38.09524%;
+}
+
+.emojione-1f1f9-1f1ec {
+ background-position: 30.95238% 38.09524%;
+}
+
+.emojione-1f1f9-1f1ed {
+ background-position: 33.33333% 38.09524%;
+}
+
+.emojione-1f1f9-1f1ef {
+ background-position: 35.71429% 38.09524%;
+}
+
+.emojione-1f1f9-1f1f0 {
+ background-position: 38.09524% 38.09524%;
+}
+
+.emojione-1f1f9-1f1f1 {
+ background-position: 40.47619% 0%;
+}
+
+.emojione-1f1f9-1f1f2 {
+ background-position: 40.47619% 2.38095%;
+}
+
+.emojione-1f1f9-1f1f3 {
+ background-position: 40.47619% 4.7619%;
+}
+
+.emojione-1f1f9-1f1f4 {
+ background-position: 40.47619% 7.14286%;
+}
+
+.emojione-1f1f9-1f1f7 {
+ background-position: 40.47619% 9.52381%;
+}
+
+.emojione-1f1f9-1f1f9 {
+ background-position: 40.47619% 11.90476%;
+}
+
+.emojione-1f1f9-1f1fb {
+ background-position: 40.47619% 14.28571%;
+}
+
+.emojione-1f1f9-1f1fc {
+ background-position: 40.47619% 16.66667%;
+}
+
+.emojione-1f1f9-1f1ff {
+ background-position: 40.47619% 19.04762%;
+}
+
+.emojione-1f1f9 {
+ background-position: 40.47619% 21.42857%;
+}
+
+.emojione-1f1fa-1f1e6 {
+ background-position: 40.47619% 23.80952%;
+}
+
+.emojione-1f1fa-1f1ec {
+ background-position: 40.47619% 26.19048%;
+}
+
+.emojione-1f1fa-1f1f2 {
+ background-position: 40.47619% 28.57143%;
+}
+
+.emojione-1f1fa-1f1f8 {
+ background-position: 40.47619% 30.95238%;
+}
+
+.emojione-1f1fa-1f1fe {
+ background-position: 40.47619% 33.33333%;
+}
+
+.emojione-1f1fa-1f1ff {
+ background-position: 40.47619% 35.71429%;
+}
+
+.emojione-1f1fa {
+ background-position: 40.47619% 38.09524%;
+}
+
+.emojione-1f1fb-1f1e6 {
+ background-position: 0% 40.47619%;
+}
+
+.emojione-1f1fb-1f1e8 {
+ background-position: 2.38095% 40.47619%;
+}
+
+.emojione-1f1fb-1f1ea {
+ background-position: 4.7619% 40.47619%;
+}
+
+.emojione-1f1fb-1f1ec {
+ background-position: 7.14286% 40.47619%;
+}
+
+.emojione-1f1fb-1f1ee {
+ background-position: 9.52381% 40.47619%;
+}
+
+.emojione-1f1fb-1f1f3 {
+ background-position: 11.90476% 40.47619%;
+}
+
+.emojione-1f1fb-1f1fa {
+ background-position: 14.28571% 40.47619%;
+}
+
+.emojione-1f1fb {
+ background-position: 16.66667% 40.47619%;
+}
+
+.emojione-1f1fc-1f1eb {
+ background-position: 19.04762% 40.47619%;
+}
+
+.emojione-1f1fc-1f1f8 {
+ background-position: 21.42857% 40.47619%;
+}
+
+.emojione-1f1fc {
+ background-position: 23.80952% 40.47619%;
+}
+
+.emojione-1f1fd-1f1f0 {
+ background-position: 26.19048% 40.47619%;
+}
+
+.emojione-1f1fd {
+ background-position: 28.57143% 40.47619%;
+}
+
+.emojione-1f1fe-1f1ea {
+ background-position: 30.95238% 40.47619%;
+}
+
+.emojione-1f1fe-1f1f9 {
+ background-position: 33.33333% 40.47619%;
+}
+
+.emojione-1f1fe {
+ background-position: 35.71429% 40.47619%;
+}
+
+.emojione-1f1ff-1f1e6 {
+ background-position: 38.09524% 40.47619%;
+}
+
+.emojione-1f1ff-1f1f2 {
+ background-position: 40.47619% 40.47619%;
+}
+
+.emojione-1f1ff-1f1fc {
+ background-position: 42.85714% 0%;
+}
+
+.emojione-1f1ff {
+ background-position: 42.85714% 2.38095%;
+}
+
+.emojione-1f201 {
+ background-position: 42.85714% 4.7619%;
+}
+
+.emojione-1f202 {
+ background-position: 42.85714% 7.14286%;
+}
+
+.emojione-1f21a {
+ background-position: 42.85714% 9.52381%;
+}
+
+.emojione-1f22f {
+ background-position: 42.85714% 11.90476%;
+}
+
+.emojione-1f232 {
+ background-position: 42.85714% 14.28571%;
+}
+
+.emojione-1f233 {
+ background-position: 42.85714% 16.66667%;
+}
+
+.emojione-1f234 {
+ background-position: 42.85714% 19.04762%;
+}
+
+.emojione-1f235 {
+ background-position: 42.85714% 21.42857%;
+}
+
+.emojione-1f236 {
+ background-position: 42.85714% 23.80952%;
+}
+
+.emojione-1f237 {
+ background-position: 42.85714% 26.19048%;
+}
+
+.emojione-1f238 {
+ background-position: 42.85714% 28.57143%;
+}
+
+.emojione-1f239 {
+ background-position: 42.85714% 30.95238%;
+}
+
+.emojione-1f23a {
+ background-position: 42.85714% 33.33333%;
+}
+
+.emojione-1f250 {
+ background-position: 42.85714% 35.71429%;
+}
+
+.emojione-1f251 {
+ background-position: 42.85714% 38.09524%;
+}
+
+.emojione-1f300 {
+ background-position: 42.85714% 40.47619%;
+}
+
+.emojione-1f301 {
+ background-position: 0% 42.85714%;
+}
+
+.emojione-1f302 {
+ background-position: 2.38095% 42.85714%;
+}
+
+.emojione-1f303 {
+ background-position: 4.7619% 42.85714%;
+}
+
+.emojione-1f304 {
+ background-position: 7.14286% 42.85714%;
+}
+
+.emojione-1f305 {
+ background-position: 9.52381% 42.85714%;
+}
+
+.emojione-1f306 {
+ background-position: 11.90476% 42.85714%;
+}
+
+.emojione-1f307 {
+ background-position: 14.28571% 42.85714%;
+}
+
+.emojione-1f308 {
+ background-position: 16.66667% 42.85714%;
+}
+
+.emojione-1f309 {
+ background-position: 19.04762% 42.85714%;
+}
+
+.emojione-1f30a {
+ background-position: 21.42857% 42.85714%;
+}
+
+.emojione-1f30b {
+ background-position: 23.80952% 42.85714%;
+}
+
+.emojione-1f30c {
+ background-position: 26.19048% 42.85714%;
+}
+
+.emojione-1f30d {
+ background-position: 28.57143% 42.85714%;
+}
+
+.emojione-1f30e {
+ background-position: 30.95238% 42.85714%;
+}
+
+.emojione-1f30f {
+ background-position: 33.33333% 42.85714%;
+}
+
+.emojione-1f310 {
+ background-position: 35.71429% 42.85714%;
+}
+
+.emojione-1f311 {
+ background-position: 38.09524% 42.85714%;
+}
+
+.emojione-1f312 {
+ background-position: 40.47619% 42.85714%;
+}
+
+.emojione-1f313 {
+ background-position: 42.85714% 42.85714%;
+}
+
+.emojione-1f314 {
+ background-position: 45.2381% 0%;
+}
+
+.emojione-1f315 {
+ background-position: 45.2381% 2.38095%;
+}
+
+.emojione-1f316 {
+ background-position: 45.2381% 4.7619%;
+}
+
+.emojione-1f317 {
+ background-position: 45.2381% 7.14286%;
+}
+
+.emojione-1f318 {
+ background-position: 45.2381% 9.52381%;
+}
+
+.emojione-1f319 {
+ background-position: 45.2381% 11.90476%;
+}
+
+.emojione-1f31a {
+ background-position: 45.2381% 14.28571%;
+}
+
+.emojione-1f31b {
+ background-position: 45.2381% 16.66667%;
+}
+
+.emojione-1f31c {
+ background-position: 45.2381% 19.04762%;
+}
+
+.emojione-1f31d {
+ background-position: 45.2381% 21.42857%;
+}
+
+.emojione-1f31e {
+ background-position: 45.2381% 23.80952%;
+}
+
+.emojione-1f31f {
+ background-position: 45.2381% 26.19048%;
+}
+
+.emojione-1f320 {
+ background-position: 45.2381% 28.57143%;
+}
+
+.emojione-1f321 {
+ background-position: 45.2381% 30.95238%;
+}
+
+.emojione-1f324 {
+ background-position: 45.2381% 33.33333%;
+}
+
+.emojione-1f325 {
+ background-position: 45.2381% 35.71429%;
+}
+
+.emojione-1f326 {
+ background-position: 45.2381% 38.09524%;
+}
+
+.emojione-1f327 {
+ background-position: 45.2381% 40.47619%;
+}
+
+.emojione-1f328 {
+ background-position: 45.2381% 42.85714%;
+}
+
+.emojione-1f329 {
+ background-position: 0% 45.2381%;
+}
+
+.emojione-1f32a {
+ background-position: 2.38095% 45.2381%;
+}
+
+.emojione-1f32b {
+ background-position: 4.7619% 45.2381%;
+}
+
+.emojione-1f32c {
+ background-position: 7.14286% 45.2381%;
+}
+
+.emojione-1f32d {
+ background-position: 9.52381% 45.2381%;
+}
+
+.emojione-1f32e {
+ background-position: 11.90476% 45.2381%;
+}
+
+.emojione-1f32f {
+ background-position: 14.28571% 45.2381%;
+}
+
+.emojione-1f330 {
+ background-position: 16.66667% 45.2381%;
+}
+
+.emojione-1f331 {
+ background-position: 19.04762% 45.2381%;
+}
+
+.emojione-1f332 {
+ background-position: 21.42857% 45.2381%;
+}
+
+.emojione-1f333 {
+ background-position: 23.80952% 45.2381%;
+}
+
+.emojione-1f334 {
+ background-position: 26.19048% 45.2381%;
+}
+
+.emojione-1f335 {
+ background-position: 28.57143% 45.2381%;
+}
+
+.emojione-1f336 {
+ background-position: 30.95238% 45.2381%;
+}
+
+.emojione-1f337 {
+ background-position: 33.33333% 45.2381%;
+}
+
+.emojione-1f338 {
+ background-position: 35.71429% 45.2381%;
+}
+
+.emojione-1f339 {
+ background-position: 38.09524% 45.2381%;
+}
+
+.emojione-1f33a {
+ background-position: 40.47619% 45.2381%;
+}
+
+.emojione-1f33b {
+ background-position: 42.85714% 45.2381%;
+}
+
+.emojione-1f33c {
+ background-position: 45.2381% 45.2381%;
+}
+
+.emojione-1f33d {
+ background-position: 47.61905% 0%;
+}
+
+.emojione-1f33e {
+ background-position: 47.61905% 2.38095%;
+}
+
+.emojione-1f33f {
+ background-position: 47.61905% 4.7619%;
+}
+
+.emojione-1f340 {
+ background-position: 47.61905% 7.14286%;
+}
+
+.emojione-1f341 {
+ background-position: 47.61905% 9.52381%;
+}
+
+.emojione-1f342 {
+ background-position: 47.61905% 11.90476%;
+}
+
+.emojione-1f343 {
+ background-position: 47.61905% 14.28571%;
+}
+
+.emojione-1f344 {
+ background-position: 47.61905% 16.66667%;
+}
+
+.emojione-1f345 {
+ background-position: 47.61905% 19.04762%;
+}
+
+.emojione-1f346 {
+ background-position: 47.61905% 21.42857%;
+}
+
+.emojione-1f347 {
+ background-position: 47.61905% 23.80952%;
+}
+
+.emojione-1f348 {
+ background-position: 47.61905% 26.19048%;
+}
+
+.emojione-1f349 {
+ background-position: 47.61905% 28.57143%;
+}
+
+.emojione-1f34a {
+ background-position: 47.61905% 30.95238%;
+}
+
+.emojione-1f34b {
+ background-position: 47.61905% 33.33333%;
+}
+
+.emojione-1f34c {
+ background-position: 47.61905% 35.71429%;
+}
+
+.emojione-1f34d {
+ background-position: 47.61905% 38.09524%;
+}
+
+.emojione-1f34e {
+ background-position: 47.61905% 40.47619%;
+}
+
+.emojione-1f34f {
+ background-position: 47.61905% 42.85714%;
+}
+
+.emojione-1f350 {
+ background-position: 47.61905% 45.2381%;
+}
+
+.emojione-1f351 {
+ background-position: 0% 47.61905%;
+}
+
+.emojione-1f352 {
+ background-position: 2.38095% 47.61905%;
+}
+
+.emojione-1f353 {
+ background-position: 4.7619% 47.61905%;
+}
+
+.emojione-1f354 {
+ background-position: 7.14286% 47.61905%;
+}
+
+.emojione-1f355 {
+ background-position: 9.52381% 47.61905%;
+}
+
+.emojione-1f356 {
+ background-position: 11.90476% 47.61905%;
+}
+
+.emojione-1f357 {
+ background-position: 14.28571% 47.61905%;
+}
+
+.emojione-1f358 {
+ background-position: 16.66667% 47.61905%;
+}
+
+.emojione-1f359 {
+ background-position: 19.04762% 47.61905%;
+}
+
+.emojione-1f35a {
+ background-position: 21.42857% 47.61905%;
+}
+
+.emojione-1f35b {
+ background-position: 23.80952% 47.61905%;
+}
+
+.emojione-1f35c {
+ background-position: 26.19048% 47.61905%;
+}
+
+.emojione-1f35d {
+ background-position: 28.57143% 47.61905%;
+}
+
+.emojione-1f35e {
+ background-position: 30.95238% 47.61905%;
+}
+
+.emojione-1f35f {
+ background-position: 33.33333% 47.61905%;
+}
+
+.emojione-1f360 {
+ background-position: 35.71429% 47.61905%;
+}
+
+.emojione-1f361 {
+ background-position: 38.09524% 47.61905%;
+}
+
+.emojione-1f362 {
+ background-position: 40.47619% 47.61905%;
+}
+
+.emojione-1f363 {
+ background-position: 42.85714% 47.61905%;
+}
+
+.emojione-1f364 {
+ background-position: 45.2381% 47.61905%;
+}
+
+.emojione-1f365 {
+ background-position: 47.61905% 47.61905%;
+}
+
+.emojione-1f366 {
+ background-position: 50% 0%;
+}
+
+.emojione-1f367 {
+ background-position: 50% 2.38095%;
+}
+
+.emojione-1f368 {
+ background-position: 50% 4.7619%;
+}
+
+.emojione-1f369 {
+ background-position: 50% 7.14286%;
+}
+
+.emojione-1f36a {
+ background-position: 50% 9.52381%;
+}
+
+.emojione-1f36b {
+ background-position: 50% 11.90476%;
+}
+
+.emojione-1f36c {
+ background-position: 50% 14.28571%;
+}
+
+.emojione-1f36d {
+ background-position: 50% 16.66667%;
+}
+
+.emojione-1f36e {
+ background-position: 50% 19.04762%;
+}
+
+.emojione-1f36f {
+ background-position: 50% 21.42857%;
+}
+
+.emojione-1f370 {
+ background-position: 50% 23.80952%;
+}
+
+.emojione-1f371 {
+ background-position: 50% 26.19048%;
+}
+
+.emojione-1f372 {
+ background-position: 50% 28.57143%;
+}
+
+.emojione-1f373 {
+ background-position: 50% 30.95238%;
+}
+
+.emojione-1f374 {
+ background-position: 50% 33.33333%;
+}
+
+.emojione-1f375 {
+ background-position: 50% 35.71429%;
+}
+
+.emojione-1f376 {
+ background-position: 50% 38.09524%;
+}
+
+.emojione-1f377 {
+ background-position: 50% 40.47619%;
+}
+
+.emojione-1f378 {
+ background-position: 50% 42.85714%;
+}
+
+.emojione-1f379 {
+ background-position: 50% 45.2381%;
+}
+
+.emojione-1f37a {
+ background-position: 50% 47.61905%;
+}
+
+.emojione-1f37b {
+ background-position: 0% 50%;
+}
+
+.emojione-1f37c {
+ background-position: 2.38095% 50%;
+}
+
+.emojione-1f37d {
+ background-position: 4.7619% 50%;
+}
+
+.emojione-1f37e {
+ background-position: 7.14286% 50%;
+}
+
+.emojione-1f37f {
+ background-position: 9.52381% 50%;
+}
+
+.emojione-1f380 {
+ background-position: 11.90476% 50%;
+}
+
+.emojione-1f381 {
+ background-position: 14.28571% 50%;
+}
+
+.emojione-1f382 {
+ background-position: 16.66667% 50%;
+}
+
+.emojione-1f383 {
+ background-position: 19.04762% 50%;
+}
+
+.emojione-1f384 {
+ background-position: 21.42857% 50%;
+}
+
+.emojione-1f385-1f3fb {
+ background-position: 23.80952% 50%;
+}
+
+.emojione-1f385-1f3fc {
+ background-position: 26.19048% 50%;
+}
+
+.emojione-1f385-1f3fd {
+ background-position: 28.57143% 50%;
+}
+
+.emojione-1f385-1f3fe {
+ background-position: 30.95238% 50%;
+}
+
+.emojione-1f385-1f3ff {
+ background-position: 33.33333% 50%;
+}
+
+.emojione-1f385 {
+ background-position: 35.71429% 50%;
+}
+
+.emojione-1f386 {
+ background-position: 38.09524% 50%;
+}
+
+.emojione-1f387 {
+ background-position: 40.47619% 50%;
+}
+
+.emojione-1f388 {
+ background-position: 42.85714% 50%;
+}
+
+.emojione-1f389 {
+ background-position: 45.2381% 50%;
+}
+
+.emojione-1f38a {
+ background-position: 47.61905% 50%;
+}
+
+.emojione-1f38b {
+ background-position: 50% 50%;
+}
+
+.emojione-1f38c {
+ background-position: 52.38095% 0%;
+}
+
+.emojione-1f38d {
+ background-position: 52.38095% 2.38095%;
+}
+
+.emojione-1f38e {
+ background-position: 52.38095% 4.7619%;
+}
+
+.emojione-1f38f {
+ background-position: 52.38095% 7.14286%;
+}
+
+.emojione-1f390 {
+ background-position: 52.38095% 9.52381%;
+}
+
+.emojione-1f391 {
+ background-position: 52.38095% 11.90476%;
+}
+
+.emojione-1f392 {
+ background-position: 52.38095% 14.28571%;
+}
+
+.emojione-1f393 {
+ background-position: 52.38095% 16.66667%;
+}
+
+.emojione-1f396 {
+ background-position: 52.38095% 19.04762%;
+}
+
+.emojione-1f397 {
+ background-position: 52.38095% 21.42857%;
+}
+
+.emojione-1f399 {
+ background-position: 52.38095% 23.80952%;
+}
+
+.emojione-1f39a {
+ background-position: 52.38095% 26.19048%;
+}
+
+.emojione-1f39b {
+ background-position: 52.38095% 28.57143%;
+}
+
+.emojione-1f39e {
+ background-position: 52.38095% 30.95238%;
+}
+
+.emojione-1f39f {
+ background-position: 52.38095% 33.33333%;
+}
+
+.emojione-1f3a0 {
+ background-position: 52.38095% 35.71429%;
+}
+
+.emojione-1f3a1 {
+ background-position: 52.38095% 38.09524%;
+}
+
+.emojione-1f3a2 {
+ background-position: 52.38095% 40.47619%;
+}
+
+.emojione-1f3a3 {
+ background-position: 52.38095% 42.85714%;
+}
+
+.emojione-1f3a4 {
+ background-position: 52.38095% 45.2381%;
+}
+
+.emojione-1f3a5 {
+ background-position: 52.38095% 47.61905%;
+}
+
+.emojione-1f3a6 {
+ background-position: 52.38095% 50%;
+}
+
+.emojione-1f3a7 {
+ background-position: 0% 52.38095%;
+}
+
+.emojione-1f3a8 {
+ background-position: 2.38095% 52.38095%;
+}
+
+.emojione-1f3a9 {
+ background-position: 4.7619% 52.38095%;
+}
+
+.emojione-1f3aa {
+ background-position: 7.14286% 52.38095%;
+}
+
+.emojione-1f3ab {
+ background-position: 9.52381% 52.38095%;
+}
+
+.emojione-1f3ac {
+ background-position: 11.90476% 52.38095%;
+}
+
+.emojione-1f3ad {
+ background-position: 14.28571% 52.38095%;
+}
+
+.emojione-1f3ae {
+ background-position: 16.66667% 52.38095%;
+}
+
+.emojione-1f3af {
+ background-position: 19.04762% 52.38095%;
+}
+
+.emojione-1f3b0 {
+ background-position: 21.42857% 52.38095%;
+}
+
+.emojione-1f3b1 {
+ background-position: 23.80952% 52.38095%;
+}
+
+.emojione-1f3b2 {
+ background-position: 26.19048% 52.38095%;
+}
+
+.emojione-1f3b3 {
+ background-position: 28.57143% 52.38095%;
+}
+
+.emojione-1f3b4 {
+ background-position: 30.95238% 52.38095%;
+}
+
+.emojione-1f3b5 {
+ background-position: 33.33333% 52.38095%;
+}
+
+.emojione-1f3b6 {
+ background-position: 35.71429% 52.38095%;
+}
+
+.emojione-1f3b7 {
+ background-position: 38.09524% 52.38095%;
+}
+
+.emojione-1f3b8 {
+ background-position: 40.47619% 52.38095%;
+}
+
+.emojione-1f3b9 {
+ background-position: 42.85714% 52.38095%;
+}
+
+.emojione-1f3ba {
+ background-position: 45.2381% 52.38095%;
+}
+
+.emojione-1f3bb {
+ background-position: 47.61905% 52.38095%;
+}
+
+.emojione-1f3bc {
+ background-position: 50% 52.38095%;
+}
+
+.emojione-1f3bd {
+ background-position: 52.38095% 52.38095%;
+}
+
+.emojione-1f3be {
+ background-position: 54.7619% 0%;
+}
+
+.emojione-1f3bf {
+ background-position: 54.7619% 2.38095%;
+}
+
+.emojione-1f3c0 {
+ background-position: 54.7619% 4.7619%;
+}
+
+.emojione-1f3c1 {
+ background-position: 54.7619% 7.14286%;
+}
+
+.emojione-1f3c2 {
+ background-position: 54.7619% 9.52381%;
+}
+
+.emojione-1f3c3-1f3fb {
+ background-position: 54.7619% 11.90476%;
+}
+
+.emojione-1f3c3-1f3fc {
+ background-position: 54.7619% 14.28571%;
+}
+
+.emojione-1f3c3-1f3fd {
+ background-position: 54.7619% 16.66667%;
+}
+
+.emojione-1f3c3-1f3fe {
+ background-position: 54.7619% 19.04762%;
+}
+
+.emojione-1f3c3-1f3ff {
+ background-position: 54.7619% 21.42857%;
+}
+
+.emojione-1f3c3 {
+ background-position: 54.7619% 23.80952%;
+}
+
+.emojione-1f3c4-1f3fb {
+ background-position: 54.7619% 26.19048%;
+}
+
+.emojione-1f3c4-1f3fc {
+ background-position: 54.7619% 28.57143%;
+}
+
+.emojione-1f3c4-1f3fd {
+ background-position: 54.7619% 30.95238%;
+}
+
+.emojione-1f3c4-1f3fe {
+ background-position: 54.7619% 33.33333%;
+}
+
+.emojione-1f3c4-1f3ff {
+ background-position: 54.7619% 35.71429%;
+}
+
+.emojione-1f3c4 {
+ background-position: 54.7619% 38.09524%;
+}
+
+.emojione-1f3c5 {
+ background-position: 54.7619% 40.47619%;
+}
+
+.emojione-1f3c6 {
+ background-position: 54.7619% 42.85714%;
+}
+
+.emojione-1f3c7-1f3fb {
+ background-position: 54.7619% 45.2381%;
+}
+
+.emojione-1f3c7-1f3fc {
+ background-position: 54.7619% 47.61905%;
+}
+
+.emojione-1f3c7-1f3fd {
+ background-position: 54.7619% 50%;
+}
+
+.emojione-1f3c7-1f3fe {
+ background-position: 54.7619% 52.38095%;
+}
+
+.emojione-1f3c7-1f3ff {
+ background-position: 0% 54.7619%;
+}
+
+.emojione-1f3c7 {
+ background-position: 2.38095% 54.7619%;
+}
+
+.emojione-1f3c8 {
+ background-position: 4.7619% 54.7619%;
+}
+
+.emojione-1f3c9 {
+ background-position: 7.14286% 54.7619%;
+}
+
+.emojione-1f3ca-1f3fb {
+ background-position: 9.52381% 54.7619%;
+}
+
+.emojione-1f3ca-1f3fc {
+ background-position: 11.90476% 54.7619%;
+}
+
+.emojione-1f3ca-1f3fd {
+ background-position: 14.28571% 54.7619%;
+}
+
+.emojione-1f3ca-1f3fe {
+ background-position: 16.66667% 54.7619%;
+}
+
+.emojione-1f3ca-1f3ff {
+ background-position: 19.04762% 54.7619%;
+}
+
+.emojione-1f3ca {
+ background-position: 21.42857% 54.7619%;
+}
+
+.emojione-1f3cb-1f3fb {
+ background-position: 23.80952% 54.7619%;
+}
+
+.emojione-1f3cb-1f3fc {
+ background-position: 26.19048% 54.7619%;
+}
+
+.emojione-1f3cb-1f3fd {
+ background-position: 28.57143% 54.7619%;
+}
+
+.emojione-1f3cb-1f3fe {
+ background-position: 30.95238% 54.7619%;
+}
+
+.emojione-1f3cb-1f3ff {
+ background-position: 33.33333% 54.7619%;
+}
+
+.emojione-1f3cb {
+ background-position: 35.71429% 54.7619%;
+}
+
+.emojione-1f3cc {
+ background-position: 38.09524% 54.7619%;
+}
+
+.emojione-1f3cd {
+ background-position: 40.47619% 54.7619%;
+}
+
+.emojione-1f3ce {
+ background-position: 42.85714% 54.7619%;
+}
+
+.emojione-1f3cf {
+ background-position: 45.2381% 54.7619%;
+}
+
+.emojione-1f3d0 {
+ background-position: 47.61905% 54.7619%;
+}
+
+.emojione-1f3d1 {
+ background-position: 50% 54.7619%;
+}
+
+.emojione-1f3d2 {
+ background-position: 52.38095% 54.7619%;
+}
+
+.emojione-1f3d3 {
+ background-position: 54.7619% 54.7619%;
+}
+
+.emojione-1f3d4 {
+ background-position: 57.14286% 0%;
+}
+
+.emojione-1f3d5 {
+ background-position: 57.14286% 2.38095%;
+}
+
+.emojione-1f3d6 {
+ background-position: 57.14286% 4.7619%;
+}
+
+.emojione-1f3d7 {
+ background-position: 57.14286% 7.14286%;
+}
+
+.emojione-1f3d8 {
+ background-position: 57.14286% 9.52381%;
+}
+
+.emojione-1f3d9 {
+ background-position: 57.14286% 11.90476%;
+}
+
+.emojione-1f3da {
+ background-position: 57.14286% 14.28571%;
+}
+
+.emojione-1f3db {
+ background-position: 57.14286% 16.66667%;
+}
+
+.emojione-1f3dc {
+ background-position: 57.14286% 19.04762%;
+}
+
+.emojione-1f3dd {
+ background-position: 57.14286% 21.42857%;
+}
+
+.emojione-1f3de {
+ background-position: 57.14286% 23.80952%;
+}
+
+.emojione-1f3df {
+ background-position: 57.14286% 26.19048%;
+}
+
+.emojione-1f3e0 {
+ background-position: 57.14286% 28.57143%;
+}
+
+.emojione-1f3e1 {
+ background-position: 57.14286% 30.95238%;
+}
+
+.emojione-1f3e2 {
+ background-position: 57.14286% 33.33333%;
+}
+
+.emojione-1f3e3 {
+ background-position: 57.14286% 35.71429%;
+}
+
+.emojione-1f3e4 {
+ background-position: 57.14286% 38.09524%;
+}
+
+.emojione-1f3e5 {
+ background-position: 57.14286% 40.47619%;
+}
+
+.emojione-1f3e6 {
+ background-position: 57.14286% 42.85714%;
+}
+
+.emojione-1f3e7 {
+ background-position: 57.14286% 45.2381%;
+}
+
+.emojione-1f3e8 {
+ background-position: 57.14286% 47.61905%;
+}
+
+.emojione-1f3e9 {
+ background-position: 57.14286% 50%;
+}
+
+.emojione-1f3ea {
+ background-position: 57.14286% 52.38095%;
+}
+
+.emojione-1f3eb {
+ background-position: 57.14286% 54.7619%;
+}
+
+.emojione-1f3ec {
+ background-position: 0% 57.14286%;
+}
+
+.emojione-1f3ed {
+ background-position: 2.38095% 57.14286%;
+}
+
+.emojione-1f3ee {
+ background-position: 4.7619% 57.14286%;
+}
+
+.emojione-1f3ef {
+ background-position: 7.14286% 57.14286%;
+}
+
+.emojione-1f3f0 {
+ background-position: 9.52381% 57.14286%;
+}
+
+.emojione-1f3f3-1f308 {
+ background-position: 11.90476% 57.14286%;
+}
+
+.emojione-1f3f3 {
+ background-position: 14.28571% 57.14286%;
+}
+
+.emojione-1f3f4 {
+ background-position: 16.66667% 57.14286%;
+}
+
+.emojione-1f3f5 {
+ background-position: 19.04762% 57.14286%;
+}
+
+.emojione-1f3f7 {
+ background-position: 21.42857% 57.14286%;
+}
+
+.emojione-1f3f8 {
+ background-position: 23.80952% 57.14286%;
+}
+
+.emojione-1f3f9 {
+ background-position: 26.19048% 57.14286%;
+}
+
+.emojione-1f3fa {
+ background-position: 28.57143% 57.14286%;
+}
+
+.emojione-1f3fb {
+ background-position: 30.95238% 57.14286%;
+}
+
+.emojione-1f3fc {
+ background-position: 33.33333% 57.14286%;
+}
+
+.emojione-1f3fd {
+ background-position: 35.71429% 57.14286%;
+}
+
+.emojione-1f3fe {
+ background-position: 38.09524% 57.14286%;
+}
+
+.emojione-1f3ff {
+ background-position: 40.47619% 57.14286%;
+}
+
+.emojione-1f400 {
+ background-position: 42.85714% 57.14286%;
+}
+
+.emojione-1f401 {
+ background-position: 45.2381% 57.14286%;
+}
+
+.emojione-1f402 {
+ background-position: 47.61905% 57.14286%;
+}
+
+.emojione-1f403 {
+ background-position: 50% 57.14286%;
+}
+
+.emojione-1f404 {
+ background-position: 52.38095% 57.14286%;
+}
+
+.emojione-1f405 {
+ background-position: 54.7619% 57.14286%;
+}
+
+.emojione-1f406 {
+ background-position: 57.14286% 57.14286%;
+}
+
+.emojione-1f407 {
+ background-position: 59.52381% 0%;
+}
+
+.emojione-1f408 {
+ background-position: 59.52381% 2.38095%;
+}
+
+.emojione-1f409 {
+ background-position: 59.52381% 4.7619%;
+}
+
+.emojione-1f40a {
+ background-position: 59.52381% 7.14286%;
+}
+
+.emojione-1f40b {
+ background-position: 59.52381% 9.52381%;
+}
+
+.emojione-1f40c {
+ background-position: 59.52381% 11.90476%;
+}
+
+.emojione-1f40d {
+ background-position: 59.52381% 14.28571%;
+}
+
+.emojione-1f40e {
+ background-position: 59.52381% 16.66667%;
+}
+
+.emojione-1f40f {
+ background-position: 59.52381% 19.04762%;
+}
+
+.emojione-1f410 {
+ background-position: 59.52381% 21.42857%;
+}
+
+.emojione-1f411 {
+ background-position: 59.52381% 23.80952%;
+}
+
+.emojione-1f412 {
+ background-position: 59.52381% 26.19048%;
+}
+
+.emojione-1f413 {
+ background-position: 59.52381% 28.57143%;
+}
+
+.emojione-1f414 {
+ background-position: 59.52381% 30.95238%;
+}
+
+.emojione-1f415 {
+ background-position: 59.52381% 33.33333%;
+}
+
+.emojione-1f416 {
+ background-position: 59.52381% 35.71429%;
+}
+
+.emojione-1f417 {
+ background-position: 59.52381% 38.09524%;
+}
+
+.emojione-1f418 {
+ background-position: 59.52381% 40.47619%;
+}
+
+.emojione-1f419 {
+ background-position: 59.52381% 42.85714%;
+}
+
+.emojione-1f41a {
+ background-position: 59.52381% 45.2381%;
+}
+
+.emojione-1f41b {
+ background-position: 59.52381% 47.61905%;
+}
+
+.emojione-1f41c {
+ background-position: 59.52381% 50%;
+}
+
+.emojione-1f41d {
+ background-position: 59.52381% 52.38095%;
+}
+
+.emojione-1f41e {
+ background-position: 59.52381% 54.7619%;
+}
+
+.emojione-1f41f {
+ background-position: 59.52381% 57.14286%;
+}
+
+.emojione-1f420 {
+ background-position: 0% 59.52381%;
+}
+
+.emojione-1f421 {
+ background-position: 2.38095% 59.52381%;
+}
+
+.emojione-1f422 {
+ background-position: 4.7619% 59.52381%;
+}
+
+.emojione-1f423 {
+ background-position: 7.14286% 59.52381%;
+}
+
+.emojione-1f424 {
+ background-position: 9.52381% 59.52381%;
+}
+
+.emojione-1f425 {
+ background-position: 11.90476% 59.52381%;
+}
+
+.emojione-1f426 {
+ background-position: 14.28571% 59.52381%;
+}
+
+.emojione-1f427 {
+ background-position: 16.66667% 59.52381%;
+}
+
+.emojione-1f428 {
+ background-position: 19.04762% 59.52381%;
+}
+
+.emojione-1f429 {
+ background-position: 21.42857% 59.52381%;
+}
+
+.emojione-1f42a {
+ background-position: 23.80952% 59.52381%;
+}
+
+.emojione-1f42b {
+ background-position: 26.19048% 59.52381%;
+}
+
+.emojione-1f42c {
+ background-position: 28.57143% 59.52381%;
+}
+
+.emojione-1f42d {
+ background-position: 30.95238% 59.52381%;
+}
+
+.emojione-1f42e {
+ background-position: 33.33333% 59.52381%;
+}
+
+.emojione-1f42f {
+ background-position: 35.71429% 59.52381%;
+}
+
+.emojione-1f430 {
+ background-position: 38.09524% 59.52381%;
+}
+
+.emojione-1f431 {
+ background-position: 40.47619% 59.52381%;
+}
+
+.emojione-1f432 {
+ background-position: 42.85714% 59.52381%;
+}
+
+.emojione-1f433 {
+ background-position: 45.2381% 59.52381%;
+}
+
+.emojione-1f434 {
+ background-position: 47.61905% 59.52381%;
+}
+
+.emojione-1f435 {
+ background-position: 50% 59.52381%;
+}
+
+.emojione-1f436 {
+ background-position: 52.38095% 59.52381%;
+}
+
+.emojione-1f437 {
+ background-position: 54.7619% 59.52381%;
+}
+
+.emojione-1f438 {
+ background-position: 57.14286% 59.52381%;
+}
+
+.emojione-1f439 {
+ background-position: 59.52381% 59.52381%;
+}
+
+.emojione-1f43a {
+ background-position: 61.90476% 0%;
+}
+
+.emojione-1f43b {
+ background-position: 61.90476% 2.38095%;
+}
+
+.emojione-1f43c {
+ background-position: 61.90476% 4.7619%;
+}
+
+.emojione-1f43d {
+ background-position: 61.90476% 7.14286%;
+}
+
+.emojione-1f43e {
+ background-position: 61.90476% 9.52381%;
+}
+
+.emojione-1f43f {
+ background-position: 61.90476% 11.90476%;
+}
+
+.emojione-1f440 {
+ background-position: 61.90476% 14.28571%;
+}
+
+.emojione-1f441-1f5e8 {
+ background-position: 61.90476% 16.66667%;
+}
+
+.emojione-1f441 {
+ background-position: 61.90476% 19.04762%;
+}
+
+.emojione-1f442-1f3fb {
+ background-position: 61.90476% 21.42857%;
+}
+
+.emojione-1f442-1f3fc {
+ background-position: 61.90476% 23.80952%;
+}
+
+.emojione-1f442-1f3fd {
+ background-position: 61.90476% 26.19048%;
+}
+
+.emojione-1f442-1f3fe {
+ background-position: 61.90476% 28.57143%;
+}
+
+.emojione-1f442-1f3ff {
+ background-position: 61.90476% 30.95238%;
+}
+
+.emojione-1f442 {
+ background-position: 61.90476% 33.33333%;
+}
+
+.emojione-1f443-1f3fb {
+ background-position: 61.90476% 35.71429%;
+}
+
+.emojione-1f443-1f3fc {
+ background-position: 61.90476% 38.09524%;
+}
+
+.emojione-1f443-1f3fd {
+ background-position: 61.90476% 40.47619%;
+}
+
+.emojione-1f443-1f3fe {
+ background-position: 61.90476% 42.85714%;
+}
+
+.emojione-1f443-1f3ff {
+ background-position: 61.90476% 45.2381%;
+}
+
+.emojione-1f443 {
+ background-position: 61.90476% 47.61905%;
+}
+
+.emojione-1f444 {
+ background-position: 61.90476% 50%;
+}
+
+.emojione-1f445 {
+ background-position: 61.90476% 52.38095%;
+}
+
+.emojione-1f446-1f3fb {
+ background-position: 61.90476% 54.7619%;
+}
+
+.emojione-1f446-1f3fc {
+ background-position: 61.90476% 57.14286%;
+}
+
+.emojione-1f446-1f3fd {
+ background-position: 61.90476% 59.52381%;
+}
+
+.emojione-1f446-1f3fe {
+ background-position: 0% 61.90476%;
+}
+
+.emojione-1f446-1f3ff {
+ background-position: 2.38095% 61.90476%;
+}
+
+.emojione-1f446 {
+ background-position: 4.7619% 61.90476%;
+}
+
+.emojione-1f447-1f3fb {
+ background-position: 7.14286% 61.90476%;
+}
+
+.emojione-1f447-1f3fc {
+ background-position: 9.52381% 61.90476%;
+}
+
+.emojione-1f447-1f3fd {
+ background-position: 11.90476% 61.90476%;
+}
+
+.emojione-1f447-1f3fe {
+ background-position: 14.28571% 61.90476%;
+}
+
+.emojione-1f447-1f3ff {
+ background-position: 16.66667% 61.90476%;
+}
+
+.emojione-1f447 {
+ background-position: 19.04762% 61.90476%;
+}
+
+.emojione-1f448-1f3fb {
+ background-position: 21.42857% 61.90476%;
+}
+
+.emojione-1f448-1f3fc {
+ background-position: 23.80952% 61.90476%;
+}
+
+.emojione-1f448-1f3fd {
+ background-position: 26.19048% 61.90476%;
+}
+
+.emojione-1f448-1f3fe {
+ background-position: 28.57143% 61.90476%;
+}
+
+.emojione-1f448-1f3ff {
+ background-position: 30.95238% 61.90476%;
+}
+
+.emojione-1f448 {
+ background-position: 33.33333% 61.90476%;
+}
+
+.emojione-1f449-1f3fb {
+ background-position: 35.71429% 61.90476%;
+}
+
+.emojione-1f449-1f3fc {
+ background-position: 38.09524% 61.90476%;
+}
+
+.emojione-1f449-1f3fd {
+ background-position: 40.47619% 61.90476%;
+}
+
+.emojione-1f449-1f3fe {
+ background-position: 42.85714% 61.90476%;
+}
+
+.emojione-1f449-1f3ff {
+ background-position: 45.2381% 61.90476%;
+}
+
+.emojione-1f449 {
+ background-position: 47.61905% 61.90476%;
+}
+
+.emojione-1f44a-1f3fb {
+ background-position: 50% 61.90476%;
+}
+
+.emojione-1f44a-1f3fc {
+ background-position: 52.38095% 61.90476%;
+}
+
+.emojione-1f44a-1f3fd {
+ background-position: 54.7619% 61.90476%;
+}
+
+.emojione-1f44a-1f3fe {
+ background-position: 57.14286% 61.90476%;
+}
+
+.emojione-1f44a-1f3ff {
+ background-position: 59.52381% 61.90476%;
+}
+
+.emojione-1f44a {
+ background-position: 61.90476% 61.90476%;
+}
+
+.emojione-1f44b-1f3fb {
+ background-position: 64.28571% 0%;
+}
+
+.emojione-1f44b-1f3fc {
+ background-position: 64.28571% 2.38095%;
+}
+
+.emojione-1f44b-1f3fd {
+ background-position: 64.28571% 4.7619%;
+}
+
+.emojione-1f44b-1f3fe {
+ background-position: 64.28571% 7.14286%;
+}
+
+.emojione-1f44b-1f3ff {
+ background-position: 64.28571% 9.52381%;
+}
+
+.emojione-1f44b {
+ background-position: 64.28571% 11.90476%;
+}
+
+.emojione-1f44c-1f3fb {
+ background-position: 64.28571% 14.28571%;
+}
+
+.emojione-1f44c-1f3fc {
+ background-position: 64.28571% 16.66667%;
+}
+
+.emojione-1f44c-1f3fd {
+ background-position: 64.28571% 19.04762%;
+}
+
+.emojione-1f44c-1f3fe {
+ background-position: 64.28571% 21.42857%;
+}
+
+.emojione-1f44c-1f3ff {
+ background-position: 64.28571% 23.80952%;
+}
+
+.emojione-1f44c {
+ background-position: 64.28571% 26.19048%;
+}
+
+.emojione-1f44d-1f3fb {
+ background-position: 64.28571% 28.57143%;
+}
+
+.emojione-1f44d-1f3fc {
+ background-position: 64.28571% 30.95238%;
+}
+
+.emojione-1f44d-1f3fd {
+ background-position: 64.28571% 33.33333%;
+}
+
+.emojione-1f44d-1f3fe {
+ background-position: 64.28571% 35.71429%;
+}
+
+.emojione-1f44d-1f3ff {
+ background-position: 64.28571% 38.09524%;
+}
+
+.emojione-1f44d {
+ background-position: 64.28571% 40.47619%;
+}
+
+.emojione-1f44e-1f3fb {
+ background-position: 64.28571% 42.85714%;
+}
+
+.emojione-1f44e-1f3fc {
+ background-position: 64.28571% 45.2381%;
+}
+
+.emojione-1f44e-1f3fd {
+ background-position: 64.28571% 47.61905%;
+}
+
+.emojione-1f44e-1f3fe {
+ background-position: 64.28571% 50%;
+}
+
+.emojione-1f44e-1f3ff {
+ background-position: 64.28571% 52.38095%;
+}
+
+.emojione-1f44e {
+ background-position: 64.28571% 54.7619%;
+}
+
+.emojione-1f44f-1f3fb {
+ background-position: 64.28571% 57.14286%;
+}
+
+.emojione-1f44f-1f3fc {
+ background-position: 64.28571% 59.52381%;
+}
+
+.emojione-1f44f-1f3fd {
+ background-position: 64.28571% 61.90476%;
+}
+
+.emojione-1f44f-1f3fe {
+ background-position: 0% 64.28571%;
+}
+
+.emojione-1f44f-1f3ff {
+ background-position: 2.38095% 64.28571%;
+}
+
+.emojione-1f44f {
+ background-position: 4.7619% 64.28571%;
+}
+
+.emojione-1f450-1f3fb {
+ background-position: 7.14286% 64.28571%;
+}
+
+.emojione-1f450-1f3fc {
+ background-position: 9.52381% 64.28571%;
+}
+
+.emojione-1f450-1f3fd {
+ background-position: 11.90476% 64.28571%;
+}
+
+.emojione-1f450-1f3fe {
+ background-position: 14.28571% 64.28571%;
+}
+
+.emojione-1f450-1f3ff {
+ background-position: 16.66667% 64.28571%;
+}
+
+.emojione-1f450 {
+ background-position: 19.04762% 64.28571%;
+}
+
+.emojione-1f451 {
+ background-position: 21.42857% 64.28571%;
+}
+
+.emojione-1f452 {
+ background-position: 23.80952% 64.28571%;
+}
+
+.emojione-1f453 {
+ background-position: 26.19048% 64.28571%;
+}
+
+.emojione-1f454 {
+ background-position: 28.57143% 64.28571%;
+}
+
+.emojione-1f455 {
+ background-position: 30.95238% 64.28571%;
+}
+
+.emojione-1f456 {
+ background-position: 33.33333% 64.28571%;
+}
+
+.emojione-1f457 {
+ background-position: 35.71429% 64.28571%;
+}
+
+.emojione-1f458 {
+ background-position: 38.09524% 64.28571%;
+}
+
+.emojione-1f459 {
+ background-position: 40.47619% 64.28571%;
+}
+
+.emojione-1f45a {
+ background-position: 42.85714% 64.28571%;
+}
+
+.emojione-1f45b {
+ background-position: 45.2381% 64.28571%;
+}
+
+.emojione-1f45c {
+ background-position: 47.61905% 64.28571%;
+}
+
+.emojione-1f45d {
+ background-position: 50% 64.28571%;
+}
+
+.emojione-1f45e {
+ background-position: 52.38095% 64.28571%;
+}
+
+.emojione-1f45f {
+ background-position: 54.7619% 64.28571%;
+}
+
+.emojione-1f460 {
+ background-position: 57.14286% 64.28571%;
+}
+
+.emojione-1f461 {
+ background-position: 59.52381% 64.28571%;
+}
+
+.emojione-1f462 {
+ background-position: 61.90476% 64.28571%;
+}
+
+.emojione-1f463 {
+ background-position: 64.28571% 64.28571%;
+}
+
+.emojione-1f464 {
+ background-position: 66.66667% 0%;
+}
+
+.emojione-1f465 {
+ background-position: 66.66667% 2.38095%;
+}
+
+.emojione-1f466-1f3fb {
+ background-position: 66.66667% 4.7619%;
+}
+
+.emojione-1f466-1f3fc {
+ background-position: 66.66667% 7.14286%;
+}
+
+.emojione-1f466-1f3fd {
+ background-position: 66.66667% 9.52381%;
+}
+
+.emojione-1f466-1f3fe {
+ background-position: 66.66667% 11.90476%;
+}
+
+.emojione-1f466-1f3ff {
+ background-position: 66.66667% 14.28571%;
+}
+
+.emojione-1f466 {
+ background-position: 66.66667% 16.66667%;
+}
+
+.emojione-1f467-1f3fb {
+ background-position: 66.66667% 19.04762%;
+}
+
+.emojione-1f467-1f3fc {
+ background-position: 66.66667% 21.42857%;
+}
+
+.emojione-1f467-1f3fd {
+ background-position: 66.66667% 23.80952%;
+}
+
+.emojione-1f467-1f3fe {
+ background-position: 66.66667% 26.19048%;
+}
+
+.emojione-1f467-1f3ff {
+ background-position: 66.66667% 28.57143%;
+}
+
+.emojione-1f467 {
+ background-position: 66.66667% 30.95238%;
+}
+
+.emojione-1f468-1f3fb {
+ background-position: 66.66667% 33.33333%;
+}
+
+.emojione-1f468-1f3fc {
+ background-position: 66.66667% 35.71429%;
+}
+
+.emojione-1f468-1f3fd {
+ background-position: 66.66667% 38.09524%;
+}
+
+.emojione-1f468-1f3fe {
+ background-position: 66.66667% 40.47619%;
+}
+
+.emojione-1f468-1f3ff {
+ background-position: 66.66667% 42.85714%;
+}
+
+.emojione-1f468-1f468-1f466-1f466 {
+ background-position: 66.66667% 45.2381%;
+}
+
+.emojione-1f468-1f468-1f466 {
+ background-position: 66.66667% 47.61905%;
+}
+
+.emojione-1f468-1f468-1f467-1f466 {
+ background-position: 66.66667% 50%;
+}
+
+.emojione-1f468-1f468-1f467-1f467 {
+ background-position: 66.66667% 52.38095%;
+}
+
+.emojione-1f468-1f468-1f467 {
+ background-position: 66.66667% 54.7619%;
+}
+
+.emojione-1f468-1f469-1f466-1f466 {
+ background-position: 66.66667% 57.14286%;
+}
+
+.emojione-1f468-1f469-1f467-1f466 {
+ background-position: 66.66667% 59.52381%;
+}
+
+.emojione-1f468-1f469-1f467-1f467 {
+ background-position: 66.66667% 61.90476%;
+}
+
+.emojione-1f468-1f469-1f467 {
+ background-position: 66.66667% 64.28571%;
+}
+
+.emojione-1f468-2764-1f468 {
+ background-position: 0% 66.66667%;
+}
+
+.emojione-1f468-2764-1f48b-1f468 {
+ background-position: 2.38095% 66.66667%;
+}
+
+.emojione-1f468 {
+ background-position: 4.7619% 66.66667%;
+}
+
+.emojione-1f469-1f3fb {
+ background-position: 7.14286% 66.66667%;
+}
+
+.emojione-1f469-1f3fc {
+ background-position: 9.52381% 66.66667%;
+}
+
+.emojione-1f469-1f3fd {
+ background-position: 11.90476% 66.66667%;
+}
+
+.emojione-1f469-1f3fe {
+ background-position: 14.28571% 66.66667%;
+}
+
+.emojione-1f469-1f3ff {
+ background-position: 16.66667% 66.66667%;
+}
+
+.emojione-1f469-1f469-1f466-1f466 {
+ background-position: 19.04762% 66.66667%;
+}
+
+.emojione-1f469-1f469-1f466 {
+ background-position: 21.42857% 66.66667%;
+}
+
+.emojione-1f469-1f469-1f467-1f466 {
+ background-position: 23.80952% 66.66667%;
+}
+
+.emojione-1f469-1f469-1f467-1f467 {
+ background-position: 26.19048% 66.66667%;
+}
+
+.emojione-1f469-1f469-1f467 {
+ background-position: 28.57143% 66.66667%;
+}
+
+.emojione-1f469-2764-1f469 {
+ background-position: 30.95238% 66.66667%;
+}
+
+.emojione-1f469-2764-1f48b-1f469 {
+ background-position: 33.33333% 66.66667%;
+}
+
+.emojione-1f469 {
+ background-position: 35.71429% 66.66667%;
+}
+
+.emojione-1f46a {
+ background-position: 38.09524% 66.66667%;
+}
+
+.emojione-1f46b {
+ background-position: 40.47619% 66.66667%;
+}
+
+.emojione-1f46c {
+ background-position: 42.85714% 66.66667%;
+}
+
+.emojione-1f46d {
+ background-position: 45.2381% 66.66667%;
+}
+
+.emojione-1f46e-1f3fb {
+ background-position: 47.61905% 66.66667%;
+}
+
+.emojione-1f46e-1f3fc {
+ background-position: 0% 0%;
+}
+
+.emojione-1f46e-1f3fd {
+ background-position: 52.38095% 66.66667%;
+}
+
+.emojione-1f46e-1f3fe {
+ background-position: 54.7619% 66.66667%;
+}
+
+.emojione-1f46e-1f3ff {
+ background-position: 57.14286% 66.66667%;
+}
+
+.emojione-1f46e {
+ background-position: 59.52381% 66.66667%;
+}
+
+.emojione-1f46f {
+ background-position: 61.90476% 66.66667%;
+}
+
+.emojione-1f470-1f3fb {
+ background-position: 64.28571% 66.66667%;
+}
+
+.emojione-1f470-1f3fc {
+ background-position: 66.66667% 66.66667%;
+}
+
+.emojione-1f470-1f3fd {
+ background-position: 69.04762% 0%;
+}
+
+.emojione-1f470-1f3fe {
+ background-position: 69.04762% 2.38095%;
+}
+
+.emojione-1f470-1f3ff {
+ background-position: 69.04762% 4.7619%;
+}
+
+.emojione-1f470 {
+ background-position: 69.04762% 7.14286%;
+}
+
+.emojione-1f471-1f3fb {
+ background-position: 69.04762% 9.52381%;
+}
+
+.emojione-1f471-1f3fc {
+ background-position: 69.04762% 11.90476%;
+}
+
+.emojione-1f471-1f3fd {
+ background-position: 69.04762% 14.28571%;
+}
+
+.emojione-1f471-1f3fe {
+ background-position: 69.04762% 16.66667%;
+}
+
+.emojione-1f471-1f3ff {
+ background-position: 69.04762% 19.04762%;
+}
+
+.emojione-1f471 {
+ background-position: 69.04762% 21.42857%;
+}
+
+.emojione-1f472-1f3fb {
+ background-position: 69.04762% 23.80952%;
+}
+
+.emojione-1f472-1f3fc {
+ background-position: 69.04762% 26.19048%;
+}
+
+.emojione-1f472-1f3fd {
+ background-position: 69.04762% 28.57143%;
+}
+
+.emojione-1f472-1f3fe {
+ background-position: 69.04762% 30.95238%;
+}
+
+.emojione-1f472-1f3ff {
+ background-position: 69.04762% 33.33333%;
+}
+
+.emojione-1f472 {
+ background-position: 69.04762% 35.71429%;
+}
+
+.emojione-1f473-1f3fb {
+ background-position: 69.04762% 38.09524%;
+}
+
+.emojione-1f473-1f3fc {
+ background-position: 69.04762% 40.47619%;
+}
+
+.emojione-1f473-1f3fd {
+ background-position: 69.04762% 42.85714%;
+}
+
+.emojione-1f473-1f3fe {
+ background-position: 69.04762% 45.2381%;
+}
+
+.emojione-1f473-1f3ff {
+ background-position: 69.04762% 47.61905%;
+}
+
+.emojione-1f473 {
+ background-position: 69.04762% 50%;
+}
+
+.emojione-1f474-1f3fb {
+ background-position: 69.04762% 52.38095%;
+}
+
+.emojione-1f474-1f3fc {
+ background-position: 69.04762% 54.7619%;
+}
+
+.emojione-1f474-1f3fd {
+ background-position: 69.04762% 57.14286%;
+}
+
+.emojione-1f474-1f3fe {
+ background-position: 69.04762% 59.52381%;
+}
+
+.emojione-1f474-1f3ff {
+ background-position: 69.04762% 61.90476%;
+}
+
+.emojione-1f474 {
+ background-position: 69.04762% 64.28571%;
+}
+
+.emojione-1f475-1f3fb {
+ background-position: 69.04762% 66.66667%;
+}
+
+.emojione-1f475-1f3fc {
+ background-position: 0% 69.04762%;
+}
+
+.emojione-1f475-1f3fd {
+ background-position: 2.38095% 69.04762%;
+}
+
+.emojione-1f475-1f3fe {
+ background-position: 4.7619% 69.04762%;
+}
+
+.emojione-1f475-1f3ff {
+ background-position: 7.14286% 69.04762%;
+}
+
+.emojione-1f475 {
+ background-position: 9.52381% 69.04762%;
+}
+
+.emojione-1f476-1f3fb {
+ background-position: 11.90476% 69.04762%;
+}
+
+.emojione-1f476-1f3fc {
+ background-position: 14.28571% 69.04762%;
+}
+
+.emojione-1f476-1f3fd {
+ background-position: 16.66667% 69.04762%;
+}
+
+.emojione-1f476-1f3fe {
+ background-position: 19.04762% 69.04762%;
+}
+
+.emojione-1f476-1f3ff {
+ background-position: 21.42857% 69.04762%;
+}
+
+.emojione-1f476 {
+ background-position: 23.80952% 69.04762%;
+}
+
+.emojione-1f477-1f3fb {
+ background-position: 26.19048% 69.04762%;
+}
+
+.emojione-1f477-1f3fc {
+ background-position: 28.57143% 69.04762%;
+}
+
+.emojione-1f477-1f3fd {
+ background-position: 30.95238% 69.04762%;
+}
+
+.emojione-1f477-1f3fe {
+ background-position: 33.33333% 69.04762%;
+}
+
+.emojione-1f477-1f3ff {
+ background-position: 35.71429% 69.04762%;
+}
+
+.emojione-1f477 {
+ background-position: 38.09524% 69.04762%;
+}
+
+.emojione-1f478-1f3fb {
+ background-position: 40.47619% 69.04762%;
+}
+
+.emojione-1f478-1f3fc {
+ background-position: 42.85714% 69.04762%;
+}
+
+.emojione-1f478-1f3fd {
+ background-position: 45.2381% 69.04762%;
+}
+
+.emojione-1f478-1f3fe {
+ background-position: 47.61905% 69.04762%;
+}
+
+.emojione-1f478-1f3ff {
+ background-position: 50% 69.04762%;
+}
+
+.emojione-1f478 {
+ background-position: 52.38095% 69.04762%;
+}
+
+.emojione-1f479 {
+ background-position: 54.7619% 69.04762%;
+}
+
+.emojione-1f47a {
+ background-position: 57.14286% 69.04762%;
+}
+
+.emojione-1f47b {
+ background-position: 59.52381% 69.04762%;
+}
+
+.emojione-1f47c-1f3fb {
+ background-position: 61.90476% 69.04762%;
+}
+
+.emojione-1f47c-1f3fc {
+ background-position: 64.28571% 69.04762%;
+}
+
+.emojione-1f47c-1f3fd {
+ background-position: 66.66667% 69.04762%;
+}
+
+.emojione-1f47c-1f3fe {
+ background-position: 69.04762% 69.04762%;
+}
+
+.emojione-1f47c-1f3ff {
+ background-position: 71.42857% 0%;
+}
+
+.emojione-1f47c {
+ background-position: 71.42857% 2.38095%;
+}
+
+.emojione-1f47d {
+ background-position: 71.42857% 4.7619%;
+}
+
+.emojione-1f47e {
+ background-position: 71.42857% 7.14286%;
+}
+
+.emojione-1f47f {
+ background-position: 71.42857% 9.52381%;
+}
+
+.emojione-1f480 {
+ background-position: 71.42857% 11.90476%;
+}
+
+.emojione-1f481-1f3fb {
+ background-position: 71.42857% 14.28571%;
+}
+
+.emojione-1f481-1f3fc {
+ background-position: 71.42857% 16.66667%;
+}
+
+.emojione-1f481-1f3fd {
+ background-position: 71.42857% 19.04762%;
+}
+
+.emojione-1f481-1f3fe {
+ background-position: 71.42857% 21.42857%;
+}
+
+.emojione-1f481-1f3ff {
+ background-position: 71.42857% 23.80952%;
+}
+
+.emojione-1f481 {
+ background-position: 71.42857% 26.19048%;
+}
+
+.emojione-1f482-1f3fb {
+ background-position: 71.42857% 28.57143%;
+}
+
+.emojione-1f482-1f3fc {
+ background-position: 71.42857% 30.95238%;
+}
+
+.emojione-1f482-1f3fd {
+ background-position: 71.42857% 33.33333%;
+}
+
+.emojione-1f482-1f3fe {
+ background-position: 71.42857% 35.71429%;
+}
+
+.emojione-1f482-1f3ff {
+ background-position: 71.42857% 38.09524%;
+}
+
+.emojione-1f482 {
+ background-position: 71.42857% 40.47619%;
+}
+
+.emojione-1f483-1f3fb {
+ background-position: 71.42857% 42.85714%;
+}
+
+.emojione-1f483-1f3fc {
+ background-position: 71.42857% 45.2381%;
+}
+
+.emojione-1f483-1f3fd {
+ background-position: 71.42857% 47.61905%;
+}
+
+.emojione-1f483-1f3fe {
+ background-position: 71.42857% 50%;
+}
+
+.emojione-1f483-1f3ff {
+ background-position: 71.42857% 52.38095%;
+}
+
+.emojione-1f483 {
+ background-position: 71.42857% 54.7619%;
+}
+
+.emojione-1f484 {
+ background-position: 71.42857% 57.14286%;
+}
+
+.emojione-1f485-1f3fb {
+ background-position: 71.42857% 59.52381%;
+}
+
+.emojione-1f485-1f3fc {
+ background-position: 71.42857% 61.90476%;
+}
+
+.emojione-1f485-1f3fd {
+ background-position: 71.42857% 64.28571%;
+}
+
+.emojione-1f485-1f3fe {
+ background-position: 71.42857% 66.66667%;
+}
+
+.emojione-1f485-1f3ff {
+ background-position: 71.42857% 69.04762%;
+}
+
+.emojione-1f485 {
+ background-position: 0% 71.42857%;
+}
+
+.emojione-1f486-1f3fb {
+ background-position: 2.38095% 71.42857%;
+}
+
+.emojione-1f486-1f3fc {
+ background-position: 4.7619% 71.42857%;
+}
+
+.emojione-1f486-1f3fd {
+ background-position: 7.14286% 71.42857%;
+}
+
+.emojione-1f486-1f3fe {
+ background-position: 9.52381% 71.42857%;
+}
+
+.emojione-1f486-1f3ff {
+ background-position: 11.90476% 71.42857%;
+}
+
+.emojione-1f486 {
+ background-position: 14.28571% 71.42857%;
+}
+
+.emojione-1f487-1f3fb {
+ background-position: 16.66667% 71.42857%;
+}
+
+.emojione-1f487-1f3fc {
+ background-position: 19.04762% 71.42857%;
+}
+
+.emojione-1f487-1f3fd {
+ background-position: 21.42857% 71.42857%;
+}
+
+.emojione-1f487-1f3fe {
+ background-position: 23.80952% 71.42857%;
+}
+
+.emojione-1f487-1f3ff {
+ background-position: 26.19048% 71.42857%;
+}
+
+.emojione-1f487 {
+ background-position: 28.57143% 71.42857%;
+}
+
+.emojione-1f488 {
+ background-position: 30.95238% 71.42857%;
+}
+
+.emojione-1f489 {
+ background-position: 33.33333% 71.42857%;
+}
+
+.emojione-1f48a {
+ background-position: 35.71429% 71.42857%;
+}
+
+.emojione-1f48b {
+ background-position: 38.09524% 71.42857%;
+}
+
+.emojione-1f48c {
+ background-position: 40.47619% 71.42857%;
+}
+
+.emojione-1f48d {
+ background-position: 42.85714% 71.42857%;
+}
+
+.emojione-1f48e {
+ background-position: 45.2381% 71.42857%;
+}
+
+.emojione-1f48f {
+ background-position: 47.61905% 71.42857%;
+}
+
+.emojione-1f490 {
+ background-position: 50% 71.42857%;
+}
+
+.emojione-1f491 {
+ background-position: 52.38095% 71.42857%;
+}
+
+.emojione-1f492 {
+ background-position: 54.7619% 71.42857%;
+}
+
+.emojione-1f493 {
+ background-position: 57.14286% 71.42857%;
+}
+
+.emojione-1f494 {
+ background-position: 59.52381% 71.42857%;
+}
+
+.emojione-1f495 {
+ background-position: 61.90476% 71.42857%;
+}
+
+.emojione-1f496 {
+ background-position: 64.28571% 71.42857%;
+}
+
+.emojione-1f497 {
+ background-position: 66.66667% 71.42857%;
+}
+
+.emojione-1f498 {
+ background-position: 69.04762% 71.42857%;
+}
+
+.emojione-1f499 {
+ background-position: 71.42857% 71.42857%;
+}
+
+.emojione-1f49a {
+ background-position: 73.80952% 0%;
+}
+
+.emojione-1f49b {
+ background-position: 73.80952% 2.38095%;
+}
+
+.emojione-1f49c {
+ background-position: 73.80952% 4.7619%;
+}
+
+.emojione-1f49d {
+ background-position: 73.80952% 7.14286%;
+}
+
+.emojione-1f49e {
+ background-position: 73.80952% 9.52381%;
+}
+
+.emojione-1f49f {
+ background-position: 73.80952% 11.90476%;
+}
+
+.emojione-1f4a0 {
+ background-position: 73.80952% 14.28571%;
+}
+
+.emojione-1f4a1 {
+ background-position: 73.80952% 16.66667%;
+}
+
+.emojione-1f4a2 {
+ background-position: 73.80952% 19.04762%;
+}
+
+.emojione-1f4a3 {
+ background-position: 73.80952% 21.42857%;
+}
+
+.emojione-1f4a4 {
+ background-position: 73.80952% 23.80952%;
+}
+
+.emojione-1f4a5 {
+ background-position: 73.80952% 26.19048%;
+}
+
+.emojione-1f4a6 {
+ background-position: 73.80952% 28.57143%;
+}
+
+.emojione-1f4a7 {
+ background-position: 73.80952% 30.95238%;
+}
+
+.emojione-1f4a8 {
+ background-position: 73.80952% 33.33333%;
+}
+
+.emojione-1f4a9 {
+ background-position: 73.80952% 35.71429%;
+}
+
+.emojione-1f4aa-1f3fb {
+ background-position: 73.80952% 38.09524%;
+}
+
+.emojione-1f4aa-1f3fc {
+ background-position: 73.80952% 40.47619%;
+}
+
+.emojione-1f4aa-1f3fd {
+ background-position: 73.80952% 42.85714%;
+}
+
+.emojione-1f4aa-1f3fe {
+ background-position: 73.80952% 45.2381%;
+}
+
+.emojione-1f4aa-1f3ff {
+ background-position: 73.80952% 47.61905%;
+}
+
+.emojione-1f4aa {
+ background-position: 73.80952% 50%;
+}
+
+.emojione-1f4ab {
+ background-position: 73.80952% 52.38095%;
+}
+
+.emojione-1f4ac {
+ background-position: 73.80952% 54.7619%;
+}
+
+.emojione-1f4ad {
+ background-position: 73.80952% 57.14286%;
+}
+
+.emojione-1f4ae {
+ background-position: 73.80952% 59.52381%;
+}
+
+.emojione-1f4af {
+ background-position: 73.80952% 61.90476%;
+}
+
+.emojione-1f4b0 {
+ background-position: 73.80952% 64.28571%;
+}
+
+.emojione-1f4b1 {
+ background-position: 73.80952% 66.66667%;
+}
+
+.emojione-1f4b2 {
+ background-position: 73.80952% 69.04762%;
+}
+
+.emojione-1f4b3 {
+ background-position: 73.80952% 71.42857%;
+}
+
+.emojione-1f4b4 {
+ background-position: 0% 73.80952%;
+}
+
+.emojione-1f4b5 {
+ background-position: 2.38095% 73.80952%;
+}
+
+.emojione-1f4b6 {
+ background-position: 4.7619% 73.80952%;
+}
+
+.emojione-1f4b7 {
+ background-position: 7.14286% 73.80952%;
+}
+
+.emojione-1f4b8 {
+ background-position: 9.52381% 73.80952%;
+}
+
+.emojione-1f4b9 {
+ background-position: 11.90476% 73.80952%;
+}
+
+.emojione-1f4ba {
+ background-position: 14.28571% 73.80952%;
+}
+
+.emojione-1f4bb {
+ background-position: 16.66667% 73.80952%;
+}
+
+.emojione-1f4bc {
+ background-position: 19.04762% 73.80952%;
+}
+
+.emojione-1f4bd {
+ background-position: 21.42857% 73.80952%;
+}
+
+.emojione-1f4be {
+ background-position: 23.80952% 73.80952%;
+}
+
+.emojione-1f4bf {
+ background-position: 26.19048% 73.80952%;
+}
+
+.emojione-1f4c0 {
+ background-position: 28.57143% 73.80952%;
+}
+
+.emojione-1f4c1 {
+ background-position: 30.95238% 73.80952%;
+}
+
+.emojione-1f4c2 {
+ background-position: 33.33333% 73.80952%;
+}
+
+.emojione-1f4c3 {
+ background-position: 35.71429% 73.80952%;
+}
+
+.emojione-1f4c4 {
+ background-position: 38.09524% 73.80952%;
+}
+
+.emojione-1f4c5 {
+ background-position: 40.47619% 73.80952%;
+}
+
+.emojione-1f4c6 {
+ background-position: 42.85714% 73.80952%;
+}
+
+.emojione-1f4c7 {
+ background-position: 45.2381% 73.80952%;
+}
+
+.emojione-1f4c8 {
+ background-position: 47.61905% 73.80952%;
+}
+
+.emojione-1f4c9 {
+ background-position: 50% 73.80952%;
+}
+
+.emojione-1f4ca {
+ background-position: 52.38095% 73.80952%;
+}
+
+.emojione-1f4cb {
+ background-position: 54.7619% 73.80952%;
+}
+
+.emojione-1f4cc {
+ background-position: 57.14286% 73.80952%;
+}
+
+.emojione-1f4cd {
+ background-position: 59.52381% 73.80952%;
+}
+
+.emojione-1f4ce {
+ background-position: 61.90476% 73.80952%;
+}
+
+.emojione-1f4cf {
+ background-position: 64.28571% 73.80952%;
+}
+
+.emojione-1f4d0 {
+ background-position: 66.66667% 73.80952%;
+}
+
+.emojione-1f4d1 {
+ background-position: 69.04762% 73.80952%;
+}
+
+.emojione-1f4d2 {
+ background-position: 71.42857% 73.80952%;
+}
+
+.emojione-1f4d3 {
+ background-position: 73.80952% 73.80952%;
+}
+
+.emojione-1f4d4 {
+ background-position: 76.19048% 0%;
+}
+
+.emojione-1f4d5 {
+ background-position: 76.19048% 2.38095%;
+}
+
+.emojione-1f4d6 {
+ background-position: 76.19048% 4.7619%;
+}
+
+.emojione-1f4d7 {
+ background-position: 76.19048% 7.14286%;
+}
+
+.emojione-1f4d8 {
+ background-position: 76.19048% 9.52381%;
+}
+
+.emojione-1f4d9 {
+ background-position: 76.19048% 11.90476%;
+}
+
+.emojione-1f4da {
+ background-position: 76.19048% 14.28571%;
+}
+
+.emojione-1f4db {
+ background-position: 76.19048% 16.66667%;
+}
+
+.emojione-1f4dc {
+ background-position: 76.19048% 19.04762%;
+}
+
+.emojione-1f4dd {
+ background-position: 76.19048% 21.42857%;
+}
+
+.emojione-1f4de {
+ background-position: 76.19048% 23.80952%;
+}
+
+.emojione-1f4df {
+ background-position: 76.19048% 26.19048%;
+}
+
+.emojione-1f4e0 {
+ background-position: 76.19048% 28.57143%;
+}
+
+.emojione-1f4e1 {
+ background-position: 76.19048% 30.95238%;
+}
+
+.emojione-1f4e2 {
+ background-position: 76.19048% 33.33333%;
+}
+
+.emojione-1f4e3 {
+ background-position: 76.19048% 35.71429%;
+}
+
+.emojione-1f4e4 {
+ background-position: 76.19048% 38.09524%;
+}
+
+.emojione-1f4e5 {
+ background-position: 76.19048% 40.47619%;
+}
+
+.emojione-1f4e6 {
+ background-position: 76.19048% 42.85714%;
+}
+
+.emojione-1f4e7 {
+ background-position: 76.19048% 45.2381%;
+}
+
+.emojione-1f4e8 {
+ background-position: 76.19048% 47.61905%;
+}
+
+.emojione-1f4e9 {
+ background-position: 76.19048% 50%;
+}
+
+.emojione-1f4ea {
+ background-position: 76.19048% 52.38095%;
+}
+
+.emojione-1f4eb {
+ background-position: 76.19048% 54.7619%;
+}
+
+.emojione-1f4ec {
+ background-position: 76.19048% 57.14286%;
+}
+
+.emojione-1f4ed {
+ background-position: 76.19048% 59.52381%;
+}
+
+.emojione-1f4ee {
+ background-position: 76.19048% 61.90476%;
+}
+
+.emojione-1f4ef {
+ background-position: 76.19048% 64.28571%;
+}
+
+.emojione-1f4f0 {
+ background-position: 76.19048% 66.66667%;
+}
+
+.emojione-1f4f1 {
+ background-position: 76.19048% 69.04762%;
+}
+
+.emojione-1f4f2 {
+ background-position: 76.19048% 71.42857%;
+}
+
+.emojione-1f4f3 {
+ background-position: 76.19048% 73.80952%;
+}
+
+.emojione-1f4f4 {
+ background-position: 0% 76.19048%;
+}
+
+.emojione-1f4f5 {
+ background-position: 2.38095% 76.19048%;
+}
+
+.emojione-1f4f6 {
+ background-position: 4.7619% 76.19048%;
+}
+
+.emojione-1f4f7 {
+ background-position: 7.14286% 76.19048%;
+}
+
+.emojione-1f4f8 {
+ background-position: 9.52381% 76.19048%;
+}
+
+.emojione-1f4f9 {
+ background-position: 11.90476% 76.19048%;
+}
+
+.emojione-1f4fa {
+ background-position: 14.28571% 76.19048%;
+}
+
+.emojione-1f4fb {
+ background-position: 16.66667% 76.19048%;
+}
+
+.emojione-1f4fc {
+ background-position: 19.04762% 76.19048%;
+}
+
+.emojione-1f4fd {
+ background-position: 21.42857% 76.19048%;
+}
+
+.emojione-1f4ff {
+ background-position: 23.80952% 76.19048%;
+}
+
+.emojione-1f500 {
+ background-position: 26.19048% 76.19048%;
+}
+
+.emojione-1f501 {
+ background-position: 28.57143% 76.19048%;
+}
+
+.emojione-1f502 {
+ background-position: 30.95238% 76.19048%;
+}
+
+.emojione-1f503 {
+ background-position: 33.33333% 76.19048%;
+}
+
+.emojione-1f504 {
+ background-position: 35.71429% 76.19048%;
+}
+
+.emojione-1f505 {
+ background-position: 38.09524% 76.19048%;
+}
+
+.emojione-1f506 {
+ background-position: 40.47619% 76.19048%;
+}
+
+.emojione-1f507 {
+ background-position: 42.85714% 76.19048%;
+}
+
+.emojione-1f508 {
+ background-position: 45.2381% 76.19048%;
+}
+
+.emojione-1f509 {
+ background-position: 47.61905% 76.19048%;
+}
+
+.emojione-1f50a {
+ background-position: 50% 76.19048%;
+}
+
+.emojione-1f50b {
+ background-position: 52.38095% 76.19048%;
+}
+
+.emojione-1f50c {
+ background-position: 54.7619% 76.19048%;
+}
+
+.emojione-1f50d {
+ background-position: 57.14286% 76.19048%;
+}
+
+.emojione-1f50e {
+ background-position: 59.52381% 76.19048%;
+}
+
+.emojione-1f50f {
+ background-position: 61.90476% 76.19048%;
+}
+
+.emojione-1f510 {
+ background-position: 64.28571% 76.19048%;
+}
+
+.emojione-1f511 {
+ background-position: 66.66667% 76.19048%;
+}
+
+.emojione-1f512 {
+ background-position: 69.04762% 76.19048%;
+}
+
+.emojione-1f513 {
+ background-position: 71.42857% 76.19048%;
+}
+
+.emojione-1f514 {
+ background-position: 73.80952% 76.19048%;
+}
+
+.emojione-1f515 {
+ background-position: 76.19048% 76.19048%;
+}
+
+.emojione-1f516 {
+ background-position: 78.57143% 0%;
+}
+
+.emojione-1f517 {
+ background-position: 78.57143% 2.38095%;
+}
+
+.emojione-1f518 {
+ background-position: 78.57143% 4.7619%;
+}
+
+.emojione-1f519 {
+ background-position: 78.57143% 7.14286%;
+}
+
+.emojione-1f51a {
+ background-position: 78.57143% 9.52381%;
+}
+
+.emojione-1f51b {
+ background-position: 78.57143% 11.90476%;
+}
+
+.emojione-1f51c {
+ background-position: 78.57143% 14.28571%;
+}
+
+.emojione-1f51d {
+ background-position: 78.57143% 16.66667%;
+}
+
+.emojione-1f51e {
+ background-position: 78.57143% 19.04762%;
+}
+
+.emojione-1f51f {
+ background-position: 78.57143% 21.42857%;
+}
+
+.emojione-1f520 {
+ background-position: 78.57143% 23.80952%;
+}
+
+.emojione-1f521 {
+ background-position: 78.57143% 26.19048%;
+}
+
+.emojione-1f522 {
+ background-position: 78.57143% 28.57143%;
+}
+
+.emojione-1f523 {
+ background-position: 78.57143% 30.95238%;
+}
+
+.emojione-1f524 {
+ background-position: 78.57143% 33.33333%;
+}
+
+.emojione-1f525 {
+ background-position: 78.57143% 35.71429%;
+}
+
+.emojione-1f526 {
+ background-position: 78.57143% 38.09524%;
+}
+
+.emojione-1f527 {
+ background-position: 78.57143% 40.47619%;
+}
+
+.emojione-1f528 {
+ background-position: 78.57143% 42.85714%;
+}
+
+.emojione-1f529 {
+ background-position: 78.57143% 45.2381%;
+}
+
+.emojione-1f52a {
+ background-position: 78.57143% 47.61905%;
+}
+
+.emojione-1f52b {
+ background-position: 78.57143% 50%;
+}
+
+.emojione-1f52c {
+ background-position: 78.57143% 52.38095%;
+}
+
+.emojione-1f52d {
+ background-position: 78.57143% 54.7619%;
+}
+
+.emojione-1f52e {
+ background-position: 78.57143% 57.14286%;
+}
+
+.emojione-1f52f {
+ background-position: 78.57143% 59.52381%;
+}
+
+.emojione-1f530 {
+ background-position: 78.57143% 61.90476%;
+}
+
+.emojione-1f531 {
+ background-position: 78.57143% 64.28571%;
+}
+
+.emojione-1f532 {
+ background-position: 78.57143% 66.66667%;
+}
+
+.emojione-1f533 {
+ background-position: 78.57143% 69.04762%;
+}
+
+.emojione-1f534 {
+ background-position: 78.57143% 71.42857%;
+}
+
+.emojione-1f535 {
+ background-position: 78.57143% 73.80952%;
+}
+
+.emojione-1f536 {
+ background-position: 78.57143% 76.19048%;
+}
+
+.emojione-1f537 {
+ background-position: 0% 78.57143%;
+}
+
+.emojione-1f538 {
+ background-position: 2.38095% 78.57143%;
+}
+
+.emojione-1f539 {
+ background-position: 4.7619% 78.57143%;
+}
+
+.emojione-1f53a {
+ background-position: 7.14286% 78.57143%;
+}
+
+.emojione-1f53b {
+ background-position: 9.52381% 78.57143%;
+}
+
+.emojione-1f53c {
+ background-position: 11.90476% 78.57143%;
+}
+
+.emojione-1f53d {
+ background-position: 14.28571% 78.57143%;
+}
+
+.emojione-1f549 {
+ background-position: 16.66667% 78.57143%;
+}
+
+.emojione-1f54a {
+ background-position: 19.04762% 78.57143%;
+}
+
+.emojione-1f54b {
+ background-position: 21.42857% 78.57143%;
+}
+
+.emojione-1f54c {
+ background-position: 23.80952% 78.57143%;
+}
+
+.emojione-1f54d {
+ background-position: 26.19048% 78.57143%;
+}
+
+.emojione-1f54e {
+ background-position: 28.57143% 78.57143%;
+}
+
+.emojione-1f550 {
+ background-position: 30.95238% 78.57143%;
+}
+
+.emojione-1f551 {
+ background-position: 33.33333% 78.57143%;
+}
+
+.emojione-1f552 {
+ background-position: 35.71429% 78.57143%;
+}
+
+.emojione-1f553 {
+ background-position: 38.09524% 78.57143%;
+}
+
+.emojione-1f554 {
+ background-position: 40.47619% 78.57143%;
+}
+
+.emojione-1f555 {
+ background-position: 42.85714% 78.57143%;
+}
+
+.emojione-1f556 {
+ background-position: 45.2381% 78.57143%;
+}
+
+.emojione-1f557 {
+ background-position: 47.61905% 78.57143%;
+}
+
+.emojione-1f558 {
+ background-position: 50% 78.57143%;
+}
+
+.emojione-1f559 {
+ background-position: 52.38095% 78.57143%;
+}
+
+.emojione-1f55a {
+ background-position: 54.7619% 78.57143%;
+}
+
+.emojione-1f55b {
+ background-position: 57.14286% 78.57143%;
+}
+
+.emojione-1f55c {
+ background-position: 59.52381% 78.57143%;
+}
+
+.emojione-1f55d {
+ background-position: 61.90476% 78.57143%;
+}
+
+.emojione-1f55e {
+ background-position: 64.28571% 78.57143%;
+}
+
+.emojione-1f55f {
+ background-position: 66.66667% 78.57143%;
+}
+
+.emojione-1f560 {
+ background-position: 69.04762% 78.57143%;
+}
+
+.emojione-1f561 {
+ background-position: 71.42857% 78.57143%;
+}
+
+.emojione-1f562 {
+ background-position: 73.80952% 78.57143%;
+}
+
+.emojione-1f563 {
+ background-position: 76.19048% 78.57143%;
+}
+
+.emojione-1f564 {
+ background-position: 78.57143% 78.57143%;
+}
+
+.emojione-1f565 {
+ background-position: 80.95238% 0%;
+}
+
+.emojione-1f566 {
+ background-position: 80.95238% 2.38095%;
+}
+
+.emojione-1f567 {
+ background-position: 80.95238% 4.7619%;
+}
+
+.emojione-1f56f {
+ background-position: 80.95238% 7.14286%;
+}
+
+.emojione-1f570 {
+ background-position: 80.95238% 9.52381%;
+}
+
+.emojione-1f573 {
+ background-position: 80.95238% 11.90476%;
+}
+
+.emojione-1f574 {
+ background-position: 80.95238% 14.28571%;
+}
+
+.emojione-1f575-1f3fb {
+ background-position: 80.95238% 16.66667%;
+}
+
+.emojione-1f575-1f3fc {
+ background-position: 80.95238% 19.04762%;
+}
+
+.emojione-1f575-1f3fd {
+ background-position: 80.95238% 21.42857%;
+}
+
+.emojione-1f575-1f3fe {
+ background-position: 80.95238% 23.80952%;
+}
+
+.emojione-1f575-1f3ff {
+ background-position: 80.95238% 26.19048%;
+}
+
+.emojione-1f575 {
+ background-position: 80.95238% 28.57143%;
+}
+
+.emojione-1f576 {
+ background-position: 80.95238% 30.95238%;
+}
+
+.emojione-1f577 {
+ background-position: 80.95238% 33.33333%;
+}
+
+.emojione-1f578 {
+ background-position: 80.95238% 35.71429%;
+}
+
+.emojione-1f579 {
+ background-position: 80.95238% 38.09524%;
+}
+
+.emojione-1f57a-1f3fb {
+ background-position: 80.95238% 40.47619%;
+}
+
+.emojione-1f57a-1f3fc {
+ background-position: 80.95238% 42.85714%;
+}
+
+.emojione-1f57a-1f3fd {
+ background-position: 80.95238% 45.2381%;
+}
+
+.emojione-1f57a-1f3fe {
+ background-position: 80.95238% 47.61905%;
+}
+
+.emojione-1f57a-1f3ff {
+ background-position: 80.95238% 50%;
+}
+
+.emojione-1f57a {
+ background-position: 80.95238% 52.38095%;
+}
+
+.emojione-1f587 {
+ background-position: 80.95238% 54.7619%;
+}
+
+.emojione-1f58a {
+ background-position: 80.95238% 57.14286%;
+}
+
+.emojione-1f58b {
+ background-position: 80.95238% 59.52381%;
+}
+
+.emojione-1f58c {
+ background-position: 80.95238% 61.90476%;
+}
+
+.emojione-1f58d {
+ background-position: 80.95238% 64.28571%;
+}
+
+.emojione-1f590-1f3fb {
+ background-position: 80.95238% 66.66667%;
+}
+
+.emojione-1f590-1f3fc {
+ background-position: 80.95238% 69.04762%;
+}
+
+.emojione-1f590-1f3fd {
+ background-position: 80.95238% 71.42857%;
+}
+
+.emojione-1f590-1f3fe {
+ background-position: 80.95238% 73.80952%;
+}
+
+.emojione-1f590-1f3ff {
+ background-position: 80.95238% 76.19048%;
+}
+
+.emojione-1f590 {
+ background-position: 80.95238% 78.57143%;
+}
+
+.emojione-1f595-1f3fb {
+ background-position: 0% 80.95238%;
+}
+
+.emojione-1f595-1f3fc {
+ background-position: 2.38095% 80.95238%;
+}
+
+.emojione-1f595-1f3fd {
+ background-position: 4.7619% 80.95238%;
+}
+
+.emojione-1f595-1f3fe {
+ background-position: 7.14286% 80.95238%;
+}
+
+.emojione-1f595-1f3ff {
+ background-position: 9.52381% 80.95238%;
+}
+
+.emojione-1f595 {
+ background-position: 11.90476% 80.95238%;
+}
+
+.emojione-1f596-1f3fb {
+ background-position: 14.28571% 80.95238%;
+}
+
+.emojione-1f596-1f3fc {
+ background-position: 16.66667% 80.95238%;
+}
+
+.emojione-1f596-1f3fd {
+ background-position: 19.04762% 80.95238%;
+}
+
+.emojione-1f596-1f3fe {
+ background-position: 21.42857% 80.95238%;
+}
+
+.emojione-1f596-1f3ff {
+ background-position: 23.80952% 80.95238%;
+}
+
+.emojione-1f596 {
+ background-position: 26.19048% 80.95238%;
+}
+
+.emojione-1f5a4 {
+ background-position: 28.57143% 80.95238%;
+}
+
+.emojione-1f5a5 {
+ background-position: 30.95238% 80.95238%;
+}
+
+.emojione-1f5a8 {
+ background-position: 33.33333% 80.95238%;
+}
+
+.emojione-1f5b1 {
+ background-position: 35.71429% 80.95238%;
+}
+
+.emojione-1f5b2 {
+ background-position: 38.09524% 80.95238%;
+}
+
+.emojione-1f5bc {
+ background-position: 40.47619% 80.95238%;
+}
+
+.emojione-1f5c2 {
+ background-position: 42.85714% 80.95238%;
+}
+
+.emojione-1f5c3 {
+ background-position: 45.2381% 80.95238%;
+}
+
+.emojione-1f5c4 {
+ background-position: 47.61905% 80.95238%;
+}
+
+.emojione-1f5d1 {
+ background-position: 50% 80.95238%;
+}
+
+.emojione-1f5d2 {
+ background-position: 52.38095% 80.95238%;
+}
+
+.emojione-1f5d3 {
+ background-position: 54.7619% 80.95238%;
+}
+
+.emojione-1f5dc {
+ background-position: 57.14286% 80.95238%;
+}
+
+.emojione-1f5dd {
+ background-position: 59.52381% 80.95238%;
+}
+
+.emojione-1f5de {
+ background-position: 61.90476% 80.95238%;
+}
+
+.emojione-1f5e1 {
+ background-position: 64.28571% 80.95238%;
+}
+
+.emojione-1f5e3 {
+ background-position: 66.66667% 80.95238%;
+}
+
+.emojione-1f5e8 {
+ background-position: 69.04762% 80.95238%;
+}
+
+.emojione-1f5ef {
+ background-position: 71.42857% 80.95238%;
+}
+
+.emojione-1f5f3 {
+ background-position: 73.80952% 80.95238%;
+}
+
+.emojione-1f5fa {
+ background-position: 76.19048% 80.95238%;
+}
+
+.emojione-1f5fb {
+ background-position: 78.57143% 80.95238%;
+}
+
+.emojione-1f5fc {
+ background-position: 80.95238% 80.95238%;
+}
+
+.emojione-1f5fd {
+ background-position: 83.33333% 0%;
+}
+
+.emojione-1f5fe {
+ background-position: 83.33333% 2.38095%;
+}
+
+.emojione-1f5ff {
+ background-position: 83.33333% 4.7619%;
+}
+
+.emojione-1f600 {
+ background-position: 83.33333% 7.14286%;
+}
+
+.emojione-1f601 {
+ background-position: 83.33333% 9.52381%;
+}
+
+.emojione-1f602 {
+ background-position: 83.33333% 11.90476%;
+}
+
+.emojione-1f603 {
+ background-position: 83.33333% 14.28571%;
+}
+
+.emojione-1f604 {
+ background-position: 83.33333% 16.66667%;
+}
+
+.emojione-1f605 {
+ background-position: 83.33333% 19.04762%;
+}
+
+.emojione-1f606 {
+ background-position: 83.33333% 21.42857%;
+}
+
+.emojione-1f607 {
+ background-position: 83.33333% 23.80952%;
+}
+
+.emojione-1f608 {
+ background-position: 83.33333% 26.19048%;
+}
+
+.emojione-1f609 {
+ background-position: 83.33333% 28.57143%;
+}
+
+.emojione-1f60a {
+ background-position: 83.33333% 30.95238%;
+}
+
+.emojione-1f60b {
+ background-position: 83.33333% 33.33333%;
+}
+
+.emojione-1f60c {
+ background-position: 83.33333% 35.71429%;
+}
+
+.emojione-1f60d {
+ background-position: 83.33333% 38.09524%;
+}
+
+.emojione-1f60e {
+ background-position: 83.33333% 40.47619%;
+}
+
+.emojione-1f60f {
+ background-position: 83.33333% 42.85714%;
+}
+
+.emojione-1f610 {
+ background-position: 83.33333% 45.2381%;
+}
+
+.emojione-1f611 {
+ background-position: 83.33333% 47.61905%;
+}
+
+.emojione-1f612 {
+ background-position: 83.33333% 50%;
+}
+
+.emojione-1f613 {
+ background-position: 83.33333% 52.38095%;
+}
+
+.emojione-1f614 {
+ background-position: 83.33333% 54.7619%;
+}
+
+.emojione-1f615 {
+ background-position: 83.33333% 57.14286%;
+}
+
+.emojione-1f616 {
+ background-position: 83.33333% 59.52381%;
+}
+
+.emojione-1f617 {
+ background-position: 83.33333% 61.90476%;
+}
+
+.emojione-1f618 {
+ background-position: 83.33333% 64.28571%;
+}
+
+.emojione-1f619 {
+ background-position: 83.33333% 66.66667%;
+}
+
+.emojione-1f61a {
+ background-position: 83.33333% 69.04762%;
+}
+
+.emojione-1f61b {
+ background-position: 83.33333% 71.42857%;
+}
+
+.emojione-1f61c {
+ background-position: 83.33333% 73.80952%;
+}
+
+.emojione-1f61d {
+ background-position: 83.33333% 76.19048%;
+}
+
+.emojione-1f61e {
+ background-position: 83.33333% 78.57143%;
+}
+
+.emojione-1f61f {
+ background-position: 83.33333% 80.95238%;
+}
+
+.emojione-1f620 {
+ background-position: 0% 83.33333%;
+}
+
+.emojione-1f621 {
+ background-position: 2.38095% 83.33333%;
+}
+
+.emojione-1f622 {
+ background-position: 4.7619% 83.33333%;
+}
+
+.emojione-1f623 {
+ background-position: 7.14286% 83.33333%;
+}
+
+.emojione-1f624 {
+ background-position: 9.52381% 83.33333%;
+}
+
+.emojione-1f625 {
+ background-position: 11.90476% 83.33333%;
+}
+
+.emojione-1f626 {
+ background-position: 14.28571% 83.33333%;
+}
+
+.emojione-1f627 {
+ background-position: 16.66667% 83.33333%;
+}
+
+.emojione-1f628 {
+ background-position: 19.04762% 83.33333%;
+}
+
+.emojione-1f629 {
+ background-position: 21.42857% 83.33333%;
+}
+
+.emojione-1f62a {
+ background-position: 23.80952% 83.33333%;
+}
+
+.emojione-1f62b {
+ background-position: 26.19048% 83.33333%;
+}
+
+.emojione-1f62c {
+ background-position: 28.57143% 83.33333%;
+}
+
+.emojione-1f62d {
+ background-position: 30.95238% 83.33333%;
+}
+
+.emojione-1f62e {
+ background-position: 33.33333% 83.33333%;
+}
+
+.emojione-1f62f {
+ background-position: 35.71429% 83.33333%;
+}
+
+.emojione-1f630 {
+ background-position: 38.09524% 83.33333%;
+}
+
+.emojione-1f631 {
+ background-position: 40.47619% 83.33333%;
+}
+
+.emojione-1f632 {
+ background-position: 42.85714% 83.33333%;
+}
+
+.emojione-1f633 {
+ background-position: 45.2381% 83.33333%;
+}
+
+.emojione-1f634 {
+ background-position: 47.61905% 83.33333%;
+}
+
+.emojione-1f635 {
+ background-position: 50% 83.33333%;
+}
+
+.emojione-1f636 {
+ background-position: 52.38095% 83.33333%;
+}
+
+.emojione-1f637 {
+ background-position: 54.7619% 83.33333%;
+}
+
+.emojione-1f638 {
+ background-position: 57.14286% 83.33333%;
+}
+
+.emojione-1f639 {
+ background-position: 59.52381% 83.33333%;
+}
+
+.emojione-1f63a {
+ background-position: 61.90476% 83.33333%;
+}
+
+.emojione-1f63b {
+ background-position: 64.28571% 83.33333%;
+}
+
+.emojione-1f63c {
+ background-position: 66.66667% 83.33333%;
+}
+
+.emojione-1f63d {
+ background-position: 69.04762% 83.33333%;
+}
+
+.emojione-1f63e {
+ background-position: 71.42857% 83.33333%;
+}
+
+.emojione-1f63f {
+ background-position: 73.80952% 83.33333%;
+}
+
+.emojione-1f640 {
+ background-position: 76.19048% 83.33333%;
+}
+
+.emojione-1f641 {
+ background-position: 78.57143% 83.33333%;
+}
+
+.emojione-1f642 {
+ background-position: 80.95238% 83.33333%;
+}
+
+.emojione-1f643 {
+ background-position: 83.33333% 83.33333%;
+}
+
+.emojione-1f644 {
+ background-position: 85.71429% 0%;
+}
+
+.emojione-1f645-1f3fb {
+ background-position: 85.71429% 2.38095%;
+}
+
+.emojione-1f645-1f3fc {
+ background-position: 85.71429% 4.7619%;
+}
+
+.emojione-1f645-1f3fd {
+ background-position: 85.71429% 7.14286%;
+}
+
+.emojione-1f645-1f3fe {
+ background-position: 85.71429% 9.52381%;
+}
+
+.emojione-1f645-1f3ff {
+ background-position: 85.71429% 11.90476%;
+}
+
+.emojione-1f645 {
+ background-position: 85.71429% 14.28571%;
+}
+
+.emojione-1f646-1f3fb {
+ background-position: 85.71429% 16.66667%;
+}
+
+.emojione-1f646-1f3fc {
+ background-position: 85.71429% 19.04762%;
+}
+
+.emojione-1f646-1f3fd {
+ background-position: 85.71429% 21.42857%;
+}
+
+.emojione-1f646-1f3fe {
+ background-position: 85.71429% 23.80952%;
+}
+
+.emojione-1f646-1f3ff {
+ background-position: 85.71429% 26.19048%;
+}
+
+.emojione-1f646 {
+ background-position: 85.71429% 28.57143%;
+}
+
+.emojione-1f647-1f3fb {
+ background-position: 85.71429% 30.95238%;
+}
+
+.emojione-1f647-1f3fc {
+ background-position: 85.71429% 33.33333%;
+}
+
+.emojione-1f647-1f3fd {
+ background-position: 85.71429% 35.71429%;
+}
+
+.emojione-1f647-1f3fe {
+ background-position: 85.71429% 38.09524%;
+}
+
+.emojione-1f647-1f3ff {
+ background-position: 85.71429% 40.47619%;
+}
+
+.emojione-1f647 {
+ background-position: 85.71429% 42.85714%;
+}
+
+.emojione-1f648 {
+ background-position: 85.71429% 45.2381%;
+}
+
+.emojione-1f649 {
+ background-position: 85.71429% 47.61905%;
+}
+
+.emojione-1f64a {
+ background-position: 85.71429% 50%;
+}
+
+.emojione-1f64b-1f3fb {
+ background-position: 85.71429% 52.38095%;
+}
+
+.emojione-1f64b-1f3fc {
+ background-position: 85.71429% 54.7619%;
+}
+
+.emojione-1f64b-1f3fd {
+ background-position: 85.71429% 57.14286%;
+}
+
+.emojione-1f64b-1f3fe {
+ background-position: 85.71429% 59.52381%;
+}
+
+.emojione-1f64b-1f3ff {
+ background-position: 85.71429% 61.90476%;
+}
+
+.emojione-1f64b {
+ background-position: 85.71429% 64.28571%;
+}
+
+.emojione-1f64c-1f3fb {
+ background-position: 85.71429% 66.66667%;
+}
+
+.emojione-1f64c-1f3fc {
+ background-position: 85.71429% 69.04762%;
+}
+
+.emojione-1f64c-1f3fd {
+ background-position: 85.71429% 71.42857%;
+}
+
+.emojione-1f64c-1f3fe {
+ background-position: 85.71429% 73.80952%;
+}
+
+.emojione-1f64c-1f3ff {
+ background-position: 85.71429% 76.19048%;
+}
+
+.emojione-1f64c {
+ background-position: 85.71429% 78.57143%;
+}
+
+.emojione-1f64d-1f3fb {
+ background-position: 85.71429% 80.95238%;
+}
+
+.emojione-1f64d-1f3fc {
+ background-position: 85.71429% 83.33333%;
+}
+
+.emojione-1f64d-1f3fd {
+ background-position: 0% 85.71429%;
+}
+
+.emojione-1f64d-1f3fe {
+ background-position: 2.38095% 85.71429%;
+}
+
+.emojione-1f64d-1f3ff {
+ background-position: 4.7619% 85.71429%;
+}
+
+.emojione-1f64d {
+ background-position: 7.14286% 85.71429%;
+}
+
+.emojione-1f64e-1f3fb {
+ background-position: 9.52381% 85.71429%;
+}
+
+.emojione-1f64e-1f3fc {
+ background-position: 11.90476% 85.71429%;
+}
+
+.emojione-1f64e-1f3fd {
+ background-position: 14.28571% 85.71429%;
+}
+
+.emojione-1f64e-1f3fe {
+ background-position: 16.66667% 85.71429%;
+}
+
+.emojione-1f64e-1f3ff {
+ background-position: 19.04762% 85.71429%;
+}
+
+.emojione-1f64e {
+ background-position: 21.42857% 85.71429%;
+}
+
+.emojione-1f64f-1f3fb {
+ background-position: 23.80952% 85.71429%;
+}
+
+.emojione-1f64f-1f3fc {
+ background-position: 26.19048% 85.71429%;
+}
+
+.emojione-1f64f-1f3fd {
+ background-position: 28.57143% 85.71429%;
+}
+
+.emojione-1f64f-1f3fe {
+ background-position: 30.95238% 85.71429%;
+}
+
+.emojione-1f64f-1f3ff {
+ background-position: 33.33333% 85.71429%;
+}
+
+.emojione-1f64f {
+ background-position: 35.71429% 85.71429%;
+}
+
+.emojione-1f680 {
+ background-position: 38.09524% 85.71429%;
+}
+
+.emojione-1f681 {
+ background-position: 40.47619% 85.71429%;
+}
+
+.emojione-1f682 {
+ background-position: 42.85714% 85.71429%;
+}
+
+.emojione-1f683 {
+ background-position: 45.2381% 85.71429%;
+}
+
+.emojione-1f684 {
+ background-position: 47.61905% 85.71429%;
+}
+
+.emojione-1f685 {
+ background-position: 50% 85.71429%;
+}
+
+.emojione-1f686 {
+ background-position: 52.38095% 85.71429%;
+}
+
+.emojione-1f687 {
+ background-position: 54.7619% 85.71429%;
+}
+
+.emojione-1f688 {
+ background-position: 57.14286% 85.71429%;
+}
+
+.emojione-1f689 {
+ background-position: 59.52381% 85.71429%;
+}
+
+.emojione-1f68a {
+ background-position: 61.90476% 85.71429%;
+}
+
+.emojione-1f68b {
+ background-position: 64.28571% 85.71429%;
+}
+
+.emojione-1f68c {
+ background-position: 66.66667% 85.71429%;
+}
+
+.emojione-1f68d {
+ background-position: 69.04762% 85.71429%;
+}
+
+.emojione-1f68e {
+ background-position: 71.42857% 85.71429%;
+}
+
+.emojione-1f68f {
+ background-position: 73.80952% 85.71429%;
+}
+
+.emojione-1f690 {
+ background-position: 76.19048% 85.71429%;
+}
+
+.emojione-1f691 {
+ background-position: 78.57143% 85.71429%;
+}
+
+.emojione-1f692 {
+ background-position: 80.95238% 85.71429%;
+}
+
+.emojione-1f693 {
+ background-position: 83.33333% 85.71429%;
+}
+
+.emojione-1f694 {
+ background-position: 85.71429% 85.71429%;
+}
+
+.emojione-1f695 {
+ background-position: 88.09524% 0%;
+}
+
+.emojione-1f696 {
+ background-position: 88.09524% 2.38095%;
+}
+
+.emojione-1f697 {
+ background-position: 88.09524% 4.7619%;
+}
+
+.emojione-1f698 {
+ background-position: 88.09524% 7.14286%;
+}
+
+.emojione-1f699 {
+ background-position: 88.09524% 9.52381%;
+}
+
+.emojione-1f69a {
+ background-position: 88.09524% 11.90476%;
+}
+
+.emojione-1f69b {
+ background-position: 88.09524% 14.28571%;
+}
+
+.emojione-1f69c {
+ background-position: 88.09524% 16.66667%;
+}
+
+.emojione-1f69d {
+ background-position: 88.09524% 19.04762%;
+}
+
+.emojione-1f69e {
+ background-position: 88.09524% 21.42857%;
+}
+
+.emojione-1f69f {
+ background-position: 88.09524% 23.80952%;
+}
+
+.emojione-1f6a0 {
+ background-position: 88.09524% 26.19048%;
+}
+
+.emojione-1f6a1 {
+ background-position: 88.09524% 28.57143%;
+}
+
+.emojione-1f6a2 {
+ background-position: 88.09524% 30.95238%;
+}
+
+.emojione-1f6a3-1f3fb {
+ background-position: 88.09524% 33.33333%;
+}
+
+.emojione-1f6a3-1f3fc {
+ background-position: 88.09524% 35.71429%;
+}
+
+.emojione-1f6a3-1f3fd {
+ background-position: 88.09524% 38.09524%;
+}
+
+.emojione-1f6a3-1f3fe {
+ background-position: 88.09524% 40.47619%;
+}
+
+.emojione-1f6a3-1f3ff {
+ background-position: 88.09524% 42.85714%;
+}
+
+.emojione-1f6a3 {
+ background-position: 88.09524% 45.2381%;
+}
+
+.emojione-1f6a4 {
+ background-position: 88.09524% 47.61905%;
+}
+
+.emojione-1f6a5 {
+ background-position: 88.09524% 50%;
+}
+
+.emojione-1f6a6 {
+ background-position: 88.09524% 52.38095%;
+}
+
+.emojione-1f6a7 {
+ background-position: 88.09524% 54.7619%;
+}
+
+.emojione-1f6a8 {
+ background-position: 88.09524% 57.14286%;
+}
+
+.emojione-1f6a9 {
+ background-position: 88.09524% 59.52381%;
+}
+
+.emojione-1f6aa {
+ background-position: 88.09524% 61.90476%;
+}
+
+.emojione-1f6ab {
+ background-position: 88.09524% 64.28571%;
+}
+
+.emojione-1f6ac {
+ background-position: 88.09524% 66.66667%;
+}
+
+.emojione-1f6ad {
+ background-position: 88.09524% 69.04762%;
+}
+
+.emojione-1f6ae {
+ background-position: 88.09524% 71.42857%;
+}
+
+.emojione-1f6af {
+ background-position: 88.09524% 73.80952%;
+}
+
+.emojione-1f6b0 {
+ background-position: 88.09524% 76.19048%;
+}
+
+.emojione-1f6b1 {
+ background-position: 88.09524% 78.57143%;
+}
+
+.emojione-1f6b2 {
+ background-position: 88.09524% 80.95238%;
+}
+
+.emojione-1f6b3 {
+ background-position: 88.09524% 83.33333%;
+}
+
+.emojione-1f6b4-1f3fb {
+ background-position: 88.09524% 85.71429%;
+}
+
+.emojione-1f6b4-1f3fc {
+ background-position: 0% 88.09524%;
+}
+
+.emojione-1f6b4-1f3fd {
+ background-position: 2.38095% 88.09524%;
+}
+
+.emojione-1f6b4-1f3fe {
+ background-position: 4.7619% 88.09524%;
+}
+
+.emojione-1f6b4-1f3ff {
+ background-position: 7.14286% 88.09524%;
+}
+
+.emojione-1f6b4 {
+ background-position: 9.52381% 88.09524%;
+}
+
+.emojione-1f6b5-1f3fb {
+ background-position: 11.90476% 88.09524%;
+}
+
+.emojione-1f6b5-1f3fc {
+ background-position: 14.28571% 88.09524%;
+}
+
+.emojione-1f6b5-1f3fd {
+ background-position: 16.66667% 88.09524%;
+}
+
+.emojione-1f6b5-1f3fe {
+ background-position: 19.04762% 88.09524%;
+}
+
+.emojione-1f6b5-1f3ff {
+ background-position: 21.42857% 88.09524%;
+}
+
+.emojione-1f6b5 {
+ background-position: 23.80952% 88.09524%;
+}
+
+.emojione-1f6b6-1f3fb {
+ background-position: 26.19048% 88.09524%;
+}
+
+.emojione-1f6b6-1f3fc {
+ background-position: 28.57143% 88.09524%;
+}
+
+.emojione-1f6b6-1f3fd {
+ background-position: 30.95238% 88.09524%;
+}
+
+.emojione-1f6b6-1f3fe {
+ background-position: 33.33333% 88.09524%;
+}
+
+.emojione-1f6b6-1f3ff {
+ background-position: 35.71429% 88.09524%;
+}
+
+.emojione-1f6b6 {
+ background-position: 38.09524% 88.09524%;
+}
+
+.emojione-1f6b7 {
+ background-position: 40.47619% 88.09524%;
+}
+
+.emojione-1f6b8 {
+ background-position: 42.85714% 88.09524%;
+}
+
+.emojione-1f6b9 {
+ background-position: 45.2381% 88.09524%;
+}
+
+.emojione-1f6ba {
+ background-position: 47.61905% 88.09524%;
+}
+
+.emojione-1f6bb {
+ background-position: 50% 88.09524%;
+}
+
+.emojione-1f6bc {
+ background-position: 52.38095% 88.09524%;
+}
+
+.emojione-1f6bd {
+ background-position: 54.7619% 88.09524%;
+}
+
+.emojione-1f6be {
+ background-position: 57.14286% 88.09524%;
+}
+
+.emojione-1f6bf {
+ background-position: 59.52381% 88.09524%;
+}
+
+.emojione-1f6c0-1f3fb {
+ background-position: 61.90476% 88.09524%;
+}
+
+.emojione-1f6c0-1f3fc {
+ background-position: 64.28571% 88.09524%;
+}
+
+.emojione-1f6c0-1f3fd {
+ background-position: 66.66667% 88.09524%;
+}
+
+.emojione-1f6c0-1f3fe {
+ background-position: 69.04762% 88.09524%;
+}
+
+.emojione-1f6c0-1f3ff {
+ background-position: 71.42857% 88.09524%;
+}
+
+.emojione-1f6c0 {
+ background-position: 73.80952% 88.09524%;
+}
+
+.emojione-1f6c1 {
+ background-position: 76.19048% 88.09524%;
+}
+
+.emojione-1f6c2 {
+ background-position: 78.57143% 88.09524%;
+}
+
+.emojione-1f6c3 {
+ background-position: 80.95238% 88.09524%;
+}
+
+.emojione-1f6c4 {
+ background-position: 83.33333% 88.09524%;
+}
+
+.emojione-1f6c5 {
+ background-position: 85.71429% 88.09524%;
+}
+
+.emojione-1f6cb {
+ background-position: 88.09524% 88.09524%;
+}
+
+.emojione-1f6cc {
+ background-position: 90.47619% 0%;
+}
+
+.emojione-1f6cd {
+ background-position: 90.47619% 2.38095%;
+}
+
+.emojione-1f6ce {
+ background-position: 90.47619% 4.7619%;
+}
+
+.emojione-1f6cf {
+ background-position: 90.47619% 7.14286%;
+}
+
+.emojione-1f6d0 {
+ background-position: 90.47619% 9.52381%;
+}
+
+.emojione-1f6d1 {
+ background-position: 90.47619% 11.90476%;
+}
+
+.emojione-1f6d2 {
+ background-position: 90.47619% 14.28571%;
+}
+
+.emojione-1f6e0 {
+ background-position: 90.47619% 16.66667%;
+}
+
+.emojione-1f6e1 {
+ background-position: 90.47619% 19.04762%;
+}
+
+.emojione-1f6e2 {
+ background-position: 90.47619% 21.42857%;
+}
+
+.emojione-1f6e3 {
+ background-position: 90.47619% 23.80952%;
+}
+
+.emojione-1f6e4 {
+ background-position: 90.47619% 26.19048%;
+}
+
+.emojione-1f6e5 {
+ background-position: 90.47619% 28.57143%;
+}
+
+.emojione-1f6e9 {
+ background-position: 90.47619% 30.95238%;
+}
+
+.emojione-1f6eb {
+ background-position: 90.47619% 33.33333%;
+}
+
+.emojione-1f6ec {
+ background-position: 90.47619% 35.71429%;
+}
+
+.emojione-1f6f0 {
+ background-position: 90.47619% 38.09524%;
+}
+
+.emojione-1f6f3 {
+ background-position: 90.47619% 40.47619%;
+}
+
+.emojione-1f6f4 {
+ background-position: 90.47619% 42.85714%;
+}
+
+.emojione-1f6f5 {
+ background-position: 90.47619% 45.2381%;
+}
+
+.emojione-1f6f6 {
+ background-position: 90.47619% 47.61905%;
+}
+
+.emojione-1f910 {
+ background-position: 90.47619% 50%;
+}
+
+.emojione-1f911 {
+ background-position: 90.47619% 52.38095%;
+}
+
+.emojione-1f912 {
+ background-position: 90.47619% 54.7619%;
+}
+
+.emojione-1f913 {
+ background-position: 90.47619% 57.14286%;
+}
+
+.emojione-1f914 {
+ background-position: 90.47619% 59.52381%;
+}
+
+.emojione-1f915 {
+ background-position: 90.47619% 61.90476%;
+}
+
+.emojione-1f916 {
+ background-position: 90.47619% 64.28571%;
+}
+
+.emojione-1f917 {
+ background-position: 90.47619% 66.66667%;
+}
+
+.emojione-1f918-1f3fb {
+ background-position: 90.47619% 69.04762%;
+}
+
+.emojione-1f918-1f3fc {
+ background-position: 90.47619% 71.42857%;
+}
+
+.emojione-1f918-1f3fd {
+ background-position: 90.47619% 73.80952%;
+}
+
+.emojione-1f918-1f3fe {
+ background-position: 90.47619% 76.19048%;
+}
+
+.emojione-1f918-1f3ff {
+ background-position: 90.47619% 78.57143%;
+}
+
+.emojione-1f918 {
+ background-position: 90.47619% 80.95238%;
+}
+
+.emojione-1f919-1f3fb {
+ background-position: 90.47619% 83.33333%;
+}
+
+.emojione-1f919-1f3fc {
+ background-position: 90.47619% 85.71429%;
+}
+
+.emojione-1f919-1f3fd {
+ background-position: 90.47619% 88.09524%;
+}
+
+.emojione-1f919-1f3fe {
+ background-position: 0% 90.47619%;
+}
+
+.emojione-1f919-1f3ff {
+ background-position: 2.38095% 90.47619%;
+}
+
+.emojione-1f919 {
+ background-position: 4.7619% 90.47619%;
+}
+
+.emojione-1f91a-1f3fb {
+ background-position: 7.14286% 90.47619%;
+}
+
+.emojione-1f91a-1f3fc {
+ background-position: 9.52381% 90.47619%;
+}
+
+.emojione-1f91a-1f3fd {
+ background-position: 11.90476% 90.47619%;
+}
+
+.emojione-1f91a-1f3fe {
+ background-position: 14.28571% 90.47619%;
+}
+
+.emojione-1f91a-1f3ff {
+ background-position: 16.66667% 90.47619%;
+}
+
+.emojione-1f91a {
+ background-position: 19.04762% 90.47619%;
+}
+
+.emojione-1f91b-1f3fb {
+ background-position: 21.42857% 90.47619%;
+}
+
+.emojione-1f91b-1f3fc {
+ background-position: 23.80952% 90.47619%;
+}
+
+.emojione-1f91b-1f3fd {
+ background-position: 26.19048% 90.47619%;
+}
+
+.emojione-1f91b-1f3fe {
+ background-position: 28.57143% 90.47619%;
+}
+
+.emojione-1f91b-1f3ff {
+ background-position: 30.95238% 90.47619%;
+}
+
+.emojione-1f91b {
+ background-position: 33.33333% 90.47619%;
+}
+
+.emojione-1f91c-1f3fb {
+ background-position: 35.71429% 90.47619%;
+}
+
+.emojione-1f91c-1f3fc {
+ background-position: 38.09524% 90.47619%;
+}
+
+.emojione-1f91c-1f3fd {
+ background-position: 40.47619% 90.47619%;
+}
+
+.emojione-1f91c-1f3fe {
+ background-position: 42.85714% 90.47619%;
+}
+
+.emojione-1f91c-1f3ff {
+ background-position: 45.2381% 90.47619%;
+}
+
+.emojione-1f91c {
+ background-position: 47.61905% 90.47619%;
+}
+
+.emojione-1f91d-1f3fb {
+ background-position: 50% 90.47619%;
+}
+
+.emojione-1f91d-1f3fc {
+ background-position: 52.38095% 90.47619%;
+}
+
+.emojione-1f91d-1f3fd {
+ background-position: 54.7619% 90.47619%;
+}
+
+.emojione-1f91d-1f3fe {
+ background-position: 57.14286% 90.47619%;
+}
+
+.emojione-1f91d-1f3ff {
+ background-position: 59.52381% 90.47619%;
+}
+
+.emojione-1f91d {
+ background-position: 61.90476% 90.47619%;
+}
+
+.emojione-1f91e-1f3fb {
+ background-position: 64.28571% 90.47619%;
+}
+
+.emojione-1f91e-1f3fc {
+ background-position: 66.66667% 90.47619%;
+}
+
+.emojione-1f91e-1f3fd {
+ background-position: 69.04762% 90.47619%;
+}
+
+.emojione-1f91e-1f3fe {
+ background-position: 71.42857% 90.47619%;
+}
+
+.emojione-1f91e-1f3ff {
+ background-position: 73.80952% 90.47619%;
+}
+
+.emojione-1f91e {
+ background-position: 76.19048% 90.47619%;
+}
+
+.emojione-1f920 {
+ background-position: 78.57143% 90.47619%;
+}
+
+.emojione-1f921 {
+ background-position: 80.95238% 90.47619%;
+}
+
+.emojione-1f922 {
+ background-position: 83.33333% 90.47619%;
+}
+
+.emojione-1f923 {
+ background-position: 85.71429% 90.47619%;
+}
+
+.emojione-1f924 {
+ background-position: 88.09524% 90.47619%;
+}
+
+.emojione-1f925 {
+ background-position: 90.47619% 90.47619%;
+}
+
+.emojione-1f926-1f3fb {
+ background-position: 92.85714% 0%;
+}
+
+.emojione-1f926-1f3fc {
+ background-position: 92.85714% 2.38095%;
+}
+
+.emojione-1f926-1f3fd {
+ background-position: 92.85714% 4.7619%;
+}
+
+.emojione-1f926-1f3fe {
+ background-position: 92.85714% 7.14286%;
+}
+
+.emojione-1f926-1f3ff {
+ background-position: 92.85714% 9.52381%;
+}
+
+.emojione-1f926 {
+ background-position: 92.85714% 11.90476%;
+}
+
+.emojione-1f927 {
+ background-position: 92.85714% 14.28571%;
+}
+
+.emojione-1f930-1f3fb {
+ background-position: 92.85714% 16.66667%;
+}
+
+.emojione-1f930-1f3fc {
+ background-position: 92.85714% 19.04762%;
+}
+
+.emojione-1f930-1f3fd {
+ background-position: 92.85714% 21.42857%;
+}
+
+.emojione-1f930-1f3fe {
+ background-position: 92.85714% 23.80952%;
+}
+
+.emojione-1f930-1f3ff {
+ background-position: 92.85714% 26.19048%;
+}
+
+.emojione-1f930 {
+ background-position: 92.85714% 28.57143%;
+}
+
+.emojione-1f933-1f3fb {
+ background-position: 92.85714% 30.95238%;
+}
+
+.emojione-1f933-1f3fc {
+ background-position: 92.85714% 33.33333%;
+}
+
+.emojione-1f933-1f3fd {
+ background-position: 92.85714% 35.71429%;
+}
+
+.emojione-1f933-1f3fe {
+ background-position: 92.85714% 38.09524%;
+}
+
+.emojione-1f933-1f3ff {
+ background-position: 92.85714% 40.47619%;
+}
+
+.emojione-1f933 {
+ background-position: 92.85714% 42.85714%;
+}
+
+.emojione-1f934-1f3fb {
+ background-position: 92.85714% 45.2381%;
+}
+
+.emojione-1f934-1f3fc {
+ background-position: 92.85714% 47.61905%;
+}
+
+.emojione-1f934-1f3fd {
+ background-position: 92.85714% 50%;
+}
+
+.emojione-1f934-1f3fe {
+ background-position: 92.85714% 52.38095%;
+}
+
+.emojione-1f934-1f3ff {
+ background-position: 92.85714% 54.7619%;
+}
+
+.emojione-1f934 {
+ background-position: 92.85714% 57.14286%;
+}
+
+.emojione-1f935-1f3fb {
+ background-position: 92.85714% 59.52381%;
+}
+
+.emojione-1f935-1f3fc {
+ background-position: 92.85714% 61.90476%;
+}
+
+.emojione-1f935-1f3fd {
+ background-position: 92.85714% 64.28571%;
+}
+
+.emojione-1f935-1f3fe {
+ background-position: 92.85714% 66.66667%;
+}
+
+.emojione-1f935-1f3ff {
+ background-position: 92.85714% 69.04762%;
+}
+
+.emojione-1f935 {
+ background-position: 92.85714% 71.42857%;
+}
+
+.emojione-1f936-1f3fb {
+ background-position: 92.85714% 73.80952%;
+}
+
+.emojione-1f936-1f3fc {
+ background-position: 92.85714% 76.19048%;
+}
+
+.emojione-1f936-1f3fd {
+ background-position: 92.85714% 78.57143%;
+}
+
+.emojione-1f936-1f3fe {
+ background-position: 92.85714% 80.95238%;
+}
+
+.emojione-1f936-1f3ff {
+ background-position: 92.85714% 83.33333%;
+}
+
+.emojione-1f936 {
+ background-position: 92.85714% 85.71429%;
+}
+
+.emojione-1f937-1f3fb {
+ background-position: 92.85714% 88.09524%;
+}
+
+.emojione-1f937-1f3fc {
+ background-position: 92.85714% 90.47619%;
+}
+
+.emojione-1f937-1f3fd {
+ background-position: 0% 92.85714%;
+}
+
+.emojione-1f937-1f3fe {
+ background-position: 2.38095% 92.85714%;
+}
+
+.emojione-1f937-1f3ff {
+ background-position: 4.7619% 92.85714%;
+}
+
+.emojione-1f937 {
+ background-position: 7.14286% 92.85714%;
+}
+
+.emojione-1f938-1f3fb {
+ background-position: 9.52381% 92.85714%;
+}
+
+.emojione-1f938-1f3fc {
+ background-position: 11.90476% 92.85714%;
+}
+
+.emojione-1f938-1f3fd {
+ background-position: 14.28571% 92.85714%;
+}
+
+.emojione-1f938-1f3fe {
+ background-position: 16.66667% 92.85714%;
+}
+
+.emojione-1f938-1f3ff {
+ background-position: 19.04762% 92.85714%;
+}
+
+.emojione-1f938 {
+ background-position: 21.42857% 92.85714%;
+}
+
+.emojione-1f939-1f3fb {
+ background-position: 23.80952% 92.85714%;
+}
+
+.emojione-1f939-1f3fc {
+ background-position: 26.19048% 92.85714%;
+}
+
+.emojione-1f939-1f3fd {
+ background-position: 28.57143% 92.85714%;
+}
+
+.emojione-1f939-1f3fe {
+ background-position: 30.95238% 92.85714%;
+}
+
+.emojione-1f939-1f3ff {
+ background-position: 33.33333% 92.85714%;
+}
+
+.emojione-1f939 {
+ background-position: 35.71429% 92.85714%;
+}
+
+.emojione-1f93a {
+ background-position: 38.09524% 92.85714%;
+}
+
+.emojione-1f93c-1f3fb {
+ background-position: 40.47619% 92.85714%;
+}
+
+.emojione-1f93c-1f3fc {
+ background-position: 42.85714% 92.85714%;
+}
+
+.emojione-1f93c-1f3fd {
+ background-position: 45.2381% 92.85714%;
+}
+
+.emojione-1f93c-1f3fe {
+ background-position: 47.61905% 92.85714%;
+}
+
+.emojione-1f93c-1f3ff {
+ background-position: 50% 92.85714%;
+}
+
+.emojione-1f93c {
+ background-position: 52.38095% 92.85714%;
+}
+
+.emojione-1f93d-1f3fb {
+ background-position: 54.7619% 92.85714%;
+}
+
+.emojione-1f93d-1f3fc {
+ background-position: 57.14286% 92.85714%;
+}
+
+.emojione-1f93d-1f3fd {
+ background-position: 59.52381% 92.85714%;
+}
+
+.emojione-1f93d-1f3fe {
+ background-position: 61.90476% 92.85714%;
+}
+
+.emojione-1f93d-1f3ff {
+ background-position: 64.28571% 92.85714%;
+}
+
+.emojione-1f93d {
+ background-position: 66.66667% 92.85714%;
+}
+
+.emojione-1f93e-1f3fb {
+ background-position: 69.04762% 92.85714%;
+}
+
+.emojione-1f93e-1f3fc {
+ background-position: 71.42857% 92.85714%;
+}
+
+.emojione-1f93e-1f3fd {
+ background-position: 73.80952% 92.85714%;
+}
+
+.emojione-1f93e-1f3fe {
+ background-position: 76.19048% 92.85714%;
+}
+
+.emojione-1f93e-1f3ff {
+ background-position: 78.57143% 92.85714%;
+}
+
+.emojione-1f93e {
+ background-position: 80.95238% 92.85714%;
+}
+
+.emojione-1f940 {
+ background-position: 83.33333% 92.85714%;
+}
+
+.emojione-1f941 {
+ background-position: 85.71429% 92.85714%;
+}
+
+.emojione-1f942 {
+ background-position: 88.09524% 92.85714%;
+}
+
+.emojione-1f943 {
+ background-position: 90.47619% 92.85714%;
+}
+
+.emojione-1f944 {
+ background-position: 92.85714% 92.85714%;
+}
+
+.emojione-1f945 {
+ background-position: 95.2381% 0%;
+}
+
+.emojione-1f947 {
+ background-position: 95.2381% 2.38095%;
+}
+
+.emojione-1f948 {
+ background-position: 95.2381% 4.7619%;
+}
+
+.emojione-1f949 {
+ background-position: 95.2381% 7.14286%;
+}
+
+.emojione-1f94a {
+ background-position: 95.2381% 9.52381%;
+}
+
+.emojione-1f94b {
+ background-position: 95.2381% 11.90476%;
+}
+
+.emojione-1f950 {
+ background-position: 95.2381% 14.28571%;
+}
+
+.emojione-1f951 {
+ background-position: 95.2381% 16.66667%;
+}
+
+.emojione-1f952 {
+ background-position: 95.2381% 19.04762%;
+}
+
+.emojione-1f953 {
+ background-position: 95.2381% 21.42857%;
+}
+
+.emojione-1f954 {
+ background-position: 95.2381% 23.80952%;
+}
+
+.emojione-1f955 {
+ background-position: 95.2381% 26.19048%;
+}
+
+.emojione-1f956 {
+ background-position: 95.2381% 28.57143%;
+}
+
+.emojione-1f957 {
+ background-position: 95.2381% 30.95238%;
+}
+
+.emojione-1f958 {
+ background-position: 95.2381% 33.33333%;
+}
+
+.emojione-1f959 {
+ background-position: 95.2381% 35.71429%;
+}
+
+.emojione-1f95a {
+ background-position: 95.2381% 38.09524%;
+}
+
+.emojione-1f95b {
+ background-position: 95.2381% 40.47619%;
+}
+
+.emojione-1f95c {
+ background-position: 95.2381% 42.85714%;
+}
+
+.emojione-1f95d {
+ background-position: 95.2381% 45.2381%;
+}
+
+.emojione-1f95e {
+ background-position: 95.2381% 47.61905%;
+}
+
+.emojione-1f980 {
+ background-position: 95.2381% 50%;
+}
+
+.emojione-1f981 {
+ background-position: 95.2381% 52.38095%;
+}
+
+.emojione-1f982 {
+ background-position: 95.2381% 54.7619%;
+}
+
+.emojione-1f983 {
+ background-position: 95.2381% 57.14286%;
+}
+
+.emojione-1f984 {
+ background-position: 95.2381% 59.52381%;
+}
+
+.emojione-1f985 {
+ background-position: 95.2381% 61.90476%;
+}
+
+.emojione-1f986 {
+ background-position: 95.2381% 64.28571%;
+}
+
+.emojione-1f987 {
+ background-position: 95.2381% 66.66667%;
+}
+
+.emojione-1f988 {
+ background-position: 95.2381% 69.04762%;
+}
+
+.emojione-1f989 {
+ background-position: 95.2381% 71.42857%;
+}
+
+.emojione-1f98a {
+ background-position: 95.2381% 73.80952%;
+}
+
+.emojione-1f98b {
+ background-position: 95.2381% 76.19048%;
+}
+
+.emojione-1f98c {
+ background-position: 95.2381% 78.57143%;
+}
+
+.emojione-1f98d {
+ background-position: 95.2381% 80.95238%;
+}
+
+.emojione-1f98e {
+ background-position: 95.2381% 83.33333%;
+}
+
+.emojione-1f98f {
+ background-position: 95.2381% 85.71429%;
+}
+
+.emojione-1f990 {
+ background-position: 95.2381% 88.09524%;
+}
+
+.emojione-1f991 {
+ background-position: 95.2381% 90.47619%;
+}
+
+.emojione-1f9c0 {
+ background-position: 95.2381% 92.85714%;
+}
+
+.emojione-203c {
+ background-position: 0% 95.2381%;
+}
+
+.emojione-2049 {
+ background-position: 2.38095% 95.2381%;
+}
+
+.emojione-2122 {
+ background-position: 4.7619% 95.2381%;
+}
+
+.emojione-2139 {
+ background-position: 7.14286% 95.2381%;
+}
+
+.emojione-2194 {
+ background-position: 9.52381% 95.2381%;
+}
+
+.emojione-2195 {
+ background-position: 11.90476% 95.2381%;
+}
+
+.emojione-2196 {
+ background-position: 14.28571% 95.2381%;
+}
+
+.emojione-2197 {
+ background-position: 16.66667% 95.2381%;
+}
+
+.emojione-2198 {
+ background-position: 19.04762% 95.2381%;
+}
+
+.emojione-2199 {
+ background-position: 21.42857% 95.2381%;
+}
+
+.emojione-21a9 {
+ background-position: 23.80952% 95.2381%;
+}
+
+.emojione-21aa {
+ background-position: 26.19048% 95.2381%;
+}
+
+.emojione-231a {
+ background-position: 28.57143% 95.2381%;
+}
+
+.emojione-231b {
+ background-position: 30.95238% 95.2381%;
+}
+
+.emojione-2328 {
+ background-position: 33.33333% 95.2381%;
+}
+
+.emojione-23cf {
+ background-position: 35.71429% 95.2381%;
+}
+
+.emojione-23e9 {
+ background-position: 38.09524% 95.2381%;
+}
+
+.emojione-23ea {
+ background-position: 40.47619% 95.2381%;
+}
+
+.emojione-23eb {
+ background-position: 42.85714% 95.2381%;
+}
+
+.emojione-23ec {
+ background-position: 45.2381% 95.2381%;
+}
+
+.emojione-23ed {
+ background-position: 47.61905% 95.2381%;
+}
+
+.emojione-23ee {
+ background-position: 50% 95.2381%;
+}
+
+.emojione-23ef {
+ background-position: 52.38095% 95.2381%;
+}
+
+.emojione-23f0 {
+ background-position: 54.7619% 95.2381%;
+}
+
+.emojione-23f1 {
+ background-position: 57.14286% 95.2381%;
+}
+
+.emojione-23f2 {
+ background-position: 59.52381% 95.2381%;
+}
+
+.emojione-23f3 {
+ background-position: 61.90476% 95.2381%;
+}
+
+.emojione-23f8 {
+ background-position: 64.28571% 95.2381%;
+}
+
+.emojione-23f9 {
+ background-position: 66.66667% 95.2381%;
+}
+
+.emojione-23fa {
+ background-position: 69.04762% 95.2381%;
+}
+
+.emojione-24c2 {
+ background-position: 71.42857% 95.2381%;
+}
+
+.emojione-25aa {
+ background-position: 73.80952% 95.2381%;
+}
+
+.emojione-25ab {
+ background-position: 76.19048% 95.2381%;
+}
+
+.emojione-25b6 {
+ background-position: 78.57143% 95.2381%;
+}
+
+.emojione-25c0 {
+ background-position: 80.95238% 95.2381%;
+}
+
+.emojione-25fb {
+ background-position: 83.33333% 95.2381%;
+}
+
+.emojione-25fc {
+ background-position: 85.71429% 95.2381%;
+}
+
+.emojione-25fd {
+ background-position: 88.09524% 95.2381%;
+}
+
+.emojione-25fe {
+ background-position: 90.47619% 95.2381%;
+}
+
+.emojione-2600 {
+ background-position: 92.85714% 95.2381%;
+}
+
+.emojione-2601 {
+ background-position: 95.2381% 95.2381%;
+}
+
+.emojione-2602 {
+ background-position: 97.61905% 0%;
+}
+
+.emojione-2603 {
+ background-position: 97.61905% 2.38095%;
+}
+
+.emojione-2604 {
+ background-position: 97.61905% 4.7619%;
+}
+
+.emojione-260e {
+ background-position: 97.61905% 7.14286%;
+}
+
+.emojione-2611 {
+ background-position: 97.61905% 9.52381%;
+}
+
+.emojione-2614 {
+ background-position: 97.61905% 11.90476%;
+}
+
+.emojione-2615 {
+ background-position: 97.61905% 14.28571%;
+}
+
+.emojione-2618 {
+ background-position: 97.61905% 16.66667%;
+}
+
+.emojione-261d-1f3fb {
+ background-position: 97.61905% 19.04762%;
+}
+
+.emojione-261d-1f3fc {
+ background-position: 97.61905% 21.42857%;
+}
+
+.emojione-261d-1f3fd {
+ background-position: 97.61905% 23.80952%;
+}
+
+.emojione-261d-1f3fe {
+ background-position: 97.61905% 26.19048%;
+}
+
+.emojione-261d-1f3ff {
+ background-position: 97.61905% 28.57143%;
+}
+
+.emojione-261d {
+ background-position: 97.61905% 30.95238%;
+}
+
+.emojione-2620 {
+ background-position: 97.61905% 33.33333%;
+}
+
+.emojione-2622 {
+ background-position: 97.61905% 35.71429%;
+}
+
+.emojione-2623 {
+ background-position: 97.61905% 38.09524%;
+}
+
+.emojione-2626 {
+ background-position: 97.61905% 40.47619%;
+}
+
+.emojione-262a {
+ background-position: 97.61905% 42.85714%;
+}
+
+.emojione-262e {
+ background-position: 97.61905% 45.2381%;
+}
+
+.emojione-262f {
+ background-position: 97.61905% 47.61905%;
+}
+
+.emojione-2638 {
+ background-position: 97.61905% 50%;
+}
+
+.emojione-2639 {
+ background-position: 97.61905% 52.38095%;
+}
+
+.emojione-263a {
+ background-position: 97.61905% 54.7619%;
+}
+
+.emojione-2648 {
+ background-position: 97.61905% 57.14286%;
+}
+
+.emojione-2649 {
+ background-position: 97.61905% 59.52381%;
+}
+
+.emojione-264a {
+ background-position: 97.61905% 61.90476%;
+}
+
+.emojione-264b {
+ background-position: 97.61905% 64.28571%;
+}
+
+.emojione-264c {
+ background-position: 97.61905% 66.66667%;
+}
+
+.emojione-264d {
+ background-position: 97.61905% 69.04762%;
+}
+
+.emojione-264e {
+ background-position: 97.61905% 71.42857%;
+}
+
+.emojione-264f {
+ background-position: 97.61905% 73.80952%;
+}
+
+.emojione-2650 {
+ background-position: 97.61905% 76.19048%;
+}
+
+.emojione-2651 {
+ background-position: 97.61905% 78.57143%;
+}
+
+.emojione-2652 {
+ background-position: 97.61905% 80.95238%;
+}
+
+.emojione-2653 {
+ background-position: 97.61905% 83.33333%;
+}
+
+.emojione-2660 {
+ background-position: 97.61905% 85.71429%;
+}
+
+.emojione-2663 {
+ background-position: 97.61905% 88.09524%;
+}
+
+.emojione-2665 {
+ background-position: 97.61905% 90.47619%;
+}
+
+.emojione-2666 {
+ background-position: 97.61905% 92.85714%;
+}
+
+.emojione-2668 {
+ background-position: 97.61905% 95.2381%;
+}
+
+.emojione-267b {
+ background-position: 0% 97.61905%;
+}
+
+.emojione-267f {
+ background-position: 2.38095% 97.61905%;
+}
+
+.emojione-2692 {
+ background-position: 4.7619% 97.61905%;
+}
+
+.emojione-2693 {
+ background-position: 7.14286% 97.61905%;
+}
+
+.emojione-2694 {
+ background-position: 9.52381% 97.61905%;
+}
+
+.emojione-2696 {
+ background-position: 11.90476% 97.61905%;
+}
+
+.emojione-2697 {
+ background-position: 14.28571% 97.61905%;
+}
+
+.emojione-2699 {
+ background-position: 16.66667% 97.61905%;
+}
+
+.emojione-269b {
+ background-position: 19.04762% 97.61905%;
+}
+
+.emojione-269c {
+ background-position: 21.42857% 97.61905%;
+}
+
+.emojione-26a0 {
+ background-position: 23.80952% 97.61905%;
+}
+
+.emojione-26a1 {
+ background-position: 26.19048% 97.61905%;
+}
+
+.emojione-26aa {
+ background-position: 28.57143% 97.61905%;
+}
+
+.emojione-26ab {
+ background-position: 30.95238% 97.61905%;
+}
+
+.emojione-26b0 {
+ background-position: 33.33333% 97.61905%;
+}
+
+.emojione-26b1 {
+ background-position: 35.71429% 97.61905%;
+}
+
+.emojione-26bd {
+ background-position: 38.09524% 97.61905%;
+}
+
+.emojione-26be {
+ background-position: 40.47619% 97.61905%;
+}
+
+.emojione-26c4 {
+ background-position: 42.85714% 97.61905%;
+}
+
+.emojione-26c5 {
+ background-position: 45.2381% 97.61905%;
+}
+
+.emojione-26c8 {
+ background-position: 47.61905% 97.61905%;
+}
+
+.emojione-26ce {
+ background-position: 50% 97.61905%;
+}
+
+.emojione-26cf {
+ background-position: 52.38095% 97.61905%;
+}
+
+.emojione-26d1 {
+ background-position: 54.7619% 97.61905%;
+}
+
+.emojione-26d3 {
+ background-position: 57.14286% 97.61905%;
+}
+
+.emojione-26d4 {
+ background-position: 59.52381% 97.61905%;
+}
+
+.emojione-26e9 {
+ background-position: 61.90476% 97.61905%;
+}
+
+.emojione-26ea {
+ background-position: 64.28571% 97.61905%;
+}
+
+.emojione-26f0 {
+ background-position: 66.66667% 97.61905%;
+}
+
+.emojione-26f1 {
+ background-position: 69.04762% 97.61905%;
+}
+
+.emojione-26f2 {
+ background-position: 71.42857% 97.61905%;
+}
+
+.emojione-26f3 {
+ background-position: 73.80952% 97.61905%;
+}
+
+.emojione-26f4 {
+ background-position: 76.19048% 97.61905%;
+}
+
+.emojione-26f5 {
+ background-position: 78.57143% 97.61905%;
+}
+
+.emojione-26f7 {
+ background-position: 80.95238% 97.61905%;
+}
+
+.emojione-26f8 {
+ background-position: 83.33333% 97.61905%;
+}
+
+.emojione-26f9-1f3fb {
+ background-position: 85.71429% 97.61905%;
+}
+
+.emojione-26f9-1f3fc {
+ background-position: 88.09524% 97.61905%;
+}
+
+.emojione-26f9-1f3fd {
+ background-position: 90.47619% 97.61905%;
+}
+
+.emojione-26f9-1f3fe {
+ background-position: 92.85714% 97.61905%;
+}
+
+.emojione-26f9-1f3ff {
+ background-position: 95.2381% 97.61905%;
+}
+
+.emojione-26f9 {
+ background-position: 97.61905% 97.61905%;
+}
+
+.emojione-26fa {
+ background-position: 100% 0%;
+}
+
+.emojione-26fd {
+ background-position: 100% 2.38095%;
+}
+
+.emojione-2702 {
+ background-position: 100% 4.7619%;
+}
+
+.emojione-2705 {
+ background-position: 100% 7.14286%;
+}
+
+.emojione-2708 {
+ background-position: 100% 9.52381%;
+}
+
+.emojione-2709 {
+ background-position: 100% 11.90476%;
+}
+
+.emojione-270a-1f3fb {
+ background-position: 100% 14.28571%;
+}
+
+.emojione-270a-1f3fc {
+ background-position: 100% 16.66667%;
+}
+
+.emojione-270a-1f3fd {
+ background-position: 100% 19.04762%;
+}
+
+.emojione-270a-1f3fe {
+ background-position: 100% 21.42857%;
+}
+
+.emojione-270a-1f3ff {
+ background-position: 100% 23.80952%;
+}
+
+.emojione-270a {
+ background-position: 100% 26.19048%;
+}
+
+.emojione-270b-1f3fb {
+ background-position: 100% 28.57143%;
+}
+
+.emojione-270b-1f3fc {
+ background-position: 100% 30.95238%;
+}
+
+.emojione-270b-1f3fd {
+ background-position: 100% 33.33333%;
+}
+
+.emojione-270b-1f3fe {
+ background-position: 100% 35.71429%;
+}
+
+.emojione-270b-1f3ff {
+ background-position: 100% 38.09524%;
+}
+
+.emojione-270b {
+ background-position: 100% 40.47619%;
+}
+
+.emojione-270c-1f3fb {
+ background-position: 100% 42.85714%;
+}
+
+.emojione-270c-1f3fc {
+ background-position: 100% 45.2381%;
+}
+
+.emojione-270c-1f3fd {
+ background-position: 100% 47.61905%;
+}
+
+.emojione-270c-1f3fe {
+ background-position: 100% 50%;
+}
+
+.emojione-270c-1f3ff {
+ background-position: 100% 52.38095%;
+}
+
+.emojione-270c {
+ background-position: 100% 54.7619%;
+}
+
+.emojione-270d-1f3fb {
+ background-position: 100% 57.14286%;
+}
+
+.emojione-270d-1f3fc {
+ background-position: 100% 59.52381%;
+}
+
+.emojione-270d-1f3fd {
+ background-position: 100% 61.90476%;
+}
+
+.emojione-270d-1f3fe {
+ background-position: 100% 64.28571%;
+}
+
+.emojione-270d-1f3ff {
+ background-position: 100% 66.66667%;
+}
+
+.emojione-270d {
+ background-position: 100% 69.04762%;
+}
+
+.emojione-270f {
+ background-position: 100% 71.42857%;
+}
+
+.emojione-2712 {
+ background-position: 100% 73.80952%;
+}
+
+.emojione-2714 {
+ background-position: 100% 76.19048%;
+}
+
+.emojione-2716 {
+ background-position: 100% 78.57143%;
+}
+
+.emojione-271d {
+ background-position: 100% 80.95238%;
+}
+
+.emojione-2721 {
+ background-position: 100% 83.33333%;
+}
+
+.emojione-2728 {
+ background-position: 100% 85.71429%;
+}
+
+.emojione-2733 {
+ background-position: 100% 88.09524%;
+}
+
+.emojione-2734 {
+ background-position: 100% 90.47619%;
+}
+
+.emojione-2744 {
+ background-position: 100% 92.85714%;
+}
+
+.emojione-2747 {
+ background-position: 100% 95.2381%;
+}
+
+.emojione-274c {
+ background-position: 100% 97.61905%;
+}
+
+.emojione-274e {
+ background-position: 0% 100%;
+}
+
+.emojione-2753 {
+ background-position: 2.38095% 100%;
+}
+
+.emojione-2754 {
+ background-position: 4.7619% 100%;
+}
+
+.emojione-2755 {
+ background-position: 7.14286% 100%;
+}
+
+.emojione-2757 {
+ background-position: 9.52381% 100%;
+}
+
+.emojione-2763 {
+ background-position: 11.90476% 100%;
+}
+
+.emojione-2764 {
+ background-position: 14.28571% 100%;
+}
+
+.emojione-2795 {
+ background-position: 16.66667% 100%;
+}
+
+.emojione-2796 {
+ background-position: 19.04762% 100%;
+}
+
+.emojione-2797 {
+ background-position: 21.42857% 100%;
+}
+
+.emojione-27a1 {
+ background-position: 23.80952% 100%;
+}
+
+.emojione-27b0 {
+ background-position: 26.19048% 100%;
+}
+
+.emojione-27bf {
+ background-position: 28.57143% 100%;
+}
+
+.emojione-2934 {
+ background-position: 30.95238% 100%;
+}
+
+.emojione-2935 {
+ background-position: 33.33333% 100%;
+}
+
+.emojione-2b05 {
+ background-position: 35.71429% 100%;
+}
+
+.emojione-2b06 {
+ background-position: 38.09524% 100%;
+}
+
+.emojione-2b07 {
+ background-position: 40.47619% 100%;
+}
+
+.emojione-2b1b {
+ background-position: 42.85714% 100%;
+}
+
+.emojione-2b1c {
+ background-position: 45.2381% 100%;
+}
+
+.emojione-2b50 {
+ background-position: 47.61905% 100%;
+}
+
+.emojione-2b55 {
+ background-position: 50% 100%;
+}
+
+.emojione-3030 {
+ background-position: 52.38095% 100%;
+}
+
+.emojione-303d {
+ background-position: 54.7619% 100%;
+}
+
+.emojione-3297 {
+ background-position: 57.14286% 100%;
+}
+
+.emojione-3299 {
+ background-position: 59.52381% 100%;
+}
diff --git a/packages/rocketchat-emoji-emojione/emojiPicker.js b/packages/rocketchat-emoji-emojione/emojiPicker.js
index 6a7a2dab3c327..f3f5b27df048a 100644
--- a/packages/rocketchat-emoji-emojione/emojiPicker.js
+++ b/packages/rocketchat-emoji-emojione/emojiPicker.js
@@ -4,14 +4,14 @@
* Mapping category hashes into human readable and translated names
*/
emojiCategories = {
- people: TAPi18n.__('Smileys_and_People'),
- nature: TAPi18n.__('Animals_and_Nature'),
- food: TAPi18n.__('Food_and_Drink'),
- activity: TAPi18n.__('Activity'),
- travel: TAPi18n.__('Travel_and_Places'),
- objects: TAPi18n.__('Objects'),
- symbols: TAPi18n.__('Symbols'),
- flags: TAPi18n.__('Flags')
+ people: 'Smileys_and_People',
+ nature: 'Animals_and_Nature',
+ food: 'Food_and_Drink',
+ activity: 'Activity',
+ travel: 'Travel_and_Places',
+ objects: 'Objects',
+ symbols: 'Symbols',
+ flags: 'Flags'
};
toneList = {
diff --git a/packages/rocketchat-emoji-emojione/generateEmojiIndex.js b/packages/rocketchat-emoji-emojione/generateEmojiIndex.js
index 76867dec661ce..f9b4a6c5ac082 100644
--- a/packages/rocketchat-emoji-emojione/generateEmojiIndex.js
+++ b/packages/rocketchat-emoji-emojione/generateEmojiIndex.js
@@ -1,5 +1,5 @@
// emoji.json from emojione@2.2.6
-var fs = require('fs');
+import fs from 'fs';
var emojiList = JSON.parse(fs.readFileSync('emoji.json', 'utf-8'));
diff --git a/packages/rocketchat-emoji-emojione/package.js b/packages/rocketchat-emoji-emojione/package.js
index e4533b2865a11..d3122c14f9864 100644
--- a/packages/rocketchat-emoji-emojione/package.js
+++ b/packages/rocketchat-emoji-emojione/package.js
@@ -8,14 +8,15 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'emojione:emojione',
+ 'emojione:emojione@2.2.6',
'rocketchat:emoji',
'rocketchat:lib'
]);
- api.addFiles('emojiPicker.js', 'client');
+ api.addFiles('emojiPicker.js');
- api.addFiles('rocketchat.js', 'client');
+ api.addFiles('rocketchat.js');
- api.addFiles('sprites.css', 'client');
+ api.addFiles('client/sprites.css', 'client');
+ api.addFiles('server/callbacks.js', 'server');
});
diff --git a/packages/rocketchat-emoji-emojione/rocketchat.js b/packages/rocketchat-emoji-emojione/rocketchat.js
index 23779013cd8bf..48d15ba3b6ebb 100644
--- a/packages/rocketchat-emoji-emojione/rocketchat.js
+++ b/packages/rocketchat-emoji-emojione/rocketchat.js
@@ -12,7 +12,7 @@ RocketChat.emoji.packages.emojione.render = function(emoji) {
//http://stackoverflow.com/a/26990347 function isSet() from Gajus
function isSetNotNull(fn) {
- var value;
+ let value;
try {
value = fn();
} catch (e) {
@@ -23,9 +23,9 @@ function isSetNotNull(fn) {
}
// RocketChat.emoji.list is the collection of emojis from all emoji packages
-for (let key in emojione.emojioneList) {
+for (const key in emojione.emojioneList) {
if (emojione.emojioneList.hasOwnProperty(key)) {
- let emoji = emojione.emojioneList[key];
+ const emoji = emojione.emojioneList[key];
emoji.emojiPackage = 'emojione';
RocketChat.emoji.list[key] = emoji;
}
@@ -35,8 +35,8 @@ for (let key in emojione.emojioneList) {
Meteor.startup(function() {
Tracker.autorun(function() {
if (isSetNotNull(() => RocketChat.emoji.packages.emojione)) {
- if (isSetNotNull(() => Meteor.user().settings.preferences.convertAsciiEmoji)) {
- RocketChat.emoji.packages.emojione.ascii = Meteor.user().settings.preferences.convertAsciiEmoji;
+ if (isSetNotNull(() => RocketChat.getUserPreference(Meteor.user(), 'convertAsciiEmoji'))) {
+ RocketChat.emoji.packages.emojione.ascii = RocketChat.getUserPreference(Meteor.user(), 'convertAsciiEmoji');
} else {
RocketChat.emoji.packages.emojione.ascii = true;
}
diff --git a/packages/rocketchat-emoji-emojione/server/callbacks.js b/packages/rocketchat-emoji-emojione/server/callbacks.js
new file mode 100644
index 0000000000000..160d902d90ffa
--- /dev/null
+++ b/packages/rocketchat-emoji-emojione/server/callbacks.js
@@ -0,0 +1,6 @@
+/* globals emojione */
+Meteor.startup(function() {
+ RocketChat.callbacks.add('beforeNotifyUser', (message) => {
+ return emojione.shortnameToUnicode(message);
+ });
+});
diff --git a/packages/rocketchat-emoji-emojione/sprites.css b/packages/rocketchat-emoji-emojione/sprites.css
deleted file mode 100644
index a10f82b425216..0000000000000
--- a/packages/rocketchat-emoji-emojione/sprites.css
+++ /dev/null
@@ -1,5517 +0,0 @@
-.emojione {
- image-rendering: -webkit-optimize-contrast;
- image-rendering: optimizeQuality;
- font-size: inherit;
- height: 22px;
- width: 22px;
- position: relative;
- display: inline-block;
- margin: 0 .15em;
- line-height: normal;
- vertical-align: middle;
- background-image: url("../../packages/emojione_emojione/assets/sprites/emojione.sprites.png");
- background-size: 4365.625% 4365.625%;
- background-repeat: no-repeat;
- text-indent: 100%;
- white-space: nowrap;
- overflow: hidden; }
-
-.emojione.big {
- height: 44px !important;
- width: 44px !important; }
-
-.emojione-0023-20e3 {
- background-position: 2.38095% 0%; }
-
-.emojione-0023 {
- background-position: 50% 66.66667%; }
-
-.emojione-002a-20e3 {
- background-position: 0% 2.38095%; }
-
-.emojione-002a {
- background-position: 2.38095% 2.38095%; }
-
-.emojione-0030-20e3 {
- background-position: 4.7619% 0%; }
-
-.emojione-0030 {
- background-position: 4.7619% 2.38095%; }
-
-.emojione-0031-20e3 {
- background-position: 0% 4.7619%; }
-
-.emojione-0031 {
- background-position: 2.38095% 4.7619%; }
-
-.emojione-0032-20e3 {
- background-position: 4.7619% 4.7619%; }
-
-.emojione-0032 {
- background-position: 7.14286% 0%; }
-
-.emojione-0033-20e3 {
- background-position: 7.14286% 2.38095%; }
-
-.emojione-0033 {
- background-position: 7.14286% 4.7619%; }
-
-.emojione-0034-20e3 {
- background-position: 0% 7.14286%; }
-
-.emojione-0034 {
- background-position: 2.38095% 7.14286%; }
-
-.emojione-0035-20e3 {
- background-position: 4.7619% 7.14286%; }
-
-.emojione-0035 {
- background-position: 7.14286% 7.14286%; }
-
-.emojione-0036-20e3 {
- background-position: 9.52381% 0%; }
-
-.emojione-0036 {
- background-position: 9.52381% 2.38095%; }
-
-.emojione-0037-20e3 {
- background-position: 9.52381% 4.7619%; }
-
-.emojione-0037 {
- background-position: 9.52381% 7.14286%; }
-
-.emojione-0038-20e3 {
- background-position: 0% 9.52381%; }
-
-.emojione-0038 {
- background-position: 2.38095% 9.52381%; }
-
-.emojione-0039-20e3 {
- background-position: 4.7619% 9.52381%; }
-
-.emojione-0039 {
- background-position: 7.14286% 9.52381%; }
-
-.emojione-00a9 {
- background-position: 9.52381% 9.52381%; }
-
-.emojione-00ae {
- background-position: 11.90476% 0%; }
-
-.emojione-1f004 {
- background-position: 11.90476% 2.38095%; }
-
-.emojione-1f0cf {
- background-position: 11.90476% 4.7619%; }
-
-.emojione-1f170 {
- background-position: 11.90476% 7.14286%; }
-
-.emojione-1f171 {
- background-position: 11.90476% 9.52381%; }
-
-.emojione-1f17e {
- background-position: 0% 11.90476%; }
-
-.emojione-1f17f {
- background-position: 2.38095% 11.90476%; }
-
-.emojione-1f18e {
- background-position: 4.7619% 11.90476%; }
-
-.emojione-1f191 {
- background-position: 7.14286% 11.90476%; }
-
-.emojione-1f192 {
- background-position: 9.52381% 11.90476%; }
-
-.emojione-1f193 {
- background-position: 11.90476% 11.90476%; }
-
-.emojione-1f194 {
- background-position: 14.28571% 0%; }
-
-.emojione-1f195 {
- background-position: 14.28571% 2.38095%; }
-
-.emojione-1f196 {
- background-position: 14.28571% 4.7619%; }
-
-.emojione-1f197 {
- background-position: 14.28571% 7.14286%; }
-
-.emojione-1f198 {
- background-position: 14.28571% 9.52381%; }
-
-.emojione-1f199 {
- background-position: 14.28571% 11.90476%; }
-
-.emojione-1f19a {
- background-position: 0% 14.28571%; }
-
-.emojione-1f1e6-1f1e8 {
- background-position: 2.38095% 14.28571%; }
-
-.emojione-1f1e6-1f1e9 {
- background-position: 4.7619% 14.28571%; }
-
-.emojione-1f1e6-1f1ea {
- background-position: 7.14286% 14.28571%; }
-
-.emojione-1f1e6-1f1eb {
- background-position: 9.52381% 14.28571%; }
-
-.emojione-1f1e6-1f1ec {
- background-position: 11.90476% 14.28571%; }
-
-.emojione-1f1e6-1f1ee {
- background-position: 14.28571% 14.28571%; }
-
-.emojione-1f1e6-1f1f1 {
- background-position: 16.66667% 0%; }
-
-.emojione-1f1e6-1f1f2 {
- background-position: 16.66667% 2.38095%; }
-
-.emojione-1f1e6-1f1f4 {
- background-position: 16.66667% 4.7619%; }
-
-.emojione-1f1e6-1f1f6 {
- background-position: 16.66667% 7.14286%; }
-
-.emojione-1f1e6-1f1f7 {
- background-position: 16.66667% 9.52381%; }
-
-.emojione-1f1e6-1f1f8 {
- background-position: 16.66667% 11.90476%; }
-
-.emojione-1f1e6-1f1f9 {
- background-position: 16.66667% 14.28571%; }
-
-.emojione-1f1e6-1f1fa {
- background-position: 0% 16.66667%; }
-
-.emojione-1f1e6-1f1fc {
- background-position: 2.38095% 16.66667%; }
-
-.emojione-1f1e6-1f1fd {
- background-position: 4.7619% 16.66667%; }
-
-.emojione-1f1e6-1f1ff {
- background-position: 7.14286% 16.66667%; }
-
-.emojione-1f1e6 {
- background-position: 9.52381% 16.66667%; }
-
-.emojione-1f1e7-1f1e6 {
- background-position: 11.90476% 16.66667%; }
-
-.emojione-1f1e7-1f1e7 {
- background-position: 14.28571% 16.66667%; }
-
-.emojione-1f1e7-1f1e9 {
- background-position: 16.66667% 16.66667%; }
-
-.emojione-1f1e7-1f1ea {
- background-position: 19.04762% 0%; }
-
-.emojione-1f1e7-1f1eb {
- background-position: 19.04762% 2.38095%; }
-
-.emojione-1f1e7-1f1ec {
- background-position: 19.04762% 4.7619%; }
-
-.emojione-1f1e7-1f1ed {
- background-position: 19.04762% 7.14286%; }
-
-.emojione-1f1e7-1f1ee {
- background-position: 19.04762% 9.52381%; }
-
-.emojione-1f1e7-1f1ef {
- background-position: 19.04762% 11.90476%; }
-
-.emojione-1f1e7-1f1f1 {
- background-position: 19.04762% 14.28571%; }
-
-.emojione-1f1e7-1f1f2 {
- background-position: 19.04762% 16.66667%; }
-
-.emojione-1f1e7-1f1f3 {
- background-position: 0% 19.04762%; }
-
-.emojione-1f1e7-1f1f4 {
- background-position: 2.38095% 19.04762%; }
-
-.emojione-1f1e7-1f1f6 {
- background-position: 4.7619% 19.04762%; }
-
-.emojione-1f1e7-1f1f7 {
- background-position: 7.14286% 19.04762%; }
-
-.emojione-1f1e7-1f1f8 {
- background-position: 9.52381% 19.04762%; }
-
-.emojione-1f1e7-1f1f9 {
- background-position: 11.90476% 19.04762%; }
-
-.emojione-1f1e7-1f1fb {
- background-position: 14.28571% 19.04762%; }
-
-.emojione-1f1e7-1f1fc {
- background-position: 16.66667% 19.04762%; }
-
-.emojione-1f1e7-1f1fe {
- background-position: 19.04762% 19.04762%; }
-
-.emojione-1f1e7-1f1ff {
- background-position: 21.42857% 0%; }
-
-.emojione-1f1e7 {
- background-position: 21.42857% 2.38095%; }
-
-.emojione-1f1e8-1f1e6 {
- background-position: 21.42857% 4.7619%; }
-
-.emojione-1f1e8-1f1e8 {
- background-position: 21.42857% 7.14286%; }
-
-.emojione-1f1e8-1f1e9 {
- background-position: 21.42857% 9.52381%; }
-
-.emojione-1f1e8-1f1eb {
- background-position: 21.42857% 11.90476%; }
-
-.emojione-1f1e8-1f1ec {
- background-position: 21.42857% 14.28571%; }
-
-.emojione-1f1e8-1f1ed {
- background-position: 21.42857% 16.66667%; }
-
-.emojione-1f1e8-1f1ee {
- background-position: 21.42857% 19.04762%; }
-
-.emojione-1f1e8-1f1f0 {
- background-position: 0% 21.42857%; }
-
-.emojione-1f1e8-1f1f1 {
- background-position: 2.38095% 21.42857%; }
-
-.emojione-1f1e8-1f1f2 {
- background-position: 4.7619% 21.42857%; }
-
-.emojione-1f1e8-1f1f3 {
- background-position: 7.14286% 21.42857%; }
-
-.emojione-1f1e8-1f1f4 {
- background-position: 9.52381% 21.42857%; }
-
-.emojione-1f1e8-1f1f5 {
- background-position: 11.90476% 21.42857%; }
-
-.emojione-1f1e8-1f1f7 {
- background-position: 14.28571% 21.42857%; }
-
-.emojione-1f1e8-1f1fa {
- background-position: 16.66667% 21.42857%; }
-
-.emojione-1f1e8-1f1fb {
- background-position: 19.04762% 21.42857%; }
-
-.emojione-1f1e8-1f1fc {
- background-position: 21.42857% 21.42857%; }
-
-.emojione-1f1e8-1f1fd {
- background-position: 23.80952% 0%; }
-
-.emojione-1f1e8-1f1fe {
- background-position: 23.80952% 2.38095%; }
-
-.emojione-1f1e8-1f1ff {
- background-position: 23.80952% 4.7619%; }
-
-.emojione-1f1e8 {
- background-position: 23.80952% 7.14286%; }
-
-.emojione-1f1e9-1f1ea {
- background-position: 23.80952% 9.52381%; }
-
-.emojione-1f1e9-1f1ec {
- background-position: 23.80952% 11.90476%; }
-
-.emojione-1f1e9-1f1ef {
- background-position: 23.80952% 14.28571%; }
-
-.emojione-1f1e9-1f1f0 {
- background-position: 23.80952% 16.66667%; }
-
-.emojione-1f1e9-1f1f2 {
- background-position: 23.80952% 19.04762%; }
-
-.emojione-1f1e9-1f1f4 {
- background-position: 23.80952% 21.42857%; }
-
-.emojione-1f1e9-1f1ff {
- background-position: 0% 23.80952%; }
-
-.emojione-1f1e9 {
- background-position: 2.38095% 23.80952%; }
-
-.emojione-1f1ea-1f1e6 {
- background-position: 4.7619% 23.80952%; }
-
-.emojione-1f1ea-1f1e8 {
- background-position: 7.14286% 23.80952%; }
-
-.emojione-1f1ea-1f1ea {
- background-position: 9.52381% 23.80952%; }
-
-.emojione-1f1ea-1f1ec {
- background-position: 11.90476% 23.80952%; }
-
-.emojione-1f1ea-1f1ed {
- background-position: 14.28571% 23.80952%; }
-
-.emojione-1f1ea-1f1f7 {
- background-position: 16.66667% 23.80952%; }
-
-.emojione-1f1ea-1f1f8 {
- background-position: 19.04762% 23.80952%; }
-
-.emojione-1f1ea-1f1f9 {
- background-position: 21.42857% 23.80952%; }
-
-.emojione-1f1ea-1f1fa {
- background-position: 23.80952% 23.80952%; }
-
-.emojione-1f1ea {
- background-position: 26.19048% 0%; }
-
-.emojione-1f1eb-1f1ee {
- background-position: 26.19048% 2.38095%; }
-
-.emojione-1f1eb-1f1ef {
- background-position: 26.19048% 4.7619%; }
-
-.emojione-1f1eb-1f1f0 {
- background-position: 26.19048% 7.14286%; }
-
-.emojione-1f1eb-1f1f2 {
- background-position: 26.19048% 9.52381%; }
-
-.emojione-1f1eb-1f1f4 {
- background-position: 26.19048% 11.90476%; }
-
-.emojione-1f1eb-1f1f7 {
- background-position: 26.19048% 14.28571%; }
-
-.emojione-1f1eb {
- background-position: 26.19048% 16.66667%; }
-
-.emojione-1f1ec-1f1e6 {
- background-position: 26.19048% 19.04762%; }
-
-.emojione-1f1ec-1f1e7 {
- background-position: 26.19048% 21.42857%; }
-
-.emojione-1f1ec-1f1e9 {
- background-position: 26.19048% 23.80952%; }
-
-.emojione-1f1ec-1f1ea {
- background-position: 0% 26.19048%; }
-
-.emojione-1f1ec-1f1eb {
- background-position: 2.38095% 26.19048%; }
-
-.emojione-1f1ec-1f1ec {
- background-position: 4.7619% 26.19048%; }
-
-.emojione-1f1ec-1f1ed {
- background-position: 7.14286% 26.19048%; }
-
-.emojione-1f1ec-1f1ee {
- background-position: 9.52381% 26.19048%; }
-
-.emojione-1f1ec-1f1f1 {
- background-position: 11.90476% 26.19048%; }
-
-.emojione-1f1ec-1f1f2 {
- background-position: 14.28571% 26.19048%; }
-
-.emojione-1f1ec-1f1f3 {
- background-position: 16.66667% 26.19048%; }
-
-.emojione-1f1ec-1f1f5 {
- background-position: 19.04762% 26.19048%; }
-
-.emojione-1f1ec-1f1f6 {
- background-position: 21.42857% 26.19048%; }
-
-.emojione-1f1ec-1f1f7 {
- background-position: 23.80952% 26.19048%; }
-
-.emojione-1f1ec-1f1f8 {
- background-position: 26.19048% 26.19048%; }
-
-.emojione-1f1ec-1f1f9 {
- background-position: 28.57143% 0%; }
-
-.emojione-1f1ec-1f1fa {
- background-position: 28.57143% 2.38095%; }
-
-.emojione-1f1ec-1f1fc {
- background-position: 28.57143% 4.7619%; }
-
-.emojione-1f1ec-1f1fe {
- background-position: 28.57143% 7.14286%; }
-
-.emojione-1f1ec {
- background-position: 28.57143% 9.52381%; }
-
-.emojione-1f1ed-1f1f0 {
- background-position: 28.57143% 11.90476%; }
-
-.emojione-1f1ed-1f1f2 {
- background-position: 28.57143% 14.28571%; }
-
-.emojione-1f1ed-1f1f3 {
- background-position: 28.57143% 16.66667%; }
-
-.emojione-1f1ed-1f1f7 {
- background-position: 28.57143% 19.04762%; }
-
-.emojione-1f1ed-1f1f9 {
- background-position: 28.57143% 21.42857%; }
-
-.emojione-1f1ed-1f1fa {
- background-position: 28.57143% 23.80952%; }
-
-.emojione-1f1ed {
- background-position: 28.57143% 26.19048%; }
-
-.emojione-1f1ee-1f1e8 {
- background-position: 0% 28.57143%; }
-
-.emojione-1f1ee-1f1e9 {
- background-position: 2.38095% 28.57143%; }
-
-.emojione-1f1ee-1f1ea {
- background-position: 4.7619% 28.57143%; }
-
-.emojione-1f1ee-1f1f1 {
- background-position: 7.14286% 28.57143%; }
-
-.emojione-1f1ee-1f1f2 {
- background-position: 9.52381% 28.57143%; }
-
-.emojione-1f1ee-1f1f3 {
- background-position: 11.90476% 28.57143%; }
-
-.emojione-1f1ee-1f1f4 {
- background-position: 14.28571% 28.57143%; }
-
-.emojione-1f1ee-1f1f6 {
- background-position: 16.66667% 28.57143%; }
-
-.emojione-1f1ee-1f1f7 {
- background-position: 19.04762% 28.57143%; }
-
-.emojione-1f1ee-1f1f8 {
- background-position: 21.42857% 28.57143%; }
-
-.emojione-1f1ee-1f1f9 {
- background-position: 23.80952% 28.57143%; }
-
-.emojione-1f1ee {
- background-position: 26.19048% 28.57143%; }
-
-.emojione-1f1ef-1f1ea {
- background-position: 28.57143% 28.57143%; }
-
-.emojione-1f1ef-1f1f2 {
- background-position: 30.95238% 0%; }
-
-.emojione-1f1ef-1f1f4 {
- background-position: 30.95238% 2.38095%; }
-
-.emojione-1f1ef-1f1f5 {
- background-position: 30.95238% 4.7619%; }
-
-.emojione-1f1ef {
- background-position: 30.95238% 7.14286%; }
-
-.emojione-1f1f0-1f1ea {
- background-position: 30.95238% 9.52381%; }
-
-.emojione-1f1f0-1f1ec {
- background-position: 30.95238% 11.90476%; }
-
-.emojione-1f1f0-1f1ed {
- background-position: 30.95238% 14.28571%; }
-
-.emojione-1f1f0-1f1ee {
- background-position: 30.95238% 16.66667%; }
-
-.emojione-1f1f0-1f1f2 {
- background-position: 30.95238% 19.04762%; }
-
-.emojione-1f1f0-1f1f3 {
- background-position: 30.95238% 21.42857%; }
-
-.emojione-1f1f0-1f1f5 {
- background-position: 30.95238% 23.80952%; }
-
-.emojione-1f1f0-1f1f7 {
- background-position: 30.95238% 26.19048%; }
-
-.emojione-1f1f0-1f1fc {
- background-position: 30.95238% 28.57143%; }
-
-.emojione-1f1f0-1f1fe {
- background-position: 0% 30.95238%; }
-
-.emojione-1f1f0-1f1ff {
- background-position: 2.38095% 30.95238%; }
-
-.emojione-1f1f0 {
- background-position: 4.7619% 30.95238%; }
-
-.emojione-1f1f1-1f1e6 {
- background-position: 7.14286% 30.95238%; }
-
-.emojione-1f1f1-1f1e7 {
- background-position: 9.52381% 30.95238%; }
-
-.emojione-1f1f1-1f1e8 {
- background-position: 11.90476% 30.95238%; }
-
-.emojione-1f1f1-1f1ee {
- background-position: 14.28571% 30.95238%; }
-
-.emojione-1f1f1-1f1f0 {
- background-position: 16.66667% 30.95238%; }
-
-.emojione-1f1f1-1f1f7 {
- background-position: 19.04762% 30.95238%; }
-
-.emojione-1f1f1-1f1f8 {
- background-position: 21.42857% 30.95238%; }
-
-.emojione-1f1f1-1f1f9 {
- background-position: 23.80952% 30.95238%; }
-
-.emojione-1f1f1-1f1fa {
- background-position: 26.19048% 30.95238%; }
-
-.emojione-1f1f1-1f1fb {
- background-position: 28.57143% 30.95238%; }
-
-.emojione-1f1f1-1f1fe {
- background-position: 30.95238% 30.95238%; }
-
-.emojione-1f1f1 {
- background-position: 33.33333% 0%; }
-
-.emojione-1f1f2-1f1e6 {
- background-position: 33.33333% 2.38095%; }
-
-.emojione-1f1f2-1f1e8 {
- background-position: 33.33333% 4.7619%; }
-
-.emojione-1f1f2-1f1e9 {
- background-position: 33.33333% 7.14286%; }
-
-.emojione-1f1f2-1f1ea {
- background-position: 33.33333% 9.52381%; }
-
-.emojione-1f1f2-1f1eb {
- background-position: 33.33333% 11.90476%; }
-
-.emojione-1f1f2-1f1ec {
- background-position: 33.33333% 14.28571%; }
-
-.emojione-1f1f2-1f1ed {
- background-position: 33.33333% 16.66667%; }
-
-.emojione-1f1f2-1f1f0 {
- background-position: 33.33333% 19.04762%; }
-
-.emojione-1f1f2-1f1f1 {
- background-position: 33.33333% 21.42857%; }
-
-.emojione-1f1f2-1f1f2 {
- background-position: 33.33333% 23.80952%; }
-
-.emojione-1f1f2-1f1f3 {
- background-position: 33.33333% 26.19048%; }
-
-.emojione-1f1f2-1f1f4 {
- background-position: 33.33333% 28.57143%; }
-
-.emojione-1f1f2-1f1f5 {
- background-position: 33.33333% 30.95238%; }
-
-.emojione-1f1f2-1f1f6 {
- background-position: 0% 33.33333%; }
-
-.emojione-1f1f2-1f1f7 {
- background-position: 2.38095% 33.33333%; }
-
-.emojione-1f1f2-1f1f8 {
- background-position: 4.7619% 33.33333%; }
-
-.emojione-1f1f2-1f1f9 {
- background-position: 7.14286% 33.33333%; }
-
-.emojione-1f1f2-1f1fa {
- background-position: 9.52381% 33.33333%; }
-
-.emojione-1f1f2-1f1fb {
- background-position: 11.90476% 33.33333%; }
-
-.emojione-1f1f2-1f1fc {
- background-position: 14.28571% 33.33333%; }
-
-.emojione-1f1f2-1f1fd {
- background-position: 16.66667% 33.33333%; }
-
-.emojione-1f1f2-1f1fe {
- background-position: 19.04762% 33.33333%; }
-
-.emojione-1f1f2-1f1ff {
- background-position: 21.42857% 33.33333%; }
-
-.emojione-1f1f2 {
- background-position: 23.80952% 33.33333%; }
-
-.emojione-1f1f3-1f1e6 {
- background-position: 26.19048% 33.33333%; }
-
-.emojione-1f1f3-1f1e8 {
- background-position: 28.57143% 33.33333%; }
-
-.emojione-1f1f3-1f1ea {
- background-position: 30.95238% 33.33333%; }
-
-.emojione-1f1f3-1f1eb {
- background-position: 33.33333% 33.33333%; }
-
-.emojione-1f1f3-1f1ec {
- background-position: 35.71429% 0%; }
-
-.emojione-1f1f3-1f1ee {
- background-position: 35.71429% 2.38095%; }
-
-.emojione-1f1f3-1f1f1 {
- background-position: 35.71429% 4.7619%; }
-
-.emojione-1f1f3-1f1f4 {
- background-position: 35.71429% 7.14286%; }
-
-.emojione-1f1f3-1f1f5 {
- background-position: 35.71429% 9.52381%; }
-
-.emojione-1f1f3-1f1f7 {
- background-position: 35.71429% 11.90476%; }
-
-.emojione-1f1f3-1f1fa {
- background-position: 35.71429% 14.28571%; }
-
-.emojione-1f1f3-1f1ff {
- background-position: 35.71429% 16.66667%; }
-
-.emojione-1f1f3 {
- background-position: 35.71429% 19.04762%; }
-
-.emojione-1f1f4-1f1f2 {
- background-position: 35.71429% 21.42857%; }
-
-.emojione-1f1f4 {
- background-position: 35.71429% 23.80952%; }
-
-.emojione-1f1f5-1f1e6 {
- background-position: 35.71429% 26.19048%; }
-
-.emojione-1f1f5-1f1ea {
- background-position: 35.71429% 28.57143%; }
-
-.emojione-1f1f5-1f1eb {
- background-position: 35.71429% 30.95238%; }
-
-.emojione-1f1f5-1f1ec {
- background-position: 35.71429% 33.33333%; }
-
-.emojione-1f1f5-1f1ed {
- background-position: 0% 35.71429%; }
-
-.emojione-1f1f5-1f1f0 {
- background-position: 2.38095% 35.71429%; }
-
-.emojione-1f1f5-1f1f1 {
- background-position: 4.7619% 35.71429%; }
-
-.emojione-1f1f5-1f1f2 {
- background-position: 7.14286% 35.71429%; }
-
-.emojione-1f1f5-1f1f3 {
- background-position: 9.52381% 35.71429%; }
-
-.emojione-1f1f5-1f1f7 {
- background-position: 11.90476% 35.71429%; }
-
-.emojione-1f1f5-1f1f8 {
- background-position: 14.28571% 35.71429%; }
-
-.emojione-1f1f5-1f1f9 {
- background-position: 16.66667% 35.71429%; }
-
-.emojione-1f1f5-1f1fc {
- background-position: 19.04762% 35.71429%; }
-
-.emojione-1f1f5-1f1fe {
- background-position: 21.42857% 35.71429%; }
-
-.emojione-1f1f5 {
- background-position: 23.80952% 35.71429%; }
-
-.emojione-1f1f6-1f1e6 {
- background-position: 26.19048% 35.71429%; }
-
-.emojione-1f1f6 {
- background-position: 28.57143% 35.71429%; }
-
-.emojione-1f1f7-1f1ea {
- background-position: 30.95238% 35.71429%; }
-
-.emojione-1f1f7-1f1f4 {
- background-position: 33.33333% 35.71429%; }
-
-.emojione-1f1f7-1f1f8 {
- background-position: 35.71429% 35.71429%; }
-
-.emojione-1f1f7-1f1fa {
- background-position: 38.09524% 0%; }
-
-.emojione-1f1f7-1f1fc {
- background-position: 38.09524% 2.38095%; }
-
-.emojione-1f1f7 {
- background-position: 38.09524% 4.7619%; }
-
-.emojione-1f1f8-1f1e6 {
- background-position: 38.09524% 7.14286%; }
-
-.emojione-1f1f8-1f1e7 {
- background-position: 38.09524% 9.52381%; }
-
-.emojione-1f1f8-1f1e8 {
- background-position: 38.09524% 11.90476%; }
-
-.emojione-1f1f8-1f1e9 {
- background-position: 38.09524% 14.28571%; }
-
-.emojione-1f1f8-1f1ea {
- background-position: 38.09524% 16.66667%; }
-
-.emojione-1f1f8-1f1ec {
- background-position: 38.09524% 19.04762%; }
-
-.emojione-1f1f8-1f1ed {
- background-position: 38.09524% 21.42857%; }
-
-.emojione-1f1f8-1f1ee {
- background-position: 38.09524% 23.80952%; }
-
-.emojione-1f1f8-1f1ef {
- background-position: 38.09524% 26.19048%; }
-
-.emojione-1f1f8-1f1f0 {
- background-position: 38.09524% 28.57143%; }
-
-.emojione-1f1f8-1f1f1 {
- background-position: 38.09524% 30.95238%; }
-
-.emojione-1f1f8-1f1f2 {
- background-position: 38.09524% 33.33333%; }
-
-.emojione-1f1f8-1f1f3 {
- background-position: 38.09524% 35.71429%; }
-
-.emojione-1f1f8-1f1f4 {
- background-position: 0% 38.09524%; }
-
-.emojione-1f1f8-1f1f7 {
- background-position: 2.38095% 38.09524%; }
-
-.emojione-1f1f8-1f1f8 {
- background-position: 4.7619% 38.09524%; }
-
-.emojione-1f1f8-1f1f9 {
- background-position: 7.14286% 38.09524%; }
-
-.emojione-1f1f8-1f1fb {
- background-position: 9.52381% 38.09524%; }
-
-.emojione-1f1f8-1f1fd {
- background-position: 11.90476% 38.09524%; }
-
-.emojione-1f1f8-1f1fe {
- background-position: 14.28571% 38.09524%; }
-
-.emojione-1f1f8-1f1ff {
- background-position: 16.66667% 38.09524%; }
-
-.emojione-1f1f8 {
- background-position: 19.04762% 38.09524%; }
-
-.emojione-1f1f9-1f1e6 {
- background-position: 21.42857% 38.09524%; }
-
-.emojione-1f1f9-1f1e8 {
- background-position: 23.80952% 38.09524%; }
-
-.emojione-1f1f9-1f1e9 {
- background-position: 26.19048% 38.09524%; }
-
-.emojione-1f1f9-1f1eb {
- background-position: 28.57143% 38.09524%; }
-
-.emojione-1f1f9-1f1ec {
- background-position: 30.95238% 38.09524%; }
-
-.emojione-1f1f9-1f1ed {
- background-position: 33.33333% 38.09524%; }
-
-.emojione-1f1f9-1f1ef {
- background-position: 35.71429% 38.09524%; }
-
-.emojione-1f1f9-1f1f0 {
- background-position: 38.09524% 38.09524%; }
-
-.emojione-1f1f9-1f1f1 {
- background-position: 40.47619% 0%; }
-
-.emojione-1f1f9-1f1f2 {
- background-position: 40.47619% 2.38095%; }
-
-.emojione-1f1f9-1f1f3 {
- background-position: 40.47619% 4.7619%; }
-
-.emojione-1f1f9-1f1f4 {
- background-position: 40.47619% 7.14286%; }
-
-.emojione-1f1f9-1f1f7 {
- background-position: 40.47619% 9.52381%; }
-
-.emojione-1f1f9-1f1f9 {
- background-position: 40.47619% 11.90476%; }
-
-.emojione-1f1f9-1f1fb {
- background-position: 40.47619% 14.28571%; }
-
-.emojione-1f1f9-1f1fc {
- background-position: 40.47619% 16.66667%; }
-
-.emojione-1f1f9-1f1ff {
- background-position: 40.47619% 19.04762%; }
-
-.emojione-1f1f9 {
- background-position: 40.47619% 21.42857%; }
-
-.emojione-1f1fa-1f1e6 {
- background-position: 40.47619% 23.80952%; }
-
-.emojione-1f1fa-1f1ec {
- background-position: 40.47619% 26.19048%; }
-
-.emojione-1f1fa-1f1f2 {
- background-position: 40.47619% 28.57143%; }
-
-.emojione-1f1fa-1f1f8 {
- background-position: 40.47619% 30.95238%; }
-
-.emojione-1f1fa-1f1fe {
- background-position: 40.47619% 33.33333%; }
-
-.emojione-1f1fa-1f1ff {
- background-position: 40.47619% 35.71429%; }
-
-.emojione-1f1fa {
- background-position: 40.47619% 38.09524%; }
-
-.emojione-1f1fb-1f1e6 {
- background-position: 0% 40.47619%; }
-
-.emojione-1f1fb-1f1e8 {
- background-position: 2.38095% 40.47619%; }
-
-.emojione-1f1fb-1f1ea {
- background-position: 4.7619% 40.47619%; }
-
-.emojione-1f1fb-1f1ec {
- background-position: 7.14286% 40.47619%; }
-
-.emojione-1f1fb-1f1ee {
- background-position: 9.52381% 40.47619%; }
-
-.emojione-1f1fb-1f1f3 {
- background-position: 11.90476% 40.47619%; }
-
-.emojione-1f1fb-1f1fa {
- background-position: 14.28571% 40.47619%; }
-
-.emojione-1f1fb {
- background-position: 16.66667% 40.47619%; }
-
-.emojione-1f1fc-1f1eb {
- background-position: 19.04762% 40.47619%; }
-
-.emojione-1f1fc-1f1f8 {
- background-position: 21.42857% 40.47619%; }
-
-.emojione-1f1fc {
- background-position: 23.80952% 40.47619%; }
-
-.emojione-1f1fd-1f1f0 {
- background-position: 26.19048% 40.47619%; }
-
-.emojione-1f1fd {
- background-position: 28.57143% 40.47619%; }
-
-.emojione-1f1fe-1f1ea {
- background-position: 30.95238% 40.47619%; }
-
-.emojione-1f1fe-1f1f9 {
- background-position: 33.33333% 40.47619%; }
-
-.emojione-1f1fe {
- background-position: 35.71429% 40.47619%; }
-
-.emojione-1f1ff-1f1e6 {
- background-position: 38.09524% 40.47619%; }
-
-.emojione-1f1ff-1f1f2 {
- background-position: 40.47619% 40.47619%; }
-
-.emojione-1f1ff-1f1fc {
- background-position: 42.85714% 0%; }
-
-.emojione-1f1ff {
- background-position: 42.85714% 2.38095%; }
-
-.emojione-1f201 {
- background-position: 42.85714% 4.7619%; }
-
-.emojione-1f202 {
- background-position: 42.85714% 7.14286%; }
-
-.emojione-1f21a {
- background-position: 42.85714% 9.52381%; }
-
-.emojione-1f22f {
- background-position: 42.85714% 11.90476%; }
-
-.emojione-1f232 {
- background-position: 42.85714% 14.28571%; }
-
-.emojione-1f233 {
- background-position: 42.85714% 16.66667%; }
-
-.emojione-1f234 {
- background-position: 42.85714% 19.04762%; }
-
-.emojione-1f235 {
- background-position: 42.85714% 21.42857%; }
-
-.emojione-1f236 {
- background-position: 42.85714% 23.80952%; }
-
-.emojione-1f237 {
- background-position: 42.85714% 26.19048%; }
-
-.emojione-1f238 {
- background-position: 42.85714% 28.57143%; }
-
-.emojione-1f239 {
- background-position: 42.85714% 30.95238%; }
-
-.emojione-1f23a {
- background-position: 42.85714% 33.33333%; }
-
-.emojione-1f250 {
- background-position: 42.85714% 35.71429%; }
-
-.emojione-1f251 {
- background-position: 42.85714% 38.09524%; }
-
-.emojione-1f300 {
- background-position: 42.85714% 40.47619%; }
-
-.emojione-1f301 {
- background-position: 0% 42.85714%; }
-
-.emojione-1f302 {
- background-position: 2.38095% 42.85714%; }
-
-.emojione-1f303 {
- background-position: 4.7619% 42.85714%; }
-
-.emojione-1f304 {
- background-position: 7.14286% 42.85714%; }
-
-.emojione-1f305 {
- background-position: 9.52381% 42.85714%; }
-
-.emojione-1f306 {
- background-position: 11.90476% 42.85714%; }
-
-.emojione-1f307 {
- background-position: 14.28571% 42.85714%; }
-
-.emojione-1f308 {
- background-position: 16.66667% 42.85714%; }
-
-.emojione-1f309 {
- background-position: 19.04762% 42.85714%; }
-
-.emojione-1f30a {
- background-position: 21.42857% 42.85714%; }
-
-.emojione-1f30b {
- background-position: 23.80952% 42.85714%; }
-
-.emojione-1f30c {
- background-position: 26.19048% 42.85714%; }
-
-.emojione-1f30d {
- background-position: 28.57143% 42.85714%; }
-
-.emojione-1f30e {
- background-position: 30.95238% 42.85714%; }
-
-.emojione-1f30f {
- background-position: 33.33333% 42.85714%; }
-
-.emojione-1f310 {
- background-position: 35.71429% 42.85714%; }
-
-.emojione-1f311 {
- background-position: 38.09524% 42.85714%; }
-
-.emojione-1f312 {
- background-position: 40.47619% 42.85714%; }
-
-.emojione-1f313 {
- background-position: 42.85714% 42.85714%; }
-
-.emojione-1f314 {
- background-position: 45.2381% 0%; }
-
-.emojione-1f315 {
- background-position: 45.2381% 2.38095%; }
-
-.emojione-1f316 {
- background-position: 45.2381% 4.7619%; }
-
-.emojione-1f317 {
- background-position: 45.2381% 7.14286%; }
-
-.emojione-1f318 {
- background-position: 45.2381% 9.52381%; }
-
-.emojione-1f319 {
- background-position: 45.2381% 11.90476%; }
-
-.emojione-1f31a {
- background-position: 45.2381% 14.28571%; }
-
-.emojione-1f31b {
- background-position: 45.2381% 16.66667%; }
-
-.emojione-1f31c {
- background-position: 45.2381% 19.04762%; }
-
-.emojione-1f31d {
- background-position: 45.2381% 21.42857%; }
-
-.emojione-1f31e {
- background-position: 45.2381% 23.80952%; }
-
-.emojione-1f31f {
- background-position: 45.2381% 26.19048%; }
-
-.emojione-1f320 {
- background-position: 45.2381% 28.57143%; }
-
-.emojione-1f321 {
- background-position: 45.2381% 30.95238%; }
-
-.emojione-1f324 {
- background-position: 45.2381% 33.33333%; }
-
-.emojione-1f325 {
- background-position: 45.2381% 35.71429%; }
-
-.emojione-1f326 {
- background-position: 45.2381% 38.09524%; }
-
-.emojione-1f327 {
- background-position: 45.2381% 40.47619%; }
-
-.emojione-1f328 {
- background-position: 45.2381% 42.85714%; }
-
-.emojione-1f329 {
- background-position: 0% 45.2381%; }
-
-.emojione-1f32a {
- background-position: 2.38095% 45.2381%; }
-
-.emojione-1f32b {
- background-position: 4.7619% 45.2381%; }
-
-.emojione-1f32c {
- background-position: 7.14286% 45.2381%; }
-
-.emojione-1f32d {
- background-position: 9.52381% 45.2381%; }
-
-.emojione-1f32e {
- background-position: 11.90476% 45.2381%; }
-
-.emojione-1f32f {
- background-position: 14.28571% 45.2381%; }
-
-.emojione-1f330 {
- background-position: 16.66667% 45.2381%; }
-
-.emojione-1f331 {
- background-position: 19.04762% 45.2381%; }
-
-.emojione-1f332 {
- background-position: 21.42857% 45.2381%; }
-
-.emojione-1f333 {
- background-position: 23.80952% 45.2381%; }
-
-.emojione-1f334 {
- background-position: 26.19048% 45.2381%; }
-
-.emojione-1f335 {
- background-position: 28.57143% 45.2381%; }
-
-.emojione-1f336 {
- background-position: 30.95238% 45.2381%; }
-
-.emojione-1f337 {
- background-position: 33.33333% 45.2381%; }
-
-.emojione-1f338 {
- background-position: 35.71429% 45.2381%; }
-
-.emojione-1f339 {
- background-position: 38.09524% 45.2381%; }
-
-.emojione-1f33a {
- background-position: 40.47619% 45.2381%; }
-
-.emojione-1f33b {
- background-position: 42.85714% 45.2381%; }
-
-.emojione-1f33c {
- background-position: 45.2381% 45.2381%; }
-
-.emojione-1f33d {
- background-position: 47.61905% 0%; }
-
-.emojione-1f33e {
- background-position: 47.61905% 2.38095%; }
-
-.emojione-1f33f {
- background-position: 47.61905% 4.7619%; }
-
-.emojione-1f340 {
- background-position: 47.61905% 7.14286%; }
-
-.emojione-1f341 {
- background-position: 47.61905% 9.52381%; }
-
-.emojione-1f342 {
- background-position: 47.61905% 11.90476%; }
-
-.emojione-1f343 {
- background-position: 47.61905% 14.28571%; }
-
-.emojione-1f344 {
- background-position: 47.61905% 16.66667%; }
-
-.emojione-1f345 {
- background-position: 47.61905% 19.04762%; }
-
-.emojione-1f346 {
- background-position: 47.61905% 21.42857%; }
-
-.emojione-1f347 {
- background-position: 47.61905% 23.80952%; }
-
-.emojione-1f348 {
- background-position: 47.61905% 26.19048%; }
-
-.emojione-1f349 {
- background-position: 47.61905% 28.57143%; }
-
-.emojione-1f34a {
- background-position: 47.61905% 30.95238%; }
-
-.emojione-1f34b {
- background-position: 47.61905% 33.33333%; }
-
-.emojione-1f34c {
- background-position: 47.61905% 35.71429%; }
-
-.emojione-1f34d {
- background-position: 47.61905% 38.09524%; }
-
-.emojione-1f34e {
- background-position: 47.61905% 40.47619%; }
-
-.emojione-1f34f {
- background-position: 47.61905% 42.85714%; }
-
-.emojione-1f350 {
- background-position: 47.61905% 45.2381%; }
-
-.emojione-1f351 {
- background-position: 0% 47.61905%; }
-
-.emojione-1f352 {
- background-position: 2.38095% 47.61905%; }
-
-.emojione-1f353 {
- background-position: 4.7619% 47.61905%; }
-
-.emojione-1f354 {
- background-position: 7.14286% 47.61905%; }
-
-.emojione-1f355 {
- background-position: 9.52381% 47.61905%; }
-
-.emojione-1f356 {
- background-position: 11.90476% 47.61905%; }
-
-.emojione-1f357 {
- background-position: 14.28571% 47.61905%; }
-
-.emojione-1f358 {
- background-position: 16.66667% 47.61905%; }
-
-.emojione-1f359 {
- background-position: 19.04762% 47.61905%; }
-
-.emojione-1f35a {
- background-position: 21.42857% 47.61905%; }
-
-.emojione-1f35b {
- background-position: 23.80952% 47.61905%; }
-
-.emojione-1f35c {
- background-position: 26.19048% 47.61905%; }
-
-.emojione-1f35d {
- background-position: 28.57143% 47.61905%; }
-
-.emojione-1f35e {
- background-position: 30.95238% 47.61905%; }
-
-.emojione-1f35f {
- background-position: 33.33333% 47.61905%; }
-
-.emojione-1f360 {
- background-position: 35.71429% 47.61905%; }
-
-.emojione-1f361 {
- background-position: 38.09524% 47.61905%; }
-
-.emojione-1f362 {
- background-position: 40.47619% 47.61905%; }
-
-.emojione-1f363 {
- background-position: 42.85714% 47.61905%; }
-
-.emojione-1f364 {
- background-position: 45.2381% 47.61905%; }
-
-.emojione-1f365 {
- background-position: 47.61905% 47.61905%; }
-
-.emojione-1f366 {
- background-position: 50% 0%; }
-
-.emojione-1f367 {
- background-position: 50% 2.38095%; }
-
-.emojione-1f368 {
- background-position: 50% 4.7619%; }
-
-.emojione-1f369 {
- background-position: 50% 7.14286%; }
-
-.emojione-1f36a {
- background-position: 50% 9.52381%; }
-
-.emojione-1f36b {
- background-position: 50% 11.90476%; }
-
-.emojione-1f36c {
- background-position: 50% 14.28571%; }
-
-.emojione-1f36d {
- background-position: 50% 16.66667%; }
-
-.emojione-1f36e {
- background-position: 50% 19.04762%; }
-
-.emojione-1f36f {
- background-position: 50% 21.42857%; }
-
-.emojione-1f370 {
- background-position: 50% 23.80952%; }
-
-.emojione-1f371 {
- background-position: 50% 26.19048%; }
-
-.emojione-1f372 {
- background-position: 50% 28.57143%; }
-
-.emojione-1f373 {
- background-position: 50% 30.95238%; }
-
-.emojione-1f374 {
- background-position: 50% 33.33333%; }
-
-.emojione-1f375 {
- background-position: 50% 35.71429%; }
-
-.emojione-1f376 {
- background-position: 50% 38.09524%; }
-
-.emojione-1f377 {
- background-position: 50% 40.47619%; }
-
-.emojione-1f378 {
- background-position: 50% 42.85714%; }
-
-.emojione-1f379 {
- background-position: 50% 45.2381%; }
-
-.emojione-1f37a {
- background-position: 50% 47.61905%; }
-
-.emojione-1f37b {
- background-position: 0% 50%; }
-
-.emojione-1f37c {
- background-position: 2.38095% 50%; }
-
-.emojione-1f37d {
- background-position: 4.7619% 50%; }
-
-.emojione-1f37e {
- background-position: 7.14286% 50%; }
-
-.emojione-1f37f {
- background-position: 9.52381% 50%; }
-
-.emojione-1f380 {
- background-position: 11.90476% 50%; }
-
-.emojione-1f381 {
- background-position: 14.28571% 50%; }
-
-.emojione-1f382 {
- background-position: 16.66667% 50%; }
-
-.emojione-1f383 {
- background-position: 19.04762% 50%; }
-
-.emojione-1f384 {
- background-position: 21.42857% 50%; }
-
-.emojione-1f385-1f3fb {
- background-position: 23.80952% 50%; }
-
-.emojione-1f385-1f3fc {
- background-position: 26.19048% 50%; }
-
-.emojione-1f385-1f3fd {
- background-position: 28.57143% 50%; }
-
-.emojione-1f385-1f3fe {
- background-position: 30.95238% 50%; }
-
-.emojione-1f385-1f3ff {
- background-position: 33.33333% 50%; }
-
-.emojione-1f385 {
- background-position: 35.71429% 50%; }
-
-.emojione-1f386 {
- background-position: 38.09524% 50%; }
-
-.emojione-1f387 {
- background-position: 40.47619% 50%; }
-
-.emojione-1f388 {
- background-position: 42.85714% 50%; }
-
-.emojione-1f389 {
- background-position: 45.2381% 50%; }
-
-.emojione-1f38a {
- background-position: 47.61905% 50%; }
-
-.emojione-1f38b {
- background-position: 50% 50%; }
-
-.emojione-1f38c {
- background-position: 52.38095% 0%; }
-
-.emojione-1f38d {
- background-position: 52.38095% 2.38095%; }
-
-.emojione-1f38e {
- background-position: 52.38095% 4.7619%; }
-
-.emojione-1f38f {
- background-position: 52.38095% 7.14286%; }
-
-.emojione-1f390 {
- background-position: 52.38095% 9.52381%; }
-
-.emojione-1f391 {
- background-position: 52.38095% 11.90476%; }
-
-.emojione-1f392 {
- background-position: 52.38095% 14.28571%; }
-
-.emojione-1f393 {
- background-position: 52.38095% 16.66667%; }
-
-.emojione-1f396 {
- background-position: 52.38095% 19.04762%; }
-
-.emojione-1f397 {
- background-position: 52.38095% 21.42857%; }
-
-.emojione-1f399 {
- background-position: 52.38095% 23.80952%; }
-
-.emojione-1f39a {
- background-position: 52.38095% 26.19048%; }
-
-.emojione-1f39b {
- background-position: 52.38095% 28.57143%; }
-
-.emojione-1f39e {
- background-position: 52.38095% 30.95238%; }
-
-.emojione-1f39f {
- background-position: 52.38095% 33.33333%; }
-
-.emojione-1f3a0 {
- background-position: 52.38095% 35.71429%; }
-
-.emojione-1f3a1 {
- background-position: 52.38095% 38.09524%; }
-
-.emojione-1f3a2 {
- background-position: 52.38095% 40.47619%; }
-
-.emojione-1f3a3 {
- background-position: 52.38095% 42.85714%; }
-
-.emojione-1f3a4 {
- background-position: 52.38095% 45.2381%; }
-
-.emojione-1f3a5 {
- background-position: 52.38095% 47.61905%; }
-
-.emojione-1f3a6 {
- background-position: 52.38095% 50%; }
-
-.emojione-1f3a7 {
- background-position: 0% 52.38095%; }
-
-.emojione-1f3a8 {
- background-position: 2.38095% 52.38095%; }
-
-.emojione-1f3a9 {
- background-position: 4.7619% 52.38095%; }
-
-.emojione-1f3aa {
- background-position: 7.14286% 52.38095%; }
-
-.emojione-1f3ab {
- background-position: 9.52381% 52.38095%; }
-
-.emojione-1f3ac {
- background-position: 11.90476% 52.38095%; }
-
-.emojione-1f3ad {
- background-position: 14.28571% 52.38095%; }
-
-.emojione-1f3ae {
- background-position: 16.66667% 52.38095%; }
-
-.emojione-1f3af {
- background-position: 19.04762% 52.38095%; }
-
-.emojione-1f3b0 {
- background-position: 21.42857% 52.38095%; }
-
-.emojione-1f3b1 {
- background-position: 23.80952% 52.38095%; }
-
-.emojione-1f3b2 {
- background-position: 26.19048% 52.38095%; }
-
-.emojione-1f3b3 {
- background-position: 28.57143% 52.38095%; }
-
-.emojione-1f3b4 {
- background-position: 30.95238% 52.38095%; }
-
-.emojione-1f3b5 {
- background-position: 33.33333% 52.38095%; }
-
-.emojione-1f3b6 {
- background-position: 35.71429% 52.38095%; }
-
-.emojione-1f3b7 {
- background-position: 38.09524% 52.38095%; }
-
-.emojione-1f3b8 {
- background-position: 40.47619% 52.38095%; }
-
-.emojione-1f3b9 {
- background-position: 42.85714% 52.38095%; }
-
-.emojione-1f3ba {
- background-position: 45.2381% 52.38095%; }
-
-.emojione-1f3bb {
- background-position: 47.61905% 52.38095%; }
-
-.emojione-1f3bc {
- background-position: 50% 52.38095%; }
-
-.emojione-1f3bd {
- background-position: 52.38095% 52.38095%; }
-
-.emojione-1f3be {
- background-position: 54.7619% 0%; }
-
-.emojione-1f3bf {
- background-position: 54.7619% 2.38095%; }
-
-.emojione-1f3c0 {
- background-position: 54.7619% 4.7619%; }
-
-.emojione-1f3c1 {
- background-position: 54.7619% 7.14286%; }
-
-.emojione-1f3c2 {
- background-position: 54.7619% 9.52381%; }
-
-.emojione-1f3c3-1f3fb {
- background-position: 54.7619% 11.90476%; }
-
-.emojione-1f3c3-1f3fc {
- background-position: 54.7619% 14.28571%; }
-
-.emojione-1f3c3-1f3fd {
- background-position: 54.7619% 16.66667%; }
-
-.emojione-1f3c3-1f3fe {
- background-position: 54.7619% 19.04762%; }
-
-.emojione-1f3c3-1f3ff {
- background-position: 54.7619% 21.42857%; }
-
-.emojione-1f3c3 {
- background-position: 54.7619% 23.80952%; }
-
-.emojione-1f3c4-1f3fb {
- background-position: 54.7619% 26.19048%; }
-
-.emojione-1f3c4-1f3fc {
- background-position: 54.7619% 28.57143%; }
-
-.emojione-1f3c4-1f3fd {
- background-position: 54.7619% 30.95238%; }
-
-.emojione-1f3c4-1f3fe {
- background-position: 54.7619% 33.33333%; }
-
-.emojione-1f3c4-1f3ff {
- background-position: 54.7619% 35.71429%; }
-
-.emojione-1f3c4 {
- background-position: 54.7619% 38.09524%; }
-
-.emojione-1f3c5 {
- background-position: 54.7619% 40.47619%; }
-
-.emojione-1f3c6 {
- background-position: 54.7619% 42.85714%; }
-
-.emojione-1f3c7-1f3fb {
- background-position: 54.7619% 45.2381%; }
-
-.emojione-1f3c7-1f3fc {
- background-position: 54.7619% 47.61905%; }
-
-.emojione-1f3c7-1f3fd {
- background-position: 54.7619% 50%; }
-
-.emojione-1f3c7-1f3fe {
- background-position: 54.7619% 52.38095%; }
-
-.emojione-1f3c7-1f3ff {
- background-position: 0% 54.7619%; }
-
-.emojione-1f3c7 {
- background-position: 2.38095% 54.7619%; }
-
-.emojione-1f3c8 {
- background-position: 4.7619% 54.7619%; }
-
-.emojione-1f3c9 {
- background-position: 7.14286% 54.7619%; }
-
-.emojione-1f3ca-1f3fb {
- background-position: 9.52381% 54.7619%; }
-
-.emojione-1f3ca-1f3fc {
- background-position: 11.90476% 54.7619%; }
-
-.emojione-1f3ca-1f3fd {
- background-position: 14.28571% 54.7619%; }
-
-.emojione-1f3ca-1f3fe {
- background-position: 16.66667% 54.7619%; }
-
-.emojione-1f3ca-1f3ff {
- background-position: 19.04762% 54.7619%; }
-
-.emojione-1f3ca {
- background-position: 21.42857% 54.7619%; }
-
-.emojione-1f3cb-1f3fb {
- background-position: 23.80952% 54.7619%; }
-
-.emojione-1f3cb-1f3fc {
- background-position: 26.19048% 54.7619%; }
-
-.emojione-1f3cb-1f3fd {
- background-position: 28.57143% 54.7619%; }
-
-.emojione-1f3cb-1f3fe {
- background-position: 30.95238% 54.7619%; }
-
-.emojione-1f3cb-1f3ff {
- background-position: 33.33333% 54.7619%; }
-
-.emojione-1f3cb {
- background-position: 35.71429% 54.7619%; }
-
-.emojione-1f3cc {
- background-position: 38.09524% 54.7619%; }
-
-.emojione-1f3cd {
- background-position: 40.47619% 54.7619%; }
-
-.emojione-1f3ce {
- background-position: 42.85714% 54.7619%; }
-
-.emojione-1f3cf {
- background-position: 45.2381% 54.7619%; }
-
-.emojione-1f3d0 {
- background-position: 47.61905% 54.7619%; }
-
-.emojione-1f3d1 {
- background-position: 50% 54.7619%; }
-
-.emojione-1f3d2 {
- background-position: 52.38095% 54.7619%; }
-
-.emojione-1f3d3 {
- background-position: 54.7619% 54.7619%; }
-
-.emojione-1f3d4 {
- background-position: 57.14286% 0%; }
-
-.emojione-1f3d5 {
- background-position: 57.14286% 2.38095%; }
-
-.emojione-1f3d6 {
- background-position: 57.14286% 4.7619%; }
-
-.emojione-1f3d7 {
- background-position: 57.14286% 7.14286%; }
-
-.emojione-1f3d8 {
- background-position: 57.14286% 9.52381%; }
-
-.emojione-1f3d9 {
- background-position: 57.14286% 11.90476%; }
-
-.emojione-1f3da {
- background-position: 57.14286% 14.28571%; }
-
-.emojione-1f3db {
- background-position: 57.14286% 16.66667%; }
-
-.emojione-1f3dc {
- background-position: 57.14286% 19.04762%; }
-
-.emojione-1f3dd {
- background-position: 57.14286% 21.42857%; }
-
-.emojione-1f3de {
- background-position: 57.14286% 23.80952%; }
-
-.emojione-1f3df {
- background-position: 57.14286% 26.19048%; }
-
-.emojione-1f3e0 {
- background-position: 57.14286% 28.57143%; }
-
-.emojione-1f3e1 {
- background-position: 57.14286% 30.95238%; }
-
-.emojione-1f3e2 {
- background-position: 57.14286% 33.33333%; }
-
-.emojione-1f3e3 {
- background-position: 57.14286% 35.71429%; }
-
-.emojione-1f3e4 {
- background-position: 57.14286% 38.09524%; }
-
-.emojione-1f3e5 {
- background-position: 57.14286% 40.47619%; }
-
-.emojione-1f3e6 {
- background-position: 57.14286% 42.85714%; }
-
-.emojione-1f3e7 {
- background-position: 57.14286% 45.2381%; }
-
-.emojione-1f3e8 {
- background-position: 57.14286% 47.61905%; }
-
-.emojione-1f3e9 {
- background-position: 57.14286% 50%; }
-
-.emojione-1f3ea {
- background-position: 57.14286% 52.38095%; }
-
-.emojione-1f3eb {
- background-position: 57.14286% 54.7619%; }
-
-.emojione-1f3ec {
- background-position: 0% 57.14286%; }
-
-.emojione-1f3ed {
- background-position: 2.38095% 57.14286%; }
-
-.emojione-1f3ee {
- background-position: 4.7619% 57.14286%; }
-
-.emojione-1f3ef {
- background-position: 7.14286% 57.14286%; }
-
-.emojione-1f3f0 {
- background-position: 9.52381% 57.14286%; }
-
-.emojione-1f3f3-1f308 {
- background-position: 11.90476% 57.14286%; }
-
-.emojione-1f3f3 {
- background-position: 14.28571% 57.14286%; }
-
-.emojione-1f3f4 {
- background-position: 16.66667% 57.14286%; }
-
-.emojione-1f3f5 {
- background-position: 19.04762% 57.14286%; }
-
-.emojione-1f3f7 {
- background-position: 21.42857% 57.14286%; }
-
-.emojione-1f3f8 {
- background-position: 23.80952% 57.14286%; }
-
-.emojione-1f3f9 {
- background-position: 26.19048% 57.14286%; }
-
-.emojione-1f3fa {
- background-position: 28.57143% 57.14286%; }
-
-.emojione-1f3fb {
- background-position: 30.95238% 57.14286%; }
-
-.emojione-1f3fc {
- background-position: 33.33333% 57.14286%; }
-
-.emojione-1f3fd {
- background-position: 35.71429% 57.14286%; }
-
-.emojione-1f3fe {
- background-position: 38.09524% 57.14286%; }
-
-.emojione-1f3ff {
- background-position: 40.47619% 57.14286%; }
-
-.emojione-1f400 {
- background-position: 42.85714% 57.14286%; }
-
-.emojione-1f401 {
- background-position: 45.2381% 57.14286%; }
-
-.emojione-1f402 {
- background-position: 47.61905% 57.14286%; }
-
-.emojione-1f403 {
- background-position: 50% 57.14286%; }
-
-.emojione-1f404 {
- background-position: 52.38095% 57.14286%; }
-
-.emojione-1f405 {
- background-position: 54.7619% 57.14286%; }
-
-.emojione-1f406 {
- background-position: 57.14286% 57.14286%; }
-
-.emojione-1f407 {
- background-position: 59.52381% 0%; }
-
-.emojione-1f408 {
- background-position: 59.52381% 2.38095%; }
-
-.emojione-1f409 {
- background-position: 59.52381% 4.7619%; }
-
-.emojione-1f40a {
- background-position: 59.52381% 7.14286%; }
-
-.emojione-1f40b {
- background-position: 59.52381% 9.52381%; }
-
-.emojione-1f40c {
- background-position: 59.52381% 11.90476%; }
-
-.emojione-1f40d {
- background-position: 59.52381% 14.28571%; }
-
-.emojione-1f40e {
- background-position: 59.52381% 16.66667%; }
-
-.emojione-1f40f {
- background-position: 59.52381% 19.04762%; }
-
-.emojione-1f410 {
- background-position: 59.52381% 21.42857%; }
-
-.emojione-1f411 {
- background-position: 59.52381% 23.80952%; }
-
-.emojione-1f412 {
- background-position: 59.52381% 26.19048%; }
-
-.emojione-1f413 {
- background-position: 59.52381% 28.57143%; }
-
-.emojione-1f414 {
- background-position: 59.52381% 30.95238%; }
-
-.emojione-1f415 {
- background-position: 59.52381% 33.33333%; }
-
-.emojione-1f416 {
- background-position: 59.52381% 35.71429%; }
-
-.emojione-1f417 {
- background-position: 59.52381% 38.09524%; }
-
-.emojione-1f418 {
- background-position: 59.52381% 40.47619%; }
-
-.emojione-1f419 {
- background-position: 59.52381% 42.85714%; }
-
-.emojione-1f41a {
- background-position: 59.52381% 45.2381%; }
-
-.emojione-1f41b {
- background-position: 59.52381% 47.61905%; }
-
-.emojione-1f41c {
- background-position: 59.52381% 50%; }
-
-.emojione-1f41d {
- background-position: 59.52381% 52.38095%; }
-
-.emojione-1f41e {
- background-position: 59.52381% 54.7619%; }
-
-.emojione-1f41f {
- background-position: 59.52381% 57.14286%; }
-
-.emojione-1f420 {
- background-position: 0% 59.52381%; }
-
-.emojione-1f421 {
- background-position: 2.38095% 59.52381%; }
-
-.emojione-1f422 {
- background-position: 4.7619% 59.52381%; }
-
-.emojione-1f423 {
- background-position: 7.14286% 59.52381%; }
-
-.emojione-1f424 {
- background-position: 9.52381% 59.52381%; }
-
-.emojione-1f425 {
- background-position: 11.90476% 59.52381%; }
-
-.emojione-1f426 {
- background-position: 14.28571% 59.52381%; }
-
-.emojione-1f427 {
- background-position: 16.66667% 59.52381%; }
-
-.emojione-1f428 {
- background-position: 19.04762% 59.52381%; }
-
-.emojione-1f429 {
- background-position: 21.42857% 59.52381%; }
-
-.emojione-1f42a {
- background-position: 23.80952% 59.52381%; }
-
-.emojione-1f42b {
- background-position: 26.19048% 59.52381%; }
-
-.emojione-1f42c {
- background-position: 28.57143% 59.52381%; }
-
-.emojione-1f42d {
- background-position: 30.95238% 59.52381%; }
-
-.emojione-1f42e {
- background-position: 33.33333% 59.52381%; }
-
-.emojione-1f42f {
- background-position: 35.71429% 59.52381%; }
-
-.emojione-1f430 {
- background-position: 38.09524% 59.52381%; }
-
-.emojione-1f431 {
- background-position: 40.47619% 59.52381%; }
-
-.emojione-1f432 {
- background-position: 42.85714% 59.52381%; }
-
-.emojione-1f433 {
- background-position: 45.2381% 59.52381%; }
-
-.emojione-1f434 {
- background-position: 47.61905% 59.52381%; }
-
-.emojione-1f435 {
- background-position: 50% 59.52381%; }
-
-.emojione-1f436 {
- background-position: 52.38095% 59.52381%; }
-
-.emojione-1f437 {
- background-position: 54.7619% 59.52381%; }
-
-.emojione-1f438 {
- background-position: 57.14286% 59.52381%; }
-
-.emojione-1f439 {
- background-position: 59.52381% 59.52381%; }
-
-.emojione-1f43a {
- background-position: 61.90476% 0%; }
-
-.emojione-1f43b {
- background-position: 61.90476% 2.38095%; }
-
-.emojione-1f43c {
- background-position: 61.90476% 4.7619%; }
-
-.emojione-1f43d {
- background-position: 61.90476% 7.14286%; }
-
-.emojione-1f43e {
- background-position: 61.90476% 9.52381%; }
-
-.emojione-1f43f {
- background-position: 61.90476% 11.90476%; }
-
-.emojione-1f440 {
- background-position: 61.90476% 14.28571%; }
-
-.emojione-1f441-1f5e8 {
- background-position: 61.90476% 16.66667%; }
-
-.emojione-1f441 {
- background-position: 61.90476% 19.04762%; }
-
-.emojione-1f442-1f3fb {
- background-position: 61.90476% 21.42857%; }
-
-.emojione-1f442-1f3fc {
- background-position: 61.90476% 23.80952%; }
-
-.emojione-1f442-1f3fd {
- background-position: 61.90476% 26.19048%; }
-
-.emojione-1f442-1f3fe {
- background-position: 61.90476% 28.57143%; }
-
-.emojione-1f442-1f3ff {
- background-position: 61.90476% 30.95238%; }
-
-.emojione-1f442 {
- background-position: 61.90476% 33.33333%; }
-
-.emojione-1f443-1f3fb {
- background-position: 61.90476% 35.71429%; }
-
-.emojione-1f443-1f3fc {
- background-position: 61.90476% 38.09524%; }
-
-.emojione-1f443-1f3fd {
- background-position: 61.90476% 40.47619%; }
-
-.emojione-1f443-1f3fe {
- background-position: 61.90476% 42.85714%; }
-
-.emojione-1f443-1f3ff {
- background-position: 61.90476% 45.2381%; }
-
-.emojione-1f443 {
- background-position: 61.90476% 47.61905%; }
-
-.emojione-1f444 {
- background-position: 61.90476% 50%; }
-
-.emojione-1f445 {
- background-position: 61.90476% 52.38095%; }
-
-.emojione-1f446-1f3fb {
- background-position: 61.90476% 54.7619%; }
-
-.emojione-1f446-1f3fc {
- background-position: 61.90476% 57.14286%; }
-
-.emojione-1f446-1f3fd {
- background-position: 61.90476% 59.52381%; }
-
-.emojione-1f446-1f3fe {
- background-position: 0% 61.90476%; }
-
-.emojione-1f446-1f3ff {
- background-position: 2.38095% 61.90476%; }
-
-.emojione-1f446 {
- background-position: 4.7619% 61.90476%; }
-
-.emojione-1f447-1f3fb {
- background-position: 7.14286% 61.90476%; }
-
-.emojione-1f447-1f3fc {
- background-position: 9.52381% 61.90476%; }
-
-.emojione-1f447-1f3fd {
- background-position: 11.90476% 61.90476%; }
-
-.emojione-1f447-1f3fe {
- background-position: 14.28571% 61.90476%; }
-
-.emojione-1f447-1f3ff {
- background-position: 16.66667% 61.90476%; }
-
-.emojione-1f447 {
- background-position: 19.04762% 61.90476%; }
-
-.emojione-1f448-1f3fb {
- background-position: 21.42857% 61.90476%; }
-
-.emojione-1f448-1f3fc {
- background-position: 23.80952% 61.90476%; }
-
-.emojione-1f448-1f3fd {
- background-position: 26.19048% 61.90476%; }
-
-.emojione-1f448-1f3fe {
- background-position: 28.57143% 61.90476%; }
-
-.emojione-1f448-1f3ff {
- background-position: 30.95238% 61.90476%; }
-
-.emojione-1f448 {
- background-position: 33.33333% 61.90476%; }
-
-.emojione-1f449-1f3fb {
- background-position: 35.71429% 61.90476%; }
-
-.emojione-1f449-1f3fc {
- background-position: 38.09524% 61.90476%; }
-
-.emojione-1f449-1f3fd {
- background-position: 40.47619% 61.90476%; }
-
-.emojione-1f449-1f3fe {
- background-position: 42.85714% 61.90476%; }
-
-.emojione-1f449-1f3ff {
- background-position: 45.2381% 61.90476%; }
-
-.emojione-1f449 {
- background-position: 47.61905% 61.90476%; }
-
-.emojione-1f44a-1f3fb {
- background-position: 50% 61.90476%; }
-
-.emojione-1f44a-1f3fc {
- background-position: 52.38095% 61.90476%; }
-
-.emojione-1f44a-1f3fd {
- background-position: 54.7619% 61.90476%; }
-
-.emojione-1f44a-1f3fe {
- background-position: 57.14286% 61.90476%; }
-
-.emojione-1f44a-1f3ff {
- background-position: 59.52381% 61.90476%; }
-
-.emojione-1f44a {
- background-position: 61.90476% 61.90476%; }
-
-.emojione-1f44b-1f3fb {
- background-position: 64.28571% 0%; }
-
-.emojione-1f44b-1f3fc {
- background-position: 64.28571% 2.38095%; }
-
-.emojione-1f44b-1f3fd {
- background-position: 64.28571% 4.7619%; }
-
-.emojione-1f44b-1f3fe {
- background-position: 64.28571% 7.14286%; }
-
-.emojione-1f44b-1f3ff {
- background-position: 64.28571% 9.52381%; }
-
-.emojione-1f44b {
- background-position: 64.28571% 11.90476%; }
-
-.emojione-1f44c-1f3fb {
- background-position: 64.28571% 14.28571%; }
-
-.emojione-1f44c-1f3fc {
- background-position: 64.28571% 16.66667%; }
-
-.emojione-1f44c-1f3fd {
- background-position: 64.28571% 19.04762%; }
-
-.emojione-1f44c-1f3fe {
- background-position: 64.28571% 21.42857%; }
-
-.emojione-1f44c-1f3ff {
- background-position: 64.28571% 23.80952%; }
-
-.emojione-1f44c {
- background-position: 64.28571% 26.19048%; }
-
-.emojione-1f44d-1f3fb {
- background-position: 64.28571% 28.57143%; }
-
-.emojione-1f44d-1f3fc {
- background-position: 64.28571% 30.95238%; }
-
-.emojione-1f44d-1f3fd {
- background-position: 64.28571% 33.33333%; }
-
-.emojione-1f44d-1f3fe {
- background-position: 64.28571% 35.71429%; }
-
-.emojione-1f44d-1f3ff {
- background-position: 64.28571% 38.09524%; }
-
-.emojione-1f44d {
- background-position: 64.28571% 40.47619%; }
-
-.emojione-1f44e-1f3fb {
- background-position: 64.28571% 42.85714%; }
-
-.emojione-1f44e-1f3fc {
- background-position: 64.28571% 45.2381%; }
-
-.emojione-1f44e-1f3fd {
- background-position: 64.28571% 47.61905%; }
-
-.emojione-1f44e-1f3fe {
- background-position: 64.28571% 50%; }
-
-.emojione-1f44e-1f3ff {
- background-position: 64.28571% 52.38095%; }
-
-.emojione-1f44e {
- background-position: 64.28571% 54.7619%; }
-
-.emojione-1f44f-1f3fb {
- background-position: 64.28571% 57.14286%; }
-
-.emojione-1f44f-1f3fc {
- background-position: 64.28571% 59.52381%; }
-
-.emojione-1f44f-1f3fd {
- background-position: 64.28571% 61.90476%; }
-
-.emojione-1f44f-1f3fe {
- background-position: 0% 64.28571%; }
-
-.emojione-1f44f-1f3ff {
- background-position: 2.38095% 64.28571%; }
-
-.emojione-1f44f {
- background-position: 4.7619% 64.28571%; }
-
-.emojione-1f450-1f3fb {
- background-position: 7.14286% 64.28571%; }
-
-.emojione-1f450-1f3fc {
- background-position: 9.52381% 64.28571%; }
-
-.emojione-1f450-1f3fd {
- background-position: 11.90476% 64.28571%; }
-
-.emojione-1f450-1f3fe {
- background-position: 14.28571% 64.28571%; }
-
-.emojione-1f450-1f3ff {
- background-position: 16.66667% 64.28571%; }
-
-.emojione-1f450 {
- background-position: 19.04762% 64.28571%; }
-
-.emojione-1f451 {
- background-position: 21.42857% 64.28571%; }
-
-.emojione-1f452 {
- background-position: 23.80952% 64.28571%; }
-
-.emojione-1f453 {
- background-position: 26.19048% 64.28571%; }
-
-.emojione-1f454 {
- background-position: 28.57143% 64.28571%; }
-
-.emojione-1f455 {
- background-position: 30.95238% 64.28571%; }
-
-.emojione-1f456 {
- background-position: 33.33333% 64.28571%; }
-
-.emojione-1f457 {
- background-position: 35.71429% 64.28571%; }
-
-.emojione-1f458 {
- background-position: 38.09524% 64.28571%; }
-
-.emojione-1f459 {
- background-position: 40.47619% 64.28571%; }
-
-.emojione-1f45a {
- background-position: 42.85714% 64.28571%; }
-
-.emojione-1f45b {
- background-position: 45.2381% 64.28571%; }
-
-.emojione-1f45c {
- background-position: 47.61905% 64.28571%; }
-
-.emojione-1f45d {
- background-position: 50% 64.28571%; }
-
-.emojione-1f45e {
- background-position: 52.38095% 64.28571%; }
-
-.emojione-1f45f {
- background-position: 54.7619% 64.28571%; }
-
-.emojione-1f460 {
- background-position: 57.14286% 64.28571%; }
-
-.emojione-1f461 {
- background-position: 59.52381% 64.28571%; }
-
-.emojione-1f462 {
- background-position: 61.90476% 64.28571%; }
-
-.emojione-1f463 {
- background-position: 64.28571% 64.28571%; }
-
-.emojione-1f464 {
- background-position: 66.66667% 0%; }
-
-.emojione-1f465 {
- background-position: 66.66667% 2.38095%; }
-
-.emojione-1f466-1f3fb {
- background-position: 66.66667% 4.7619%; }
-
-.emojione-1f466-1f3fc {
- background-position: 66.66667% 7.14286%; }
-
-.emojione-1f466-1f3fd {
- background-position: 66.66667% 9.52381%; }
-
-.emojione-1f466-1f3fe {
- background-position: 66.66667% 11.90476%; }
-
-.emojione-1f466-1f3ff {
- background-position: 66.66667% 14.28571%; }
-
-.emojione-1f466 {
- background-position: 66.66667% 16.66667%; }
-
-.emojione-1f467-1f3fb {
- background-position: 66.66667% 19.04762%; }
-
-.emojione-1f467-1f3fc {
- background-position: 66.66667% 21.42857%; }
-
-.emojione-1f467-1f3fd {
- background-position: 66.66667% 23.80952%; }
-
-.emojione-1f467-1f3fe {
- background-position: 66.66667% 26.19048%; }
-
-.emojione-1f467-1f3ff {
- background-position: 66.66667% 28.57143%; }
-
-.emojione-1f467 {
- background-position: 66.66667% 30.95238%; }
-
-.emojione-1f468-1f3fb {
- background-position: 66.66667% 33.33333%; }
-
-.emojione-1f468-1f3fc {
- background-position: 66.66667% 35.71429%; }
-
-.emojione-1f468-1f3fd {
- background-position: 66.66667% 38.09524%; }
-
-.emojione-1f468-1f3fe {
- background-position: 66.66667% 40.47619%; }
-
-.emojione-1f468-1f3ff {
- background-position: 66.66667% 42.85714%; }
-
-.emojione-1f468-1f468-1f466-1f466 {
- background-position: 66.66667% 45.2381%; }
-
-.emojione-1f468-1f468-1f466 {
- background-position: 66.66667% 47.61905%; }
-
-.emojione-1f468-1f468-1f467-1f466 {
- background-position: 66.66667% 50%; }
-
-.emojione-1f468-1f468-1f467-1f467 {
- background-position: 66.66667% 52.38095%; }
-
-.emojione-1f468-1f468-1f467 {
- background-position: 66.66667% 54.7619%; }
-
-.emojione-1f468-1f469-1f466-1f466 {
- background-position: 66.66667% 57.14286%; }
-
-.emojione-1f468-1f469-1f467-1f466 {
- background-position: 66.66667% 59.52381%; }
-
-.emojione-1f468-1f469-1f467-1f467 {
- background-position: 66.66667% 61.90476%; }
-
-.emojione-1f468-1f469-1f467 {
- background-position: 66.66667% 64.28571%; }
-
-.emojione-1f468-2764-1f468 {
- background-position: 0% 66.66667%; }
-
-.emojione-1f468-2764-1f48b-1f468 {
- background-position: 2.38095% 66.66667%; }
-
-.emojione-1f468 {
- background-position: 4.7619% 66.66667%; }
-
-.emojione-1f469-1f3fb {
- background-position: 7.14286% 66.66667%; }
-
-.emojione-1f469-1f3fc {
- background-position: 9.52381% 66.66667%; }
-
-.emojione-1f469-1f3fd {
- background-position: 11.90476% 66.66667%; }
-
-.emojione-1f469-1f3fe {
- background-position: 14.28571% 66.66667%; }
-
-.emojione-1f469-1f3ff {
- background-position: 16.66667% 66.66667%; }
-
-.emojione-1f469-1f469-1f466-1f466 {
- background-position: 19.04762% 66.66667%; }
-
-.emojione-1f469-1f469-1f466 {
- background-position: 21.42857% 66.66667%; }
-
-.emojione-1f469-1f469-1f467-1f466 {
- background-position: 23.80952% 66.66667%; }
-
-.emojione-1f469-1f469-1f467-1f467 {
- background-position: 26.19048% 66.66667%; }
-
-.emojione-1f469-1f469-1f467 {
- background-position: 28.57143% 66.66667%; }
-
-.emojione-1f469-2764-1f469 {
- background-position: 30.95238% 66.66667%; }
-
-.emojione-1f469-2764-1f48b-1f469 {
- background-position: 33.33333% 66.66667%; }
-
-.emojione-1f469 {
- background-position: 35.71429% 66.66667%; }
-
-.emojione-1f46a {
- background-position: 38.09524% 66.66667%; }
-
-.emojione-1f46b {
- background-position: 40.47619% 66.66667%; }
-
-.emojione-1f46c {
- background-position: 42.85714% 66.66667%; }
-
-.emojione-1f46d {
- background-position: 45.2381% 66.66667%; }
-
-.emojione-1f46e-1f3fb {
- background-position: 47.61905% 66.66667%; }
-
-.emojione-1f46e-1f3fc {
- background-position: 0% 0%; }
-
-.emojione-1f46e-1f3fd {
- background-position: 52.38095% 66.66667%; }
-
-.emojione-1f46e-1f3fe {
- background-position: 54.7619% 66.66667%; }
-
-.emojione-1f46e-1f3ff {
- background-position: 57.14286% 66.66667%; }
-
-.emojione-1f46e {
- background-position: 59.52381% 66.66667%; }
-
-.emojione-1f46f {
- background-position: 61.90476% 66.66667%; }
-
-.emojione-1f470-1f3fb {
- background-position: 64.28571% 66.66667%; }
-
-.emojione-1f470-1f3fc {
- background-position: 66.66667% 66.66667%; }
-
-.emojione-1f470-1f3fd {
- background-position: 69.04762% 0%; }
-
-.emojione-1f470-1f3fe {
- background-position: 69.04762% 2.38095%; }
-
-.emojione-1f470-1f3ff {
- background-position: 69.04762% 4.7619%; }
-
-.emojione-1f470 {
- background-position: 69.04762% 7.14286%; }
-
-.emojione-1f471-1f3fb {
- background-position: 69.04762% 9.52381%; }
-
-.emojione-1f471-1f3fc {
- background-position: 69.04762% 11.90476%; }
-
-.emojione-1f471-1f3fd {
- background-position: 69.04762% 14.28571%; }
-
-.emojione-1f471-1f3fe {
- background-position: 69.04762% 16.66667%; }
-
-.emojione-1f471-1f3ff {
- background-position: 69.04762% 19.04762%; }
-
-.emojione-1f471 {
- background-position: 69.04762% 21.42857%; }
-
-.emojione-1f472-1f3fb {
- background-position: 69.04762% 23.80952%; }
-
-.emojione-1f472-1f3fc {
- background-position: 69.04762% 26.19048%; }
-
-.emojione-1f472-1f3fd {
- background-position: 69.04762% 28.57143%; }
-
-.emojione-1f472-1f3fe {
- background-position: 69.04762% 30.95238%; }
-
-.emojione-1f472-1f3ff {
- background-position: 69.04762% 33.33333%; }
-
-.emojione-1f472 {
- background-position: 69.04762% 35.71429%; }
-
-.emojione-1f473-1f3fb {
- background-position: 69.04762% 38.09524%; }
-
-.emojione-1f473-1f3fc {
- background-position: 69.04762% 40.47619%; }
-
-.emojione-1f473-1f3fd {
- background-position: 69.04762% 42.85714%; }
-
-.emojione-1f473-1f3fe {
- background-position: 69.04762% 45.2381%; }
-
-.emojione-1f473-1f3ff {
- background-position: 69.04762% 47.61905%; }
-
-.emojione-1f473 {
- background-position: 69.04762% 50%; }
-
-.emojione-1f474-1f3fb {
- background-position: 69.04762% 52.38095%; }
-
-.emojione-1f474-1f3fc {
- background-position: 69.04762% 54.7619%; }
-
-.emojione-1f474-1f3fd {
- background-position: 69.04762% 57.14286%; }
-
-.emojione-1f474-1f3fe {
- background-position: 69.04762% 59.52381%; }
-
-.emojione-1f474-1f3ff {
- background-position: 69.04762% 61.90476%; }
-
-.emojione-1f474 {
- background-position: 69.04762% 64.28571%; }
-
-.emojione-1f475-1f3fb {
- background-position: 69.04762% 66.66667%; }
-
-.emojione-1f475-1f3fc {
- background-position: 0% 69.04762%; }
-
-.emojione-1f475-1f3fd {
- background-position: 2.38095% 69.04762%; }
-
-.emojione-1f475-1f3fe {
- background-position: 4.7619% 69.04762%; }
-
-.emojione-1f475-1f3ff {
- background-position: 7.14286% 69.04762%; }
-
-.emojione-1f475 {
- background-position: 9.52381% 69.04762%; }
-
-.emojione-1f476-1f3fb {
- background-position: 11.90476% 69.04762%; }
-
-.emojione-1f476-1f3fc {
- background-position: 14.28571% 69.04762%; }
-
-.emojione-1f476-1f3fd {
- background-position: 16.66667% 69.04762%; }
-
-.emojione-1f476-1f3fe {
- background-position: 19.04762% 69.04762%; }
-
-.emojione-1f476-1f3ff {
- background-position: 21.42857% 69.04762%; }
-
-.emojione-1f476 {
- background-position: 23.80952% 69.04762%; }
-
-.emojione-1f477-1f3fb {
- background-position: 26.19048% 69.04762%; }
-
-.emojione-1f477-1f3fc {
- background-position: 28.57143% 69.04762%; }
-
-.emojione-1f477-1f3fd {
- background-position: 30.95238% 69.04762%; }
-
-.emojione-1f477-1f3fe {
- background-position: 33.33333% 69.04762%; }
-
-.emojione-1f477-1f3ff {
- background-position: 35.71429% 69.04762%; }
-
-.emojione-1f477 {
- background-position: 38.09524% 69.04762%; }
-
-.emojione-1f478-1f3fb {
- background-position: 40.47619% 69.04762%; }
-
-.emojione-1f478-1f3fc {
- background-position: 42.85714% 69.04762%; }
-
-.emojione-1f478-1f3fd {
- background-position: 45.2381% 69.04762%; }
-
-.emojione-1f478-1f3fe {
- background-position: 47.61905% 69.04762%; }
-
-.emojione-1f478-1f3ff {
- background-position: 50% 69.04762%; }
-
-.emojione-1f478 {
- background-position: 52.38095% 69.04762%; }
-
-.emojione-1f479 {
- background-position: 54.7619% 69.04762%; }
-
-.emojione-1f47a {
- background-position: 57.14286% 69.04762%; }
-
-.emojione-1f47b {
- background-position: 59.52381% 69.04762%; }
-
-.emojione-1f47c-1f3fb {
- background-position: 61.90476% 69.04762%; }
-
-.emojione-1f47c-1f3fc {
- background-position: 64.28571% 69.04762%; }
-
-.emojione-1f47c-1f3fd {
- background-position: 66.66667% 69.04762%; }
-
-.emojione-1f47c-1f3fe {
- background-position: 69.04762% 69.04762%; }
-
-.emojione-1f47c-1f3ff {
- background-position: 71.42857% 0%; }
-
-.emojione-1f47c {
- background-position: 71.42857% 2.38095%; }
-
-.emojione-1f47d {
- background-position: 71.42857% 4.7619%; }
-
-.emojione-1f47e {
- background-position: 71.42857% 7.14286%; }
-
-.emojione-1f47f {
- background-position: 71.42857% 9.52381%; }
-
-.emojione-1f480 {
- background-position: 71.42857% 11.90476%; }
-
-.emojione-1f481-1f3fb {
- background-position: 71.42857% 14.28571%; }
-
-.emojione-1f481-1f3fc {
- background-position: 71.42857% 16.66667%; }
-
-.emojione-1f481-1f3fd {
- background-position: 71.42857% 19.04762%; }
-
-.emojione-1f481-1f3fe {
- background-position: 71.42857% 21.42857%; }
-
-.emojione-1f481-1f3ff {
- background-position: 71.42857% 23.80952%; }
-
-.emojione-1f481 {
- background-position: 71.42857% 26.19048%; }
-
-.emojione-1f482-1f3fb {
- background-position: 71.42857% 28.57143%; }
-
-.emojione-1f482-1f3fc {
- background-position: 71.42857% 30.95238%; }
-
-.emojione-1f482-1f3fd {
- background-position: 71.42857% 33.33333%; }
-
-.emojione-1f482-1f3fe {
- background-position: 71.42857% 35.71429%; }
-
-.emojione-1f482-1f3ff {
- background-position: 71.42857% 38.09524%; }
-
-.emojione-1f482 {
- background-position: 71.42857% 40.47619%; }
-
-.emojione-1f483-1f3fb {
- background-position: 71.42857% 42.85714%; }
-
-.emojione-1f483-1f3fc {
- background-position: 71.42857% 45.2381%; }
-
-.emojione-1f483-1f3fd {
- background-position: 71.42857% 47.61905%; }
-
-.emojione-1f483-1f3fe {
- background-position: 71.42857% 50%; }
-
-.emojione-1f483-1f3ff {
- background-position: 71.42857% 52.38095%; }
-
-.emojione-1f483 {
- background-position: 71.42857% 54.7619%; }
-
-.emojione-1f484 {
- background-position: 71.42857% 57.14286%; }
-
-.emojione-1f485-1f3fb {
- background-position: 71.42857% 59.52381%; }
-
-.emojione-1f485-1f3fc {
- background-position: 71.42857% 61.90476%; }
-
-.emojione-1f485-1f3fd {
- background-position: 71.42857% 64.28571%; }
-
-.emojione-1f485-1f3fe {
- background-position: 71.42857% 66.66667%; }
-
-.emojione-1f485-1f3ff {
- background-position: 71.42857% 69.04762%; }
-
-.emojione-1f485 {
- background-position: 0% 71.42857%; }
-
-.emojione-1f486-1f3fb {
- background-position: 2.38095% 71.42857%; }
-
-.emojione-1f486-1f3fc {
- background-position: 4.7619% 71.42857%; }
-
-.emojione-1f486-1f3fd {
- background-position: 7.14286% 71.42857%; }
-
-.emojione-1f486-1f3fe {
- background-position: 9.52381% 71.42857%; }
-
-.emojione-1f486-1f3ff {
- background-position: 11.90476% 71.42857%; }
-
-.emojione-1f486 {
- background-position: 14.28571% 71.42857%; }
-
-.emojione-1f487-1f3fb {
- background-position: 16.66667% 71.42857%; }
-
-.emojione-1f487-1f3fc {
- background-position: 19.04762% 71.42857%; }
-
-.emojione-1f487-1f3fd {
- background-position: 21.42857% 71.42857%; }
-
-.emojione-1f487-1f3fe {
- background-position: 23.80952% 71.42857%; }
-
-.emojione-1f487-1f3ff {
- background-position: 26.19048% 71.42857%; }
-
-.emojione-1f487 {
- background-position: 28.57143% 71.42857%; }
-
-.emojione-1f488 {
- background-position: 30.95238% 71.42857%; }
-
-.emojione-1f489 {
- background-position: 33.33333% 71.42857%; }
-
-.emojione-1f48a {
- background-position: 35.71429% 71.42857%; }
-
-.emojione-1f48b {
- background-position: 38.09524% 71.42857%; }
-
-.emojione-1f48c {
- background-position: 40.47619% 71.42857%; }
-
-.emojione-1f48d {
- background-position: 42.85714% 71.42857%; }
-
-.emojione-1f48e {
- background-position: 45.2381% 71.42857%; }
-
-.emojione-1f48f {
- background-position: 47.61905% 71.42857%; }
-
-.emojione-1f490 {
- background-position: 50% 71.42857%; }
-
-.emojione-1f491 {
- background-position: 52.38095% 71.42857%; }
-
-.emojione-1f492 {
- background-position: 54.7619% 71.42857%; }
-
-.emojione-1f493 {
- background-position: 57.14286% 71.42857%; }
-
-.emojione-1f494 {
- background-position: 59.52381% 71.42857%; }
-
-.emojione-1f495 {
- background-position: 61.90476% 71.42857%; }
-
-.emojione-1f496 {
- background-position: 64.28571% 71.42857%; }
-
-.emojione-1f497 {
- background-position: 66.66667% 71.42857%; }
-
-.emojione-1f498 {
- background-position: 69.04762% 71.42857%; }
-
-.emojione-1f499 {
- background-position: 71.42857% 71.42857%; }
-
-.emojione-1f49a {
- background-position: 73.80952% 0%; }
-
-.emojione-1f49b {
- background-position: 73.80952% 2.38095%; }
-
-.emojione-1f49c {
- background-position: 73.80952% 4.7619%; }
-
-.emojione-1f49d {
- background-position: 73.80952% 7.14286%; }
-
-.emojione-1f49e {
- background-position: 73.80952% 9.52381%; }
-
-.emojione-1f49f {
- background-position: 73.80952% 11.90476%; }
-
-.emojione-1f4a0 {
- background-position: 73.80952% 14.28571%; }
-
-.emojione-1f4a1 {
- background-position: 73.80952% 16.66667%; }
-
-.emojione-1f4a2 {
- background-position: 73.80952% 19.04762%; }
-
-.emojione-1f4a3 {
- background-position: 73.80952% 21.42857%; }
-
-.emojione-1f4a4 {
- background-position: 73.80952% 23.80952%; }
-
-.emojione-1f4a5 {
- background-position: 73.80952% 26.19048%; }
-
-.emojione-1f4a6 {
- background-position: 73.80952% 28.57143%; }
-
-.emojione-1f4a7 {
- background-position: 73.80952% 30.95238%; }
-
-.emojione-1f4a8 {
- background-position: 73.80952% 33.33333%; }
-
-.emojione-1f4a9 {
- background-position: 73.80952% 35.71429%; }
-
-.emojione-1f4aa-1f3fb {
- background-position: 73.80952% 38.09524%; }
-
-.emojione-1f4aa-1f3fc {
- background-position: 73.80952% 40.47619%; }
-
-.emojione-1f4aa-1f3fd {
- background-position: 73.80952% 42.85714%; }
-
-.emojione-1f4aa-1f3fe {
- background-position: 73.80952% 45.2381%; }
-
-.emojione-1f4aa-1f3ff {
- background-position: 73.80952% 47.61905%; }
-
-.emojione-1f4aa {
- background-position: 73.80952% 50%; }
-
-.emojione-1f4ab {
- background-position: 73.80952% 52.38095%; }
-
-.emojione-1f4ac {
- background-position: 73.80952% 54.7619%; }
-
-.emojione-1f4ad {
- background-position: 73.80952% 57.14286%; }
-
-.emojione-1f4ae {
- background-position: 73.80952% 59.52381%; }
-
-.emojione-1f4af {
- background-position: 73.80952% 61.90476%; }
-
-.emojione-1f4b0 {
- background-position: 73.80952% 64.28571%; }
-
-.emojione-1f4b1 {
- background-position: 73.80952% 66.66667%; }
-
-.emojione-1f4b2 {
- background-position: 73.80952% 69.04762%; }
-
-.emojione-1f4b3 {
- background-position: 73.80952% 71.42857%; }
-
-.emojione-1f4b4 {
- background-position: 0% 73.80952%; }
-
-.emojione-1f4b5 {
- background-position: 2.38095% 73.80952%; }
-
-.emojione-1f4b6 {
- background-position: 4.7619% 73.80952%; }
-
-.emojione-1f4b7 {
- background-position: 7.14286% 73.80952%; }
-
-.emojione-1f4b8 {
- background-position: 9.52381% 73.80952%; }
-
-.emojione-1f4b9 {
- background-position: 11.90476% 73.80952%; }
-
-.emojione-1f4ba {
- background-position: 14.28571% 73.80952%; }
-
-.emojione-1f4bb {
- background-position: 16.66667% 73.80952%; }
-
-.emojione-1f4bc {
- background-position: 19.04762% 73.80952%; }
-
-.emojione-1f4bd {
- background-position: 21.42857% 73.80952%; }
-
-.emojione-1f4be {
- background-position: 23.80952% 73.80952%; }
-
-.emojione-1f4bf {
- background-position: 26.19048% 73.80952%; }
-
-.emojione-1f4c0 {
- background-position: 28.57143% 73.80952%; }
-
-.emojione-1f4c1 {
- background-position: 30.95238% 73.80952%; }
-
-.emojione-1f4c2 {
- background-position: 33.33333% 73.80952%; }
-
-.emojione-1f4c3 {
- background-position: 35.71429% 73.80952%; }
-
-.emojione-1f4c4 {
- background-position: 38.09524% 73.80952%; }
-
-.emojione-1f4c5 {
- background-position: 40.47619% 73.80952%; }
-
-.emojione-1f4c6 {
- background-position: 42.85714% 73.80952%; }
-
-.emojione-1f4c7 {
- background-position: 45.2381% 73.80952%; }
-
-.emojione-1f4c8 {
- background-position: 47.61905% 73.80952%; }
-
-.emojione-1f4c9 {
- background-position: 50% 73.80952%; }
-
-.emojione-1f4ca {
- background-position: 52.38095% 73.80952%; }
-
-.emojione-1f4cb {
- background-position: 54.7619% 73.80952%; }
-
-.emojione-1f4cc {
- background-position: 57.14286% 73.80952%; }
-
-.emojione-1f4cd {
- background-position: 59.52381% 73.80952%; }
-
-.emojione-1f4ce {
- background-position: 61.90476% 73.80952%; }
-
-.emojione-1f4cf {
- background-position: 64.28571% 73.80952%; }
-
-.emojione-1f4d0 {
- background-position: 66.66667% 73.80952%; }
-
-.emojione-1f4d1 {
- background-position: 69.04762% 73.80952%; }
-
-.emojione-1f4d2 {
- background-position: 71.42857% 73.80952%; }
-
-.emojione-1f4d3 {
- background-position: 73.80952% 73.80952%; }
-
-.emojione-1f4d4 {
- background-position: 76.19048% 0%; }
-
-.emojione-1f4d5 {
- background-position: 76.19048% 2.38095%; }
-
-.emojione-1f4d6 {
- background-position: 76.19048% 4.7619%; }
-
-.emojione-1f4d7 {
- background-position: 76.19048% 7.14286%; }
-
-.emojione-1f4d8 {
- background-position: 76.19048% 9.52381%; }
-
-.emojione-1f4d9 {
- background-position: 76.19048% 11.90476%; }
-
-.emojione-1f4da {
- background-position: 76.19048% 14.28571%; }
-
-.emojione-1f4db {
- background-position: 76.19048% 16.66667%; }
-
-.emojione-1f4dc {
- background-position: 76.19048% 19.04762%; }
-
-.emojione-1f4dd {
- background-position: 76.19048% 21.42857%; }
-
-.emojione-1f4de {
- background-position: 76.19048% 23.80952%; }
-
-.emojione-1f4df {
- background-position: 76.19048% 26.19048%; }
-
-.emojione-1f4e0 {
- background-position: 76.19048% 28.57143%; }
-
-.emojione-1f4e1 {
- background-position: 76.19048% 30.95238%; }
-
-.emojione-1f4e2 {
- background-position: 76.19048% 33.33333%; }
-
-.emojione-1f4e3 {
- background-position: 76.19048% 35.71429%; }
-
-.emojione-1f4e4 {
- background-position: 76.19048% 38.09524%; }
-
-.emojione-1f4e5 {
- background-position: 76.19048% 40.47619%; }
-
-.emojione-1f4e6 {
- background-position: 76.19048% 42.85714%; }
-
-.emojione-1f4e7 {
- background-position: 76.19048% 45.2381%; }
-
-.emojione-1f4e8 {
- background-position: 76.19048% 47.61905%; }
-
-.emojione-1f4e9 {
- background-position: 76.19048% 50%; }
-
-.emojione-1f4ea {
- background-position: 76.19048% 52.38095%; }
-
-.emojione-1f4eb {
- background-position: 76.19048% 54.7619%; }
-
-.emojione-1f4ec {
- background-position: 76.19048% 57.14286%; }
-
-.emojione-1f4ed {
- background-position: 76.19048% 59.52381%; }
-
-.emojione-1f4ee {
- background-position: 76.19048% 61.90476%; }
-
-.emojione-1f4ef {
- background-position: 76.19048% 64.28571%; }
-
-.emojione-1f4f0 {
- background-position: 76.19048% 66.66667%; }
-
-.emojione-1f4f1 {
- background-position: 76.19048% 69.04762%; }
-
-.emojione-1f4f2 {
- background-position: 76.19048% 71.42857%; }
-
-.emojione-1f4f3 {
- background-position: 76.19048% 73.80952%; }
-
-.emojione-1f4f4 {
- background-position: 0% 76.19048%; }
-
-.emojione-1f4f5 {
- background-position: 2.38095% 76.19048%; }
-
-.emojione-1f4f6 {
- background-position: 4.7619% 76.19048%; }
-
-.emojione-1f4f7 {
- background-position: 7.14286% 76.19048%; }
-
-.emojione-1f4f8 {
- background-position: 9.52381% 76.19048%; }
-
-.emojione-1f4f9 {
- background-position: 11.90476% 76.19048%; }
-
-.emojione-1f4fa {
- background-position: 14.28571% 76.19048%; }
-
-.emojione-1f4fb {
- background-position: 16.66667% 76.19048%; }
-
-.emojione-1f4fc {
- background-position: 19.04762% 76.19048%; }
-
-.emojione-1f4fd {
- background-position: 21.42857% 76.19048%; }
-
-.emojione-1f4ff {
- background-position: 23.80952% 76.19048%; }
-
-.emojione-1f500 {
- background-position: 26.19048% 76.19048%; }
-
-.emojione-1f501 {
- background-position: 28.57143% 76.19048%; }
-
-.emojione-1f502 {
- background-position: 30.95238% 76.19048%; }
-
-.emojione-1f503 {
- background-position: 33.33333% 76.19048%; }
-
-.emojione-1f504 {
- background-position: 35.71429% 76.19048%; }
-
-.emojione-1f505 {
- background-position: 38.09524% 76.19048%; }
-
-.emojione-1f506 {
- background-position: 40.47619% 76.19048%; }
-
-.emojione-1f507 {
- background-position: 42.85714% 76.19048%; }
-
-.emojione-1f508 {
- background-position: 45.2381% 76.19048%; }
-
-.emojione-1f509 {
- background-position: 47.61905% 76.19048%; }
-
-.emojione-1f50a {
- background-position: 50% 76.19048%; }
-
-.emojione-1f50b {
- background-position: 52.38095% 76.19048%; }
-
-.emojione-1f50c {
- background-position: 54.7619% 76.19048%; }
-
-.emojione-1f50d {
- background-position: 57.14286% 76.19048%; }
-
-.emojione-1f50e {
- background-position: 59.52381% 76.19048%; }
-
-.emojione-1f50f {
- background-position: 61.90476% 76.19048%; }
-
-.emojione-1f510 {
- background-position: 64.28571% 76.19048%; }
-
-.emojione-1f511 {
- background-position: 66.66667% 76.19048%; }
-
-.emojione-1f512 {
- background-position: 69.04762% 76.19048%; }
-
-.emojione-1f513 {
- background-position: 71.42857% 76.19048%; }
-
-.emojione-1f514 {
- background-position: 73.80952% 76.19048%; }
-
-.emojione-1f515 {
- background-position: 76.19048% 76.19048%; }
-
-.emojione-1f516 {
- background-position: 78.57143% 0%; }
-
-.emojione-1f517 {
- background-position: 78.57143% 2.38095%; }
-
-.emojione-1f518 {
- background-position: 78.57143% 4.7619%; }
-
-.emojione-1f519 {
- background-position: 78.57143% 7.14286%; }
-
-.emojione-1f51a {
- background-position: 78.57143% 9.52381%; }
-
-.emojione-1f51b {
- background-position: 78.57143% 11.90476%; }
-
-.emojione-1f51c {
- background-position: 78.57143% 14.28571%; }
-
-.emojione-1f51d {
- background-position: 78.57143% 16.66667%; }
-
-.emojione-1f51e {
- background-position: 78.57143% 19.04762%; }
-
-.emojione-1f51f {
- background-position: 78.57143% 21.42857%; }
-
-.emojione-1f520 {
- background-position: 78.57143% 23.80952%; }
-
-.emojione-1f521 {
- background-position: 78.57143% 26.19048%; }
-
-.emojione-1f522 {
- background-position: 78.57143% 28.57143%; }
-
-.emojione-1f523 {
- background-position: 78.57143% 30.95238%; }
-
-.emojione-1f524 {
- background-position: 78.57143% 33.33333%; }
-
-.emojione-1f525 {
- background-position: 78.57143% 35.71429%; }
-
-.emojione-1f526 {
- background-position: 78.57143% 38.09524%; }
-
-.emojione-1f527 {
- background-position: 78.57143% 40.47619%; }
-
-.emojione-1f528 {
- background-position: 78.57143% 42.85714%; }
-
-.emojione-1f529 {
- background-position: 78.57143% 45.2381%; }
-
-.emojione-1f52a {
- background-position: 78.57143% 47.61905%; }
-
-.emojione-1f52b {
- background-position: 78.57143% 50%; }
-
-.emojione-1f52c {
- background-position: 78.57143% 52.38095%; }
-
-.emojione-1f52d {
- background-position: 78.57143% 54.7619%; }
-
-.emojione-1f52e {
- background-position: 78.57143% 57.14286%; }
-
-.emojione-1f52f {
- background-position: 78.57143% 59.52381%; }
-
-.emojione-1f530 {
- background-position: 78.57143% 61.90476%; }
-
-.emojione-1f531 {
- background-position: 78.57143% 64.28571%; }
-
-.emojione-1f532 {
- background-position: 78.57143% 66.66667%; }
-
-.emojione-1f533 {
- background-position: 78.57143% 69.04762%; }
-
-.emojione-1f534 {
- background-position: 78.57143% 71.42857%; }
-
-.emojione-1f535 {
- background-position: 78.57143% 73.80952%; }
-
-.emojione-1f536 {
- background-position: 78.57143% 76.19048%; }
-
-.emojione-1f537 {
- background-position: 0% 78.57143%; }
-
-.emojione-1f538 {
- background-position: 2.38095% 78.57143%; }
-
-.emojione-1f539 {
- background-position: 4.7619% 78.57143%; }
-
-.emojione-1f53a {
- background-position: 7.14286% 78.57143%; }
-
-.emojione-1f53b {
- background-position: 9.52381% 78.57143%; }
-
-.emojione-1f53c {
- background-position: 11.90476% 78.57143%; }
-
-.emojione-1f53d {
- background-position: 14.28571% 78.57143%; }
-
-.emojione-1f549 {
- background-position: 16.66667% 78.57143%; }
-
-.emojione-1f54a {
- background-position: 19.04762% 78.57143%; }
-
-.emojione-1f54b {
- background-position: 21.42857% 78.57143%; }
-
-.emojione-1f54c {
- background-position: 23.80952% 78.57143%; }
-
-.emojione-1f54d {
- background-position: 26.19048% 78.57143%; }
-
-.emojione-1f54e {
- background-position: 28.57143% 78.57143%; }
-
-.emojione-1f550 {
- background-position: 30.95238% 78.57143%; }
-
-.emojione-1f551 {
- background-position: 33.33333% 78.57143%; }
-
-.emojione-1f552 {
- background-position: 35.71429% 78.57143%; }
-
-.emojione-1f553 {
- background-position: 38.09524% 78.57143%; }
-
-.emojione-1f554 {
- background-position: 40.47619% 78.57143%; }
-
-.emojione-1f555 {
- background-position: 42.85714% 78.57143%; }
-
-.emojione-1f556 {
- background-position: 45.2381% 78.57143%; }
-
-.emojione-1f557 {
- background-position: 47.61905% 78.57143%; }
-
-.emojione-1f558 {
- background-position: 50% 78.57143%; }
-
-.emojione-1f559 {
- background-position: 52.38095% 78.57143%; }
-
-.emojione-1f55a {
- background-position: 54.7619% 78.57143%; }
-
-.emojione-1f55b {
- background-position: 57.14286% 78.57143%; }
-
-.emojione-1f55c {
- background-position: 59.52381% 78.57143%; }
-
-.emojione-1f55d {
- background-position: 61.90476% 78.57143%; }
-
-.emojione-1f55e {
- background-position: 64.28571% 78.57143%; }
-
-.emojione-1f55f {
- background-position: 66.66667% 78.57143%; }
-
-.emojione-1f560 {
- background-position: 69.04762% 78.57143%; }
-
-.emojione-1f561 {
- background-position: 71.42857% 78.57143%; }
-
-.emojione-1f562 {
- background-position: 73.80952% 78.57143%; }
-
-.emojione-1f563 {
- background-position: 76.19048% 78.57143%; }
-
-.emojione-1f564 {
- background-position: 78.57143% 78.57143%; }
-
-.emojione-1f565 {
- background-position: 80.95238% 0%; }
-
-.emojione-1f566 {
- background-position: 80.95238% 2.38095%; }
-
-.emojione-1f567 {
- background-position: 80.95238% 4.7619%; }
-
-.emojione-1f56f {
- background-position: 80.95238% 7.14286%; }
-
-.emojione-1f570 {
- background-position: 80.95238% 9.52381%; }
-
-.emojione-1f573 {
- background-position: 80.95238% 11.90476%; }
-
-.emojione-1f574 {
- background-position: 80.95238% 14.28571%; }
-
-.emojione-1f575-1f3fb {
- background-position: 80.95238% 16.66667%; }
-
-.emojione-1f575-1f3fc {
- background-position: 80.95238% 19.04762%; }
-
-.emojione-1f575-1f3fd {
- background-position: 80.95238% 21.42857%; }
-
-.emojione-1f575-1f3fe {
- background-position: 80.95238% 23.80952%; }
-
-.emojione-1f575-1f3ff {
- background-position: 80.95238% 26.19048%; }
-
-.emojione-1f575 {
- background-position: 80.95238% 28.57143%; }
-
-.emojione-1f576 {
- background-position: 80.95238% 30.95238%; }
-
-.emojione-1f577 {
- background-position: 80.95238% 33.33333%; }
-
-.emojione-1f578 {
- background-position: 80.95238% 35.71429%; }
-
-.emojione-1f579 {
- background-position: 80.95238% 38.09524%; }
-
-.emojione-1f57a-1f3fb {
- background-position: 80.95238% 40.47619%; }
-
-.emojione-1f57a-1f3fc {
- background-position: 80.95238% 42.85714%; }
-
-.emojione-1f57a-1f3fd {
- background-position: 80.95238% 45.2381%; }
-
-.emojione-1f57a-1f3fe {
- background-position: 80.95238% 47.61905%; }
-
-.emojione-1f57a-1f3ff {
- background-position: 80.95238% 50%; }
-
-.emojione-1f57a {
- background-position: 80.95238% 52.38095%; }
-
-.emojione-1f587 {
- background-position: 80.95238% 54.7619%; }
-
-.emojione-1f58a {
- background-position: 80.95238% 57.14286%; }
-
-.emojione-1f58b {
- background-position: 80.95238% 59.52381%; }
-
-.emojione-1f58c {
- background-position: 80.95238% 61.90476%; }
-
-.emojione-1f58d {
- background-position: 80.95238% 64.28571%; }
-
-.emojione-1f590-1f3fb {
- background-position: 80.95238% 66.66667%; }
-
-.emojione-1f590-1f3fc {
- background-position: 80.95238% 69.04762%; }
-
-.emojione-1f590-1f3fd {
- background-position: 80.95238% 71.42857%; }
-
-.emojione-1f590-1f3fe {
- background-position: 80.95238% 73.80952%; }
-
-.emojione-1f590-1f3ff {
- background-position: 80.95238% 76.19048%; }
-
-.emojione-1f590 {
- background-position: 80.95238% 78.57143%; }
-
-.emojione-1f595-1f3fb {
- background-position: 0% 80.95238%; }
-
-.emojione-1f595-1f3fc {
- background-position: 2.38095% 80.95238%; }
-
-.emojione-1f595-1f3fd {
- background-position: 4.7619% 80.95238%; }
-
-.emojione-1f595-1f3fe {
- background-position: 7.14286% 80.95238%; }
-
-.emojione-1f595-1f3ff {
- background-position: 9.52381% 80.95238%; }
-
-.emojione-1f595 {
- background-position: 11.90476% 80.95238%; }
-
-.emojione-1f596-1f3fb {
- background-position: 14.28571% 80.95238%; }
-
-.emojione-1f596-1f3fc {
- background-position: 16.66667% 80.95238%; }
-
-.emojione-1f596-1f3fd {
- background-position: 19.04762% 80.95238%; }
-
-.emojione-1f596-1f3fe {
- background-position: 21.42857% 80.95238%; }
-
-.emojione-1f596-1f3ff {
- background-position: 23.80952% 80.95238%; }
-
-.emojione-1f596 {
- background-position: 26.19048% 80.95238%; }
-
-.emojione-1f5a4 {
- background-position: 28.57143% 80.95238%; }
-
-.emojione-1f5a5 {
- background-position: 30.95238% 80.95238%; }
-
-.emojione-1f5a8 {
- background-position: 33.33333% 80.95238%; }
-
-.emojione-1f5b1 {
- background-position: 35.71429% 80.95238%; }
-
-.emojione-1f5b2 {
- background-position: 38.09524% 80.95238%; }
-
-.emojione-1f5bc {
- background-position: 40.47619% 80.95238%; }
-
-.emojione-1f5c2 {
- background-position: 42.85714% 80.95238%; }
-
-.emojione-1f5c3 {
- background-position: 45.2381% 80.95238%; }
-
-.emojione-1f5c4 {
- background-position: 47.61905% 80.95238%; }
-
-.emojione-1f5d1 {
- background-position: 50% 80.95238%; }
-
-.emojione-1f5d2 {
- background-position: 52.38095% 80.95238%; }
-
-.emojione-1f5d3 {
- background-position: 54.7619% 80.95238%; }
-
-.emojione-1f5dc {
- background-position: 57.14286% 80.95238%; }
-
-.emojione-1f5dd {
- background-position: 59.52381% 80.95238%; }
-
-.emojione-1f5de {
- background-position: 61.90476% 80.95238%; }
-
-.emojione-1f5e1 {
- background-position: 64.28571% 80.95238%; }
-
-.emojione-1f5e3 {
- background-position: 66.66667% 80.95238%; }
-
-.emojione-1f5e8 {
- background-position: 69.04762% 80.95238%; }
-
-.emojione-1f5ef {
- background-position: 71.42857% 80.95238%; }
-
-.emojione-1f5f3 {
- background-position: 73.80952% 80.95238%; }
-
-.emojione-1f5fa {
- background-position: 76.19048% 80.95238%; }
-
-.emojione-1f5fb {
- background-position: 78.57143% 80.95238%; }
-
-.emojione-1f5fc {
- background-position: 80.95238% 80.95238%; }
-
-.emojione-1f5fd {
- background-position: 83.33333% 0%; }
-
-.emojione-1f5fe {
- background-position: 83.33333% 2.38095%; }
-
-.emojione-1f5ff {
- background-position: 83.33333% 4.7619%; }
-
-.emojione-1f600 {
- background-position: 83.33333% 7.14286%; }
-
-.emojione-1f601 {
- background-position: 83.33333% 9.52381%; }
-
-.emojione-1f602 {
- background-position: 83.33333% 11.90476%; }
-
-.emojione-1f603 {
- background-position: 83.33333% 14.28571%; }
-
-.emojione-1f604 {
- background-position: 83.33333% 16.66667%; }
-
-.emojione-1f605 {
- background-position: 83.33333% 19.04762%; }
-
-.emojione-1f606 {
- background-position: 83.33333% 21.42857%; }
-
-.emojione-1f607 {
- background-position: 83.33333% 23.80952%; }
-
-.emojione-1f608 {
- background-position: 83.33333% 26.19048%; }
-
-.emojione-1f609 {
- background-position: 83.33333% 28.57143%; }
-
-.emojione-1f60a {
- background-position: 83.33333% 30.95238%; }
-
-.emojione-1f60b {
- background-position: 83.33333% 33.33333%; }
-
-.emojione-1f60c {
- background-position: 83.33333% 35.71429%; }
-
-.emojione-1f60d {
- background-position: 83.33333% 38.09524%; }
-
-.emojione-1f60e {
- background-position: 83.33333% 40.47619%; }
-
-.emojione-1f60f {
- background-position: 83.33333% 42.85714%; }
-
-.emojione-1f610 {
- background-position: 83.33333% 45.2381%; }
-
-.emojione-1f611 {
- background-position: 83.33333% 47.61905%; }
-
-.emojione-1f612 {
- background-position: 83.33333% 50%; }
-
-.emojione-1f613 {
- background-position: 83.33333% 52.38095%; }
-
-.emojione-1f614 {
- background-position: 83.33333% 54.7619%; }
-
-.emojione-1f615 {
- background-position: 83.33333% 57.14286%; }
-
-.emojione-1f616 {
- background-position: 83.33333% 59.52381%; }
-
-.emojione-1f617 {
- background-position: 83.33333% 61.90476%; }
-
-.emojione-1f618 {
- background-position: 83.33333% 64.28571%; }
-
-.emojione-1f619 {
- background-position: 83.33333% 66.66667%; }
-
-.emojione-1f61a {
- background-position: 83.33333% 69.04762%; }
-
-.emojione-1f61b {
- background-position: 83.33333% 71.42857%; }
-
-.emojione-1f61c {
- background-position: 83.33333% 73.80952%; }
-
-.emojione-1f61d {
- background-position: 83.33333% 76.19048%; }
-
-.emojione-1f61e {
- background-position: 83.33333% 78.57143%; }
-
-.emojione-1f61f {
- background-position: 83.33333% 80.95238%; }
-
-.emojione-1f620 {
- background-position: 0% 83.33333%; }
-
-.emojione-1f621 {
- background-position: 2.38095% 83.33333%; }
-
-.emojione-1f622 {
- background-position: 4.7619% 83.33333%; }
-
-.emojione-1f623 {
- background-position: 7.14286% 83.33333%; }
-
-.emojione-1f624 {
- background-position: 9.52381% 83.33333%; }
-
-.emojione-1f625 {
- background-position: 11.90476% 83.33333%; }
-
-.emojione-1f626 {
- background-position: 14.28571% 83.33333%; }
-
-.emojione-1f627 {
- background-position: 16.66667% 83.33333%; }
-
-.emojione-1f628 {
- background-position: 19.04762% 83.33333%; }
-
-.emojione-1f629 {
- background-position: 21.42857% 83.33333%; }
-
-.emojione-1f62a {
- background-position: 23.80952% 83.33333%; }
-
-.emojione-1f62b {
- background-position: 26.19048% 83.33333%; }
-
-.emojione-1f62c {
- background-position: 28.57143% 83.33333%; }
-
-.emojione-1f62d {
- background-position: 30.95238% 83.33333%; }
-
-.emojione-1f62e {
- background-position: 33.33333% 83.33333%; }
-
-.emojione-1f62f {
- background-position: 35.71429% 83.33333%; }
-
-.emojione-1f630 {
- background-position: 38.09524% 83.33333%; }
-
-.emojione-1f631 {
- background-position: 40.47619% 83.33333%; }
-
-.emojione-1f632 {
- background-position: 42.85714% 83.33333%; }
-
-.emojione-1f633 {
- background-position: 45.2381% 83.33333%; }
-
-.emojione-1f634 {
- background-position: 47.61905% 83.33333%; }
-
-.emojione-1f635 {
- background-position: 50% 83.33333%; }
-
-.emojione-1f636 {
- background-position: 52.38095% 83.33333%; }
-
-.emojione-1f637 {
- background-position: 54.7619% 83.33333%; }
-
-.emojione-1f638 {
- background-position: 57.14286% 83.33333%; }
-
-.emojione-1f639 {
- background-position: 59.52381% 83.33333%; }
-
-.emojione-1f63a {
- background-position: 61.90476% 83.33333%; }
-
-.emojione-1f63b {
- background-position: 64.28571% 83.33333%; }
-
-.emojione-1f63c {
- background-position: 66.66667% 83.33333%; }
-
-.emojione-1f63d {
- background-position: 69.04762% 83.33333%; }
-
-.emojione-1f63e {
- background-position: 71.42857% 83.33333%; }
-
-.emojione-1f63f {
- background-position: 73.80952% 83.33333%; }
-
-.emojione-1f640 {
- background-position: 76.19048% 83.33333%; }
-
-.emojione-1f641 {
- background-position: 78.57143% 83.33333%; }
-
-.emojione-1f642 {
- background-position: 80.95238% 83.33333%; }
-
-.emojione-1f643 {
- background-position: 83.33333% 83.33333%; }
-
-.emojione-1f644 {
- background-position: 85.71429% 0%; }
-
-.emojione-1f645-1f3fb {
- background-position: 85.71429% 2.38095%; }
-
-.emojione-1f645-1f3fc {
- background-position: 85.71429% 4.7619%; }
-
-.emojione-1f645-1f3fd {
- background-position: 85.71429% 7.14286%; }
-
-.emojione-1f645-1f3fe {
- background-position: 85.71429% 9.52381%; }
-
-.emojione-1f645-1f3ff {
- background-position: 85.71429% 11.90476%; }
-
-.emojione-1f645 {
- background-position: 85.71429% 14.28571%; }
-
-.emojione-1f646-1f3fb {
- background-position: 85.71429% 16.66667%; }
-
-.emojione-1f646-1f3fc {
- background-position: 85.71429% 19.04762%; }
-
-.emojione-1f646-1f3fd {
- background-position: 85.71429% 21.42857%; }
-
-.emojione-1f646-1f3fe {
- background-position: 85.71429% 23.80952%; }
-
-.emojione-1f646-1f3ff {
- background-position: 85.71429% 26.19048%; }
-
-.emojione-1f646 {
- background-position: 85.71429% 28.57143%; }
-
-.emojione-1f647-1f3fb {
- background-position: 85.71429% 30.95238%; }
-
-.emojione-1f647-1f3fc {
- background-position: 85.71429% 33.33333%; }
-
-.emojione-1f647-1f3fd {
- background-position: 85.71429% 35.71429%; }
-
-.emojione-1f647-1f3fe {
- background-position: 85.71429% 38.09524%; }
-
-.emojione-1f647-1f3ff {
- background-position: 85.71429% 40.47619%; }
-
-.emojione-1f647 {
- background-position: 85.71429% 42.85714%; }
-
-.emojione-1f648 {
- background-position: 85.71429% 45.2381%; }
-
-.emojione-1f649 {
- background-position: 85.71429% 47.61905%; }
-
-.emojione-1f64a {
- background-position: 85.71429% 50%; }
-
-.emojione-1f64b-1f3fb {
- background-position: 85.71429% 52.38095%; }
-
-.emojione-1f64b-1f3fc {
- background-position: 85.71429% 54.7619%; }
-
-.emojione-1f64b-1f3fd {
- background-position: 85.71429% 57.14286%; }
-
-.emojione-1f64b-1f3fe {
- background-position: 85.71429% 59.52381%; }
-
-.emojione-1f64b-1f3ff {
- background-position: 85.71429% 61.90476%; }
-
-.emojione-1f64b {
- background-position: 85.71429% 64.28571%; }
-
-.emojione-1f64c-1f3fb {
- background-position: 85.71429% 66.66667%; }
-
-.emojione-1f64c-1f3fc {
- background-position: 85.71429% 69.04762%; }
-
-.emojione-1f64c-1f3fd {
- background-position: 85.71429% 71.42857%; }
-
-.emojione-1f64c-1f3fe {
- background-position: 85.71429% 73.80952%; }
-
-.emojione-1f64c-1f3ff {
- background-position: 85.71429% 76.19048%; }
-
-.emojione-1f64c {
- background-position: 85.71429% 78.57143%; }
-
-.emojione-1f64d-1f3fb {
- background-position: 85.71429% 80.95238%; }
-
-.emojione-1f64d-1f3fc {
- background-position: 85.71429% 83.33333%; }
-
-.emojione-1f64d-1f3fd {
- background-position: 0% 85.71429%; }
-
-.emojione-1f64d-1f3fe {
- background-position: 2.38095% 85.71429%; }
-
-.emojione-1f64d-1f3ff {
- background-position: 4.7619% 85.71429%; }
-
-.emojione-1f64d {
- background-position: 7.14286% 85.71429%; }
-
-.emojione-1f64e-1f3fb {
- background-position: 9.52381% 85.71429%; }
-
-.emojione-1f64e-1f3fc {
- background-position: 11.90476% 85.71429%; }
-
-.emojione-1f64e-1f3fd {
- background-position: 14.28571% 85.71429%; }
-
-.emojione-1f64e-1f3fe {
- background-position: 16.66667% 85.71429%; }
-
-.emojione-1f64e-1f3ff {
- background-position: 19.04762% 85.71429%; }
-
-.emojione-1f64e {
- background-position: 21.42857% 85.71429%; }
-
-.emojione-1f64f-1f3fb {
- background-position: 23.80952% 85.71429%; }
-
-.emojione-1f64f-1f3fc {
- background-position: 26.19048% 85.71429%; }
-
-.emojione-1f64f-1f3fd {
- background-position: 28.57143% 85.71429%; }
-
-.emojione-1f64f-1f3fe {
- background-position: 30.95238% 85.71429%; }
-
-.emojione-1f64f-1f3ff {
- background-position: 33.33333% 85.71429%; }
-
-.emojione-1f64f {
- background-position: 35.71429% 85.71429%; }
-
-.emojione-1f680 {
- background-position: 38.09524% 85.71429%; }
-
-.emojione-1f681 {
- background-position: 40.47619% 85.71429%; }
-
-.emojione-1f682 {
- background-position: 42.85714% 85.71429%; }
-
-.emojione-1f683 {
- background-position: 45.2381% 85.71429%; }
-
-.emojione-1f684 {
- background-position: 47.61905% 85.71429%; }
-
-.emojione-1f685 {
- background-position: 50% 85.71429%; }
-
-.emojione-1f686 {
- background-position: 52.38095% 85.71429%; }
-
-.emojione-1f687 {
- background-position: 54.7619% 85.71429%; }
-
-.emojione-1f688 {
- background-position: 57.14286% 85.71429%; }
-
-.emojione-1f689 {
- background-position: 59.52381% 85.71429%; }
-
-.emojione-1f68a {
- background-position: 61.90476% 85.71429%; }
-
-.emojione-1f68b {
- background-position: 64.28571% 85.71429%; }
-
-.emojione-1f68c {
- background-position: 66.66667% 85.71429%; }
-
-.emojione-1f68d {
- background-position: 69.04762% 85.71429%; }
-
-.emojione-1f68e {
- background-position: 71.42857% 85.71429%; }
-
-.emojione-1f68f {
- background-position: 73.80952% 85.71429%; }
-
-.emojione-1f690 {
- background-position: 76.19048% 85.71429%; }
-
-.emojione-1f691 {
- background-position: 78.57143% 85.71429%; }
-
-.emojione-1f692 {
- background-position: 80.95238% 85.71429%; }
-
-.emojione-1f693 {
- background-position: 83.33333% 85.71429%; }
-
-.emojione-1f694 {
- background-position: 85.71429% 85.71429%; }
-
-.emojione-1f695 {
- background-position: 88.09524% 0%; }
-
-.emojione-1f696 {
- background-position: 88.09524% 2.38095%; }
-
-.emojione-1f697 {
- background-position: 88.09524% 4.7619%; }
-
-.emojione-1f698 {
- background-position: 88.09524% 7.14286%; }
-
-.emojione-1f699 {
- background-position: 88.09524% 9.52381%; }
-
-.emojione-1f69a {
- background-position: 88.09524% 11.90476%; }
-
-.emojione-1f69b {
- background-position: 88.09524% 14.28571%; }
-
-.emojione-1f69c {
- background-position: 88.09524% 16.66667%; }
-
-.emojione-1f69d {
- background-position: 88.09524% 19.04762%; }
-
-.emojione-1f69e {
- background-position: 88.09524% 21.42857%; }
-
-.emojione-1f69f {
- background-position: 88.09524% 23.80952%; }
-
-.emojione-1f6a0 {
- background-position: 88.09524% 26.19048%; }
-
-.emojione-1f6a1 {
- background-position: 88.09524% 28.57143%; }
-
-.emojione-1f6a2 {
- background-position: 88.09524% 30.95238%; }
-
-.emojione-1f6a3-1f3fb {
- background-position: 88.09524% 33.33333%; }
-
-.emojione-1f6a3-1f3fc {
- background-position: 88.09524% 35.71429%; }
-
-.emojione-1f6a3-1f3fd {
- background-position: 88.09524% 38.09524%; }
-
-.emojione-1f6a3-1f3fe {
- background-position: 88.09524% 40.47619%; }
-
-.emojione-1f6a3-1f3ff {
- background-position: 88.09524% 42.85714%; }
-
-.emojione-1f6a3 {
- background-position: 88.09524% 45.2381%; }
-
-.emojione-1f6a4 {
- background-position: 88.09524% 47.61905%; }
-
-.emojione-1f6a5 {
- background-position: 88.09524% 50%; }
-
-.emojione-1f6a6 {
- background-position: 88.09524% 52.38095%; }
-
-.emojione-1f6a7 {
- background-position: 88.09524% 54.7619%; }
-
-.emojione-1f6a8 {
- background-position: 88.09524% 57.14286%; }
-
-.emojione-1f6a9 {
- background-position: 88.09524% 59.52381%; }
-
-.emojione-1f6aa {
- background-position: 88.09524% 61.90476%; }
-
-.emojione-1f6ab {
- background-position: 88.09524% 64.28571%; }
-
-.emojione-1f6ac {
- background-position: 88.09524% 66.66667%; }
-
-.emojione-1f6ad {
- background-position: 88.09524% 69.04762%; }
-
-.emojione-1f6ae {
- background-position: 88.09524% 71.42857%; }
-
-.emojione-1f6af {
- background-position: 88.09524% 73.80952%; }
-
-.emojione-1f6b0 {
- background-position: 88.09524% 76.19048%; }
-
-.emojione-1f6b1 {
- background-position: 88.09524% 78.57143%; }
-
-.emojione-1f6b2 {
- background-position: 88.09524% 80.95238%; }
-
-.emojione-1f6b3 {
- background-position: 88.09524% 83.33333%; }
-
-.emojione-1f6b4-1f3fb {
- background-position: 88.09524% 85.71429%; }
-
-.emojione-1f6b4-1f3fc {
- background-position: 0% 88.09524%; }
-
-.emojione-1f6b4-1f3fd {
- background-position: 2.38095% 88.09524%; }
-
-.emojione-1f6b4-1f3fe {
- background-position: 4.7619% 88.09524%; }
-
-.emojione-1f6b4-1f3ff {
- background-position: 7.14286% 88.09524%; }
-
-.emojione-1f6b4 {
- background-position: 9.52381% 88.09524%; }
-
-.emojione-1f6b5-1f3fb {
- background-position: 11.90476% 88.09524%; }
-
-.emojione-1f6b5-1f3fc {
- background-position: 14.28571% 88.09524%; }
-
-.emojione-1f6b5-1f3fd {
- background-position: 16.66667% 88.09524%; }
-
-.emojione-1f6b5-1f3fe {
- background-position: 19.04762% 88.09524%; }
-
-.emojione-1f6b5-1f3ff {
- background-position: 21.42857% 88.09524%; }
-
-.emojione-1f6b5 {
- background-position: 23.80952% 88.09524%; }
-
-.emojione-1f6b6-1f3fb {
- background-position: 26.19048% 88.09524%; }
-
-.emojione-1f6b6-1f3fc {
- background-position: 28.57143% 88.09524%; }
-
-.emojione-1f6b6-1f3fd {
- background-position: 30.95238% 88.09524%; }
-
-.emojione-1f6b6-1f3fe {
- background-position: 33.33333% 88.09524%; }
-
-.emojione-1f6b6-1f3ff {
- background-position: 35.71429% 88.09524%; }
-
-.emojione-1f6b6 {
- background-position: 38.09524% 88.09524%; }
-
-.emojione-1f6b7 {
- background-position: 40.47619% 88.09524%; }
-
-.emojione-1f6b8 {
- background-position: 42.85714% 88.09524%; }
-
-.emojione-1f6b9 {
- background-position: 45.2381% 88.09524%; }
-
-.emojione-1f6ba {
- background-position: 47.61905% 88.09524%; }
-
-.emojione-1f6bb {
- background-position: 50% 88.09524%; }
-
-.emojione-1f6bc {
- background-position: 52.38095% 88.09524%; }
-
-.emojione-1f6bd {
- background-position: 54.7619% 88.09524%; }
-
-.emojione-1f6be {
- background-position: 57.14286% 88.09524%; }
-
-.emojione-1f6bf {
- background-position: 59.52381% 88.09524%; }
-
-.emojione-1f6c0-1f3fb {
- background-position: 61.90476% 88.09524%; }
-
-.emojione-1f6c0-1f3fc {
- background-position: 64.28571% 88.09524%; }
-
-.emojione-1f6c0-1f3fd {
- background-position: 66.66667% 88.09524%; }
-
-.emojione-1f6c0-1f3fe {
- background-position: 69.04762% 88.09524%; }
-
-.emojione-1f6c0-1f3ff {
- background-position: 71.42857% 88.09524%; }
-
-.emojione-1f6c0 {
- background-position: 73.80952% 88.09524%; }
-
-.emojione-1f6c1 {
- background-position: 76.19048% 88.09524%; }
-
-.emojione-1f6c2 {
- background-position: 78.57143% 88.09524%; }
-
-.emojione-1f6c3 {
- background-position: 80.95238% 88.09524%; }
-
-.emojione-1f6c4 {
- background-position: 83.33333% 88.09524%; }
-
-.emojione-1f6c5 {
- background-position: 85.71429% 88.09524%; }
-
-.emojione-1f6cb {
- background-position: 88.09524% 88.09524%; }
-
-.emojione-1f6cc {
- background-position: 90.47619% 0%; }
-
-.emojione-1f6cd {
- background-position: 90.47619% 2.38095%; }
-
-.emojione-1f6ce {
- background-position: 90.47619% 4.7619%; }
-
-.emojione-1f6cf {
- background-position: 90.47619% 7.14286%; }
-
-.emojione-1f6d0 {
- background-position: 90.47619% 9.52381%; }
-
-.emojione-1f6d1 {
- background-position: 90.47619% 11.90476%; }
-
-.emojione-1f6d2 {
- background-position: 90.47619% 14.28571%; }
-
-.emojione-1f6e0 {
- background-position: 90.47619% 16.66667%; }
-
-.emojione-1f6e1 {
- background-position: 90.47619% 19.04762%; }
-
-.emojione-1f6e2 {
- background-position: 90.47619% 21.42857%; }
-
-.emojione-1f6e3 {
- background-position: 90.47619% 23.80952%; }
-
-.emojione-1f6e4 {
- background-position: 90.47619% 26.19048%; }
-
-.emojione-1f6e5 {
- background-position: 90.47619% 28.57143%; }
-
-.emojione-1f6e9 {
- background-position: 90.47619% 30.95238%; }
-
-.emojione-1f6eb {
- background-position: 90.47619% 33.33333%; }
-
-.emojione-1f6ec {
- background-position: 90.47619% 35.71429%; }
-
-.emojione-1f6f0 {
- background-position: 90.47619% 38.09524%; }
-
-.emojione-1f6f3 {
- background-position: 90.47619% 40.47619%; }
-
-.emojione-1f6f4 {
- background-position: 90.47619% 42.85714%; }
-
-.emojione-1f6f5 {
- background-position: 90.47619% 45.2381%; }
-
-.emojione-1f6f6 {
- background-position: 90.47619% 47.61905%; }
-
-.emojione-1f910 {
- background-position: 90.47619% 50%; }
-
-.emojione-1f911 {
- background-position: 90.47619% 52.38095%; }
-
-.emojione-1f912 {
- background-position: 90.47619% 54.7619%; }
-
-.emojione-1f913 {
- background-position: 90.47619% 57.14286%; }
-
-.emojione-1f914 {
- background-position: 90.47619% 59.52381%; }
-
-.emojione-1f915 {
- background-position: 90.47619% 61.90476%; }
-
-.emojione-1f916 {
- background-position: 90.47619% 64.28571%; }
-
-.emojione-1f917 {
- background-position: 90.47619% 66.66667%; }
-
-.emojione-1f918-1f3fb {
- background-position: 90.47619% 69.04762%; }
-
-.emojione-1f918-1f3fc {
- background-position: 90.47619% 71.42857%; }
-
-.emojione-1f918-1f3fd {
- background-position: 90.47619% 73.80952%; }
-
-.emojione-1f918-1f3fe {
- background-position: 90.47619% 76.19048%; }
-
-.emojione-1f918-1f3ff {
- background-position: 90.47619% 78.57143%; }
-
-.emojione-1f918 {
- background-position: 90.47619% 80.95238%; }
-
-.emojione-1f919-1f3fb {
- background-position: 90.47619% 83.33333%; }
-
-.emojione-1f919-1f3fc {
- background-position: 90.47619% 85.71429%; }
-
-.emojione-1f919-1f3fd {
- background-position: 90.47619% 88.09524%; }
-
-.emojione-1f919-1f3fe {
- background-position: 0% 90.47619%; }
-
-.emojione-1f919-1f3ff {
- background-position: 2.38095% 90.47619%; }
-
-.emojione-1f919 {
- background-position: 4.7619% 90.47619%; }
-
-.emojione-1f91a-1f3fb {
- background-position: 7.14286% 90.47619%; }
-
-.emojione-1f91a-1f3fc {
- background-position: 9.52381% 90.47619%; }
-
-.emojione-1f91a-1f3fd {
- background-position: 11.90476% 90.47619%; }
-
-.emojione-1f91a-1f3fe {
- background-position: 14.28571% 90.47619%; }
-
-.emojione-1f91a-1f3ff {
- background-position: 16.66667% 90.47619%; }
-
-.emojione-1f91a {
- background-position: 19.04762% 90.47619%; }
-
-.emojione-1f91b-1f3fb {
- background-position: 21.42857% 90.47619%; }
-
-.emojione-1f91b-1f3fc {
- background-position: 23.80952% 90.47619%; }
-
-.emojione-1f91b-1f3fd {
- background-position: 26.19048% 90.47619%; }
-
-.emojione-1f91b-1f3fe {
- background-position: 28.57143% 90.47619%; }
-
-.emojione-1f91b-1f3ff {
- background-position: 30.95238% 90.47619%; }
-
-.emojione-1f91b {
- background-position: 33.33333% 90.47619%; }
-
-.emojione-1f91c-1f3fb {
- background-position: 35.71429% 90.47619%; }
-
-.emojione-1f91c-1f3fc {
- background-position: 38.09524% 90.47619%; }
-
-.emojione-1f91c-1f3fd {
- background-position: 40.47619% 90.47619%; }
-
-.emojione-1f91c-1f3fe {
- background-position: 42.85714% 90.47619%; }
-
-.emojione-1f91c-1f3ff {
- background-position: 45.2381% 90.47619%; }
-
-.emojione-1f91c {
- background-position: 47.61905% 90.47619%; }
-
-.emojione-1f91d-1f3fb {
- background-position: 50% 90.47619%; }
-
-.emojione-1f91d-1f3fc {
- background-position: 52.38095% 90.47619%; }
-
-.emojione-1f91d-1f3fd {
- background-position: 54.7619% 90.47619%; }
-
-.emojione-1f91d-1f3fe {
- background-position: 57.14286% 90.47619%; }
-
-.emojione-1f91d-1f3ff {
- background-position: 59.52381% 90.47619%; }
-
-.emojione-1f91d {
- background-position: 61.90476% 90.47619%; }
-
-.emojione-1f91e-1f3fb {
- background-position: 64.28571% 90.47619%; }
-
-.emojione-1f91e-1f3fc {
- background-position: 66.66667% 90.47619%; }
-
-.emojione-1f91e-1f3fd {
- background-position: 69.04762% 90.47619%; }
-
-.emojione-1f91e-1f3fe {
- background-position: 71.42857% 90.47619%; }
-
-.emojione-1f91e-1f3ff {
- background-position: 73.80952% 90.47619%; }
-
-.emojione-1f91e {
- background-position: 76.19048% 90.47619%; }
-
-.emojione-1f920 {
- background-position: 78.57143% 90.47619%; }
-
-.emojione-1f921 {
- background-position: 80.95238% 90.47619%; }
-
-.emojione-1f922 {
- background-position: 83.33333% 90.47619%; }
-
-.emojione-1f923 {
- background-position: 85.71429% 90.47619%; }
-
-.emojione-1f924 {
- background-position: 88.09524% 90.47619%; }
-
-.emojione-1f925 {
- background-position: 90.47619% 90.47619%; }
-
-.emojione-1f926-1f3fb {
- background-position: 92.85714% 0%; }
-
-.emojione-1f926-1f3fc {
- background-position: 92.85714% 2.38095%; }
-
-.emojione-1f926-1f3fd {
- background-position: 92.85714% 4.7619%; }
-
-.emojione-1f926-1f3fe {
- background-position: 92.85714% 7.14286%; }
-
-.emojione-1f926-1f3ff {
- background-position: 92.85714% 9.52381%; }
-
-.emojione-1f926 {
- background-position: 92.85714% 11.90476%; }
-
-.emojione-1f927 {
- background-position: 92.85714% 14.28571%; }
-
-.emojione-1f930-1f3fb {
- background-position: 92.85714% 16.66667%; }
-
-.emojione-1f930-1f3fc {
- background-position: 92.85714% 19.04762%; }
-
-.emojione-1f930-1f3fd {
- background-position: 92.85714% 21.42857%; }
-
-.emojione-1f930-1f3fe {
- background-position: 92.85714% 23.80952%; }
-
-.emojione-1f930-1f3ff {
- background-position: 92.85714% 26.19048%; }
-
-.emojione-1f930 {
- background-position: 92.85714% 28.57143%; }
-
-.emojione-1f933-1f3fb {
- background-position: 92.85714% 30.95238%; }
-
-.emojione-1f933-1f3fc {
- background-position: 92.85714% 33.33333%; }
-
-.emojione-1f933-1f3fd {
- background-position: 92.85714% 35.71429%; }
-
-.emojione-1f933-1f3fe {
- background-position: 92.85714% 38.09524%; }
-
-.emojione-1f933-1f3ff {
- background-position: 92.85714% 40.47619%; }
-
-.emojione-1f933 {
- background-position: 92.85714% 42.85714%; }
-
-.emojione-1f934-1f3fb {
- background-position: 92.85714% 45.2381%; }
-
-.emojione-1f934-1f3fc {
- background-position: 92.85714% 47.61905%; }
-
-.emojione-1f934-1f3fd {
- background-position: 92.85714% 50%; }
-
-.emojione-1f934-1f3fe {
- background-position: 92.85714% 52.38095%; }
-
-.emojione-1f934-1f3ff {
- background-position: 92.85714% 54.7619%; }
-
-.emojione-1f934 {
- background-position: 92.85714% 57.14286%; }
-
-.emojione-1f935-1f3fb {
- background-position: 92.85714% 59.52381%; }
-
-.emojione-1f935-1f3fc {
- background-position: 92.85714% 61.90476%; }
-
-.emojione-1f935-1f3fd {
- background-position: 92.85714% 64.28571%; }
-
-.emojione-1f935-1f3fe {
- background-position: 92.85714% 66.66667%; }
-
-.emojione-1f935-1f3ff {
- background-position: 92.85714% 69.04762%; }
-
-.emojione-1f935 {
- background-position: 92.85714% 71.42857%; }
-
-.emojione-1f936-1f3fb {
- background-position: 92.85714% 73.80952%; }
-
-.emojione-1f936-1f3fc {
- background-position: 92.85714% 76.19048%; }
-
-.emojione-1f936-1f3fd {
- background-position: 92.85714% 78.57143%; }
-
-.emojione-1f936-1f3fe {
- background-position: 92.85714% 80.95238%; }
-
-.emojione-1f936-1f3ff {
- background-position: 92.85714% 83.33333%; }
-
-.emojione-1f936 {
- background-position: 92.85714% 85.71429%; }
-
-.emojione-1f937-1f3fb {
- background-position: 92.85714% 88.09524%; }
-
-.emojione-1f937-1f3fc {
- background-position: 92.85714% 90.47619%; }
-
-.emojione-1f937-1f3fd {
- background-position: 0% 92.85714%; }
-
-.emojione-1f937-1f3fe {
- background-position: 2.38095% 92.85714%; }
-
-.emojione-1f937-1f3ff {
- background-position: 4.7619% 92.85714%; }
-
-.emojione-1f937 {
- background-position: 7.14286% 92.85714%; }
-
-.emojione-1f938-1f3fb {
- background-position: 9.52381% 92.85714%; }
-
-.emojione-1f938-1f3fc {
- background-position: 11.90476% 92.85714%; }
-
-.emojione-1f938-1f3fd {
- background-position: 14.28571% 92.85714%; }
-
-.emojione-1f938-1f3fe {
- background-position: 16.66667% 92.85714%; }
-
-.emojione-1f938-1f3ff {
- background-position: 19.04762% 92.85714%; }
-
-.emojione-1f938 {
- background-position: 21.42857% 92.85714%; }
-
-.emojione-1f939-1f3fb {
- background-position: 23.80952% 92.85714%; }
-
-.emojione-1f939-1f3fc {
- background-position: 26.19048% 92.85714%; }
-
-.emojione-1f939-1f3fd {
- background-position: 28.57143% 92.85714%; }
-
-.emojione-1f939-1f3fe {
- background-position: 30.95238% 92.85714%; }
-
-.emojione-1f939-1f3ff {
- background-position: 33.33333% 92.85714%; }
-
-.emojione-1f939 {
- background-position: 35.71429% 92.85714%; }
-
-.emojione-1f93a {
- background-position: 38.09524% 92.85714%; }
-
-.emojione-1f93c-1f3fb {
- background-position: 40.47619% 92.85714%; }
-
-.emojione-1f93c-1f3fc {
- background-position: 42.85714% 92.85714%; }
-
-.emojione-1f93c-1f3fd {
- background-position: 45.2381% 92.85714%; }
-
-.emojione-1f93c-1f3fe {
- background-position: 47.61905% 92.85714%; }
-
-.emojione-1f93c-1f3ff {
- background-position: 50% 92.85714%; }
-
-.emojione-1f93c {
- background-position: 52.38095% 92.85714%; }
-
-.emojione-1f93d-1f3fb {
- background-position: 54.7619% 92.85714%; }
-
-.emojione-1f93d-1f3fc {
- background-position: 57.14286% 92.85714%; }
-
-.emojione-1f93d-1f3fd {
- background-position: 59.52381% 92.85714%; }
-
-.emojione-1f93d-1f3fe {
- background-position: 61.90476% 92.85714%; }
-
-.emojione-1f93d-1f3ff {
- background-position: 64.28571% 92.85714%; }
-
-.emojione-1f93d {
- background-position: 66.66667% 92.85714%; }
-
-.emojione-1f93e-1f3fb {
- background-position: 69.04762% 92.85714%; }
-
-.emojione-1f93e-1f3fc {
- background-position: 71.42857% 92.85714%; }
-
-.emojione-1f93e-1f3fd {
- background-position: 73.80952% 92.85714%; }
-
-.emojione-1f93e-1f3fe {
- background-position: 76.19048% 92.85714%; }
-
-.emojione-1f93e-1f3ff {
- background-position: 78.57143% 92.85714%; }
-
-.emojione-1f93e {
- background-position: 80.95238% 92.85714%; }
-
-.emojione-1f940 {
- background-position: 83.33333% 92.85714%; }
-
-.emojione-1f941 {
- background-position: 85.71429% 92.85714%; }
-
-.emojione-1f942 {
- background-position: 88.09524% 92.85714%; }
-
-.emojione-1f943 {
- background-position: 90.47619% 92.85714%; }
-
-.emojione-1f944 {
- background-position: 92.85714% 92.85714%; }
-
-.emojione-1f945 {
- background-position: 95.2381% 0%; }
-
-.emojione-1f947 {
- background-position: 95.2381% 2.38095%; }
-
-.emojione-1f948 {
- background-position: 95.2381% 4.7619%; }
-
-.emojione-1f949 {
- background-position: 95.2381% 7.14286%; }
-
-.emojione-1f94a {
- background-position: 95.2381% 9.52381%; }
-
-.emojione-1f94b {
- background-position: 95.2381% 11.90476%; }
-
-.emojione-1f950 {
- background-position: 95.2381% 14.28571%; }
-
-.emojione-1f951 {
- background-position: 95.2381% 16.66667%; }
-
-.emojione-1f952 {
- background-position: 95.2381% 19.04762%; }
-
-.emojione-1f953 {
- background-position: 95.2381% 21.42857%; }
-
-.emojione-1f954 {
- background-position: 95.2381% 23.80952%; }
-
-.emojione-1f955 {
- background-position: 95.2381% 26.19048%; }
-
-.emojione-1f956 {
- background-position: 95.2381% 28.57143%; }
-
-.emojione-1f957 {
- background-position: 95.2381% 30.95238%; }
-
-.emojione-1f958 {
- background-position: 95.2381% 33.33333%; }
-
-.emojione-1f959 {
- background-position: 95.2381% 35.71429%; }
-
-.emojione-1f95a {
- background-position: 95.2381% 38.09524%; }
-
-.emojione-1f95b {
- background-position: 95.2381% 40.47619%; }
-
-.emojione-1f95c {
- background-position: 95.2381% 42.85714%; }
-
-.emojione-1f95d {
- background-position: 95.2381% 45.2381%; }
-
-.emojione-1f95e {
- background-position: 95.2381% 47.61905%; }
-
-.emojione-1f980 {
- background-position: 95.2381% 50%; }
-
-.emojione-1f981 {
- background-position: 95.2381% 52.38095%; }
-
-.emojione-1f982 {
- background-position: 95.2381% 54.7619%; }
-
-.emojione-1f983 {
- background-position: 95.2381% 57.14286%; }
-
-.emojione-1f984 {
- background-position: 95.2381% 59.52381%; }
-
-.emojione-1f985 {
- background-position: 95.2381% 61.90476%; }
-
-.emojione-1f986 {
- background-position: 95.2381% 64.28571%; }
-
-.emojione-1f987 {
- background-position: 95.2381% 66.66667%; }
-
-.emojione-1f988 {
- background-position: 95.2381% 69.04762%; }
-
-.emojione-1f989 {
- background-position: 95.2381% 71.42857%; }
-
-.emojione-1f98a {
- background-position: 95.2381% 73.80952%; }
-
-.emojione-1f98b {
- background-position: 95.2381% 76.19048%; }
-
-.emojione-1f98c {
- background-position: 95.2381% 78.57143%; }
-
-.emojione-1f98d {
- background-position: 95.2381% 80.95238%; }
-
-.emojione-1f98e {
- background-position: 95.2381% 83.33333%; }
-
-.emojione-1f98f {
- background-position: 95.2381% 85.71429%; }
-
-.emojione-1f990 {
- background-position: 95.2381% 88.09524%; }
-
-.emojione-1f991 {
- background-position: 95.2381% 90.47619%; }
-
-.emojione-1f9c0 {
- background-position: 95.2381% 92.85714%; }
-
-.emojione-203c {
- background-position: 0% 95.2381%; }
-
-.emojione-2049 {
- background-position: 2.38095% 95.2381%; }
-
-.emojione-2122 {
- background-position: 4.7619% 95.2381%; }
-
-.emojione-2139 {
- background-position: 7.14286% 95.2381%; }
-
-.emojione-2194 {
- background-position: 9.52381% 95.2381%; }
-
-.emojione-2195 {
- background-position: 11.90476% 95.2381%; }
-
-.emojione-2196 {
- background-position: 14.28571% 95.2381%; }
-
-.emojione-2197 {
- background-position: 16.66667% 95.2381%; }
-
-.emojione-2198 {
- background-position: 19.04762% 95.2381%; }
-
-.emojione-2199 {
- background-position: 21.42857% 95.2381%; }
-
-.emojione-21a9 {
- background-position: 23.80952% 95.2381%; }
-
-.emojione-21aa {
- background-position: 26.19048% 95.2381%; }
-
-.emojione-231a {
- background-position: 28.57143% 95.2381%; }
-
-.emojione-231b {
- background-position: 30.95238% 95.2381%; }
-
-.emojione-2328 {
- background-position: 33.33333% 95.2381%; }
-
-.emojione-23cf {
- background-position: 35.71429% 95.2381%; }
-
-.emojione-23e9 {
- background-position: 38.09524% 95.2381%; }
-
-.emojione-23ea {
- background-position: 40.47619% 95.2381%; }
-
-.emojione-23eb {
- background-position: 42.85714% 95.2381%; }
-
-.emojione-23ec {
- background-position: 45.2381% 95.2381%; }
-
-.emojione-23ed {
- background-position: 47.61905% 95.2381%; }
-
-.emojione-23ee {
- background-position: 50% 95.2381%; }
-
-.emojione-23ef {
- background-position: 52.38095% 95.2381%; }
-
-.emojione-23f0 {
- background-position: 54.7619% 95.2381%; }
-
-.emojione-23f1 {
- background-position: 57.14286% 95.2381%; }
-
-.emojione-23f2 {
- background-position: 59.52381% 95.2381%; }
-
-.emojione-23f3 {
- background-position: 61.90476% 95.2381%; }
-
-.emojione-23f8 {
- background-position: 64.28571% 95.2381%; }
-
-.emojione-23f9 {
- background-position: 66.66667% 95.2381%; }
-
-.emojione-23fa {
- background-position: 69.04762% 95.2381%; }
-
-.emojione-24c2 {
- background-position: 71.42857% 95.2381%; }
-
-.emojione-25aa {
- background-position: 73.80952% 95.2381%; }
-
-.emojione-25ab {
- background-position: 76.19048% 95.2381%; }
-
-.emojione-25b6 {
- background-position: 78.57143% 95.2381%; }
-
-.emojione-25c0 {
- background-position: 80.95238% 95.2381%; }
-
-.emojione-25fb {
- background-position: 83.33333% 95.2381%; }
-
-.emojione-25fc {
- background-position: 85.71429% 95.2381%; }
-
-.emojione-25fd {
- background-position: 88.09524% 95.2381%; }
-
-.emojione-25fe {
- background-position: 90.47619% 95.2381%; }
-
-.emojione-2600 {
- background-position: 92.85714% 95.2381%; }
-
-.emojione-2601 {
- background-position: 95.2381% 95.2381%; }
-
-.emojione-2602 {
- background-position: 97.61905% 0%; }
-
-.emojione-2603 {
- background-position: 97.61905% 2.38095%; }
-
-.emojione-2604 {
- background-position: 97.61905% 4.7619%; }
-
-.emojione-260e {
- background-position: 97.61905% 7.14286%; }
-
-.emojione-2611 {
- background-position: 97.61905% 9.52381%; }
-
-.emojione-2614 {
- background-position: 97.61905% 11.90476%; }
-
-.emojione-2615 {
- background-position: 97.61905% 14.28571%; }
-
-.emojione-2618 {
- background-position: 97.61905% 16.66667%; }
-
-.emojione-261d-1f3fb {
- background-position: 97.61905% 19.04762%; }
-
-.emojione-261d-1f3fc {
- background-position: 97.61905% 21.42857%; }
-
-.emojione-261d-1f3fd {
- background-position: 97.61905% 23.80952%; }
-
-.emojione-261d-1f3fe {
- background-position: 97.61905% 26.19048%; }
-
-.emojione-261d-1f3ff {
- background-position: 97.61905% 28.57143%; }
-
-.emojione-261d {
- background-position: 97.61905% 30.95238%; }
-
-.emojione-2620 {
- background-position: 97.61905% 33.33333%; }
-
-.emojione-2622 {
- background-position: 97.61905% 35.71429%; }
-
-.emojione-2623 {
- background-position: 97.61905% 38.09524%; }
-
-.emojione-2626 {
- background-position: 97.61905% 40.47619%; }
-
-.emojione-262a {
- background-position: 97.61905% 42.85714%; }
-
-.emojione-262e {
- background-position: 97.61905% 45.2381%; }
-
-.emojione-262f {
- background-position: 97.61905% 47.61905%; }
-
-.emojione-2638 {
- background-position: 97.61905% 50%; }
-
-.emojione-2639 {
- background-position: 97.61905% 52.38095%; }
-
-.emojione-263a {
- background-position: 97.61905% 54.7619%; }
-
-.emojione-2648 {
- background-position: 97.61905% 57.14286%; }
-
-.emojione-2649 {
- background-position: 97.61905% 59.52381%; }
-
-.emojione-264a {
- background-position: 97.61905% 61.90476%; }
-
-.emojione-264b {
- background-position: 97.61905% 64.28571%; }
-
-.emojione-264c {
- background-position: 97.61905% 66.66667%; }
-
-.emojione-264d {
- background-position: 97.61905% 69.04762%; }
-
-.emojione-264e {
- background-position: 97.61905% 71.42857%; }
-
-.emojione-264f {
- background-position: 97.61905% 73.80952%; }
-
-.emojione-2650 {
- background-position: 97.61905% 76.19048%; }
-
-.emojione-2651 {
- background-position: 97.61905% 78.57143%; }
-
-.emojione-2652 {
- background-position: 97.61905% 80.95238%; }
-
-.emojione-2653 {
- background-position: 97.61905% 83.33333%; }
-
-.emojione-2660 {
- background-position: 97.61905% 85.71429%; }
-
-.emojione-2663 {
- background-position: 97.61905% 88.09524%; }
-
-.emojione-2665 {
- background-position: 97.61905% 90.47619%; }
-
-.emojione-2666 {
- background-position: 97.61905% 92.85714%; }
-
-.emojione-2668 {
- background-position: 97.61905% 95.2381%; }
-
-.emojione-267b {
- background-position: 0% 97.61905%; }
-
-.emojione-267f {
- background-position: 2.38095% 97.61905%; }
-
-.emojione-2692 {
- background-position: 4.7619% 97.61905%; }
-
-.emojione-2693 {
- background-position: 7.14286% 97.61905%; }
-
-.emojione-2694 {
- background-position: 9.52381% 97.61905%; }
-
-.emojione-2696 {
- background-position: 11.90476% 97.61905%; }
-
-.emojione-2697 {
- background-position: 14.28571% 97.61905%; }
-
-.emojione-2699 {
- background-position: 16.66667% 97.61905%; }
-
-.emojione-269b {
- background-position: 19.04762% 97.61905%; }
-
-.emojione-269c {
- background-position: 21.42857% 97.61905%; }
-
-.emojione-26a0 {
- background-position: 23.80952% 97.61905%; }
-
-.emojione-26a1 {
- background-position: 26.19048% 97.61905%; }
-
-.emojione-26aa {
- background-position: 28.57143% 97.61905%; }
-
-.emojione-26ab {
- background-position: 30.95238% 97.61905%; }
-
-.emojione-26b0 {
- background-position: 33.33333% 97.61905%; }
-
-.emojione-26b1 {
- background-position: 35.71429% 97.61905%; }
-
-.emojione-26bd {
- background-position: 38.09524% 97.61905%; }
-
-.emojione-26be {
- background-position: 40.47619% 97.61905%; }
-
-.emojione-26c4 {
- background-position: 42.85714% 97.61905%; }
-
-.emojione-26c5 {
- background-position: 45.2381% 97.61905%; }
-
-.emojione-26c8 {
- background-position: 47.61905% 97.61905%; }
-
-.emojione-26ce {
- background-position: 50% 97.61905%; }
-
-.emojione-26cf {
- background-position: 52.38095% 97.61905%; }
-
-.emojione-26d1 {
- background-position: 54.7619% 97.61905%; }
-
-.emojione-26d3 {
- background-position: 57.14286% 97.61905%; }
-
-.emojione-26d4 {
- background-position: 59.52381% 97.61905%; }
-
-.emojione-26e9 {
- background-position: 61.90476% 97.61905%; }
-
-.emojione-26ea {
- background-position: 64.28571% 97.61905%; }
-
-.emojione-26f0 {
- background-position: 66.66667% 97.61905%; }
-
-.emojione-26f1 {
- background-position: 69.04762% 97.61905%; }
-
-.emojione-26f2 {
- background-position: 71.42857% 97.61905%; }
-
-.emojione-26f3 {
- background-position: 73.80952% 97.61905%; }
-
-.emojione-26f4 {
- background-position: 76.19048% 97.61905%; }
-
-.emojione-26f5 {
- background-position: 78.57143% 97.61905%; }
-
-.emojione-26f7 {
- background-position: 80.95238% 97.61905%; }
-
-.emojione-26f8 {
- background-position: 83.33333% 97.61905%; }
-
-.emojione-26f9-1f3fb {
- background-position: 85.71429% 97.61905%; }
-
-.emojione-26f9-1f3fc {
- background-position: 88.09524% 97.61905%; }
-
-.emojione-26f9-1f3fd {
- background-position: 90.47619% 97.61905%; }
-
-.emojione-26f9-1f3fe {
- background-position: 92.85714% 97.61905%; }
-
-.emojione-26f9-1f3ff {
- background-position: 95.2381% 97.61905%; }
-
-.emojione-26f9 {
- background-position: 97.61905% 97.61905%; }
-
-.emojione-26fa {
- background-position: 100% 0%; }
-
-.emojione-26fd {
- background-position: 100% 2.38095%; }
-
-.emojione-2702 {
- background-position: 100% 4.7619%; }
-
-.emojione-2705 {
- background-position: 100% 7.14286%; }
-
-.emojione-2708 {
- background-position: 100% 9.52381%; }
-
-.emojione-2709 {
- background-position: 100% 11.90476%; }
-
-.emojione-270a-1f3fb {
- background-position: 100% 14.28571%; }
-
-.emojione-270a-1f3fc {
- background-position: 100% 16.66667%; }
-
-.emojione-270a-1f3fd {
- background-position: 100% 19.04762%; }
-
-.emojione-270a-1f3fe {
- background-position: 100% 21.42857%; }
-
-.emojione-270a-1f3ff {
- background-position: 100% 23.80952%; }
-
-.emojione-270a {
- background-position: 100% 26.19048%; }
-
-.emojione-270b-1f3fb {
- background-position: 100% 28.57143%; }
-
-.emojione-270b-1f3fc {
- background-position: 100% 30.95238%; }
-
-.emojione-270b-1f3fd {
- background-position: 100% 33.33333%; }
-
-.emojione-270b-1f3fe {
- background-position: 100% 35.71429%; }
-
-.emojione-270b-1f3ff {
- background-position: 100% 38.09524%; }
-
-.emojione-270b {
- background-position: 100% 40.47619%; }
-
-.emojione-270c-1f3fb {
- background-position: 100% 42.85714%; }
-
-.emojione-270c-1f3fc {
- background-position: 100% 45.2381%; }
-
-.emojione-270c-1f3fd {
- background-position: 100% 47.61905%; }
-
-.emojione-270c-1f3fe {
- background-position: 100% 50%; }
-
-.emojione-270c-1f3ff {
- background-position: 100% 52.38095%; }
-
-.emojione-270c {
- background-position: 100% 54.7619%; }
-
-.emojione-270d-1f3fb {
- background-position: 100% 57.14286%; }
-
-.emojione-270d-1f3fc {
- background-position: 100% 59.52381%; }
-
-.emojione-270d-1f3fd {
- background-position: 100% 61.90476%; }
-
-.emojione-270d-1f3fe {
- background-position: 100% 64.28571%; }
-
-.emojione-270d-1f3ff {
- background-position: 100% 66.66667%; }
-
-.emojione-270d {
- background-position: 100% 69.04762%; }
-
-.emojione-270f {
- background-position: 100% 71.42857%; }
-
-.emojione-2712 {
- background-position: 100% 73.80952%; }
-
-.emojione-2714 {
- background-position: 100% 76.19048%; }
-
-.emojione-2716 {
- background-position: 100% 78.57143%; }
-
-.emojione-271d {
- background-position: 100% 80.95238%; }
-
-.emojione-2721 {
- background-position: 100% 83.33333%; }
-
-.emojione-2728 {
- background-position: 100% 85.71429%; }
-
-.emojione-2733 {
- background-position: 100% 88.09524%; }
-
-.emojione-2734 {
- background-position: 100% 90.47619%; }
-
-.emojione-2744 {
- background-position: 100% 92.85714%; }
-
-.emojione-2747 {
- background-position: 100% 95.2381%; }
-
-.emojione-274c {
- background-position: 100% 97.61905%; }
-
-.emojione-274e {
- background-position: 0% 100%; }
-
-.emojione-2753 {
- background-position: 2.38095% 100%; }
-
-.emojione-2754 {
- background-position: 4.7619% 100%; }
-
-.emojione-2755 {
- background-position: 7.14286% 100%; }
-
-.emojione-2757 {
- background-position: 9.52381% 100%; }
-
-.emojione-2763 {
- background-position: 11.90476% 100%; }
-
-.emojione-2764 {
- background-position: 14.28571% 100%; }
-
-.emojione-2795 {
- background-position: 16.66667% 100%; }
-
-.emojione-2796 {
- background-position: 19.04762% 100%; }
-
-.emojione-2797 {
- background-position: 21.42857% 100%; }
-
-.emojione-27a1 {
- background-position: 23.80952% 100%; }
-
-.emojione-27b0 {
- background-position: 26.19048% 100%; }
-
-.emojione-27bf {
- background-position: 28.57143% 100%; }
-
-.emojione-2934 {
- background-position: 30.95238% 100%; }
-
-.emojione-2935 {
- background-position: 33.33333% 100%; }
-
-.emojione-2b05 {
- background-position: 35.71429% 100%; }
-
-.emojione-2b06 {
- background-position: 38.09524% 100%; }
-
-.emojione-2b07 {
- background-position: 40.47619% 100%; }
-
-.emojione-2b1b {
- background-position: 42.85714% 100%; }
-
-.emojione-2b1c {
- background-position: 45.2381% 100%; }
-
-.emojione-2b50 {
- background-position: 47.61905% 100%; }
-
-.emojione-2b55 {
- background-position: 50% 100%; }
-
-.emojione-3030 {
- background-position: 52.38095% 100%; }
-
-.emojione-303d {
- background-position: 54.7619% 100%; }
-
-.emojione-3297 {
- background-position: 57.14286% 100%; }
-
-.emojione-3299 {
- background-position: 59.52381% 100%; }
diff --git a/packages/rocketchat-emoji/client/emojiButton.js b/packages/rocketchat-emoji/client/emojiButton.js
new file mode 100644
index 0000000000000..997dc4966763b
--- /dev/null
+++ b/packages/rocketchat-emoji/client/emojiButton.js
@@ -0,0 +1,37 @@
+/* globals Template chatMessages*/
+Template.messageBox.events({
+ 'click .emoji-picker-icon'(event) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ if (!RocketChat.getUserPreference(Meteor.user(), 'useEmojis')) {
+ return false;
+ }
+
+ if (RocketChat.EmojiPicker.isOpened()) {
+ RocketChat.EmojiPicker.close();
+ } else {
+ RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => {
+ const {input} = chatMessages[RocketChat.openedRoom];
+
+ const emojiValue = `:${ emoji }:`;
+
+ const caretPos = input.selectionStart;
+ const textAreaTxt = input.value;
+ input.focus();
+ if (!document.execCommand || !document.execCommand('insertText', false, emojiValue)) {
+ input.value = textAreaTxt.substring(0, caretPos) + emojiValue + textAreaTxt.substring(caretPos);
+ }
+
+ input.focus();
+
+ input.selectionStart = caretPos + emojiValue.length;
+ input.selectionEnd = caretPos + emojiValue.length;
+ });
+ }
+ }
+});
+
+Template.messageBox.onCreated(function() {
+ RocketChat.EmojiPicker.init();
+});
diff --git a/packages/rocketchat-emoji/client/emojiParser.js b/packages/rocketchat-emoji/client/emojiParser.js
new file mode 100644
index 0000000000000..d31b4bc77887f
--- /dev/null
+++ b/packages/rocketchat-emoji/client/emojiParser.js
@@ -0,0 +1,51 @@
+/* globals isSetNotNull */
+import s from 'underscore.string';
+
+/*
+ * emojiParser is a function that will replace emojis
+ * @param {Object} message - The message object
+ */
+RocketChat.callbacks.add('renderMessage', (message) => {
+ if (isSetNotNull(() => RocketChat.getUserPreference(Meteor.user(), 'useEmojis')) &&
+ !RocketChat.getUserPreference(Meteor.user(), 'useEmojis')) {
+ return message;
+ }
+
+ if (s.trim(message.html)) {
+ //' to apostrophe (') for emojis such as :')
+ message.html = message.html.replace(/'/g, '\'');
+
+ Object.keys(RocketChat.emoji.packages).forEach((emojiPackage) => {
+ message.html = RocketChat.emoji.packages[emojiPackage].render(message.html);
+ });
+
+ const checkEmojiOnly = $(`${ message.html }
`);
+ let emojiOnly = true;
+ for (const childNode in checkEmojiOnly[0].childNodes) {
+ if (checkEmojiOnly[0].childNodes.hasOwnProperty(childNode)) {
+ const child = $(checkEmojiOnly[0].childNodes[childNode]);
+
+ if (child.hasClass('emoji') || child.hasClass('emojione')) {
+ checkEmojiOnly[0].childNodes[childNode] = child.addClass('big');
+ continue;
+ }
+
+ if (s.trim(child.text()) === '') {
+ continue;
+ }
+
+ emojiOnly = false;
+ break;
+ }
+ }
+
+ if (emojiOnly) {
+ message.html = checkEmojiOnly.unwrap().html();
+ }
+
+ //apostrophe (') back to '
+ message.html = message.html.replace(/\'/g, ''');
+ }
+
+ return message;
+}, RocketChat.callbacks.priority.LOW, 'emoji');
diff --git a/packages/rocketchat-emoji/emojiPicker.html b/packages/rocketchat-emoji/client/emojiPicker.html
similarity index 75%
rename from packages/rocketchat-emoji/emojiPicker.html
rename to packages/rocketchat-emoji/client/emojiPicker.html
index 8ac2e5e66b256..6cb450e9d40a0 100644
--- a/packages/rocketchat-emoji/emojiPicker.html
+++ b/packages/rocketchat-emoji/client/emojiPicker.html
@@ -1,10 +1,16 @@
-
+
-
+
diff --git a/packages/rocketchat-emoji/client/emojiPicker.js b/packages/rocketchat-emoji/client/emojiPicker.js
new file mode 100644
index 0000000000000..415825effbaa5
--- /dev/null
+++ b/packages/rocketchat-emoji/client/emojiPicker.js
@@ -0,0 +1,283 @@
+/* globals Template, isSetNotNull */
+const emojiCategories = {};
+/**
+ * Turns category hash to a nice readable translated name
+ * @param {string} category hash
+ * @return {string} readable and translated
+ */
+function categoryName(category) {
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ if (RocketChat.emoji.packages[emojiPackage].emojiCategories.hasOwnProperty(category)) {
+ const categoryTag = RocketChat.emoji.packages[emojiPackage].emojiCategories[category];
+ return TAPi18n.__(categoryTag);
+ }
+ }
+ }
+ if (emojiCategories.hasOwnProperty(category)) {
+ return emojiCategories[category];
+ }
+ // unknown category; better hash than nothing
+ return category;
+}
+
+function getEmojisByCategory(category) {
+ const t = Template.instance();
+ const actualTone = t.tone;
+ let html = '';
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(category)) {
+ const total = RocketChat.emoji.packages[emojiPackage].emojisByCategory[category].length;
+ for (let i = 0; i < total; i++) {
+ const emoji = RocketChat.emoji.packages[emojiPackage].emojisByCategory[category][i];
+ let tone = '';
+
+ if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
+ tone = `_tone${ actualTone }`;
+ }
+
+ //set correctPackage here to allow for recent emojis to work properly
+ if (isSetNotNull(() => RocketChat.emoji.list[`:${ emoji }:`].emojiPackage)) {
+ const correctPackage = RocketChat.emoji.list[`:${ emoji }:`].emojiPackage;
+ const image = RocketChat.emoji.packages[correctPackage].render(`:${ emoji }${ tone }:`);
+
+ html += `${ image } `;
+ }
+ }
+ }
+ }
+ }
+ return html;
+}
+
+function getEmojisBySearchTerm(searchTerm) {
+ let html = '';
+ const t = Template.instance();
+ const actualTone = t.tone;
+
+ const searchRegExp = new RegExp(RegExp.escape(searchTerm.replace(/:/g, '')), 'i');
+
+ for (let emoji in RocketChat.emoji.list) {
+ if (!RocketChat.emoji.list.hasOwnProperty(emoji)) {
+ continue;
+ }
+
+ if (searchRegExp.test(emoji)) {
+ const emojiObject = RocketChat.emoji.list[emoji];
+ const emojiPackage = emojiObject.emojiPackage;
+ let tone = '';
+ emoji = emoji.replace(/:/g, '');
+
+ if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
+ tone = `_tone${ actualTone }`;
+ }
+
+ let emojiFound = false;
+
+ for (const key in RocketChat.emoji.packages[emojiPackage].emojisByCategory) {
+ if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(key)) {
+ const contents = RocketChat.emoji.packages[emojiPackage].emojisByCategory[key];
+ if (contents.indexOf(emoji) !== -1) {
+ emojiFound = true;
+ break;
+ }
+ }
+ }
+
+ if (emojiFound) {
+ const image = RocketChat.emoji.packages[emojiPackage].render(`:${ emoji }${ tone }:`);
+ html += `${ image } `;
+ }
+ }
+ }
+
+ return html;
+}
+
+Template.emojiPicker.helpers({
+ category() {
+ const categories = [];
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ for (const key in RocketChat.emoji.packages[emojiPackage].emojisByCategory) {
+ if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(key)) {
+ categories.push(key);
+ }
+ }
+ }
+ }
+ return categories;
+ },
+ emojiByCategory(category) {
+ let emojisByCategory = [];
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(category)) {
+ emojisByCategory = emojisByCategory.concat(RocketChat.emoji.packages[emojiPackage].emojisByCategory[category]);
+ }
+ }
+ }
+ return emojisByCategory;
+ },
+ isVisible(category) {
+ return Template.instance().currentCategory.get() === category ? 'visible' : '';
+ },
+ emojiList(category) {
+ const t = Template.instance();
+ const searchTerm = t.currentSearchTerm.get();
+ const activeCategory = t.currentCategory.get();
+ //this will cause the reflow when recent list gets updated
+ t.recentNeedsUpdate.get();
+
+ //we only need to replace the active category, since switching tabs resets the filter
+ if (activeCategory !== category) {
+ return;
+ }
+
+ if (searchTerm.length > 0) {
+ return getEmojisBySearchTerm(searchTerm);
+ } else {
+ return getEmojisByCategory(category);
+ }
+ },
+ currentTone() {
+ return `tone-${ Template.instance().tone }`;
+ },
+ /**
+ * Returns true if a given emoji category is active
+ *
+ * @param {string} category hash
+ * @return {boolean} true if active, false otherwise
+ */
+ activeCategory(category) {
+ return Template.instance().currentCategory.get() === category ? 'active' : '';
+ },
+ categoryName,
+ /**
+ * Returns currently active emoji category hash
+ *
+ * @return {string} category hash
+ */
+ currentCategory() {
+ const t = Template.instance();
+ const hash = t.currentCategory.get();
+ const searchTerm = t.currentSearchTerm.get();
+
+ if (searchTerm.length > 0) {
+ return TAPi18n.__('Search');
+ } else {
+ return categoryName(hash);
+ }
+ }
+});
+
+Template.emojiPicker.events({
+ 'click .emoji-picker'(event) {
+ event.stopPropagation();
+ event.preventDefault();
+ },
+ 'click .category-link'(event, instance) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ instance.$('.emoji-filter .search').val('').change();
+ instance.$('.emoji-filter .search').focus();
+
+ instance.currentCategory.set(event.currentTarget.hash.substr(1));
+
+ return false;
+ },
+ 'click .change-tone > a'(event, instance) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ instance.$('.tone-selector').toggleClass('show');
+ },
+ 'click .tone-selector .tone'(event, instance) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ const tone = parseInt(event.currentTarget.dataset.tone);
+ let newTone;
+
+ if (tone > 0) {
+ newTone = `_tone${ tone }`;
+ } else {
+ newTone = '';
+ }
+
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ if (RocketChat.emoji.packages[emojiPackage].hasOwnProperty('toneList')) {
+ for (const emoji in RocketChat.emoji.packages[emojiPackage].toneList) {
+ if (RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
+ $(`.emoji-${ emoji }`).html(RocketChat.emoji.packages[emojiPackage].render(`:${ emoji }${ newTone }:`));
+ }
+ }
+ }
+ }
+ }
+
+ RocketChat.EmojiPicker.setTone(tone);
+
+ instance.setCurrentTone(tone);
+
+ $('.tone-selector').toggleClass('show');
+ },
+ 'click .emoji-list li'(event, instance) {
+ event.stopPropagation();
+
+ const emoji = event.currentTarget.dataset.emoji;
+ const actualTone = instance.tone;
+ let tone = '';
+
+ for (const emojiPackage in RocketChat.emoji.packages) {
+ if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
+ if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
+ tone = `_tone${ actualTone }`;
+ }
+ }
+ }
+
+ const input = $('.emoji-filter input.search');
+ if (input) {
+ input.val('');
+ }
+ instance.currentSearchTerm.set('');
+
+ RocketChat.EmojiPicker.pickEmoji(emoji + tone);
+ },
+ 'keyup .js-emojipicker-search, change .js-emojipicker-search'(event, instance) {
+ const value = event.target.value.trim();
+ const cst = instance.currentSearchTerm;
+ if (value === cst.get()) {
+ return;
+ }
+ cst.set(value);
+ }
+});
+
+Template.emojiPicker.onCreated(function() {
+ this.tone = RocketChat.EmojiPicker.getTone();
+ const recent = RocketChat.EmojiPicker.getRecent();
+ this.recentNeedsUpdate = new ReactiveVar(false);
+ this.currentCategory = new ReactiveVar(recent.length > 0 ? 'recent' : 'people');
+ this.currentSearchTerm = new ReactiveVar('');
+
+ recent.forEach((emoji) => {
+ RocketChat.emoji.packages.base.emojisByCategory.recent.push(emoji);
+ });
+
+ this.setCurrentTone = (newTone) => {
+ $('.current-tone').removeClass(`tone-${ this.tone }`);
+ $('.current-tone').addClass(`tone-${ newTone }`);
+ this.tone = newTone;
+ };
+
+ this.autorun(() => {
+ if (this.recentNeedsUpdate.get()) {
+ this.recentNeedsUpdate.set(false);
+ }
+ });
+});
diff --git a/packages/rocketchat-emoji/function-isSet.js b/packages/rocketchat-emoji/client/function-isSet.js
similarity index 94%
rename from packages/rocketchat-emoji/function-isSet.js
rename to packages/rocketchat-emoji/client/function-isSet.js
index 9bd663ba5c08b..de7bdf3827f12 100644
--- a/packages/rocketchat-emoji/function-isSet.js
+++ b/packages/rocketchat-emoji/client/function-isSet.js
@@ -1,7 +1,7 @@
/* globals isSet:true, isSetNotNull:true */
//http://stackoverflow.com/a/26990347 function isSet() from Gajus
isSet = function(fn) {
- var value;
+ let value;
try {
value = fn();
} catch (e) {
@@ -12,7 +12,7 @@ isSet = function(fn) {
};
isSetNotNull = function(fn) {
- var value;
+ let value;
try {
value = fn();
} catch (e) {
diff --git a/packages/rocketchat-emoji/keyboardFix.js b/packages/rocketchat-emoji/client/keyboardFix.js
similarity index 99%
rename from packages/rocketchat-emoji/keyboardFix.js
rename to packages/rocketchat-emoji/client/keyboardFix.js
index 7bf03ead5c529..297887458074f 100644
--- a/packages/rocketchat-emoji/keyboardFix.js
+++ b/packages/rocketchat-emoji/client/keyboardFix.js
@@ -11,4 +11,4 @@ if (Meteor.isCordova) {
RocketChat.EmojiPicker.setPosition();
}
});
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-emoji/client/lib/EmojiPicker.js b/packages/rocketchat-emoji/client/lib/EmojiPicker.js
new file mode 100644
index 0000000000000..d5d2759520496
--- /dev/null
+++ b/packages/rocketchat-emoji/client/lib/EmojiPicker.js
@@ -0,0 +1,146 @@
+/* globals Blaze, Template */
+import _ from 'underscore';
+
+RocketChat.EmojiPicker = {
+ width: 390,
+ height: 238,
+ initiated: false,
+ input: null,
+ source: null,
+ recent: [],
+ tone: null,
+ opened: false,
+ pickCallback: null,
+ init() {
+ if (this.initiated) {
+ return;
+ }
+ this.initiated = true;
+
+ this.recent = window.localStorage.getItem('emoji.recent') ? window.localStorage.getItem('emoji.recent').split(',') : [];
+ this.tone = window.localStorage.getItem('emoji.tone') || 0;
+
+ Blaze.render(Template.emojiPicker, document.body);
+
+ $(document).click((event) => {
+ if (!this.opened) {
+ return;
+ }
+ if (!$(event.target).closest('.emoji-picker').length && !$(event.target).is('.emoji-picker')) {
+ if (this.opened) {
+ this.close();
+ }
+ }
+ });
+
+ $(window).resize(_.debounce(() => {
+ if (!this.opened) {
+ return;
+ }
+ this.setPosition();
+ }, 300));
+ },
+ isOpened() {
+ return this.opened;
+ },
+ setTone(tone) {
+ this.tone = tone;
+ window.localStorage.setItem('emoji.tone', tone);
+ },
+ getTone() {
+ return this.tone;
+ },
+ getRecent() {
+ return this.recent;
+ },
+ setPosition() {
+ const sourcePos = $(this.source).offset();
+ const left = sourcePos.left;
+ const top = sourcePos.top - this.height - 60;
+ const cssProperties = {
+ top,
+ left
+ };
+
+ if (top < 0) {
+ cssProperties.top = 10;
+ }
+
+ if (left < 35) {
+ cssProperties.left = 0;
+ } else {
+ const windowSize = $(window).width();
+ const pickerWidth = $('.emoji-picker').outerWidth();
+
+ if (left + pickerWidth > windowSize) {
+ cssProperties.left = left - pickerWidth;
+ }
+ }
+
+ return $('.emoji-picker').css(cssProperties);
+ },
+ open(source, callback) {
+ if (!this.initiated) {
+ this.init();
+ }
+ this.pickCallback = callback;
+ this.source = source;
+
+ const containerEl = this.setPosition();
+ containerEl.addClass('show');
+
+ const emojiInput = containerEl.find('.emoji-filter input.search');
+ if (emojiInput) {
+ emojiInput.focus();
+ }
+ this.opened = true;
+ },
+ close() {
+ $('.emoji-picker').removeClass('show');
+ this.opened = false;
+ },
+ pickEmoji(emoji) {
+ this.pickCallback(emoji);
+
+ this.close();
+ this.addRecent(emoji);
+ },
+ addRecent(emoji) {
+ const pos = this.recent.indexOf(emoji);
+
+ if (pos !== -1) {
+ this.recent.splice(pos, 1);
+ }
+
+ this.recent.unshift(emoji);
+
+ window.localStorage.setItem('emoji.recent', this.recent);
+ RocketChat.emoji.packages.base.emojisByCategory.recent = this.recent;
+ this.updateRecent();
+ },
+ updateRecent() {
+ const instance = Template.instance();
+ if (instance) {
+ instance.recentNeedsUpdate.set(true);
+ } else {
+ this.refreshDynamicEmojiLists();
+ }
+ },
+ refreshDynamicEmojiLists() {
+ const dynamicEmojiLists = [
+ RocketChat.emoji.packages.base.emojisByCategory.recent,
+ RocketChat.emoji.packages.emojiCustom.emojisByCategory.rocket
+ ];
+
+ dynamicEmojiLists.forEach((category) => {
+ if (category) {
+ for (let i = 0; i < category.length; i++) {
+ const emoji = category[i];
+ if (!RocketChat.emoji.list[`:${ emoji }:`]) {
+ category = _.without(category, emoji);
+ }
+ }
+ }
+ });
+ }
+};
diff --git a/packages/rocketchat-emoji/client/lib/emojiRenderer.js b/packages/rocketchat-emoji/client/lib/emojiRenderer.js
new file mode 100644
index 0000000000000..2f91e74ea4d4c
--- /dev/null
+++ b/packages/rocketchat-emoji/client/lib/emojiRenderer.js
@@ -0,0 +1,23 @@
+/* globals HTML, isSetNotNull, renderEmoji:true */
+renderEmoji = function(emoji) {
+ if (isSetNotNull(() => RocketChat.emoji.list[emoji].emojiPackage)) {
+ const emojiPackage = RocketChat.emoji.list[emoji].emojiPackage;
+ return RocketChat.emoji.packages[emojiPackage].render(emoji);
+ }
+};
+
+Blaze.registerHelper('renderEmoji', renderEmoji);
+
+Template.registerHelper('renderEmoji', new Template('renderEmoji', function() {
+ const view = this;
+ const emoji = Blaze.getData(view);
+
+ if (isSetNotNull(() => RocketChat.emoji.list[emoji].emojiPackage)) {
+ const emojiPackage = RocketChat.emoji.list[emoji].emojiPackage;
+ return new HTML.Raw(RocketChat.emoji.packages[emojiPackage].render(emoji));
+ }
+
+ return '';
+}));
+
+/* exported renderEmoji */
diff --git a/packages/rocketchat-emoji/client/rocketchat.js b/packages/rocketchat-emoji/client/rocketchat.js
new file mode 100644
index 0000000000000..33a4e0d2cb811
--- /dev/null
+++ b/packages/rocketchat-emoji/client/rocketchat.js
@@ -0,0 +1,15 @@
+RocketChat.emoji = {
+ packages: {
+ base: {
+ emojiCategories: { recent: 'Frequently_Used' },
+ emojisByCategory: {
+ recent: []
+ },
+ toneList: {},
+ render(html) {
+ return html;
+ }
+ }
+ },
+ list: {}
+};
diff --git a/packages/rocketchat-emoji/emoji.css b/packages/rocketchat-emoji/emoji.css
deleted file mode 100644
index 01dc97f89176b..0000000000000
--- a/packages/rocketchat-emoji/emoji.css
+++ /dev/null
@@ -1,22 +0,0 @@
-.emoji {
- image-rendering: auto;
- font-size: inherit;
- height: 22px;
- width: 22px;
- position: relative;
- display: inline-block;
- margin: 0 .15em;
- line-height: normal;
- vertical-align: middle;
- background-position: center;
- background-repeat: no-repeat;
- background-size: cover;
- text-indent: 100%;
- white-space: nowrap;
- overflow: hidden;
-}
-
-.emoji.big {
- height: 44px !important;
- width: 44px !important;
-}
diff --git a/packages/rocketchat-emoji/emojiButton.js b/packages/rocketchat-emoji/emojiButton.js
deleted file mode 100644
index 0544610658a99..0000000000000
--- a/packages/rocketchat-emoji/emojiButton.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/* globals Template */
-Template.messageBox.events({
- 'click .emoji-picker-icon'(event) {
- event.stopPropagation();
- if (RocketChat.EmojiPicker.isOpened()) {
- RocketChat.EmojiPicker.close();
- } else {
- RocketChat.EmojiPicker.open(event.currentTarget, (emoji) => {
- const input = $(event.currentTarget).parent().parent().find('.input-message');
-
- let emojiValue = ':' + emoji + ':';
-
- var caretPos = input.prop('selectionStart');
- var textAreaTxt = input.val();
-
- input.val(textAreaTxt.substring(0, caretPos) + emojiValue + textAreaTxt.substring(caretPos));
-
- input.focus();
-
- input.prop('selectionStart', caretPos + emojiValue.length);
- input.prop('selectionEnd', caretPos + emojiValue.length);
- });
- }
- }
-});
-
-Template.messageBox.onCreated(function() {
- RocketChat.EmojiPicker.init();
-});
diff --git a/packages/rocketchat-emoji/emojiParser.js b/packages/rocketchat-emoji/emojiParser.js
deleted file mode 100644
index 5a7641409bb33..0000000000000
--- a/packages/rocketchat-emoji/emojiParser.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* globals isSetNotNull */
-/*
- * emojiParser is a function that will replace emojis
- * @param {Object} message - The message object
- */
-RocketChat.callbacks.add('renderMessage', (message) => {
- if (isSetNotNull(() => Meteor.user().settings.preferences.useEmojis) && !Meteor.user().settings.preferences.useEmojis) {
- return message;
- }
-
- if (_.trim(message.html)) {
- //' to apostrophe (') for emojis such as :')
- message.html = message.html.replace(/'/g, '\'');
-
- Object.keys(RocketChat.emoji.packages).forEach((emojiPackage) => {
- message.html = RocketChat.emoji.packages[emojiPackage].render(message.html);
- });
-
- let checkEmojiOnly = $(`${message.html}
`);
- let emojiOnly = true;
- for (let childNode in checkEmojiOnly[0].childNodes) {
- if (checkEmojiOnly[0].childNodes.hasOwnProperty(childNode)) {
- let child = $(checkEmojiOnly[0].childNodes[childNode]);
-
- if (child.hasClass('emoji') || child.hasClass('emojione')) {
- checkEmojiOnly[0].childNodes[childNode] = child.addClass('big');
- continue;
- }
-
- if (_.trim(child.text()) === '') {
- continue;
- }
-
- emojiOnly = false;
- break;
- }
- }
-
- if (emojiOnly) {
- message.html = checkEmojiOnly.unwrap().html();
- }
-
- //apostrophe (') back to '
- message.html = message.html.replace(/\'/g, ''');
- }
-
- return message;
-}, RocketChat.callbacks.priority.LOW, 'emoji');
diff --git a/packages/rocketchat-emoji/emojiPicker.js b/packages/rocketchat-emoji/emojiPicker.js
deleted file mode 100644
index d4c5802ddde43..0000000000000
--- a/packages/rocketchat-emoji/emojiPicker.js
+++ /dev/null
@@ -1,279 +0,0 @@
-/* globals Template, isSetNotNull */
-var emojiCategories = {};
-/**
- * Turns category hash to a nice readable translated name
- * @param {string} category hash
- * @return {string} readable and translated
- */
-function categoryName(category) {
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- if (RocketChat.emoji.packages[emojiPackage].emojiCategories.hasOwnProperty(category)) {
- return RocketChat.emoji.packages[emojiPackage].emojiCategories[category];
- }
- }
- }
- if (emojiCategories.hasOwnProperty(category)) {
- return emojiCategories[category];
- }
- // unknown category; better hash than nothing
- return category;
-}
-
-function getEmojisByCategory(category) {
- const t = Template.instance();
- const actualTone = t.tone;
- let html = '';
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(category)) {
- let total = RocketChat.emoji.packages[emojiPackage].emojisByCategory[category].length;
- for (let i = 0; i < total; i++) {
- let emoji = RocketChat.emoji.packages[emojiPackage].emojisByCategory[category][i];
- let tone = '';
-
- if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
- tone = '_tone' + actualTone;
- }
-
- //set correctPackage here to allow for recent emojis to work properly
- if (isSetNotNull(() => RocketChat.emoji.list[`:${emoji}:`].emojiPackage)) {
- let correctPackage = RocketChat.emoji.list[`:${emoji}:`].emojiPackage;
-
- const image = RocketChat.emoji.packages[correctPackage].render(`:${emoji}${tone}:`);
-
- html += `${image} `;
- }
- }
- }
- }
- }
- return html;
-}
-
-function getEmojisBySearchTerm(searchTerm) {
- let html = '';
- const t = Template.instance();
- const actualTone = t.tone;
-
- let searchRegExp = new RegExp(RegExp.escape(searchTerm.replace(/:/g, '')), 'i');
-
- for (let emoji in RocketChat.emoji.list) {
- if (!RocketChat.emoji.list.hasOwnProperty(emoji)) {
- continue;
- }
-
- if (searchRegExp.test(emoji)) {
- let emojiObject = RocketChat.emoji.list[emoji];
- let emojiPackage = emojiObject.emojiPackage;
- let tone = '';
- emoji = emoji.replace(/:/g, '');
-
- if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
- tone = '_tone' + actualTone;
- }
-
- let emojiFound = false;
-
- for (let key in RocketChat.emoji.packages[emojiPackage].emojisByCategory) {
- if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(key)) {
- let contents = RocketChat.emoji.packages[emojiPackage].emojisByCategory[key];
- if (contents.indexOf(emoji) !== -1) {
- emojiFound = true;
- break;
- }
- }
- }
-
- if (emojiFound) {
- let image = RocketChat.emoji.packages[emojiPackage].render(`:${emoji}${tone}:`);
- html += `${image} `;
- }
- }
- }
-
- return html;
-}
-
-Template.emojiPicker.helpers({
- category() {
- let categories = [];
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- for (let key in RocketChat.emoji.packages[emojiPackage].emojisByCategory) {
- if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(key)) {
- categories.push(key);
- }
- }
- }
- }
- return categories;
- },
- emojiByCategory(category) {
- let emojisByCategory = [];
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- if (RocketChat.emoji.packages[emojiPackage].emojisByCategory.hasOwnProperty(category)) {
- emojisByCategory = emojisByCategory.concat(RocketChat.emoji.packages[emojiPackage].emojisByCategory[category]);
- }
- }
- }
- return emojisByCategory;
- },
- isVisible(category) {
- return Template.instance().currentCategory.get() === category ? 'visible' : '';
- },
- emojiList(category) {
- const t = Template.instance();
- const searchTerm = t.currentSearchTerm.get();
-
- //clear dynamic categories to prevent duplication issues
- if (category === 'recent' || category === 'rocket') {
- $(`.${category}.emoji-list`).empty();
- }
-
- if (searchTerm.length > 0) {
- return getEmojisBySearchTerm(searchTerm);
- } else {
- return getEmojisByCategory(category);
- }
- },
- currentTone() {
- return 'tone-' + Template.instance().tone;
- },
- /**
- * Returns true if a given emoji category is active
- *
- * @param {string} category hash
- * @return {boolean} true if active, false otherwise
- */
- activeCategory(category) {
- return Template.instance().currentCategory.get() === category ? 'active' : '';
- },
- categoryName: categoryName,
- /**
- * Returns currently active emoji category hash
- *
- * @return {string} category hash
- */
- currentCategory() {
- const t = Template.instance();
- const hash = t.currentCategory.get();
- const searchTerm = t.currentSearchTerm.get();
-
- if (searchTerm.length > 0) {
- return TAPi18n.__('Search');
- } else {
- return categoryName(hash);
- }
- }
-});
-
-Template.emojiPicker.events({
- 'click .emoji-picker'(event) {
- event.stopPropagation();
- event.preventDefault();
- },
- 'click .category-link'(event, instance) {
- event.stopPropagation();
- event.preventDefault();
-
- instance.$('.emoji-filter .search').val('').change();
- instance.$('.emoji-filter .search').focus();
-
- instance.currentCategory.set(event.currentTarget.hash.substr(1));
-
- return false;
- },
- 'click .change-tone > a'(event, instance) {
- event.stopPropagation();
- event.preventDefault();
-
- instance.$('.tone-selector').toggleClass('show');
- },
- 'click .tone-selector .tone'(event, instance) {
- event.stopPropagation();
- event.preventDefault();
-
- let tone = parseInt(event.currentTarget.dataset.tone);
- let newTone;
-
- if (tone > 0) {
- newTone = '_tone' + tone;
- } else {
- newTone = '';
- }
-
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- if (RocketChat.emoji.packages[emojiPackage].hasOwnProperty('toneList')) {
- for (let emoji in RocketChat.emoji.packages[emojiPackage].toneList) {
- if (RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
- $('.emoji-'+emoji).html(RocketChat.emoji.packages[emojiPackage].render(':' + emoji + newTone + ':'));
- }
- }
- }
- }
- }
-
- RocketChat.EmojiPicker.setTone(tone);
-
- instance.setCurrentTone(tone);
-
- $('.tone-selector').toggleClass('show');
- },
- 'click .emoji-list li'(event, instance) {
- event.stopPropagation();
-
- let emoji = event.currentTarget.dataset.emoji;
- let actualTone = instance.tone;
- let tone = '';
-
- for (let emojiPackage in RocketChat.emoji.packages) {
- if (RocketChat.emoji.packages.hasOwnProperty(emojiPackage)) {
- if (actualTone > 0 && RocketChat.emoji.packages[emojiPackage].toneList.hasOwnProperty(emoji)) {
- tone = '_tone' + actualTone;
- }
- }
- }
-
- const input = $('.emoji-filter input.search');
- if (input) {
- input.val('');
- }
- instance.currentSearchTerm.set('');
-
- RocketChat.EmojiPicker.pickEmoji(emoji + tone);
- },
- 'keydown .emoji-filter .search'(event) {
- if (event.keyCode === 13) {
- event.preventDefault();
- }
- },
- 'keyup .emoji-filter .search, change .emoji-filter .search'(event, instance) {
- const value = event.target.value.trim();
- const cst = instance.currentSearchTerm;
- if (value === cst.get()) {
- return;
- }
- cst.set(value);
- }
-});
-
-Template.emojiPicker.onCreated(function() {
- this.tone = RocketChat.EmojiPicker.getTone();
- let recent = RocketChat.EmojiPicker.getRecent();
-
- this.currentCategory = new ReactiveVar(recent.length > 0 ? 'recent' : 'people');
- this.currentSearchTerm = new ReactiveVar('');
-
- recent.forEach((emoji) => {
- RocketChat.emoji.packages.base.emojisByCategory.recent.push(emoji);
- });
-
- this.setCurrentTone = (newTone) => {
- $('.current-tone').removeClass('tone-' + this.tone);
- $('.current-tone').addClass('tone-' + newTone);
- this.tone = newTone;
- };
-});
diff --git a/packages/rocketchat-emoji/emojiPicker.less b/packages/rocketchat-emoji/emojiPicker.less
deleted file mode 100644
index 05454ae247838..0000000000000
--- a/packages/rocketchat-emoji/emojiPicker.less
+++ /dev/null
@@ -1,175 +0,0 @@
-@import "lesshat.less";
-
-.emoji-picker-icon {
- cursor: pointer;
- font-size: 18px;
-
- &::before {
- transition: transform 0.2s ease;
- }
-
- &:hover {
- &::before {
- .transform(scale(1.2));
- }
- }
-}
-
-.emoji-picker {
- width: 100%;
- max-width: 365px;
- border-radius: 5px;
- box-shadow:
- 0 1px 1px 0 rgba(0, 0, 0, 0.2),
- 0 2px 10px 0 rgba(0, 0, 0, 0.16);
- position: absolute;
- display: none;
-
- &.show {
- display: block;
- }
-
- .filter {
- box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2);
- }
-
- .filter-list {
- display: flex;
- width: 100%;
- padding: 0 5px;
- }
-
- .filter-item {
- padding: 6px 0;
- border-style: solid;
- border-width: 0 0 2px;
- display: flex;
- justify-content: center;
- flex-grow: 1;
-
- .category-icon {
- font-size: 20px;
- }
- }
-
- .current-category-header {
- padding: 3px 5px;
- }
-
- .emojis {
- height: 160px;
- overflow-y: auto;
- padding: 3px 0 0 2px;
-
- .emoji-list {
- display: none;
-
- li {
- display: inline-block;
- margin: 2px;
- padding: 4px 2px 2px;
- border-radius: 4px;
- cursor: pointer;
- transition: transform 0.2s ease;
-
- &:hover {
- .transform(scale(1.2));
- background-color: #dddddd;
- }
- }
-
- &.visible {
- display: block;
- }
- }
- }
-}
-
-.emoji-top {
- display: flex;
- align-items: center;
- padding: 5px;
-
- .emoji-filter {
- width: 90%;
- margin-bottom: 0;
- }
-
- .change-tone {
- width: 10%;
- display: flex;
- justify-content: center;
- position: relative;
-
- a {
- position: relative;
- z-index: 10;
- }
-
- .current-tone {
- display: block;
- width: 20px;
- height: 20px;
- border-radius: 10px;
- }
-
- .tone-selector {
- position: absolute;
- border-radius: 4px;
- box-shadow:
- 0 1px 1px 0 rgba(0, 0, 0, 0.2),
- 0 2px 10px 0 rgba(0, 0, 0, 0.16);
- padding: 4px 2px;
- top: 25px;
- z-index: 1;
- transition: transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease;
- .transform(translateY(-20px));
- opacity: 0;
- visibility: hidden;
-
- &.show {
- .transform(translateY(0px));
- opacity: 1;
- display: block;
- visibility: visible;
- }
-
- li {
- display: block;
- padding: 0 4px;
- }
-
- span {
- display: inline-block;
- width: 20px;
- height: 20px;
- border-radius: 10px;
- transition: transform 0.2s ease;
- }
- }
-
- .tone-0 {
- background-color: #ffcf11;
- }
-
- .tone-1 {
- background-color: #fae3c3;
- }
-
- .tone-2 {
- background-color: #e2cfa1;
- }
-
- .tone-3 {
- background-color: #dba373;
- }
-
- .tone-4 {
- background-color: #a88054;
- }
-
- .tone-5 {
- background-color: #5f4e43;
- }
- }
-}
diff --git a/packages/rocketchat-emoji/lesshat.less b/packages/rocketchat-emoji/lesshat.less
deleted file mode 100644
index 7c9f0ae86a267..0000000000000
--- a/packages/rocketchat-emoji/lesshat.less
+++ /dev/null
@@ -1,17 +0,0 @@
-// lesshat - The best mixin library in the world
-//
-// version: v4.1.0 (2016-07-19)
-
-.calc(...) {
- @process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- @state: 1; -lh-property: @process;
-}
-
-.transform(...) {
- @process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: @process;
- -moz-transform: @process;
- -ms-transform: @process;
- -o-transform: @process;
- transform: @process;
-}
diff --git a/packages/rocketchat-emoji/lib/EmojiPicker.js b/packages/rocketchat-emoji/lib/EmojiPicker.js
deleted file mode 100644
index fbb47a9caacc3..0000000000000
--- a/packages/rocketchat-emoji/lib/EmojiPicker.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/* globals Blaze, isSetNotNull, Template */
-RocketChat.EmojiPicker = {
- width: 390,
- height: 238,
- initiated: false,
- input: null,
- source: null,
- recent: [],
- tone: null,
- opened: false,
- pickCallback: null,
- init() {
- if (this.initiated) {
- return;
- }
- this.initiated = true;
-
- this.recent = window.localStorage.getItem('emoji.recent') ? window.localStorage.getItem('emoji.recent').split(',') : [];
- this.tone = window.localStorage.getItem('emoji.tone') || 0;
-
- Blaze.render(Template.emojiPicker, document.body);
-
- $(document).click((event) => {
- if (!this.opened) {
- return;
- }
- if (!$(event.target).closest('.emoji-picker').length && !$(event.target).is('.emoji-picker')) {
- if (this.opened) {
- this.close();
- }
- }
- });
-
- $(window).resize(_.debounce(() => {
- if (!this.opened) {
- return;
- }
- this.setPosition();
- }, 300));
- },
- isOpened() {
- return this.opened;
- },
- setTone(tone) {
- this.tone = tone;
- window.localStorage.setItem('emoji.tone', tone);
- },
- getTone() {
- return this.tone;
- },
- getRecent() {
- return this.recent;
- },
- setPosition() {
- let sourcePos = $(this.source).offset();
- let left = sourcePos.left;
- let top = (sourcePos.top - this.height - 5);
- let cssProperties = {
- top: top,
- left: left
- };
-
- if (top < 0) {
- cssProperties.top = 10;
- }
-
- if (left < 35) {
- cssProperties.left = 0;
- } else {
- let windowSize = $(window).width();
- let pickerWidth = $('.emoji-picker').width();
-
- if (left + pickerWidth > windowSize) {
- let emojiButtonSize = $('.reaction-message.message-action').outerWidth();
- cssProperties.left = left - pickerWidth + emojiButtonSize;
- }
- }
-
- return $('.emoji-picker').css(cssProperties);
- },
- open(source, callback) {
- if (!this.initiated) {
- this.init();
- }
- this.pickCallback = callback;
- this.source = source;
-
- const containerEl = this.setPosition();
- containerEl.addClass('show');
-
- const emojiInput = containerEl.find('.emoji-filter input.search');
- if (emojiInput) {
- emojiInput.focus();
- }
- this.opened = true;
- },
- close() {
- $('.emoji-picker').removeClass('show');
- this.opened = false;
- },
- pickEmoji(emoji) {
- this.pickCallback(emoji);
-
- this.close();
- this.addRecent(emoji);
- },
- addRecent(emoji) {
- let pos = this.recent.indexOf(emoji);
-
- if (pos !== -1) {
- this.recent.splice(pos, 1);
- }
-
- this.recent.unshift(emoji);
-
- window.localStorage.setItem('emoji.recent', this.recent);
- RocketChat.emoji.packages.base.emojisByCategory.recent = this.recent;
-
- this.updateRecent();
- },
- updateRecent() {
- let total = RocketChat.emoji.packages.base.emojisByCategory.recent.length;
- let html = '';
- for (var i = 0; i < total; i++) {
- let emoji = RocketChat.emoji.packages.base.emojisByCategory.recent[i];
-
- if (isSetNotNull(() => RocketChat.emoji.list[`:${emoji}:`])) {
- let emojiPackage = RocketChat.emoji.list[`:${emoji}:`].emojiPackage;
- let renderedEmoji = RocketChat.emoji.packages[emojiPackage].render(`:${emoji}:`);
- html += `${renderedEmoji} `;
- } else {
- this.recent = _.without(this.recent, emoji);
- }
- }
- $('.recent.emoji-list').empty().append(html);
- }
-};
diff --git a/packages/rocketchat-emoji/lib/emojiRenderer.js b/packages/rocketchat-emoji/lib/emojiRenderer.js
deleted file mode 100644
index 760ee075d5e01..0000000000000
--- a/packages/rocketchat-emoji/lib/emojiRenderer.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* globals HTML, isSetNotNull, renderEmoji:true */
-renderEmoji = function(emoji) {
- if (isSetNotNull(() => RocketChat.emoji.list[emoji].emojiPackage)) {
- let emojiPackage = RocketChat.emoji.list[emoji].emojiPackage;
- return RocketChat.emoji.packages[emojiPackage].render(emoji);
- }
-};
-
-Blaze.registerHelper('renderEmoji', renderEmoji);
-
-Template.registerHelper('renderEmoji', new Template('renderEmoji', function() {
- let view = this;
- let emoji = Blaze.getData(view);
-
- if (isSetNotNull(() => RocketChat.emoji.list[emoji].emojiPackage)) {
- let emojiPackage = RocketChat.emoji.list[emoji].emojiPackage;
- return new HTML.Raw(RocketChat.emoji.packages[emojiPackage].render(emoji));
- }
-
- return '';
-}));
-
-/* exported renderEmoji */
diff --git a/packages/rocketchat-emoji/package.js b/packages/rocketchat-emoji/package.js
index f8cf84d88be23..7b3e3f3d1a611 100644
--- a/packages/rocketchat-emoji/package.js
+++ b/packages/rocketchat-emoji/package.js
@@ -8,28 +8,24 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'underscore',
'templating',
- 'less',
'rocketchat:lib',
+ 'rocketchat:theme',
'rocketchat:ui-message'
]);
- api.addFiles('function-isSet.js', 'client');
- api.addFiles('rocketchat.js', 'client');
+ api.addFiles('client/function-isSet.js', 'client');
+ api.addFiles('client/rocketchat.js');
- api.addFiles('emojiParser.js', 'client');
+ api.addFiles('client/emojiParser.js', 'client');
- api.addFiles('emojiPicker.html', 'client');
- api.addFiles('emojiPicker.js', 'client');
- api.addFiles('emojiPicker.less', 'client');
+ api.addFiles('client/emojiPicker.html', 'client');
+ api.addFiles('client/emojiPicker.js', 'client');
- api.addFiles('emoji.css', 'client');
-
- api.addFiles('lib/emojiRenderer.js', 'client');
- api.addFiles('lib/EmojiPicker.js', 'client');
- api.addFiles('emojiButton.js', 'client');
- api.addFiles('keyboardFix.js', 'client');
+ api.addFiles('client/lib/emojiRenderer.js', 'client');
+ api.addFiles('client/lib/EmojiPicker.js', 'client');
+ api.addFiles('client/emojiButton.js', 'client');
+ api.addFiles('client/keyboardFix.js', 'client');
api.export('renderEmoji');
});
diff --git a/packages/rocketchat-emoji/rocketchat.js b/packages/rocketchat-emoji/rocketchat.js
deleted file mode 100644
index 878ae629f0535..0000000000000
--- a/packages/rocketchat-emoji/rocketchat.js
+++ /dev/null
@@ -1,15 +0,0 @@
-RocketChat.emoji = {
- packages: {
- base: {
- emojiCategories: { recent: TAPi18n.__('Frequently_Used') },
- emojisByCategory: {
- recent: []
- },
- toneList: {},
- render(html) {
- return html;
- }
- }
- },
- list: {}
-};
diff --git a/packages/rocketchat-error-handler/server/lib/RocketChat.ErrorHandler.js b/packages/rocketchat-error-handler/server/lib/RocketChat.ErrorHandler.js
index 701f1134308d9..276e3c6ddd444 100644
--- a/packages/rocketchat-error-handler/server/lib/RocketChat.ErrorHandler.js
+++ b/packages/rocketchat-error-handler/server/lib/RocketChat.ErrorHandler.js
@@ -26,7 +26,7 @@ class ErrorHandler {
}));
const self = this;
- let originalMeteorDebug = Meteor._debug;
+ const originalMeteorDebug = Meteor._debug;
Meteor._debug = function(message, stack) {
if (!self.reporting) {
return originalMeteorDebug.call(this, message, stack);
@@ -38,7 +38,7 @@ class ErrorHandler {
getRoomId(roomName) {
roomName = roomName.replace('#');
- let room = RocketChat.models.Rooms.findOneByName(roomName, { fields: { _id: 1, t: 1 } });
+ const room = RocketChat.models.Rooms.findOneByName(roomName, { fields: { _id: 1, t: 1 } });
if (room && (room.t === 'c' || room.t === 'p')) {
return room._id;
} else {
@@ -49,10 +49,10 @@ class ErrorHandler {
trackError(message, stack) {
if (this.reporting && this.rid && this.lastError !== message) {
this.lastError = message;
- let user = RocketChat.models.Users.findOneById('rocket.cat');
+ const user = RocketChat.models.Users.findOneById('rocket.cat');
if (stack) {
- message = message + '\n```\n' + stack + '\n```';
+ message = `${ message }\n\`\`\`\n${ stack }\n\`\`\``;
}
RocketChat.sendMessage(user, { msg: message }, { _id: this.rid });
diff --git a/packages/rocketchat-favico/favico.js b/packages/rocketchat-favico/client/favico.js
similarity index 99%
rename from packages/rocketchat-favico/favico.js
rename to packages/rocketchat-favico/client/favico.js
index 1cef87bd2c1fa..00f6f5e60fa31 100644
--- a/packages/rocketchat-favico/favico.js
+++ b/packages/rocketchat-favico/client/favico.js
@@ -22,6 +22,7 @@
* win: top
* });
*/
+/* eslint-disable */
(function() {
var Favico = (function(opt) {
diff --git a/packages/rocketchat-favico/package.js b/packages/rocketchat-favico/package.js
index 90c885f58e633..3ce2a3443e4ac 100644
--- a/packages/rocketchat-favico/package.js
+++ b/packages/rocketchat-favico/package.js
@@ -5,10 +5,5 @@ Package.describe({
});
Package.onUse(function(api) {
- api.use([
- 'coffeescript'
- ], 'client');
- api.addFiles([
- 'favico.js'
- ], 'client');
+ api.addFiles('client/favico.js', 'client');
});
diff --git a/packages/rocketchat-file-upload/.npm/package/.gitignore b/packages/rocketchat-file-upload/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-file-upload/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-file-upload/.npm/package/README b/packages/rocketchat-file-upload/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-file-upload/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-file-upload/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-file-upload/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 62e1770f2f683..0000000000000
--- a/packages/rocketchat-file-upload/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "dependencies": {
- "filesize": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.3.0.tgz",
- "from": "filesize@3.3.0"
- },
- "mime-db": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz",
- "from": "mime-db@>=1.23.0 <1.24.0"
- },
- "mime-types": {
- "version": "2.1.11",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
- "from": "mime-types@2.1.11"
- }
- }
-}
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js b/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js
deleted file mode 100644
index 61f1ae64d29ee..0000000000000
--- a/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* globals FileUpload, FileUploadBase, Slingshot */
-
-FileUpload.AmazonS3 = class FileUploadAmazonS3 extends FileUploadBase {
- constructor(meta, file) {
- super(meta, file);
- this.uploader = new Slingshot.Upload('rocketchat-uploads', { rid: meta.rid });
- }
-
- start() {
- this.uploader.send(this.file, (error, downloadUrl) => {
- if (this.computation) {
- this.computation.stop();
- }
-
- if (error) {
- let uploading = Session.get('uploading');
- if (!Array.isArray(uploading)) {
- uploading = [];
- }
-
- const item = _.findWhere(uploading, {
- id: this.id
- });
- if (_.isObject(item)) {
- item.error = error.error;
- item.percentage = 0;
- } else {
- uploading.push({
- error: error.error,
- percentage: 0
- });
- }
- Session.set('uploading', uploading);
- } else {
- const file = _.pick(this.meta, 'type', 'size', 'name', 'identify', 'description');
- file._id = downloadUrl.substr(downloadUrl.lastIndexOf('/') + 1);
- file.url = downloadUrl;
-
- Meteor.call('sendFileMessage', this.meta.rid, 's3', file, () => {
- Meteor.setTimeout(() => {
- const uploading = Session.get('uploading');
- if (uploading !== null) {
- const item = _.findWhere(uploading, {
- id: this.id
- });
- return Session.set('uploading', _.without(uploading, item));
- }
- }, 2000);
- });
- }
- });
-
- this.computation = Tracker.autorun(() => {
- this.onProgress(this.uploader.progress());
- });
- }
-
- onProgress() {}
-
- stop() {
- if (this.uploader && this.uploader.xhr) {
- this.uploader.xhr.abort();
- }
- }
-};
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js b/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js
deleted file mode 100644
index 2c6110258747a..0000000000000
--- a/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* globals FileUploadBase, UploadFS, FileUpload:true, FileSystemStore:true */
-
-FileSystemStore = new UploadFS.store.Local({
- collection: RocketChat.models.Uploads.model,
- name: 'fileSystem',
- filter: new UploadFS.Filter({
- onCheck: FileUpload.validateFileUpload
- })
-});
-
-FileUpload.FileSystem = class FileUploadFileSystem extends FileUploadBase {
- constructor(meta, file) {
- super(meta, file);
- this.handler = new UploadFS.Uploader({
- store: FileSystemStore,
- data: file,
- file: meta,
- onError: (err) => {
- var uploading = Session.get('uploading');
- if (uploading != null) {
- let item = _.findWhere(uploading, {
- id: this.id
- });
- if (item != null) {
- item.error = err.reason;
- item.percentage = 0;
- }
- return Session.set('uploading', uploading);
- }
- },
- onComplete: (fileData) => {
- var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify', 'description');
-
- file.url = fileData.url.replace(Meteor.absoluteUrl(), '/');
-
- Meteor.call('sendFileMessage', this.meta.rid, null, file, () => {
- Meteor.setTimeout(() => {
- var uploading = Session.get('uploading');
- if (uploading != null) {
- let item = _.findWhere(uploading, {
- id: this.id
- });
- return Session.set('uploading', _.without(uploading, item));
- }
- }, 2000);
- });
- }
- });
-
- this.handler.onProgress = (file, progress) => {
- this.onProgress(progress);
- };
- }
-
- start() {
- return this.handler.start();
- }
-
- onProgress() {}
-
- stop() {
- return this.handler.stop();
- }
-};
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js b/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js
deleted file mode 100644
index ab48cc8a116df..0000000000000
--- a/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* globals FileUploadBase, UploadFS, FileUpload:true */
-FileUpload.GridFS = class FileUploadGridFS extends FileUploadBase {
- constructor(meta, file) {
- super(meta, file);
- this.handler = new UploadFS.Uploader({
- store: Meteor.fileStore,
- data: file,
- file: meta,
- onError: (err) => {
- var uploading = Session.get('uploading');
- if (uploading != null) {
- let item = _.findWhere(uploading, {
- id: this.id
- });
- if (item != null) {
- item.error = err.reason;
- item.percentage = 0;
- }
- return Session.set('uploading', uploading);
- }
- },
- onComplete: (fileData) => {
- var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify', 'description');
-
- file.url = fileData.url.replace(Meteor.absoluteUrl(), '/');
-
- Meteor.call('sendFileMessage', this.meta.rid, null, file, () => {
- Meteor.setTimeout(() => {
- var uploading = Session.get('uploading');
- if (uploading != null) {
- let item = _.findWhere(uploading, {
- id: this.id
- });
- return Session.set('uploading', _.without(uploading, item));
- }
- }, 2000);
- });
- }
- });
-
- this.handler.onProgress = (file, progress) => {
- this.onProgress(progress);
- };
- }
-
- start() {
- return this.handler.start();
- }
-
- onProgress() {}
-
- stop() {
- return this.handler.stop();
- }
-};
diff --git a/packages/rocketchat-file-upload/client/lib/fileUploadHandler.js b/packages/rocketchat-file-upload/client/lib/fileUploadHandler.js
index 71f5fbdf15196..73474ab5181f3 100644
--- a/packages/rocketchat-file-upload/client/lib/fileUploadHandler.js
+++ b/packages/rocketchat-file-upload/client/lib/fileUploadHandler.js
@@ -1,10 +1,36 @@
-/* globals FileUpload, fileUploadHandler:true */
+/* globals FileUploadBase, UploadFS, fileUploadHandler:true */
/* exported fileUploadHandler */
-fileUploadHandler = (meta, file) => {
- const storageType = RocketChat.settings.get('FileUpload_Storage_Type');
+new UploadFS.Store({
+ collection: RocketChat.models.Uploads.model,
+ name: 'Uploads',
+ filter: new UploadFS.Filter({
+ onCheck: FileUpload.validateFileUpload
+ })
+});
- if (FileUpload[storageType] !== undefined) {
- return new FileUpload[storageType](meta, file);
+new UploadFS.Store({
+ collection: RocketChat.models.Avatars.model,
+ name: 'Avatars',
+ filter: new UploadFS.Filter({
+ onCheck: FileUpload.validateFileUpload
+ })
+});
+
+
+fileUploadHandler = (directive, meta, file) => {
+ const store = UploadFS.getStore(directive);
+
+ if (store) {
+ return new FileUploadBase(store, meta, file);
+ } else {
+ console.error('Invalid file store', directive);
}
};
+
+Tracker.autorun(function() {
+ if (Meteor.userId()) {
+ document.cookie = `rc_uid=${ escape(Meteor.userId()) }; path=/`;
+ document.cookie = `rc_token=${ escape(Accounts._storedLoginToken()) }; path=/`;
+ }
+});
diff --git a/packages/rocketchat-file-upload/globalFileRestrictions.js b/packages/rocketchat-file-upload/globalFileRestrictions.js
index bc07450761821..ca98fd5a6f3b7 100644
--- a/packages/rocketchat-file-upload/globalFileRestrictions.js
+++ b/packages/rocketchat-file-upload/globalFileRestrictions.js
@@ -2,25 +2,28 @@
import filesize from 'filesize';
-Slingshot.fileRestrictions('rocketchat-uploads', {
- authorize: function(file/*, metaContext*/) {
+const slingShotConfig = {
+ authorize(file/*, metaContext*/) {
+ //Deny uploads if user is not logged in.
+ if (!this.userId) {
+ throw new Meteor.Error('login-required', 'Please login before posting files');
+ }
+
if (!RocketChat.fileUploadIsValidContentType(file.type)) {
throw new Meteor.Error(TAPi18n.__('error-invalid-file-type'));
}
const maxFileSize = RocketChat.settings.get('FileUpload_MaxFileSize');
- if (maxFileSize && maxFileSize < file.size) {
+ if (maxFileSize >= -1 && maxFileSize < file.size) {
throw new Meteor.Error(TAPi18n.__('File_exceeds_allowed_size_of_bytes', { size: filesize(maxFileSize) }));
}
- //Deny uploads if user is not logged in.
- if (!this.userId) {
- throw new Meteor.Error('login-require', 'Please login before posting files');
- }
-
return true;
},
maxSize: 0,
allowedFileTypes: null
-});
+};
+
+Slingshot.fileRestrictions('rocketchat-uploads', slingShotConfig);
+Slingshot.fileRestrictions('rocketchat-uploads-gs', slingShotConfig);
diff --git a/packages/rocketchat-file-upload/lib/FileUpload.js b/packages/rocketchat-file-upload/lib/FileUpload.js
index f4fe43e253c14..006b2e37a1702 100644
--- a/packages/rocketchat-file-upload/lib/FileUpload.js
+++ b/packages/rocketchat-file-upload/lib/FileUpload.js
@@ -30,14 +30,15 @@ FileUpload = {
throw new Meteor.Error('error-direct-message-file-upload-not-allowed', reason);
}
- if (file.size > maxFileSize) {
+ // -1 maxFileSize means there is no limit
+ if (maxFileSize >= -1 && file.size > maxFileSize) {
const reason = TAPi18n.__('File_exceeds_allowed_size_of_bytes', {
size: filesize(maxFileSize)
}, user.language);
throw new Meteor.Error('error-file-too-large', reason);
}
- if (parseInt(maxFileSize) > 0) {
+ if (maxFileSize > 0) {
if (file.size > maxFileSize) {
const reason = TAPi18n.__('File_exceeds_allowed_size_of_bytes', {
size: filesize(maxFileSize)
@@ -56,5 +57,9 @@ FileUpload = {
};
RocketChat.settings.get('FileUpload_MaxFileSize', function(key, value) {
- maxFileSize = value;
-});
\ No newline at end of file
+ try {
+ maxFileSize = parseInt(value);
+ } catch (e) {
+ maxFileSize = RocketChat.models.Settings.findOneById('FileUpload_MaxFileSize').packageValue;
+ }
+});
diff --git a/packages/rocketchat-file-upload/lib/FileUploadBase.js b/packages/rocketchat-file-upload/lib/FileUploadBase.js
index 9f8e4e6a1cf38..3e2b166547f59 100644
--- a/packages/rocketchat-file-upload/lib/FileUploadBase.js
+++ b/packages/rocketchat-file-upload/lib/FileUploadBase.js
@@ -1,24 +1,26 @@
/* globals FileUploadBase:true, UploadFS */
/* exported FileUploadBase */
+import _ from 'underscore';
UploadFS.config.defaultStorePermissions = new UploadFS.StorePermissions({
- insert: function(userId/*, doc*/) {
- return userId;
+ insert(userId, doc) {
+ return userId || (doc && doc.message_id && doc.message_id.indexOf('slack-') === 0); // allow inserts from slackbridge (message_id = slack-timestamp-milli)
},
- update: function(userId, doc) {
- return userId === doc.userId;
+ update(userId, doc) {
+ return RocketChat.authz.hasPermission(Meteor.userId(), 'delete-message', doc.rid) || (RocketChat.settings.get('Message_AllowDeleting') && userId === doc.userId);
},
- remove: function(userId, doc) {
+ remove(userId, doc) {
return RocketChat.authz.hasPermission(Meteor.userId(), 'delete-message', doc.rid) || (RocketChat.settings.get('Message_AllowDeleting') && userId === doc.userId);
}
});
FileUploadBase = class FileUploadBase {
- constructor(meta, file) {
+ constructor(store, meta, file) {
this.id = Random.id();
this.meta = meta;
this.file = file;
+ this.store = store;
}
getProgress() {
@@ -29,11 +31,32 @@ FileUploadBase = class FileUploadBase {
return this.meta.name;
}
- start() {
-
+ start(callback) {
+ this.handler = new UploadFS.Uploader({
+ store: this.store,
+ data: this.file,
+ file: this.meta,
+ onError: (err) => {
+ return callback(err);
+ },
+ onComplete: (fileData) => {
+ const file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify', 'description');
+
+ file.url = fileData.url.replace(Meteor.absoluteUrl(), '/');
+ return callback(null, file, this.store.options.name);
+ }
+ });
+
+ this.handler.onProgress = (file, progress) => {
+ this.onProgress(progress);
+ };
+
+ return this.handler.start();
}
- stop() {
+ onProgress() {}
+ stop() {
+ return this.handler.stop();
}
};
diff --git a/packages/rocketchat-file-upload/package.js b/packages/rocketchat-file-upload/package.js
index 55491f0e8229d..b1ceb42f871d0 100644
--- a/packages/rocketchat-file-upload/package.js
+++ b/packages/rocketchat-file-upload/package.js
@@ -11,12 +11,13 @@ Package.onUse(function(api) {
api.use('ecmascript');
api.use('rocketchat:file');
api.use('jalik:ufs');
+ api.use('jalik:ufs-gridfs');
api.use('jalik:ufs-local@0.2.5');
api.use('edgee:slingshot');
- api.use('peerlibrary:aws-sdk');
+ api.use('ostrio:cookies');
api.use('rocketchat:lib');
api.use('random');
- api.use('underscore');
+ api.use('accounts-base');
api.use('tracker');
api.use('webapp');
@@ -26,26 +27,19 @@ Package.onUse(function(api) {
api.addFiles('lib/FileUpload.js');
api.addFiles('lib/FileUploadBase.js');
- api.addFiles('client/lib/FileUploadFileSystem.js', 'client');
api.addFiles('client/lib/fileUploadHandler.js', 'client');
- api.addFiles('client/lib/FileUploadAmazonS3.js', 'client');
- api.addFiles('client/lib/FileUploadGridFS.js', 'client');
api.addFiles('server/lib/FileUpload.js', 'server');
+ api.addFiles('server/lib/proxy.js', 'server');
api.addFiles('server/lib/requests.js', 'server');
- api.addFiles('server/config/configFileUploadAmazonS3.js', 'server');
- api.addFiles('server/config/configFileUploadFileSystem.js', 'server');
- api.addFiles('server/config/configFileUploadGridFS.js', 'server');
+ api.addFiles('server/config/_configUploadStorage.js', 'server');
api.addFiles('server/methods/sendFileMessage.js', 'server');
+ api.addFiles('server/methods/getS3FileUrl.js', 'server');
api.addFiles('server/startup/settings.js', 'server');
api.export('fileUploadHandler');
api.export('FileUpload');
});
-
-Npm.depends({
- 'filesize': '3.3.0'
-});
diff --git a/packages/rocketchat-file-upload/server/config/AmazonS3.js b/packages/rocketchat-file-upload/server/config/AmazonS3.js
new file mode 100644
index 0000000000000..bc80d64b233dc
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/AmazonS3.js
@@ -0,0 +1,77 @@
+/* globals FileUpload */
+
+import _ from 'underscore';
+import { FileUploadClass } from '../lib/FileUpload';
+import '../../ufs/AmazonS3/server.js';
+import http from 'http';
+import https from 'https';
+
+const get = function(file, req, res) {
+ const fileUrl = this.store.getRedirectURL(file);
+
+ if (fileUrl) {
+ if (RocketChat.settings.get('FileUpload_S3_Proxy')) {
+ const request = /^https:/.test(fileUrl) ? https : http;
+ request.get(fileUrl, fileRes => fileRes.pipe(res));
+ } else {
+ res.setHeader('Location', fileUrl);
+ res.writeHead(302);
+ res.end();
+ }
+ } else {
+ res.end();
+ }
+};
+
+const AmazonS3Uploads = new FileUploadClass({
+ name: 'AmazonS3:Uploads',
+ get
+ // store setted bellow
+});
+
+const AmazonS3Avatars = new FileUploadClass({
+ name: 'AmazonS3:Avatars',
+ get
+ // store setted bellow
+});
+
+const configure = _.debounce(function() {
+ const Bucket = RocketChat.settings.get('FileUpload_S3_Bucket');
+ const Acl = RocketChat.settings.get('FileUpload_S3_Acl');
+ const AWSAccessKeyId = RocketChat.settings.get('FileUpload_S3_AWSAccessKeyId');
+ const AWSSecretAccessKey = RocketChat.settings.get('FileUpload_S3_AWSSecretAccessKey');
+ const URLExpiryTimeSpan = RocketChat.settings.get('FileUpload_S3_URLExpiryTimeSpan');
+ const Region = RocketChat.settings.get('FileUpload_S3_Region');
+ const SignatureVersion = RocketChat.settings.get('FileUpload_S3_SignatureVersion');
+ const ForcePathStyle = RocketChat.settings.get('FileUpload_S3_ForcePathStyle');
+ // const CDN = RocketChat.settings.get('FileUpload_S3_CDN');
+ const BucketURL = RocketChat.settings.get('FileUpload_S3_BucketURL');
+
+ if (!Bucket || !AWSAccessKeyId || !AWSSecretAccessKey) {
+ return;
+ }
+
+ const config = {
+ connection: {
+ accessKeyId: AWSAccessKeyId,
+ secretAccessKey: AWSSecretAccessKey,
+ signatureVersion: SignatureVersion,
+ s3ForcePathStyle: ForcePathStyle,
+ params: {
+ Bucket,
+ ACL: Acl
+ },
+ region: Region
+ },
+ URLExpiryTimeSpan
+ };
+
+ if (BucketURL) {
+ config.connection.endpoint = BucketURL;
+ }
+
+ AmazonS3Uploads.store = FileUpload.configureUploadsStore('AmazonS3', AmazonS3Uploads.name, config);
+ AmazonS3Avatars.store = FileUpload.configureUploadsStore('AmazonS3', AmazonS3Avatars.name, config);
+}, 500);
+
+RocketChat.settings.get(/^FileUpload_S3_/, configure);
diff --git a/packages/rocketchat-file-upload/server/config/FileSystem.js b/packages/rocketchat-file-upload/server/config/FileSystem.js
new file mode 100644
index 0000000000000..096df87e4dee0
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/FileSystem.js
@@ -0,0 +1,70 @@
+/* globals FileUpload, UploadFS */
+
+import _ from 'underscore';
+import fs from 'fs';
+import { FileUploadClass } from '../lib/FileUpload';
+
+const FileSystemUploads = new FileUploadClass({
+ name: 'FileSystem:Uploads',
+ // store setted bellow
+
+ get(file, req, res) {
+ const filePath = this.store.getFilePath(file._id, file);
+
+ try {
+ const stat = Meteor.wrapAsync(fs.stat)(filePath);
+
+ if (stat && stat.isFile()) {
+ file = FileUpload.addExtensionTo(file);
+ res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${ encodeURIComponent(file.name) }`);
+ res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
+ res.setHeader('Content-Type', file.type);
+ res.setHeader('Content-Length', file.size);
+
+ this.store.getReadStream(file._id, file).pipe(res);
+ }
+ } catch (e) {
+ res.writeHead(404);
+ res.end();
+ return;
+ }
+ }
+});
+
+const FileSystemAvatars = new FileUploadClass({
+ name: 'FileSystem:Avatars',
+ // store setted bellow
+
+ get(file, req, res) {
+ const filePath = this.store.getFilePath(file._id, file);
+
+ try {
+ const stat = Meteor.wrapAsync(fs.stat)(filePath);
+
+ if (stat && stat.isFile()) {
+ file = FileUpload.addExtensionTo(file);
+
+ this.store.getReadStream(file._id, file).pipe(res);
+ }
+ } catch (e) {
+ res.writeHead(404);
+ res.end();
+ return;
+ }
+ }
+});
+
+
+const createFileSystemStore = _.debounce(function() {
+ const options = {
+ path: RocketChat.settings.get('FileUpload_FileSystemPath') //'/tmp/uploads/photos',
+ };
+
+ FileSystemUploads.store = FileUpload.configureUploadsStore('Local', FileSystemUploads.name, options);
+ FileSystemAvatars.store = FileUpload.configureUploadsStore('Local', FileSystemAvatars.name, options);
+
+ // DEPRECATED backwards compatibililty (remove)
+ UploadFS.getStores()['fileSystem'] = UploadFS.getStores()[FileSystemUploads.name];
+}, 500);
+
+RocketChat.settings.get('FileUpload_FileSystemPath', createFileSystemStore);
diff --git a/packages/rocketchat-file-upload/server/config/GoogleStorage.js b/packages/rocketchat-file-upload/server/config/GoogleStorage.js
new file mode 100644
index 0000000000000..fd571ea6ec8f6
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/GoogleStorage.js
@@ -0,0 +1,67 @@
+/* globals FileUpload */
+
+import _ from 'underscore';
+import { FileUploadClass } from '../lib/FileUpload';
+import '../../ufs/GoogleStorage/server.js';
+import http from 'http';
+import https from 'https';
+
+const get = function(file, req, res) {
+ this.store.getRedirectURL(file, (err, fileUrl) => {
+ if (err) {
+ console.error(err);
+ }
+
+ if (fileUrl) {
+ if (RocketChat.settings.get('FileUpload_GoogleStorage_Proxy')) {
+ const request = /^https:/.test(fileUrl) ? https : http;
+ request.get(fileUrl, fileRes => fileRes.pipe(res));
+ } else {
+ res.setHeader('Location', fileUrl);
+ res.writeHead(302);
+ res.end();
+ }
+ } else {
+ res.end();
+ }
+ });
+};
+
+const GoogleCloudStorageUploads = new FileUploadClass({
+ name: 'GoogleCloudStorage:Uploads',
+ get
+ // store setted bellow
+});
+
+const GoogleCloudStorageAvatars = new FileUploadClass({
+ name: 'GoogleCloudStorage:Avatars',
+ get
+ // store setted bellow
+});
+
+const configure = _.debounce(function() {
+ const bucket = RocketChat.settings.get('FileUpload_GoogleStorage_Bucket');
+ const accessId = RocketChat.settings.get('FileUpload_GoogleStorage_AccessId');
+ const secret = RocketChat.settings.get('FileUpload_GoogleStorage_Secret');
+ const URLExpiryTimeSpan = RocketChat.settings.get('FileUpload_S3_URLExpiryTimeSpan');
+
+ if (!bucket || !accessId || !secret) {
+ return;
+ }
+
+ const config = {
+ connection: {
+ credentials: {
+ client_email: accessId,
+ private_key: secret
+ }
+ },
+ bucket,
+ URLExpiryTimeSpan
+ };
+
+ GoogleCloudStorageUploads.store = FileUpload.configureUploadsStore('GoogleStorage', GoogleCloudStorageUploads.name, config);
+ GoogleCloudStorageAvatars.store = FileUpload.configureUploadsStore('GoogleStorage', GoogleCloudStorageAvatars.name, config);
+}, 500);
+
+RocketChat.settings.get(/^FileUpload_GoogleStorage_/, configure);
diff --git a/packages/rocketchat-file-upload/server/config/GridFS.js b/packages/rocketchat-file-upload/server/config/GridFS.js
new file mode 100644
index 0000000000000..54bb40712cacd
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/GridFS.js
@@ -0,0 +1,161 @@
+/* globals FileUpload, UploadFS */
+import stream from 'stream';
+import zlib from 'zlib';
+import util from 'util';
+
+import { FileUploadClass } from '../lib/FileUpload';
+
+const logger = new Logger('FileUpload');
+
+function ExtractRange(options) {
+ if (!(this instanceof ExtractRange)) {
+ return new ExtractRange(options);
+ }
+
+ this.start = options.start;
+ this.stop = options.stop;
+ this.bytes_read = 0;
+
+ stream.Transform.call(this, options);
+}
+util.inherits(ExtractRange, stream.Transform);
+
+
+ExtractRange.prototype._transform = function(chunk, enc, cb) {
+ if (this.bytes_read > this.stop) {
+ // done reading
+ this.end();
+ } else if (this.bytes_read + chunk.length < this.start) {
+ // this chunk is still before the start byte
+ } else {
+ let start;
+ let stop;
+
+ if (this.start <= this.bytes_read) {
+ start = 0;
+ } else {
+ start = this.start - this.bytes_read;
+ }
+ if ((this.stop - this.bytes_read + 1) < chunk.length) {
+ stop = this.stop - this.bytes_read + 1;
+ } else {
+ stop = chunk.length;
+ }
+ const newchunk = chunk.slice(start, stop);
+ this.push(newchunk);
+ }
+ this.bytes_read += chunk.length;
+ cb();
+};
+
+
+const getByteRange = function(header) {
+ if (header) {
+ const matches = header.match(/(\d+)-(\d+)/);
+ if (matches) {
+ return {
+ start: parseInt(matches[1], 10),
+ stop: parseInt(matches[2], 10)
+ };
+ }
+ }
+ return null;
+};
+
+
+// code from: https://github.com/jalik/jalik-ufs/blob/master/ufs-server.js#L310
+const readFromGridFS = function(storeName, fileId, file, req, res) {
+ const store = UploadFS.getStore(storeName);
+ const rs = store.getReadStream(fileId, file);
+ const ws = new stream.PassThrough();
+
+ [rs, ws].forEach(stream => stream.on('error', function(err) {
+ store.onReadError.call(store, err, fileId, file);
+ res.end();
+ }));
+
+ ws.on('close', function() {
+ // Close output stream at the end
+ ws.emit('end');
+ });
+
+ const accept = req.headers['accept-encoding'] || '';
+
+ // Transform stream
+ store.transformRead(rs, ws, fileId, file, req);
+ const range = getByteRange(req.headers.range);
+ let out_of_range = false;
+ if (range) {
+ out_of_range = (range.start > file.size) || (range.stop <= range.start) || (range.stop > file.size);
+ }
+
+ // Compress data using gzip
+ if (accept.match(/\bgzip\b/) && range === null) {
+ res.setHeader('Content-Encoding', 'gzip');
+ res.removeHeader('Content-Length');
+ res.writeHead(200);
+ ws.pipe(zlib.createGzip()).pipe(res);
+ } else if (accept.match(/\bdeflate\b/) && range === null) {
+ // Compress data using deflate
+ res.setHeader('Content-Encoding', 'deflate');
+ res.removeHeader('Content-Length');
+ res.writeHead(200);
+ ws.pipe(zlib.createDeflate()).pipe(res);
+ } else if (range && out_of_range) {
+ // out of range request, return 416
+ res.removeHeader('Content-Length');
+ res.removeHeader('Content-Type');
+ res.removeHeader('Content-Disposition');
+ res.removeHeader('Last-Modified');
+ res.setHeader('Content-Range', `bytes */${ file.size }`);
+ res.writeHead(416);
+ res.end();
+ } else if (range) {
+ res.setHeader('Content-Range', `bytes ${ range.start }-${ range.stop }/${ file.size }`);
+ res.removeHeader('Content-Length');
+ res.setHeader('Content-Length', range.stop - range.start + 1);
+ res.writeHead(206);
+ logger.debug('File upload extracting range');
+ ws.pipe(new ExtractRange({ start: range.start, stop: range.stop })).pipe(res);
+ } else {
+ res.writeHead(200);
+ ws.pipe(res);
+ }
+};
+
+FileUpload.configureUploadsStore('GridFS', 'GridFS:Uploads', {
+ collectionName: 'rocketchat_uploads'
+});
+
+// DEPRECATED: backwards compatibility (remove)
+UploadFS.getStores()['rocketchat_uploads'] = UploadFS.getStores()['GridFS:Uploads'];
+
+FileUpload.configureUploadsStore('GridFS', 'GridFS:Avatars', {
+ collectionName: 'rocketchat_avatars'
+});
+
+
+new FileUploadClass({
+ name: 'GridFS:Uploads',
+
+ get(file, req, res) {
+ file = FileUpload.addExtensionTo(file);
+
+ res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${ encodeURIComponent(file.name) }`);
+ res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
+ res.setHeader('Content-Type', file.type);
+ res.setHeader('Content-Length', file.size);
+
+ return readFromGridFS(file.store, file._id, file, req, res);
+ }
+});
+
+new FileUploadClass({
+ name: 'GridFS:Avatars',
+
+ get(file, req, res) {
+ file = FileUpload.addExtensionTo(file);
+
+ return readFromGridFS(file.store, file._id, file, req, res);
+ }
+});
diff --git a/packages/rocketchat-file-upload/server/config/Slingshot_DEPRECATED.js b/packages/rocketchat-file-upload/server/config/Slingshot_DEPRECATED.js
new file mode 100644
index 0000000000000..d741a1411f685
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/Slingshot_DEPRECATED.js
@@ -0,0 +1,115 @@
+/* globals Slingshot, FileUpload */
+import _ from 'underscore';
+
+const configureSlingshot = _.debounce(() => {
+ const type = RocketChat.settings.get('FileUpload_Storage_Type');
+ const bucket = RocketChat.settings.get('FileUpload_S3_Bucket');
+ const acl = RocketChat.settings.get('FileUpload_S3_Acl');
+ const accessKey = RocketChat.settings.get('FileUpload_S3_AWSAccessKeyId');
+ const secretKey = RocketChat.settings.get('FileUpload_S3_AWSSecretAccessKey');
+ const cdn = RocketChat.settings.get('FileUpload_S3_CDN');
+ const region = RocketChat.settings.get('FileUpload_S3_Region');
+ const bucketUrl = RocketChat.settings.get('FileUpload_S3_BucketURL');
+
+ delete Slingshot._directives['rocketchat-uploads'];
+
+ if (type === 'AmazonS3' && !_.isEmpty(bucket) && !_.isEmpty(accessKey) && !_.isEmpty(secretKey)) {
+ if (Slingshot._directives['rocketchat-uploads']) {
+ delete Slingshot._directives['rocketchat-uploads'];
+ }
+ const config = {
+ bucket,
+ key(file, metaContext) {
+ const id = Random.id();
+ const path = `${ RocketChat.settings.get('uniqueID') }/uploads/${ metaContext.rid }/${ this.userId }/${ id }`;
+
+ const upload = {
+ _id: id,
+ rid: metaContext.rid,
+ AmazonS3: {
+ path
+ }
+ };
+
+ RocketChat.models.Uploads.insertFileInit(this.userId, 'AmazonS3:Uploads', file, upload);
+
+ return path;
+ },
+ AWSAccessKeyId: accessKey,
+ AWSSecretAccessKey: secretKey
+ };
+
+ if (!_.isEmpty(acl)) {
+ config.acl = acl;
+ }
+
+ if (!_.isEmpty(cdn)) {
+ config.cdn = cdn;
+ }
+
+ if (!_.isEmpty(region)) {
+ config.region = region;
+ }
+
+ if (!_.isEmpty(bucketUrl)) {
+ config.bucketUrl = bucketUrl;
+ }
+
+ try {
+ Slingshot.createDirective('rocketchat-uploads', Slingshot.S3Storage, config);
+ } catch (e) {
+ console.error('Error configuring S3 ->', e.message);
+ }
+ }
+}, 500);
+
+RocketChat.settings.get('FileUpload_Storage_Type', configureSlingshot);
+RocketChat.settings.get(/^FileUpload_S3_/, configureSlingshot);
+
+
+
+const createGoogleStorageDirective = _.debounce(() => {
+ const type = RocketChat.settings.get('FileUpload_Storage_Type');
+ const bucket = RocketChat.settings.get('FileUpload_GoogleStorage_Bucket');
+ const accessId = RocketChat.settings.get('FileUpload_GoogleStorage_AccessId');
+ const secret = RocketChat.settings.get('FileUpload_GoogleStorage_Secret');
+
+ delete Slingshot._directives['rocketchat-uploads-gs'];
+
+ if (type === 'GoogleCloudStorage' && !_.isEmpty(secret) && !_.isEmpty(accessId) && !_.isEmpty(bucket)) {
+ if (Slingshot._directives['rocketchat-uploads-gs']) {
+ delete Slingshot._directives['rocketchat-uploads-gs'];
+ }
+
+ const config = {
+ bucket,
+ GoogleAccessId: accessId,
+ GoogleSecretKey: secret,
+ key(file, metaContext) {
+ const id = Random.id();
+ const path = `${ RocketChat.settings.get('uniqueID') }/uploads/${ metaContext.rid }/${ this.userId }/${ id }`;
+
+ const upload = {
+ _id: id,
+ rid: metaContext.rid,
+ GoogleStorage: {
+ path
+ }
+ };
+
+ RocketChat.models.Uploads.insertFileInit(this.userId, 'GoogleCloudStorage:Uploads', file, upload);
+
+ return path;
+ }
+ };
+
+ try {
+ Slingshot.createDirective('rocketchat-uploads-gs', Slingshot.GoogleCloud, config);
+ } catch (e) {
+ console.error('Error configuring GoogleCloudStorage ->', e.message);
+ }
+ }
+}, 500);
+
+RocketChat.settings.get('FileUpload_Storage_Type', createGoogleStorageDirective);
+RocketChat.settings.get(/^FileUpload_GoogleStorage_/, createGoogleStorageDirective);
diff --git a/packages/rocketchat-file-upload/server/config/_configUploadStorage.js b/packages/rocketchat-file-upload/server/config/_configUploadStorage.js
new file mode 100644
index 0000000000000..d2ba5505f2d4d
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/config/_configUploadStorage.js
@@ -0,0 +1,20 @@
+/* globals UploadFS */
+
+import _ from 'underscore';
+import './AmazonS3.js';
+import './FileSystem.js';
+import './GoogleStorage.js';
+import './GridFS.js';
+import './Slingshot_DEPRECATED.js';
+
+const configStore = _.debounce(() => {
+ const store = RocketChat.settings.get('FileUpload_Storage_Type');
+
+ if (store) {
+ console.log('Setting default file store to', store);
+ UploadFS.getStores().Avatars = UploadFS.getStore(`${ store }:Avatars`);
+ UploadFS.getStores().Uploads = UploadFS.getStore(`${ store }:Uploads`);
+ }
+}, 1000);
+
+RocketChat.settings.get(/^FileUpload_/, configStore);
diff --git a/packages/rocketchat-file-upload/server/config/configFileUploadAmazonS3.js b/packages/rocketchat-file-upload/server/config/configFileUploadAmazonS3.js
deleted file mode 100644
index 96ab42ab89172..0000000000000
--- a/packages/rocketchat-file-upload/server/config/configFileUploadAmazonS3.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/* globals Slingshot, FileUpload, AWS, SystemLogger */
-const crypto = Npm.require('crypto');
-
-let S3accessKey, S3secretKey, S3expiryTimeSpan;
-
-const generateURL = function(file) {
- if (!file || !file.s3) {
- return;
- }
- const resourceURL = '/' + file.s3.bucket + '/' + file.s3.path + file._id;
- const expires = parseInt(new Date().getTime() / 1000) + Math.max(5, S3expiryTimeSpan);
- const StringToSign = 'GET\n\n\n' + expires +'\n'+resourceURL;
- const signature = crypto.createHmac('sha1', S3secretKey).update(new Buffer(StringToSign, 'utf-8')).digest('base64');
- return file.url + '?AWSAccessKeyId='+encodeURIComponent(S3accessKey)+'&Expires='+expires+'&Signature='+encodeURIComponent(signature);
-};
-
-FileUpload.addHandler('s3', {
- get(file, req, res) {
- let fileUrl = generateURL(file);
-
- if (fileUrl) {
- res.setHeader('Location', fileUrl);
- res.writeHead(302);
- }
- res.end();
- },
- delete(file) {
- let s3 = new AWS.S3();
- let request = s3.deleteObject({
- Bucket: file.s3.bucket,
- Key: file.s3.path + file._id
- });
- request.send();
- }
-});
-
-const createS3Directive = _.debounce(() => {
- const directiveName = 'rocketchat-uploads';
-
- const type = RocketChat.settings.get('FileUpload_Storage_Type');
- const bucket = RocketChat.settings.get('FileUpload_S3_Bucket');
- const acl = RocketChat.settings.get('FileUpload_S3_Acl');
- const accessKey = RocketChat.settings.get('FileUpload_S3_AWSAccessKeyId');
- const secretKey = RocketChat.settings.get('FileUpload_S3_AWSSecretAccessKey');
- const cdn = RocketChat.settings.get('FileUpload_S3_CDN');
- const region = RocketChat.settings.get('FileUpload_S3_Region');
- const bucketUrl = RocketChat.settings.get('FileUpload_S3_BucketURL');
-
- AWS.config.update({
- accessKeyId: RocketChat.settings.get('FileUpload_S3_AWSAccessKeyId'),
- secretAccessKey: RocketChat.settings.get('FileUpload_S3_AWSSecretAccessKey')
- });
-
- if (type === 'AmazonS3' && !_.isEmpty(bucket) && !_.isEmpty(accessKey) && !_.isEmpty(secretKey)) {
- if (Slingshot._directives[directiveName]) {
- delete Slingshot._directives[directiveName];
- }
- const config = {
- bucket: bucket,
- AWSAccessKeyId: accessKey,
- AWSSecretAccessKey: secretKey,
- key: function(file, metaContext) {
- const path = RocketChat.hostname + '/' + metaContext.rid + '/' + this.userId + '/';
-
- const upload = { s3: {
- bucket,
- region,
- path
- }};
- const fileId = RocketChat.models.Uploads.insertFileInit(metaContext.rid, this.userId, 's3', file, upload);
-
- return path + fileId;
- }
- };
-
- if (!_.isEmpty(acl)) {
- config.acl = acl;
- }
-
- if (!_.isEmpty(cdn)) {
- config.cdn = cdn;
- }
-
- if (!_.isEmpty(region)) {
- config.region = region;
- }
-
- if (!_.isEmpty(bucketUrl)) {
- config.bucketUrl = bucketUrl;
- }
-
- try {
- Slingshot.createDirective(directiveName, Slingshot.S3Storage, config);
- } catch (e) {
- SystemLogger.error('Error configuring S3 ->', e.message);
- }
- } else if (Slingshot._directives[directiveName]) {
- delete Slingshot._directives[directiveName];
- }
-}, 500);
-
-RocketChat.settings.get('FileUpload_Storage_Type', createS3Directive);
-
-RocketChat.settings.get('FileUpload_S3_Bucket', createS3Directive);
-
-RocketChat.settings.get('FileUpload_S3_Acl', createS3Directive);
-
-RocketChat.settings.get('FileUpload_S3_AWSAccessKeyId', function(key, value) {
- S3accessKey = value;
- createS3Directive();
-});
-
-RocketChat.settings.get('FileUpload_S3_AWSSecretAccessKey', function(key, value) {
- S3secretKey = value;
- createS3Directive();
-});
-
-RocketChat.settings.get('FileUpload_S3_URLExpiryTimeSpan', function(key, value) {
- S3expiryTimeSpan = value;
- createS3Directive();
-});
-
-RocketChat.settings.get('FileUpload_S3_CDN', createS3Directive);
-
-RocketChat.settings.get('FileUpload_S3_Region', createS3Directive);
-
-RocketChat.settings.get('FileUpload_S3_BucketURL', createS3Directive);
diff --git a/packages/rocketchat-file-upload/server/config/configFileUploadFileSystem.js b/packages/rocketchat-file-upload/server/config/configFileUploadFileSystem.js
deleted file mode 100644
index aacb97542a41d..0000000000000
--- a/packages/rocketchat-file-upload/server/config/configFileUploadFileSystem.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* globals FileSystemStore:true, FileUpload, UploadFS, RocketChatFile */
-
-const storeName = 'fileSystem';
-
-FileSystemStore = null;
-
-const createFileSystemStore = _.debounce(function() {
- const stores = UploadFS.getStores();
- if (stores[storeName]) {
- delete stores[storeName];
- }
- FileSystemStore = new UploadFS.store.Local({
- collection: RocketChat.models.Uploads.model,
- name: storeName,
- path: RocketChat.settings.get('FileUpload_FileSystemPath'), //'/tmp/uploads/photos',
- filter: new UploadFS.Filter({
- onCheck: FileUpload.validateFileUpload
- }),
- transformWrite: function(readStream, writeStream, fileId, file) {
- if (RocketChatFile.enabled === false || !/^image\/((x-windows-)?bmp|p?jpeg|png)$/.test(file.type)) {
- return readStream.pipe(writeStream);
- }
-
- let stream = void 0;
-
- const identify = function(err, data) {
- if (err != null) {
- return stream.pipe(writeStream);
- }
-
- file.identify = {
- format: data.format,
- size: data.size
- };
-
- if ([null, undefined, '', 'Unknown', 'Undefined'].indexOf(data.Orientation) === -1) {
- return RocketChatFile.gm(stream).autoOrient().stream().pipe(writeStream);
- } else {
- return stream.pipe(writeStream);
- }
- };
-
- stream = RocketChatFile.gm(readStream).identify(identify).stream();
- return;
- }
- });
-}, 500);
-
-RocketChat.settings.get('FileUpload_FileSystemPath', createFileSystemStore);
-
-const fs = Npm.require('fs');
-
-FileUpload.addHandler(storeName, {
- get(file, req, res) {
- const filePath = FileSystemStore.getFilePath(file._id, file);
-
- try {
- const stat = Meteor.wrapAsync(fs.stat)(filePath);
-
- if (stat && stat.isFile()) {
- file = FileUpload.addExtensionTo(file);
- res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(file.name)}`);
- res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
- res.setHeader('Content-Type', file.type);
- res.setHeader('Content-Length', file.size);
-
- FileSystemStore.getReadStream(file._id, file).pipe(res);
- }
- } catch (e) {
- res.writeHead(404);
- res.end();
- return;
- }
- },
-
- delete(file) {
- return FileSystemStore.delete(file._id);
- }
-});
diff --git a/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js b/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js
deleted file mode 100644
index 17298d0f5a0f5..0000000000000
--- a/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js
+++ /dev/null
@@ -1,139 +0,0 @@
-/* globals FileUpload, UploadFS */
-const stream = Npm.require('stream');
-const zlib = Npm.require('zlib');
-const util = Npm.require('util');
-const logger = new Logger('FileUpload');
-
-function ExtractRange(options) {
- if (!(this instanceof ExtractRange)) {
- return new ExtractRange(options);
- }
-
- this.start = options.start;
- this.stop = options.stop;
- this.bytes_read = 0;
-
- stream.Transform.call(this, options);
-}
-util.inherits(ExtractRange, stream.Transform);
-
-
-ExtractRange.prototype._transform = function(chunk, enc, cb) {
- if (this.bytes_read > this.stop) {
- // done reading
- this.end();
- } else if (this.bytes_read + chunk.length < this.start) {
- // this chunk is still before the start byte
- } else {
- let start, stop;
- if (this.start <= this.bytes_read) {
- start = 0;
- } else {
- start = this.start - this.bytes_read;
- }
- if ((this.stop - this.bytes_read + 1) < chunk.length) {
- stop = this.stop - this.bytes_read + 1;
- } else {
- stop = chunk.length;
- }
- const newchunk = chunk.slice(start, stop);
- this.push(newchunk);
- }
- this.bytes_read += chunk.length;
- cb();
-};
-
-
-const getByteRange = function(header) {
- if (header) {
- const matches = header.match(/(\d+)-(\d+)/);
- if (matches) {
- return {
- start: parseInt(matches[1], 10),
- stop: parseInt(matches[2], 10)
- };
- }
- }
- return null;
-};
-
-
-// code from: https://github.com/jalik/jalik-ufs/blob/master/ufs-server.js#L91
-const readFromGridFS = function(storeName, fileId, file, headers, req, res) {
- const store = UploadFS.getStore(storeName);
- const rs = store.getReadStream(fileId, file);
- const ws = new stream.PassThrough();
-
- rs.on('error', function(err) {
- store.onReadError.call(store, err, fileId, file);
- res.end();
- });
- ws.on('error', function(err) {
- store.onReadError.call(store, err, fileId, file);
- res.end();
- });
- ws.on('close', function() {
- // Close output stream at the end
- ws.emit('end');
- });
-
- const accept = req.headers['accept-encoding'] || '';
-
- // Transform stream
- store.transformRead(rs, ws, fileId, file, req, headers);
-
- const range = getByteRange(req.headers.range);
- let out_of_range = false;
- if (range) {
- out_of_range = (range.start > file.size) || (range.stop <= range.start) || (range.stop > file.size);
- }
-
- // Compress data using gzip
- if (accept.match(/\bgzip\b/) && range === null) {
- headers['Content-Encoding'] = 'gzip';
- delete headers['Content-Length'];
- res.writeHead(200, headers);
- ws.pipe(zlib.createGzip()).pipe(res);
- } else if (accept.match(/\bdeflate\b/) && range === null) {
- // Compress data using deflate
- headers['Content-Encoding'] = 'deflate';
- delete headers['Content-Length'];
- res.writeHead(200, headers);
- ws.pipe(zlib.createDeflate()).pipe(res);
- } else if (range && out_of_range) {
- // out of range request, return 416
- delete headers['Content-Length'];
- delete headers['Content-Type'];
- delete headers['Content-Disposition'];
- delete headers['Last-Modified'];
- headers['Content-Range'] = 'bytes */' + file.size;
- res.writeHead(416, headers);
- res.end();
- } else if (range) {
- headers['Content-Range'] = 'bytes ' + range.start + '-' + range.stop + '/' + file.size;
- delete headers['Content-Length'];
- headers['Content-Length'] = range.stop - range.start + 1;
- res.writeHead(206, headers);
- logger.debug('File upload extracting range');
- ws.pipe(new ExtractRange({ start: range.start, stop: range.stop })).pipe(res);
- } else {
- res.writeHead(200, headers);
- ws.pipe(res);
- }
-};
-
-FileUpload.addHandler('rocketchat_uploads', {
- get(file, req, res) {
- file = FileUpload.addExtensionTo(file);
- const headers = {
- 'Content-Disposition': `attachment; filename*=UTF-8''${encodeURIComponent(file.name)}`,
- 'Last-Modified': file.uploadedAt.toUTCString(),
- 'Content-Type': file.type,
- 'Content-Length': file.size
- };
- return readFromGridFS(file.store, file._id, file, headers, req, res);
- },
- delete(file) {
- return Meteor.fileStore.delete(file._id);
- }
-});
diff --git a/packages/rocketchat-file-upload/server/lib/FileUpload.js b/packages/rocketchat-file-upload/server/lib/FileUpload.js
index 73f74cfec6e60..a056e991fba5e 100644
--- a/packages/rocketchat-file-upload/server/lib/FileUpload.js
+++ b/packages/rocketchat-file-upload/server/lib/FileUpload.js
@@ -1,43 +1,339 @@
-/* globals FileUpload:true */
-const mime = Npm.require('mime-types');
+/* globals UploadFS */
-FileUpload.handlers = {};
+import fs from 'fs';
+import stream from 'stream';
+import mime from 'mime-type/with-db';
+import Future from 'fibers/future';
+import sharp from 'sharp';
+import { Cookies } from 'meteor/ostrio:cookies';
-FileUpload.addHandler = function(store, handler) {
- this.handlers[store] = handler;
-};
+const cookie = new Cookies();
-FileUpload.delete = function(fileId) {
- const file = RocketChat.models.Uploads.findOneById(fileId);
+Object.assign(FileUpload, {
+ handlers: {},
- if (!file) {
- return;
- }
+ configureUploadsStore(store, name, options) {
+ const type = name.split(':').pop();
+ const stores = UploadFS.getStores();
+ delete stores[name];
+
+ return new UploadFS.store[store](Object.assign({
+ name
+ }, options, FileUpload[`default${ type }`]()));
+ },
+
+ defaultUploads() {
+ return {
+ collection: RocketChat.models.Uploads.model,
+ filter: new UploadFS.Filter({
+ onCheck: FileUpload.validateFileUpload
+ }),
+ getPath(file) {
+ return `${ RocketChat.settings.get('uniqueID') }/uploads/${ file.rid }/${ file.userId }/${ file._id }`;
+ },
+ onValidate: FileUpload.uploadsOnValidate,
+ onRead(fileId, file, req, res) {
+ if (!FileUpload.requestCanAccessFiles(req)) {
+ res.writeHead(403);
+ return false;
+ }
+
+ res.setHeader('content-disposition', `attachment; filename="${ encodeURIComponent(file.name) }"`);
+ return true;
+ }
+ };
+ },
+
+ defaultAvatars() {
+ return {
+ collection: RocketChat.models.Avatars.model,
+ // filter: new UploadFS.Filter({
+ // onCheck: FileUpload.validateFileUpload
+ // }),
+ getPath(file) {
+ return `${ RocketChat.settings.get('uniqueID') }/avatars/${ file.userId }`;
+ },
+ onValidate: FileUpload.avatarsOnValidate,
+ onFinishUpload: FileUpload.avatarsOnFinishUpload
+ };
+ },
+
+ avatarsOnValidate(file) {
+ if (RocketChat.settings.get('Accounts_AvatarResize') !== true) {
+ return;
+ }
+
+ const tempFilePath = UploadFS.getTempFilePath(file._id);
+
+ const height = RocketChat.settings.get('Accounts_AvatarSize');
+ const future = new Future();
+
+ const s = sharp(tempFilePath);
+ s.rotate();
+ // Get metadata to resize the image the first time to keep "inside" the dimensions
+ // then resize again to create the canvas around
+ s.metadata(Meteor.bindEnvironment((err, metadata) => {
+ s.toFormat(sharp.format.jpeg)
+ .resize(Math.min(height, metadata.width), Math.min(height, metadata.height))
+ .pipe(sharp()
+ .resize(height, height)
+ .background('#FFFFFF')
+ .embed()
+ )
+ // Use buffer to get the result in memory then replace the existing file
+ // There is no option to override a file using this library
+ .toBuffer()
+ .then(Meteor.bindEnvironment(outputBuffer => {
+ fs.writeFile(tempFilePath, outputBuffer, Meteor.bindEnvironment(err => {
+ if (err != null) {
+ console.error(err);
+ }
+ const size = fs.lstatSync(tempFilePath).size;
+ this.getCollection().direct.update({_id: file._id}, {$set: {size}});
+ future.return();
+ }));
+ }));
+ }));
+
+ return future.wait();
+ },
+
+ resizeImagePreview(file) {
+ file = RocketChat.models.Uploads.findOneById(file._id);
+ file = FileUpload.addExtensionTo(file);
+ const image = FileUpload.getStore('Uploads')._store.getReadStream(file._id, file);
+
+ const transformer = sharp()
+ .resize(32, 32)
+ .max()
+ .jpeg()
+ .blur();
+ const result = transformer.toBuffer().then((out) => out.toString('base64'));
+ image.pipe(transformer);
+ return result;
+ },
+
+ uploadsOnValidate(file) {
+ if (!/^image\/((x-windows-)?bmp|p?jpeg|png)$/.test(file.type)) {
+ return;
+ }
+
+ const tmpFile = UploadFS.getTempFilePath(file._id);
+
+ const fut = new Future();
+
+ const s = sharp(tmpFile);
+ s.metadata(Meteor.bindEnvironment((err, metadata) => {
+ if (err != null) {
+ console.error(err);
+ return fut.return();
+ }
+
+ const identify = {
+ format: metadata.format,
+ size: {
+ width: metadata.width,
+ height: metadata.height
+ }
+ };
+
+ if (metadata.orientation == null) {
+ return fut.return();
+ }
+
+ s.rotate()
+ .toFile(`${ tmpFile }.tmp`)
+ .then(Meteor.bindEnvironment(() => {
+ fs.unlink(tmpFile, Meteor.bindEnvironment(() => {
+ fs.rename(`${ tmpFile }.tmp`, tmpFile, Meteor.bindEnvironment(() => {
+ const size = fs.lstatSync(tmpFile).size;
+ this.getCollection().direct.update({_id: file._id}, {
+ $set: {
+ size,
+ identify
+ }
+ });
+ fut.return();
+ }));
+ }));
+ })).catch((err) => {
+ console.error(err);
+ fut.return();
+ });
+ }));
+
+ return fut.wait();
+ },
+
+ avatarsOnFinishUpload(file) {
+ // update file record to match user's username
+ const user = RocketChat.models.Users.findOneById(file.userId);
+ const oldAvatar = RocketChat.models.Avatars.findOneByName(user.username);
+ if (oldAvatar) {
+ RocketChat.models.Avatars.deleteFile(oldAvatar._id);
+ }
+ RocketChat.models.Avatars.updateFileNameById(file._id, user.username);
+ // console.log('upload finished ->', file);
+ },
+
+ requestCanAccessFiles({ headers = {}, query = {} }) {
+ if (!RocketChat.settings.get('FileUpload_ProtectFiles')) {
+ return true;
+ }
+
+ let { rc_uid, rc_token } = query;
+
+ if (!rc_uid && headers.cookie) {
+ rc_uid = cookie.get('rc_uid', headers.cookie) ;
+ rc_token = cookie.get('rc_token', headers.cookie);
+ }
+
+ if (!rc_uid || !rc_token || !RocketChat.models.Users.findOneByIdAndLoginToken(rc_uid, rc_token)) {
+ return false;
+ }
+
+ return true;
+ },
+
+ addExtensionTo(file) {
+ if (mime.lookup(file.name) === file.type) {
+ return file;
+ }
+
+ const ext = mime.extension(file.type);
+ if (ext && false === new RegExp(`\.${ ext }$`, 'i').test(file.name)) {
+ file.name = `${ file.name }.${ ext }`;
+ }
+
+ return file;
+ },
+
+ getStore(modelName) {
+ const storageType = RocketChat.settings.get('FileUpload_Storage_Type');
+ const handlerName = `${ storageType }:${ modelName }`;
- this.handlers[file.store].delete(file);
+ return this.getStoreByName(handlerName);
+ },
- return RocketChat.models.Uploads.remove(file._id);
-};
+ getStoreByName(handlerName) {
+ if (this.handlers[handlerName] == null) {
+ console.error(`Upload handler "${ handlerName }" does not exists`);
+ }
+ return this.handlers[handlerName];
+ },
-FileUpload.get = function(file, req, res, next) {
- if (file.store && this.handlers && this.handlers[file.store] && this.handlers[file.store].get) {
- this.handlers[file.store].get.call(this, file, req, res, next);
- } else {
+ get(file, req, res, next) {
+ const store = this.getStoreByName(file.store);
+ if (store && store.get) {
+ return store.get(file, req, res, next);
+ }
res.writeHead(404);
res.end();
- return;
}
-};
+});
-FileUpload.addExtensionTo = function(file) {
- if (mime.lookup(file.name) === file.type) {
- return file;
+
+export class FileUploadClass {
+ constructor({ name, model, store, get, insert, getStore }) {
+ this.name = name;
+ this.model = model || this.getModelFromName();
+ this._store = store || UploadFS.getStore(name);
+ this.get = get;
+
+ if (insert) {
+ this.insert = insert;
+ }
+
+ if (getStore) {
+ this.getStore = getStore;
+ }
+
+ FileUpload.handlers[name] = this;
+ }
+
+ getStore() {
+ return this._store;
+ }
+
+ get store() {
+ return this.getStore();
+ }
+
+ set store(store) {
+ this._store = store;
+ }
+
+ getModelFromName() {
+ return RocketChat.models[this.name.split(':')[1]];
}
- const ext = mime.extension(file.type);
- if (ext && false === new RegExp(`\.${ext}$`, 'i').test(file.name)) {
- file.name = `${file.name}.${ext}`;
+ delete(fileId) {
+ if (this.store && this.store.delete) {
+ this.store.delete(fileId);
+ }
+
+ return this.model.deleteFile(fileId);
}
- return file;
-};
+ deleteById(fileId) {
+ const file = this.model.findOneById(fileId);
+
+ if (!file) {
+ return;
+ }
+
+ const store = FileUpload.getStoreByName(file.store);
+
+ return store.delete(file._id);
+ }
+
+ deleteByName(fileName) {
+ const file = this.model.findOneByName(fileName);
+
+ if (!file) {
+ return;
+ }
+
+ const store = FileUpload.getStoreByName(file.store);
+
+ return store.delete(file._id);
+ }
+
+ insert(fileData, streamOrBuffer, cb) {
+ fileData.size = parseInt(fileData.size) || 0;
+
+ // Check if the fileData matches store filter
+ const filter = this.store.getFilter();
+ if (filter && filter.check) {
+ filter.check(fileData);
+ }
+
+ const fileId = this.store.create(fileData);
+ const token = this.store.createToken(fileId);
+ const tmpFile = UploadFS.getTempFilePath(fileId);
+
+ try {
+ if (streamOrBuffer instanceof stream) {
+ streamOrBuffer.pipe(fs.createWriteStream(tmpFile));
+ } else if (streamOrBuffer instanceof Buffer) {
+ fs.writeFileSync(tmpFile, streamOrBuffer);
+ } else {
+ throw new Error('Invalid file type');
+ }
+
+ const file = Meteor.call('ufsComplete', fileId, this.name, token);
+
+ if (cb) {
+ cb(null, file);
+ }
+
+ return file;
+ } catch (e) {
+ if (cb) {
+ cb(e);
+ } else {
+ throw e;
+ }
+ }
+ }
+}
diff --git a/packages/rocketchat-file-upload/server/lib/proxy.js b/packages/rocketchat-file-upload/server/lib/proxy.js
new file mode 100644
index 0000000000000..d3a1be5c48d92
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/lib/proxy.js
@@ -0,0 +1,91 @@
+/* globals UploadFS, InstanceStatus */
+
+import http from 'http';
+import URL from 'url';
+
+const logger = new Logger('UploadProxy');
+
+WebApp.connectHandlers.stack.unshift({
+ route: '',
+ handle: Meteor.bindEnvironment(function(req, res, next) {
+ // Quick check to see if request should be catch
+ if (req.url.indexOf(UploadFS.config.storesPath) === -1) {
+ return next();
+ }
+
+ logger.debug('Upload URL:', req.url);
+
+ if (req.method !== 'POST') {
+ return next();
+ }
+
+ // Remove store path
+ const parsedUrl = URL.parse(req.url);
+ const path = parsedUrl.pathname.substr(UploadFS.config.storesPath.length + 1);
+
+ // Get store
+ const regExp = new RegExp('^\/([^\/\?]+)\/([^\/\?]+)$');
+ const match = regExp.exec(path);
+
+ // Request is not valid
+ if (match === null) {
+ res.writeHead(400);
+ res.end();
+ return;
+ }
+
+ // Get store
+ const store = UploadFS.getStore(match[1]);
+ if (!store) {
+ res.writeHead(404);
+ res.end();
+ return;
+ }
+
+ // Get file
+ const fileId = match[2];
+ const file = store.getCollection().findOne({_id: fileId});
+ if (file === undefined) {
+ res.writeHead(404);
+ res.end();
+ return;
+ }
+
+ if (file.instanceId === InstanceStatus.id()) {
+ logger.debug('Correct instance');
+ return next();
+ }
+
+ // Proxy to other instance
+ const instance = InstanceStatus.getCollection().findOne({_id: file.instanceId});
+
+ if (instance == null) {
+ res.writeHead(404);
+ res.end();
+ return;
+ }
+
+ if (instance.extraInformation.host === process.env.INSTANCE_IP && RocketChat.isDocker() === false) {
+ instance.extraInformation.host = 'localhost';
+ }
+
+ logger.debug('Wrong instance, proxing to:', `${ instance.extraInformation.host }:${ instance.extraInformation.port }`);
+
+ const options = {
+ hostname: instance.extraInformation.host,
+ port: instance.extraInformation.port,
+ path: req.originalUrl,
+ method: 'POST'
+ };
+
+ const proxy = http.request(options, function(proxy_res) {
+ proxy_res.pipe(res, {
+ end: true
+ });
+ });
+
+ req.pipe(proxy, {
+ end: true
+ });
+ })
+});
diff --git a/packages/rocketchat-file-upload/server/lib/requests.js b/packages/rocketchat-file-upload/server/lib/requests.js
index 45d6f77ab5c8d..7a47c0496e818 100644
--- a/packages/rocketchat-file-upload/server/lib/requests.js
+++ b/packages/rocketchat-file-upload/server/lib/requests.js
@@ -1,50 +1,23 @@
-/* globals FileUpload, WebApp, Cookies */
-let protectedFiles;
+/* globals FileUpload, WebApp */
-RocketChat.settings.get('FileUpload_ProtectFiles', function(key, value) {
- protectedFiles = value;
-});
+WebApp.connectHandlers.use(`${ __meteor_runtime_config__.ROOT_URL_PATH_PREFIX }/file-upload/`, function(req, res, next) {
-WebApp.connectHandlers.use('/file-upload/', function(req, res, next) {
const match = /^\/([^\/]+)\/(.*)/.exec(req.url);
if (match[1]) {
const file = RocketChat.models.Uploads.findOneById(match[1]);
if (file) {
- if (!Meteor.settings.public.sandstorm && protectedFiles) {
- let rawCookies, ref, token, uid;
- const cookie = new Cookies();
-
- if ((typeof req !== 'undefined' && req !== null ? (ref = req.headers) != null ? ref.cookie : void 0 : void 0) != null) {
- rawCookies = req.headers.cookie;
- }
-
- if (rawCookies != null) {
- uid = cookie.get('rc_uid', rawCookies);
- }
-
- if (rawCookies != null) {
- token = cookie.get('rc_token', rawCookies);
- }
-
- if (uid == null) {
- uid = req.query.rc_uid;
- token = req.query.rc_token;
- }
-
- if (!(uid && token && RocketChat.models.Users.findOneByIdAndLoginToken(uid, token))) {
- res.writeHead(403);
- res.end();
- return false;
- }
+ if (!Meteor.settings.public.sandstorm && !FileUpload.requestCanAccessFiles(req)) {
+ res.writeHead(403);
+ return res.end();
}
+ res.setHeader('Content-Security-Policy', 'default-src \'none\'');
return FileUpload.get(file, req, res, next);
}
}
res.writeHead(404);
res.end();
- return;
});
diff --git a/packages/rocketchat-file-upload/server/methods/getS3FileUrl.js b/packages/rocketchat-file-upload/server/methods/getS3FileUrl.js
new file mode 100644
index 0000000000000..421740d18b840
--- /dev/null
+++ b/packages/rocketchat-file-upload/server/methods/getS3FileUrl.js
@@ -0,0 +1,18 @@
+/* globals UploadFS */
+
+let protectedFiles;
+
+RocketChat.settings.get('FileUpload_ProtectFiles', function(key, value) {
+ protectedFiles = value;
+});
+
+Meteor.methods({
+ getS3FileUrl(fileId) {
+ if (protectedFiles && !Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'sendFileMessage' });
+ }
+ const file = RocketChat.models.Uploads.findOneById(fileId);
+
+ return UploadFS.getStore('AmazonS3:Uploads').getRedirectURL(file);
+ }
+});
diff --git a/packages/rocketchat-file-upload/server/methods/sendFileMessage.js b/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
index efd2101094dc5..74a6c30d2e982 100644
--- a/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
+++ b/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
@@ -1,5 +1,7 @@
+import _ from 'underscore';
+
Meteor.methods({
- 'sendFileMessage'(roomId, store, file, msgData = {}) {
+ async 'sendFileMessage'(roomId, store, file, msgData = {}) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'sendFileMessage' });
}
@@ -20,10 +22,11 @@ Meteor.methods({
RocketChat.models.Uploads.updateFileComplete(file._id, Meteor.userId(), _.omit(file, '_id'));
- const fileUrl = '/file-upload/' + file._id + '/' + file.name;
+ const fileUrl = `/file-upload/${ file._id }/${ encodeURI(file.name) }`;
const attachment = {
- title: `${TAPi18n.__('Attachment_File_Uploaded')}: ${file.name}`,
+ title: file.name,
+ type: 'file',
description: file.description,
title_link: fileUrl,
title_link_download: true
@@ -36,6 +39,7 @@ Meteor.methods({
if (file.identify && file.identify.size) {
attachment.image_dimensions = file.identify.size;
}
+ attachment.image_preview = await FileUpload.resizeImagePreview(file);
} else if (/^audio\/.+/.test(file.type)) {
attachment.audio_url = fileUrl;
attachment.audio_type = file.type;
@@ -46,17 +50,25 @@ Meteor.methods({
attachment.video_size = file.size;
}
- const msg = Object.assign({
+ const user = Meteor.user();
+ let msg = Object.assign({
_id: Random.id(),
rid: roomId,
+ ts: new Date(),
msg: '',
file: {
- _id: file._id
+ _id: file._id,
+ name: file.name,
+ type: file.type
},
groupable: false,
attachments: [attachment]
}, msgData);
- return Meteor.call('sendMessage', msg);
+ msg = Meteor.call('sendMessage', msg);
+
+ Meteor.defer(() => RocketChat.callbacks.run('afterFileUpload', { user, room, message: msg }));
+
+ return msg;
}
});
diff --git a/packages/rocketchat-file-upload/server/startup/settings.js b/packages/rocketchat-file-upload/server/startup/settings.js
index 8e51b3fb407ee..d5b3cbb5f3859 100644
--- a/packages/rocketchat-file-upload/server/startup/settings.js
+++ b/packages/rocketchat-file-upload/server/startup/settings.js
@@ -29,6 +29,9 @@ RocketChat.settings.addGroup('FileUpload', function() {
}, {
key: 'AmazonS3',
i18nLabel: 'AmazonS3'
+ }, {
+ key: 'GoogleCloudStorage',
+ i18nLabel: 'GoogleCloudStorage'
}, {
key: 'FileSystem',
i18nLabel: 'FileSystem'
@@ -87,6 +90,20 @@ RocketChat.settings.addGroup('FileUpload', function() {
},
i18nDescription: 'Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given.'
});
+ this.add('FileUpload_S3_SignatureVersion', 'v4', {
+ type: 'string',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'AmazonS3'
+ }
+ });
+ this.add('FileUpload_S3_ForcePathStyle', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'AmazonS3'
+ }
+ });
this.add('FileUpload_S3_URLExpiryTimeSpan', 120, {
type: 'int',
enableQuery: {
@@ -95,6 +112,48 @@ RocketChat.settings.addGroup('FileUpload', function() {
},
i18nDescription: 'FileUpload_S3_URLExpiryTimeSpan_Description'
});
+ this.add('FileUpload_S3_Proxy', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'AmazonS3'
+ }
+ });
+ });
+
+ this.section('Google Cloud Storage', function() {
+ this.add('FileUpload_GoogleStorage_Bucket', '', {
+ type: 'string',
+ private: true,
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'GoogleCloudStorage'
+ }
+ });
+ this.add('FileUpload_GoogleStorage_AccessId', '', {
+ type: 'string',
+ private: true,
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'GoogleCloudStorage'
+ }
+ });
+ this.add('FileUpload_GoogleStorage_Secret', '', {
+ type: 'string',
+ multiline: true,
+ private: true,
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'GoogleCloudStorage'
+ }
+ });
+ this.add('FileUpload_GoogleStorage_Proxy', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'GoogleCloudStorage'
+ }
+ });
});
this.section('File System', function() {
diff --git a/packages/rocketchat-file-upload/ufs/AmazonS3/client.js b/packages/rocketchat-file-upload/ufs/AmazonS3/client.js
new file mode 100644
index 0000000000000..6d9f66f467a46
--- /dev/null
+++ b/packages/rocketchat-file-upload/ufs/AmazonS3/client.js
@@ -0,0 +1,6 @@
+import {UploadFS} from 'meteor/jalik:ufs';
+
+export class AmazonS3Store extends UploadFS.Store {}
+
+// Add store to UFS namespace
+UploadFS.store.AmazonS3 = AmazonS3Store;
diff --git a/packages/rocketchat-file-upload/ufs/AmazonS3/server.js b/packages/rocketchat-file-upload/ufs/AmazonS3/server.js
new file mode 100644
index 0000000000000..b78b9299b60ba
--- /dev/null
+++ b/packages/rocketchat-file-upload/ufs/AmazonS3/server.js
@@ -0,0 +1,157 @@
+import {UploadFS} from 'meteor/jalik:ufs';
+import _ from 'underscore';
+import S3 from 'aws-sdk/clients/s3';
+import stream from 'stream';
+
+/**
+ * AmazonS3 store
+ * @param options
+ * @constructor
+ */
+export class AmazonS3Store extends UploadFS.Store {
+
+ constructor(options) {
+ // Default options
+ // options.secretAccessKey,
+ // options.accessKeyId,
+ // options.region,
+ // options.sslEnabled // optional
+
+ options = _.extend({
+ httpOptions: {
+ timeout: 6000,
+ agent: false
+ }
+ }, options);
+
+ super(options);
+
+ const classOptions = options;
+
+ const s3 = new S3(options.connection);
+
+ options.getPath = options.getPath || function(file) {
+ return file._id;
+ };
+
+ this.getPath = function(file) {
+ if (file.AmazonS3) {
+ return file.AmazonS3.path;
+ }
+ // Compatibility
+ // TODO: Migration
+ if (file.s3) {
+ return file.s3.path + file._id;
+ }
+ };
+
+ this.getRedirectURL = function(file) {
+ const params = {
+ Key: this.getPath(file),
+ Expires: classOptions.URLExpiryTimeSpan
+ };
+
+ return s3.getSignedUrl('getObject', params);
+ };
+
+ /**
+ * Creates the file in the collection
+ * @param file
+ * @param callback
+ * @return {string}
+ */
+ this.create = function(file, callback) {
+ check(file, Object);
+
+ if (file._id == null) {
+ file._id = Random.id();
+ }
+
+ file.AmazonS3 = {
+ path: this.options.getPath(file)
+ };
+
+ file.store = this.options.name; // assign store to file
+ return this.getCollection().insert(file, callback);
+ };
+
+ /**
+ * Removes the file
+ * @param fileId
+ * @param callback
+ */
+ this.delete = function(fileId, callback) {
+ const file = this.getCollection().findOne({_id: fileId});
+ const params = {
+ Key: this.getPath(file)
+ };
+
+ s3.deleteObject(params, (err, data) => {
+ if (err) {
+ console.error(err);
+ }
+
+ callback && callback(err, data);
+ });
+ };
+
+ /**
+ * Returns the file read stream
+ * @param fileId
+ * @param file
+ * @param options
+ * @return {*}
+ */
+ this.getReadStream = function(fileId, file, options = {}) {
+ const params = {
+ Key: this.getPath(file)
+ };
+
+ if (options.start && options.end) {
+ params.Range = `${ options.start } - ${ options.end }`;
+ }
+
+ return s3.getObject(params).createReadStream();
+ };
+
+ /**
+ * Returns the file write stream
+ * @param fileId
+ * @param file
+ * @param options
+ * @return {*}
+ */
+ this.getWriteStream = function(fileId, file/*, options*/) {
+ const writeStream = new stream.PassThrough();
+ writeStream.length = file.size;
+
+ writeStream.on('newListener', (event, listener) => {
+ if (event === 'finish') {
+ process.nextTick(() => {
+ writeStream.removeListener(event, listener);
+ writeStream.on('real_finish', listener);
+ });
+ }
+ });
+
+ s3.putObject({
+ Key: this.getPath(file),
+ Body: writeStream,
+ ContentType: file.type,
+ ContentDisposition: `inline; filename="${ encodeURI(file.name) }"`
+
+ }, (error) => {
+ if (error) {
+ console.error(error);
+ }
+
+ writeStream.emit('real_finish');
+ });
+
+ return writeStream;
+ };
+ }
+}
+
+// Add store to UFS namespace
+UploadFS.store.AmazonS3 = AmazonS3Store;
diff --git a/packages/rocketchat-file-upload/ufs/GoogleStorage/client.js b/packages/rocketchat-file-upload/ufs/GoogleStorage/client.js
new file mode 100644
index 0000000000000..2c11dc0d68285
--- /dev/null
+++ b/packages/rocketchat-file-upload/ufs/GoogleStorage/client.js
@@ -0,0 +1,6 @@
+import {UploadFS} from 'meteor/jalik:ufs';
+
+export class GoogleStorageStore extends UploadFS.Store {}
+
+// Add store to UFS namespace
+UploadFS.store.GoogleStorage = GoogleStorageStore;
diff --git a/packages/rocketchat-file-upload/ufs/GoogleStorage/server.js b/packages/rocketchat-file-upload/ufs/GoogleStorage/server.js
new file mode 100644
index 0000000000000..8a764caac7323
--- /dev/null
+++ b/packages/rocketchat-file-upload/ufs/GoogleStorage/server.js
@@ -0,0 +1,123 @@
+import {UploadFS} from 'meteor/jalik:ufs';
+import gcStorage from '@google-cloud/storage';
+
+/**
+ * GoogleStorage store
+ * @param options
+ * @constructor
+ */
+export class GoogleStorageStore extends UploadFS.Store {
+
+ constructor(options) {
+ super(options);
+
+ const gcs = gcStorage(options.connection);
+ this.bucket = gcs.bucket(options.bucket);
+
+ options.getPath = options.getPath || function(file) {
+ return file._id;
+ };
+
+ this.getPath = function(file) {
+ if (file.GoogleStorage) {
+ return file.GoogleStorage.path;
+ }
+ // Compatibility
+ // TODO: Migration
+ if (file.googleCloudStorage) {
+ return file.googleCloudStorage.path + file._id;
+ }
+ };
+
+ this.getRedirectURL = function(file, callback) {
+ const params = {
+ action: 'read',
+ responseDisposition: 'inline',
+ expires: Date.now()+this.options.URLExpiryTimeSpan*1000
+ };
+
+ this.bucket.file(this.getPath(file)).getSignedUrl(params, callback);
+ };
+
+ /**
+ * Creates the file in the collection
+ * @param file
+ * @param callback
+ * @return {string}
+ */
+ this.create = function(file, callback) {
+ check(file, Object);
+
+ if (file._id == null) {
+ file._id = Random.id();
+ }
+
+ file.GoogleStorage = {
+ path: this.options.getPath(file)
+ };
+
+ file.store = this.options.name; // assign store to file
+ return this.getCollection().insert(file, callback);
+ };
+
+ /**
+ * Removes the file
+ * @param fileId
+ * @param callback
+ */
+ this.delete = function(fileId, callback) {
+ const file = this.getCollection().findOne({_id: fileId});
+ this.bucket.file(this.getPath(file)).delete(function(err, data) {
+ if (err) {
+ console.error(err);
+ }
+
+ callback && callback(err, data);
+ });
+ };
+
+ /**
+ * Returns the file read stream
+ * @param fileId
+ * @param file
+ * @param options
+ * @return {*}
+ */
+ this.getReadStream = function(fileId, file, options = {}) {
+ const config = {};
+
+ if (options.start != null) {
+ config.start = options.start;
+ }
+
+ if (options.end != null) {
+ config.end = options.end;
+ }
+
+ return this.bucket.file(this.getPath(file)).createReadStream(config);
+ };
+
+ /**
+ * Returns the file write stream
+ * @param fileId
+ * @param file
+ * @param options
+ * @return {*}
+ */
+ this.getWriteStream = function(fileId, file/*, options*/) {
+ return this.bucket.file(this.getPath(file)).createWriteStream({
+ gzip: false,
+ metadata: {
+ contentType: file.type,
+ contentDisposition: `inline; filename=${ file.name }`
+ // metadata: {
+ // custom: 'metadata'
+ // }
+ }
+ });
+ };
+ }
+}
+
+// Add store to UFS namespace
+UploadFS.store.GoogleStorage = GoogleStorageStore;
diff --git a/packages/rocketchat-file/.npm/package/.gitignore b/packages/rocketchat-file/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-file/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-file/.npm/package/README b/packages/rocketchat-file/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-file/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-file/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-file/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 212f661b90784..0000000000000
--- a/packages/rocketchat-file/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,79 +0,0 @@
-{
- "dependencies": {
- "array-parallel": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz",
- "from": "array-parallel@>=0.1.3 <0.2.0"
- },
- "array-series": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz",
- "from": "array-series@>=0.1.5 <0.2.0"
- },
- "cross-spawn": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
- "from": "cross-spawn@>=4.0.0 <5.0.0"
- },
- "debug": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
- "from": "debug@>=2.2.0 <2.3.0"
- },
- "flushwritable": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz",
- "from": "flushwritable@>=1.0.0 <2.0.0"
- },
- "gm": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/gm/-/gm-1.23.0.tgz",
- "from": "gm@1.23.0"
- },
- "gridfs-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/gridfs-stream/-/gridfs-stream-1.1.1.tgz",
- "from": "gridfs-stream@1.1.1"
- },
- "isexe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz",
- "from": "isexe@>=1.1.1 <2.0.0"
- },
- "lru-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
- "from": "lru-cache@>=4.0.1 <5.0.0"
- },
- "minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "from": "minimist@0.0.8"
- },
- "mkdirp": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
- "from": "mkdirp@0.5.1"
- },
- "ms": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
- "from": "ms@0.7.1"
- },
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "from": "pseudomap@>=1.0.1 <2.0.0"
- },
- "which": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/which/-/which-1.2.11.tgz",
- "from": "which@>=1.2.9 <2.0.0"
- },
- "yallist": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz",
- "from": "yallist@>=2.0.0 <3.0.0"
- }
- }
-}
diff --git a/packages/rocketchat-file/file.server.coffee b/packages/rocketchat-file/file.server.coffee
deleted file mode 100644
index 75e80a2c0ddcb..0000000000000
--- a/packages/rocketchat-file/file.server.coffee
+++ /dev/null
@@ -1,256 +0,0 @@
-Grid = Npm.require('gridfs-stream')
-stream = Npm.require('stream')
-fs = Npm.require('fs')
-path = Npm.require('path')
-mkdirp = Npm.require('mkdirp')
-gm = Npm.require('gm')
-exec = Npm.require('child_process').exec
-
-# Fix problem with usernames being converted to object id
-Grid.prototype.tryParseObjectId = -> false
-
-RocketChatFile =
- gm: gm
- enabled: undefined
- enable: ->
- RocketChatFile.enabled = true
- RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: undefined}
- disable: ->
- RocketChatFile.enabled = false
- RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server'}
-
-
-detectGM = ->
- exec 'gm version', Meteor.bindEnvironment (error, stdout, stderr) ->
- if not error? and stdout.indexOf('GraphicsMagick') > -1
- RocketChatFile.enable()
-
- RocketChat.Info.GraphicsMagick =
- enabled: true
- version: stdout
- else
- RocketChat.Info.GraphicsMagick =
- enabled: false
-
- exec 'convert -version', Meteor.bindEnvironment (error, stdout, stderr) ->
- if not error? and stdout.indexOf('ImageMagick') > -1
- if RocketChatFile.enabled isnt true
- # Enable GM to work with ImageMagick if no GraphicsMagick
- RocketChatFile.gm = RocketChatFile.gm.subClass({imageMagick: true})
- RocketChatFile.enable()
-
- RocketChat.Info.ImageMagick =
- enabled: true
- version: stdout
- else
- if RocketChatFile.enabled isnt true
- RocketChatFile.disable()
-
- RocketChat.Info.ImageMagick =
- enabled: false
-
-detectGM()
-
-Meteor.methods
- 'detectGM': ->
- detectGM()
- return
-
-
-RocketChatFile.bufferToStream = (buffer) ->
- bufferStream = new stream.PassThrough()
- bufferStream.end buffer
- return bufferStream
-
-RocketChatFile.dataURIParse = (dataURI) ->
- imageData = dataURI.split ';base64,'
- return {
- image: imageData[1]
- contentType: imageData[0].replace('data:', '')
- }
-
-RocketChatFile.addPassThrough = (st, fn) ->
- pass = new stream.PassThrough()
- fn pass, st
- return pass
-
-
-RocketChatFile.GridFS = class
- constructor: (config={}) ->
- {name, transformWrite} = config
-
- name ?= 'file'
-
- this.name = name
- this.transformWrite = transformWrite
-
- mongo = Package.mongo.MongoInternals.NpmModule
- db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db
-
- this.store = new Grid(db, mongo)
- this.findOneSync = Meteor.wrapAsync this.store.collection(this.name).findOne.bind this.store.collection(this.name)
- this.removeSync = Meteor.wrapAsync this.store.remove.bind this.store
-
- this.getFileSync = Meteor.wrapAsync this.getFile.bind this
-
- findOne: (fileName) ->
- return this.findOneSync {_id: fileName}
-
- remove: (fileName) ->
- return this.removeSync
- _id: fileName
- root: this.name
-
- createWriteStream: (fileName, contentType) ->
- self = this
-
- ws = this.store.createWriteStream
- _id: fileName
- filename: fileName
- mode: 'w'
- root: this.name
- content_type: contentType
-
- if self.transformWrite?
- ws = RocketChatFile.addPassThrough ws, (rs, ws) ->
- file =
- name: self.name
- fileName: fileName
- contentType: contentType
-
- self.transformWrite file, rs, ws
-
- ws.on 'close', ->
- ws.emit 'end'
-
- return ws
-
- createReadStream: (fileName) ->
- return this.store.createReadStream
- _id: fileName
- root: this.name
- return undefined
-
- getFileWithReadStream: (fileName) ->
- file = this.findOne fileName
- if not file?
- return undefined
-
- rs = this.createReadStream fileName
-
- return {
- readStream: rs
- contentType: file.contentType
- length: file.length
- uploadDate: file.uploadDate
- }
-
- getFile: (fileName, cb) ->
- file = this.getFileWithReadStream(fileName)
-
- if not file
- return cb()
-
- data = []
- file.readStream.on 'data', Meteor.bindEnvironment (chunk) ->
- data.push chunk
-
- file.readStream.on 'end', Meteor.bindEnvironment ->
- cb null,
- buffer: Buffer.concat(data)
- contentType: file.contentType
- length: file.length
- uploadDate: file.uploadDate
-
- deleteFile: (fileName) ->
- file = this.findOne fileName
- if not file?
- return undefined
-
- return this.remove fileName
-
-
-RocketChatFile.FileSystem = class
- constructor: (config={}) ->
- {absolutePath, transformWrite} = config
-
- absolutePath ?= '~/uploads'
-
- this.transformWrite = transformWrite
-
- if absolutePath.split(path.sep)[0] is '~'
- homepath = process.env.HOME or process.env.HOMEPATH or process.env.USERPROFILE
- if homepath?
- absolutePath = absolutePath.replace '~', homepath
- else
- throw new Error('Unable to resolve "~" in path')
-
- this.absolutePath = path.resolve absolutePath
- mkdirp.sync this.absolutePath
- this.statSync = Meteor.wrapAsync fs.stat.bind fs
- this.unlinkSync = Meteor.wrapAsync fs.unlink.bind fs
-
- this.getFileSync = Meteor.wrapAsync this.getFile.bind this
-
- createWriteStream: (fileName, contentType) ->
- self = this
-
- ws = fs.createWriteStream path.join this.absolutePath, fileName
-
- if self.transformWrite?
- ws = RocketChatFile.addPassThrough ws, (rs, ws) ->
- file =
- fileName: fileName
- contentType: contentType
-
- self.transformWrite file, rs, ws
-
- ws.on 'close', ->
- ws.emit 'end'
-
- return ws
-
- createReadStream: (fileName) ->
- return fs.createReadStream path.join this.absolutePath, fileName
-
- stat: (fileName) ->
- return this.statSync path.join this.absolutePath, fileName
-
- remove: (fileName) ->
- return this.unlinkSync path.join this.absolutePath, fileName
-
- getFileWithReadStream: (fileName) ->
- try
- stat = this.stat fileName
- rs = this.createReadStream fileName
-
- return {
- readStream: rs
- # contentType: file.contentType
- length: stat.size
- }
- catch e
- return undefined
-
- getFile: (fileName, cb) ->
- file = this.getFileWithReadStream(fileName)
-
- if not file
- return cb()
-
- data = []
- file.readStream.on 'data', Meteor.bindEnvironment (chunk) ->
- data.push chunk
-
- file.readStream.on 'end', Meteor.bindEnvironment ->
- buffer: Buffer.concat(data)
- contentType: file.contentType
- length: file.length
- uploadDate: file.uploadDate
-
- deleteFile: (fileName) ->
- try
- stat = this.stat fileName
- return this.remove fileName
- catch e
- return undefined
diff --git a/packages/rocketchat-file/file.server.js b/packages/rocketchat-file/file.server.js
new file mode 100644
index 0000000000000..e4888d56d291e
--- /dev/null
+++ b/packages/rocketchat-file/file.server.js
@@ -0,0 +1,230 @@
+import Grid from 'gridfs-stream';
+import stream from 'stream';
+import fs from 'fs';
+import path from 'path';
+import mkdirp from 'mkdirp';
+
+// Fix problem with usernames being converted to object id
+Grid.prototype.tryParseObjectId = function() {
+ return false;
+};
+//TODO: REMOVE RocketChatFile from globals
+RocketChatFile = {};
+
+RocketChatFile.bufferToStream = function(buffer) {
+ const bufferStream = new stream.PassThrough();
+ bufferStream.end(buffer);
+ return bufferStream;
+};
+
+RocketChatFile.dataURIParse = function(dataURI) {
+ const imageData = dataURI.split(';base64,');
+ return {
+ image: imageData[1],
+ contentType: imageData[0].replace('data:', '')
+ };
+};
+
+RocketChatFile.addPassThrough = function(st, fn) {
+ const pass = new stream.PassThrough();
+ fn(pass, st);
+ return pass;
+};
+
+RocketChatFile.GridFS = class {
+ constructor(config = {}) {
+ const {name = 'file', transformWrite} = config;
+
+ this.name = name;
+ this.transformWrite = transformWrite;
+ const mongo = Package.mongo.MongoInternals.NpmModule;
+ const db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db;
+ this.store = new Grid(db, mongo);
+ this.findOneSync = Meteor.wrapAsync(this.store.collection(this.name).findOne.bind(this.store.collection(this.name)));
+ this.removeSync = Meteor.wrapAsync(this.store.remove.bind(this.store));
+ this.countSync = Meteor.wrapAsync(this.store._col.count.bind(this.store._col));
+ this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this));
+ }
+
+ findOne(fileName) {
+ return this.findOneSync({
+ _id: fileName
+ });
+ }
+
+ remove(fileName) {
+ return this.removeSync({
+ _id: fileName,
+ root: this.name
+ });
+ }
+
+ createWriteStream(fileName, contentType) {
+ const self = this;
+ let ws = this.store.createWriteStream({
+ _id: fileName,
+ filename: fileName,
+ mode: 'w',
+ root: this.name,
+ content_type: contentType
+ });
+ if (self.transformWrite != null) {
+ ws = RocketChatFile.addPassThrough(ws, function(rs, ws) {
+ const file = {
+ name: self.name,
+ fileName,
+ contentType
+ };
+ return self.transformWrite(file, rs, ws);
+ });
+ }
+ ws.on('close', function() {
+ return ws.emit('end');
+ });
+ return ws;
+ }
+
+ createReadStream(fileName) {
+ return this.store.createReadStream({
+ _id: fileName,
+ root: this.name
+ });
+ }
+
+ getFileWithReadStream(fileName) {
+ const file = this.findOne(fileName);
+ if (file == null) {
+ return null;
+ }
+ const rs = this.createReadStream(fileName);
+ return {
+ readStream: rs,
+ contentType: file.contentType,
+ length: file.length,
+ uploadDate: file.uploadDate
+ };
+ }
+
+ getFile(fileName, cb) {
+ const file = this.getFileWithReadStream(fileName);
+ if (!file) {
+ return cb();
+ }
+ const data = [];
+ file.readStream.on('data', Meteor.bindEnvironment(function(chunk) {
+ return data.push(chunk);
+ }));
+ return file.readStream.on('end', Meteor.bindEnvironment(function() {
+ return cb(null, {
+ buffer: Buffer.concat(data),
+ contentType: file.contentType,
+ length: file.length,
+ uploadDate: file.uploadDate
+ });
+ }));
+ }
+
+ deleteFile(fileName) {
+ const file = this.findOne(fileName);
+ if (file == null) {
+ return undefined;
+ }
+ return this.remove(fileName);
+ }
+
+
+};
+
+RocketChatFile.FileSystem = class {
+ constructor(config = {}) {
+ let {absolutePath = '~/uploads'} = config;
+ const {transformWrite} = config;
+
+ this.transformWrite = transformWrite;
+ if (absolutePath.split(path.sep)[0] === '~') {
+ const homepath = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
+ if (homepath != null) {
+ absolutePath = absolutePath.replace('~', homepath);
+ } else {
+ throw new Error('Unable to resolve "~" in path');
+ }
+ }
+ this.absolutePath = path.resolve(absolutePath);
+ mkdirp.sync(this.absolutePath);
+ this.statSync = Meteor.wrapAsync(fs.stat.bind(fs));
+ this.unlinkSync = Meteor.wrapAsync(fs.unlink.bind(fs));
+ this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this));
+ }
+
+ createWriteStream(fileName, contentType) {
+ const self = this;
+ let ws = fs.createWriteStream(path.join(this.absolutePath, fileName));
+ if (self.transformWrite != null) {
+ ws = RocketChatFile.addPassThrough(ws, function(rs, ws) {
+ const file = {
+ fileName,
+ contentType
+ };
+ return self.transformWrite(file, rs, ws);
+ });
+ }
+ ws.on('close', function() {
+ return ws.emit('end');
+ });
+ return ws;
+ }
+
+ createReadStream(fileName) {
+ return fs.createReadStream(path.join(this.absolutePath, fileName));
+ }
+
+ stat(fileName) {
+ return this.statSync(path.join(this.absolutePath, fileName));
+ }
+
+ remove(fileName) {
+ return this.unlinkSync(path.join(this.absolutePath, fileName));
+ }
+
+ getFileWithReadStream(fileName) {
+ try {
+ const stat = this.stat(fileName);
+ const rs = this.createReadStream(fileName);
+ return {
+ readStream: rs,
+ // contentType: file.contentType
+ length: stat.size
+ };
+ } catch (error1) {
+ return null;
+ }
+ }
+
+ getFile(fileName, cb) {
+ const file = this.getFileWithReadStream(fileName);
+ if (!file) {
+ return cb();
+ }
+ const data = [];
+ file.readStream.on('data', Meteor.bindEnvironment(function(chunk) {
+ return data.push(chunk);
+ }));
+ return file.readStream.on('end', Meteor.bindEnvironment(function() {
+ return {
+ buffer: Buffer.concat(data)({
+ contentType: file.contentType,
+ length: file.length,
+ uploadDate: file.uploadDate
+ })
+ };
+ }));
+ }
+
+ deleteFile(fileName) {
+ try {
+ return this.remove(fileName);
+ } catch (error1) {
+ return null;
+ }
+ }
+};
diff --git a/packages/rocketchat-file/package.js b/packages/rocketchat-file/package.js
index cf616d8f1f52f..41dfa74a6faf8 100644
--- a/packages/rocketchat-file/package.js
+++ b/packages/rocketchat-file/package.js
@@ -8,16 +8,9 @@ Package.describe({
Package.onUse(function(api) {
api.use('rocketchat:lib');
api.use('rocketchat:version');
- api.use('coffeescript');
api.use('ecmascript');
- api.addFiles('file.server.coffee', 'server');
+ api.addFiles('file.server.js', 'server');
api.export('RocketChatFile', 'server');
});
-
-Npm.depends({
- 'mkdirp': '0.5.1',
- 'gridfs-stream': '1.1.1',
- 'gm': '1.23.0'
-});
diff --git a/packages/rocketchat-github-enterprise/github-enterprise-login-button.css b/packages/rocketchat-github-enterprise/github-enterprise-login-button.css
index d8593c928a4d5..e7ba61d7be385 100644
--- a/packages/rocketchat-github-enterprise/github-enterprise-login-button.css
+++ b/packages/rocketchat-github-enterprise/github-enterprise-login-button.css
@@ -1,7 +1,9 @@
-.icon-github_enterprise:before {
+.icon-github_enterprise::before {
+ height: 1em;
+
content: "";
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=);
- height: 1em;
- background-position: center center;
background-repeat: no-repeat;
+ background-position: center center;
}
diff --git a/packages/rocketchat-github-enterprise/startup.js b/packages/rocketchat-github-enterprise/startup.js
index e0ace3bf5bf9e..71ded8631fd4b 100644
--- a/packages/rocketchat-github-enterprise/startup.js
+++ b/packages/rocketchat-github-enterprise/startup.js
@@ -6,9 +6,9 @@ RocketChat.settings.addGroup('OAuth', function() {
};
this.add('Accounts_OAuth_GitHub_Enterprise', false, { type: 'boolean' });
- this.add('API_GitHub_Enterprise_URL', '', { type: 'string', public: true, enableQuery: enableQuery, i18nDescription: 'API_GitHub_Enterprise_URL_Description' });
- this.add('Accounts_OAuth_GitHub_Enterprise_id', '', { type: 'string', enableQuery: enableQuery });
- this.add('Accounts_OAuth_GitHub_Enterprise_secret', '', { type: 'string', enableQuery: enableQuery });
- this.add('Accounts_OAuth_GitHub_Enterprise_callback_url', '_oauth/github_enterprise', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery });
+ this.add('API_GitHub_Enterprise_URL', '', { type: 'string', public: true, enableQuery, i18nDescription: 'API_GitHub_Enterprise_URL_Description' });
+ this.add('Accounts_OAuth_GitHub_Enterprise_id', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_GitHub_Enterprise_secret', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_GitHub_Enterprise_callback_url', '_oauth/github_enterprise', { type: 'relativeUrl', readonly: true, force: true, enableQuery });
});
});
diff --git a/packages/rocketchat-gitlab/common.js b/packages/rocketchat-gitlab/common.js
index a241811297976..6a7ed05249383 100644
--- a/packages/rocketchat-gitlab/common.js
+++ b/packages/rocketchat-gitlab/common.js
@@ -14,7 +14,7 @@ const Gitlab = new CustomOAuth('gitlab', config);
if (Meteor.isServer) {
Meteor.startup(function() {
RocketChat.settings.get('API_Gitlab_URL', function(key, value) {
- config.serverURL = value;
+ config.serverURL = value.trim().replace(/\/*$/, '');
Gitlab.configure(config);
});
});
@@ -22,7 +22,7 @@ if (Meteor.isServer) {
Meteor.startup(function() {
Tracker.autorun(function() {
if (RocketChat.settings.get('API_Gitlab_URL')) {
- config.serverURL = RocketChat.settings.get('API_Gitlab_URL');
+ config.serverURL = RocketChat.settings.get('API_Gitlab_URL').trim().replace(/\/*$/, '');
Gitlab.configure(config);
}
});
diff --git a/packages/rocketchat-gitlab/gitlab-login-button.css b/packages/rocketchat-gitlab/gitlab-login-button.css
index d417a55741ade..c73a1ee23c91f 100644
--- a/packages/rocketchat-gitlab/gitlab-login-button.css
+++ b/packages/rocketchat-gitlab/gitlab-login-button.css
@@ -1,3 +1,3 @@
#login-buttons-image-gitlab {
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=);
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=);
}
diff --git a/packages/rocketchat-gitlab/startup.js b/packages/rocketchat-gitlab/startup.js
index 29eb8d3aceec1..f854c79fd7cb7 100644
--- a/packages/rocketchat-gitlab/startup.js
+++ b/packages/rocketchat-gitlab/startup.js
@@ -6,9 +6,9 @@ RocketChat.settings.addGroup('OAuth', function() {
};
this.add('Accounts_OAuth_Gitlab', false, { type: 'boolean', public: true });
- this.add('API_Gitlab_URL', '', { type: 'string', enableQuery: enableQuery, public: true });
- this.add('Accounts_OAuth_Gitlab_id', '', { type: 'string', enableQuery: enableQuery });
- this.add('Accounts_OAuth_Gitlab_secret', '', { type: 'string', enableQuery: enableQuery });
- this.add('Accounts_OAuth_Gitlab_callback_url', '_oauth/gitlab', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery });
+ this.add('API_Gitlab_URL', '', { type: 'string', enableQuery, public: true });
+ this.add('Accounts_OAuth_Gitlab_id', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_Gitlab_secret', '', { type: 'string', enableQuery });
+ this.add('Accounts_OAuth_Gitlab_callback_url', '_oauth/gitlab', { type: 'relativeUrl', readonly: true, force: true, enableQuery });
});
});
diff --git a/packages/rocketchat-api/.npm/package/.gitignore b/packages/rocketchat-google-natural-language/.npm/package/.gitignore
similarity index 100%
rename from packages/rocketchat-api/.npm/package/.gitignore
rename to packages/rocketchat-google-natural-language/.npm/package/.gitignore
diff --git a/packages/rocketchat-api/.npm/package/README b/packages/rocketchat-google-natural-language/.npm/package/README
similarity index 100%
rename from packages/rocketchat-api/.npm/package/README
rename to packages/rocketchat-google-natural-language/.npm/package/README
diff --git a/packages/rocketchat-google-natural-language/client/index.js b/packages/rocketchat-google-natural-language/client/index.js
new file mode 100644
index 0000000000000..4b9ac1c1b8dca
--- /dev/null
+++ b/packages/rocketchat-google-natural-language/client/index.js
@@ -0,0 +1,17 @@
+Template.room.helpers({
+ sentimentSmile() {
+ if (!RocketChat.settings.get('GoogleNaturalLanguage_Enabled')) {
+ return;
+ }
+
+ const room = ChatRoom.findOne(this._id, { fields: { sentiment: 1 } });
+
+ if (room.sentiment >= 0.3) {
+ return ':)';
+ } else if (room.sentiment >= -0.3) {
+ return ':|';
+ } else if (room.sentiment < -0.3) {
+ return ':(';
+ }
+ }
+});
diff --git a/packages/rocketchat-google-natural-language/package.js b/packages/rocketchat-google-natural-language/package.js
new file mode 100644
index 0000000000000..be1ddf61e020a
--- /dev/null
+++ b/packages/rocketchat-google-natural-language/package.js
@@ -0,0 +1,18 @@
+Package.describe({
+ name: 'rocketchat:google-natural-language',
+ version: '0.0.1',
+ summary: 'Rocket.Chat Google Natural Language integration',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use('ecmascript');
+ api.use('http');
+ api.use('templating', 'client');
+
+ api.use('rocketchat:lib');
+ api.use('rocketchat:ui', 'client');
+
+ api.mainModule('client/index.js', 'client');
+ api.mainModule('server/index.js', 'server');
+});
diff --git a/packages/rocketchat-google-natural-language/server/index.js b/packages/rocketchat-google-natural-language/server/index.js
new file mode 100644
index 0000000000000..5055add17340d
--- /dev/null
+++ b/packages/rocketchat-google-natural-language/server/index.js
@@ -0,0 +1,40 @@
+import './settings.js';
+import './models/Rooms.js';
+import googleLanguage from '@google-cloud/language';
+
+let languageClient;
+
+RocketChat.settings.get('GoogleNaturalLanguage_ServiceAccount', (key, value) => {
+ if (value) {
+ try {
+ languageClient = googleLanguage({
+ credentials: JSON.parse(value)
+ });
+ } catch (e) {
+ languageClient = null;
+ console.error('Error parsing Google Natural Language credential.', e);
+ }
+ }
+});
+
+const setRoomSentiment = function(message) {
+ if (!languageClient) {
+ return;
+ }
+
+ languageClient.detectSentiment(message.msg, Meteor.bindEnvironment((error, result) => {
+ if (!error) {
+ RocketChat.models.Rooms.setSentiment(message.rid, result);
+ }
+ }));
+
+ return message;
+};
+
+RocketChat.settings.get('GoogleNaturalLanguage_Enabled', (key, value) => {
+ if (value) {
+ RocketChat.callbacks.add('afterSaveMessage', setRoomSentiment, RocketChat.callbacks.priority.MEDIUM, 'GoogleNaturalLanguage');
+ } else {
+ RocketChat.callbacks.remove('afterSaveMessage', 'GoogleNaturalLanguage');
+ }
+});
diff --git a/packages/rocketchat-google-natural-language/server/models/Rooms.js b/packages/rocketchat-google-natural-language/server/models/Rooms.js
new file mode 100644
index 0000000000000..d08a7df7db403
--- /dev/null
+++ b/packages/rocketchat-google-natural-language/server/models/Rooms.js
@@ -0,0 +1,3 @@
+RocketChat.models.Rooms.setSentiment = function(roomId, sentiment) {
+ return this.update({ _id: roomId }, { $set: { sentiment } });
+};
diff --git a/packages/rocketchat-google-natural-language/server/settings.js b/packages/rocketchat-google-natural-language/server/settings.js
new file mode 100644
index 0000000000000..4541ba662fadb
--- /dev/null
+++ b/packages/rocketchat-google-natural-language/server/settings.js
@@ -0,0 +1,20 @@
+Meteor.startup(function() {
+ RocketChat.settings.add('GoogleNaturalLanguage_Enabled', false, {
+ type: 'boolean',
+ group: 'Message',
+ section: 'Google Natural Language',
+ public: true,
+ i18nLabel: 'Enabled'
+ });
+ RocketChat.settings.add('GoogleNaturalLanguage_ServiceAccount', '', {
+ type: 'string',
+ group: 'Message',
+ section: 'Google Natural Language',
+ multiline: true,
+ enableQuery: {
+ _id: 'GoogleNaturalLanguage_Enabled',
+ value: true
+ },
+ i18nLabel: 'Service_account_key'
+ });
+});
diff --git a/packages/rocketchat-google-vision/README.md b/packages/rocketchat-google-vision/README.md
new file mode 100644
index 0000000000000..75ada0a6d01b8
--- /dev/null
+++ b/packages/rocketchat-google-vision/README.md
@@ -0,0 +1,7 @@
+For this to properly work, you need to have a Google Service Account;
+https://console.cloud.google.com/apis/credentials
+
+Then you have to authorize that service account access to your buckets;
+https://console.cloud.google.com/storage/browser
+To do that, click on the ellipsis by your bucket's row and Edit object default permissions
+Add user and paste the service account e-mail with owner privileges
diff --git a/packages/rocketchat-google-vision/client/googlevision.js b/packages/rocketchat-google-vision/client/googlevision.js
new file mode 100644
index 0000000000000..9191afa4181bb
--- /dev/null
+++ b/packages/rocketchat-google-vision/client/googlevision.js
@@ -0,0 +1,84 @@
+RocketChat.GoogleVision = {
+ getVisionAttributes(attachment) {
+ const attributes = {};
+ const labels = [];
+ if (attachment.labels && attachment.labels.length > 0) {
+ attachment.labels.forEach(label => {
+ labels.push({ label });
+ });
+ }
+ if (attachment.safeSearch && attachment.safeSearch && attachment.safeSearch.adult === true) {
+ labels.push({ label: 'NSFW', bgColor: 'red', fontColor: 'white' });
+ }
+ if (attachment.safeSearch && attachment.safeSearch.violence === true) {
+ labels.push({ label: 'Violence', bgColor: 'red', fontColor: 'white' });
+ }
+ if (attachment.colors && attachment.colors.length > 0) {
+ attributes.color = `#${ attachment.colors[0] }`;
+ }
+ if (attachment.logos && attachment.logos.length > 0) {
+ labels.push({ label: `Logo: ${ attachment.logos[0] }` });
+ }
+ if (attachment.faces && attachment.faces.length > 0) {
+ let faceCount = 0;
+ attachment.faces.forEach(face => {
+ const faceAttributes = [];
+ if (face.joy) {
+ faceAttributes.push('Joy');
+ }
+ if (face.sorrow) {
+ faceAttributes.push('Sorrow');
+ }
+ if (face.anger) {
+ faceAttributes.push('Anger');
+ }
+ if (face.surprise) {
+ faceAttributes.push('Surprise');
+ }
+ if (faceAttributes.length > 0) {
+ labels.push({ label: `Face ${ ++faceCount }: ${ faceAttributes.join(', ') }` });
+ }
+ });
+ }
+ if (labels.length > 0) {
+ attributes.labels = labels;
+ }
+ return attributes;
+ },
+
+ init() {
+ Tracker.autorun(() => {
+ if (RocketChat.settings.get('GoogleVision_Enable')) {
+ RocketChat.callbacks.add('renderMessage', (message) => {
+ if (message.attachments && message.attachments.length > 0) {
+ for (const index in message.attachments) {
+ if (message.attachments.hasOwnProperty(index)) {
+ const attachment = message.attachments[index];
+ message.attachments[index] = Object.assign(message.attachments[index], this.getVisionAttributes(attachment));
+ }
+ }
+ }
+ return message;
+ }, RocketChat.callbacks.priority.HIGH - 3, 'googlevision');
+
+ RocketChat.callbacks.add('streamMessage', (message) => {
+ if (message.attachments && message.attachments.length > 0) {
+ for (const index in message.attachments) {
+ if (message.attachments.hasOwnProperty(index)) {
+ const attachment = message.attachments[index];
+ message.attachments[index] = Object.assign(message.attachments[index], this.getVisionAttributes(attachment));
+ }
+ }
+ }
+ }, RocketChat.callbacks.priority.HIGH - 3, 'googlevision-stream');
+ } else {
+ RocketChat.callbacks.remove('renderMessage', 'googlevision');
+ RocketChat.callbacks.remove('streamMessage', 'googlevision-stream');
+ }
+ });
+ }
+};
+
+Meteor.startup(function() {
+ RocketChat.GoogleVision.init();
+});
diff --git a/packages/rocketchat-google-vision/package.js b/packages/rocketchat-google-vision/package.js
new file mode 100644
index 0000000000000..a42650b27feae
--- /dev/null
+++ b/packages/rocketchat-google-vision/package.js
@@ -0,0 +1,16 @@
+Package.describe({
+ name: 'rocketchat:google-vision',
+ version: '0.0.1',
+ summary: 'Rocket.Chat Google Vision Integration',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'rocketchat:lib'
+ ]);
+
+ api.addFiles('client/googlevision.js', 'client');
+ api.addFiles(['server/settings.js', 'server/googlevision.js', 'server/models/Messages.js'], 'server');
+});
diff --git a/packages/rocketchat-google-vision/server/googlevision.js b/packages/rocketchat-google-vision/server/googlevision.js
new file mode 100644
index 0000000000000..9a701afdf8fd4
--- /dev/null
+++ b/packages/rocketchat-google-vision/server/googlevision.js
@@ -0,0 +1,153 @@
+class GoogleVision {
+ constructor() {
+ this.storage = require('@google-cloud/storage');
+ this.vision = require('@google-cloud/vision');
+ this.storageClient = {};
+ this.visionClient = {};
+ this.enabled = RocketChat.settings.get('GoogleVision_Enable');
+ this.serviceAccount = {};
+ RocketChat.settings.get('GoogleVision_Enable', (key, value) => {
+ this.enabled = value;
+ });
+ RocketChat.settings.get('GoogleVision_ServiceAccount', (key, value) => {
+ try {
+ this.serviceAccount = JSON.parse(value);
+ this.storageClient = this.storage({ credentials: this.serviceAccount });
+ this.visionClient = this.vision({ credentials: this.serviceAccount });
+ } catch (e) {
+ this.serviceAccount = {};
+ }
+ });
+ RocketChat.settings.get('GoogleVision_Block_Adult_Images', (key, value) => {
+ if (value) {
+ RocketChat.callbacks.add('beforeSaveMessage', this.blockUnsafeImages.bind(this), RocketChat.callbacks.priority.MEDIUM, 'googlevision-blockunsafe');
+ } else {
+ RocketChat.callbacks.remove('beforeSaveMessage', 'googlevision-blockunsafe');
+ }
+ });
+ RocketChat.callbacks.add('afterFileUpload', this.annotate.bind(this));
+ }
+
+ incCallCount(count) {
+ const currentMonth = new Date().getMonth();
+ const maxMonthlyCalls = RocketChat.settings.get('GoogleVision_Max_Monthly_Calls') || 0;
+ if (maxMonthlyCalls > 0) {
+ if (RocketChat.settings.get('GoogleVision_Current_Month') !== currentMonth) {
+ RocketChat.settings.set('GoogleVision_Current_Month', currentMonth);
+ if (count > maxMonthlyCalls) {
+ return false;
+ }
+ } else if (count + (RocketChat.settings.get('GoogleVision_Current_Month_Calls') || 0) > maxMonthlyCalls) {
+ return false;
+ }
+ }
+ RocketChat.models.Settings.update({ _id: 'GoogleVision_Current_Month_Calls' }, { $inc: { value: count } });
+ return true;
+ }
+
+ blockUnsafeImages(message) {
+ if (this.enabled && this.serviceAccount && message && message.file && message.file._id) {
+ const file = RocketChat.models.Uploads.findOne({ _id: message.file._id });
+ if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) {
+ if (this.incCallCount(1)) {
+ const bucket = this.storageClient.bucket(RocketChat.settings.get('FileUpload_GoogleStorage_Bucket'));
+ const bucketFile = bucket.file(file.GoogleStorage.path);
+ const results = Meteor.wrapAsync(this.visionClient.detectSafeSearch, this.visionClient)(bucketFile);
+ if (results && results.adult === true) {
+ FileUpload.getStore('Uploads').deleteById(file._id);
+ const user = RocketChat.models.Users.findOneById(message.u && message.u._id);
+ if (user) {
+ RocketChat.Notifications.notifyUser(user._id, 'message', {
+ _id: Random.id(),
+ rid: message.rid,
+ ts: new Date,
+ msg: TAPi18n.__('Adult_images_are_not_allowed', {}, user.language)
+ });
+ }
+ throw new Meteor.Error('GoogleVisionError: Image blocked');
+ }
+ } else {
+ console.error('Google Vision: Usage limit exceeded');
+ }
+ return message;
+ }
+ }
+ }
+
+ annotate({ message }) {
+ const visionTypes = [];
+ if (RocketChat.settings.get('GoogleVision_Type_Document')) {
+ visionTypes.push('document');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Faces')) {
+ visionTypes.push('faces');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Landmarks')) {
+ visionTypes.push('landmarks');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Labels')) {
+ visionTypes.push('labels');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Logos')) {
+ visionTypes.push('logos');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Properties')) {
+ visionTypes.push('properties');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_SafeSearch')) {
+ visionTypes.push('safeSearch');
+ }
+ if (RocketChat.settings.get('GoogleVision_Type_Similar')) {
+ visionTypes.push('similar');
+ }
+ if (this.enabled && this.serviceAccount && visionTypes.length > 0 && message.file && message.file._id) {
+ const file = RocketChat.models.Uploads.findOne({ _id: message.file._id });
+ if (file && file.type && file.type.indexOf('image') !== -1 && file.store === 'GoogleCloudStorage:Uploads' && file.GoogleStorage) {
+ if (this.incCallCount(visionTypes.length)) {
+ const bucket = this.storageClient.bucket(RocketChat.settings.get('FileUpload_GoogleStorage_Bucket'));
+ const bucketFile = bucket.file(file.GoogleStorage.path);
+ this.visionClient.detect(bucketFile, visionTypes, Meteor.bindEnvironment((error, results) => {
+ if (!error) {
+ RocketChat.models.Messages.setGoogleVisionData(message._id, this.getAnnotations(visionTypes, results));
+ } else {
+ console.trace('GoogleVision error: ', error.stack);
+ }
+ }));
+ } else {
+ console.error('Google Vision: Usage limit exceeded');
+ }
+ }
+ }
+ }
+
+ getAnnotations(visionTypes, visionData) {
+ if (visionTypes.length === 1) {
+ const _visionData = {};
+ _visionData[`${ visionTypes[0] }`] = visionData;
+ visionData = _visionData;
+ }
+ const results = {};
+ for (const index in visionData) {
+ if (visionData.hasOwnProperty(index)) {
+ switch (index) {
+ case 'faces':
+ case 'landmarks':
+ case 'labels':
+ case 'similar':
+ case 'logos':
+ results[index] = (results[index] || []).concat(visionData[index] || []);
+ break;
+ case 'safeSearch':
+ results['safeSearch'] = visionData['safeSearch'];
+ break;
+ case 'properties':
+ results['colors'] = visionData[index]['colors'];
+ break;
+ }
+ }
+ }
+ return results;
+ }
+}
+
+RocketChat.GoogleVision = new GoogleVision;
diff --git a/packages/rocketchat-google-vision/server/models/Messages.js b/packages/rocketchat-google-vision/server/models/Messages.js
new file mode 100644
index 0000000000000..47776984618dc
--- /dev/null
+++ b/packages/rocketchat-google-vision/server/models/Messages.js
@@ -0,0 +1,10 @@
+RocketChat.models.Messages.setGoogleVisionData = function(messageId, visionData) {
+ const updateObj = {};
+ for (const index in visionData) {
+ if (visionData.hasOwnProperty(index)) {
+ updateObj[`attachments.0.${ index }`] = visionData[index];
+ }
+ }
+
+ return this.update({ _id: messageId }, { $set: updateObj });
+};
diff --git a/packages/rocketchat-google-vision/server/settings.js b/packages/rocketchat-google-vision/server/settings.js
new file mode 100644
index 0000000000000..5fe8b46776fa2
--- /dev/null
+++ b/packages/rocketchat-google-vision/server/settings.js
@@ -0,0 +1,88 @@
+Meteor.startup(function() {
+ RocketChat.settings.add('GoogleVision_Enable', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ public: true,
+ enableQuery: { _id: 'FileUpload_Storage_Type', value: 'GoogleCloudStorage' }
+ });
+ RocketChat.settings.add('GoogleVision_ServiceAccount', '', {
+ type: 'string',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ multiline: true,
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Max_Monthly_Calls', 0, {
+ type: 'int',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Current_Month', 0, {
+ type: 'int',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ hidden: true
+ });
+ RocketChat.settings.add('GoogleVision_Current_Month_Calls', 0, {
+ type: 'int',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ blocked: true
+ });
+ RocketChat.settings.add('GoogleVision_Type_Document', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_Faces', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_Landmarks', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_Labels', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_Logos', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_Properties', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Type_SafeSearch', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+ RocketChat.settings.add('GoogleVision_Block_Adult_Images', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: [{ _id: 'GoogleVision_Enable', value: true }, { _id: 'GoogleVision_Type_SafeSearch', value: true }]
+ });
+ RocketChat.settings.add('GoogleVision_Type_Similar', false, {
+ type: 'boolean',
+ group: 'FileUpload',
+ section: 'Google Vision',
+ enableQuery: { _id: 'GoogleVision_Enable', value: true }
+ });
+});
diff --git a/packages/rocketchat-grant-facebook/README.md b/packages/rocketchat-grant-facebook/README.md
new file mode 100644
index 0000000000000..9d2da06860b2f
--- /dev/null
+++ b/packages/rocketchat-grant-facebook/README.md
@@ -0,0 +1,3 @@
+# rocketchat:grant-facebook
+
+An implementation of the Facebook OAuth flow.
diff --git a/packages/rocketchat-grant-facebook/package.js b/packages/rocketchat-grant-facebook/package.js
new file mode 100644
index 0000000000000..ad67058dde827
--- /dev/null
+++ b/packages/rocketchat-grant-facebook/package.js
@@ -0,0 +1,16 @@
+Package.describe({
+ name: 'rocketchat:grant-facebook',
+ version: '0.0.1',
+ summary: 'Provides Facebook to rocketchat:grant',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'http',
+ 'rocketchat:grant'
+ ]);
+
+ api.mainModule('server/index.js', 'server');
+});
diff --git a/packages/rocketchat-grant-facebook/server/index.js b/packages/rocketchat-grant-facebook/server/index.js
new file mode 100644
index 0000000000000..7dc87f6494f9a
--- /dev/null
+++ b/packages/rocketchat-grant-facebook/server/index.js
@@ -0,0 +1,56 @@
+import { Providers, GrantError } from 'meteor/rocketchat:grant';
+import { HTTP } from 'meteor/http';
+
+const userAgent = 'Meteor';
+const version = 'v2.10';
+
+function getIdentity(accessToken, fields) {
+ try {
+ return HTTP.get(
+ `https://graph.facebook.com/${ version }/me`, {
+ headers: { 'User-Agent': userAgent },
+ params: {
+ access_token: accessToken,
+ fields: fields.join(',')
+ }
+ }).data;
+ } catch (err) {
+ throw new GrantError(`Failed to fetch identity from Facebook. ${ err.message }`);
+ }
+}
+
+function getPicture(accessToken) {
+ try {
+ return HTTP.get(
+ `https://graph.facebook.com/${ version }/me/picture`, {
+ headers: { 'User-Agent': userAgent },
+ params: {
+ redirect: false,
+ height: 200,
+ width: 200,
+ type: 'normal',
+ access_token: accessToken
+ }
+ }).data;
+ } catch (err) {
+ throw new GrantError(`Failed to fetch profile picture from Facebook. ${ err.message }`);
+ }
+}
+
+export function getUser(accessToken) {
+ const whitelisted = ['id', 'email', 'name', 'first_name', 'last_name'];
+ const identity = getIdentity(accessToken, whitelisted);
+ const avatar = getPicture(accessToken);
+ const username = identity.name.toLowerCase().replace(' ', '.');
+
+ return {
+ id: identity.id,
+ email: identity.email,
+ username,
+ name: `${ identity.first_name } ${ identity.last_name }`,
+ avatar: avatar.data.url
+ };
+}
+
+// Register Facebook OAuth
+Providers.register('facebook', { scope: ['public_profile', 'email'] }, getUser);
diff --git a/packages/rocketchat-grant-github/README.md b/packages/rocketchat-grant-github/README.md
new file mode 100644
index 0000000000000..e5fea3c781c72
--- /dev/null
+++ b/packages/rocketchat-grant-github/README.md
@@ -0,0 +1,3 @@
+# rocketchat:grant-github
+
+An implementation of the GitHub OAuth flow.
diff --git a/packages/rocketchat-grant-github/package.js b/packages/rocketchat-grant-github/package.js
new file mode 100644
index 0000000000000..0e3ce2d86198e
--- /dev/null
+++ b/packages/rocketchat-grant-github/package.js
@@ -0,0 +1,16 @@
+Package.describe({
+ name: 'rocketchat:grant-github',
+ version: '0.0.1',
+ summary: 'Provides GitHub to rocketchat:grant',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'http',
+ 'rocketchat:grant'
+ ]);
+
+ api.mainModule('server/index.js', 'server');
+});
diff --git a/packages/rocketchat-grant-github/server/index.js b/packages/rocketchat-grant-github/server/index.js
new file mode 100644
index 0000000000000..1358986420c34
--- /dev/null
+++ b/packages/rocketchat-grant-github/server/index.js
@@ -0,0 +1,46 @@
+import { Providers, GrantError } from 'meteor/rocketchat:grant';
+import { HTTP } from 'meteor/http';
+
+const userAgent = 'Meteor';
+
+function getIdentity(accessToken) {
+ try {
+ return HTTP.get(
+ 'https://api.github.com/user', {
+ headers: { 'User-Agent': userAgent }, // http://developer.github.com/v3/#user-agent-required
+ params: { access_token: accessToken }
+ }).data;
+ } catch (err) {
+ throw new GrantError(`Failed to fetch identity from Github. ${ err.message }`);
+ }
+}
+
+function getEmails(accessToken) {
+ try {
+ return HTTP.get(
+ 'https://api.github.com/user/emails', {
+ headers: { 'User-Agent': userAgent }, // http://developer.github.com/v3/#user-agent-required
+ params: { access_token: accessToken }
+ }).data;
+ } catch (err) {
+ return [];
+ }
+}
+
+export function getUser(accessToken) {
+ const identity = getIdentity(accessToken);
+ const emails = getEmails(accessToken);
+ const primaryEmail = (emails || []).find(email => email.primary === true);
+
+ return {
+ id: identity.id,
+ email: identity.email || (primaryEmail && primaryEmail.email) || '',
+ username: identity.login,
+ emails,
+ name: identity.name,
+ avatar: identity.avatar_url
+ };
+}
+
+// Register GitHub OAuth
+Providers.register('github', { scope: ['user', 'user:email'] }, getUser);
diff --git a/packages/rocketchat-grant-google/README.md b/packages/rocketchat-grant-google/README.md
new file mode 100644
index 0000000000000..cdd59d97b562f
--- /dev/null
+++ b/packages/rocketchat-grant-google/README.md
@@ -0,0 +1,3 @@
+# rocketchat:grant-google
+
+An implementation of the Google OAuth flow.
diff --git a/packages/rocketchat-grant-google/package.js b/packages/rocketchat-grant-google/package.js
new file mode 100644
index 0000000000000..b0a538c44e57e
--- /dev/null
+++ b/packages/rocketchat-grant-google/package.js
@@ -0,0 +1,16 @@
+Package.describe({
+ name: 'rocketchat:grant-google',
+ version: '0.0.1',
+ summary: 'Provides Google to rocketchat:grant',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'http',
+ 'rocketchat:grant'
+ ]);
+
+ api.mainModule('server/index.js', 'server');
+});
diff --git a/packages/rocketchat-grant-google/server/index.js b/packages/rocketchat-grant-google/server/index.js
new file mode 100644
index 0000000000000..f1cf2ae853a66
--- /dev/null
+++ b/packages/rocketchat-grant-google/server/index.js
@@ -0,0 +1,38 @@
+import { Providers, GrantError } from 'meteor/rocketchat:grant';
+import { HTTP } from 'meteor/http';
+
+const userAgent = 'Meteor';
+
+function getIdentity(accessToken) {
+ try {
+ return HTTP.get(
+ 'https://www.googleapis.com/oauth2/v1/userinfo', {
+ headers: { 'User-Agent': userAgent },
+ params: {
+ access_token: accessToken
+ }
+ }).data;
+ } catch (err) {
+ throw new GrantError(`Failed to fetch identity from Google. ${ err.message }`);
+ }
+}
+
+export function getUser(accessToken) {
+ const whitelisted = [
+ 'id', 'email', 'verified_email', 'name',
+ 'given_name', 'family_name', 'picture'
+ ];
+ const identity = getIdentity(accessToken, whitelisted);
+ const username = `${ identity.given_name.toLowerCase() }.${ identity.family_name.toLowerCase() }`;
+
+ return {
+ id: identity.id,
+ email: identity.email,
+ username,
+ name: identity.name,
+ avatar: identity.picture
+ };
+}
+
+// Register Google OAuth
+Providers.register('google', { scope: ['openid', 'email'] }, getUser);
diff --git a/packages/rocketchat-assets/.npm/package/.gitignore b/packages/rocketchat-grant/.npm/package/.gitignore
similarity index 100%
rename from packages/rocketchat-assets/.npm/package/.gitignore
rename to packages/rocketchat-grant/.npm/package/.gitignore
diff --git a/packages/rocketchat-assets/.npm/package/README b/packages/rocketchat-grant/.npm/package/README
similarity index 100%
rename from packages/rocketchat-assets/.npm/package/README
rename to packages/rocketchat-grant/.npm/package/README
diff --git a/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json
new file mode 100644
index 0000000000000..0f2cc65af3df3
--- /dev/null
+++ b/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json
@@ -0,0 +1,539 @@
+{
+ "lockfileVersion": 1,
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",
+ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo="
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
+ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY="
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40="
+ },
+ "boom": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk="
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+ },
+ "content-type": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0="
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "crc": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz",
+ "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms="
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g="
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz",
+ "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4="
+ },
+ "deep-copy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/deep-copy/-/deep-copy-1.2.0.tgz",
+ "integrity": "sha1-X7KnqV9UVUc9fOOaOS9Cw1FOEeg="
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "etag": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz",
+ "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE="
+ },
+ "express": {
+ "version": "4.15.3",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz",
+ "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI="
+ },
+ "express-session": {
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.4.tgz",
+ "integrity": "sha1-Xizc9t7+PB7aTpgPE7mGzFjPuVQ=",
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "finalhandler": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz",
+ "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE="
+ },
+ "forwarded": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz",
+ "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M="
+ },
+ "fresh": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz",
+ "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44="
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "grant": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/grant/-/grant-3.8.0.tgz",
+ "integrity": "sha512-Q8UN1j9JQmmb/Wf7PlYXJn92IjX9Tio21rEV5jOte/novOaZ/l0xMWNel7CDbRw0zqFEnYIIAyh1Cri2u3poUw=="
+ },
+ "grant-express": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/grant-express/-/grant-express-3.8.0.tgz",
+ "integrity": "sha512-Ph3SSr8vQTt9igZn4GAARjfOYPlB3nxngs0NwBqFNPbBdSPf+m5keEibfrP2GfeYK1GCYoz85BPQzQQZYbBzpQ=="
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
+ "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4="
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
+ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio="
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ="
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+ },
+ "http-errors": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz",
+ "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=",
+ "dependencies": {
+ "depd": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
+ "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
+ }
+ }
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8="
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ipaddr.js": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz",
+ "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA="
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8="
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM="
+ },
+ "mime-db": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz",
+ "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg="
+ },
+ "mime-types": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz",
+ "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
+ },
+ "on-headers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
+ },
+ "parseurl": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
+ "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
+ "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU="
+ },
+ "proxy-addr": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz",
+ "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg="
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "qs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+ "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
+ },
+ "random-bytes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+ "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "request": {
+ "version": "2.81.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
+ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA="
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "send": {
+ "version": "0.15.3",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz",
+ "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk="
+ },
+ "serve-static": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz",
+ "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI="
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg="
+ },
+ "sshpk": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+ "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+ "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo="
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0="
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
+ },
+ "uid-safe": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+ "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA=="
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
+ "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg="
+ },
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ },
+ "vary": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz",
+ "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ }
+ }
+}
diff --git a/packages/rocketchat-grant/README.md b/packages/rocketchat-grant/README.md
new file mode 100644
index 0000000000000..716b57bfcf802
--- /dev/null
+++ b/packages/rocketchat-grant/README.md
@@ -0,0 +1,101 @@
+# rocketchat:grant
+
+The main idea behind creating this package was to allow external apps (i.e. PWA) to use OAuth smoothely with currently available accounts system.
+
+## Usage
+
+1. Define providers using `Settings.add()`
+1. Add apps with `Settings.apps.add()`
+1. Put the path that stars OAuth flow in your app
+1. You app should be able to authenticate user with received tokens
+
+## Paths
+
+There are few paths you need to be familiar with.
+
+### Start OAuth flow
+
+> \/_oauth_apps/connect/\/\
+
+### Authorization callback URL
+
+> \/_oauth_apps/connect/\/callback
+
+### List of available providers
+
+> \/_oauth_apps/providers
+
+## API
+
+### Providers
+
+#### Providers.register(name, options, getUser)
+
+Allows to register an OAuth Provider.
+
+- name - string that represents the name of an OAuth provider
+- options - contains fields like _scope_
+- getUser - a function that returns fields: _id, email, username, name and avatar_
+
+### Settings
+
+#### Settings.add(options)
+
+Defines a provider that is able for being used in OAuth.
+
+**options**:
+
+- enabled - __boolean__ - tells to `rocketchat:grant` if provider could be used
+- provider - __string__ - id of a provider
+- key - __string__ - client ID provided for your OAuth access
+- secret - __string__ - secret key
+
+Example:
+
+```js
+ Settings.add({
+ enabled: true,
+ provider: 'google',
+ key: 'CLIENT_ID',
+ secret: 'SECRET'
+ });
+```
+
+#### Settings.apps.add(name, options)
+
+Defines an app that is able for using OAuth.
+
+**options**:
+
+- redirectUrl - __string__ - where to redirect if auth was succesful
+- errorUrl - __string__ - place to redirect on failure
+
+Example:
+
+```js
+
+ const redirectUrl = 'http://localhost:4200/login?service={provider}&access_token={accessToken}&refresh_token={refreshToken}';
+
+ const errorUrl = 'http://localhost:4200/login?service={provider}&error={error}'
+
+
+ Settings.apps.add('PWA', {
+ redirectUrl,
+ errorUrl
+ });
+```
+
+About URLs:
+
+We use a parser to produce a URL.
+There are few available variables for each type of redirect.
+
+- redirectUrl - provider, accessToken, refreshToken
+- errorUrl - provider, error
+
+Example:
+
+```
+http://localhost:4200/login?provider={provider}
+// outputs: http://localhost:4200/login?provider=google
+```
diff --git a/packages/rocketchat-grant/package.js b/packages/rocketchat-grant/package.js
new file mode 100644
index 0000000000000..bec938b3cb229
--- /dev/null
+++ b/packages/rocketchat-grant/package.js
@@ -0,0 +1,25 @@
+Package.describe({
+ name: 'rocketchat:grant',
+ version: '0.0.1',
+ summary: 'OAuth2',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'webapp',
+ 'mongo',
+ 'check',
+ 'ecmascript',
+ 'rocketchat:lib',
+ 'rocketchat:accounts'
+ ]);
+
+ api.mainModule('server/index.js', 'server');
+});
+
+Npm.depends({
+ 'express': '4.15.3',
+ 'express-session': '1.15.4',
+ 'grant-express': '3.8.0'
+});
diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js
new file mode 100644
index 0000000000000..7e5aae261e1fa
--- /dev/null
+++ b/packages/rocketchat-grant/server/authenticate.js
@@ -0,0 +1,111 @@
+import { AccountsServer } from 'meteor/rocketchat:accounts';
+import { RocketChat } from 'meteor/rocketchat:lib';
+import { Accounts } from 'meteor/accounts-base';
+import { Meteor } from 'meteor/meteor';
+
+import { GrantError } from './error';
+import Providers from './providers';
+
+const setAvatarFromUrl = (userId, url) => {
+ return new Promise((resolve, reject) => {
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setAvatarFromService', url, '', 'url', (err) => {
+ if (err) {
+ if (err.details.timeToReset && err.details.timeToReset) {
+ reject((t('error-too-many-requests', {
+ seconds: parseInt(err.details.timeToReset / 1000)
+ })));
+ } else {
+ reject(t('Avatar_url_invalid_or_error'));
+ }
+ } else {
+ resolve();
+ }
+ });
+ });
+ });
+};
+
+const findUserByOAuthId = (providerName, id) => {
+ return RocketChat.models.Users.findOne({ [`settings.profile.oauth.${ providerName }`]: id });
+};
+
+const addOAuthIdToUserProfile = (user, providerName, providerId) => {
+ const profile = Object.assign({}, user.settings.profile, {
+ oauth: {
+ ...user.settings.profile.oauth,
+ [providerName]: providerId
+ }
+ });
+
+ RocketChat.models.Users.setProfile(user.id, profile);
+};
+
+function getAccessToken(req) {
+ const i = req.url.indexOf('?');
+
+ if (i === -1) {
+ return;
+ }
+
+ const barePath = req.url.substring(i + 1);
+ const splitPath = barePath.split('&');
+ const token = splitPath.find(p => p.match(/access_token=[a-zA-Z0-9]+/));
+
+ if (token) {
+ return token.replace('access_token=', '');
+ }
+}
+
+export async function authenticate(providerName, req) {
+ let tokens;
+ const accessToken = getAccessToken(req);
+ const provider = Providers.get(providerName);
+
+ if (!provider) {
+ throw new GrantError(`Provider '${ providerName }' not found`);
+ }
+
+ const userData = provider.getUser(accessToken);
+
+ let user = findUserByOAuthId(providerName, userData.id);
+
+ if (user) {
+ user.id = user._id;
+ } else {
+ user = RocketChat.models.Users.findOneByEmailAddress(userData.email);
+ if (user) {
+ user.id = user._id;
+ }
+ }
+
+ if (user) {
+ addOAuthIdToUserProfile(user, providerName, userData.id);
+
+ const loginResult = await AccountsServer.loginWithUser({ id: user.id });
+
+ tokens = loginResult.tokens;
+ } else {
+ const id = Accounts.createUser({
+ email: userData.email,
+ username: userData.username
+ });
+
+ RocketChat.models.Users.setProfile(id, {
+ avatar: userData.avatar,
+ oauth: {
+ [providerName]: userData.id
+ }
+ });
+ RocketChat.models.Users.setName(id, userData.name);
+ RocketChat.models.Users.setEmailVerified(id, userData.email);
+
+ await setAvatarFromUrl(id, userData.avatar);
+
+ const loginResult = await AccountsServer.loginWithUser({ id });
+
+ tokens = loginResult.tokens;
+ }
+
+ return tokens;
+}
diff --git a/packages/rocketchat-grant/server/error.js b/packages/rocketchat-grant/server/error.js
new file mode 100644
index 0000000000000..16ab38913db88
--- /dev/null
+++ b/packages/rocketchat-grant/server/error.js
@@ -0,0 +1,5 @@
+export class GrantError extends Error {
+ constructor(...args) {
+ super(...args);
+ }
+}
diff --git a/packages/rocketchat-grant/server/grant.js b/packages/rocketchat-grant/server/grant.js
new file mode 100644
index 0000000000000..b4adfd3081dd3
--- /dev/null
+++ b/packages/rocketchat-grant/server/grant.js
@@ -0,0 +1,53 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import Providers from './providers';
+import Settings from './settings';
+import { path, generateCallback, generateAppCallback } from './routes';
+
+function addProviders(config) {
+ Settings.forEach((settings, providerName) => {
+ if (settings.enabled === true) {
+ const registeredProvider = Providers.get(providerName);
+
+ if (!registeredProvider) {
+ console.error(`No configuration for '${ providerName }' provider`);
+ }
+
+ // basic settings
+ const data = {
+ key: settings.key,
+ secret: settings.secret,
+ scope: registeredProvider.scope,
+ callback: generateCallback(providerName)
+ };
+
+ // set each app
+ Settings.apps.forEach((_, appName) => {
+ data[appName] = {
+ callback: generateAppCallback(providerName, appName)
+ };
+ });
+
+ config[providerName] = data;
+ }
+ });
+}
+
+const config = {};
+
+export function generateConfig() {
+ config['server'] = {
+ protocol: 'http',
+ host: RocketChat.hostname,
+ path,
+ state: true
+ };
+
+ addProviders(config);
+
+ return config;
+}
+
+export function getConfig() {
+ return config;
+}
diff --git a/packages/rocketchat-grant/server/index.js b/packages/rocketchat-grant/server/index.js
new file mode 100644
index 0000000000000..5aec92218200d
--- /dev/null
+++ b/packages/rocketchat-grant/server/index.js
@@ -0,0 +1,57 @@
+import { WebApp } from 'meteor/webapp';
+import session from 'express-session';
+import Grant from 'grant-express';
+import fiber from 'fibers';
+
+import { GrantError } from './error';
+import { generateConfig } from './grant';
+import { path, generateCallback, generateAppCallback } from './routes';
+import { middleware as redirect } from './redirect';
+import Providers, { middleware as providers } from './providers';
+import Settings from './settings';
+
+let grant;
+
+WebApp.connectHandlers.use(session({
+ secret: 'grant',
+ resave: true,
+ saveUninitialized: true
+}));
+
+// grant
+WebApp.connectHandlers.use(path, (req, res, next) => {
+ if (grant) {
+ grant(req, res, next);
+ } else {
+ next();
+ }
+});
+
+// callbacks
+WebApp.connectHandlers.use((req, res, next) => {
+ fiber(() => {
+ redirect(req, res, next);
+ }).run();
+});
+
+// providers
+WebApp.connectHandlers.use((req, res, next) => {
+ fiber(() => {
+ providers(req, res, next);
+ }).run();
+});
+
+Meteor.startup(() => {
+ const config = generateConfig();
+
+ grant = new Grant(config);
+});
+
+export {
+ path,
+ generateCallback,
+ generateAppCallback,
+ Providers,
+ Settings,
+ GrantError
+};
diff --git a/packages/rocketchat-grant/server/providers.js b/packages/rocketchat-grant/server/providers.js
new file mode 100644
index 0000000000000..debad8d091e86
--- /dev/null
+++ b/packages/rocketchat-grant/server/providers.js
@@ -0,0 +1,41 @@
+import { check } from 'meteor/check';
+
+import { Storage } from './storage';
+import { routes } from './routes';
+
+class Providers extends Storage {
+ register(name, options, getUser) {
+ check(name, String);
+ check(options, {
+ // eslint-disable-next-line
+ scope: Match.OneOf(String, [String])
+ });
+ check(getUser, Function);
+
+ this._add(name.toLowerCase(), {
+ scope: options.scope,
+ getUser
+ });
+ }
+}
+
+const providers = new Providers;
+
+export default providers;
+
+export function middleware(req, res, next) {
+ const route = routes.providers(req);
+
+ if (route) {
+ const list = [];
+
+ providers.forEach((_, name) => list.push(name));
+
+ res.end(JSON.stringify({
+ data: list
+ }));
+ return;
+ }
+
+ next();
+}
diff --git a/packages/rocketchat-grant/server/redirect.js b/packages/rocketchat-grant/server/redirect.js
new file mode 100644
index 0000000000000..2423758f48ca5
--- /dev/null
+++ b/packages/rocketchat-grant/server/redirect.js
@@ -0,0 +1,54 @@
+import { authenticate } from './authenticate';
+import Settings from './settings';
+import { routes } from './routes';
+import { GrantError } from './error';
+
+function parseUrl(url, config) {
+ return url.replace(/\{[\ ]*(provider|accessToken|refreshToken|error)[\ ]*\}/g, (_, key) => config[key]);
+}
+
+function getAppConfig(providerName, appName) {
+ const providerConfig = Settings.get(providerName);
+
+ if (providerConfig) {
+ return Settings.apps.get(appName);
+ }
+}
+
+export async function middleware(req, res, next) {
+ const route = routes.appCallback(req);
+
+ // handle app callback
+ if (route) {
+ const config = {
+ provider: route.provider
+ };
+ const appConfig = getAppConfig(route.provider, route.app);
+
+ if (appConfig) {
+ const {
+ redirectUrl,
+ errorUrl
+ } = appConfig;
+
+ try {
+ const tokens = await authenticate(route.provider, req);
+
+ config.accessToken = tokens.accessToken;
+ config.refreshToken = tokens.refreshToken;
+
+ res.redirect(parseUrl(redirectUrl, config));
+ return;
+ } catch (error) {
+ config.error = error instanceof GrantError ? error.message : 'Something went wrong';
+
+ console.error(error);
+
+ res.redirect(parseUrl(errorUrl, config));
+ return;
+ }
+ }
+ }
+
+ next();
+}
diff --git a/packages/rocketchat-grant/server/routes.js b/packages/rocketchat-grant/server/routes.js
new file mode 100644
index 0000000000000..041156f2abca6
--- /dev/null
+++ b/packages/rocketchat-grant/server/routes.js
@@ -0,0 +1,48 @@
+export const path = '/_oauth_apps';
+
+export function generateCallback(providerName) {
+ return `${ path }/${ providerName }/callback`;
+}
+
+export function generateAppCallback(providerName, appName) {
+ return generateCallback(`${ providerName }/${ appName }`);
+}
+
+export function getPaths(req) {
+ const i = req.url.indexOf('?');
+ let barePath;
+
+ if (i === -1) {
+ barePath = req.url;
+ } else {
+ barePath = req.url.substring(0, i);
+ }
+
+ const splitPath = barePath.split('/');
+
+ // Any non-oauth request will continue down the default
+ // middlewares.
+ if (splitPath[1] === '_oauth_apps') {
+ return splitPath.slice(2);
+ }
+}
+
+export const routes = {
+ // :path/:provider/:app/callback
+ appCallback: (req) => {
+ const paths = getPaths(req);
+
+ if (paths && paths[2] === 'callback') {
+ return {
+ provider: paths[0],
+ app: paths[1]
+ };
+ }
+ },
+ // :path/providers
+ providers: (req) => {
+ const paths = getPaths(req);
+
+ return paths && paths[0] === 'providers';
+ }
+};
diff --git a/packages/rocketchat-grant/server/settings.js b/packages/rocketchat-grant/server/settings.js
new file mode 100644
index 0000000000000..e53b466fa87f2
--- /dev/null
+++ b/packages/rocketchat-grant/server/settings.js
@@ -0,0 +1,42 @@
+import { check } from 'meteor/check';
+
+import { Storage } from './storage';
+
+class Apps extends Storage {
+ add(name, body) {
+ check(name, String);
+ check(body, {
+ redirectUrl: String,
+ errorUrl: String
+ });
+
+ this._add(name, body);
+ }
+}
+
+class Settings extends Storage {
+ constructor() {
+ super();
+
+ this.apps = new Apps;
+ }
+ add(settings) {
+ check(settings, {
+ enabled: Match.Optional(Boolean),
+ provider: String,
+ key: String,
+ secret: String
+ });
+
+ this._add(settings.provider, {
+ enabled: settings.enabled === true,
+ provider: settings.provider,
+ key: settings.key,
+ secret: settings.secret
+ });
+ }
+}
+
+const settings = new Settings;
+
+export default settings;
diff --git a/packages/rocketchat-grant/server/storage.js b/packages/rocketchat-grant/server/storage.js
new file mode 100644
index 0000000000000..90d506681a835
--- /dev/null
+++ b/packages/rocketchat-grant/server/storage.js
@@ -0,0 +1,33 @@
+export class Storage {
+ constructor() {
+ this._data = {};
+ }
+
+ all() {
+ return this._data;
+ }
+
+ forEach(fn) {
+ Object.keys(this.all())
+ .forEach((name) => {
+ fn(this.get(name), name);
+ });
+ }
+
+ get(name) {
+ return this.all()[name.toLowerCase()];
+ }
+
+ has(name) {
+ return !!this._data[name];
+ }
+
+ _add(name, body) {
+ if (this.has(name)) {
+ console.error(`'${ name }' have been already defined`);
+ return;
+ }
+
+ this._data[name] = body;
+ }
+}
diff --git a/packages/rocketchat-autolinker/.npm/package/.gitignore b/packages/rocketchat-graphql/.npm/package/.gitignore
similarity index 100%
rename from packages/rocketchat-autolinker/.npm/package/.gitignore
rename to packages/rocketchat-graphql/.npm/package/.gitignore
diff --git a/packages/rocketchat-autolinker/.npm/package/README b/packages/rocketchat-graphql/.npm/package/README
similarity index 100%
rename from packages/rocketchat-autolinker/.npm/package/README
rename to packages/rocketchat-graphql/.npm/package/README
diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json
new file mode 100644
index 0000000000000..ebd390267c543
--- /dev/null
+++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json
@@ -0,0 +1,590 @@
+{
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@accounts/common": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@accounts/common/-/common-0.0.4.tgz",
+ "integrity": "sha1-xaPs4coEYr38Au1JWWLeBhmiQ5Y="
+ },
+ "@accounts/graphql-api": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@accounts/graphql-api/-/graphql-api-0.1.1.tgz",
+ "integrity": "sha1-Dg6PHFumsZce9PIjnlnJRyWRtpo="
+ },
+ "@accounts/server": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@accounts/server/-/server-0.0.4.tgz",
+ "integrity": "sha1-5UU5kczficvmSVxuHK1BPEHgLJM="
+ },
+ "@types/graphql": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.9.4.tgz",
+ "integrity": "sha512-ob2dps4itT/Le5DbxjssBXtBnloDIRUbkgtAvaB42mJ8pVIWMRuURD9WjnhaEGZ4Ql/EryXMQWeU8Y0EU73QLw=="
+ },
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8="
+ },
+ "apollo-cache-control": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.0.7.tgz",
+ "integrity": "sha512-DoMTr3uTC5Cx9ukSO63wlzHD15C37FwZuoOZEu+m/UTzVFKQ4PnlBKzwZ0H2+iIwcdSulV0xte6Z3wBe9lHAOA=="
+ },
+ "apollo-server-core": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-1.3.0.tgz",
+ "integrity": "sha1-p50ppw6BUKqKAUMjThFZS6QczI0="
+ },
+ "apollo-server-express": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-1.1.2.tgz",
+ "integrity": "sha1-aTPHf+XfuafzDdOTI5rZlTphPNk="
+ },
+ "apollo-server-module-graphiql": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.3.0.tgz",
+ "integrity": "sha1-B3u4x78pL2EoxsltWcIJZEWwhO8="
+ },
+ "apollo-tracing": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.1.1.tgz",
+ "integrity": "sha512-OrL0SYpmwNs6R339y7Is6PppOkyooMB1iLSN+HAp1FdBycQ88SqVV5Dqjxb4Du+TrMyyJLHfR5BAENZSFQyWGQ=="
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "async-limiter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+ },
+ "babel-polyfill": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
+ }
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4="
+ },
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+ },
+ "base64url": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
+ "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
+ },
+ "bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
+ },
+ "body-parser": {
+ "version": "1.17.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz",
+ "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4="
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
+ "bytes": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "core-js": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
+ "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4="
+ },
+ "cors": {
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz",
+ "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY="
+ },
+ "crypto": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz",
+ "integrity": "sha1-RwqBuGvkxe4XrMggeh9TFa4g27A="
+ },
+ "debug": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz",
+ "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=",
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "deepmerge": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
+ "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
+ },
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
+ },
+ "deprecated-decorator": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz",
+ "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "ecdsa-sig-formatter": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz",
+ "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA="
+ },
+ "es6-promise": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz",
+ "integrity": "sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng=="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo="
+ },
+ "express": {
+ "version": "4.15.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
+ "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "qs": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz",
+ "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg=="
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz",
+ "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=",
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ }
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz",
+ "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44="
+ },
+ "graphql": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz",
+ "integrity": "sha1-wxOv1VGOZzNRvuGPtj4qDkh0B6s="
+ },
+ "graphql-extensions": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.0.5.tgz",
+ "integrity": "sha512-IbgYhKIyI60Nio/uJjkkiXaOZ2fI8ynAyzcA/okD0iuKzBdWX4Tn6tidMLgd16Bf2v3TtNnyXnN0F2BJDs6e4A=="
+ },
+ "graphql-subscriptions": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz",
+ "integrity": "sha512-hqfUsZv39qmK4SEoKMnTO05U4EVvIeAD4ai5ztE9gCl4hEdeaF2Q5gvF80ONQQAnkys4odzxWYd2tBLS/cWl8g=="
+ },
+ "graphql-tag": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.6.0.tgz",
+ "integrity": "sha1-D7G59tZlEmPEejQg6CeRDm/tOVI="
+ },
+ "graphql-tools": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.2.2.tgz",
+ "integrity": "sha512-FBcpceJMOYq8PEI8c40S5vAiCtwWh9vSrJc4DoanAiQOLC8DOXaZ8nY+3+/AwHRur+R+zDprGoL14QqcWr0RrA=="
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+ },
+ "http-errors": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY="
+ },
+ "iconv-lite": {
+ "version": "0.4.15",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz",
+ "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es="
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ipaddr.js": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz",
+ "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA="
+ },
+ "isemail": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
+ "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
+ },
+ "iterall": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz",
+ "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ=="
+ },
+ "joi": {
+ "version": "6.10.1",
+ "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz",
+ "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY="
+ },
+ "jsonwebtoken": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz",
+ "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg="
+ },
+ "jwa": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz",
+ "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU="
+ },
+ "jws": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz",
+ "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI="
+ },
+ "jwt-decode": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz",
+ "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk="
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
+ },
+ "lodash.assign": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
+ },
+ "lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "lodash.property": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.property/-/lodash.property-4.4.2.tgz",
+ "integrity": "sha1-2gcSSCHGQJ0CXzDbjfhRMUUVv/4="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "merge-graphql-schemas": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/merge-graphql-schemas/-/merge-graphql-schemas-1.1.3.tgz",
+ "integrity": "sha512-1e5tkvITcq5EtnCoSmZz9i6YBBZYBn5/QBD1YIpiG1dSzyuz+YuZTU5RY1voocljrPYzr1Of2tWNRy+CYaRZTA=="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM="
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo="
+ },
+ "moment": {
+ "version": "2.19.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz",
+ "integrity": "sha512-1xFTAknSLfc47DIxHDUbnJWC+UwgWxATmymaxIPQpmMh7LBm7ZbwVEsuushqwL2GYZU0jie4xO+TK44hJPjNSQ=="
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "proxy-addr": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz",
+ "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg="
+ },
+ "qs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
+ "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "raw-body": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz",
+ "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y="
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "send": {
+ "version": "0.15.4",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz",
+ "integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=",
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz",
+ "integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE="
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "source-map-support": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz",
+ "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q=="
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+ },
+ "subscriptions-transport-ws": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.2.tgz",
+ "integrity": "sha512-bp0XR7ccnOspEFUKnmvTRN2VtrFdB4PqCWe7eooTY2fMwjBcm1kYkikWW/lo/d37yQ/BYUA+v0GPsyBakpc0OQ=="
+ },
+ "symbol-observable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz",
+ "integrity": "sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw=="
+ },
+ "topo": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz",
+ "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU="
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
+ "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg="
+ },
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "ws": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.2.tgz",
+ "integrity": "sha512-t+WGpsNxhMR4v6EClXS8r8km5ZljKJzyGhJf7goJz9k5Ye3+b5Bvno5rjqPuIBn5mnn5GBb7o8IrIWHxX1qOLQ=="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+ }
+ }
+}
diff --git a/packages/rocketchat-graphql/README.md b/packages/rocketchat-graphql/README.md
new file mode 100644
index 0000000000000..712c36fd39aef
--- /dev/null
+++ b/packages/rocketchat-graphql/README.md
@@ -0,0 +1,3 @@
+# rocketchat:graphql
+
+GraphQL API
diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js
new file mode 100644
index 0000000000000..e93877ee58149
--- /dev/null
+++ b/packages/rocketchat-graphql/package.js
@@ -0,0 +1,34 @@
+Package.describe({
+ name: 'rocketchat:graphql',
+ version: '0.0.1',
+ summary: 'GraphQL API',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'underscore',
+ 'ecmascript',
+ 'http',
+ 'rocketchat:lib',
+ 'rocketchat:api',
+ 'rocketchat:accounts',
+ 'swydo:graphql'
+ ]);
+ api.addFiles('server/settings.js', 'server');
+ api.mainModule('server/api.js', 'server');
+});
+
+Npm.depends({
+ '@accounts/graphql-api': '0.1.1',
+ 'apollo-server-express': '1.1.2',
+ 'cors': '2.8.4',
+ 'body-parser': '1.17.2',
+ 'express': '4.15.4',
+ 'graphql': '0.10.3',
+ 'graphql-subscriptions': '0.4.4',
+ 'graphql-tools': '1.2.2',
+ 'lodash.property': '4.4.2',
+ 'merge-graphql-schemas': '1.1.3',
+ 'subscriptions-transport-ws': '0.8.2'
+});
diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js
new file mode 100644
index 0000000000000..ca1e6d30b8aec
--- /dev/null
+++ b/packages/rocketchat-graphql/server/api.js
@@ -0,0 +1,77 @@
+import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
+import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api';
+import { SubscriptionServer } from 'subscriptions-transport-ws';
+import { execute, subscribe } from 'graphql';
+import { Meteor } from 'meteor/meteor';
+import { WebApp } from 'meteor/webapp';
+import bodyParser from 'body-parser';
+import express from 'express';
+import cors from 'cors';
+
+import { executableSchema } from './schema';
+
+const subscriptionPort = RocketChat.settings.get('Graphql_Subscription_Port') || 3100;
+
+// the Meteor GraphQL server is an Express server
+const graphQLServer = express();
+
+if (RocketChat.settings.get('Graphql_CORS')) {
+ graphQLServer.use(cors());
+}
+
+graphQLServer.use('/api/graphql', (req, res, next) => {
+ if (RocketChat.settings.get('Graphql_Enabled')) {
+ next();
+ } else {
+ res.status(400).send('Graphql is not enabled in this server');
+ }
+});
+
+graphQLServer.use(
+ '/api/graphql',
+ bodyParser.json(),
+ graphqlExpress(request => {
+ return {
+ schema: executableSchema,
+ context: jsAccountsContext(request),
+ formatError: e => ({
+ message: e.message,
+ locations: e.locations,
+ path: e.path
+ }),
+ debug: Meteor.isDevelopment
+ };
+ })
+);
+
+graphQLServer.use(
+ '/graphiql',
+ graphiqlExpress({
+ endpointURL: '/api/graphql',
+ subscriptionsEndpoint: `ws://localhost:${ subscriptionPort }`
+ })
+);
+
+const startSubscriptionServer = () => {
+ if (RocketChat.settings.get('Graphql_Enabled')) {
+ SubscriptionServer.create({
+ schema: executableSchema,
+ execute,
+ subscribe,
+ onConnect: (connectionParams) => ({ authToken: connectionParams.Authorization })
+ },
+ {
+ port: subscriptionPort,
+ host: process.env.BIND_IP || '0.0.0.0'
+ });
+
+ console.log('GraphQL Subscription server runs on port:', subscriptionPort);
+ }
+};
+
+WebApp.onListening(() => {
+ startSubscriptionServer();
+});
+
+// this binds the specified paths to the Express server running Apollo + GraphiQL
+WebApp.connectHandlers.use(graphQLServer);
diff --git a/packages/rocketchat-graphql/server/helpers/authenticated.js b/packages/rocketchat-graphql/server/helpers/authenticated.js
new file mode 100644
index 0000000000000..44c54e053996d
--- /dev/null
+++ b/packages/rocketchat-graphql/server/helpers/authenticated.js
@@ -0,0 +1,7 @@
+import { AccountsServer } from 'meteor/rocketchat:accounts';
+//import { authenticated as _authenticated } from '@accounts/graphql-api';
+import { authenticated as _authenticated } from '../mocks/accounts/graphql-api';
+
+export const authenticated = (resolver) => {
+ return _authenticated(AccountsServer, resolver);
+};
diff --git a/packages/rocketchat-graphql/server/helpers/dateToFloat.js b/packages/rocketchat-graphql/server/helpers/dateToFloat.js
new file mode 100644
index 0000000000000..faf206706f1bf
--- /dev/null
+++ b/packages/rocketchat-graphql/server/helpers/dateToFloat.js
@@ -0,0 +1,5 @@
+export function dateToFloat(date) {
+ if (date) {
+ return new Date(date).getTime();
+ }
+}
diff --git a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js
new file mode 100644
index 0000000000000..b94a295187f9e
--- /dev/null
+++ b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js
@@ -0,0 +1,21 @@
+// Same as here: https://github.com/js-accounts/graphql/blob/master/packages/graphql-api/src/utils/authenticated-resolver.js
+// except code below works
+// It might be like that because of async/await,
+// maybe Promise is not wrapped with Fiber
+// See: https://github.com/meteor/meteor/blob/a362e20a37547362b581fed52f7171d022e83b62/packages/promise/server.js
+// Opened issue: https://github.com/js-accounts/graphql/issues/16
+export const authenticated = (Accounts, func) => (async(root, args, context, info) => {
+ const authToken = context.authToken;
+
+ if (!authToken || authToken === '' || authToken === null) {
+ throw new Error('Unable to find authorization token in request');
+ }
+
+ const userObject = await Accounts.resumeSession(authToken);
+
+ if (userObject === null) {
+ throw new Error('Invalid or expired token!');
+ }
+
+ return await func(root, args, Object.assign(context, { user: userObject }), info);
+});
diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js
new file mode 100644
index 0000000000000..7cf39ff561390
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/accounts/OauthProvider-type.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/index.js b/packages/rocketchat-graphql/server/resolvers/accounts/index.js
new file mode 100644
index 0000000000000..e82a7077059b2
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/accounts/index.js
@@ -0,0 +1,21 @@
+import { createJSAccountsGraphQL } from '@accounts/graphql-api';
+import { AccountsServer } from 'meteor/rocketchat:accounts';
+import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
+
+// queries
+import * as oauthProviders from './oauthProviders';
+// types
+import * as OauthProviderType from './OauthProvider-type';
+
+const accountsGraphQL = createJSAccountsGraphQL(AccountsServer);
+
+export const schema = mergeTypes([
+ accountsGraphQL.schema,
+ oauthProviders.schema,
+ OauthProviderType.schema
+]);
+
+export const resolvers = mergeResolvers([
+ accountsGraphQL.extendWithResolvers({}),
+ oauthProviders.resolver
+]);
diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js
new file mode 100644
index 0000000000000..de487b8f9265c
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js
@@ -0,0 +1,39 @@
+import { HTTP } from 'meteor/http';
+import { Meteor } from 'meteor/meteor';
+
+import schema from '../../schemas/accounts/oauthProviders.graphqls';
+
+function isJSON(obj) {
+ try {
+ JSON.parse(obj);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+const resolver = {
+ Query: {
+ oauthProviders: async() => {
+ // depends on rocketchat:grant package
+ try {
+ const result = HTTP.get(Meteor.absoluteUrl('_oauth_apps/providers')).content;
+
+ if (isJSON(result)) {
+ const providers = JSON.parse(result).data;
+
+ return providers.map((name) => ({ name }));
+ } else {
+ throw new Error('Could not parse the result');
+ }
+ } catch (e) {
+ throw new Error('rocketchat:grant not installed');
+ }
+ }
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js
new file mode 100644
index 0000000000000..e16dffa8ab83e
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js
@@ -0,0 +1,50 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+import property from 'lodash.property';
+
+import schema from '../../schemas/channels/Channel-type.graphqls';
+
+const resolver = {
+ Channel: {
+ id: property('_id'),
+ name: (root, args, { user }) => {
+ if (root.t === 'd') {
+ return root.usernames.find(u => u !== user.username);
+ }
+
+ return root.name;
+ },
+ members: (root) => {
+ return root.usernames.map(
+ username => RocketChat.models.Users.findOneByUsername(username)
+ );
+ },
+ owners: (root) => {
+ // there might be no owner
+ if (!root.u) {
+ return;
+ }
+
+ return [RocketChat.models.Users.findOneByUsername(root.u.username)];
+ },
+ numberOfMembers: (root) => (root.usernames || []).length,
+ numberOfMessages: property('msgs'),
+ readOnly: (root) => root.ro === true,
+ direct: (root) => root.t === 'd',
+ privateChannel: (root) => root.t === 'p',
+ favourite: (root, args, { user }) => {
+ const room = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id);
+
+ return room && room.f === true;
+ },
+ unseenMessages: (root, args, { user }) => {
+ const room = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id);
+
+ return (room || {}).unread;
+ }
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js
new file mode 100644
index 0000000000000..cb1c26b0efa5c
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/channels/ChannelFilter-input.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js
new file mode 100644
index 0000000000000..70cb2f18e6b67
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/channels/ChannelNameAndDirect-input.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js
new file mode 100644
index 0000000000000..39e2cfc9aef5d
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/channels/ChannelSort-enum.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js
new file mode 100644
index 0000000000000..978a69b5ac0f9
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/channels/Privacy-enum.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js
new file mode 100644
index 0000000000000..580280b549a2c
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js
@@ -0,0 +1,25 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import { roomPublicFields } from './settings';
+import schema from '../../schemas/channels/channelByName.graphqls';
+
+const resolver = {
+ Query: {
+ channelByName: authenticated((root, { name }) => {
+ const query = {
+ name,
+ t: 'c'
+ };
+
+ return RocketChat.models.Rooms.findOne(query, {
+ fields: roomPublicFields
+ });
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channels.js b/packages/rocketchat-graphql/server/resolvers/channels/channels.js
new file mode 100644
index 0000000000000..04723ff5f5d4f
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/channels.js
@@ -0,0 +1,56 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import { roomPublicFields } from './settings';
+import schema from '../../schemas/channels/channels.graphqls';
+
+const resolver = {
+ Query: {
+ channels: authenticated((root, args) => {
+ const query = {};
+ const options = {
+ sort: {
+ name: 1
+ },
+ fields: roomPublicFields
+ };
+
+ // Filter
+ if (typeof args.filter !== 'undefined') {
+ // nameFilter
+ if (typeof args.filter.nameFilter !== undefined) {
+ query.name = {
+ $regex: new RegExp(args.filter.nameFilter, 'i')
+ };
+ }
+
+ // sortBy
+ if (args.filter.sortBy === 'NUMBER_OF_MESSAGES') {
+ options.sort = {
+ msgs: -1
+ };
+ }
+
+ // privacy
+ switch (args.filter.privacy) {
+ case 'PRIVATE':
+ query.t = 'p';
+ break;
+ case 'PUBLIC':
+ query.t = {
+ $ne: 'p'
+ };
+ break;
+ }
+ }
+
+ return RocketChat.models.Rooms.find(query, options).fetch();
+ })
+ }
+};
+
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js
new file mode 100644
index 0000000000000..4fdc6e15a3094
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js
@@ -0,0 +1,31 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import { roomPublicFields } from './settings';
+import schema from '../../schemas/channels/channelsByUser.graphqls';
+
+const resolver = {
+ Query: {
+ channelsByUser: authenticated((root, { userId }) => {
+ const user = RocketChat.models.Users.findOneById(userId);
+
+ if (!user) {
+ throw new Error('No user');
+ }
+
+ const rooms = RocketChat.models.Rooms.findByContainingUsername(user.username, {
+ sort: {
+ name: 1
+ },
+ fields: roomPublicFields
+ }).fetch();
+
+ return rooms;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js
new file mode 100644
index 0000000000000..59435add38bbe
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js
@@ -0,0 +1,40 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/channels/createChannel.graphqls';
+
+const resolver = {
+ Mutation: {
+ createChannel: authenticated((root, args, { user }) => {
+ try {
+ RocketChat.API.channels.create.validate({
+ user: {
+ value: user._id
+ },
+ name: {
+ value: args.name,
+ key: 'name'
+ },
+ members: {
+ value: args.membersId,
+ key: 'membersId'
+ }
+ });
+ } catch (e) {
+ throw e;
+ }
+
+ const { channel } = RocketChat.API.channels.create.execute(user._id, {
+ name: args.name,
+ members: args.membersId
+ });
+
+ return channel;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js
new file mode 100644
index 0000000000000..e18e39af19dca
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js
@@ -0,0 +1,37 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import { roomPublicFields } from './settings';
+import schema from '../../schemas/channels/directChannel.graphqls';
+
+const resolver = {
+ Query: {
+ directChannel: authenticated((root, { username, channelId }, { user }) => {
+ const query = {
+ t: 'd',
+ usernames: user.username
+ };
+
+ if (typeof username !== 'undefined') {
+ if (username === user.username) {
+ throw new Error('You cannot specify your username');
+ }
+
+ query.usernames = { $all: [ user.username, username ] };
+ } else if (typeof channelId !== 'undefined') {
+ query.id = channelId;
+ } else {
+ throw new Error('Use one of those fields: username, channelId');
+ }
+
+ return RocketChat.models.Rooms.findOne(query, {
+ fields: roomPublicFields
+ });
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js
new file mode 100644
index 0000000000000..08c55efa7796c
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js
@@ -0,0 +1,41 @@
+import { Meteor } from 'meteor/meteor';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/channels/hideChannel.graphqls';
+
+const resolver = {
+ Mutation: {
+ hideChannel: authenticated((root, args, { user }) => {
+ const channel = RocketChat.models.Rooms.findOne({
+ _id: args.channelId,
+ t: 'c'
+ });
+
+ if (!channel) {
+ throw new Error('error-room-not-found', 'The required "channelId" param provided does not match any channel');
+ }
+
+ const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(channel._id, user._id);
+
+ if (!sub) {
+ throw new Error(`The user/callee is not in the channel "${ channel.name }.`);
+ }
+
+ if (!sub.open) {
+ throw new Error(`The channel, ${ channel.name }, is already closed to the sender`);
+ }
+
+ Meteor.runAsUser(user._id, () => {
+ Meteor.call('hideRoom', channel._id);
+ });
+
+ return true;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/index.js b/packages/rocketchat-graphql/server/resolvers/channels/index.js
new file mode 100644
index 0000000000000..063e9da418042
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/index.js
@@ -0,0 +1,49 @@
+import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
+
+// queries
+import * as channels from './channels';
+import * as channelByName from './channelByName';
+import * as directChannel from './directChannel';
+import * as channelsByUser from './channelsByUser';
+// mutations
+import * as createChannel from './createChannel';
+import * as leaveChannel from './leaveChannel';
+import * as hideChannel from './hideChannel';
+// types
+import * as ChannelType from './Channel-type';
+import * as ChannelSort from './ChannelSort-enum';
+import * as ChannelFilter from './ChannelFilter-input';
+import * as Privacy from './Privacy-enum';
+import * as ChannelNameAndDirect from './ChannelNameAndDirect-input';
+
+export const schema = mergeTypes([
+ // queries
+ channels.schema,
+ channelByName.schema,
+ directChannel.schema,
+ channelsByUser.schema,
+ // mutations
+ createChannel.schema,
+ leaveChannel.schema,
+ hideChannel.schema,
+ // types
+ ChannelType.schema,
+ ChannelSort.schema,
+ ChannelFilter.schema,
+ Privacy.schema,
+ ChannelNameAndDirect.schema
+]);
+
+export const resolvers = mergeResolvers([
+ // queries
+ channels.resolver,
+ channelByName.resolver,
+ directChannel.resolver,
+ channelsByUser.resolver,
+ // mutations
+ createChannel.resolver,
+ leaveChannel.resolver,
+ hideChannel.resolver,
+ // types
+ ChannelType.resolver
+]);
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js
new file mode 100644
index 0000000000000..46afd2a08940a
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js
@@ -0,0 +1,31 @@
+import { Meteor } from 'meteor/meteor';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/channels/leaveChannel.graphqls';
+
+const resolver = {
+ Mutation: {
+ leaveChannel: authenticated((root, args, { user }) => {
+ const channel = RocketChat.models.Rooms.findOne({
+ _id: args.channelId,
+ t: 'c'
+ });
+
+ if (!channel) {
+ throw new Error('error-room-not-found', 'The required "channelId" param provided does not match any channel');
+ }
+
+ Meteor.runAsUser(user._id, () => {
+ Meteor.call('leaveRoom', channel._id);
+ });
+
+ return true;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/settings.js b/packages/rocketchat-graphql/server/resolvers/channels/settings.js
new file mode 100644
index 0000000000000..7cace07a7cbc8
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/channels/settings.js
@@ -0,0 +1,12 @@
+export const roomPublicFields = {
+ t: 1,
+ name: 1,
+ description: 1,
+ announcement: 1,
+ topic: 1,
+ usernames: 1,
+ msgs: 1,
+ ro: 1,
+ u: 1,
+ archived: 1
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js
new file mode 100644
index 0000000000000..362ce8b50b606
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js
@@ -0,0 +1,76 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+import property from 'lodash.property';
+
+import { dateToFloat } from '../../helpers/dateToFloat';
+import schema from '../../schemas/messages/Message-type.graphqls';
+
+const resolver = {
+ Message: {
+ id: property('_id'),
+ content: property('msg'),
+ creationTime: (root) => dateToFloat(root.ts),
+ author: (root) => {
+ const user = RocketChat.models.Users.findOne(root.u._id);
+
+ return user || root.u;
+ },
+ channel: (root) => {
+ return RocketChat.models.Rooms.findOne(root.rid);
+ },
+ fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false`
+ type: property('t'),
+ channelRef: (root) => {
+ if (!root.channels) {
+ return;
+ }
+
+ return RocketChat.models.Rooms.find({
+ _id: {
+ $in: root.channels.map(c => c._id)
+ }
+ }, {
+ sort: {
+ name: 1
+ }
+ }).fetch();
+ },
+ userRef: (root) => {
+ if (!root.mentions) {
+ return;
+ }
+
+ return RocketChat.models.Users.find({
+ _id: {
+ $in: root.mentions.map(c => c._id)
+ }
+ }, {
+ sort: {
+ username: 1
+ }
+ }).fetch();
+ },
+ reactions: (root) => {
+ if (!root.reactions || Object.keys(root.reactions).length === 0) {
+ return;
+ }
+
+ const reactions = [];
+
+ Object.keys(root.reactions).forEach(icon => {
+ root.reactions[icon].usernames.forEach(username => {
+ reactions.push({
+ icon,
+ username
+ });
+ });
+ });
+
+ return reactions;
+ }
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js
new file mode 100644
index 0000000000000..bda12ad6ac682
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/messages/MessageIdentifier-input.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js
new file mode 100644
index 0000000000000..02e630ff45891
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/messages/MessagesWithCursor-type.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js
new file mode 100644
index 0000000000000..37a9c7a71ef64
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/messages/Reaction-type.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js
new file mode 100644
index 0000000000000..ee3e49843d52f
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js
@@ -0,0 +1,24 @@
+import { Meteor } from 'meteor/meteor';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/addReactionToMessage.graphqls';
+
+const resolver = {
+ Mutation: {
+ addReactionToMessage: authenticated((root, { id, icon }, { user }) => {
+ return new Promise((resolve) => {
+ Meteor.runAsUser(user._id, () => {
+ Meteor.call('setReaction', id.messageId, icon, () => {
+ resolve(RocketChat.models.Messages.findOne(id.messageId));
+ });
+ });
+ });
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js
new file mode 100644
index 0000000000000..8a81c66a69b3a
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js
@@ -0,0 +1,51 @@
+import { withFilter } from 'graphql-subscriptions';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { pubsub } from '../../subscriptions';
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/chatMessageAdded.graphqls';
+
+export const CHAT_MESSAGE_SUBSCRIPTION_TOPIC = 'CHAT_MESSAGE_ADDED';
+
+export function publishMessage(message) {
+ pubsub.publish(CHAT_MESSAGE_SUBSCRIPTION_TOPIC, { chatMessageAdded: message });
+}
+
+function shouldPublish(message, { id, directTo }, username) {
+ if (id) {
+ return message.rid === id;
+ } else if (directTo) {
+ const room = RocketChat.models.Rooms.findOne({
+ usernames: { $all: [directTo, username] },
+ t: 'd'
+ });
+
+ return room && room._id === message.rid;
+ }
+
+ return false;
+}
+
+const resolver = {
+ Subscription: {
+ chatMessageAdded: {
+ subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), authenticated((payload, args, { user }) => {
+ const channel = {
+ id: args.channelId,
+ directTo: args.directTo
+ };
+
+ return shouldPublish(payload.chatMessageAdded, channel, user.username);
+ }))
+ }
+ }
+};
+
+RocketChat.callbacks.add('afterSaveMessage', (message) => {
+ publishMessage(message);
+}, null, 'chatMessageAddedSubscription');
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js
new file mode 100644
index 0000000000000..33225c02f282d
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js
@@ -0,0 +1,32 @@
+import { Meteor } from 'meteor/meteor';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/deleteMessage.graphqls';
+
+const resolver = {
+ Mutation: {
+ deleteMessage: authenticated((root, { id }, { user }) => {
+ const msg = RocketChat.models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }});
+
+ if (!msg) {
+ throw new Error(`No message found with the id of "${ id.messageId }".`);
+ }
+
+ if (id.channelId !== msg.rid) {
+ throw new Error('The room id provided does not match where the message is from.');
+ }
+
+ Meteor.runAsUser(user._id, () => {
+ Meteor.call('deleteMessage', { _id: msg._id });
+ });
+
+ return msg;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js
new file mode 100644
index 0000000000000..0fabc8b34db9a
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js
@@ -0,0 +1,34 @@
+import { Meteor } from 'meteor/meteor';
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/editMessage.graphqls';
+
+const resolver = {
+ Mutation: {
+ editMessage: authenticated((root, { id, content }, { user }) => {
+ const msg = RocketChat.models.Messages.findOneById(id.messageId);
+
+ //Ensure the message exists
+ if (!msg) {
+ throw new Error(`No message found with the id of "${ id.messageId }".`);
+ }
+
+ if (id.channelId !== msg.rid) {
+ throw new Error('The channel id provided does not match where the message is from.');
+ }
+
+ //Permission checks are already done in the updateMessage method, so no need to duplicate them
+ Meteor.runAsUser(user._id, () => {
+ Meteor.call('updateMessage', { _id: msg._id, msg: content, rid: msg.rid });
+ });
+
+ return RocketChat.models.Messages.findOneById(msg._id);
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/index.js b/packages/rocketchat-graphql/server/resolvers/messages/index.js
new file mode 100644
index 0000000000000..fb9728b198155
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/index.js
@@ -0,0 +1,47 @@
+import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
+
+// queries
+import * as messages from './messages';
+// mutations
+import * as sendMessage from './sendMessage';
+import * as editMessage from './editMessage';
+import * as deleteMessage from './deleteMessage';
+import * as addReactionToMessage from './addReactionToMessage';
+// subscriptions
+import * as chatMessageAdded from './chatMessageAdded';
+// types
+import * as MessageType from './Message-type';
+import * as MessagesWithCursorType from './MessagesWithCursor-type';
+import * as MessageIdentifier from './MessageIdentifier-input';
+import * as ReactionType from './Reaction-type';
+
+export const schema = mergeTypes([
+ // queries
+ messages.schema,
+ // mutations
+ sendMessage.schema,
+ editMessage.schema,
+ deleteMessage.schema,
+ addReactionToMessage.schema,
+ // subscriptions
+ chatMessageAdded.schema,
+ // types
+ MessageType.schema,
+ MessagesWithCursorType.schema,
+ MessageIdentifier.schema,
+ ReactionType.schema
+]);
+
+export const resolvers = mergeResolvers([
+ // queries
+ messages.resolver,
+ // mutations
+ sendMessage.resolver,
+ editMessage.resolver,
+ deleteMessage.resolver,
+ addReactionToMessage.resolver,
+ // subscriptions
+ chatMessageAdded.resolver,
+ // types
+ MessageType.resolver
+]);
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/messages.js b/packages/rocketchat-graphql/server/resolvers/messages/messages.js
new file mode 100644
index 0000000000000..a163ebefa406d
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/messages.js
@@ -0,0 +1,91 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/messages.graphqls';
+
+const resolver = {
+ Query: {
+ messages: authenticated((root, args, { user }) => {
+ const messagesQuery = {};
+ const messagesOptions = {
+ sort: { ts: -1 }
+ };
+ const channelQuery = {};
+ const isPagination = !!args.cursor || args.count > 0;
+ let cursor;
+
+ if (args.channelId) {
+ // channelId
+ channelQuery._id = args.channelId;
+ } else if (args.directTo) {
+ // direct message where directTo is a user id
+ channelQuery.t = 'd';
+ channelQuery.usernames = { $all: [args.directTo, user.username] };
+ } else if (args.channelName) {
+ // non-direct channel
+ channelQuery.t = { $ne: 'd' };
+ channelQuery.name = args.channelName;
+ } else {
+ console.error('messages query must be called with channelId or directTo');
+ return null;
+ }
+
+ const channel = RocketChat.models.Rooms.findOne(channelQuery);
+
+ let messagesArray = [];
+
+ if (channel) {
+ // cursor
+ if (isPagination && args.cursor) {
+ const cursorMsg = RocketChat.models.Messages.findOne(args.cursor, { fields: { ts: 1 } });
+ messagesQuery.ts = { $lt: cursorMsg.ts };
+ }
+
+ // search
+ if (typeof args.searchRegex === 'string') {
+ messagesQuery.msg = {
+ $regex: new RegExp(args.searchRegex, 'i')
+ };
+ }
+
+ // count
+ if (isPagination && args.count) {
+ messagesOptions.limit = args.count;
+ }
+
+ // exclude messages generated by server
+ if (args.excludeServer === true) {
+ messagesQuery.t = { $exists: false };
+ }
+
+ // look for messages that belongs to specific channel
+ messagesQuery.rid = channel._id;
+
+ const messages = RocketChat.models.Messages.find(messagesQuery, messagesOptions);
+
+ messagesArray = messages.fetch();
+
+ if (isPagination) {
+ // oldest first (because of findOne)
+ messagesOptions.sort.ts = 1;
+
+ const firstMessage = RocketChat.models.Messages.findOne(messagesQuery, messagesOptions);
+ const lastId = (messagesArray[messagesArray.length - 1] || {})._id;
+
+ cursor = !lastId || lastId === firstMessage._id ? null : lastId;
+ }
+ }
+
+ return {
+ cursor,
+ channel,
+ messagesArray
+ };
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js
new file mode 100644
index 0000000000000..7bbd20b71ec02
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js
@@ -0,0 +1,28 @@
+/* global processWebhookMessage */
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/messages/sendMessage.graphqls';
+
+const resolver = {
+ Mutation: {
+ sendMessage: authenticated((root, { channelId, directTo, content }, { user }) => {
+ const options = {
+ text: content,
+ channel: channelId || directTo
+ };
+
+ const messageReturn = processWebhookMessage(options, user)[0];
+
+ if (!messageReturn) {
+ throw new Error('Unknown error');
+ }
+
+ return messageReturn.message;
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/users/User-type.js b/packages/rocketchat-graphql/server/resolvers/users/User-type.js
new file mode 100644
index 0000000000000..d768b78ab7f8b
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/users/User-type.js
@@ -0,0 +1,32 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+import property from 'lodash.property';
+
+import schema from '../../schemas/users/User-type.graphqls';
+
+const resolver = {
+ User: {
+ id: property('_id'),
+ status: ({status}) => status.toUpperCase(),
+ avatar: async({ _id }) => {
+ // XXX js-accounts/graphql#16
+ const avatar = await RocketChat.models.Avatars.model.rawCollection().findOne({
+ userId: _id
+ }, { fields: { url: 1 }});
+
+ if (avatar) {
+ return avatar.url;
+ }
+ },
+ channels: Meteor.bindEnvironment(async({ _id }) => {
+ return await RocketChat.models.Rooms.findBySubscriptionUserId(_id).fetch();
+ }),
+ directMessages: ({ username }) => {
+ return RocketChat.models.Rooms.findByTypeContainingUsername('d', username).fetch();
+ }
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js
new file mode 100644
index 0000000000000..d1d526338c1a6
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js
@@ -0,0 +1,5 @@
+import schema from '../../schemas/users/UserStatus-enum.graphqls';
+
+export {
+ schema
+};
diff --git a/packages/rocketchat-graphql/server/resolvers/users/index.js b/packages/rocketchat-graphql/server/resolvers/users/index.js
new file mode 100644
index 0000000000000..7647d5a5fdd6c
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/users/index.js
@@ -0,0 +1,22 @@
+import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
+
+// mutations
+import * as setStatus from './setStatus';
+// types
+import * as UserType from './User-type';
+import * as UserStatus from './UserStatus-enum';
+
+export const schema = mergeTypes([
+ // mutations
+ setStatus.schema,
+ // types
+ UserType.schema,
+ UserStatus.schema
+]);
+
+export const resolvers = mergeResolvers([
+ // mutations
+ setStatus.resolver,
+ // types
+ UserType.resolver
+]);
diff --git a/packages/rocketchat-graphql/server/resolvers/users/setStatus.js b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js
new file mode 100644
index 0000000000000..ad6b4ebef6b66
--- /dev/null
+++ b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js
@@ -0,0 +1,23 @@
+import { RocketChat } from 'meteor/rocketchat:lib';
+
+import { authenticated } from '../../helpers/authenticated';
+import schema from '../../schemas/users/setStatus.graphqls';
+
+const resolver = {
+ Mutation: {
+ setStatus: authenticated((root, { status }, { user }) => {
+ RocketChat.models.Users.update(user._id, {
+ $set: {
+ status: status.toLowerCase()
+ }
+ });
+
+ return RocketChat.models.Users.findOne(user._id);
+ })
+ }
+};
+
+export {
+ schema,
+ resolver
+};
diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js
new file mode 100644
index 0000000000000..e8d3cbdd489e3
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schema.js
@@ -0,0 +1,29 @@
+import { makeExecutableSchema } from 'graphql-tools';
+import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
+
+import * as channels from './resolvers/channels';
+import * as messages from './resolvers/messages';
+import * as accounts from './resolvers/accounts';
+import * as users from './resolvers/users';
+
+const schema = mergeTypes([
+ channels.schema,
+ messages.schema,
+ accounts.schema,
+ users.schema
+]);
+
+const resolvers = mergeResolvers([
+ channels.resolvers,
+ messages.resolvers,
+ accounts.resolvers,
+ users.resolvers
+]);
+
+export const executableSchema = makeExecutableSchema({
+ typeDefs: [schema],
+ resolvers,
+ logger: {
+ log: (e) => console.log(e)
+ }
+});
diff --git a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphqls b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphqls
new file mode 100644
index 0000000000000..0bdf1ed7e00bd
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphqls
@@ -0,0 +1,4 @@
+type LoginResult {
+ accessToken: String!
+ refreshToken: String!
+}
diff --git a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphqls b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphqls
new file mode 100644
index 0000000000000..c91fe5e6379a9
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphqls
@@ -0,0 +1,3 @@
+type OauthProvider {
+ name: String!
+}
diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphqls b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphqls
new file mode 100644
index 0000000000000..9ba76de8adb8b
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphqls
@@ -0,0 +1,3 @@
+type Query {
+ oauthProviders: [OauthProvider]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphqls b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphqls
new file mode 100644
index 0000000000000..03c4557918df1
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphqls
@@ -0,0 +1,16 @@
+type Channel {
+ id: String!
+ name: String
+ description: String
+ announcement: String
+ topic: String
+ members: [User]
+ owners: [User]
+ numberOfMembers: Int
+ numberOfMessages: Int
+ readOnly: Boolean
+ direct: Boolean
+ privateChannel: Boolean
+ favourite: Boolean
+ unseenMessages: Int
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphqls b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphqls
new file mode 100644
index 0000000000000..a00850e371cc8
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphqls
@@ -0,0 +1,6 @@
+input ChannelFilter {
+ nameFilter: String
+ privacy: Privacy
+ joinedChannels: Boolean
+ sortBy: ChannelSort
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphqls b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphqls
new file mode 100644
index 0000000000000..139567e862e93
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphqls
@@ -0,0 +1,4 @@
+input ChannelNameAndDirect {
+ name: String!
+ direct: Boolean!
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphqls b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphqls
new file mode 100644
index 0000000000000..8a2c2902e6dbf
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphqls
@@ -0,0 +1,4 @@
+enum ChannelSort {
+ NAME
+ NUMBER_OF_MESSAGES
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphqls b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphqls
new file mode 100644
index 0000000000000..f28a57d51c281
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphqls
@@ -0,0 +1,5 @@
+enum Privacy {
+ PRIVATE
+ PUBLIC
+ ALL
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphqls b/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphqls
new file mode 100644
index 0000000000000..e301ce38f7f6a
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphqls
@@ -0,0 +1,3 @@
+type Query {
+ channelByName(name: String!): Channel
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.graphqls b/packages/rocketchat-graphql/server/schemas/channels/channels.graphqls
new file mode 100644
index 0000000000000..6e4ac56082497
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/channels.graphqls
@@ -0,0 +1,7 @@
+type Query {
+ channels(filter: ChannelFilter = {
+ privacy: ALL,
+ joinedChannels: false,
+ sortBy: NAME
+ }): [Channel]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphqls b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphqls
new file mode 100644
index 0000000000000..8dfe20a071c59
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphqls
@@ -0,0 +1,3 @@
+type Query {
+ channelsByUser(userId: String!): [Channel]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphqls b/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphqls
new file mode 100644
index 0000000000000..85317c86603a3
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphqls
@@ -0,0 +1,8 @@
+type Mutation {
+ createChannel(
+ name: String!,
+ private: Boolean = false,
+ readOnly: Boolean = false,
+ membersId: [String!]
+ ): Channel
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphqls b/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphqls
new file mode 100644
index 0000000000000..4e41994bce80f
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphqls
@@ -0,0 +1,3 @@
+type Query {
+ directChannel(username: String, channelId: String): Channel
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphqls b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphqls
new file mode 100644
index 0000000000000..5ea9517f57418
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ hideChannel(channelId: String!): Boolean
+}
diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphqls b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphqls
new file mode 100644
index 0000000000000..e6ceb4075c4e7
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ leaveChannel(channelId: String!): Boolean
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphqls b/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphqls
new file mode 100644
index 0000000000000..8ccfdebfbf1df
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphqls
@@ -0,0 +1,15 @@
+type Message {
+ id: String
+ author: User
+ content: String
+ channel: Channel
+ creationTime: Float
+ # Message sent by server e.g. User joined channel
+ fromServer: Boolean
+ type: String
+ # List of mentioned users
+ userRef: [User]
+ # list of mentioned channels
+ channelRef: [Channel]
+ reactions: [Reaction]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphqls b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphqls
new file mode 100644
index 0000000000000..88fbe90711cf9
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphqls
@@ -0,0 +1,4 @@
+input MessageIdentifier {
+ channelId: String!
+ messageId: String!
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphqls b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphqls
new file mode 100644
index 0000000000000..e890725f6efb3
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphqls
@@ -0,0 +1,5 @@
+type MessagesWithCursor {
+ cursor: String
+ channel: Channel
+ messagesArray: [Message]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphqls b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphqls
new file mode 100644
index 0000000000000..e6eedf75d1e18
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphqls
@@ -0,0 +1,4 @@
+type Reaction {
+ username: String
+ icon: String
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphqls b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphqls
new file mode 100644
index 0000000000000..3b6be025a59ba
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ addReactionToMessage(id: MessageIdentifier!, icon: String!): Message
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls
new file mode 100644
index 0000000000000..d05c00afc3bcd
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls
@@ -0,0 +1,3 @@
+type Subscription {
+ chatMessageAdded(channelId: String, directTo: String): Message
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphqls b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphqls
new file mode 100644
index 0000000000000..f298a14ebf98b
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ deleteMessage(id: MessageIdentifier!): Message
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphqls b/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphqls
new file mode 100644
index 0000000000000..19900c58b2724
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ editMessage(id: MessageIdentifier!, content: String!): Message
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.graphqls b/packages/rocketchat-graphql/server/schemas/messages/messages.graphqls
new file mode 100644
index 0000000000000..a81fe2186ca77
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/messages.graphqls
@@ -0,0 +1,11 @@
+type Query {
+ messages(
+ channelId: String,
+ channelName: String,
+ directTo: String,
+ cursor: String,
+ count: Int,
+ searchRegex: String,
+ excludeServer: Boolean
+ ): MessagesWithCursor
+}
diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls
new file mode 100644
index 0000000000000..78933ec6a7635
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ sendMessage(channelId: String, directTo: String, content: String!): Message
+}
diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.graphqls b/packages/rocketchat-graphql/server/schemas/users/User-type.graphqls
new file mode 100644
index 0000000000000..2a345415227ef
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/users/User-type.graphqls
@@ -0,0 +1,8 @@
+extend type User {
+ status: UserStatus
+ avatar: String
+ name: String
+ lastLogin: String
+ channels: [Channel]
+ directMessages: [Channel]
+}
diff --git a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphqls b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphqls
new file mode 100644
index 0000000000000..a360cc2a72b95
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphqls
@@ -0,0 +1,7 @@
+enum UserStatus {
+ ONLINE
+ AWAY
+ BUSY
+ INVISIBLE
+ OFFLINE
+}
diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.graphqls b/packages/rocketchat-graphql/server/schemas/users/setStatus.graphqls
new file mode 100644
index 0000000000000..7beb3512a91b2
--- /dev/null
+++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.graphqls
@@ -0,0 +1,3 @@
+type Mutation {
+ setStatus(status: UserStatus!): User
+}
diff --git a/packages/rocketchat-graphql/server/settings.js b/packages/rocketchat-graphql/server/settings.js
new file mode 100644
index 0000000000000..f7d06fb80fe45
--- /dev/null
+++ b/packages/rocketchat-graphql/server/settings.js
@@ -0,0 +1,7 @@
+RocketChat.settings.addGroup('General', function() {
+ this.section('GraphQL API', function() {
+ this.add('Graphql_Enabled', false, { type: 'boolean', public: false });
+ this.add('Graphql_CORS', true, { type: 'boolean', public: false, enableQuery: { _id: 'Graphql_Enabled', value: true } });
+ this.add('Graphql_Subscription_Port', 3100, { type: 'int', public: false, enableQuery: { _id: 'Graphql_Enabled', value: true } });
+ });
+});
diff --git a/packages/rocketchat-graphql/server/subscriptions.js b/packages/rocketchat-graphql/server/subscriptions.js
new file mode 100644
index 0000000000000..d86d23f85d055
--- /dev/null
+++ b/packages/rocketchat-graphql/server/subscriptions.js
@@ -0,0 +1,3 @@
+import { PubSub } from 'graphql-subscriptions';
+
+export const pubsub = new PubSub();
diff --git a/packages/rocketchat-highlight-words/client.js b/packages/rocketchat-highlight-words/client.js
deleted file mode 100644
index 57ed309e147b8..0000000000000
--- a/packages/rocketchat-highlight-words/client.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Hilights is a named function that will process Highlights
- * @param {Object} message - The message object
- */
-
-function HighlightWordsClient(message) {
- let msg = message;
- if (!_.isString(message)) {
- if (_.trim(message.html)) {
- msg = message.html;
- } else {
- return message;
- }
- }
-
- const to_highlight = Meteor.user() && Meteor.user().settings && Meteor.user().settings.preferences && Meteor.user().settings.preferences.highlights;
- if (Array.isArray(to_highlight)) {
- to_highlight.forEach((highlight) => {
- if (!_.isBlank(highlight)) {
- return msg = msg.replace(new RegExp('(^|\\b|[\\s\\n\\r\\t.,،\'\\\"\\+!?:-])(' + s.escapeRegExp(highlight) + ')($|\\b|[\\s\\n\\r\\t.,،\'\\\"\\+!?:-])(?![^<]*>|[^<>]*<\\/)', 'gmi'), '$1$2 $3');
- }
- });
- }
-
- message.html = msg;
- return message;
-}
-
-RocketChat.callbacks.add('renderMessage', HighlightWordsClient, RocketChat.callbacks.priority.MEDIUM + 1, 'highlight-words');
diff --git a/packages/rocketchat-highlight-words/client/client.js b/packages/rocketchat-highlight-words/client/client.js
new file mode 100644
index 0000000000000..aa3c6dc5c32b5
--- /dev/null
+++ b/packages/rocketchat-highlight-words/client/client.js
@@ -0,0 +1,31 @@
+/*
+ * Hilights is a named function that will process Highlights
+ * @param {Object} message - The message object
+ */
+import _ from 'underscore';
+import s from 'underscore.string';
+
+function HighlightWordsClient(message) {
+ let msg = message;
+ if (!_.isString(message)) {
+ if (s.trim(message.html)) {
+ msg = message.html;
+ } else {
+ return message;
+ }
+ }
+
+ const to_highlight = RocketChat.getUserPreference(Meteor.user(), 'highlights');
+ if (Array.isArray(to_highlight)) {
+ to_highlight.forEach((highlight) => {
+ if (!s.isBlank(highlight)) {
+ return msg = msg.replace(new RegExp(`(^|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(${ s.escapeRegExp(highlight) })($|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(?![^<]*>|[^<>]*<\\/)`, 'gmi'), '$1$2 $3');
+ }
+ });
+ }
+
+ message.html = msg;
+ return message;
+}
+
+RocketChat.callbacks.add('renderMessage', HighlightWordsClient, RocketChat.callbacks.priority.MEDIUM + 1, 'highlight-words');
diff --git a/packages/rocketchat-highlight-words/package.js b/packages/rocketchat-highlight-words/package.js
index 3e72ab94dc73e..5fa73cc2ff9d4 100644
--- a/packages/rocketchat-highlight-words/package.js
+++ b/packages/rocketchat-highlight-words/package.js
@@ -16,5 +16,5 @@ Package.onUse(function(api) {
'rocketchat:lib'
]);
- api.addFiles('client.js', 'client');
+ api.addFiles('client/client.js', 'client');
});
diff --git a/packages/rocketchat-i18n/i18n/af.i18n.json b/packages/rocketchat-i18n/i18n/af.i18n.json
new file mode 100644
index 0000000000000..db1a62920d66b
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/af.i18n.json
@@ -0,0 +1,3 @@
+{
+ "#channel": "#channel"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/ar.i18n.json b/packages/rocketchat-i18n/i18n/ar.i18n.json
index 3dbd8af238ace..11d55b3b27a08 100644
--- a/packages/rocketchat-i18n/i18n/ar.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ar.i18n.json
@@ -1,4 +1,5 @@
{
+ "#channel": "#channel",
"0_Errors_Only": "0 - أخطاء فقط",
"1_Errors_and_Information": "1 - أخطاء ومعلومات",
"2_Erros_Information_and_Debug": "2 - Erros والمعلومات وتصحيح",
@@ -6,11 +7,20 @@
"500": "خطأ محلي في الخادم",
"__username__is_no_longer__role__defined_by__user_by_": "__username__ لم يعد __role__، من خلال __user_by__",
"__username__was_set__role__by__user_by_": "تم تعيين __username__ __role__ التي كتبها __user_by__",
+ "Accept": "قبول",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "قبول طلبات الدردشة المباشرة وإن لم يكن هناك موظفون أونلاين",
+ "Accept_with_no_online_agents": "قبول إن ولم يكن هنالك موظفون أونلاين",
+ "access-mailer": "الدخول إلى نافذة البريد",
+ "access-mailer_description": "التصريح بإرسال إيميلات دفعة واحدة إلى كل المستخدمين",
+ "access-permissions": "الدخول إلى صفحة الصلاحيات والأذونات",
+ "access-permissions_description": "تعديل الصلاحيات للأدوار المختلفة",
"Access_not_authorized": "وصول غير مخول",
"Access_Token_URL": "URL الوصول رمز",
"Accessing_permissions": "أذونات الوصول",
"Account_SID": "SID حساب",
"Accounts": "الحسابات",
+ "Accounts_AllowAnonymousRead": "السماح للأشخاص المجهولون بالقراءة",
+ "Accounts_AllowAnonymousWrite": "السماح للأشخاص المجهولون بالكتابة",
"Accounts_AllowDeleteOwnAccount": " السماح للمستخدمين بحذف الحساب الخاص بهم",
"Accounts_AllowedDomainsList": "قائمة النطاقات المسموحة",
"Accounts_AllowedDomainsList_Description": "قائمة مفصولة بفواصل من المجالات المسموح بها",
@@ -21,19 +31,19 @@
"Accounts_AllowUserProfileChange": "السماح بتعديل الملف الشخصي للعضو",
"Accounts_AvatarResize": "تغيير حجم الصور الرمزية",
"Accounts_AvatarSize": "حجم الصورة الرمزية",
- "Accounts_AvatarStorePath": "مسار تخزين الصورة الرمزية",
- "Accounts_AvatarStoreType": "نوع تخزين الصورة الرمزية",
"Accounts_BlockedDomainsList": "محظور قائمة المجالات",
"Accounts_BlockedDomainsList_Description": "قائمة مفصولة بفواصل من المجالات سدت",
"Accounts_BlockedUsernameList": "قائمة اﻷسماء المحظورة",
"Accounts_BlockedUsernameList_Description": "قائمة مفصولة بفواصل من أسماء المستخدمين المحظورة (تحسس حالة الأحرف)",
+ "Accounts_DefaultUsernamePrefixSuggestion": "اقتراح بادئة اسم المستخدم الافتراضية",
"Accounts_denyUnverifiedEmail": "رفض البريد الإلكتروني لم يتم التحقق منها",
"Accounts_EmailVerification": "التحقق من البريد الإلكتروني",
"Accounts_EmailVerification_Description": "تأكد أن لديك إعدادات SMTP الصحيحة لاستخدام هذه الميزة",
"Accounts_Enrollment_Email": "البريد الإلكتروني E-التحاق",
- "Accounts_Enrollment_Email_Default": " مرحبا بكم في [Site_Name] الذهاب إلى [Site_URL] ومحاولة أفضل المصدر المفتوح دردشة الحلول المتاحة اليوم!
",
+ "Accounts_Enrollment_Email_Default": " مرحبا بكم في [Site_Name] الذهاب إلى [Site_URL] ومحاولة أفضل المصدر المفتوح دردشة الحلول المتاحة اليوم!
",
"Accounts_Enrollment_Email_Description": "يمكنك استخدام [name]، [fname]، [lname] عن الاسم الكامل للمستخدم، الاسم الأول أو اسم العائلة، على التوالي. يمكنك استخدام [email] للبريد الإلكتروني الخاص بالمستخدم.",
"Accounts_Enrollment_Email_Subject_Default": "مرحبا بكم في [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "مسح جلسة المستخدم وإغلاق النافذة",
"Accounts_Iframe_api_method": "الطريقة المعهد",
"Accounts_Iframe_api_url": "المعهد رابط",
"Accounts_iframe_enabled": "تمكين",
@@ -48,9 +58,15 @@
"Accounts_OAuth_Custom_id": "هوية شخصية",
"Accounts_OAuth_Custom_Identity_Path": "مسار الهوية",
"Accounts_OAuth_Custom_Login_Style": "الدخول ستايل",
+ "Accounts_OAuth_Custom_Merge_Users": "دمج المستخدمين",
+ "Accounts_OAuth_Custom_Scope": "الإطار",
"Accounts_OAuth_Custom_Secret": "سر",
"Accounts_OAuth_Custom_Token_Path": "مسار رمزي",
"Accounts_OAuth_Custom_Token_Sent_Via": "رمزي المرسلة عن طريق",
+ "Accounts_OAuth_Custom_Username_Field": "حقل اسم المستخدم",
+ "Accounts_OAuth_Drupal": "تم تفعيل تسجيل الدخول عبر دوربال",
+ "Accounts_OAuth_Drupal_id": "رمز تعريف العميل الخاص بدوربال oAuth2",
+ "Accounts_OAuth_Drupal_secret": "مفتاح العميل السري الخاص بدوربال oAuth2",
"Accounts_OAuth_Facebook": "تسجيل الدخول الى الفيسبوك",
"Accounts_OAuth_Facebook_callback_url": "URL الفيسبوك الاستدعاء",
"Accounts_OAuth_Facebook_id": "الفيسبوك معرف التطبيق",
@@ -79,6 +95,8 @@
"Accounts_OAuth_Meteor_callback_url": "URL نيزك الاستدعاء",
"Accounts_OAuth_Meteor_id": "نيزك رقم",
"Accounts_OAuth_Meteor_secret": "نيزك السرية",
+ "Accounts_OAuth_Proxy_host": "مضيف الوكيل -البروكسي-",
+ "Accounts_OAuth_Proxy_services": "خدمات البروكسي",
"Accounts_OAuth_Twitter": "تويتر الدخول",
"Accounts_OAuth_Twitter_callback_url": "URL تويتر الاستدعاء",
"Accounts_OAuth_Twitter_id": "تويتر إيد",
@@ -88,6 +106,8 @@
"Accounts_OAuth_Wordpress_id": "وورد إيد",
"Accounts_OAuth_Wordpress_secret": "وورد السرية",
"Accounts_PasswordReset": "إعادة تعيين كلمة السر",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "الأدوار الافتراضية لخدمات المصادقة",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "سيتم تعيين الأدوار الافتراضية للمستخدمين عند التسجيل عبر خدمات المصادقة (افصل بينها بفاصلة)",
"Accounts_Registration_AuthenticationServices_Enabled": "تسجيل مع خدمات المصادقة",
"Accounts_RegistrationForm": "استمارة التسجيل",
"Accounts_RegistrationForm_Disabled": "معطل",
@@ -95,19 +115,29 @@
"Accounts_RegistrationForm_Public": "عام",
"Accounts_RegistrationForm_Secret_URL": "رابط سري",
"Accounts_RegistrationForm_SecretURL": "رابط استمارة التسجيل السري",
- "Accounts_RegistrationForm_SecretURL_Description": "يجب توفير سلسلة العشوائية التي ستضاف إلى URL تسجيلك. على سبيل المثال: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "يجب توفير سلسلة العشوائية التي ستضاف إلى URL تسجيلك. على سبيل المثال: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "تتطلب اسم للاشتراك",
+ "Accounts_RequirePasswordConfirmation": "يتطلب تأكيد كلمة المرور",
+ "Accounts_SetDefaultAvatar": "ضبط إعدادات الصورة الرمزية",
+ "Accounts_SetDefaultAvatar_Description": "يتم المحاولة لتعيين الصورة الرمزية الافتراضية بناءً على حساب OAuth أو حساب Gravatar",
"Accounts_ShowFormLogin": "يستند النموذج مشاهدة الدخول",
"Accounts_UseDefaultBlockedDomainsList": "استخدام الافتراضي محظور قائمة المجالات",
"Accounts_UseDNSDomainCheck": "استخدام المجال DNS تحقق",
- "Accounts_UserAddedEmail_Default": " مرحبا بكم في [Site_Name] الذهاب إلى [Site_URL] ومحاولة أفضل المصدر المفتوح دردشة الحلول المتاحة اليوم!
تستطيع تسجيل الدخول باستخدام البريد الإلكتروني: [email] وكلمة المرور: [password]. قد تكون هناك حاجة لتغييره بعد تسجيل الدخول الخاص بك أولا.",
+ "Accounts_UserAddedEmail_Default": "
مرحبا بكم في [Site_Name] الذهاب إلى [Site_URL] ومحاولة أفضل المصدر المفتوح دردشة الحلول المتاحة اليوم!
تستطيع تسجيل الدخول باستخدام البريد الإلكتروني: [email] وكلمة المرور: [password]. قد تكون هناك حاجة لتغييره بعد تسجيل الدخول الخاص بك أولا.",
"Accounts_UserAddedEmail_Description": "يمكنك استخدام العناصر النائبة التالية:
[name]، [fname]، [lname] لاسم المستخدم الكامل أو الاسم الأول أو اسم العائلة، على التوالي. [email] للبريد الإلكتروني الخاص بالمستخدم. [password] لكلمة المرور الخاصة بالمستخدم. [Site_Name] و [Site_URL] لاسم التطبيق وعنوان URL على التوالي. ",
"Accounts_UserAddedEmailSubject_Default": "لقد تم إضافتك إلى [Site_Name]",
"Activate": "تفعيل",
"Activity": "أنشطة",
"Add": "إضافة",
+ "add-user": "إضافة مستخدم",
+ "add-user-to-any-c-room": "إضافة مستخدم لأي قناة عامة",
+ "add-user-to-any-c-room_description": "التصريح بإضافة مستخدم إلى أي قناة عامة",
+ "add-user-to-any-p-room": "إضافة مستخدم لأي قناة خاصة",
+ "add-user-to-any-p-room_description": "التصريح بإضافة مستخدم إلى أي قناة خاصة",
+ "add-user_description": "التصريح بإضافة مستخدمين جدد إلى الخادم عبر نافذة المستخدمين",
"Add_agent": "أضف وكيل",
"Add_custom_oauth": "إضافة أوث مخصصة",
+ "Add_Domain": "إضافة اسم مجال",
"Add_manager": "أضف مدير",
"Add_user": "إضافة مستخدم",
"Add_User": "إضافة مستخدم",
@@ -119,35 +149,52 @@
"Additional_Feedback": "ملاحظات إضافية",
"Administration": "الإدارة",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "بعد المصادقة في OAuth2، سيتم إعادة توجيه المستخدمين إلى هذا الرابط",
+ "Agent": "الموظف",
"Agent_added": "تمت إضافة الوكيل",
"Agent_removed": "تمت إزالة الوكيل",
"Alias": "الاسم المستعار",
+ "Alias_Format": "صيغة الخدمة البديلة",
+ "Alias_Set": "مجموعة الخدمات البديلة",
"All": "الكل",
"All_channels": "جميع القنوات",
"All_logs": "كل السجلات",
"All_messages": "كل الرسائل",
"Allow_Invalid_SelfSigned_Certs": "السماح بالشهادات غير الصالحة الموقعة ذاتيا",
"Allow_Invalid_SelfSigned_Certs_Description": "السماح لشهادة SSL غير صحيحة وموقعة ذاتيا للتأكد من صحة الرابط ومعاينات.",
+ "Allow_switching_departments": "السماح للمستخدمين بتغيير الفرع",
+ "Always_open_in_new_window": "دائماً قم بالفتح بنافذة جديدة",
"Analytics_features_enabled": "الميزات الممكنة",
"Analytics_features_messages_Description": "يتابع أحداث مخصصة ذات الصلة إلى إجراءات المستخدم لا على الرسائل.",
"Analytics_features_rooms_Description": "يتابع أحداث مخصصة تتعلق الإجراءات على قناة أو مجموعة (خلق، وترك، وحذف).",
"Analytics_features_users_Description": "يتابع أحداث مخصصة تتعلق الإجراءات ذات الصلة للمستخدمين (مرات إعادة تعيين كلمة المرور، الشخصية تغيير الصورة، الخ).",
+ "Analytics_Google": "تحليلات الغوغول",
+ "Analytics_Google_id": "رمز تتبع تحليلات الغوغل",
"and": "و",
"And_more": "وأكثر من ذلك __length __",
"Animals_and_Nature": "حيوانات و طبيعة",
+ "Announcement": "إعلان",
"API": "API",
+ "API_Allow_Infinite_Count": "سماح كل شيء",
"API_Analytics": "التحليلات",
+ "API_CORS_Origin": "مصدر CORS ",
+ "API_Default_Count": "التعداد الافتراضي",
+ "API_Drupal_URL": "رابط خادم دوربال",
+ "API_Drupal_URL_Description": "مثال: https://domain.com -بدون الشرطة المائلة في النهاية -",
"API_Embed": "تضمين",
+ "API_EmbedCacheExpirationDays": "تضمين أيام انتهاء صلاحية التخزين المؤقت",
"API_EmbedDisabledFor": "تضمين تعطيل للمستخدمين",
"API_EmbedDisabledFor_Description": "قائمة مفصولة بفواصل من أسماء المستخدمين",
"API_EmbedIgnoredHosts": "تضمين تستضيف تجاهل",
"API_EmbedIgnoredHosts_Description": "قائمة المضيفين أو عناوين CIDR، على سبيل المثال مفصولة بفواصل. المضيف المحلي، 127.0.0.1، 10.0.0.0/8، 172.16.0.0/12، 192.168.0.0/16",
"API_EmbedSafePorts": "موانئ آمنة",
"API_EmbedSafePorts_Description": "قائمة المنافذ المسموح بها لمعاينة مفصولة بفواصل.",
+ "API_Enable_CORS": "تفعيل CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "تفعيل نهاية سجل الرسائل المباشرة ",
"API_GitHub_Enterprise_URL": "URL الخادم",
"API_GitHub_Enterprise_URL_Description": "مثال: http://domain.com (بدون الشرطة المائلة في الأخير)",
"API_Gitlab_URL": "URL GitLab",
"API_Token": "API رمز",
+ "API_Upper_Count_Limit": "الحد الأقصى لقيمة القيد",
"API_User_Limit": "حد المستخدم لإضافة جميع الاعضاء للقناة",
"API_Wordpress_URL": "URL ورد",
"Apiai_Key": "Api.ai مفتاح",
@@ -158,16 +205,26 @@
"Application_updated": "تحديث التطبيق",
"Apply_and_refresh_all_clients": "تطبيق وتحديث كافة عملاء",
"Archive": "الأرشيف",
+ "archive-room": "أرشفة الغرفة",
+ "archive-room_description": "التصريح بأرشفة القناة",
"are_also_typing": "هم أيضا يكتبون",
"are_typing": "يكتبون",
"Are_you_sure": "هل أنت متأكد؟",
"Are_you_sure_you_want_to_delete_your_account": "هل أنت متأكد من أنك تريد حذف حسابك؟",
+ "assign-admin-role": "تعيين دور المدير",
+ "assign-admin-role_description": "التصريح بمنح المستخدمين الآخرين دور المدير",
+ "Assign_admin": "تعيين المدير",
"at": "في",
+ "Attachment_File_Uploaded": "تم رفع الملف",
+ "Attribute_handling": "معالجة الخصائص ",
"Auth_Token": "المصادقة رمز",
"Author": "الكاتب",
"Authorization_URL": "URL التخويل",
"Authorize": "يأذن",
+ "auto-translate": "ترجمة تلقائية",
+ "auto-translate_description": "التصريح باستخدام أداة الترجمة التلقائية",
"Auto_Load_Images": "تحميل تلقائي للصور",
+ "Auto_Translate": "ترجمة تلقائية",
"AutoLinker_Email": "AutoLinker البريد الإلكتروني",
"AutoLinker_Phone": "AutoLinker الهاتف",
"AutoLinker_Phone_Description": "ترتبط آليا عن أرقام الهاتف. على سبيل المثال `(123) 456-7890`",
@@ -177,6 +234,10 @@
"AutoLinker_Urls_TLD": "عناوين AutoLinker TLD",
"AutoLinker_Urls_www": "عناوين AutoLinker \"شبكة الاتصالات العالمية\"",
"AutoLinker_UrlsRegExp": "AutoLinker URL التعبير منتظم",
+ "Automatic_Translation": "ترجمة تلقائية",
+ "AutoTranslate_Change_Language_Description": "لن يتم ترجمة الرسائل السابقة عند تغيير لغة الترجمة التلقائية ",
+ "AutoTranslate_Enabled": "تفعيل الترجمة التلقائية",
+ "AutoTranslate_GoogleAPIKey": "مفتاح API للغوغل",
"Available": "متاح",
"Available_agents": "الوكلاء الموجودون",
"Avatar": "الصورة الرمزية",
@@ -191,12 +252,24 @@
"Away_male": "بعيد",
"Back": "العودة",
"Back_to_applications": "العودة إلى التطبيقات",
+ "Back_to_integration_detail": "العودة إلى تفاصيل الدمج",
"Back_to_integrations": "العودة إلى التكامل",
"Back_to_login": "العودة إلى تسجيل الدخول",
"Back_to_permissions": "العودة إلى التصريحات",
+ "Backup_codes": "شيفرات التخزين الاحتياطي",
+ "ban-user": "حظر المستخدم",
+ "ban-user_description": "التصريح لحظر مستخدم من القناة",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "ميزة تجريبية. تعتمد على تفعيل إقامة مؤتمر عبر الفيديو.",
+ "Block_User": "حظر المستخدم",
"Body": "الجسم",
"bold": "عريض",
+ "bot_request": "طلب الروبوت",
+ "BotHelpers_userFields": "حقول المستخدم",
"Branch": "الفرع",
+ "bulk-create-c": "إنشاء قنوات دفعة واحدة",
+ "bulk-create-c_description": "التصريح بإنشاء قنوات دفعة واحدة",
+ "bulk-register-user": "إنشاء قنوات دفعة واحدة",
+ "bulk-register-user_description": "التصريح بإنشاء قنوات دفعة واحدة",
"busy": "مشغول",
"Busy": "مشغول",
"busy_female": "مشغولة",
@@ -204,17 +277,33 @@
"busy_male": "مشغول",
"Busy_male": "مشغول",
"by": "بواسطة",
+ "cache_cleared": "تم مسح التخزين المؤقت",
"Cancel": "إلغاء",
"Cancel_message_input": "لإلغاء التغييرات",
"Cannot_invite_users_to_direct_rooms": "لا يمكن دعوة المستخدمين إلى غرف توجيه",
+ "Cannot_open_conversation_with_yourself": "لا يُمكن البدء بمحادثة مع نفسك",
+ "CAS_autoclose": "الإغلاق التلقائي لنافذة تسجيل الدخول المنبثقة",
+ "CAS_button_color": "لون خلفية زر تسجيل الدخول",
+ "CAS_button_label_color": "لون نص زر تسجيل الدخول",
+ "CAS_button_label_text": "عنوان زر تسجيل الدخول",
+ "CAS_enabled": "مُفعّل",
+ "CAS_popup_height": "ارتفاع نافذة تسجيل الدخول المنبثقة",
+ "CAS_popup_width": "عرض نافذة تسجيل الدخول المنبثقة",
+ "CAS_Sync_User_Data_Enabled": "المزامنة مع بيانات المستخدم دائماً",
+ "CAS_Sync_User_Data_FieldMap": "خريطة السمة",
+ "CAS_version": "نسخة CAS",
"CDN_PREFIX": "كندي البادئة",
"Certificates_and_Keys": "شهادات ومفاتيح",
+ "Change_Room_Type": "تغيير نوع الغرفة",
"Changing_email": "البريد الإلكتروني تغيير",
+ "channel": "القناة",
"Channel": "قناة",
"Channel_already_exist": "القناة #٪ s 'موجود مسبقا.",
"Channel_already_Unarchived": "قناة مع اسم `#٪ s` هي بالفعل في حالة إلغاء أرشفة",
"Channel_Archived": "تم أرشفة قناة مع اسم `#٪ s` بنجاح",
+ "Channel_created": "تم إنشاء قناة `#%s`",
"Channel_doesnt_exist": "القناة '#%s' غير موجودة.",
+ "Channel_to_listen_on": "السماع إلى هذه القناة",
"Channel_Unarchived": "وكانت قناة مع اسم `#٪ s` إلغاء أرشفة بنجاح",
"Channels": "القنوات",
"Channels_list": "قائمة القنوات العامة",
@@ -229,19 +318,27 @@
"Choose_messages": "اختر الرسائل",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "اختيار الاسم المستعار الذي سيمثل أمام اسم المستخدم في الرسائل.",
"Choose_the_username_that_this_integration_will_post_as": "اختيار اسم المستخدم أن هذا التكامل سوف منصب.",
+ "clear": "مسح",
"Clear_all_unreads_question": "مسح كافة الغير مقروءة؟",
+ "clear_cache_now": "مسح التخزين المؤقت الآن",
+ "clear_history": "مسح السجل",
"Click_here": "انقر هنا",
+ "Click_here_for_more_info": "انقر هنا للمزيد من المعلومات",
"Client_ID": "معرف العميل",
"Client_Secret": "سر العميل",
"Clients_will_refresh_in_a_few_seconds": "سوف عملاء تجديد في بضع ثوان",
"close": "غلق",
+ "Close": "إغلاق",
"Closed": "مغلق",
+ "Closed_by_visitor": "تم الإغلاق من قبل الزائر",
"Closing_chat": "إغلاق الدردشة",
"Collapse_Embedded_Media_By_Default": "إخفاء الوسائط المدمجة بشكل تلقائي",
"Color": "اللون",
"Commands": "الأوامر",
+ "Comment_to_leave_on_closing_session": "التعليق الموضوع على إنهاء الجلسة",
"Compact": "اتفاق",
"Confirm_password": "تأكيد كلمة السر",
+ "Content": "المحتوى",
"Conversation": "محادثة",
"Conversation_closed": "المحادثة أغلقت: __comment__.",
"Convert_Ascii_Emojis": "حول محارف الأسكي إلى اموجي",
@@ -252,30 +349,76 @@
"Count": "عد",
"Cozy": "دافئ",
"Create": "خلق",
+ "create-c_description": "التصريح بإنشاء قنوات عامة",
+ "create-d": "إنشاء رسائل مباشرة",
+ "create-d_description": "التصريح بالبدء بإرسال رسائل مباشرة",
+ "create-p": "إنشاء قنوات خاصة",
+ "create-p_description": "التصريح بإنشاء قنوات خاصة",
+ "create-user": "إنشاء مستخدم",
+ "create-user_description": "التصريح بإنشاء مستخدمين",
"Create_A_New_Channel": "إنشاء قناة جديدة",
"Create_new": "إنشاء جديد",
"Created_at": "أنشئت في",
"Created_at_s_by_s": "أنشئت في %s بواسطة %s ",
+ "Created_at_s_by_s_triggered_by_s": "تم الإنشاء في %s بوساطة %s ومُشغّل بوساطة %s ",
+ "CRM_Integration": "دمج CRM",
+ "CROWD_Reject_Unauthorized": "رفض غير المُصرّح به",
"Current_Chats": "الدردشات الحالية",
+ "Current_Status": "الحالة الحالية",
"Custom": "عرف",
+ "Custom_Emoji": "رمز تعبيري مخصص",
+ "Custom_Emoji_Add": "إضافة رمز تعبيري جديد",
+ "Custom_Emoji_Added_Successfully": "تم إضافة رمز تعبيري جديد بنجاح",
+ "Custom_Emoji_Delete_Warning": "لا يمكن التراجع عن حذف الرمز التعبيري",
+ "Custom_Emoji_Error_Invalid_Emoji": "رمز تعبيري غير صالح",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "يتم استخدام هذا الرمز التعبيري المخصص أو أحد خدماته البديلة حالياً",
+ "Custom_Emoji_Has_Been_Deleted": "تم حذف الرمز التعبيري",
+ "Custom_Emoji_Info": "معلومات الرمز التعبيري المخصص",
+ "Custom_Emoji_Updated_Successfully": "تم تحديث الرمز التعبيري بنجاح",
"Custom_Fields": "الحقول المخصصة",
"Custom_oauth_helper": "عند إعداد مزود أوث الخاص بك، سيكون لديك لإبلاغ URL الاستدعاء. استعمال ٪ الصورة .",
"Custom_oauth_unique_name": "اسم فريد أوث مخصص",
"Custom_Script_Logged_In": "سيناريو المخصصة لتسجيل الدخول للمستخدمين",
"Custom_Script_Logged_Out": "سيناريو مخصصة للمستخدمين تسجيل الخروج",
+ "Custom_Scripts": "سكربتات مخصصة",
+ "Custom_Sound_Add": "إضافة صوت مخصص",
+ "Custom_Sound_Delete_Warning": "لا يمكن التراجع عن حذف الصوت",
+ "Custom_Sound_Error_Invalid_Sound": "صوت غير صالح",
+ "Custom_Sound_Error_Name_Already_In_Use": "الصوت المخصص مُستخدم للتوّ",
+ "Custom_Sound_Has_Been_Deleted": "تم حذف الصوت المخصص",
+ "Custom_Sound_Info": "بيانات الصوت المخصص",
+ "Custom_Sound_Saved_Successfully": "تم حفظ الصوت المخصص بنجاح",
+ "Custom_Sounds": "أصوات مخصصة",
+ "Custom_Translations": "ترجمة مخصصة",
+ "Custom_Translations_Description": "يجب أن يكون كود JSON صالح. حيث تكون المفاتيح لغات تحتوي على قاموس المفتاح والترجمة. مثال:\n {\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n\n}",
+ "CustomSoundsFilesystem": "ملفات الأصوات المخصصة",
"Dashboard": "لوحة القيادة",
"Date": "تاريخ",
+ "Date_From": "من",
+ "Date_to": "إلى",
"days": "أيام",
"DB_Migration": "الهجرة قاعدة البيانات",
"DB_Migration_Date": "قاعدة بيانات التسجيل الهجرة",
"Deactivate": "تعطيل",
+ "Decline": "إلغاء",
"Default": "افتراضي",
"Delete": "حذف",
+ "delete-c": "حذف قنوات عامة",
+ "delete-c_description": "التصريح بحذف قنوات عامة",
+ "delete-d": "حذف رسائل مباشرة",
+ "delete-d_description": "التصريح بحذف الرسائل العامة",
+ "delete-message": "حذف الرسائل",
+ "delete-message_description": "التصريح بحذف رسالة في غرفة",
+ "delete-p": "حذف القنوات الخاصة",
+ "delete-p_description": "التصريح بحذف القنوات الخاصة",
+ "delete-user": "حذف مسخدم",
+ "delete-user_description": "التصريح بحذف المستخدمين",
"Delete_message": "حذف رسالة",
"Delete_my_account": "حذف حسابي",
"Delete_Room_Warning": "حذف الغرفة، يحذف جميع الرسائل المرسلة داخل الغرفة.، هذا لا يمكن التراجع عنه.",
"Delete_User_Warning": "سوف حذف مستخدم حذف كل الرسائل من هذا المستخدم أيضا. هذا لا يمكن التراجع عنها.",
"Deleted": "تم الحذف!",
+ "Department": "الفرع",
"Department_removed": "قسم إزالة",
"Departments": "الأقسام",
"Deployment_ID": "معرف النشر",
@@ -289,11 +432,16 @@
"Desktop_Notifications_Enabled": "تنبيهات سطح المكتب مفعلة",
"Direct_message_someone": "رسالة شخص المباشر",
"Direct_Messages": "الرسائل المباشرة",
+ "Disable_Notifications": "إلغاء تفعيل الإشعارات",
+ "Disable_two-factor_authentication": "إلغاء تفعيل المصادقة بخطوتين",
"Display_offline_form": "عرض النموذج متواجد حاليا",
"Displays_action_text": "نص العمل يعرض",
"Do_you_want_to_change_to_s_question": "هل تريد التغيير إلى %s ؟",
"Domain": "نطاق",
+ "Domain_added": "تم إضافة اسم المجال",
+ "Domain_removed": "تم حذف اسم المجال",
"Domains": "المجالات",
+ "Download_Snippet": "تحميل",
"Drop_to_upload_file": "إسقاط لتحميل الملف",
"Dry_run": "تنفيذ تجريبي",
"Dry_run_description": "سيتم إرسال رسالة بريدية واحدة إلى نفس العنوان الموجود في خانة \"من\". تأكد من كون ذلك العنوان البريدي فعال",
@@ -303,8 +451,21 @@
"Duplicate_private_group_name": "توجد مجموعة خاصة باسم '%s'",
"Duration": "المدة",
"Edit": "تعديل",
+ "edit-message": "تعديل الرسالة",
+ "edit-message_description": "التصريح بتعديل رسالة في غرفة",
+ "edit-other-user-active-status": "تعديل حالة المستخدمين النشطين الآخرين",
+ "edit-other-user-active-status_description": "التصريح بتفعيل أو إلغاء تفعيل الحسابات الأخرى",
+ "edit-other-user-info": "تعديل معلومات المستخدمين الآخرين",
+ "edit-other-user-info_description": "التصريح بتغيير الاسم، أو اسم المستخدم أو عنوان البريد الإلكتروني",
+ "edit-other-user-password": "تعديل كلمات مرور المستخدمين الآخرين",
+ "edit-other-user-password_description": "التصريح بتعديل كلمات المرور للأشخاص. يتطلب تعديل تصريح معلومات المستخدم الأخرى",
+ "edit-privileged-setting": "تعديل إعدادات الامتيازات",
+ "edit-privileged-setting_description": "التصريح بتعديل الإعدادات",
+ "edit-room": "تعديل الرسالة",
"Edit_Custom_Field": "تحرير حقل مخصص",
"Edit_Department": "وزارة تحرير",
+ "Edit_previous_message": "`%s` تعديل الرسالة السابقة",
+ "Edit_Trigger": "تعديل المُشغل",
"edited": "تم العديل",
"Editing_room": "غرفة التحرير",
"Editing_user": "تحرير المستخدم",
@@ -323,15 +484,19 @@
"Email_subject": "الموضوع",
"Email_verified": "تم التحقق من البريد الإلكتروني",
"Emoji": "رمز تعبيري (اموجي)",
+ "EmojiCustomFilesystem": "ملفات الرموز التعبيرية المخصصة",
"Empty_title": "عنوان فارغ",
"Enable": "تمكين",
"Enable_Desktop_Notifications": "تفعيل تنبيهات سطح المكتب",
+ "Enable_Svg_Favicon": "تفعيل أيقونة SVG ",
+ "Enable_two-factor_authentication": "تفعيل المصادقة بخطوتين",
"Enabled": "مفعل",
"Encrypted_message": "رسالة مشفرة",
"End_OTR": "إنهاء المحادثة السرية",
"Enter_a_regex": "أدخل التعابير المنطقية",
"Enter_a_room_name": "أدخل اسم الغرفة",
"Enter_a_username": "أدخل اسم المستخدم",
+ "Enter_authentication_code": "ادخل رمز المصادقة",
"Enter_name_here": "أدخل اسم هنا",
"Enter_to": "زر الإدخال",
"Error": "خطأ",
@@ -346,6 +511,7 @@
"error-could-not-change-username": "لا يمكن تغيير اسم المستخدم",
"error-delete-protected-role": "لا يمكنك حذف دور محمية",
"error-department-not-found": "قسم غير موجود",
+ "error-direct-message-file-upload-not-allowed": "لا يسمح بمشاركة الملفات في الرسائل المباشرة",
"error-duplicate-channel-name": "توجد قناة باسم '%s'",
"error-email-domain-blacklisted": "القائمة السوداء المجال البريد الإلكتروني",
"error-field-unavailable": "__field__ مستخدم مسبقا :(",
@@ -359,9 +525,11 @@
"error-invalid-channel-start-with-chars": "قناة غير صالحة. ابدأ بـ @ أو #",
"error-invalid-custom-field": "حقل مخصص غير صالح",
"error-invalid-custom-field-name": "اسم الحقل المخصص غير صالح. استخدام حروف أو أرقام أو الواصلات والشرطات السفلية.",
+ "error-invalid-date": "التاريخ المُدخل غير صالح",
"error-invalid-description": "وصف صالح",
"error-invalid-domain": "مجال غير صالح",
"error-invalid-email": "__email__ البريد الإلكتروني غير صالح",
+ "error-invalid-email-address": "البريد الإلكتروني غير صالح",
"error-invalid-file-height": "ارتفاع ملف غير صالح",
"error-invalid-file-type": "نوع الملف غير صالح",
"error-invalid-file-width": "عرض ملف غير صالح",
@@ -404,18 +572,31 @@
"error-you-are-last-owner": "كنت صاحب الماضي. الرجاء تعيين المالك الجديد قبل مغادرة الغرفة.",
"Error_changing_password": "خطأ في تغيير كلمة السر",
"Esc_to": "زر الهروب",
+ "Event_Trigger": "مشغل العملية",
+ "every_30_minutes": "مرة في كل 30 دقيقة",
+ "every_hour": "مرة في كل ساعة",
+ "every_six_hours": "مرة في كل ست ساعات",
"Example_s": "على سبيل المثال: %s",
+ "Exclude_Botnames": "استبعاد الروبوتات",
"False": "لا",
"Favorite_Rooms": "تمكين تفضيل الغرف",
"Favorites": "المفضلة",
"Features_Enabled": "الميزات الممكنة",
"Field": "حقل",
"Field_removed": "إزالة الميدان",
+ "Field_required": "حقل مطلوب",
"File_exceeds_allowed_size_of_bytes": "يتجاوز حجم الملف المسموح به بايت __size__",
+ "File_not_allowed_direct_messages": "لا يسمح بمشاركة الملفات في الرسائل المباشرة",
+ "File_type_is_not_accepted": "نوع الملف غير مسموح",
+ "File_uploaded": "الملف المرفوع",
"FileUpload": "تحميل الملف",
+ "FileUpload_Disabled": "تم إلغاء تفعيل رفع الملفات",
"FileUpload_Enabled": "تحميل الملفات مفعلة",
"FileUpload_File_Empty": "ملف فارغ",
"FileUpload_FileSystemPath": "مسار النظام",
+ "FileUpload_GoogleStorage_AccessId": "رمز تعريف وصول تخزين غوغل",
+ "FileUpload_GoogleStorage_Bucket": "اسم سلة تخزين غوغل",
+ "FileUpload_GoogleStorage_Secret": "المفتاح السري لتخزين غوغل",
"FileUpload_MaxFileSize": "الحد الأقصى لتحميل الملف الحجم (بايت)",
"FileUpload_MediaType_NotAccepted": "أنواع وسائل الإعلام ليس مقبول",
"FileUpload_MediaTypeWhiteList": "أنواع الوسائط المقبولة",
@@ -428,17 +609,31 @@
"FileUpload_S3_Bucket": "الأمازون S3 اسم دلو",
"FileUpload_S3_BucketURL": "URL دلو",
"FileUpload_S3_CDN": "نطاق كندي للتنزيل",
+ "FileUpload_S3_ForcePathStyle": "فرض مظهر المسار",
"FileUpload_S3_Region": "منطقة",
+ "FileUpload_S3_SignatureVersion": "نسخة التوقيع",
+ "FileUpload_S3_URLExpiryTimeSpan": "فترة انتهاء صلاحية الروابط",
"FileUpload_Storage_Type": "نوع التخزين",
"Flags": "أعلام",
"Follow_social_profiles": "اتبع محات اجتماعية لدينا، مفترق لنا على جيثب وتبادل الأفكار حول التطبيق rocket.chat على متن trello لدينا.",
+ "Fonts": "الخطوط",
"Food_and_Drink": "طعام و مشروبات",
"Footer": "تذييل",
"For_your_security_you_must_enter_your_current_password_to_continue": "ﻷسباب أمنية، عليك إعادة إدخال كلمة المرور للمتابعة",
+ "force-delete-message": "فرض حذف الرسالة",
+ "force-delete-message_description": "التصريح بحذف رسالة بتخطي كل القيود",
"Force_SSL": "قوة SSL",
"Force_SSL_Description": "* الحذر! * لا ينبغي أبدا أن تستخدم _Force SSL_ مع وكيل عكسي. إذا كان لديك وكيل عكسي، يجب القيام إعادة التوجيه هناك. يوجد هذا الخيار لنشر مثل Heroku، لا يسمح التكوين إعادة توجيه في كيل عكسي.",
"Forgot_password": "نسيت كلمة السر",
+ "Forgot_Password_Email": "انقر هنا لإعادة تعيين كلمة المرور الخاصة بك.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - استرداد كلمة المرور",
+ "Forgot_password_section": "تم نسيان كلمة المرور",
+ "Forward": "إعادة توجيه",
+ "Forward_chat": "إعادة توجيه الدردشة",
+ "Forward_to_department": "إعادة التوجيه إلى فرع",
+ "Forward_to_user": "إعادة التوجيه إلى مستخدم",
"Frequently_Used": "الأكثر استعمالا",
+ "Friday": "الجمعة",
"From": "من",
"From_Email": "من البريد الإلكتروني",
"From_email_warning": "تحذير: حقل من يخضع لإعدادات خادم البريد الخاص بك.",
@@ -447,14 +642,22 @@
"Give_a_unique_name_for_the_custom_oauth": "تعطي اسما فريدا لأوث مخصصة",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "إعطاء التطبيق اسما. وسوف يظهر هذا من قبل المستخدمين.",
"Global": "عالمي",
+ "GoogleCloudStorage": "التخزين السحابي للغوغل",
"GoogleTagManager_id": "جوجل مدير العلامات معرف",
"Hash": "مزيج",
"Header": "رأس",
+ "Header_and_Footer": "الترويسة والتذييل",
+ "Helpers": "المساعدون",
+ "Hex_Color_Preview": "معاينة اللون السداسي",
"Hidden": "مخفي",
+ "Hide_Avatars": "إخفاء الأفتار",
+ "Hide_flextab": "إخفاء الشريط الجانبي الأيمن بنقرة واحدة",
"Hide_Group_Warning": "هل أنت متأكد من أنك تريد إخفاء المجموعة \"%s\"؟",
"Hide_Private_Warning": "هل أنت متأكد من أنك تريد إخفاء المحادثة مع \"%s\"؟",
+ "Hide_roles": "إخفاء الأدوار",
"Hide_room": "إخفاء الغرفة",
"Hide_Room_Warning": "هل أنت متأكد من أنك تريد إخفاء الغرفة \"%s\"؟",
+ "Hide_Unread_Room_Status": "إخفاء حالة الغرفة في حالة غير المقروءة",
"Hide_usernames": "إخفاء أسماء المستخدمين",
"Highlights": "التظليل",
"Highlights_How_To": "إذا أردت أن يتم تنبيهك عندما يذكر احدهم كلمة ما أضفها هنا. قم بفصل الكلمات بفاصلة , الكلمات الأعجمية المظللة لا تتأثر بحالة الحرف (صغير أو كبير).",
@@ -462,12 +665,20 @@
"History": "تاريخ",
"Host": "مضيف",
"hours": "ساعة",
+ "Hours": "ساعات",
"How_friendly_was_the_chat_agent": "كيف ودية وكان وكيل الدردشة؟",
"How_knowledgeable_was_the_chat_agent": "معرفة كيف كان وكيل الدردشة؟",
+ "How_long_to_wait_after_agent_goes_offline": "كم من الوقت يجب الإنتظار بعد ذهاب الموظف أوفلاين",
"How_responsive_was_the_chat_agent": "كيف تستجيب كان وكيل الدردشة؟",
"How_satisfied_were_you_with_this_chat": "ما مدى رضاك مع هذه الدردشة؟",
"If_you_are_sure_type_in_your_password": "إدا كنت متأكد أدخل كلمة المرور الخاصة بك:",
"If_you_are_sure_type_in_your_username": "إذا كنت متأكدا من نوع في اسم المستخدم الخاص بك:",
+ "Iframe_Integration": "دمج Iframe",
+ "Iframe_Integration_receive_enable": "تفعيل الاستقبال",
+ "Iframe_Integration_receive_enable_Description": "السماح للنافذة الأم بإرسال أوامر لــِ Rocket.Chat",
+ "Iframe_Integration_receive_origin": "استقبال الأصل",
+ "Iframe_Integration_send_enable": "تفعيل الإرسال",
+ "Iframe_Integration_send_enable_Description": "إرسال العمليات إلى النافذة الأم",
"Importer_Archived": "مؤرشفة",
"Importer_done": "استيراد كاملة!",
"Importer_finishing": "حتى الانتهاء من الاستيراد.",
@@ -485,6 +696,8 @@
"Importer_Prepare_Uncheck_Deleted_Users": "المستخدمين قم بإلغاء التحديد محذوفة",
"Importer_progress_error": "فشل في الحصول على التقدم للاستيراد.",
"Importer_setup_error": "حدث خطأ أثناء إعداد المستورد.",
+ "Importer_Source_File": "اختيار ملف المصدر",
+ "Incoming_Livechats": "رسائل الدردشة المباشرة القادمة",
"inline_code": "نص_برمجي",
"Install_Extension": "تثبيت التمديد",
"Install_FxOs": "تثبيت Rocket.Chat على فايرفوكس",
@@ -493,13 +706,35 @@
"Install_FxOs_follow_instructions": "الرجاء التأكد من تثبيت التطبيق على جهازك (اضغط على \"تثبيت\" عندما دفع).",
"Installation": "تركيب",
"Installed_at": "تثبيت في",
+ "Instance_Record": "مثال على قيد",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "تعليمات لزائرك ملء النموذج لإرسال رسالة",
"Integration_added": "تمت إضافة التكامل",
+ "Integration_Advanced_Settings": "الإعدادات المتقدمة",
+ "Integration_History_Cleared": "تم مسح سجل الدمج بنجاح",
"Integration_Incoming_WebHook": "واردة التكامل WebHook",
"Integration_New": "التكامل الجديد",
"Integration_Outgoing_WebHook": "المنتهية ولايته التكامل WebHook",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "تم نقل البيانات للدمج",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "تم إرسال البيانات عبر الرابط",
+ "Integration_Outgoing_WebHook_History_Http_Response": "استجابة HTTP",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "خطأ في استجابة HTTP",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "الرسائل المرسلة في خطوة الإعداد",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "الرسائل المرسلة في خطوة استجابة العملية",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "خطوة المُشغّل الأخيرة",
+ "Integration_Retry_Count": "إعادة العد",
+ "Integration_Retry_Count_Description": "كم مرة يجب إعادة محاولة الدمج في حالة فشل استجابة الرابط؟",
+ "Integration_Retry_Delay": "إعادة محاولة التأخير",
+ "Integration_Run_When_Message_Is_Edited": "التشغيل عند التعديل",
"Integration_updated": "تم تحديث التكامل",
+ "Integration_Word_Trigger_Placement": "استبدال الكلمة في كل موضع",
"Integrations": "التكامل",
+ "Integrations_Outgoing_Type_FileUploaded": "تم رفع الملف",
+ "Integrations_Outgoing_Type_RoomArchived": "تمت أرشفة الغرفة",
+ "Integrations_Outgoing_Type_RoomCreated": "تم إنشاء الغرفة (عامة أو خاصة)",
+ "Integrations_Outgoing_Type_RoomJoined": "انضم مستخدم للغرفة",
+ "Integrations_Outgoing_Type_RoomLeft": "غادر مستخدم الغرفة",
+ "Integrations_Outgoing_Type_SendMessage": "تم إرسال الرسالة",
+ "Integrations_Outgoing_Type_UserCreated": "تم إنشاء المستخدم",
"InternalHubot": "Hubot الداخلية",
"InternalHubot_ScriptsToLoad": "مخطوطات لتحميل",
"InternalHubot_ScriptsToLoad_Description": "الرجاء إدخال قائمة مفصولة بفواصل من مخطوطات لتحميل من https://github.com/github/hubot-scripts/tree/master/src/scripts",
@@ -513,6 +748,8 @@
"Invalid_pass": "لا يجب أن تكون كلمة السر فارغة",
"Invalid_room_name": "%s لا يصلح كاسم، استخدم حروفا و أرقاما وشرطات فقط",
"Invalid_secret_URL_message": "عنوان URL المقدمة غير صالح.",
+ "Invalid_setting_s": "ضبط غير صالح: %s",
+ "Invalid_two_factor_code": "رمز المصادقة بخطوتين غير صالح",
"invisible": "خفي",
"Invisible": "خفي",
"Invitation_HTML": "دعوة HTML",
@@ -533,7 +770,9 @@
"Jitsi_Chrome_Extension": "الكروم تمديد إيد",
"Jitsi_Enable_Channels": "تمكين في القنوات",
"join": "انضم",
+ "join-without-join-code": "الانضمام بدون كود الانضمام",
"Join_audio_call": "انضم للاتصال الصوتي",
+ "Join_Chat": "الانضمام للدردشة",
"Join_default_channels": "تاريخ القنوات الافتراضية",
"Join_the_Community": "إنظم للمجتمع",
"Join_the_given_channel": "انضم للقناة",
@@ -566,30 +805,24 @@
"Layout_Terms_of_Service": "شروط الخدمة",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA سيرت",
- "LDAP_Custom_Domain_Search": "البحث المجال مخصص",
- "LDAP_Custom_Domain_Search_Description": "قطعة من JSON الذي يحكم ربط واتصال من المعلومات وهو النموذج: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "انتهاء مدة الاتصال (بالملي ثانية)",
"LDAP_Default_Domain": "المجال الافتراضي",
"LDAP_Description": "LDAP هي قاعدة بيانات هرمية التي تستخدم العديد من الشركات لتقديم إشارة واحدة على - مرفق لتقاسم كلمة مرور واحدة بين المواقع وخدمات متعددة. للحصول على معلومات التكوين المتقدمة والأمثلة، يرجى الرجوع لدينا ويكي: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "قاعدة المجال",
- "LDAP_Domain_Base_Description": "اسم المؤهل بالكامل المميز (DN) من الشجرة الفرعية LDAP تريد البحث للمستخدمين والمجموعات. يمكنك إضافة ما تريد. ومع ذلك، يجب أن تحدد كل مجموعة في قاعدة نطاق نفس المستخدمين التي تنتمي إليها. إذا قمت بتحديد مجموعات المستخدمين المحظورة، وفقط للمستخدمين الذين ينتمون لتلك الجماعات أن يكون في نطاق. نوصي تحديد المستوى الخاص بك شجرة دليل LDAP كقاعدة المجال الخاص بك واستخدام فلتر البحث للتحكم في الوصول.",
- "LDAP_Domain_Search_Filter": "نطاق البحث تصفية",
- "LDAP_Domain_Search_Filter_Description": "إذا كان سيتم السماح محددة، فقط للمستخدمين تطابق هذا المرشح لتسجيل الدخول. إذا لم يتم تحديد مرشح، جميع المستخدمين ضمن نطاق قاعدة المجال المحدد سوف تكون قادرة على تسجيل الدخول. على سبيل المثال ل Active Directory `memberOf = CN = ROCKET_CHAT، أوو = العام Groups`. على سبيل المثال لب OpenLDAP (للمد بحث مباراة) `أوو: DN: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "المجال كائن البحث التصنيف",
- "LDAP_Domain_Search_Object_Category_Description": "و* objectCategory * أن تحديد المستخدمين. اتركه فارغا ل* ب OpenLDAP *. على سبيل المثال `person`، الخ",
- "LDAP_Domain_Search_Object_Class": "نطاق فئة كائن البحث",
- "LDAP_Domain_Search_Object_Class_Description": "و* objectclass * أن تحديد المستخدمين. على سبيل المثال `organizationalPerson`،` user`، `inetOrgPerson`، الخ",
- "LDAP_Domain_Search_Password": "بحث نطاق كلمة المرور",
- "LDAP_Domain_Search_Password_Description": "كلمة السر للمستخدم البحث المجال.",
- "LDAP_Domain_Search_User": "نطاق البحث العضو",
- "LDAP_Domain_Search_User_Description": "المستخدم LDAP التي تنفذ عمليات البحث المستخدم لمصادقة المستخدمين الآخرين عند تسجيل الدخول. هذا هو عادة حساب خدمة أنشئت خصيصا لالتكامل طرف ثالث. استخدام اسم مؤهل بشكل كامل، مثل `CN = مسؤول، CN = المستخدمين، DC = المثال، DC = com`.",
- "LDAP_Domain_Search_User_ID": "بحث نطاق هوية المستخدم",
- "LDAP_Domain_Search_User_ID_Description": "السمة LDAP أن يحدد المستخدم LDAP الذي يحاول المصادقة. وينبغي أن يكون هذا المجال `sAMAccountName` للمنشآت الأكثر نشاطا دليل، ولكنه قد يكون` uid` عن حلول LDAP الأخرى، مثل ب OpenLDAP. يمكنك استخدام `mail` لتعريف المستخدمين عن طريق البريد الإلكتروني أو أيا كان السمة التي تريد. يمكنك استخدام قيم متعددة مفصولة بفواصل للسماح للمستخدمين تسجيل الدخول باستخدام معرفات متعددة مثل اسم المستخدم أو البريد الإلكتروني.",
+ "LDAP_BaseDN_Description": "اسم المؤهل بالكامل المميز (DN) من الشجرة الفرعية LDAP تريد البحث للمستخدمين والمجموعات. يمكنك إضافة ما تريد. ومع ذلك، يجب أن تحدد كل مجموعة في قاعدة نطاق نفس المستخدمين التي تنتمي إليها. إذا قمت بتحديد مجموعات المستخدمين المحظورة، وفقط للمستخدمين الذين ينتمون لتلك الجماعات أن يكون في نطاق. نوصي تحديد المستوى الخاص بك شجرة دليل LDAP كقاعدة المجال الخاص بك واستخدام فلتر البحث للتحكم في الوصول.",
+ "LDAP_User_Search_Field_Description": "السمة LDAP أن يحدد المستخدم LDAP الذي يحاول المصادقة. وينبغي أن يكون هذا المجال `sAMAccountName` للمنشآت الأكثر نشاطا دليل، ولكنه قد يكون` uid` عن حلول LDAP الأخرى، مثل ب OpenLDAP. يمكنك استخدام `mail` لتعريف المستخدمين عن طريق البريد الإلكتروني أو أيا كان السمة التي تريد. يمكنك استخدام قيم متعددة مفصولة بفواصل للسماح للمستخدمين تسجيل الدخول باستخدام معرفات متعددة مثل اسم المستخدم أو البريد الإلكتروني.",
+ "LDAP_User_Search_Filter_Description": "إذا كان سيتم السماح محددة، فقط للمستخدمين تطابق هذا المرشح لتسجيل الدخول. إذا لم يتم تحديد مرشح، جميع المستخدمين ضمن نطاق قاعدة المجال المحدد سوف تكون قادرة على تسجيل الدخول. على سبيل المثال ل Active Directory `memberOf = CN = ROCKET_CHAT، أوو = العام Groups`. على سبيل المثال لب OpenLDAP (للمد بحث مباراة) `أوو: DN: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "المستخدم LDAP التي تنفذ عمليات البحث المستخدم لمصادقة المستخدمين الآخرين عند تسجيل الدخول. هذا هو عادة حساب خدمة أنشئت خصيصا لالتكامل طرف ثالث. استخدام اسم مؤهل بشكل كامل، مثل `CN = مسؤول، CN = المستخدمين، DC = المثال، DC = com`.",
"LDAP_Enable": "تفعيل",
"LDAP_Enable_Description": "محاولة استخدام LDAP للمصادقة.",
"LDAP_Encryption": "التشفير",
"LDAP_Encryption_Description": "طريقة التشفير المستخدمة لتأمين الاتصالات إلى خادم LDAP. ومن الأمثلة `plain` (بدون تشفير)،` SSL / LDAPS` (مشفرة من البداية)، و`StartTLS` (الترقية إلى الاتصالات المشفرة مرة واحدة متصلة).",
+ "LDAP_Group_Filter_Group_Member_Format": "صيغة عضو المجموعة",
+ "LDAP_Group_Filter_Group_Name": "اسم المجموعة",
+ "LDAP_Group_Filter_Group_Name_Description": "اسم المجموعة التي تنتمي للمستخدم",
"LDAP_Host": "مضيف",
"LDAP_Host_Description": "المضيف LDAP، على سبيل المثال `ldap.example.com` أو` 10.0.0.30`.",
+ "LDAP_Idle_Timeout": "انتهاء مدة عدم النشاط (بالملي ثانية)",
+ "LDAP_Merge_Existing_Users": "دمج المستخدمين الموجودون",
"LDAP_Port": "منفذ",
"LDAP_Port_Description": "ميناء للوصول LDAP. على سبيل المثال: `389` أو` 636` لLDAPS",
"LDAP_Reject_Unauthorized": "رفض غير مصرح بها",
@@ -598,22 +831,22 @@
"LDAP_Sync_User_Data_Description": "حافظ على بيانات المستخدم في تزامن مع الخادم على تسجيل الدخول (على سبيل المثال: الاسم، البريد الإلكتروني).",
"LDAP_Sync_User_Data_FieldMap": "العضو بيانات خريطة الميدان",
"LDAP_Sync_User_Data_FieldMap_Description": "تكوين كيف يتم ملؤها الحقول حساب المستخدم (مثل البريد الإلكتروني) من مستوى قياسي في LDAP (وجدت مرة واحدة). وكمثال على ذلك، `{\" CN \":\" اسم \"،\" البريد الإلكتروني \":\" البريد الإلكتروني \"}` سيختار اسم الشخص البشري للقراءة من سمة CN، وبريدهم الإلكتروني من السمة البريد. وتشمل المجالات المتاحة `name`، و` email`.",
- "LDAP_Sync_Users": "المستخدمين مزامنة",
"LDAP_Test_Connection": "اختبار الاتصال",
"LDAP_Unique_Identifier_Field": "معرف الميدان وفريدة من نوعها",
"LDAP_Unique_Identifier_Field_Description": "التي الحقل سيتم استخدامها لربط المستخدم LDAP والمستخدم Rocket.Chat. يمكنك إبلاغ قيم متعددة مفصولة بفواصل في محاولة للحصول على قيمة من سجل LDAP. القيمة الافتراضية هي `objectGUID يتم، آي بي إم، entryUUID، GUID، dominoUNID، nsuniqueId، uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "استخدام البحث المجال مخصص",
- "LDAP_Use_Custom_Domain_Search_Description": "إرسال الفلتر الخاص للمستخدمين البحث في خادم LDAP.",
"LDAP_Username_Field": "اسم المستخدم الميدان",
"LDAP_Username_Field_Description": "التي المجال سوف تستخدم * اسم المستخدم * للمستخدمين الجدد. اتركه فارغا لاستخدام اسم المستخدم على علم صفحة تسجيل الدخول. يمكنك استخدام العلامات قالب جدا، مثل `#{givenName}.#{sn}`. القيمة الافتراضية هي `sAMAccountName`.",
+ "Least_Amount": "المقدار الأقل",
"Leave_Group_Warning": "هل أنت متأكد من أنك تريد مغادرة المجموعة \"%s\"؟",
"Leave_Private_Warning": "هل أنت متأكد من أنك تريد مغادرة المحادثة مع \"%s\"؟",
"Leave_room": "مغادرة الغرفة",
"Leave_Room_Warning": "هل أنت متأكد من أنك تريد مغادرة الغرفة \"%s\"؟",
+ "Leave_the_current_channel": "مغادرة الغرفة الحالية",
"line": "الأسطر",
"List_of_Channels": "قائمة القنوات",
"List_of_Direct_Messages": "قائمة الرسائل الخاصة",
"Livechat_agents": "وكلاء المحادثات الحية",
+ "Livechat_AllowedDomainsList": "أسماء المجالات المسموحة في الدردشة المباشرة",
"Livechat_Dashboard": "لوحة المحادثات الحية",
"Livechat_enabled": "تفعيل المحادثات الحية",
"Livechat_forward_open_chats": "دردشات مفتوحة إلى الأمام",
@@ -640,6 +873,7 @@
"Login_with": "تسجيل الدخول بـ %s",
"Logout": "تسجيل خروج",
"Logout_Others": "تسجيل الخروج من الأجهزة الأخرى",
+ "mail-messages": "رسلائل البريد",
"Mail_Message_Invalid_emails": "لقد قدمت رسائل البريد الإلكتروني واحدة أو أكثر غير صالحة:٪ ق",
"Mail_Message_Missing_to": "يجب عليك اختيار واحد أو أكثر من المستخدمين أو تقديم واحدة أو أكثر من عناوين البريد الإلكتروني، مفصولة بفواصل.",
"Mail_Message_No_messages_selected_select_all": "لم تقم بتحديد أي رسالة. هل تريد أن تحدد جميع الرسائل الظاهرة؟",
@@ -650,15 +884,24 @@
"Mailer_body_tags": "يجب عليك استخدام[unsubscribe] للارتباط إلغاء الاشتراك. يمكنك استخدام [name]، [fname]، [lname] عن الاسم الكامل للمستخدم، الاسم الأول أو اسم العائلة، على التوالي. يمكنك استخدام [email] للبريد الإلكتروني الخاص بالمستخدم.",
"Mailing": "المراسلات",
"Make_Admin": "جعل مدير",
+ "manage-emoji": "إدارة الرموز التعبيرية",
+ "manage-emoji_description": "التصريح بإدارة الرموز التعبيرية في الخادم",
+ "manage-sounds": "إدارة الأصوات",
+ "manage-sounds_description": "التصريح بإدارة أصوات الخادم",
"Manager_added": "تمت إضافة المدير",
"Manager_removed": "إزالة مدير",
"Managing_assets": "إدارة الأصول",
"Managing_integrations": "إدارة التكامل",
+ "MapView_Enabled": "تفعيل عرض الخريطة",
+ "MapView_Enabled_Description": "يعرض تفعيل عرض الخريطة زر مشاركة الموقع على يسار حقل رسالة الدردشة",
"Mark_as_read": "تعليم كمقروء",
+ "Mark_as_unread": "تعيين كغير مقروء",
"Markdown_Headers": "ماركداون للعناوين",
"Markdown_SupportSchemesForLink": "دعم الماركداون لنوع الروابط",
"Markdown_SupportSchemesForLink_Description": "قائمة مفصولة بفواصل من مخططات سمح",
+ "Max_length_is": "الحد الأقصى للطول هو %s",
"Members_List": "قائمة الأعضاء",
+ "mention-all": "ذكر الجميع",
"Mentions": "تنويهات",
"Mentions_default": "تنويهات (افتراضي)",
"Message": "رسالة",
@@ -672,8 +915,10 @@
"Message_AllowPinning": "السماح بتثبيت الرسائل",
"Message_AllowPinning_Description": "السماح رسائل يتم معلقة على أي من القنوات.",
"Message_AllowStarring": "السماح بتمييز الرسائل",
+ "Message_AllowUnrecognizedSlashCommand": "السماح بأوامر الشرطة المائلة -/- غير المعروفة",
"Message_AlwaysSearchRegExp": "دائما البحث باستخدام التعبير العادي",
"Message_AlwaysSearchRegExp_Description": "نوصي لوضع `TRUE` إذا لم يتم دعم اللغة الخاصة بك على البحث عن نص MongoDB .",
+ "Message_Attachments": "روابط الرسالة",
"Message_AudioRecorderEnabled": "تسجيل أغنية ممكن",
"Message_AudioRecorderEnabledDescription": "يتطلب '/ WAV الصوت \"الملفات إلى أن يكون نوع وسائط المقبولة في إعدادات' ملف تحميل\".",
"Message_BadWordsFilterList": "إضافة كلمات سيئة إلى القائمة السوداء",
@@ -684,6 +929,11 @@
"Message_editing": "تحرير رسالة",
"Message_GroupingPeriod": "تجمع الفترة (بالثواني)",
"Message_GroupingPeriodDescription": "سيتم تجميع الرسائل مع الرسالة السابقة إذا كان كلاهما من نفس المستخدم والوقت المنقضي كان أقل من الوقت مستنير في ثوان.",
+ "Message_HideType_au": "إخفاء رسائل إضافة المستخدمين",
+ "Message_HideType_mute_unmute": "إخفاء رسائل كتم أو إلغاء كتم المستخدمين",
+ "Message_HideType_ru": "إخفاء رسائل حذف المستخدم",
+ "Message_HideType_uj": "إخفاء رسائل انضمام مستخدم",
+ "Message_HideType_ul": "إخفاء رسائل مغادرة مستخدم",
"Message_KeepHistory": "إبقاء محفوظات الرسائل",
"Message_MaxAll": "الحد الأقصى لحجم قناة لجميع رسالة",
"Message_MaxAllowedSize": "الحجم الأقصى المسموح للرسالة",
@@ -693,24 +943,35 @@
"Message_ShowEditedStatus": "عرض حالة الحذف",
"Message_ShowFormattingTips": "اظهار نصائح التنسيق",
"Message_starring": "تمييز الرسالة",
+ "Message_TimeAndDateFormat": "صيغة الوقت والتاريخ",
+ "Message_TimeAndDateFormat_Description": "انظر أيضاً: Moment.js ",
"Message_TimeFormat": "تنسيق الوقت",
"Message_TimeFormat_Description": "انظر أيضا: Moment.js ",
"Message_too_long": "رسالة طويلة جدا",
+ "Message_VideoRecorderEnabled": "تم تفعيل مُسجّل الفيديو",
"Messages": "الرسائل",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "وسوف يتم نشر الرسائل التي يتم إرسالها إلى الواردة WebHook هنا.",
"Meta": "ميتا",
+ "Meta_custom": "وسوم الميتا المُخصصة",
"Meta_fb_app_id": "معرف تطبيق الفيسبوك",
"Meta_google-site-verification": "Google Site Verification",
"Meta_language": "اللغة",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "الروبوتات",
+ "Min_length_is": "الحد الأدنى للطول هو %s",
"minutes": "دقيقة",
+ "Mobile": "الهاتف المتنقل - الموبايل-",
+ "Monday": "الاثنين",
"More_channels": "المزيد من القنوات",
"More_direct_messages": "المزيد من الرسائل الخاصة",
"More_groups": "المزيد من المجموعات الخاصة",
"More_unreads": "المزيد غير مقروءة",
+ "Move_beginning_message": "`%s` الانتقال إلى بداية الرسالة",
+ "Move_end_message": "`%s` الانتقال إلى نهاية الرسالة",
"Msgs": "رسائل",
"multi": "متعدد",
+ "mute-user": "كتم المستخدم",
+ "mute-user_description": "التصريح بكتم المستخدمين الآخرين في نفس القناة",
"Mute_someone_in_room": "إسكات شخص في الغرفة",
"Mute_user": "اسكات المستخدم",
"Muted": "صامتة",
@@ -732,19 +993,27 @@
"New_password": "كلمة سر جديدة",
"New_role": "دور جديد",
"New_Room_Notification": "إشعار جديد في الغرفة",
+ "New_videocall_request": "طلب اتصال عبر الفيديو جديد",
+ "No_available_agents_to_transfer": "لا يوجد أي موظفين ليتم نقلهم",
"No_channel_with_name_%s_was_found": "لا توجد قناة باسم \"%s\" ",
"No_channels_yet": "لست جزء من أي قناة حتى الآن.",
"No_direct_messages_yet": "لم تبدأ أي محادثات حتى الآن.",
"No_Encryption": "لا التشفير",
"No_group_with_name_%s_was_found": "لا توجد مجموعة خاصة باسم \"%s\" ",
"No_groups_yet": "لا يوجد لديك مجموعات خاصة حتى الآن.",
+ "No_integration_found": "لم يتم العثور على أي دمج مطابق للرمز المُدخل",
"No_livechats": "ليس لديك محادثات حية",
"No_mentions_found": "لا يوجد تنويهات",
"No_pinned_messages": "لا توجد رسائل مثبتة",
"No_results_found": "لا توجد نتائج",
+ "No_snippet_messages": "دون مقتطفات",
"No_starred_messages": "لا توجد رسائل مميزة",
+ "No_such_command": "لا يوجد أي أمر كهذا: `/__command__`",
"No_user_with_username_%s_was_found": "لا يوجد مستخدم باسم \"%s\" ",
+ "Nobody_available": "لا يوجد أي شخص متاح",
"Node_version": "نسخة العقدة",
+ "None": "لا يوجد",
+ "Normal": "عادي",
"Not_authorized": "غير مصرح",
"Not_Available": "غير متاح",
"Not_found_or_not_allowed": "غير موجود أو غير مسموح",
@@ -752,28 +1021,44 @@
"Nothing_found": "لا يوجد شيء",
"Notification_Duration": "مدة التنبيهات",
"Notifications": "الإشعارات",
+ "Notify_active_in_this_room": "إبلاغ المستخدمين النشطين في هذه الغرفة",
"Notify_all_in_this_room": "إخطار جميع من في هذه الغرفة",
"Num_Agents": "وكلاء",
"Number_of_messages": "عدد الرسائل",
"OAuth_Application": "أوث التطبيق",
"OAuth_Applications": "تطبيقات أوث",
"Objects": "أشياء",
+ "Off": "غير مُفعّل",
"Off_the_record_conversation": "خارج على تسجيل المحادثة",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "المحادثة السرية غير متوفرة لمتصفحك أو جهازك",
+ "Office_Hours": "ساعات دوام المكتب",
+ "Office_hours_enabled": "تم تفعيل ساعات الدوام في المكتب",
+ "Office_hours_updated": "تم تحديث ساعات الدوام في المكتب",
"Offline": "غير متصل",
"Offline_DM_Email": "لقد تم بعث برسالة مباشرة من قبل __user__",
"Offline_form": "شكل متواجد حاليا",
"Offline_form_unavailable_message": "شكل متواجد حاليا رسالة غير متوفرة",
+ "Offline_Link_Message": "الذهاب إلى الرسالة",
"Offline_Mention_Email": "تم التنويه باسمك بواسطة __user__ في #__room__",
"Offline_message": "رسالة متواجد حاليا",
"Offline_success_message": "رسالة نجاح متواجد حاليا",
"Offline_unavailable": "غير متوفر حاليا",
+ "On": "مُفعّل",
"Online": "متواجد",
+ "Only_On_Desktop": "وضع المكتب -إرسال من خلال النقر على إدخال على سطح المكتب-",
"Only_you_can_see_this_message": "يمكنك أنت فقط رؤية هذه الرسالة",
"Oops!": "عذرا",
"Open": "فتح",
+ "Open_channel_user_search": "`%s`- فتح قناة/ بحث المستخدم",
+ "Open_days_of_the_week": "أيام الدوام",
+ "Open_Livechats": "فتح الدردشة المباشرة",
+ "Open_your_authentication_app_and_enter_the_code": "شغّل تطبيق المصادقة وادخل الكود. تستطيع أيضاً استخدام أحد النسخ الاحتياطية للأكواد",
"Opened": "افتتح",
+ "Opened_in_a_new_window": "مفتوح في نافذة جديدة",
+ "Opens_a_channel_group_or_direct_message": "فتح قناة، أو مجموعة أو رسالة مباشرة",
"optional": "اختياري",
+ "or": "أو",
+ "Or_talk_as_anonymous": "تحدث كشخص مجهول",
"Order": "طلب",
"OS_Arch": "بنية النظام",
"OS_Cpus": "عدد أنوية النظام",
@@ -787,7 +1072,10 @@
"others": "آخرون",
"OTR": "محادثة سرية",
"OTR_is_only_available_when_both_users_are_online": "المحادثة السرية ممكنة فقط في حال تواجد كلا الطرفين",
+ "Outgoing_WebHook_Description": "استخراج البيانات من روكيت-تشات فعلاً",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL تجاوز إلى التي يتم تحميل الملفات. يعطى هذا الرابط تستخدم أيضا لتحميل ما لم كندي",
+ "Page_title": "عنوان الصفحة",
+ "Page_URL": "رابط الصفحة",
"Password": "كلمة السر",
"Password_Change_Disabled": "مدير الموقع منع تغيير كلمة السر",
"Password_changed_successfully": "تم تغيير كلمة السر بنجاح",
@@ -796,6 +1084,8 @@
"People": "الناس",
"Permalink": "الرابط الثابت",
"Permissions": "التصريحات",
+ "pin-message": "تثبيت الرسالة",
+ "pin-message_description": "التصريح بتثبيت الرسالة في قناة",
"Pin_Message": "تثبيث الرسالة",
"Pinned_a_message": "دبس رسالة:",
"Pinned_Messages": "رسائل مثبتة",
@@ -806,6 +1096,7 @@
"Please_add_a_comment": "الرجاء إضافة تعليق",
"Please_add_a_comment_to_close_the_room": "يرجى إضافة تعليق لإغلاق الغرفة",
"Please_answer_survey": "يرجى ان نتوقف لحظة للرد على مسح سريع حول هذه الدردشة",
+ "please_enter_valid_domain": "الرجاء إدخال اسم مجال صالح",
"Please_enter_value_for_url": "الرجاء إدخال قيمة للرابط من صورتك.",
"Please_enter_your_new_password_below": "الرجاء إدخال كلمة المرور الجديدة أدناه:",
"Please_enter_your_password": "الرجاء إعادة إدخال كلمة المرور",
@@ -813,6 +1104,7 @@
"Please_fill_a_name": "الرجاء تعبئة اسم",
"Please_fill_a_username": "يرجى ملء اسم المستخدم",
"Please_fill_name_and_email": "الرجاء تعبئة اسم والبريد الإلكتروني",
+ "Please_select_an_user": "الرجاء اختيار مستخدم",
"Please_select_enabled_yes_or_no": "الرجاء تحديد خيار لتمكين",
"Please_wait": "يرجى الانتظار",
"Please_wait_activation": "يرجى الانتظار، قد يستغرق بعض الوقت.",
@@ -820,11 +1112,15 @@
"Please_wait_while_your_account_is_being_deleted": "الرجاء اﻹنتظار جاري حذف حسابك....",
"Please_wait_while_your_profile_is_being_saved": "الرجاء اﻹنتظار ... جاري حفظ ملفك الشخصي...",
"Port": "ميناء",
+ "post-readonly": "نشر في وضع القراءة فقط",
+ "post-readonly_description": "التصريح بنشر رسالة في قناة في وضع القراءة فقط",
"Post_as": "منصب",
"Post_to_Channel": "أضف إلى القناة",
"Post_to_s_as_s": "آخر إلى %s ك %s ",
"Preferences": "التفضيلات",
"Preferences_saved": "تم حفظ التفضيلات",
+ "preview-c-room": "عرض القناة العامة",
+ "preview-c-room_description": "التصريح بعرض محتوى القناة العامة قبل الانضمام",
"Privacy": "الخصوصية",
"Private": "خاص",
"Private_Group": "مجموعة خاصة",
@@ -852,57 +1148,90 @@
"Push_test_push": "تجربة",
"Query": "سؤال",
"Query_description": "شروط إضافية لتحديد أي من المستخدمين لإرسال رسالة إلكترونية إلى. تتم إزالة المستخدمين غير المشتركين تلقائيا من الاستعلام. يجب أن يكون JSON صالح. على سبيل المثال: \"{\" createdAt \": {\" $ GT \": {\" تاريخ $ \":\" 2015-01-01T00: 00: 00.000Z \"}}}\"",
+ "Queue": "صف الانتظار",
"quote": "اقتباس",
"Quote": "اقتباس",
"Random": "عشوائية",
+ "React_when_read_only": "السماح بالتفاعل",
+ "React_when_read_only_changed_successfully": "السماح بالتفاعل عندما يتم تغيير إلى وضع القراءة فقط بنجاح",
"Reacted_with": "تفاعل بـ",
"Reactions": "ردود الفعل",
+ "Read_only": "قراءة فقط",
+ "Read_only_changed_successfully": "تم تغيير إلى وضع القراءة فقط بنجاح",
+ "Read_only_channel": "قناة في وضع القراءة فقط",
+ "Read_only_group": "مجموعة في القراءة فقط",
"Record": "سجل",
"Redirect_URI": "إعادة توجيه URI",
"Refresh_keys": "تحديث المفاتيح",
+ "Refresh_oauth_services": "تحديث خدمات OAuth",
"Refresh_your_page_after_install_to_enable_screen_sharing": "تحديث الصفحة بعد تثبيت لتمكين مشاركة الشاشة",
+ "Regenerate_codes": "إعادة توليد الأكواد",
"Register": "تسجيل حساب جديد",
+ "Registration": "التسجيل",
"Registration_Succeeded": "تم التسجيل بنجاح",
+ "Registration_via_Admin": "التسجيل عبر المدير",
+ "Regular_Expressions": "التعابير الاعتيادية",
"Release": "إطلاق سراح",
+ "Reload": "إعادة تحميل",
"Remove": "إزالة",
+ "remove-user": "حذف المستخدم",
+ "remove-user_description": "التصريح بحذف مستخدم من غرفة دردشة",
"Remove_Admin": "إزالة مدير",
"Remove_as_moderator": "إزالة كمشرف",
"Remove_as_owner": "إزالة كمالك",
"Remove_custom_oauth": "إزالة أوث مخصصة",
"Remove_from_room": "إزالة من الغرفة",
+ "Remove_last_admin": "حذف المدير الأخير",
"Remove_someone_from_room": "إزالة شخص من الغرفة",
"Removed": "تمت اﻹزالة",
+ "Reply": "رد",
"Report_Abuse": "التبليغ عن إساءة استخدام",
"Report_exclamation_mark": "تقرير!",
"Report_sent": "تم اسال القرير",
"Report_this_message_question_mark": "أبلغ عن هذه الرسالة؟",
+ "Reporting": "تقديم التقرير",
"Require_password_change": "تتطلب تغيير كلمة المرور",
"Resend_verification_email": "اعد إرسال بريد التحقق",
"Reset": "إعادة التعيين",
"Reset_password": "إعادة تعيين كلمة السر",
+ "Reset_section_settings": "إعادة ضبط إعدادات القسم",
"Restart": "إعادة التشغيل",
"Restart_the_server": "إعادة تشغيل السيرفر",
+ "Retry_Count": "تعداد إعادة المحاولة",
"Role": "دور",
"Role_Editing": "دور التحرير",
"Role_removed": "دور إزالة",
"Room": "غرفة",
+ "Room_announcement_changed_successfully": "تم تغيير إعلان الغرفة بنجاح",
"Room_archivation_state": "الحالة",
"Room_archivation_state_false": "نشطة",
"Room_archivation_state_true": "مؤرشفة",
"Room_archived": "غرفة مؤرشفة",
"room_changed_privacy": "تم تغيير نوع الغرفة إلى: __room_type__ بواسطة __user_by__ ",
"room_changed_topic": "تم تغيير موضوع الغرفة إلى: __room_topic__ بواسطة __user_by__ ",
+ "Room_description_changed_successfully": "تم تغيير وصف الغرفة بنجاح",
+ "Room_has_been_archived": "تم أرشفة الغرفة",
"Room_has_been_deleted": "تم حذف الغرفة",
+ "Room_has_been_unarchived": "تم إلغاء أرشفة الغرفة",
"Room_Info": "معلومات الغرفة",
+ "room_is_blocked": "تم حظر هذه الغرفة",
+ "room_is_read_only": "يُمكن قراءة دردشة هذه الغرفة فقط",
+ "room_name": "اسم الغرفة",
"Room_name_changed": "تم تغيير اسم الغرفة إلى: __room_name__ بواسطة __user_by__ ",
"Room_name_changed_successfully": "تم تغيير اسم الغرفة بنجاح",
"Room_not_found": "لم يتم العثور على الغرفة",
+ "Room_password_changed_successfully": "تم تغيير كلمة مرور الغرفة بنجاح",
"Room_topic_changed_successfully": "تغيير موضوع الغرفة بنجاح",
"Room_type_changed_successfully": "تم تغيير نوع الغرفة بنجاح",
+ "Room_type_of_default_rooms_cant_be_changed": "هذه غرفة افتراضية. لا يُمكن تغيير المكتوب. الرجاء الاتصال بالمدير!",
"Room_unarchived": "غرفة نشطة",
"Room_uploaded_file_list": "قائمة الملفات",
"Room_uploaded_file_list_empty": "لا يوجد ملفات.",
"Rooms": "الغرف",
+ "run-import": "تشغيل الاستيراد",
+ "run-import_description": "التصريح لتشغيل المستورد",
+ "run-migration": "تشغيل الترحيل",
+ "run-migration_description": "التصريح لتشغيل الترحيل",
"Running_Instances": "تشغيل مثيلات",
"S_new_messages_since_s": "% رسالة جديدة منذ %",
"SAML": "SAML",
@@ -910,8 +1239,13 @@
"SAML_Custom_Entry_point": "عرف نقطة إدخال",
"SAML_Custom_Generate_Username": "توليد اسم المستخدم",
"SAML_Custom_Issuer": "المصدر مخصص",
+ "SAML_Custom_Private_Key": "محتويات المفتاح الخاص",
"SAML_Custom_Provider": "مزود مخصص",
+ "SAML_Custom_Public_Cert": "محتويات الشهادة العامة",
+ "Saturday": "السبت",
"Save": "حفظ",
+ "save-others-livechat-room-info": "حفظ معلومات غرف الدردشة المباشرة الأخرى",
+ "save-others-livechat-room-info_description": "التصريح بحفظ المعلومات من قنوات الدردشة الأخرى",
"Save_changes": "لحفظ التغييرات",
"Save_Mobile_Bandwidth": "توفير استهلاك الانترنت",
"Save_to_enable_this_action": "حفظ لتمكين هذا العمل",
@@ -926,7 +1260,9 @@
"Search_Private_Groups": "البحث في المجموعات الخاصة",
"seconds": "ثواني",
"Secret_token": "رمز سري",
+ "Security": "الحماية",
"Select_a_department": "حدد القسم",
+ "Select_a_user": "اختيار مستخدم",
"Select_an_avatar": "اختر صورة",
"Select_file": "اختر ملفا",
"Select_service_to_login": "اختر خدمة للدخول إليها لتحميل صورتك أو قم بالتحميل مباشرة من جهازك",
@@ -950,20 +1286,37 @@
"Send_welcome_email": "ارسال رسالة ترحيب",
"Send_your_JSON_payloads_to_this_URL": "إرسال حمولات JSON لهذا الرابط.",
"Sending": "جار الإرسال...",
+ "Served_By": "مُشغّل بوساطة ",
"Service": "خدمة",
+ "Service_account_key": "مفتاح حساب الخدمة",
+ "set-moderator": "تعيين المشرف",
+ "set-moderator_description": "التصريح بتعيين المستخدمين الآخرين كمشرف القناة",
+ "set-owner": "تعيين المسؤول",
+ "set-owner_description": "التصريح بتعيين المستخدمين الآخرين كمسؤول القناة",
+ "set-react-when-readonly": "وضع تفاعل في حالة القراءة فقط",
+ "set-react-when-readonly_description": "التصريح بوضع قابلية التفاعل مع الرسائل في قناة في وضع القراءة فقط",
+ "set-readonly": "وضع للقراءة فقط",
+ "set-readonly_description": "التصريح بوضع القناة في وضع القراءة فقط",
"Set_as_moderator": "إضافة كمشرف",
"Set_as_owner": "إضافة إلى مالك",
"Settings": "اﻹعدادات",
"Settings_updated": "تم تحديث الإعدادات",
+ "Share_Location_Title": "مشاركة الموقع؟",
+ "Shared_Location": "الموقع المُشارك",
"Should_be_a_URL_of_an_image": "يجب أن يكون عنوان URL للصورة.",
"Should_exists_a_user_with_this_username": "يجب على المستخدم موجودة بالفعل.",
"Show_all": "عرض الكل",
"Show_more": "عرض المزيد",
+ "show_offline_users": "إظهار المستخدمين الموجودون حالياً -أونلاين-",
+ "Show_on_registration_page": "إظهار على صفحة التسجيل",
"Show_only_online": "عرض المتصلين فقط",
"Show_preregistration_form": "عرض استمارة التسجيل المسبق",
+ "Show_queue_list_to_all_agents": "إظهار قائمة صف الانتظار لكل الموظفين",
+ "Show_the_keyboard_shortcut_list": "عرض قائمة اختصارات لوحة المفاتيح",
"Showing_archived_results": "عرض %s نتائج مؤرشفة
",
- "Showing_online_users": "معروض __total_showing__ من __total__ عضو",
+ "Showing_online_users": " معروض: __total_showing__, على الانترنت: __online__, عضو: __total__",
"Showing_results": "معروض %s نتائج
",
+ "Sign_in_to_start_talking": "قم بتسجيل الدخول للبدء بالدردشة",
"since_creation": "منذ %s",
"Site_Name": "اسم الموقع",
"Site_Url": "رابط الموقع",
@@ -976,6 +1329,9 @@
"Slash_TableUnflip_Description": "يعرض ┬─┬ ノ (゜ - ゜ ノ)",
"Slash_Topic_Description": "ضبط الموضوع",
"Slash_Topic_Params": "رسالة الموضوع",
+ "Smarsh_Email": "البريد الإلكتروني لحساب سمارش",
+ "Smarsh_Enabled": "تم تفعيل سمارش",
+ "Smarsh_MissingEmail_Email": "البريد الإلكتروني غير موجود",
"Smileys_and_People": "ابتسامات و أشخاص",
"SMS_Enabled": "تمكين الرسائل القصيرة SMS",
"SMTP": "SMTP",
@@ -984,7 +1340,12 @@
"SMTP_Port": "منفذ SMTP",
"SMTP_Test_Button": "إعدادات اختبار SMTP",
"SMTP_Username": "اسم المستخدم SMTP",
+ "snippet-message": "مقتطف الرسالة",
+ "snippet-message_description": "التصريح بإنشاء مقتطف رسالة",
+ "Snippet_Added": "تم الإنشاء في %s",
+ "Snippet_Messages": "مقتطفات الرسائل",
"Sound": "الصوت",
+ "Sound_File_mp3": "ملف صوتي -mp3-",
"SSL": "SSL",
"Star_Message": "ميز الرسالة",
"Starred_Messages": "رسائل مميزة",
@@ -1008,22 +1369,31 @@
"Stats_Online_Users": "المستخدمون المتصلون",
"Stats_Total_Channels": "مجموع القنوات",
"Stats_Total_Direct_Messages": "إجمالي عدد غرف الرسالة المباشرة",
+ "Stats_Total_Livechat_Rooms": "غرف الدردشة المباشرة الكلية",
"Stats_Total_Messages": "مجموع الرسائل",
+ "Stats_Total_Messages_Channel": "عدد الرسائل الكلي في القنوات",
+ "Stats_Total_Messages_Direct": "عدد الرسائل الكلية في الرسائل المباشرة",
+ "Stats_Total_Messages_PrivateGroup": "عدد الرسائل الكلي في المجموعات الخاصة",
"Stats_Total_Private_Groups": "عدد المجموعات الخاصة",
"Stats_Total_Rooms": "عدد الغرف",
"Stats_Total_Users": "عدد الأعضاء",
+ "Status": "الحالة",
"Stop_Recording": "إيقاف التسجيل",
"strike": "شطب",
"Subject": "الموضوع",
"Submit": "تقديم",
"Success": "نجاح",
"Success_message": "رسالة نجاح",
+ "Sunday": "الأحد",
"Survey": "الدراسة الاستقصائية",
"Survey_instructions": "معدل كل سؤال وفقا لالارتياح الخاص بك، 1 وهذا يعني أنك غير راضي تماما و 5 يعني كنت راضيا تماما.",
"Symbols": "رموز",
"Sync_success": "نجاح المزامنة",
"Sync_Users": "المستخدمين مزامنة",
+ "System_messages": "رسائل النظام",
"Tag": "بطاقة",
+ "Take_it": "قم بأخذه!",
+ "TargetRoom": "الغرفة المُستخدمة",
"Test_Connection": "اختبار اﻹتصال",
"Test_Desktop_Notifications": "تجربيب تنبيهات سطح المكتب",
"Thank_you_exclamation_mark": "شكرا!",
@@ -1039,30 +1409,44 @@
"The_user_will_be_removed_from_s": "سيتم إزالة المستخدم من %s",
"The_user_wont_be_able_to_type_in_s": "المستخدم لن يكون قادرا على كتابة في٪ الصورة",
"Theme": "موضوع",
+ "theme-color-component-color": "لون التركيبة",
"theme-color-content-background-color": "المحتوى لون الخلفية",
+ "theme-color-custom-scrollbar-color": "مخصص شريط التمرير اللون",
+ "theme-color-error-color": "لون الخطأ",
+ "theme-color-info-font-color": "معلومات لون الخط",
+ "theme-color-link-font-color": "رابط لون الخط",
+ "theme-color-pending-color": "لون الانتظار",
+ "theme-color-primary-action-color": "لون الإجراء الرئيسي",
"theme-color-primary-background-color": "الابتدائي لون الخلفية",
"theme-color-primary-font-color": "الابتدائية لون الخط",
+ "theme-color-secondary-action-color": "لون الإجراء الثانوي",
"theme-color-secondary-background-color": "الثانوية لون الخلفية",
"theme-color-secondary-font-color": "الثانوية لون الخط",
- "theme-color-tertiary-background-color": "التعليم العالي لون الخلفية",
- "theme-color-tertiary-font-color": "التعليم العالي لون الخط",
- "theme-color-link-font-color": "رابط لون الخط",
- "theme-color-info-font-color": "معلومات لون الخط",
- "theme-color-custom-scrollbar-color": "مخصص شريط التمرير اللون",
+ "theme-color-selection-color": "لون الاختيار",
"theme-color-status-away": "لون حالة بعيد",
"theme-color-status-busy": "لون حالة مشغول",
"theme-color-status-offline": "حاليا وضع اللون",
"theme-color-status-online": "الحالة عبر الإنترنت اللون",
+ "theme-color-success-color": "لون النجاح",
+ "theme-color-tertiary-background-color": "التعليم العالي لون الخلفية",
+ "theme-color-tertiary-font-color": "التعليم العالي لون الخط",
+ "theme-color-transparent-dark": "شفاف قاتم",
+ "theme-color-transparent-darker": "شفاف أكثر قتماً",
+ "theme-color-transparent-light": "شفاف فاتح",
+ "theme-color-transparent-lighter": "شفاف أفتح",
+ "theme-color-transparent-lightest": "شفاف الأكثر فتحاً",
"theme-color-unread-notification-color": "غير مقروء الإخطارات اللون",
"theme-custom-css": "لغة تنسيق ويب حسب الطلب",
"There_are_no_agents_added_to_this_department_yet": "لا يوجد وكلاء مضافون لهذا القسم",
"There_are_no_integrations": "لا توجد التكامل",
"There_are_no_users_in_this_role": "هناك مستخدمين في هذا الدور.",
+ "This_conversation_is_already_closed": "تم إغلاق الدردشة للتو",
"This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "وقد تم بالفعل استخدام هذا البريد الإلكتروني ولم يتم التحقق منها. الرجاء قم بتغيير كلمة المرور الخاصة بك.",
"This_is_a_desktop_notification": "مثال على تنبيهات سطح المكتب",
"This_is_a_push_test_messsage": "هذا هو بإرسال رسالة اختبار الضغط",
"This_room_has_been_archived_by__username_": "تم أرشفة هذه الغرفة التي __username__",
"This_room_has_been_unarchived_by__username_": "تم إلغاء أرشفة هذه الغرفة التي __username__",
+ "Thursday": "الخميس",
"Time_in_seconds": "الوقت بالثواني",
"Title": "العنوان",
"Title_bar_color": "شريط العنوان اللون",
@@ -1072,11 +1456,16 @@
"to_see_more_details_on_how_to_integrate": "لمعرفة المزيد من التفاصيل حول كيفية دمج.",
"To_users": "إلى",
"Topic": "الموضوع",
+ "Transcript_Enabled": "سؤال المستخدم إذا أراد تحويل الدردشة لنص كتابي قبل الإغلاق",
+ "Translated": "تمت الترجمة",
+ "Translations": "الترجمات",
"Travel_and_Places": "سفر و أماكن",
"Trigger_removed": "الزناد إزالة",
"Trigger_Words": "الكلمات الزناد",
"Triggers": "محفزات",
"True": "نعم",
+ "Tuesday": "الثلاثاء",
+ "Two-factor_authentication_is_currently_disabled": "المصادقة بخطوتين غير مُفعّل حالياً",
"Type": "النوع",
"Type_your_email": "اكتب بريدك الالكتروني",
"Type_your_message": "اكتب رسالتك",
@@ -1084,25 +1473,37 @@
"Type_your_new_password": "اكتب كلمة المرور الجديدة",
"UI_DisplayRoles": "أدوار العرض",
"UI_Merge_Channels_Groups": "دمج المجموعات الخاصة مع قنوات",
+ "UI_Use_Name_Avatar": "استخدم أول حرفين من الاسم الكامل لتوليد الصورة الرمزية",
+ "UI_Use_Real_Name": "استخدم اسمك الحقيقي",
"Unarchive": "إزالة من الأرشيف",
+ "unarchive-room": "إلغاء أرشفة الغرفة",
+ "Unblock_User": "إلغاء حظر المستخدم",
"Unmute_someone_in_room": "إلغاء إسكات شخص في هذه الغرفة",
"Unmute_user": "إلغاء اسكات المستخدم",
"Unnamed": "غير مسمى",
"Unpin_Message": "إلغاء تثبيث الرسالة",
+ "Unread_Count": "عدد غير المقروء",
+ "Unread_Messages": "رسائل غير مقروءة",
"Unread_Rooms": "الغرف غير مقروءة",
"Unread_Rooms_Mode": "وضع الغرف الغير مقروءة",
"Unstar_Message": "إزالة التمييز",
+ "Updated_at": "تم التحديث في ",
+ "Upload_file_description": "وصف الملف",
+ "Upload_file_name": "اسم الملف",
"Upload_file_question": "تحميل الملف؟",
"Uploading_file": "تحميل الملف ...",
"Uptime": "الجهوزية",
"URL": "URL",
+ "URL_room_prefix": "بادئة رابط الغرفة",
"Use_account_preference": "استخدم تفضيلات الحساب",
"Use_Emojis": "استخدم الرموز التعبيرية (ايموجي)",
+ "Use_Global_Settings": "استخدام الإعدادات العالمية",
"Use_initials_avatar": "استخدم الأحرف الأولى من اسم المستخدم",
"Use_service_avatar": "استخدام %s الرمزية",
"Use_this_username": "استخدم هذا الاسم",
"Use_uploaded_avatar": "استخدم الصورة المحملة",
"Use_url_for_avatar": "استخدم رابط للصورة الرمزية",
+ "Use_User_Preferences_or_Global_Settings": "استخدام تفضيلات المستخدم أو الإعدادات العالمية ",
"User__username__is_now_a_moderator_of__room_name_": "__username__ المستخدم الآن مشرفة من __room_name__",
"User__username__is_now_a_owner_of__room_name_": "__username__ المستخدم هو الآن صاحب __room_name__",
"User__username__removed_from__room_name__moderators": "__username__ المستخدم إزالتها من المشرفين __room_name__",
@@ -1117,8 +1518,11 @@
"User_has_been_muted_in_s": "لم يصدر المستخدم في٪ الصورة",
"User_has_been_removed_from_s": "تمت إزالة العضو من %s",
"User_Info": "معلومات المستخدم",
+ "User_Interface": "واجهة المستخدم",
+ "User_is_blocked": "تم حظر المستخدم",
"User_is_no_longer_an_admin": "المستخدم لم يعد مديرا",
"User_is_now_an_admin": "المستخدم الآن مدير",
+ "User_is_unblocked": "تم إلغاء حظر المستخدم",
"User_joined_channel": "انضم للقناة.",
"User_joined_channel_female": "انضمت للقناة",
"User_joined_channel_male": "انضم للقناة.",
@@ -1127,6 +1531,7 @@
"User_left_male": "غادر القناة.",
"User_logged_out": "المستخدم سجل الخروج",
"User_management": "إدارةالمستخدم",
+ "User_muted": "تم كتم المستخدم",
"User_muted_by": "تم اسكات __user_muted__ بواسطة __user_by__ .",
"User_not_found": "لم يتم العثور على المستخدم",
"User_not_found_or_incorrect_password": "لم يتم العثور على المستخدم أو كلمة المرور غير صحيحة",
@@ -1151,14 +1556,48 @@
"Username_title": "تسجيل اسم المستخدم",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ يريد أن يبدأ محادثة سرية. هل توافق؟",
"Users": "المستخدمين",
+ "Users_added": "تم إضافة المستخدمين",
"Users_in_role": "المستخدمين في دور",
"UTF8_Names_Slugify": "UTF8 أسماء Slugify",
"UTF8_Names_Validation": "UTF8 أسماء التحقق",
"UTF8_Names_Validation_Description": "لا تسمح باستخدام رموز خاصة و مسافات. يمكنك استخدام العلامات التالية - _ . لكن لا تسمح بهن في نهاية الاسم.",
+ "Validate_email_address": "التحقق من صحة البريد الإلكتروني",
+ "Verification": "التحقق",
+ "Verification_Email": "انقر هنا لتأكيد حسابك.",
"Verification_email_sent": "تم ارسال رسالة التحقق",
+ "Verification_Email_Subject": "Site_Name] - تأكيد حسابك",
"Verified": "التحقق",
+ "Verify": "التحقق",
"Version": "الإصدار",
"Video_Chat_Window": "دردشة الفيديو",
+ "Video_Conference": "مؤتمر عبر الفيديو",
+ "Videocall_declined": "تم إلغاء اتصال الفيديو",
+ "Videocall_enabled": "تم تفعيل الاتصال عبر الفيديو",
+ "view-c-room": "عرض القناة العامة",
+ "view-c-room_description": "التصريح بعرض القناة العامة",
+ "view-d-room": "عرض الرسائل المباشرة",
+ "view-d-room_description": "التصريح بعرض الرسائل المباشرة",
+ "view-full-other-user-info": "عرض كل معلومات المستخدم",
+ "view-history": "عرض السجل",
+ "view-history_description": "التصريح لعرض سجل القناة",
+ "view-join-code": "عرض كود الانضمام",
+ "view-join-code_description": "التصريح بعرض كود الانضمام للقناة",
+ "view-joined-room": "عرض الغرفة التي تم الانضمام إليها",
+ "view-joined-room_description": "التصريح بعرض القنوات التي تم الانضمام إليها",
+ "view-l-room": "عرض غرف الدردشة المباشرة",
+ "view-l-room_description": "التصريح بعرض كل قنوات الدردشة المباشرة",
+ "view-livechat-manager": "عرض مدير الدردشة المباشرة",
+ "view-livechat-rooms_description": "التصريح بعرض قنوات الدردشة المباشرة الأخرى",
+ "view-logs": "عرض السجلات",
+ "view-logs_description": "التصريخ بعرض سجلات الخادم",
+ "view-other-user-channels": "عرض قنوات المستخدمين الآخرين",
+ "view-other-user-channels_description": "التصريح بعرض قنوات المستخدمين الآخرين",
+ "view-p-room": "عرض الغرفة الخاصة",
+ "view-privileged-setting": "عرض إعدادات الامتيازات",
+ "view-privileged-setting_description": "التصريح بعرض الإعدادات",
+ "view-room-administration": "عرض إدارة الغرفة",
+ "view-statistics": "عرض الإحصائيات",
+ "view-user-administration": "عرض المستخدم المدير",
"View_All": "مشاهدة الكل",
"View_Logs": "عرض سجلات",
"View_mode": "اسلوب العرض",
@@ -1172,6 +1611,7 @@
"Visitor_page_URL": "URL صفحة الزوار",
"Visitor_time_on_site": "الساعة الزوار في الموقع",
"Wait_activation_warning": "يجب تفعيل حسابك من قبل المدير قبل أن تتمكن من الولوج",
+ "Warnings": "التحذيرات",
"We_are_offline_Sorry_for_the_inconvenience": "نحن حاليا. آسف للإزعاج.",
"We_have_sent_password_email": "لقد قمنا بإرسال رسالة بريد إلكتروني مع إرشادات إعادة تعيين كلمة السر. إذا لم يصلك البريد الإلكتروني قريبا، يرجى العودة والمحاولة مرة أخرى.",
"We_have_sent_registration_email": "لقد قمنا بإرسال رسالة بريد إلكتروني لتأكيد تسجيلك. إذا لم يصلك البريد الإلكتروني قريبا، يرجى العودة والمحاولة مرة أخرى.",
@@ -1182,17 +1622,21 @@
"WebRTC_Enable_Private": "تمكين للقنوات الخاصة",
"WebRTC_Servers": "خوادم أذهل / TURN",
"WebRTC_Servers_Description": "قائمة الخوادم أذهل وTURN مفصولة بفواصل. ويسمح المستخدم، كلمة المرور و ميناء في شكل `اسم المستخدم: كلمة المرور @ الصاعقة: المضيف: port` أو` اسم المستخدم: كلمة المرور @ بدوره: المضيف: port`.",
+ "Wednesday": "الأربعاء",
"Welcome": "مرحبا بك يا %s .",
"Welcome_to_the": "أهلا بك في",
"Why_do_you_want_to_report_question_mark": "لماذا تريد الإبلاغ عن؟",
"will_be_able_to": "سوف يكون قادر على",
+ "Would_you_like_to_return_the_inquiry": "هل ترغب بإعادة الطلب؟",
"Yes": "نعم",
+ "Yes_archive_it": "نعم، قم بأرشفته!",
"Yes_clear_all": "نعم، حذف الكل!",
"Yes_delete_it": "نعم، أحذف!",
"Yes_hide_it": "نعم، إخفاء!",
"Yes_leave_it": "نعم، مغادرة!",
"Yes_mute_user": "نعم، المستعمل أخرس!",
"Yes_remove_user": "نعم، إزالة المستخدم!",
+ "Yes_unarchive_it": "نعم! قم بإلغاء أرشفته!",
"You": "أنت",
"you_are_in_preview_mode_of": "انت في وضع المعاينة لقناة # __room_name__ ",
"You_are_logged_in_as": "لقد تم تسجيل دخولك كما",
@@ -1203,8 +1647,10 @@
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "يمكنك استخدام webhooks إلى الاندماج بسهولة LIVECHAT مع إدارة علاقات العملاء الخاص بك.",
"You_cant_leave_a_livechat_room_Please_use_the_close_button": "لا يمكنك ترك غرفة LIVECHAT. يرجى استخدام زر الإغلاق.",
"You_have_been_muted": "لقد تم اسكاتك ولا يمكنك التحدث في هذه الغرفة",
+ "You_have_n_codes_remaining": "تبقى لديك __number__ codes ",
"You_have_not_verified_your_email": "لم يتم التحقق من بريدك الإلكتروني.",
"You_have_successfully_unsubscribed": "لقد تم إلغاء اشتراكك بنجاح من القائمة البريدية لدينا.",
+ "You_must_join_to_view_messages_in_this_channel": "عليك الانضمام لكي تستطيع عرض الرسائل في هذه القناة",
"You_need_confirm_email": "تحتاج إلى تأكيد بريدك الإلكتروني لتسجيل الدخول!",
"You_need_install_an_extension_to_allow_screen_sharing": "تحتاج إلى تركيب إضافة للسماح بمشاركة الشاشة",
"You_need_to_change_your_password": "يجب عليك تغيير كلمة المرور",
@@ -1221,6 +1667,8 @@
"Your_entry_has_been_deleted": "لقد تم حذف رسالتك",
"Your_file_has_been_deleted": "لقد تم حذف الملف.",
"Your_mail_was_sent_to_s": "وأرسل البريد إلى %s",
+ "your_message": "رسالتك",
+ "your_message_optional": "رسالتك (اختياري)",
"Your_password_is_wrong": "كلمة السر خاطئة",
"Your_push_was_sent_to_s_devices": "وقد أرسلت دفعك إلى أجهزة٪ الصورة"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/az.i18n.json b/packages/rocketchat-i18n/i18n/az.i18n.json
new file mode 100644
index 0000000000000..7cb0319c61309
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/az.i18n.json
@@ -0,0 +1,3 @@
+{
+ "#channel": "#kanal"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/bg.i18n.json b/packages/rocketchat-i18n/i18n/bg.i18n.json
index fbedfc1e680bc..893252288ea96 100644
--- a/packages/rocketchat-i18n/i18n/bg.i18n.json
+++ b/packages/rocketchat-i18n/i18n/bg.i18n.json
@@ -1,6 +1,8 @@
{
"#channel": "#канал",
"0_Errors_Only": "0 - Само Грешки",
+ "1_Errors_and_Information": "1 - Грешки и Информация",
+ "2_Erros_Information_and_Debug": "2 - Грешки, Информация и Дебъг",
"403": "Забранен",
"@username": "@потребителско име",
"@username_message": "@потребителско име",
@@ -23,6 +25,7 @@
"Accounts_OAuth_Facebook": "Влизана с Facebook профил",
"Accounts_OAuth_Google": "Влизане с Google профил",
"Accounts_RegistrationForm_Public": "Обществен",
+ "All_channels": "Всички канали",
"All_messages": "Всички съобщения",
"and": "и",
"Application_Name": "Име на Приложение",
@@ -38,6 +41,8 @@
"Busy_male": "Зает",
"channel": "канал",
"Channel": "Канал",
+ "Channels": "Канали",
+ "Channels_list": "Списък на публични канали",
"Click_here": "Натисни тук",
"close": "затвори",
"Close": "Затвори",
@@ -84,6 +89,7 @@
"LDAP_Port": "Порт",
"Leave_room": "Излез от стаята",
"line": "линия",
+ "List_of_Channels": "Списък с Канали",
"Loading...": "Зареждане...",
"Log_Package": "Покажи пакет",
"Login": "Влез",
@@ -96,6 +102,7 @@
"Message_too_long": "Съобщението е твърде дълго",
"Messages": "Съобщения",
"minutes": "Минути",
+ "More_channels": "Още канали",
"My_Account": "Моя Профил",
"n_messages": "%s съобщения",
"N_new_messages": "%s нови съобщения",
@@ -112,6 +119,7 @@
"Online": "На линия",
"Oops!": "Упс",
"Open": "Отвори",
+ "Password": "Парола",
"People": "Хора",
"Please_add_a_comment": "Добави коментар моля",
"Please_wait": "Моля изчакайте",
@@ -145,6 +153,8 @@
"Site_Name": "Име на Сайта",
"Skip": "Прескочи",
"Smarsh_MissingEmail_Email": "Липсваща Електрона поща",
+ "Stats_Total_Channels": "Общо Канали",
+ "Stats_Total_Messages_Channel": "Общо Съобщения в Канали",
"Test_Desktop_Notifications": "Изпробвай Известия на работния плот",
"Thank_you_exclamation_mark": "Благодаря!",
"The_server_will_restart_in_s_seconds": "Сървъра ще бъде рестартиран след %s секунди",
diff --git a/packages/rocketchat-i18n/i18n/ca.i18n.json b/packages/rocketchat-i18n/i18n/ca.i18n.json
index d3b5ad35e10c6..e4118ed13bffc 100644
--- a/packages/rocketchat-i18n/i18n/ca.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ca.i18n.json
@@ -12,11 +12,17 @@
"Accept": "Accepta",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Acceptar sol·licituds de xat en viu entrant encara que no hi hagi agents en línia",
"Accept_with_no_online_agents": "Acceptar sense agents en línia",
+ "access-mailer": "Accedir a la pantalla d'enviament",
+ "access-mailer_description": "Permís per enviar correu-e massiu a tots els usuaris",
+ "access-permissions": "Accés a la pantalla de permisos",
+ "access-permissions_description": "Modifica permisos per a diversos rols",
"Access_not_authorized": "Accés no autoritzat",
"Access_Token_URL": "URL Access Token",
"Accessing_permissions": "L'accés als permisos",
"Account_SID": "Compte SID",
"Accounts": "Comptes",
+ "Accounts_AllowAnonymousRead": "Permetre lectura anònima",
+ "Accounts_AllowAnonymousWrite": "Permetre escriptura anònima",
"Accounts_AllowDeleteOwnAccount": "Permetre als usuaris eliminar el seu propi compte",
"Accounts_AllowedDomainsList": "Llista de dominis permesos",
"Accounts_AllowedDomainsList_Description": "Llista dels dominis permesos separada per comes ",
@@ -27,18 +33,20 @@
"Accounts_AllowUserProfileChange": "Permetre modificar el perfil d'usuari",
"Accounts_AvatarResize": "Canviar la mida dels avatars",
"Accounts_AvatarSize": "Mida d'avatar",
- "Accounts_AvatarStorePath": "Ruta d'emmagatzematge dels avatars",
- "Accounts_AvatarStoreType": "Tipus d'emmagatzematge dels avatars",
"Accounts_BlockedDomainsList": "Llista de dominis bloquejats",
"Accounts_BlockedDomainsList_Description": "Llista de dominis bloquejats separada per comes",
"Accounts_BlockedUsernameList": "Llista de noms d'usuari bloquejats",
"Accounts_BlockedUsernameList_Description": "Llista separada per comes de noms d'usuari bloquejats (no distingeix majúscules/minúscules)",
- "Accounts_CustomFields_Description": "Ha de ser un objecte JSON vàlid on les claus són els noms dels camps i contenen un diccionari amb les opcions del camp. Exemple:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFields_Description": "Ha de ser un objecte JSON vàlid on les claus són els noms dels camps i contenen un diccionari amb les opcions del camp. Exemple:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Camps personalitzats a mostrar a l'informació d'usuari",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Prefix suggerit per al nom d'usuari per defecte",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Alerta per defecte per a les notificacions d'escriptori",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Alerta per defecte notificacions mòbil",
"Accounts_denyUnverifiedEmail": "Denegar correu electrònic sense verificar",
"Accounts_EmailVerification": "Verificació de correu electrònic",
"Accounts_EmailVerification_Description": "Assegura't que la configuració SMTP és correcta per fer servir aquesta funcionalitat",
"Accounts_Enrollment_Email": "Missatge de correu electrònic d'inscripció",
- "Accounts_Enrollment_Email_Default": "Benvingut a [Site_Name] Vés a [Site_URL] i prova la millor eina de programari lliure per a treball a distància disponible actualment!
",
+ "Accounts_Enrollment_Email_Default": "Benvingut a [Site_Name] Vés a [Site_URL] i prova la millor eina de programari lliure per a treball a distància disponible actualment!
",
"Accounts_Enrollment_Email_Description": "És possible utilitzar els marcadors: [name], [fname], [lname] per al nom complet de l'usuari, nom o cognom, respectivament. [email] per a l'adreça de correu electrònic de l'usuari. [Site_Name] i [Site_URL] pel nom del lloc web i de l'adreça URL, respectivament. ",
"Accounts_Enrollment_Email_Subject_Default": "Benvingut a [Site_Name]",
"Accounts_ForgetUserSessionOnWindowClose": "Oblida la sessió d'usuari en tancar la finestra",
@@ -62,6 +70,10 @@
"Accounts_OAuth_Custom_Token_Path": "Ruta del token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token enviat via",
"Accounts_OAuth_Custom_Username_Field": "Camp de nom d'usuari",
+ "Accounts_OAuth_Drupal": "Activa inici de sessió de Drupal",
+ "Accounts_OAuth_Drupal_callback_url": "Redirect URI de Drupal oAuth2",
+ "Accounts_OAuth_Drupal_id": "Client ID de Drupal oAuth2",
+ "Accounts_OAuth_Drupal_secret": "Client Secret de Drupal oAuth2",
"Accounts_OAuth_Facebook": "Inici de sessió amb Facebook",
"Accounts_OAuth_Facebook_callback_url": "URL de retorn (callback) de Facebook",
"Accounts_OAuth_Facebook_id": "App ID de Facebook",
@@ -90,15 +102,19 @@
"Accounts_OAuth_Meteor_callback_url": "URL de retorn (callback) de Meteor",
"Accounts_OAuth_Meteor_id": "Meteor ID",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_host": "Host del servidor intermediari (proxy)",
+ "Accounts_OAuth_Proxy_services": "Serveis del servidor intermediari (proxy)",
"Accounts_OAuth_Twitter": "Inici de sessió amb Twitter",
"Accounts_OAuth_Twitter_callback_url": "URL de retorn (callback) de Twitter",
"Accounts_OAuth_Twitter_id": "Twitter ID",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "Inici de sessió amb WordPress",
"Accounts_OAuth_Wordpress_callback_url": "URL de retorn (callback) de WordPress",
- "Accounts_OAuth_Wordpress_id": "Wordpress ID",
- "Accounts_OAuth_Wordpress_secret": "Wordpress Secret",
+ "Accounts_OAuth_Wordpress_id": "WordPress ID",
+ "Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Restablir contrasenya",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Rols per defecte per als serveis d'autenticació",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Rols per defecte (separats per comes) que s'assignaran als usuaris quan es registrin a través dels serveis d'autenticació",
"Accounts_Registration_AuthenticationServices_Enabled": "Registre mitjançant serveis d'autenticació",
"Accounts_RegistrationForm": "Formulari de registre",
"Accounts_RegistrationForm_Disabled": "Deshabilitat",
@@ -106,24 +122,37 @@
"Accounts_RegistrationForm_Public": "Públic",
"Accounts_RegistrationForm_Secret_URL": "URL secret",
"Accounts_RegistrationForm_SecretURL": "URL secret del fomulari de registre",
- "Accounts_RegistrationForm_SecretURL_Description": "Cal proporcionar una cadena de text aleatori que s'afegirà a l'URL de registre. Exemple: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Cal proporcionar una cadena de text aleatori que s'afegirà a l'URL de registre. Exemple: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Requerir el nom per registrar-se",
"Accounts_RequirePasswordConfirmation": "Requereix confirmació de la contrasenya",
+ "Accounts_SearchFields": "Camps a considerar a la cerca",
"Accounts_SetDefaultAvatar": "Avatar per defecte",
"Accounts_SetDefaultAvatar_Description": "Prova de determinar l'avatar per defecte basant-se en el compte d'OAuth o bé Gravatar",
"Accounts_ShowFormLogin": "Mostra inici de sessió basat en formulari",
"Accounts_UseDefaultBlockedDomainsList": "Utilitza la llista predeterminada de dominis bloquejats",
"Accounts_UseDNSDomainCheck": "Utilitza la comprovació DNS de dominis",
- "Accounts_UserAddedEmail_Default": "Benvingut a [Site_Name] Vés a [Site_URL] i prova la millor eina de programari lliure per a treball a distància disponible actualment!
",
+ "Accounts_UserAddedEmail_Default": "Benvingut a [Site_Name] Vés a [Site_URL] i prova la millor eina de programari lliure per a treball a distància disponible actualment!
",
"Accounts_UserAddedEmail_Description": "És possible utilitzar els marcadors: [name], [fname], [lname] per al nom complet de l'usuari, nom o cognom, respectivament. [email] per a l'adreça de correu electrònic de l'usuari. [password] per la contrasenya. [Site_Name] i [Site_URL] pel nom del lloc web i de l'adreça URL, respectivament. ",
"Accounts_UserAddedEmailSubject_Default": "Se t'ha afegit a [Site_Name]",
"Activate": "Activa",
"Activity": "Activitat",
"Add": "Afegeix",
+ "add-oauth-service": "Afegir servei Oauth",
+ "add-oauth-service_description": "Permís per afegir nous serveis Oauth",
+ "add-user": "Afegir usuari",
+ "add-user-to-any-c-room": "Afegir usuari a canal públic",
+ "add-user-to-any-c-room_description": "Permís per afegir un usuari a qualsevol canal públic",
+ "add-user-to-any-p-room": "Afegir usuari a canal privat",
+ "add-user-to-any-p-room_description": "Permís per afegir un usuari a qualsevol canal privat",
+ "add-user-to-joined-room": "Afegir usuari a canal on unit",
+ "add-user-to-joined-room_description": "Permís per afegir un usuari a un canal on està unit",
+ "add-user_description": "Permís per afegir nous usuaris al servidor via la pantalla d'usuaris",
"Add_agent": "Afegeix agent",
"Add_custom_oauth": "Afegeix OAuth personalitzat",
"Add_Domain": "Afegir domini",
+ "Add_files_from": "Afegeix arxius de",
"Add_manager": "Afegeix supervisor",
+ "Add_Role": "Afegeix rol",
"Add_user": "Afegeix usuari",
"Add_User": "Afegeix usuari",
"Add_users": "Afegeix usuaris",
@@ -133,6 +162,7 @@
"Additional_emails": "Correus electrònics addicionals",
"Additional_Feedback": "Retroalimentació addicional",
"Administration": "Administració",
+ "Adult_images_are_not_allowed": "Les imatges per a adults no són permeses",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Després de l'autenticació OAuth2, els usuaris seran redirigits a aquesta URL",
"Agent": "Agent",
"Agent_added": "Agent afegit",
@@ -147,22 +177,30 @@
"All_messages": "Tots els missatges",
"Allow_Invalid_SelfSigned_Certs": "Permetre certificats auto-signats invàlids",
"Allow_Invalid_SelfSigned_Certs_Description": "Permetre certificats SSL auto-signats i invàlids per a enllaços de validació i vistes prèvies.",
+ "Allow_switching_departments": "Permet al visitant canviar de departament",
"Always_open_in_new_window": "Obre sempre en finestra nova",
"Analytics_features_enabled": "Funcionalitats habilitades",
"Analytics_features_messages_Description": "Monitoritza esdeveniments personalitzats relacionats amb accions que els usuaris fan als missatges.",
"Analytics_features_rooms_Description": "Monitoritza esdeveniments personalitzats relacionats amb accions en un canal o grup (crear, abandonar, eliminar...).",
"Analytics_features_users_Description": "Monitoritza esdeveniments personalitzats relacionats amb la gestió d'usuaris (reset de contrasenya, canvis d'avatar, etc.).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "Tracking ID",
"and": "i",
"And_more": "I __length__ més",
"Animals_and_Nature": "Animals i natura",
+ "Announcement": "Anunci",
"API": "API",
"API_Allow_Infinite_Count": "Permet obtenir tot",
"API_Allow_Infinite_Count_Description": "Les peticions a la API REST haurien de permetre retornar-ho tot en una sola petició?",
"API_Analytics": "Analítiques",
+ "API_CORS_Origin": "Origen CORS",
"API_Default_Count": "Comptador per defecte",
"API_Default_Count_Description": "El comptador per defecte per als resultats de les peticions API REST si el consumidor no n'ha especificat cap.",
+ "API_Drupal_URL": "Adreça URL del servidor de Drupal",
+ "API_Drupal_URL_Description": "Exemple: https://domini.com (sense la barra final)",
"API_Embed": "Incrusta (embed)",
"API_Embed_Description": "Activa o no les previsualitzacions d'enllaços quan un usuari publica l'enllaç a un web.",
+ "API_Embed_UserAgent": "Incrusta user agent de la consulta",
"API_EmbedCacheExpirationDays": "Caducitat de la memòria cau de les incrustacions (en dies)",
"API_EmbedDisabledFor": "Deshabilitar la incrustació per als usuaris",
"API_EmbedDisabledFor_Description": "Llista de noms d'usuari separats per comes",
@@ -170,9 +208,16 @@
"API_EmbedIgnoredHosts_Description": "Llista de hosts o adreces CIDR separada per comes, per exemple: localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Ports segurs",
"API_EmbedSafePorts_Description": "Llista de ports permesos per a la vista prèvia, separada per comes.",
+ "API_Enable_CORS": "Activa CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "Activa la consulta de l'historial de missatges directes",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Això activa el `/api/v1/im.history.others` que permet veure missatges directes enviats per altres usuaris tot i no formar-ne part.",
+ "API_Enable_Shields": "Activa escuts",
+ "API_Enable_Shields_Description": "Activa els escuts disponibles a `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "URL del servidor",
"API_GitHub_Enterprise_URL_Description": "Exemple: http://domain.com (sense la barra final)",
"API_Gitlab_URL": "URL de GitLab",
+ "API_Shield_Types": "Tipus d'escut",
+ "API_Shield_Types_Description": "Tipus d'escut que s'activaran, com a llista separada per comes. Triar entre `online`, `channel` o `*` per a tots",
"API_Token": "API Token",
"API_Upper_Count_Limit": "Nombre màxim de registres",
"API_Upper_Count_Limit_Description": "Quin és el nombre màxim de registres que la API REST pot retornar (si no és il·limitat)?",
@@ -186,19 +231,28 @@
"Application_updated": "Aplicació actualitzada",
"Apply_and_refresh_all_clients": "Aplicar i refrescar tots els clients",
"Archive": "Arxiu",
+ "archive-room": "Arxivar sala",
+ "archive-room_description": "Permís per arxivar un canal",
"are_also_typing": "també estan escrivint",
"are_typing": "estan escrivint",
"Are_you_sure": "N'estàs segur?",
"Are_you_sure_you_want_to_delete_your_account": "Estàs segur d'eliminar el teu compte?",
+ "assign-admin-role": "Assignar rol d'administrador",
+ "assign-admin-role_description": "Permís per assignar el rol d'administrador a altres usuaris",
"Assign_admin": "Assignant admin",
"at": "a",
"AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Fitxer pujat",
+ "Attribute_handling": "Tractament d'atributs",
+ "Audio_message": "Missatge d'àudio",
"Auth_Token": "Auth Token",
"Author": "Autor",
"Authorization_URL": "URL d'autorització",
"Authorize": "Autoritzar",
+ "auto-translate": "Auto-traducció",
+ "auto-translate_description": "Permís per utilitzar l'eina d'auto-traducció",
"Auto_Load_Images": "Carregar automàticament les imatges",
+ "Auto_Translate": "Autotraducció",
"AutoLinker_Email": "Auto-enllaça correu-e",
"AutoLinker_Phone": "Auto-enllaça telèfon",
"AutoLinker_Phone_Description": "Enllaça automàticament per als números de telèfon. Per exemple: `(123) 456-7890`",
@@ -208,6 +262,11 @@
"AutoLinker_Urls_TLD": "Auto-enllaça URL TLD",
"AutoLinker_Urls_www": "Auto-enllaça URL 'www'",
"AutoLinker_UrlsRegExp": "Auto-enllaça URL d'expressions regulars",
+ "Automatic_Translation": "Traducció automàtica",
+ "AutoTranslate_Change_Language_Description": "Canviar l'idioma d'autotraducció no traduirà els missatges anteriors.",
+ "AutoTranslate_Enabled": "Activa autotraducció",
+ "AutoTranslate_Enabled_Description": "Activar l'autotraducció permetrà a qui tingui el permís auto-translate veure els missatges traduïts automàticament a l'idioma que seleccioni. Pot tenir càrrecs suplementaris, veure la Documentació de Google ",
+ "AutoTranslate_GoogleAPIKey": "API Key Google",
"Available": "En línia",
"Available_agents": "Agents disponibles",
"Avatar": "Avatar",
@@ -222,9 +281,14 @@
"Away_male": "Absent",
"Back": "Torna",
"Back_to_applications": "Torna a les aplicacions",
+ "Back_to_chat": "Torna al xat",
+ "Back_to_integration_detail": "Tornar al detall de la integració",
"Back_to_integrations": "Torna a les integracions",
"Back_to_login": "Torna a identificar-me",
"Back_to_permissions": "Torna a permisos",
+ "Backup_codes": "Codis de recuperació",
+ "ban-user": "Banejar usuari",
+ "ban-user_description": "Permís per banejar un usuari d'un canal",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Característica Beta. Requereix que la videoconferència estigui activa.",
"Block_User": "Bloqueja usuari",
"Body": "Cos",
@@ -233,7 +297,12 @@
"BotHelpers_userFields": "Camps d'usuari",
"BotHelpers_userFields_Description": "CSV de camps d'usuari que poden ser accedits pels mètodes helper dels bots.",
"Branch": "Branca",
+ "Broadcast_Connected_Instances": "Difusió de les instàncies connectades",
"Bugsnag_api_key": "Clau API Bugsnag",
+ "bulk-create-c": "Crear canals en massa",
+ "bulk-create-c_description": "Permís per a crear canals en massa",
+ "bulk-register-user": "Crear canals en massa",
+ "bulk-register-user_description": "Permís per a crear canals en massa",
"busy": "ocupat",
"Busy": "Ocupat",
"busy_female": "ocupada",
@@ -245,6 +314,7 @@
"Cancel": "Cancel·la",
"Cancel_message_input": "Cancel·la",
"Cannot_invite_users_to_direct_rooms": "No es pot convidar els usuaris a les sales directes",
+ "Cannot_open_conversation_with_yourself": "No es pot obrir una conversa amb un mateix",
"CAS_autoclose": "Tancar automàticament la finestra emergent d'inici de sessió",
"CAS_base_url": "Adreça URL SSO base",
"CAS_base_url_Description": "Adreça URL base del servei extern SSO. Ex: https://sso.example.undef/sso/",
@@ -252,6 +322,7 @@
"CAS_button_label_color": "Color de text del botó d'inici de sessió",
"CAS_button_label_text": "Etiqueta del botó d'inici de sessió",
"CAS_enabled": "Actiu",
+ "CAS_Login_Layout": "Plantilla de la identificació CAS",
"CAS_login_url": "Adreça URL d'inici de sessió SSO",
"CAS_login_url_Description": "Adreça URL d'inici de sessió del servei extern SSO. Ex: https://sso.example.undef/sso/login",
"CAS_popup_height": "Alçada de la finestra emergent d'inici de sessió",
@@ -264,20 +335,27 @@
"CAS_version_Description": "Només utilitzis una versió CAS suportada pel teu servei CAS SSO.",
"CDN_PREFIX": "Prefix CDN",
"Certificates_and_Keys": "Certificats i claus",
- "Changing_email": "Canvi de correu-e",
"Change_Room_Type": "Canvi de tipus de sala",
+ "Changing_email": "Canvi de correu-e",
"channel": "canal",
"Channel": "Canal",
- "Channel_already_exist": "El canal '#%s' ja existeix.",
+ "Channel_already_exist": "El canal `#%s` ja existeix.",
+ "Channel_already_exist_static": "El canal ja existeix.",
"Channel_already_Unarchived": "El canal `#%s` ja es troba desarxivat.",
"Channel_Archived": "El canal `#%s` s'ha arxivat correctament.",
+ "Channel_created": "Canal `#%s` creat.",
"Channel_doesnt_exist": "El canal `#%s` no existeix",
+ "Channel_name": "Nom del canal",
+ "Channel_Name_Placeholder": "Sisplau, introdueix el nom de canal...",
+ "Channel_to_listen_on": "Canal on escoltar",
"Channel_Unarchived": "El canal `#%s` s'ha desarxivat correctament.",
"Channels": "Canals",
+ "Channels_are_where_your_team_communicate": "Els canals són on es comunica el teu equip",
"Channels_list": "Llista de canals públics",
"Chat_button": "botó de xat",
"Chat_closed": "Xat tancat",
"Chat_closed_successfully": "Xat tancat correctament",
+ "Chat_Now": "Xateja ara",
"Chat_window": "finestra de xat",
"Chatops_Enabled": "Activa Chatops",
"Chatops_Title": "Tauler de Chatops",
@@ -286,15 +364,24 @@
"Choose_messages": "Tria missatges",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Tria l'àlies que apareixerà abans del nom d'usuari als missatges.",
"Choose_the_username_that_this_integration_will_post_as": "Tria el nom d'usuari amb el qual aquesta integració publicarà.",
+ "clean-channel-history": "Esborrar l'historial de canal",
+ "clean-channel-history_description": "Permís per esborrar l'historial dels canals",
"clear": "Esborra",
- "clear_cache_now": "Esborra la memòria cau ara",
"Clear_all_unreads_question": "Esborrar tots els missatges no llegits?",
+ "clear_cache_now": "Esborra la memòria cau ara",
+ "clear_history": "Esborra l'historial",
"Click_here": "Fes clic aquí",
+ "Click_here_for_more_info": "Fes clic aquí per a més informació",
+ "Click_to_join": "Fes clic per unir-te!",
"Client_ID": "Client ID",
"Client_Secret": "Client Secret",
"Clients_will_refresh_in_a_few_seconds": "Els clients es refrescaran en breus instants",
"close": "tanca",
"Close": "Tanca",
+ "close-livechat-room": "Tancar sala de xat en viu",
+ "close-livechat-room_description": "Permís per tancar el canal de xat en viu actiu",
+ "close-others-livechat-room": "Tancar sala de xat en viu",
+ "close-others-livechat-room_description": "Permís per tancar altres canals de xat en viu",
"Closed": "Tancat",
"Closed_by_visitor": "Tancat pel visitant",
"Closing_chat": "Tancant xat",
@@ -304,6 +391,7 @@
"Comment_to_leave_on_closing_session": "Comentari a deixar en tancar la sessió",
"Compact": "Compacte",
"Confirm_password": "Confirma la contrasenya",
+ "Content": "Contingut",
"Conversation": "Conversa",
"Conversation_closed": "Conversa tancada: __comment__.",
"Convert_Ascii_Emojis": "Converteix ASCII a Emoji",
@@ -314,12 +402,23 @@
"Count": "Compta",
"Cozy": "Acollidor",
"Create": "Crea",
+ "create-c": "Crear canals públics",
+ "create-c_description": "Permís per crear canals públics",
+ "create-d": "Crear missatges directes",
+ "create-d_description": "Permís per a iniciar missatges directes",
+ "create-p": "Crear canals privats",
+ "create-p_description": "Permís per crear canals privats",
+ "create-user": "Crear usuari",
+ "create-user_description": "Permís per crear usuaris",
"Create_A_New_Channel": "Crea un nou canal",
"Create_new": "Crea nou",
"Created_at": "Creat a",
"Created_at_s_by_s": "Creat a %s per %s ",
+ "Created_at_s_by_s_triggered_by_s": "Creat el %s per %s i disparat per %s ",
+ "CRM_Integration": "Integració CRM",
"CROWD_Reject_Unauthorized": "Rebutja no autoritzat",
"Current_Chats": "Xats actuals",
+ "Current_Status": "Estat actual",
"Custom": "Personalitzat",
"Custom_Emoji": "Emoticona personalitzada",
"Custom_Emoji_Add": "Afegir nova emoticona",
@@ -335,8 +434,18 @@
"Custom_oauth_unique_name": "Nom únic de OAuth personalitzat",
"Custom_Script_Logged_In": "Script personalitzat per als usuaris en identificar-se",
"Custom_Script_Logged_Out": "Script personalitzat per als usuaris en sortir",
+ "Custom_Scripts": "Scripts personalitzats",
+ "Custom_Sound_Add": "Afegir so personalitzat",
+ "Custom_Sound_Delete_Warning": "L'eliminació d'un so no es pot revertir.",
+ "Custom_Sound_Error_Invalid_Sound": "So invàlid",
+ "Custom_Sound_Error_Name_Already_In_Use": "El nom del so personalitzat ja està en ús.",
+ "Custom_Sound_Has_Been_Deleted": "El so personalitzat s'ha esborrat.",
+ "Custom_Sound_Info": "Informació del so personalitzat",
+ "Custom_Sound_Saved_Successfully": "So personalitzat guardat correctament",
+ "Custom_Sounds": "Sons personalitzats",
"Custom_Translations": "Traduccions personalitzades",
- "Custom_Translations_Description": "Ha de ser un objecte JSON vàlid on les claus són el codi de l'idioma i contenen un diccionari de clau (key) i traduccions. Exemple:{\n \"en\": {\n \"key\": \"translation\"\n },\n \"ca\": {\n \"key\": \"traducció\"\n }\n} ",
+ "Custom_Translations_Description": "Ha de ser un objecte JSON vàlid on les claus són el codi de l'idioma i contenen un diccionari de clau i traducció. Exemple:{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"ca\": {\n \"Channels\": \"Sales\"\n }\n} ",
+ "CustomSoundsFilesystem": "Sistema d'arxius dels sons personalitzats",
"Dashboard": "Tauler",
"Date": "Data",
"Date_From": "De",
@@ -348,6 +457,16 @@
"Decline": "Rebutja",
"Default": "Per defecte",
"Delete": "Elimina",
+ "delete-c": "Esborrar canals públics",
+ "delete-c_description": "Permís per esborrar canals públics",
+ "delete-d": "Esborrar missatges directes",
+ "delete-d_description": "Permís per esborrar missatges directes",
+ "delete-message": "Esborrar missatge",
+ "delete-message_description": "Permís per esborrar un missatge d'una sala",
+ "delete-p": "Esborrar canals privats",
+ "delete-p_description": "Permís per esborrar canals privats",
+ "delete-user": "Esborrar usuari",
+ "delete-user_description": "Permís per esborrar usuaris",
"Delete_message": "Esborra missatge",
"Delete_my_account": "Esborra el meu compte",
"Delete_Room_Warning": "Eliminar una sala de xat esborra tots els missatges que conté. Aquesta acció no es pot desfer.",
@@ -361,12 +480,29 @@
"Desktop": "Escriptori",
"Desktop_Notification_Test": "Prova de notificació d'escriptori",
"Desktop_Notifications": "Notificacions d'escriptori",
+ "Desktop_Notifications_Default_Alert": "Alerta per defecte per a les notificacions d'escriptori",
"Desktop_Notifications_Disabled": "Les notificacions d'escriptori han estat desactivades. Canvia les preferències del navegador si vols tornar a activar-les.",
"Desktop_Notifications_Duration": "Durada de les notificacions d'escriptori",
"Desktop_Notifications_Duration_Description": "Segons de mostra de les notificacions d'escriptori. Això pot afectar al centre de notificacions del macOS. Introduïu 0 per utilitzar la configuració del navegador per defecte i no afectar al centre de notificacions.",
"Desktop_Notifications_Enabled": "Les notificacions d'escriptori estan activades",
+ "Different_Style_For_User_Mentions": "Estil diferent per les mencions d'usuari",
"Direct_message_someone": "Envia un missatge directe a algú",
"Direct_Messages": "Missatges directes",
+ "Direct_Reply": "Resposta directa",
+ "Direct_Reply_Debug": "Debug resposta directa",
+ "Direct_Reply_Delete": "Esborra correus-e interceptats",
+ "Direct_Reply_Enable": "Activa resposta directa",
+ "Direct_Reply_Frequency": "Freqüència de comprovació de correu-e",
+ "Direct_Reply_Frequency_Description": "(en minuts, per defecte/mínim 2)",
+ "Direct_Reply_Host": "Host de resposta directa",
+ "Direct_Reply_IgnoreTLS": "Ignorar TLS",
+ "Direct_Reply_Password": "Contrasenya",
+ "Direct_Reply_Port": "Port de resposta directa",
+ "Direct_Reply_Protocol": "Protocol de resposta directa",
+ "Direct_Reply_Separator": "Separador",
+ "Direct_Reply_Username": "Nom d'usuari",
+ "Disable_Notifications": "Desactiva notificacions",
+ "Disable_two-factor_authentication": "Desactiva l'autenticació de dos factors",
"Display_offline_form": "Mostra el formulari de fora de línia",
"Displays_action_text": "Mostra text de l'acció",
"Do_you_want_to_change_to_s_question": "Canvia a %s ?",
@@ -374,6 +510,7 @@
"Domain_added": "Domini afegit",
"Domain_removed": "Domini eliminat",
"Domains": "dominis",
+ "Domains_allowed_to_embed_the_livechat_widget": "Llista separada per comes dels dominis on es permet incloure el xat en viu. Deixeu en blanc per permetre'ls tots.",
"Download_Snippet": "Descarrega",
"Drop_to_upload_file": "Arrossega un arxiu aquí per pujar-lo",
"Dry_run": "Prova de funcionament",
@@ -384,8 +521,21 @@
"Duplicate_private_group_name": "Ja hi ha un grup privat amb el nom '%s'",
"Duration": "Durada",
"Edit": "Edita",
+ "edit-message": "Editar missatge",
+ "edit-message_description": "Permís per editar un missatge d'una sala",
+ "edit-other-user-active-status": "Editar l'estat actiu d'un altre usuari",
+ "edit-other-user-active-status_description": "Permís per activar o desactivar altres comptes",
+ "edit-other-user-info": "Editar la informació d'un altre usuari",
+ "edit-other-user-info_description": "Permís per canviar el nom, el nom d'usuari o l'adreça de correu-e d'altres usuaris",
+ "edit-other-user-password": "Editar la contrasenya d'un altre usuari",
+ "edit-other-user-password_description": "Permís per modificar la contrasenya d'altres usuaris. Requereix el permís edit-other-user-info.",
+ "edit-privileged-setting": "Editar opcions privilegiades",
+ "edit-privileged-setting_description": "Permís per editar la configuració",
+ "edit-room": "Editar sala",
+ "edit-room_description": "Permís per editar el nom d'una sala, el tema, el tipus (privada o pública) o l'estat (actiu o arxivat)",
"Edit_Custom_Field": "Edita camp personalitzat",
"Edit_Department": "Edita departament",
+ "Edit_previous_message": "`%s` - Edita el missatge anterior",
"Edit_Trigger": "Edita disparador",
"edited": "editat",
"Editing_room": "Edició de sala",
@@ -402,6 +552,7 @@
"Email_Notification_Mode_All": "Cada menció / DM",
"Email_Notification_Mode_Disabled": "Deshabilitat",
"Email_or_username": "Adreça de correu-e o nom d'usuari",
+ "Email_Placeholder": "Sisplau, introdueix la teva adreça de correu-e...",
"Email_subject": "Assumpte",
"Email_verified": "Adreça de correu-e verificada",
"Emoji": "Emoji",
@@ -409,14 +560,20 @@
"Empty_title": "Títol buit",
"Enable": "Activa",
"Enable_Desktop_Notifications": "Activa notificacions d'escriptori",
- "Enabled": "Activa",
"Enable_Svg_Favicon": "Activa el favicon SVG",
+ "Enable_two-factor_authentication": "Activa l'autenticació de dos factors",
+ "Enabled": "Activa",
"Encrypted_message": "Missatge xifrat",
"End_OTR": "Finalitza OTR",
"Enter_a_regex": "Introdueix una RegExp",
"Enter_a_room_name": "Introdueix un nom de sala",
"Enter_a_username": "Introdueix un nom d'usuari",
+ "Enter_Alternative": "Mode alternatiu (envia amb Enter + Ctrl/Alt/Shift/CMD)",
+ "Enter_authentication_code": "Entra el codi d'autenticació",
+ "Enter_Behaviour": "Comportament de la tecla Enter",
+ "Enter_Behaviour_Description": "Canvia si la tecla Enter envia el missatge o fa un salt de línia",
"Enter_name_here": "Introdueix el nom aquí",
+ "Enter_Normal": "Mode normal (envia amb Enter)",
"Enter_to": "Entra a",
"Error": "Error",
"error-action-not-allowed": "__action__ no permès",
@@ -430,6 +587,7 @@
"error-could-not-change-username": "No s'ha pogut canviar el nom d'usuari",
"error-delete-protected-role": "No es pot eliminar un rol protegit",
"error-department-not-found": "Departament no trobat",
+ "error-direct-message-file-upload-not-allowed": "Compartició d'arxius no permesa als missatges directes",
"error-duplicate-channel-name": "Ja hi ha un canal amb el nom '%s' ",
"error-email-domain-blacklisted": "El domini de l'adreça electrònica és a la llista negra",
"error-email-send-failed": "Error en l'intent d'enviament de correu-e: __message__",
@@ -451,7 +609,6 @@
"error-invalid-email-address": "Adreça de correu-e invàlida",
"error-invalid-file-height": "Alçada de la imatge invàlida",
"error-invalid-file-type": "Tipus d'arxiu no vàlid",
- "error-direct-message-file-upload-not-allowed": "Compartició d'arxius no permesa als missatges directes",
"error-invalid-file-width": "Amplada de la imatge invàlida",
"error-invalid-from-address": "Adreça invàlida al camp 'De'.",
"error-invalid-integration": "Integració no vàlida",
@@ -462,7 +619,7 @@
"error-invalid-redirectUri": "Redirecció URI invàlida",
"error-invalid-role": "Rol no vàlid",
"error-invalid-room": "Sala no vàlida",
- "error-invalid-room-name": "__room_name__ no és un nom de sala vàlid, utilitzeu només lletres, números, guions i guions baixos",
+ "error-invalid-room-name": "__room_name__ no és un nom de sala vàlid",
"error-invalid-room-type": "__type__ no és un tipus vàlid de sala.",
"error-invalid-settings": "La configuració proporcionada no és vàlida",
"error-invalid-subscription": "Subscripció no vàlida",
@@ -486,15 +643,21 @@
"error-the-field-is-required": "Es requereix el camp __field__.",
"error-too-many-requests": "Error, massa peticions. Si us plau, més a poc a poc. Heu d'esperar __seconds__ segons abans de reintentar-ho.",
"error-user-is-not-activated": "L'usuari no ha estat activat",
+ "error-user-limit-exceeded": "El nombre d'usuaris per invitar al canal #channel_name supera el límit establert per l'administrador",
"error-user-not-in-room": "L'usuari no es troba en aquesta sala",
"error-user-registration-disabled": "El registre d'usuaris està desactivat",
"error-user-registration-secret": "El registre d'usuaris només es permet a través d'URL secret",
"error-you-are-last-owner": "Ets l'últim propietari. Si us plau, estableix un nou propietari abans de sortir de la sala.",
"Error_changing_password": "Error en canviar la contrasenya",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: El Rocket.Chat requereix oplog tailing quan corre en múltiples instàncies",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Si us plau, assegureu-vos que MongoDB és en mode ReplicaSet i la variable d'entorn MONGO_OPLOG_URL està definida correctament al servidor d'aplicacions",
"Esc_to": "Esc a",
+ "Event_Trigger": "Disparador d'esdeveniments",
+ "Event_Trigger_Description": "Selecciona quin tipus d'esdeveniment desencadenarà aquesta integració WebHook de sortida",
"every_30_minutes": "Cada 30 minuts",
"every_hour": "Cada hora",
"every_six_hours": "Cada 6 hores",
+ "Everyone_can_access_this_channel": "Qualsevol pot accedir a aquest canal",
"Example_s": "Exemple: %s",
"Exclude_Botnames": "Excloure bots",
"Exclude_Botnames_Description": "No processar missatges de bots el nom dels quals encaixa amb l'expressió regular superior. Si es deixa en blanc, tots els missatges dels bots es propagaran.",
@@ -508,38 +671,56 @@
"File_exceeds_allowed_size_of_bytes": "L'arxiu supera la mida màxima de __size__.",
"File_not_allowed_direct_messages": "Compartició d'arxius no permesa als missatges directes.",
"File_type_is_not_accepted": "El tipus de fitxer no s'accepta.",
+ "File_uploaded": "Fitxer pujat",
"FileUpload": "Pujar arxius",
- "FileUpload_Enabled": "Habilita pujar arxius",
"FileUpload_Disabled": "Les pujades de fitxers estan desactivades.",
+ "FileUpload_Enabled": "Habilita pujar arxius",
"FileUpload_Enabled_Direct": "Compartició d'arxius activa als missatges directes",
"FileUpload_File_Empty": "Arxiu buit",
"FileUpload_FileSystemPath": "Ruta dels arxius",
+ "FileUpload_GoogleStorage_AccessId": "Acces Id del Google Storage",
+ "FileUpload_GoogleStorage_AccessId_Description": "L'Acces Id generalment és en format de correu-e, per exemple: \"exemple-prova@exemple.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Nom del Bucket Google Storage",
+ "FileUpload_GoogleStorage_Bucket_Description": "El nom del bucket on els arxius s'haurien de pujar.",
+ "FileUpload_GoogleStorage_Secret": "Secret Google Storage",
+ "FileUpload_GoogleStorage_Secret_Description": "Si us plau, segueix aquestes instruccions i enganxa el resultat aquí.",
"FileUpload_MaxFileSize": "Mida màxima de pujada (en bytes)",
"FileUpload_MediaType_NotAccepted": "Tipus d'arxius no acceptats",
"FileUpload_MediaTypeWhiteList": "Tipus d'arxius acceptats",
"FileUpload_MediaTypeWhiteListDescription": "Llista de tipus d'arxiu separada per comes. Deixa-la en blanc per acceptar tots els tipus.",
"FileUpload_ProtectFiles": "Protegir els arxius pujats",
"FileUpload_ProtectFilesDescription": "Només els usuaris identificats hi tindran accés",
- "FileUpload_S3_Acl": "Amazon S3 acl",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyID",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 BucketName",
+ "FileUpload_S3_Acl": "Acl",
+ "FileUpload_S3_AWSAccessKeyId": "Access Key",
+ "FileUpload_S3_AWSSecretAccessKey": "Secret Key",
+ "FileUpload_S3_Bucket": "Bucket Name",
"FileUpload_S3_BucketURL": "Bucket URL",
"FileUpload_S3_CDN": "Domini CDN per descàrregues",
+ "FileUpload_S3_ForcePathStyle": "Force Path Style",
"FileUpload_S3_Region": "Regió S3",
+ "FileUpload_S3_SignatureVersion": "Signature Version",
"FileUpload_S3_URLExpiryTimeSpan": "Caducitat de les URL",
"FileUpload_S3_URLExpiryTimeSpan_Description": "Temps després el qual les adreces d'Amazon S3 generades deixaran de ser vàlides (en segons). Si s'estableix a menys de 5 segons, aquest camp serà ignorat.",
"FileUpload_Storage_Type": "Tipus d'emmagatzematge",
+ "First_Channel_After_Login": "Primer canal després del login",
"Flags": "Indicadors",
"Follow_social_profiles": "Segueix els nostres perfils, fes-nos un fork a GitHub i comparteix la teva opinió sobre Rocket.Chat al nostre tauler de Trello.",
+ "Fonts": "Fonts",
"Food_and_Drink": "Menjar i beure",
"Footer": "Peu de pàgina",
+ "Footer_Direct_Reply": "Peu quan resposta directa està activa",
"For_your_security_you_must_enter_your_current_password_to_continue": "Per a la seva seguretat, ha de tornar a introduir la contrasenya per continuar",
+ "force-delete-message": "Forçar esborrar missatge",
+ "force-delete-message_description": "Permís per esborrar un missatge ignorant totes les restriccions",
"Force_Disable_OpLog_For_Cache": "Força la inhabilitació de OpLog per la cache",
"Force_Disable_OpLog_For_Cache_Description": "No s'utilitzarà OpLog per sincronitzar la cache tot i estar disponible",
"Force_SSL": "Força SSL",
"Force_SSL_Description": "*Atenció!* _Force SSL_ mai ha de ser usat amb servidor intermediari invers. Si s'utilitza un proxy invers, s'ha de fer la redirecció AL PROXY. Aquesta opció existeix per a les instal·lacions tipus Heroku, que no permeten la configuració de redireccions al proxy invers.",
"Forgot_password": "No recordes la contrasenya?",
+ "Forgot_Password_Description": "És possible utilitzar els marcadors: [Forgot_Password_Url] per a l'adreça URL de recuperació de contrasenya. [name], [fname], [lname] per al nom complet de l'usuari, nom o cognom, respectivament. [email] per a l'adreça de correu electrònic de l'usuari. [Site_Name] i [Site_URL] pel nom del lloc web i de l'adreça URL, respectivament. ",
+ "Forgot_Password_Email": "Fes clic aquí per restablir la teva contrasenya.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Recuperació de contrasenya",
+ "Forgot_password_section": "No recordo la contrasenya",
"Forward": "Remetre",
"Forward_chat": "Remetre xat",
"Forward_to_department": "Remetre al departament",
@@ -554,17 +735,42 @@
"Give_a_unique_name_for_the_custom_oauth": "Estableix un nom únic per al OAuth personalitzat",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Bateja l'aplicació. El nom escollit serà visible als usuaris.",
"Global": "Global",
+ "Google_Vision_usage_limit_exceeded": "S'ha excedit el límit d'ús de Google Vision",
+ "GoogleCloudStorage": "Emmagatzematge Google Cloud",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "Arxiu JSON amb la clau del compte de servei (\"Service account key\"). Pots trobar més informació [aquí](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "ID de Google Tag Manager",
+ "GoogleVision_Block_Adult_Images": "Bloqueja imatges per a adults",
+ "GoogleVision_Block_Adult_Images_Description": "El bloqueig d'imatges per a adults no funcionarà una vegada s'hagi arribat al límit mensual.",
+ "GoogleVision_Current_Month_Calls": "Nombre trucades mes actual",
+ "GoogleVision_Enable": "Activa Google Vision",
+ "GoogleVision_Max_Monthly_Calls": "Nombre màxim trucades mensuals",
+ "GoogleVision_Max_Monthly_Calls_Description": "Utilitza 0 per il·limitat",
+ "GoogleVision_ServiceAccount": "Compte del servei Google Vision",
+ "GoogleVision_ServiceAccount_Description": "Crea una server key (en format JSON) i enganxa el contingut JSON aquí",
+ "GoogleVision_Type_Document": "Detecció de documents de text",
+ "GoogleVision_Type_Faces": "Detecció de cares",
+ "GoogleVision_Type_Labels": "Detecció d'etiquetes",
+ "GoogleVision_Type_Landmarks": "Detecció geogràfica",
+ "GoogleVision_Type_Logos": "Detecció de logos",
+ "GoogleVision_Type_Properties": "Detecció de propietats (color)",
+ "GoogleVision_Type_SafeSearch": "Detecció SafeSearch",
+ "GoogleVision_Type_Similar": "Cerca imatges similars",
+ "Group_mentions_only": "Només mencions de grup",
"Guest_Pool": "Llista de clients",
"Hash": "Hash",
"Header": "Encapçalament",
+ "Header_and_Footer": "Encapçalament i peu ",
+ "Helpers": "Ajuda",
+ "Hex_Color_Preview": "Previsualització del color",
"Hidden": "Ocult",
"Hide_Avatars": "Oculta avatars",
"Hide_flextab": "Amaga la barra lateral dreta amb un clic",
"Hide_Group_Warning": "Segur que voleu ocultar el grup \"%s\"?",
"Hide_Private_Warning": "Segur que voleu ocultar la discussió amb \"%s\"?",
+ "Hide_roles": "Amaga rols",
"Hide_room": "Oculta sala",
"Hide_Room_Warning": "Segur que voleu ocultar la sala \"%s\"?",
+ "Hide_Unread_Room_Status": "Amaga l'estat de sales no llegides",
"Hide_usernames": "Oculta els noms d'usuari",
"Highlights": "Ressalta",
"Highlights_How_To": "Per ser notificat quan algú esmenta una paraula o frase, afegeix-la aquí. Es poden separar les paraules o frases amb comes. No es distingeix entre majúscules i minúscules.",
@@ -579,23 +785,30 @@
"How_responsive_was_the_chat_agent": "Heu rebut respostes ràpides?",
"How_satisfied_were_you_with_this_chat": "Ha quedat satisfet amb aquesta conversa?",
"How_to_handle_open_sessions_when_agent_goes_offline": "Què fer amb les sessions obertes quan l'agent es posa fora de línia",
+ "If_this_email_is_registered": "Si l'adreça de correu-e ja està registrada, t'enviarem instruccions sobre com restablir la contrasenya. Si no reps el missatge en breu, si us plau torna i reintenta-ho.",
"If_you_are_sure_type_in_your_password": "Si n'està segur escrigui la contrasenya:",
"If_you_are_sure_type_in_your_username": "Si n'està segur escrigui el seu nom d'usuari:",
+ "Iframe_Integration": "Integració Iframe",
"Iframe_Integration_receive_enable": "Activa recepció",
"Iframe_Integration_receive_enable_Description": "Permetre que la finestra pare enviï ordres a Rocket.Chat.",
"Iframe_Integration_receive_origin": "Rebre orígens",
- "Iframe_Integration_receive_origin_Description": "Només les pàgines de les quals es proporciona l'origen podran enviar ordres o `*` per a totes. Es poden utilitzar múltiples valors separats per `,`. Exemple `http://localhost,https://localhost`",
+ "Iframe_Integration_receive_origin_Description": "Origens amb prefix del protocol, separats per comes, dels quals es permet rebre comandes. Exemple 'http://localhost, https://localhost', o * per permetre rebre de qualsevol lloc.",
"Iframe_Integration_send_enable": "Activa enviament",
"Iframe_Integration_send_enable_Description": "Envia esdeveniments a la finestra pare",
"Iframe_Integration_send_target_origin": "Envia l'origen a l'objectiu",
- "Iframe_Integration_send_target_origin_Description": "Només les pàgines amb l'origen proporcionat podran rebre esdeveniments o `*` per a totes. Exemple `http://localhost`",
+ "Iframe_Integration_send_target_origin_Description": "Origens amb prefix del protocol on les comandes són enviades. Exemple 'https://localhost', o * per permetre enviar a qualsevol lloc.",
+ "IMAP_intercepter_already_running": "L'interceptador IMAP ja està executant-se",
+ "IMAP_intercepter_Not_running": "L'interceptador IMAP no està executant-se",
+ "Impersonate_user": "Suplantar usuari",
+ "Impersonate_user_description": "Quan s'activa, la integració publica com a l'usuari que ha desencadenat la integració",
+ "Import": "Importa",
"Importer_Archived": "Arxivat",
"Importer_CSV_Information": "L'importador CSV requereix un format específic, si us plau llegiu la documentació sobre com estructurar l'arxiu .zip:",
- "Importer_HipChatEnterprise_Information": "L'arxiu pujat ha de ser un tar.gz desencriptat. Si us plau, llegiu la documentació per a més informació:",
- "Importer_HipChatEnterprise_BetaWarning": "Tingueu en compte que aquest sistema d'importació encara està en desenvolupament. Si us plau, notifiqueu-nos a GitHub els errors que es produeixin:",
"Importer_done": "Importació completa!",
"Importer_finishing": "Finalitza la importació.",
"Importer_From_Description": "Importa les dades de __from__ a Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Tingueu en compte que aquest sistema d'importació encara està en desenvolupament. Si us plau, notifiqueu-nos a GitHub els errors que es produeixin:",
+ "Importer_HipChatEnterprise_Information": "L'arxiu pujat ha de ser un tar.gz desencriptat. Si us plau, llegiu la documentació per a més informació:",
"Importer_import_cancelled": "Importació cancel·lada.",
"Importer_import_failed": "S'ha produït un error durant la importació.",
"Importer_importing_channels": "Important els canals.",
@@ -612,7 +825,8 @@
"Importer_setup_error": "S'ha produït un error en configurar l'importador.",
"Importer_Source_File": "Selecció de fitxer d'origen",
"Incoming_Livechats": "LiveChats entrants",
- "inline_code": "inline_code",
+ "Incoming_WebHook": "WebHook entrant",
+ "inline_code": "codi inline",
"Install_Extension": "Instal·lar complement",
"Install_FxOs": "Instal·lar el Rocket.Chat al Firefox",
"Install_FxOs_done": "Perfecte! Ja pots utilitzar el Rocket.Chat mitjançant la icona de l'escriptori.",
@@ -620,19 +834,51 @@
"Install_FxOs_follow_instructions": "Si us plau, confirma la instal·lació de l'aplicació al teu dispositiu (polsi \"Instal·lar\" quan se us demani).",
"Installation": "Instal·lació",
"Installed_at": "Instal·lat a",
+ "Instance_Record": "Registre d'instància",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instruccions als visitants, ompliu el formulari per enviar un missatge",
- "Impersonate_user": "Suplantar usuari",
- "Impersonate_user_description": "Quan s'activa, la integració publica com a l'usuari que ha desencadenat la integració",
"Integration_added": "La integració s'ha afegit",
+ "Integration_Advanced_Settings": "Configuració avançada",
+ "Integration_History_Cleared": "L'historial d'integracions s'ha esborrat correctament",
"Integration_Incoming_WebHook": "Integració WebHook d'entrada",
"Integration_New": "Nova integració",
"Integration_Outgoing_WebHook": "Integració WebHook de sortida",
- "Integration_updated": "La integració s'ha actualitzat",
+ "Integration_Outgoing_WebHook_History": "Historial d'integracions WebHook de sortida",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Dades passades a la integració",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Dades passades a l'adreça URL",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Error Stacktrace",
+ "Integration_Outgoing_WebHook_History_Http_Response": "Resposta HTML",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "Error HTTP de resposta",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Missatges enviats durant el pas de preparació",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Missatges enviats durant el procés de la resposta",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Quan ha acabat o emès un error",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Quan s'ha disparat la integració",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "Darrer pas del disparador",
+ "Integration_Outgoing_WebHook_No_History": "Aquesta integració WebHook de sortida encara no té cap historial registrat.",
+ "Integration_Retry_Count": "Comptador de reintents",
+ "Integration_Retry_Count_Description": "Quantes vegades s'ha de reintentar la integració si la petició a l'adreça URL falla?",
+ "Integration_Retry_Delay": "Temps de reintent",
+ "Integration_Retry_Delay_Description": "Quin algorisme de retard de reintent s'ha d'utilitzar? 10^x o 2^x o x*2",
+ "Integration_Retry_Failed_Url_Calls": "Reintenta peticions d'URL fallades",
+ "Integration_Retry_Failed_Url_Calls_Description": "Si la petició a l'adreça URL falla, la integració ha d'esperar un temps raonable abans de reintentar-la?",
+ "Integration_Run_When_Message_Is_Edited": "Executa en edicions",
+ "Integration_Run_When_Message_Is_Edited_Description": "Aquesta integració s'ha d'executar quan el missatge s'edita? Desactivar aquesta opció farà que la integració només s'executi en missatges nous .",
+ "Integration_updated": "La integració s'ha actualitzat.",
+ "Integration_Word_Trigger_Placement": "Posició indeterminada de paraula",
+ "Integration_Word_Trigger_Placement_Description": "S'hauria d'activar el disparador quan la paraula es troba en un lloc de la frase fora del començament?",
"Integrations": "Integracions",
"Integrations_for_all_channels": "Introdueix all_public_channels per escoltar a totes les sales públiques, all_private_groups per escoltar a tots els grups privats i all_direct_messages per escoltar tots els missatges directes.",
+ "Integrations_Outgoing_Type_FileUploaded": "Arxiu pujat",
+ "Integrations_Outgoing_Type_RoomArchived": "Sala arxivada",
+ "Integrations_Outgoing_Type_RoomCreated": "Sala creada (pública i privada)",
+ "Integrations_Outgoing_Type_RoomJoined": "L'usuari ha entrat a la sala",
+ "Integrations_Outgoing_Type_RoomLeft": "L'usuari ha sortit de la sala",
+ "Integrations_Outgoing_Type_SendMessage": "Missatge enviat",
+ "Integrations_Outgoing_Type_UserCreated": "Usuari creat",
"InternalHubot": "Hubot intern",
+ "InternalHubot_PathToLoadCustomScripts": "Carpeta des d'on carregar els scripts",
+ "InternalHubot_reload": "Recarrega els scripts",
"InternalHubot_ScriptsToLoad": "Seqüències d'ordres (scripts) per carregar",
- "InternalHubot_ScriptsToLoad_Description": "Si us plau, introduiu una llista separada per comes de scripts de https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_ScriptsToLoad_Description": "Si us plau, introduiu una llista separada per comes de scripts per carregar des de la carpeta personalitzada",
"InternalHubot_Username_Description": "Ha de ser un nom d'usuari vàlid d'un bot registrat al servidor.",
"Invalid_confirm_pass": "La confirmació de la contrasenya no coincideix amb la contrasenya",
"Invalid_email": "L'adreça de correu-e és invàlida",
@@ -641,42 +887,50 @@
"Invalid_name": "El nom no ha d'estar buit",
"Invalid_notification_setting_s": "Configuració de notificació invàlida: %s",
"Invalid_pass": "La contrasenya no ha d'estar buida",
- "Invalid_room_name": "%s no és un nom de sala vàlid, utilitza només lletres, números, guions i guions baixos",
+ "Invalid_room_name": "%s no és un nom de sala vàlid",
"Invalid_secret_URL_message": "L'adreça URL proporcionada no és vàlida.",
+ "Invalid_setting_s": "Opció invàlida: %s",
+ "Invalid_two_factor_code": "Codi de dos factors invàlid",
"invisible": "invisible",
"Invisible": "Invisible",
+ "Invitation": "Invitació",
"Invitation_HTML": "HTML de la invitació",
"Invitation_HTML_Default": "Se us ha convidat a [Site_Name] Aneu a [Site_URL] i proveu la millor solució de col·laboració a distància de codi lliure!
",
"Invitation_HTML_Description": "Podeu utilitzar els següents marcadors: [email] per a l'adreça del receptor del missatge. [Site_Name] i [Site_URL] per al nom de l'aplicació i l'adreça URL, respectivament. ",
"Invitation_Subject": "Assumpte de la invitació",
"Invitation_Subject_Default": "Se us ha convidat a [Site_Name]",
"Invite_user_to_join_channel": "Convidar un usuari a unir-se a aquest canal",
+ "Invite_user_to_join_channel_all_from": "Invita a tots els usuaris del canal [#channel] a unir-se a aquest canal",
+ "Invite_user_to_join_channel_all_to": "Invita a tots els usuaris d'aquest canal a unir-se a [#channel]",
"Invite_Users": "Convidar usuaris",
- "is_also_typing": "també està escrivint",
- "is_also_typing_female": "també està escrivint",
- "is_also_typing_male": "també està escrivint",
- "is_typing": "està escrivint",
- "is_typing_female": "està escrivint",
- "is_typing_male": "està escrivint",
"IRC_Channel_Join": "Resposta de la comanda JOIN.",
"IRC_Channel_Leave": "Resposta de la comanda PART.",
- "IRC_Description": "L'IRC (Internet Relay Chat) és una eina de comunicació per a grups basada en text. Els usuaris s'uneixen a sales/canals de xat per a comunicar-se. L'IRC també suporta missatges privats entre usuaris i compartició de fitxers. Aquest paquet integra aquestes funcionalitats amb Rocket.Chat.",
- "IRC_Enabled": "Integrar suport IRC. Canviar aquest valor requereix reiniciar el Rocket.Chat.",
- "IRC_Private_Message": "Resposta de la comanda PRIVMSG.",
"IRC_Channel_Users": "Resposta de la comanda NAMES.",
"IRC_Channel_Users_End": "Final de la resposta de la comanda NAMES.",
+ "IRC_Description": "L'IRC (Internet Relay Chat) és una eina de comunicació per a grups basada en text. Els usuaris s'uneixen a sales/canals de xat per a comunicar-se. L'IRC també suporta missatges privats entre usuaris i compartició de fitxers. Aquest paquet integra aquestes funcionalitats amb Rocket.Chat.",
+ "IRC_Enabled": "Integrar suport IRC. Canviar aquest valor requereix reiniciar el Rocket.Chat.",
"IRC_Hostname": "Servidor d'IRC on connectar.",
"IRC_Login_Fail": "Resposta en cas de connexió al servidor d'IRC fallida.",
"IRC_Login_Success": "Resposta en cas de connexió al servidor d'IRC reeixida.",
"IRC_Message_Cache_Size": "Límit de memòria d'intercanvi (cache) per manegar els missatges sortints.",
"IRC_Port": "Port on unir-se al servidor d'IRC.",
+ "IRC_Private_Message": "Resposta de la comanda PRIVMSG.",
"IRC_Quit": "Resposta en sortir de la sessió d'IRC.",
+ "is_also_typing": "també està escrivint",
+ "is_also_typing_female": "també està escrivint",
+ "is_also_typing_male": "també està escrivint",
+ "is_typing": "està escrivint",
+ "is_typing_female": "està escrivint",
+ "is_typing_male": "està escrivint",
"It_works": "Funciona",
"italics": "cursiva",
"Jitsi_Chrome_Extension": "ID d'extensió del Chrome",
"Jitsi_Enable_Channels": "Activa als canals",
"join": "Unir-se",
+ "join-without-join-code": "Unir-se sense el codi",
+ "join-without-join-code_description": "Permís per unir-se a canals amb codi d'unió actiu sense tenir-lo",
"Join_audio_call": "Unir-se a la trucada",
+ "Join_Chat": "Uneix-te al xat",
"Join_default_channels": "Unir-se als canals predeterminats",
"Join_the_Community": "Uneix-te a la comunitat",
"Join_the_given_channel": "Unir-se al canal proporcionat",
@@ -692,6 +946,19 @@
"Katex_Enabled_Description": "Permetre l'ús de katex per a la composició tipogràfica de matemàtiques en els missatges",
"Katex_Parenthesis_Syntax": "Permetre Parèntesi Sintaxi",
"Katex_Parenthesis_Syntax_Description": "Permetre l'ús de \\ [bloc katex \\] \\ sintaxi i (en línia katex \\)",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Edita missatge anterior",
+ "Keyboard_Shortcuts_Keys_1": "Ctrl + p ",
+ "Keyboard_Shortcuts_Keys_2": "Fletxa amunt ",
+ "Keyboard_Shortcuts_Keys_3": "Cmd (o Alt ) + Fletxa esquerra ",
+ "Keyboard_Shortcuts_Keys_4": "Cmd (o Alt ) + Fletxa amunt ",
+ "Keyboard_Shortcuts_Keys_5": "Cmd (o Alt ) + Fletxa dreta ",
+ "Keyboard_Shortcuts_Keys_6": "Cmd (o Alt ) + Fletxa avall ",
+ "Keyboard_Shortcuts_Keys_7": "Shift + Enter ",
+ "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "Moure's al principi del missatge",
+ "Keyboard_Shortcuts_Move_To_End_Of_Message": "Moure's al final del missatge",
+ "Keyboard_Shortcuts_New_Line_In_Message": "Nova línia al camp d'entrada de missatge",
+ "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Canal obert / Cerca d'usuari",
+ "Keyboard_Shortcuts_Title": "Dreceres de teclat",
"Knowledge_Base": "Centre de suport",
"Label": "Etiqueta",
"Language": "Idioma",
@@ -710,32 +977,39 @@
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
"LDAP_Connect_Timeout": "Temps d'espera connexió (ms)",
- "LDAP_Custom_Domain_Search": "Domini de cerca personalitzat",
- "LDAP_Custom_Domain_Search_Description": "Objecte JSON per definir el bind i la informació de connexió, segons el format: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domini predeterminat",
"LDAP_Description": "LDAP és una base de dades jeràrquica que moltes empreses utilitzen per proporcionar un inici de sessió únic –una eina per tenir una sola contrasenya a múltiples llocs web i serveis. Per a exemples i informació sobre configuracions més avançades, consulteu la nostra wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Domini base",
- "LDAP_Domain_Base_Description": "Nom distingit (Distinguished Name, DN), complet i qualificat d'una branca LDAP on voleu cercar usuaris i grups. Se'n poden afegir tants com es vulgui, però cada grup s'ha de definir al mateix domini base que els usuaris que hi pertanyen. Si especifica grups d'usuaris restringits, només els usuaris que pertanyen a aquests grups seran considerats. Recomanem que s'especifici el nivell superior de l'arbre de directoris LDAP com a domini base i que s'utilitzi el filtre de cerca per controlar l'accés.",
- "LDAP_Domain_Search_Filter": "Filtre de cerca al domini",
- "LDAP_Domain_Search_Filter_Description": "Si s'especifica, només els usuaris que compleixin aquest filtre podran iniciar sessió. Si no s'especifica cap filtre, tots els usuaris del domini base podran fer-ho. Exemple per Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Exemple per OpenLDAP (cerca de patró extensible) `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Categoria d'objecte del domini de cerca",
- "LDAP_Domain_Search_Object_Category_Description": "L'*objectCategory* que identifica als teus usuaris. Deixar buit per *OpenLDAP*. Exemple: `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Classe d'objecte del domini de cerca",
- "LDAP_Domain_Search_Object_Class_Description": "La classe d'objecte (*Object Class*) que identifica els usuaris. Per exemple, `organizationalPerson`,`user`,`inetOrgPerson`, etcètera.",
- "LDAP_Domain_Search_Password": "Contrasenya del domini de cerca",
- "LDAP_Domain_Search_Password_Description": "Contrasenya de l'usuari del domini de cerca.",
- "LDAP_Domain_Search_User": "Usuari del domini de cerca",
- "LDAP_Domain_Search_User_Description": "Usuari LDAP que fa cerques d'usuari per identificar altres usuaris quan inicien sessió. Aquest és un compte que s'acostuma a crear específicament per a fer les integracions de tercers. Utilitza un nom complet i qualificat, com `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "ID d'usuari del domini de cerca",
- "LDAP_Domain_Search_User_ID_Description": "L'atribut LDAP que identifica a l'usuari quan intenta l'inici de sessió. Aquest camp ha de ser `sAMAccountName` per a la majoria de les instal·lacions d'Active Directory, però pot ser `uid` per altres solucions LDAP, com OpenLDAP. Podeu fer servir `mail` per identificar els usuaris per correu electrònic o qualsevol altre atribut que vulgueu. Es poden utilitzar diversos valors separats per comes per permetre als usuaris accedir utilitzant diversos identificadors com nom d'usuari o adreça de correu-e.",
+ "LDAP_BaseDN": "Base DN",
+ "LDAP_BaseDN_Description": "Nom distingit (Distinguished Name, DN), complet i qualificat d'una branca LDAP on voleu cercar usuaris i grups. Se'n poden afegir tants com es vulgui, però cada grup s'ha de definir al mateix domini base que els usuaris que hi pertanyen. Si especifica grups d'usuaris restringits, només els usuaris que pertanyen a aquests grups seran considerats. Recomanem que s'especifici el nivell superior de l'arbre de directoris LDAP com a domini base i que s'utilitzi el filtre de cerca per controlar l'accés.",
+ "LDAP_User_Search_Field": "Camp de cerca",
+ "LDAP_User_Search_Field_Description": "L'atribut LDAP que identifica a l'usuari quan intenta l'inici de sessió. Aquest camp ha de ser `sAMAccountName` per a la majoria de les instal·lacions d'Active Directory, però pot ser `uid` per altres solucions LDAP, com OpenLDAP. Podeu fer servir `mail` per identificar els usuaris per correu electrònic o qualsevol altre atribut que vulgueu. Es poden utilitzar diversos valors separats per comes per permetre als usuaris accedir utilitzant diversos identificadors com nom d'usuari o adreça de correu-e.",
+ "LDAP_User_Search_Filter": "Filter",
+ "LDAP_User_Search_Filter_Description": "Si s'especifica, només els usuaris que compleixin aquest filtre podran iniciar sessió. Si no s'especifica cap filtre, tots els usuaris del domini base podran fer-ho. Exemple per Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Exemple per OpenLDAP (cerca de patró extensible) `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_User_Search_Scope": "Scope",
+ "LDAP_Authentication": "Activa",
+ "LDAP_Authentication_Password": "Contrasenya",
+ "LDAP_Authentication_UserDN": "User DN",
+ "LDAP_Authentication_UserDN_Description": "Usuari LDAP que fa cerques d'usuari per identificar altres usuaris quan inicien sessió. Aquest és un compte que s'acostuma a crear específicament per a fer les integracions de tercers. Utilitza un nom complet i qualificat, com `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "Activa",
- "LDAP_Enable_Description": "Intentar utilitzar LDAP com a mètode de s'autentiquen",
+ "LDAP_Enable_Description": "Intentar utilitzar LDAP com a mètode d'autenticació",
"LDAP_Encryption": "Xifrat",
"LDAP_Encryption_Description": "Mètode de xifrat utilitzat per a la comunicació segura cap al servidor LDAP. Alguns exemples 'sense xifrat', 'SSL / LDAPS (xifrat des de l'inici), i' StartTLS '(actualitzar a comunicacions xifrades una vegada connectat).",
+ "LDAP_Internal_Log_Level": "Nivell de log intern",
+ "LDAP_Group_Filter_Enable": "Activa el filtre de grups d'usuaris LDAP",
+ "LDAP_Group_Filter_Enable_Description": "Restringeix l'accés a usuaris d'un grup LDAP Útil per a servidors OpenLDAP sense capes que permetin filtres *memberOf*",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Atribut ID de grup (Group ID)",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "Exemple: *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute": "Atribut Membre de grup (Group Member)",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "Exemple: *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format": "Format Membre de grup (Group Member)",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "Exemple: *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Nom del grup",
+ "LDAP_Group_Filter_Group_Name_Description": "Nom del grup on pertany l'usuari",
+ "LDAP_Group_Filter_ObjectClass": "Grup ObjectClass",
+ "LDAP_Group_Filter_ObjectClass_Description": "L'*objectclass* que identifica als grups. Exemple: OpenLDAP:groupOfUniqueNames",
"LDAP_Host": "Amfitrió (host) ",
"LDAP_Host_Description": "Amfitrió (host) LDAP, exemple: `ldap.exemple.com` o `10.0.0.30`.",
"LDAP_Idle_Timeout": "Temps d'espera inactiu (ms)",
- "LDAP_Import_Users": "Importa usuaris LDAP",
"LDAP_Import_Users_Description": "Si s'activa, el procés de sincronització importarà tots els usuaris LDAP *Compte!* Cal especificar un filtre de cerca per no importar més usuaris del compte.",
"LDAP_Login_Fallback": "Inici de sessió alternativa (fallback)",
"LDAP_Login_Fallback_Description": "Si l'inici de sessió LDAP no funciona, intenta iniciar-la amb el sistema de comptes per defecte/local. Útil si el servei LDAP no està disponible per algun motiu.",
@@ -743,32 +1017,18 @@
"LDAP_Merge_Existing_Users_Description": "*Atenció!* Quan s'importa un usuari LDAP i ja existeix un usuari amb el mateix nom d'usuari, es canviarà la informació LDAP i el password de l'usuari ja existent.",
"LDAP_Port": "Port",
"LDAP_Port_Description": "Port per accedir a LDAP. Ex. `389` o `636` per LDAPS",
+ "LDAP_Reconnect": "Reconnecta",
"LDAP_Reject_Unauthorized": "Rebutja no autoritzat",
"LDAP_Sync_User_Avatar": "Sincronitzar avatar de l'usuari",
"LDAP_Sync_User_Data": "Sincronitzar dades d'usuari",
- "LDAP_Sync_User_Data_Description": "Mantenir les dades de l'usuari sincronitzades amb el servidor quan s'identifiqui (ex: nom, adreça de correu, etcètera).",
+ "LDAP_Sync_User_Data_Description": "Mantenir les dades de l'usuari sincronitzades amb el servidor **quan s'identifiqui** o en **sincronització en background** (ex: nom, adreça de correu, etcètera).",
"LDAP_Sync_User_Data_FieldMap": "Mapatge de camps de dades d'usuari",
- "LDAP_Sync_User_Data_FieldMap_Description": "Configura com els camps del compte d'usuari (com el de correu-e) s'omplen des del registre LDAP (un cop trobat). A tall d'exemple, `{\"cn\":\"name\", \"mail\":\"email\"}` triarà el nom des de l'atribut `cn`, i l'adreça-e des de l'atribut `mail`. Els camps disponibles `name` i `email`.",
- "LDAP_Sync_Users": "Sincronització d'usuaris",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configura com els camps del compte d'usuari (com el de correu-e) s'omplen des del registre LDAP (un cop trobat). A tall d'exemple, `{\"cn\":\"name\", \"mail\":\"email\"}` triarà el nom des de l'atribut `cn`, i l'adreça-e des de l'atribut `mail`. Addicionalment, és possible utilitzar variables, per exemple: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` utilitza una combinació del nom de pila i del cognom per al camp `name` de l'usuari de rocket chat. Camps disponibles a Rocket.Chat: `name`, `email` i `customFields`.",
"LDAP_Test_Connection": "Prova la connexió",
"LDAP_Unique_Identifier_Field": "Camp d'identificador únic",
"LDAP_Unique_Identifier_Field_Description": "Aquest camp s'utilitzarà per vincular l'usuari LDAP amb l'usuari Rocket.Chat. Pot proporcionar diversos valors separats per coma per intentar obtenir el valor del registre LDAP. El valor per defecte és `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Utilitza el domini de cerca personalitzat",
- "LDAP_Use_Custom_Domain_Search_Description": "Escriviu el vostre propi filtre per cercar usuaris al servidor LDAP.",
"LDAP_Username_Field": "Camp del nom d'usuari",
"LDAP_Username_Field_Description": "El camp que s'utilitzarà com a nom d'usuari (*username*) per als nous usuaris. Deixar en blanc per a utilitzar el nom d'usuari proporcionat durant l'inici de sessió. També es poden utilitzar plantilles d'etiqueta, com `#{givenName}.#{sn}`. El valor per defecte és `sAMAccountName`.",
- "LDAP_Group_Filter_Enable": "Activa el filtre de grups d'usuaris LDAP",
- "LDAP_Group_Filter_Enable_Description": "Restringeix l'accés a usuaris d'un grup LDAP Útil per a servidors OpenLDAP sense capes que permetin filtres *memberOf*",
- "LDAP_Group_Filter_ObjectClass": "Grup ObjectClass",
- "LDAP_Group_Filter_ObjectClass_Description": "L'*objectclass* que identifica als grups. Exemple: OpenLDAP:groupOfUniqueNames",
- "LDAP_Group_Filter_Group_Id_Attribute": "Atribut ID de grup (Group ID)",
- "LDAP_Group_Filter_Group_Id_Attribute_Description": "Exemple: *OpenLDAP:*cn",
- "LDAP_Group_Filter_Group_Member_Attribute": "Atribut Membre de grup (Group Member)",
- "LDAP_Group_Filter_Group_Member_Attribute_Description": "Exemple: *OpenLDAP:*uniqueMember",
- "LDAP_Group_Filter_Group_Member_Format": "Format Membre de grup (Group Member)",
- "LDAP_Group_Filter_Group_Member_Format_Description": "Exemple: *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
- "LDAP_Group_Filter_Group_Name": "Nom del grup",
- "LDAP_Group_Filter_Group_Name_Description": "Nom del grup on pertany l'usuari",
"Least_Amount": "Quantitat mínima",
"Leave_Group_Warning": "Segur que vols abandonar el grup \"%s\"?",
"Leave_Private_Warning": "Segur que vols sortir de la conversa amb \"%s\"?",
@@ -779,8 +1039,7 @@
"List_of_Channels": "Llista de canals",
"List_of_Direct_Messages": "Llista de missatges directes",
"Livechat_agents": "Agents de xat en viu",
- "Livechat_AllowedDomainsList": "Dominis permesos al xat en directe",
- "Domains_allowed_to_embed_the_livechat_widget": "Llista separada per comes dels dominis on es permet incloure el xat en viu. Deixeu en blanc per permetre'ls tots.",
+ "Livechat_AllowedDomainsList": "Dominis permesos al xat en viu",
"Livechat_Dashboard": "Tauler de xat en viu",
"Livechat_enabled": "Xat en viu actiu",
"Livechat_forward_open_chats": "Reenviament de xats oberts",
@@ -801,7 +1060,7 @@
"Load_more": "Carrega'n més",
"Loading...": "Carregant...",
"Loading_more_from_history": "Carregant-ne més des de l'historial",
- "Loading_suggestion": "Carregant suggeriments...",
+ "Loading_suggestion": "Carregant suggeriments",
"Localization": "Localització",
"Log_Exceptions_to_Channel": "Registra excepcions al canal",
"Log_Exceptions_to_Channel_Description": "Canal que rebrà les excepcions capturades. Deixar en blanc per ignorar-les.",
@@ -814,6 +1073,8 @@
"Login_with": "Inicia sessió amb %s",
"Logout": "Tanca sessió",
"Logout_Others": "Tanca les sessions obertes en altres llocs",
+ "mail-messages": "Missatges via correu-e",
+ "mail-messages_description": "Permís per utilitzar l'opció d'enviament de missatges via correu-e",
"Mail_Message_Invalid_emails": "S'ha proporcionat almenys una adreça de correu-e invàlida: %s",
"Mail_Message_Missing_to": "Ha de seleccionar almenys un usuari o proporcionar almenys una adreça de correu electrònic, separades per comes.",
"Mail_Message_No_messages_selected_select_all": "No s'ha seleccionat cap missatge. Vols seleccionar tots els missatges visibles?",
@@ -824,6 +1085,19 @@
"Mailer_body_tags": "És necessari utilitzar [unsubscribe] per a l'enllaç d'anul·lació de la subscripció. És possible utilitzar [name], [fname], [lname] per al nom complet de l'usuari, nom o cognom, respectivament. També [email] per a l'adreça de correu electrònic de l'usuari.",
"Mailing": "Enviament",
"Make_Admin": "Fes admin",
+ "Make_sure_you_have_a_copy_of_your_codes": "Assegura't de tenir una còpia dels teus codis: __codes__ Si perds accés a la teva app d'autenticació, pots utilitzar un d'aquests codis per entrar.",
+ "manage-assets": "Gestionar recursos",
+ "manage-assets_description": "Permís per gestionar els recursos del servidor",
+ "manage-emoji": "Gestionar emoticones",
+ "manage-emoji_description": "Permís per gestionar les emoticones del servidor",
+ "manage-integrations": "Gestionar les integracions",
+ "manage-integrations_description": "Permís per gestionar les integracions del servidor",
+ "manage-oauth-apps": "Gestionar apps Oauth",
+ "manage-oauth-apps_description": "Permís per gestionar les apps Oauth del servidor",
+ "manage-own-integrations": "Gestionar les pròpies integracions",
+ "manage-own-integrations_description": "Permís per permetre als usuaris crear i editar les seves pròpies integracions o webhooks",
+ "manage-sounds": "Gestionar sons",
+ "manage-sounds_description": "Permís per gestionar els sons del servidor",
"Manager_added": "Supervisor afegit",
"Manager_removed": "Supervisor eliminat",
"Managing_assets": "Gestió de recursos",
@@ -834,18 +1108,23 @@
"MapView_GMapsAPIKey_Description": "Es pot obtenir de la Google Developers Console gratuïtament.",
"Mark_as_read": "Marca llegit/s",
"Mark_as_unread": "Marca com a no llegit",
- "Markdown_Headers": "Encapçalaments Markdown",
+ "Markdown_Headers": "Permetre encapçalaments Markdown als missatges",
+ "Markdown_Parser": "Parsejador Markdown",
"Markdown_SupportSchemesForLink": "Markdown detecta scheme:// com a enllaç",
"Markdown_SupportSchemesForLink_Description": "Llista dels scheme:// permesos separats per comes",
"Max_length_is": "La llargada màxima és %s",
"Members_List": "Llista de membres",
+ "mention-all": "Mencionar tots",
+ "mention-all_description": "Permís per utilitzar la menció @all",
"Mentions": "Mencions",
"Mentions_default": "Mencions (per defecte)",
+ "Mentions_only": "Només mencions",
"Message": "Missatge",
"Message_AllowBadWordsFilter": "Permet el filtratge de paraulotes",
"Message_AllowDeleting": "Permet l'eliminació de missatges",
"Message_AllowDeleting_BlockDeleteInMinutes": "Bloqueja l'eliminació de missatges després de (n) minuts",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Introdueix 0 per desactivar el bloqueig.",
+ "Message_AllowDirectMessagesToYourself": "Permetre missatges directes al propi usuari",
"Message_AllowEditing": "Permet l'edició de missatges",
"Message_AllowEditing_BlockEditInMinutes": "Bloqueja l'edició de missatges després de (n) minuts",
"Message_AllowEditing_BlockEditInMinutesDescription": "Introdueix 0 per desactivar el bloqueig.",
@@ -856,6 +1135,9 @@
"Message_AllowUnrecognizedSlashCommand": "Permet /comandes no reconegudes",
"Message_AlwaysSearchRegExp": "Sempre cercar utilitzant RegExp",
"Message_AlwaysSearchRegExp_Description": "Recomanem activar-ho si el teu idioma no està suportat per la cerca de text MongoDB .",
+ "Message_Attachments": "Adjunts al missatge",
+ "Message_Attachments_GroupAttach": "Agrupa els botons d'adjuntar",
+ "Message_Attachments_GroupAttachDescription": "Això uneix les icones en un menú desplegable. Ocupen menys espai a la pantalla.",
"Message_AudioRecorderEnabled": "Gravadora d'àudio activa",
"Message_AudioRecorderEnabledDescription": "Requereix que els arxius de tipus 'audio/wav' siguin un tipus de fitxer vàlid dins les opcions de 'Pujar arxius'.",
"Message_BadWordsFilterList": "Afegir paraulotes a la llista negra",
@@ -875,13 +1157,17 @@
"Message_MaxAll": "Mida màxima de canal per al missatge ALL",
"Message_MaxAllowedSize": "Mida màxima de missatge",
"Message_pinning": "Fixació de missatges",
+ "Message_QuoteChainLimit": "Màxim nombre de cites encadenades",
"Message_removed": "Missatge eliminat",
+ "Message_sent_by_email": "Missatge enviat via correu-e",
"Message_SetNameToAliasEnabled": "Establir un nom d'usuari com àlies al missatge",
"Message_SetNameToAliasEnabled_Description": "Només si encara no s'ha establert àlies. Els àlies dels missatges antics no es canvien si l'usuari ha canviat el nom.",
"Message_ShowDeletedStatus": "Mostra l'estat 'eliminat'",
"Message_ShowEditedStatus": "Mostra l'estat 'editat'",
"Message_ShowFormattingTips": "Mostra suggeriments de formatació",
"Message_starring": "Destacar missatges",
+ "Message_TimeAndDateFormat": "Format de data i hora",
+ "Message_TimeAndDateFormat_Description": "Veure també: Moment.js ",
"Message_TimeFormat": "Format d'hora",
"Message_TimeFormat_Description": "Veure: Moment.js ",
"Message_too_long": "Missatge massa llarg",
@@ -890,8 +1176,8 @@
"Messages": "Missatges",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Els missatges enviats al WebHook d'entrada seran publicats aquí.",
"Meta": "Meta",
- "Meta_fb_app_id": "App ID de Facebook",
"Meta_custom": "Etiquetes Meta personalitzades",
+ "Meta_fb_app_id": "App ID de Facebook",
"Meta_google-site-verification": "Verificació del lloc web a Google (google-site-verification)",
"Meta_language": "Idioma",
"Meta_msvalidate01": "MSValidate.01",
@@ -899,37 +1185,47 @@
"Min_length_is": "La llargada mínima és %s",
"minutes": "minuts",
"Mobile": "Mòbil",
+ "Mobile_Notifications_Default_Alert": "Alerta per defecte notificacions mòbil",
"Monday": "dilluns",
"Monitor_history_for_changes_on": "Monitoritza l'historial per canvis a ",
"More_channels": "Més canals",
"More_direct_messages": "Més missatges directes",
"More_groups": "Més grups privats",
"More_unreads": "Més per llegir",
+ "Move_beginning_message": "`%s` - Anar al principi del missatge",
+ "Move_end_message": "`%s` - Anar al final del missatge",
"Msgs": "Missatges",
"multi": "multi",
+ "multi_line": "línia múltiple",
+ "mute-user": "Silenciar usuari",
+ "mute-user_description": "Permís per silenciar altres usuaris del mateix canal",
"Mute_someone_in_room": "Silenciar algú a la sala",
"Mute_user": "Silencia l'usuari",
"Muted": "Silenciat",
"My_Account": "El meu compte",
+ "My_location": "La meva localització",
"n_messages": "%s missatges",
"N_new_messages": "%s nous",
"Name": "Nom",
"Name_cant_be_empty": "El nom no pot estar buit",
"Name_of_agent": "Nom de l'agent",
"Name_optional": "Nom (opcional)",
+ "Name_Placeholder": "Sisplau, introdueix el teu nom...",
"Navigation_History": "Historial de navegació",
"New_Application": "Nova aplicació",
"New_Custom_Field": "Nou camp personalitzat",
"New_Department": "Nou departament",
"New_integration": "Nova integració",
+ "New_line_message_compose_input": "`%s` - Nova línia a l'entrada de missatge",
"New_logs": "Nous registres log",
"New_Message_Notification": "Nova notificació de missatges",
"New_messages": "Nous missatges",
"New_password": "Nova contrasenya",
+ "New_Password_Placeholder": "Sisplau, introdueix una nova contrasenya...",
"New_role": "Nou rol",
"New_Room_Notification": "Nova notificació de sala",
- "New_videocall_request": "Nova petició de vídeo trucada",
"New_Trigger": "Nou disparador",
+ "New_videocall_request": "Nova petició de vídeo trucada",
"No_available_agents_to_transfer": "No hi ha agents disponibles per a transferir",
"No_channel_with_name_%s_was_found": "No s'ha trobat cap canal amb el nom \"%s\" !",
"No_channels_yet": "Encara no ets a cap canal.",
@@ -937,13 +1233,14 @@
"No_Encryption": "Sense xifrat",
"No_group_with_name_%s_was_found": "No s'ha trobat cap grup privat amb el nom \"%s\" !",
"No_groups_yet": "Encara no tens cap grup privat.",
+ "No_integration_found": "No s'ha trobat cap integració amb l'id proporcionat.",
"No_livechats": "No tens cap xat en viu.",
"No_mentions_found": "Cap menció trobada",
"No_pinned_messages": "Cap missatge fixat.",
"No_results_found": "No s'han trobat resultats",
+ "No_snippet_messages": "Cap retall",
"No_starred_messages": "Cap missatge destacat.",
"No_such_command": "Comanda `/__command__` no trobada.",
- "No_snippet_messages": "Cap retall",
"No_user_with_username_%s_was_found": "No s'ha trobat cap usuari amb el nom \"%s\" !",
"Nobody_available": "Ningú disponible",
"Node_version": "Versió de Node",
@@ -954,10 +1251,14 @@
"Not_found_or_not_allowed": "No trobat o no permès",
"Nothing": "Res",
"Nothing_found": "No s'ha trobat res",
+ "Notification_Desktop_Default_For": "Mostra notificacions d'escriptori per",
"Notification_Duration": "Duració de la notificació",
+ "Notification_Mobile_Default_For": "Notificacions push mòbil per",
"Notifications": "Notificacions",
- "Notify_all_in_this_room": "Notifica a tothom d'aquest canal",
+ "Notifications_Muted_Description": "Si esculls silenciar-ho tot, no veuràs la sala destacada a la llista quan hi hagi nous missatges, excepte si són mencions. Silenciar les notificacions sobreescriurà les opcions de notificació.",
+ "Notifications_Sound_Volume": "Volum del so de notificacions",
"Notify_active_in_this_room": "Notifica als usuaris actius d'aquesta sala",
+ "Notify_all_in_this_room": "Notifica a tothom d'aquest canal",
"Num_Agents": "# d'agents",
"Number_of_messages": "Nombre de missatges",
"OAuth_Application": "Aplicació OAuth",
@@ -967,7 +1268,8 @@
"Off_the_record_conversation": "Conversa sense registre (off-the-record)",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "La conversa sense registre no està disponible per al teu navegador o dispositiu.",
"Office_Hours": "Horari d'obertura",
- "Office_Hours_Enabled": "Horari d'obertura actiu",
+ "Office_hours_enabled": "Horari d'obertura actiu",
+ "Office_hours_updated": "Horari actualitzat",
"Offline": "Fora de línia",
"Offline_DM_Email": "__user__ us ha enviat un missatge directe",
"Offline_form": "formulari en línia",
@@ -979,18 +1281,22 @@
"Offline_unavailable": "Fora de línia no disponible",
"On": "Activa",
"Online": "Connectat",
+ "Only_On_Desktop": "Mode ordinador d'escriptori (només envia amb Enter en ordinadors)",
"Only_you_can_see_this_message": "Només tu pots veure aquest missatge",
"Oops!": "Ui!",
"Open": "Obre",
+ "Open_channel_user_search": "`%s` - Obre canal / Cerca usuari",
"Open_days_of_the_week": "Dies d'obertura",
"Open_Livechats": "LiveChats oberts",
+ "Open_your_authentication_app_and_enter_the_code": "Obre l'app d'autenticació i entra el codi. També pots utilitzar un dels codis de recuperació.",
"Opened": "Obert",
"Opened_in_a_new_window": "Obert en una nova finestra.",
"Opens_a_channel_group_or_direct_message": "Obrir un canal, grup o missatge directe",
"optional": "opcional",
- "Use_minor_colors": "Utilitza la paleta de colors secundària (per defecte s'hereta de la primària)",
"or": "o",
+ "Or_talk_as_anonymous": "O parla com a anònim",
"Order": "Ordre",
+ "Original": "Original",
"OS_Arch": "Arquitectura del sistema",
"OS_Cpus": "Recompte de CPU",
"OS_Freemem": "Memòria RAM lliure",
@@ -1003,6 +1309,8 @@
"others": "altres",
"OTR": "Off-the-record",
"OTR_is_only_available_when_both_users_are_online": "La missatgeria OTR només està disponible quan els usuaris estan connectats simultàniament.",
+ "Outgoing_WebHook": "WebHook sortint",
+ "Outgoing_WebHook_Description": "Extreu dades de Rocket.Chat en temps real.",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Sobreescriu l'adreça URL a la qual es pugen els arxius. Aquesta adreça també s'utilitza per a les descàrregues a menys que s'especifiqui un CDN",
"Page_title": "Titol de la pàgina",
"Page_URL": "Adreça URL de la pàgina",
@@ -1014,9 +1322,17 @@
"People": "Gent",
"Permalink": "Enllaç permanent (Permalink)",
"Permissions": "Permisos",
+ "pin-message": "Fixar missatge",
+ "pin-message_description": "Permís per fixar un missatge en un canal",
"Pin_Message": "Fixa missatge",
"Pinned_a_message": "S'ha fixat un missatge:",
"Pinned_Messages": "Missatges fixats",
+ "PiwikAdditionalTrackers": "Llocs piwik addicionals",
+ "PiwikAnalytics_cookieDomain": "Tots els subdominis",
+ "PiwikAnalytics_cookieDomain_Description": "Segueix visitants per tots els subdominis",
+ "PiwikAnalytics_domains": "Amaga enllaços de sortida",
+ "PiwikAnalytics_prependDomain": "Prefixa domini",
+ "PiwikAnalytics_prependDomain_Description": "Prefixa el domini del lloc al títol de la pàgina",
"PiwikAnalytics_siteId_Description": "L'ID de lloc a utilitzar per a la identificació d'aquest lloc. Exemple: 17",
"PiwikAnalytics_url_Description": "L'adreça URL on es troba el Piwik, assegureu-vos d'incloure la barra del final. Exemple: //piwik.rocket.chat/",
"Placeholder_for_email_or_username_login_field": "Indicatiu per al camp d'inici de sessió (correu electrònic o nom d'usuari)",
@@ -1024,13 +1340,14 @@
"Please_add_a_comment": "Si us plau, afegeix un comentari",
"Please_add_a_comment_to_close_the_room": "Si us plau, afegeix un comentari per tancar la sala",
"Please_answer_survey": "Si us plau, permeti'ns un moment per una breu enquesta sobre aquest xat",
+ "please_enter_valid_domain": "Si us plau introduiu un domini vàlid",
"Please_enter_value_for_url": "Si us plau introdueix l'adreça URL del teu avatar.",
"Please_enter_your_new_password_below": "Si us plau, introdueix a continuació la nova contrasenya:",
"Please_enter_your_password": "Si us plau, introdueix la teva contrasenya",
- "please_enter_valid_domain": "Si us plau introduiu un domini vàlid",
"Please_fill_a_label": "Si us plau, omple una etiqueta",
"Please_fill_a_name": "Si us plau, introdueix un nom",
"Please_fill_a_username": "Si us plau, escull un nom d'usuari",
+ "Please_fill_all_the_information": "Si us plau, omple tota la informació",
"Please_fill_name_and_email": "Si us plau, omple el nom i l'adreça electrònica",
"Please_select_an_user": "Si us plau seleccioneu un usuari",
"Please_select_enabled_yes_or_no": "Si us plau, selecciona SÍ o NO",
@@ -1040,19 +1357,27 @@
"Please_wait_while_your_account_is_being_deleted": "Si us plau, espera mentre s'elimina el compte...",
"Please_wait_while_your_profile_is_being_saved": "Si us plau, espera mentre el perfil es guarda...",
"Port": "Port",
+ "post-readonly": "Publicar on només lectura",
+ "post-readonly_description": "Permís per publicar un missatge en canal de només lectura",
"Post_as": "Publica com",
"Post_to_Channel": "Publica al canal",
"Post_to_s_as_s": "Publica a %s com %s ",
"Preferences": "Preferències",
"Preferences_saved": "Preferències guardades",
+ "preview-c-room": "Previsualitzar canal públic",
+ "preview-c-room_description": "Permís per veure els continguts d'un canal públic abans d'unir-s'hi",
"Privacy": "Privacitat",
"Private": "Privat",
+ "Private_Channel": "Canal privat",
"Private_Group": "Grup privat",
"Private_Groups": "Grups privats",
"Private_Groups_list": "Llista de grups privats",
"Profile": "Perfil",
+ "Profile_details": "Detalls del perfil",
+ "Profile_picture": "Foto del perfil",
"Profile_saved_successfully": "Perfil guardat correctament",
"Public": "Públic",
+ "Public_Channel": "Canal públic",
"Push": "Push (notificacions)",
"Push_apn_cert": "Certificat APN",
"Push_apn_dev_cert": "Certificat APN de desenvolupador (Dev)",
@@ -1086,14 +1411,22 @@
"Read_only_group": "Grup de només lectura",
"Record": "Gravar",
"Redirect_URI": "URI de redireccionament (Redirect URI)",
- "Refresh_oauth_services": "Refresca serveis OAuth",
"Refresh_keys": "Refresca les claus",
+ "Refresh_oauth_services": "Refresca serveis OAuth",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Per poder compartir la pantalla refresqui la pàgina després de la instal·lació ",
+ "Regenerate_codes": "Regenera codis",
"Register": "Crea un compte nou",
+ "Registration": "Registre",
"Registration_Succeeded": "Registre reeixit",
+ "Registration_via_Admin": "Registre via Admin",
+ "Regular_Expressions": "Expressions regulars",
"Release": "Llançament",
+ "Reload": "Recarrega",
"Remove": "Esborrar",
+ "remove-user": "Expulsar usuari",
+ "remove-user_description": "Permís per expulsar un usuari d'una sala",
"Remove_Admin": "Treu admin",
+ "Remove_as_leader": "Treure de líder",
"Remove_as_moderator": "Treu de moderador",
"Remove_as_owner": "Treu de propietari",
"Remove_custom_oauth": "Esborra OAuth personalitzat",
@@ -1106,27 +1439,32 @@
"Report_exclamation_mark": "Informa!",
"Report_sent": "Informe enviat",
"Report_this_message_question_mark": "Informar d'aquest missatge?",
+ "Reporting": "Informes",
"Require_password_change": "Requerir el canvi de la contrasenya",
"Resend_verification_email": "Reenviar el correu-e de verificació",
"Reset": "Reinicialitza (reset)",
- "Reset_section_settings": "Reinicialitza els ajustos de la secció",
"Reset_password": "Reinicialitza la contrasenya",
+ "Reset_section_settings": "Reinicialitza els ajustos de la secció",
"Restart": "Reinicia (restart)",
"Restart_the_server": "Reinicia el servidor",
+ "Retry_Count": "Comptador de reintents",
"Role": "Rol",
"Role_Editing": "Edició de rols",
"Role_removed": "Rol eliminat",
"Room": "Sala",
+ "Room_announcement_changed_successfully": "L'anunci de la sala s'ha canviat correctament",
"Room_archivation_state": "Estat",
"Room_archivation_state_false": "Actiu",
"Room_archivation_state_true": "Arxivada",
"Room_archived": "Sala arxivada",
+ "room_changed_announcement": "L'anunci de la sala s'ha canviat a: __room_announcement__ per __user_by__ ",
"room_changed_description": "Descripció de la sala canviada a: __room_description__ per __user_by__ .",
"room_changed_privacy": "Tipus de sala canviat a: __room_type__ per __user_by__ .",
"room_changed_topic": "Tema de la sala canviat a: __room_topic__ per __user_by__ .",
+ "Room_default_change_to_private_will_be_default_no_more": "Aquest és un canal per defecte i canviar-lo a grup privat farà que deixi de ser-ho. Voleu continuar?",
"Room_description_changed_successfully": "Descripció de la sala canviada correctament",
- "Room_has_been_deleted": "La sala s'ha eliminat",
"Room_has_been_archived": "La sala s'ha arxivat",
+ "Room_has_been_deleted": "La sala s'ha eliminat",
"Room_has_been_unarchived": "La sala s'ha desarxivat",
"Room_Info": "Informació de la sala",
"room_is_blocked": "Aquesta sala està bloquejada",
@@ -1135,31 +1473,41 @@
"Room_name_changed": "Nom de la sala canviat a: __room_name__ per __user_by__ .",
"Room_name_changed_successfully": "El nom de la sala s'ha canviat correctament",
"Room_not_found": "Sala no trobada",
+ "Room_password_changed_successfully": "Contrasenya de la sala canviada correctament",
"Room_topic_changed_successfully": "El tema de la sala s'ha canviat correctament",
"Room_type_changed_successfully": "El tipus de sala s'ha canviat correctament",
+ "Room_type_of_default_rooms_cant_be_changed": "Aquesta és una sala per defecte i no es pot canviar el tipus, si us plau consulta-ho amb l'administrador.",
"Room_unarchived": "La sala s'ha desarxivat",
"Room_uploaded_file_list": "Llista d'arxius pujats",
"Room_uploaded_file_list_empty": "No hi ha cap arxiu.",
"Rooms": "Sales",
+ "run-import": "Executar importació",
+ "run-import_description": "Permís per executar els importadors",
+ "run-migration": "Executar migració",
+ "run-migration_description": "Permís per executar les migracions",
"Running_Instances": "Instàncies executant-se",
"S_new_messages_since_s": "%s nous des de: %s",
+ "Same_Style_For_Mentions": "Mateix estil per a mencions",
"SAML": "SAML",
"SAML_Custom_Cert": "Certificat personalitzat",
"SAML_Custom_Entry_point": "Punt d'entrada (Entry Point) personalitzat",
"SAML_Custom_Generate_Username": "Generar nom d'usuari",
"SAML_Custom_IDP_SLO_Redirect_URL": "Redirecció URL IDP SLO",
"SAML_Custom_Issuer": "Emissor (issuer) personalitzat",
+ "SAML_Custom_Private_Key": "Contingut de la clau privada",
"SAML_Custom_Provider": "Proveïdor (provider) personalitzat",
"SAML_Custom_Public_Cert": "Contingut del certificat públic",
- "SAML_Custom_Private_Key": "Contingut de la clau privada",
"Sandstorm_Powerbox_Share": "Comparteix un gra de Sandstorm",
"Saturday": "dissabte",
"Save": "Desa",
+ "save-others-livechat-room-info": "Guardar info altres xats en viu",
+ "save-others-livechat-room-info_description": "Permís per guardar informació d'altres canals de xat en viu",
"Save_changes": "Desa els canvis",
"Save_Mobile_Bandwidth": "Estalvia ample de banda mòbil",
"Save_to_enable_this_action": "Desa per activar els canvis",
"Saved": "Desat",
"Saving": "Desant",
+ "Scan_QR_code": "Fent servir una app d'autenticació com Google Authenticator, Authy o Duo, escanneja el codi QR. Et mostrarà un codi de 6 dígits que has d'entrar aquí a sota.",
"Scope": "Abast (scope)",
"Screen_Share": "Compartir pantalla",
"Script_Enabled": "Script actiu",
@@ -1169,10 +1517,12 @@
"Search_Private_Groups": "Cerca grups privats",
"seconds": "segons",
"Secret_token": "Token secret",
+ "Security": "Seguretat",
"Select_a_department": "Selecciona un departament",
"Select_a_user": "Selecciona un usuari",
"Select_an_avatar": "Selecciona un avatar",
"Select_file": "Selecciona un arxiu",
+ "Select_role": "Selecciona un rol",
"Select_service_to_login": "Selecciona un servei per iniciar sessió i carregar la teva imatge o puja una foto del teu ordinador",
"Select_user": "Selecciona usuari",
"Select_users": "Selecciona els usuaris",
@@ -1196,6 +1546,16 @@
"Sending": "Enviant...",
"Served_By": "Servit per",
"Service": "Servei",
+ "Service_account_key": "Service account key",
+ "set-moderator": "Assignar moderador",
+ "set-moderator_description": "Permís per assignar altres usuaris com a moderadors d'un canal",
+ "set-owner": "Assignar propietari",
+ "set-owner_description": "Permís per assignar altres usuaris com a propietaris d'un canal",
+ "set-react-when-readonly": "Reaccions quan només lectura",
+ "set-react-when-readonly_description": "Permís per poder afegir reaccions a missatges en canals de només lectura",
+ "set-readonly": "Fer només lectura",
+ "set-readonly_description": "Permís per fer un canal de només lectura",
+ "Set_as_leader": "Posar com a líder",
"Set_as_moderator": "Fes-lo moderador",
"Set_as_owner": "Fes-lo propietari",
"Settings": "Configuració",
@@ -1211,20 +1571,23 @@
"Show_only_online": "Veure només connectats",
"Show_preregistration_form": "Veure formulari de pre-registre",
"Show_queue_list_to_all_agents": "Mostra la cua a tots els agents",
+ "Show_the_keyboard_shortcut_list": "Mostra la llista de dreceres de teclat",
"Showing_archived_results": "Mostrant %s resultats arxivats
",
"Showing_online_users": "Mostrant-ne __total_showing__ , En línia: __online__, Total: __total__ usuaris",
"Showing_results": "Mostrant %s resultats
",
+ "Sidebar_list_mode": "Mode de la barra lateral de la llista de canals",
+ "Sign_in_to_start_talking": "Identifica't per començar a parlar",
"since_creation": "des de %s",
"Site_Name": "Nom del lloc",
"Site_Url": "URL del lloc",
"Site_Url_Description": "Exemple: https://xat.domini.com",
"Skip": "Salta",
"SlackBridge_error": "Hi ha hagut un error a SlackBridge mentre importava els missatges a %s: %s",
+ "SlackBridge_finish": "SlackBridge ha finalitat la importació a %s. Si us plau, refresqueu per veure tots els missatges.",
"SlackBridge_Out_All": "SlackBridge Out de tot",
"SlackBridge_Out_All_Description": "Envia els missatges de tots els canals que existeixen a Slack i en els quals el bot s'ha unit",
"SlackBridge_Out_Channels": "SlackBridge Out de canals",
"SlackBridge_Out_Channels_Description": "Escull els canals dels quals es reenviaran els missatges a Slack",
- "SlackBridge_finish": "SlackBridge ha finalitat la importació a %s. Si us plau, refresqueu per veure tots els missatges.",
"SlackBridge_Out_Enabled": "SlackBridge Out actiu",
"SlackBridge_Out_Enabled_Description": "Escull si SlackBridge ha de reenviar els missatges a Slack",
"SlackBridge_start": "@%s ha iniciat una importació SlackBridge a `#%s`. Us avisarem quan finalitzi.",
@@ -1251,20 +1614,28 @@
"SMTP_Port": "Port SMTP",
"SMTP_Test_Button": "Prova la configuració del SMTP",
"SMTP_Username": "Usuari SMTP",
+ "snippet-message": "Retalls de missatge",
+ "snippet-message_description": "Permís per crear retalls de missatge",
"Snippet_Added": "Creat %s",
"Snippet_Messages": "Retalls de missatges",
"Snippeted_a_message": "S'ha creat un retall de missatge __snippetLink__",
+ "Sort_by_activity": "Ordena per activitat",
"Sound": "So",
+ "Sound_File_mp3": "Fitxer de so (mp3)",
+ "Split_by_categories": "Separa per categories",
"SSL": "SSL",
"Star_Message": "Destacar un missatge",
"Starred_Messages": "Missatges destacats",
+ "Start": "Inicia",
"Start_audio_call": "Inicia trucada",
"Start_Chat": "Inicia el xat",
"Start_of_conversation": "Inici de la conversa",
"Start_OTR": "Inicia conversa OTR",
"Start_video_call": "Inicia videotrucada",
+ "Start_video_conference": "Inicia videoconferència?",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Comença amb %s per a usuari o %s per a canal. Ex: %s o %s",
"Started_At": "Va començar a les",
+ "Started_a_video_call": "Inicia una videoconferència",
"Statistics": "Estadístiques",
"Statistics_reporting": "Enviar estadístiques a Rocket.Chat",
"Statistics_reporting_Description": "Mitjançant l'enviament de les estadístiques, ens ajudes a saber com s'implementa el Rocket.Chat, així com de bé es comporta el sistema, per poder-lo millorar encara més. No s'envia informació dels usuaris i tota la informació que rebem es manté confidencial.",
@@ -1278,12 +1649,18 @@
"Stats_Online_Users": "Usuaris connectats",
"Stats_Total_Channels": "Total de canals",
"Stats_Total_Direct_Messages": "Total de sales de missatges directes",
+ "Stats_Total_Livechat_Rooms": "Total de sales de xat en viu",
"Stats_Total_Messages": "Total de missatges",
+ "Stats_Total_Messages_Channel": "Total de missatges a canals",
+ "Stats_Total_Messages_Direct": "Total de missatges a missatges directes",
+ "Stats_Total_Messages_Livechat": "Total de missatges a xats en viu",
+ "Stats_Total_Messages_PrivateGroup": "Total de missatges a grups privats",
"Stats_Total_Private_Groups": "Total de grups privats",
"Stats_Total_Rooms": "Total de sales",
"Stats_Total_Users": "Total d'usuaris",
"Status": "Estat",
"Stop_Recording": "Atura gravació",
+ "Stream_Cast": "Stream Cast",
"Stream_Cast_Address": "Adreça Stream Cast",
"Stream_Cast_Address_Description": "IP o host del Stream Cast del teu Rocket.Chat central. Exemple: `192.168.1.1:3000` o `localhost:4000`.",
"strike": "strike",
@@ -1296,10 +1673,14 @@
"Survey_instructions": "Valoreu cada pregunta d'acord al nivell de satisfacció, sent 1 completament insatisfet i 5 completament satisfet.",
"Symbols": "Símbols",
"Sync_success": "Sincronització correcta",
+ "Sync_in_progress": "Sincronització en progrés",
"Sync_Users": "Sincronitza usuaris",
"System_messages": "Missatges del sistema",
"Tag": "Etiqueta",
"Take_it": "Agafa'l!",
+ "TargetRoom": "Sala de destí",
+ "TargetRoom_Description": "Sala que rebrà els missatges resultants de les execucions d'aquest esdeveniment. Només es permet una sala de destí i aquesta ha d'existir.",
+ "Team": "Equip",
"Test_Connection": "Prova de connexió",
"Test_Desktop_Notifications": "Prova de notificacions d'escriptori",
"Thank_you_exclamation_mark": "Gràcies!",
@@ -1315,33 +1696,48 @@
"The_user_will_be_removed_from_s": "L'usuari s'eliminarà de %s",
"The_user_wont_be_able_to_type_in_s": "L'usuari no podrà escriure a %s",
"Theme": "Aparença",
- "theme-color-transparent-darker": "Transparent més fosc",
- "theme-color-transparent-dark": "Transparent fosc",
- "theme-color-transparent-light": "Transparent clar",
- "theme-color-transparent-lighter": "Transparent més clar",
- "theme-color-transparent-lightest": "Transparent el més clar",
+ "theme-color-component-color": "Color de component",
"theme-color-content-background-color": "Color del fons del contingut",
+ "theme-color-custom-scrollbar-color": "Color personalitzat de barra de desplaçament",
+ "theme-color-error-color": "Color d''Error'",
+ "theme-color-info-font-color": "Color del text d'informació",
+ "theme-color-link-font-color": "Color del text dels enllaços",
+ "theme-color-pending-color": "Color de 'Pendent'",
+ "theme-color-primary-action-color": "Color d'acció principal",
"theme-color-primary-background-color": "Color primari del fons",
"theme-color-primary-font-color": "Color primari del text",
- "theme-color-primary-action-color": "Color d'acció principal",
+ "theme-color-secondary-action-color": "Color d'acció secundària",
"theme-color-secondary-background-color": "Color secundari del fons",
"theme-color-secondary-font-color": "Color secundari del text",
- "theme-color-secondary-action-color": "Color d'acció secundària",
- "theme-color-component-color": "Color de component",
- "theme-color-success-color": "Color de 'Correcte'",
- "theme-color-pending-color": "Color de 'Pendent'",
- "theme-color-error-color": "Color d''Error'",
"theme-color-selection-color": "Color de selecció",
- "theme-color-tertiary-background-color": "Color terciari del fons",
- "theme-color-tertiary-font-color": "Color terciari del text",
- "theme-color-link-font-color": "Color del text dels enllaços",
- "theme-color-info-font-color": "Color del text d'informació",
- "theme-color-custom-scrollbar-color": "Color personalitzat de barra de desplaçament",
"theme-color-status-away": "Color de l'estat absent",
"theme-color-status-busy": "Color de l'estat ocupat",
"theme-color-status-offline": "Color de l'estat desconnectat",
"theme-color-status-online": "Color de l'estat connectat",
+ "theme-color-success-color": "Color de 'Correcte'",
+ "theme-color-tertiary-background-color": "Color terciari del fons",
+ "theme-color-tertiary-font-color": "Color terciari del text",
+ "theme-color-transparent-dark": "Transparent fosc",
+ "theme-color-transparent-darker": "Transparent més fosc",
+ "theme-color-transparent-light": "Transparent clar",
+ "theme-color-transparent-lighter": "Transparent més clar",
+ "theme-color-transparent-lightest": "Transparent el més clar",
"theme-color-unread-notification-color": "Color de les notificacions de no llegit",
+ "theme-color-rc-color-error": "Error",
+ "theme-color-rc-color-error-light": "Error clar",
+ "theme-color-rc-color-alert": "Alerta",
+ "theme-color-rc-color-alert-light": "Alerta clar",
+ "theme-color-rc-color-success": "Correcte",
+ "theme-color-rc-color-success-light": "Correcte clar",
+ "theme-color-rc-color-button-primary": "Botó primari",
+ "theme-color-rc-color-button-primary-light": "Botó primari clar",
+ "theme-color-rc-color-primary": "Primari",
+ "theme-color-rc-color-primary-darkest": "Primari el més fosc",
+ "theme-color-rc-color-primary-dark": "Primari fosc",
+ "theme-color-rc-color-primary-light": "Primari clar",
+ "theme-color-rc-color-primary-light-medium": "Primari clar mig",
+ "theme-color-rc-color-primary-lightest": "Primari el més clar",
+ "theme-color-rc-color-content": "Contingut",
"theme-custom-css": "CSS personalitzat",
"theme-font-body-font-family": "Font Family del Body",
"There_are_no_agents_added_to_this_department_yet": "Encara no hi ha cap agent afegit a aquest departament.",
@@ -1362,33 +1758,53 @@
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Per instal·lar el xat en viu (livechat) de Rocket.Chat al teu lloc web, còpia i enganxa aquest codi damunt la darrera etiqueta </body> del mateix.",
"to_see_more_details_on_how_to_integrate": "per a veure més detalls sobre com fer la integració.",
"To_users": "Per als usuaris",
+ "Toggle_original_translated": "Canvia original/traducció",
"Topic": "Tema",
- "Travel_and_Places": "Viatges i llocs",
"Transcript_Enabled": "Pregunta als visitants si volen rebre la transcripció del xat després de tancar-lo",
"Transcript_message": "Missatge a mostrar per a la pregunta sobre la transcripció",
"Transcript_of_your_livechat_conversation": "Transcripció de la conversa de xat en viu.",
- "Trigger_removed": "Activació eliminada",
+ "Translated": "Traduït",
+ "Translations": "Traduccions",
+ "Travel_and_Places": "Viatges i llocs",
+ "Trigger_removed": "Disparador eliminat",
"Trigger_Words": "Paraules d'activació",
"Triggers": "Activadors (triggers)",
"True": "Sí",
"Tuesday": "dimarts",
+ "Two-factor_authentication": "Autenticació de dos factors",
+ "Two-factor_authentication_disabled": "Autenticació de dos factors desactivada",
+ "Two-factor_authentication_enabled": "Autenticació de dos factors activada",
+ "Two-factor_authentication_is_currently_disabled": "L'autenticació de dos factors actualment està desactivada",
+ "Two-factor_authentication_native_mobile_app_warning": "ATENCIÓ: Un cop activat això, no es podrà fer login des de les aplicacions mòbils natives (Rocket.Chat+) utilitzant la contrasenya fins que aquestes implementin el 2FA.",
"Type": "Tipus",
"Type_your_email": "Escrigui el seu correu electrònic",
"Type_your_message": "Introduïu el missatge",
"Type_your_name": "Escriu el teu nom",
"Type_your_new_password": "Escriu la nova contrasenya",
+ "UI_Allow_room_names_with_special_chars": "Permet caràcters especials als noms de sala",
+ "UI_Click_Direct_Message": "Clica per crear un missatge directe",
+ "UI_Click_Direct_Message_Description": "Evita obrir la pestanya del perfil, vés directe a la conversa",
"UI_DisplayRoles": "Mostra rols",
"UI_Merge_Channels_Groups": "Uneix grups privats amb canals",
+ "UI_Unread_Counter_Style": "Estil de comptador de no-llegits",
+ "UI_Use_Name_Avatar": "Utilitza les inicials del nom complet per generar l'avatar per defecte",
+ "UI_Use_Real_Name": "Utilitza el nom real",
"Unarchive": "Desarxiva",
+ "unarchive-room": "Desarxivar sala",
+ "unarchive-room_description": "Permís per desarxivar canals",
"Unblock_User": "Desbloqueja usuari",
"Unmute_someone_in_room": "Torna a donar veu a algú de la sala",
"Unmute_user": "Dóna veu a l'usuari",
"Unnamed": "Sense nom",
"Unpin_Message": "Desfixa el missatge",
- "Unread_Alert": "Alerta de no llegit",
+ "Unread_Count": "Comptador de no llegits",
+ "Unread_Count_DM": "Comptador de no-llegits per als missatges directes",
+ "Unread_Messages": "Missatges no llegits",
"Unread_Rooms": "Sales no llegides",
"Unread_Rooms_Mode": "Mode de sales no llegides",
+ "Unread_Tray_Icon_Alert": "Icona d'alerta de no llegits a la safata",
"Unstar_Message": "Esborra el destacat",
+ "Updated_at": "Actualitzat el",
"Upload_file_description": "Descripció de l'arxiu",
"Upload_file_name": "Nom de l'arxiu",
"Upload_file_question": "Pujar l'arxiu?",
@@ -1400,18 +1816,25 @@
"Use_Emojis": "Utilitza emojis",
"Use_Global_Settings": "Usa la configuració global",
"Use_initials_avatar": "Utilitza les inicials del nom d'usuari",
+ "Use_minor_colors": "Utilitza la paleta de colors secundària (per defecte s'hereta de la primària)",
"Use_service_avatar": "Utilitza l'avatar de %s",
"Use_this_username": "Utilitza aquest nom d'usuari",
"Use_uploaded_avatar": "Utilitza l'avatar pujat",
"Use_url_for_avatar": "Utilitza una URL per l'avatar",
"Use_User_Preferences_or_Global_Settings": "Usa les preferències d'usuari o la configuració global",
+ "User": "Usuari",
+ "user-generate-access-token": "Usuaris generen Access Tokens",
+ "user-generate-access-token_description": "Permís perquè els usuaris puguin generar access tokens",
+ "User__username__is_now_a_leader_of__room_name_": "L'usuari __username__ ara és líder de __room_name__",
"User__username__is_now_a_moderator_of__room_name_": "L'usuari __username__ ara és moderador de la sala __room_name__",
"User__username__is_now_a_owner_of__room_name_": "L'usuari __username__ ara és un propietari de __room_name__",
+ "User__username__removed_from__room_name__leaders": "L'usuari __username__ ja no és líder de __room_name__",
"User__username__removed_from__room_name__moderators": "L'usuari __username__ ja no és moderador de la sala __room_name__",
"User__username__removed_from__room_name__owners": "L'usuari __username__ ja no és propietari de __room_name__",
"User_added": "Usuari afegit",
"User_added_by": "Usuari __user_added__ afegit per __user_by__ .",
"User_added_successfully": "Usuari afegit correctament",
+ "User_and_group_mentions_only": "Només mencions d'usuari i de grup",
"User_doesnt_exist": "No existeix cap usuari amb el nom `@%s`.",
"User_has_been_activated": "L'usuari s'ha activat",
"User_has_been_deactivated": "L'usuari s'ha desactivat",
@@ -1419,6 +1842,7 @@
"User_has_been_muted_in_s": "L'usuari ha sigut silenciat a %s",
"User_has_been_removed_from_s": "L'usuari s'ha eliminat de %s",
"User_Info": "Informació de l'usuari",
+ "User_Interface": "Interfície d'usuari",
"User_is_blocked": "L'usuari està bloquejat",
"User_is_no_longer_an_admin": "L'usuari ja no és administrador",
"User_is_now_an_admin": "L'usuari ara és administrador",
@@ -1431,6 +1855,7 @@
"User_left_male": "Ha sortit del canal.",
"User_logged_out": "L'usuari està desconnectat",
"User_management": "Administració d'usuaris",
+ "User_mentions_only": "Només mencions d'usuari",
"User_muted": "Usuari silenciat",
"User_muted_by": "Usuari __user_muted__ silenciat per __user_by__ .",
"User_not_found": "Usuari no trobat",
@@ -1442,6 +1867,8 @@
"User_unmuted_by": "L'usuari __user_by__ ha tornat la veu a __user_unmuted__ .",
"User_unmuted_in_room": "L'usuari torna a tenir veu a la sala",
"User_updated_successfully": "L'usuari s'ha actualitzat correctament",
+ "User_uploaded_file": "Ha pujat un arxiu",
+ "User_uploaded_image": "Ha pujat una imatge",
"Username": "Nom d'usuari",
"Username_and_message_must_not_be_empty": "El nom d'usuari i el missatge no han d'estar buits.",
"Username_cant_be_empty": "El nom d'usuari no pot estar buit",
@@ -1453,21 +1880,61 @@
"Username_invalid": "%s no és un nom d'usuari vàlid, feu servir només lletres, números, punts, guions i guions baixos",
"Username_is_already_in_here": "`@%s` ja hi és.",
"Username_is_not_in_this_room": "L'usuari `#%s` no és en aquesta sala.",
+ "Username_Placeholder": "Sisplau, entra noms d'usuari...",
"Username_title": "Tria un nom d'usuari",
"Username_wants_to_start_otr_Do_you_want_to_accept": "L'usuari __username__ vol iniciar una conversa OTR. L'acceptes?",
"Users": "Usuaris",
+ "Users_added": "Els usuaris s'han afegit",
"Users_in_role": "Usuaris al rol",
"UTF8_Names_Slugify": "Slugify de noms UTF8",
"UTF8_Names_Validation": "Validació de noms UTF8",
"UTF8_Names_Validation_Description": "RegExp que s'utilitzarà per validar noms d'usuari i de sala",
"Validate_email_address": "Valida l'adreça de correu-e",
+ "Verification": "Verificació",
+ "Verification_Description": "És possible utilitzar els marcadors: [Verification_Url] per a l'adreça URL de verificació. [name], [fname], [lname] per al nom complet de l'usuari, nom o cognom, respectivament. [email] per a l'adreça de correu electrònic de l'usuari. [Site_Name] i [Site_URL] pel nom del lloc web i de l'adreça URL, respectivament. ",
+ "Verification_Email": "Fes clic aquí per verificar el teu compte.",
"Verification_email_sent": "Missatge de correu-e de verificació enviat",
+ "Verification_Email_Subject": "[Site_Name] - Verifica el teu compte",
"Verified": "Verificat",
+ "Verify": "Verifica",
"Version": "Versió",
"Video_Chat_Window": "Vídeo-xat",
"Video_Conference": "Videoconferència",
+ "Video_message": "Missatge de vídeo",
"Videocall_declined": "Vídeo trucada rebutjada.",
"Videocall_enabled": "Vídeo trucada activa",
+ "view-c-room": "Veure canal públic",
+ "view-c-room_description": "Permís per veure canals públics",
+ "view-d-room": "Veure missatges directes",
+ "view-d-room_description": "Permís per veure missatges directes",
+ "view-full-other-user-info": "Veure tota la info d'usuaris",
+ "view-full-other-user-info_description": "Permís per veure el perfil complet d'altres usuaris, incloent la data de creació del compte, el darrer accés, etcètera.",
+ "view-history": "Veure historial",
+ "view-history_description": "Permís per veure l'historial del canal",
+ "view-join-code": "Veure el codi per unir-se",
+ "view-join-code_description": "Permís per veure el codi per unir-se al canal",
+ "view-joined-room": "Veure sales on unit",
+ "view-joined-room_description": "Permís per veure els canals on actualment s'està unit",
+ "view-l-room": "Veure sales de xat en viu",
+ "view-l-room_description": "Permís per veure els canals de xat en viu",
+ "view-livechat-manager": "Veure el gestor de xats en viu",
+ "view-livechat-manager_description": "Permís per veure gestors d'altres xats en viu",
+ "view-livechat-rooms": "Veure xats en viu",
+ "view-livechat-rooms_description": "Permís per veure altres canals de xat en viu",
+ "view-logs": "Veure registres",
+ "view-logs_description": "Permís per veure els registres del servidor",
+ "view-other-user-channels": "Veure canals d'altres usuaris",
+ "view-other-user-channels_description": "Permís per veure canals que pertanyen a altres usuaris",
+ "view-p-room": "Veure sala privada",
+ "view-p-room_description": "Permís per veure canals privats",
+ "view-privileged-setting": "Veure opcions privilegiades",
+ "view-privileged-setting_description": "Permís per a veure la configuració",
+ "view-room-administration": "Veure administració de sala",
+ "view-room-administration_description": "Permís per veure estadístiques de missatges públics, privats i directes. No inclou veure converses o arxius",
+ "view-statistics": "Veure estadístiques",
+ "view-statistics_description": "Permís per veure estadístiques del sistema com el nombre d'usuaris autenticats, el nombre de sales o informació del sistema operatiu",
+ "view-user-administration": "Veure administració d'usuaris",
+ "view-user-administration_description": "Permís per veure una llista de només lectura parcial dels comptes d'usuari actualment autenticats al sistema. Amb aquest permís no és possible veure informació dels comptes d'usuari.",
"View_All": "Veure tot",
"View_Logs": "Veure registre log",
"View_mode": "Densitat de visualització",
@@ -1485,7 +1952,7 @@
"We_are_offline_Sorry_for_the_inconvenience": "Estem fora de línia. Disculpi les molèsties.",
"We_have_sent_password_email": "T'hem enviat un missatge de correu electrònic amb les instruccions per reinicialitzar la contrasenya. Si no reps el missatge en breu, si us plau mira al correu brossa i/o torna i reintenta-ho.",
"We_have_sent_registration_email": "T'hem enviat un missatge de correu electrònic per confirmar el registre. Si no reps el missatge en breu, si us plau mira al correu brossa i/o torna i reintenta-ho.",
- "Webhook_URL": "URL Webhook",
+ "Webhook_URL": "Adreça URL WebHook",
"Webhooks": "Webhooks",
"WebRTC_Enable_Channel": "Activa per a canals públics",
"WebRTC_Enable_Direct": "Activa per a missatges directes",
@@ -1500,13 +1967,13 @@
"Would_you_like_to_return_the_inquiry": "Vols retornar la sol·licitud?",
"Yes": "Sí",
"Yes_archive_it": "Sí, arxiva'l!",
- "Yes_unarchive_it": "Sí, desarxiva'l!",
"Yes_clear_all": "Sí, esborra!",
"Yes_delete_it": "Sí, elimina!",
"Yes_hide_it": "Sí, oculta!",
"Yes_leave_it": "Sí, deixa-ho!",
"Yes_mute_user": "Sí, silencia l'usuari!",
"Yes_remove_user": "Sí, elimina l'usuari!",
+ "Yes_unarchive_it": "Sí, desarxiva'l!",
"You": "Vostè",
"you_are_in_preview_mode_of": "Estàs en mode vista prèvia del canal #__room_name__ ",
"You_are_logged_in_as": "Sessió iniciada com",
@@ -1517,6 +1984,7 @@
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Es poden utilitzar webhooks per a integrar fàcilment el xat en viu amb el teu CRM.",
"You_cant_leave_a_livechat_room_Please_use_the_close_button": "No es pot abandonar una sala de xat en viu. Si us plau, utilitzi el botó de tancar.",
"You_have_been_muted": "Has estat silenciat i no podràs dir res en aquesta sala",
+ "You_have_n_codes_remaining": "Encara et queden __number__ codis.",
"You_have_not_verified_your_email": "Encara no has verificat la teva adreça de correu electrònic.",
"You_have_successfully_unsubscribed": "T'has donat de baixa correctament de la nostra llista de distribució de correu.",
"You_must_join_to_view_messages_in_this_channel": "Has d'unir-te per veure els missatges d'aquest canal",
@@ -1540,4 +2008,4 @@
"your_message_optional": "el teu missatge (opcional)",
"Your_password_is_wrong": "La contrasenya és incorrecta!",
"Your_push_was_sent_to_s_devices": "La notificació push s'ha enviat a %s dispositius"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/cs.i18n.json b/packages/rocketchat-i18n/i18n/cs.i18n.json
index df2522bcedf9a..e48647fdddba4 100644
--- a/packages/rocketchat-i18n/i18n/cs.i18n.json
+++ b/packages/rocketchat-i18n/i18n/cs.i18n.json
@@ -10,13 +10,19 @@
"__username__is_no_longer__role__defined_by__user_by_": "__username__ již není __role__ (odebral/a __user_by__ )",
"__username__was_set__role__by__user_by_": "__username__ je nyní __role__ (nastavil/a __user_by__)",
"Accept": "Přijmout",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Přijímat livechat požadavky i pokud není online žádný operátor",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Přijímat LiveChat požadavky i pokud není online žádný operátor",
"Accept_with_no_online_agents": "Přijímat i bez aktivních operátorů",
+ "access-mailer": "Přístup k maileru",
+ "access-mailer_description": "Právo rozesílat hromadný email na všechny uživatele.",
+ "access-permissions": "Přístup k nastavení práv",
+ "access-permissions_description": "Měnít práva pro jednotlivé uživatelské role.",
"Access_not_authorized": "Přístup není povolen",
"Access_Token_URL": "Token přístupové adresy",
"Accessing_permissions": "Přístup k oprávnění",
"Account_SID": "SID účtu",
"Accounts": "Účty",
+ "Accounts_AllowAnonymousRead": "Povolit anonymům číst",
+ "Accounts_AllowAnonymousWrite": "Povolit anonymům zapisovat",
"Accounts_AllowDeleteOwnAccount": "Povolit uživatelům odstranit vlastní účet",
"Accounts_AllowedDomainsList": "Seznam povolených domén",
"Accounts_AllowedDomainsList_Description": "Čárkami oddělený seznam povolených domén",
@@ -27,18 +33,21 @@
"Accounts_AllowUserProfileChange": "Povolit úpravy profilu",
"Accounts_AvatarResize": "Rozměry avataru",
"Accounts_AvatarSize": "Velikost avataru",
- "Accounts_AvatarStorePath": "Cesta k úložišti avatarů",
- "Accounts_AvatarStoreType": "Typ úložiště avatarů",
"Accounts_BlockedDomainsList": "Seznam blokovaných domén",
"Accounts_BlockedDomainsList_Description": "Čárkami oddělený seznam blokovaných domén",
"Accounts_BlockedUsernameList": "Zakázaná uživatelská jména",
"Accounts_BlockedUsernameList_Description": "čárkou oddělený seznam uživatelských jmen (na velikosti písmen nezáleží)",
- "Accounts_CustomFields_Description": "Validní JSON obsahující klíče polí s nastavením. Například: {\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n}",
+ "Accounts_CustomFields_Description": "Validní JSON obsahující klíče polí s nastavením. Například:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n}",
+ "Accounts_CustomFieldsToShowInUserInfo": "Vlastní pole zobrazená v uživatelském profilu",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Výchozí návrh prefixu uživatelského jména",
+ "Accounts_Default_User_Preferences_audioNotifications": "Výchozí zvuk upozornění audia",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Výchozí upozornění oznámení na ploše",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Výchozí upozornění mobilní notifikace",
"Accounts_denyUnverifiedEmail": "Zakázat neověřené e-mailové adresy",
"Accounts_EmailVerification": "Ověření e-mailu",
"Accounts_EmailVerification_Description": "Pro použití této funkce se ujistěte, že máte správné nastavení SMTP",
"Accounts_Enrollment_Email": "Úvodní E-mail",
- "Accounts_Enrollment_Email_Default": "Vítejte v [Site_Name] Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!
",
+ "Accounts_Enrollment_Email_Default": "Vítejte v [Site_Name] Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!
",
"Accounts_Enrollment_Email_Description": "Můžete použít [name], [fname], [lname] pro uživatelské jména, křestní jméno a příjmení, pro e-mail uživatele, můžete použít [email].",
"Accounts_Enrollment_Email_Subject_Default": "Vítejte na stránkách [Site_Name]",
"Accounts_ForgetUserSessionOnWindowClose": "Zapomenout session uživatele při zavření okna",
@@ -62,6 +71,10 @@
"Accounts_OAuth_Custom_Token_Path": "Cesta k tokenu",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token odesílány přes",
"Accounts_OAuth_Custom_Username_Field": "Pole uživatelské jméno",
+ "Accounts_OAuth_Drupal": "Povolit Drupal přihlášení",
+ "Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 URI Přesměrování",
+ "Accounts_OAuth_Drupal_id": "Drupal oAuth2 ID klienta",
+ "Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Secret klienta",
"Accounts_OAuth_Facebook": "Facebook Přihlášení",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -90,15 +103,19 @@
"Accounts_OAuth_Meteor_callback_url": "Meteor callback URL",
"Accounts_OAuth_Meteor_id": "ID Meteor",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_host": "Proxy host",
+ "Accounts_OAuth_Proxy_services": "Proxy služby",
"Accounts_OAuth_Twitter": "Twitter Přihlášení",
"Accounts_OAuth_Twitter_callback_url": "Twitter callback URL",
"Accounts_OAuth_Twitter_id": "Twitter ID",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Přihlášení",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress callback URL",
"Accounts_OAuth_Wordpress_id": "ID WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Obnovit heslo",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Výchozí role pro autentikační služby",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Čárkou oddělené role, které budou přiděleny uživateli při registraci skrz autentikační služby",
"Accounts_Registration_AuthenticationServices_Enabled": "Registrace pomocí zabezpečené služby",
"Accounts_RegistrationForm": "Registrační formulář",
"Accounts_RegistrationForm_Disabled": "Zakázáno",
@@ -106,24 +123,37 @@
"Accounts_RegistrationForm_Public": "Veřejný",
"Accounts_RegistrationForm_Secret_URL": "Tajná URL",
"Accounts_RegistrationForm_SecretURL": "Tajná URL pro registracI",
- "Accounts_RegistrationForm_SecretURL_Description": "Vložte náhodný retězec, který bude přidán do vaší registrační URL. Příklad: https://demo.rocket.chat/register/[tajny_kod]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Vložte náhodný retězec, který bude přidán do vaší registrační URL. Příklad: https://open.rocket.chat/register/[tajny_kod]",
"Accounts_RequireNameForSignUp": "Vyžadovat jméno",
"Accounts_RequirePasswordConfirmation": "Vyžadovat potvrzení hesla",
+ "Accounts_SearchFields": "Pole zohledněná ve vyhledávání",
"Accounts_SetDefaultAvatar": "Nastavit výchozí avatar",
"Accounts_SetDefaultAvatar_Description": "Pokusí se určit výchozí avatar na základě OAuth účtu nebo gravataru",
"Accounts_ShowFormLogin": "Zobrazit formulářové přihlášení",
"Accounts_UseDefaultBlockedDomainsList": "Použít výchozí seznam blokovaných domén",
"Accounts_UseDNSDomainCheck": "Použít ověření DNS domény",
- "Accounts_UserAddedEmail_Default": " Vítejte v [Site_Name] Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!
Můžete se přihlásit pomocí e-mailu: [email] a hesla: [password]. Po přihlášení jej možná budete muset změnit.",
+ "Accounts_UserAddedEmail_Default": "
Vítejte v [Site_Name] Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!
Můžete se přihlásit pomocí e-mailu: [email] a hesla: [password]. Po přihlášení jej možná budete muset změnit.",
"Accounts_UserAddedEmail_Description": "Můžete použít:
[name], [fname], [lname] pro celé jméno, křestní nebo příjmení. [email] pro email uživatele. [password] pro heslo uživatele. [Site_Name] a [Site_URL] pro jméno a URL aplikace. ",
"Accounts_UserAddedEmailSubject_Default": "Vítejte na [Site_Name]",
"Activate": "Aktivovat",
"Activity": "Aktivita",
"Add": "Přidat",
+ "add-oauth-service": "Přidat Oauth službu",
+ "add-oauth-service_description": "Právo přidat novou Oauth službu",
+ "add-user": "Přidat uživatele",
+ "add-user-to-any-c-room": "Přidat uživatele do veřejných místností",
+ "add-user-to-any-c-room_description": "Právo přidat uživatele do jakékoliv veřejné místnosti",
+ "add-user-to-any-p-room": "Přidat uživatele do soukromých místností",
+ "add-user-to-any-p-room_description": "Právo přidat uživatele do jakékoliv soukromé místnosti",
+ "add-user-to-joined-room": "Přidat uživatele do místností ve kterých jsem",
+ "add-user-to-joined-room_description": "Právo přidat uživatele do jakékoliv aktuálně připojené místnosti",
+ "add-user_description": "Právo přidat nového uživatele přes seznam uživatelů",
"Add_agent": "Přidat operátora",
"Add_custom_oauth": "Přidat vlastní OAuth",
"Add_Domain": "Přidat Doménu",
+ "Add_files_from": "Přidat soubory z",
"Add_manager": "Přidat správce",
+ "Add_Role": "Přidat roli",
"Add_user": "Přidat uživatele",
"Add_User": "Přidat uživatele",
"Add_users": "Přidat uživatele",
@@ -133,6 +163,7 @@
"Additional_emails": "Další e-maily",
"Additional_Feedback": "Dodatečný Feedback",
"Administration": "Administrace",
+ "Adult_images_are_not_allowed": "Obrázky nevhodné pro mladistvé nejsou povoleny",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Po ověření OAuth2, budou uživatelé přesměrováni na tuto adresu URL",
"Agent": "Operátor",
"Agent_added": "Operátor přidán",
@@ -145,24 +176,33 @@
"All_channels": "Všechny místnosti",
"All_logs": "Všechny logy",
"All_messages": "Všechny zprávy",
- "Allow_Invalid_SelfSigned_Certs": "Umožnit nevalidní či self-signed certifikáty",
+ "All_users_in_the_channel_can_write_new_messages": "Všichni uživatelé v kanálu mohou psát nové zprávy",
+ "Allow_Invalid_SelfSigned_Certs": "Umožnit neplatné či self-signed certifikáty",
"Allow_Invalid_SelfSigned_Certs_Description": "Umožňují použít neplatné/self-signed SSL certifikáty pro ověření odkazů a náhledů.",
+ "Allow_switching_departments": "Povolit uživateli změnit oddělení",
"Always_open_in_new_window": "Vždy otevírat v novém okně",
- "Analytics_features_enabled": "Funkce Povoleny",
+ "Analytics_features_enabled": "Povolené funkce",
"Analytics_features_messages_Description": "Sleduje vlastní události spojené s uživatelskými akcemi u zpráv.",
"Analytics_features_rooms_Description": "Sleduje vlastní události spojené s uživatelskými akcemi na místnosti nebo skupině (vytvoření, odchod, smazání).",
"Analytics_features_users_Description": "Sleduje vlastní události spojené s úpravou uživatele (počet obnovení hesla, úprava profilovu či obrázku, atd).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "ID trackovacího kódu",
"and": "a",
"And_more": "A další __length __",
"Animals_and_Nature": "Zvířata & Příroda",
+ "Announcement": "Oznámení",
"API": "API",
"API_Allow_Infinite_Count": "Povolit získání všeho",
"API_Allow_Infinite_Count_Description": "Měla by volání REST API mít povoleno vrátit všechno v jedné odpovědi?",
"API_Analytics": "Analytika",
+ "API_CORS_Origin": "CORS Origin",
"API_Default_Count": "Výchozí počet",
"API_Default_Count_Description": "Výchozí počet výsledků v REST API pokud není zažádáno konkrétní číslo",
+ "API_Drupal_URL": "Drupal URL Serveru",
+ "API_Drupal_URL_Description": "Například: https://domain.com (bez lomítka na konci)",
"API_Embed": "Náhled vložených odkazů",
"API_Embed_Description": "Zda zobrazit náhled stránky když uživatel pošle odkaz",
+ "API_Embed_UserAgent": "User agent requestu na embed zdroj",
"API_EmbedCacheExpirationDays": "Počet dní expirace cache embed",
"API_EmbedDisabledFor": "Zakázat vložený obsah pro uživatele",
"API_EmbedDisabledFor_Description": "Čárkami oddělený seznam uživatelských jmen",
@@ -170,13 +210,20 @@
"API_EmbedIgnoredHosts_Description": "Čárkami oddělený seznam hostitelů nebo adres CIDR, např. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Bezpečné Porty",
"API_EmbedSafePorts_Description": "Čárkami oddělený seznam portů povolených pro zobrazení náhledu.",
+ "API_Enable_CORS": "Povolit CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "Povolit Endpoint přímých zpráv",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Povolí endpoint `/api/v1/im.history.others` přes který lze stahovat přímé zprávy mezi všemi uživateli.",
+ "API_Enable_Shields": "Povolit sdílecí ikony",
+ "API_Enable_Shields_Description": "Ikony dostupné na adrese `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "Adresa URL serveru",
"API_GitHub_Enterprise_URL_Description": "Příklad: http://domain.com (bez lomítka na konci)",
"API_Gitlab_URL": "GitLab URL",
+ "API_Shield_Types": "Typy ikon",
+ "API_Shield_Types_Description": "Čárkou oddělený seznam povolených typů. Na výběr z `online`, `channel` nebo `*` pro všechny.",
"API_Token": "API Token",
"API_Upper_Count_Limit": "Maximální počet",
"API_Upper_Count_Limit_Description": "Kolik nejvíce záznamů smí REST API vrátit (pokud není limitovaná)",
- "API_User_Limit": "Maximální počet uživatelů přidaných do místnosti",
+ "API_User_Limit": "Uživatelský limit pro přidání všech uživatelů do Channel",
"API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Klíč",
"Apiai_Language": "Api.ai Jazyk",
@@ -186,19 +233,31 @@
"Application_updated": "Aplikace aktualizována",
"Apply_and_refresh_all_clients": "Použít a aktualizovat všechny klienty",
"Archive": "Archiv",
+ "archive-room": "Archivovat místnost",
+ "archive-room_description": "Právo archivovat místnost",
"are_also_typing": "také píší",
"are_typing": "píše",
"Are_you_sure": "Jste si jisti?",
"Are_you_sure_you_want_to_delete_your_account": "Jste si jisti, že chcete smazat svůj účet?",
+ "assign-admin-role": "Přiřadit roli administrátora",
+ "assign-admin-role_description": "Právo přiřadit roli administrátora dalším uživatelům",
"Assign_admin": "Přiřadit administrátora",
"at": "v",
"AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Soubor nahrán",
+ "Attribute_handling": "Operace s atributy",
+ "Audio_message": "Audio zpráva",
+ "Audio_Notification_Value_Description": "Jakýkoliv z výchozích zvuků: beep, chelle, ding, droplet, highbell, seasons",
+ "Audio_Notifications_Default_Alert": "Výchozí zvuk upozornění audia",
+ "Audio_Notifications_Value": "Výchozí zvuk upozornění zprávy",
"Auth_Token": "Auth Token",
"Author": "Autor",
"Authorization_URL": "URL autorizace",
"Authorize": "Povolit",
+ "auto-translate": "Auto překlad",
+ "auto-translate_description": "Právo používat automatické překládání",
"Auto_Load_Images": "Automaticky načítat obrázky",
+ "Auto_Translate": "Automatický překlad",
"AutoLinker_Email": "AutoLinkovat Email",
"AutoLinker_Phone": "AutoLinkovat Telefon",
"AutoLinker_Phone_Description": "Automaticky odkazovat na telefonní čísla. např `(123) 456-7890`",
@@ -208,6 +267,11 @@
"AutoLinker_Urls_TLD": "AutoLinkovat TLD (např. '.cz') adresy",
"AutoLinker_Urls_www": "AutoLinkovat adresy s 'www'",
"AutoLinker_UrlsRegExp": "AutoLinkovat URL odpovídající regulárnímu výrazu",
+ "Automatic_Translation": "Automatický překlad",
+ "AutoTranslate_Change_Language_Description": "Změna jazyka automatického překladu nepřekládá předchozí zprávy.",
+ "AutoTranslate_Enabled": "Povolit automatický překlad",
+ "AutoTranslate_Enabled_Description": "Povolení automatického překladu umožní uživatelům s auto-translate právy nechat si přeložit všechny zprávy do jejich jazyka. Služba je zpoplatněná, viz dokumentace Google .",
+ "AutoTranslate_GoogleAPIKey": "Google API klíč",
"Available": "Dostupný",
"Available_agents": "Dostupní operátoři",
"Avatar": "Avatar",
@@ -222,9 +286,14 @@
"Away_male": "Pryč",
"Back": "Zpět",
"Back_to_applications": "Zpět k aplikacím",
+ "Back_to_chat": "Zpět do konverzace",
+ "Back_to_integration_detail": "Zpět na detail integrace",
"Back_to_integrations": "Zpět k integracím",
"Back_to_login": "Zpět na přihlašovací formulář",
"Back_to_permissions": "Zpět na práva",
+ "Backup_codes": "Záložní kódy",
+ "ban-user": "Zabanovat uživatele",
+ "ban-user_description": "Právo vykázat uživatele z místnosti",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta funkcionalita. Videohovory musí být povoleny.",
"Block_User": "Blokovat uživatele",
"Body": "Obsah",
@@ -233,7 +302,12 @@
"BotHelpers_userFields": "Uživatelská pole",
"BotHelpers_userFields_Description": "CSV uživatelských polí, která budou přístupná botům",
"Branch": "Větev",
+ "Broadcast_Connected_Instances": "Připojené instance",
"Bugsnag_api_key": "Bugsnag API klíč",
+ "bulk-create-c": "Hromadné vytvoření místností",
+ "bulk-create-c_description": "Právo hromadné vytvářet místnosti",
+ "bulk-register-user": "Hromadné vytvoření místností",
+ "bulk-register-user_description": "Právo hromadné vytvářet místnosti",
"busy": "zaneprázdněný",
"Busy": "Zaneprázdněný",
"busy_female": "zaneprázdněná",
@@ -245,13 +319,15 @@
"Cancel": "Zrušit",
"Cancel_message_input": "Zrušit",
"Cannot_invite_users_to_direct_rooms": "Do přímé konverzace nelze pozvat uživatele.",
+ "Cannot_open_conversation_with_yourself": "Nelze psát sám sobě",
"CAS_autoclose": "Automaticky zavřít přihlašovací popup",
"CAS_base_url": "SSO URL",
"CAS_base_url_Description": "Adresa vaší externí SSO služby např: https://sso.priklad.cz/sso/",
"CAS_button_color": "Barva pozadí tlačítka přihlásit",
- "CAS_button_label_color": "Barva textu login přihlásit",
+ "CAS_button_label_color": "Barva textu tlačítka přihlásit",
"CAS_button_label_text": "Text tlačítka přihlásit",
"CAS_enabled": "Povoleno",
+ "CAS_Login_Layout": "Rozložení CAS přihlášení",
"CAS_login_url": "SSO přihlašovací URL",
"CAS_login_url_Description": "Adresa přihlášení vaší externí SSO služby např: https://sso.priklad.cz/sso/login",
"CAS_popup_height": "Výška přihlašovacího popupu",
@@ -264,21 +340,27 @@
"CAS_version_Description": "Zvolte verzi CAS podporovanou vaší CAS SSO službou",
"CDN_PREFIX": "CDN Prefix",
"Certificates_and_Keys": "Certifikáty a klíče",
- "Changing_email": "Změna e-mailu",
"Change_Room_Type": "Změna typu místnosti",
+ "Changing_email": "Změna e-mailu",
"channel": "místnost",
"Channel": "Místnost",
"Channel_already_exist": "Místnost '#%s' již existuje.",
+ "Channel_already_exist_static": "Místnost již existuje",
"Channel_already_Unarchived": "Místnost `#%s` je již v odarchivovaném stavu",
"Channel_Archived": "Místnost `#%s` byla úspěšně archivována",
+ "Channel_created": "Místnost `#%s` byla vytvořena.",
"Channel_doesnt_exist": "Místnost `# %s` neexistuje.",
+ "Channel_name": "Název místnosti",
+ "Channel_Name_Placeholder": "Zadejte název místnosti...",
"Channel_to_listen_on": "Poslouchat místnost",
"Channel_Unarchived": "Místnost `#%s` byla úspěšně odarchivována",
"Channels": "Místnosti",
+ "Channels_are_where_your_team_communicate": "Místnosti jsou pro komunikaci vašich týmů",
"Channels_list": "Seznam veřejných místnosti",
"Chat_button": "Chat Tlačítko",
"Chat_closed": "Místnost uzavřena",
"Chat_closed_successfully": "Místnost úspěšně uzavřena",
+ "Chat_Now": "Chatovat nyní",
"Chat_window": "Chat okno",
"Chatops_Enabled": "Aktivovat Chatops",
"Chatops_Title": "Chatops Panel",
@@ -287,15 +369,24 @@
"Choose_messages": "Výberte zprávy",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Vyberte alias, který se objeví před uživatelským jménem ve zprávách.",
"Choose_the_username_that_this_integration_will_post_as": "Vyberte uživatelské jméno, za které bude tato integrace posílat zprávy.",
+ "clean-channel-history": "Pročistit historii místnosti",
+ "clean-channel-history_description": "Právo pročistit historii místnosti",
"clear": "Vyčistit",
- "clear_cache_now": "Vyčistit cache",
"Clear_all_unreads_question": "Označit vše jako přečtené?",
+ "clear_cache_now": "Vyčistit cache nyní",
+ "clear_history": "Smazat historii",
"Click_here": "Klikněte zde",
+ "Click_here_for_more_info": "Klikněte pro více infomací",
+ "Click_to_join": "Klikněte pro připojení!",
"Client_ID": "ID klienta",
"Client_Secret": "Secret klienta",
"Clients_will_refresh_in_a_few_seconds": "Klienti se obnoví během několika sekund",
"close": "zavřít",
"Close": "Zavřít",
+ "close-livechat-room": "Uzavřít LiveChat místnost (aktuální)",
+ "close-livechat-room_description": "Právo uzavřít svou LiveChat místnost",
+ "close-others-livechat-room": "Uzavřít LiveChat místnost (ostatní)",
+ "close-others-livechat-room_description": "Právo uzavřít ostatní LiveChat místnosti",
"Closed": "Zavřeno",
"Closed_by_visitor": "Ukončeno návštěvníkem",
"Closing_chat": "Uzavření místnosti",
@@ -305,6 +396,7 @@
"Comment_to_leave_on_closing_session": "Okomentovat odchod",
"Compact": "Kompaktní",
"Confirm_password": "Potvrďte heslo",
+ "Content": "Obsah",
"Conversation": "Konverzace",
"Conversation_closed": "Konverzace uzavřena: __comment__.",
"Convert_Ascii_Emojis": "Převod ASCII na Emoji",
@@ -315,14 +407,25 @@
"Count": "Počet",
"Cozy": "Útulný",
"Create": "Vytvořit",
+ "create-c": "Vytvářet veřejné místnosti",
+ "create-c_description": "Právo vytvářet veřejné místnosti",
+ "create-d": "Vytvářet soukromé zprávy",
+ "create-d_description": "Právo odesílat soukromé zprávy",
+ "create-p": "Vytvářet soukromé místnosti",
+ "create-p_description": "Právo vytvářet soukromé místnosti",
+ "create-user": "Vytvořit uživatele",
+ "create-user_description": "Právo vytvořit uživatele",
"Create_A_New_Channel": "Vytvořit novou místnost",
"Create_new": "Vytvořit nový",
"Created_at": "Vytvořeno ",
"Created_at_s_by_s": "Vytvořeno v %s %s ",
+ "Created_at_s_by_s_triggered_by_s": "Vytvořeno ve %s %s vyvoláno %s ",
+ "CRM_Integration": "Integrace CRM",
"CROWD_Reject_Unauthorized": "Zamítnout neutorizované",
"Current_Chats": "Aktuální Místnosti",
+ "Current_Status": "Aktuální stav",
"Custom": "Vlastní",
- "Custom_Emoji": "Vlastní emotikona",
+ "Custom_Emoji": "Vlastní emotikony",
"Custom_Emoji_Add": "Přidat novou emotikonu",
"Custom_Emoji_Added_Successfully": "Vlastní emotikona přidána",
"Custom_Emoji_Delete_Warning": "Smazání emotikony nelze vzít zpět",
@@ -336,8 +439,18 @@
"Custom_oauth_unique_name": "Název vlastní OAuth",
"Custom_Script_Logged_In": "Vlastní skripty pro přihlášené uživatele",
"Custom_Script_Logged_Out": "Vlastní skripty pro odhlášené uživatele",
+ "Custom_Scripts": "Vlastní skripty",
+ "Custom_Sound_Add": "Přidat vlastní zvuk",
+ "Custom_Sound_Delete_Warning": "Smazání zvuku je nevratná operace.",
+ "Custom_Sound_Error_Invalid_Sound": "Neplatný soubor zvuku",
+ "Custom_Sound_Error_Name_Already_In_Use": "Tento vlastní zvuk se již používá.",
+ "Custom_Sound_Has_Been_Deleted": "Vlastní zvuk byl smazán.",
+ "Custom_Sound_Info": "Informace vlastního zvuku",
+ "Custom_Sound_Saved_Successfully": "Vlastní zvuk úspěšně uložen",
+ "Custom_Sounds": "Vlastní zvuky",
"Custom_Translations": "Vlastní překlady",
- "Custom_Translations_Description": "Validní JSON obsahující slovník. Například {\n \"en\": {\n \"key\": \"translation\"\n },\n \"pt\": {\n \"key\": \"tradução\"\n }\n}",
+ "Custom_Translations_Description": "Validní JSON obsahující slovník. Například {\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n}",
+ "CustomSoundsFilesystem": "Filesystem vlastních zvuků",
"Dashboard": "Hlavní panel",
"Date": "Datum",
"Date_From": "Od",
@@ -349,10 +462,20 @@
"Decline": "Zamítnout",
"Default": "Výchozí",
"Delete": "Smazat",
+ "delete-c": "Smazat veřejné místnosti",
+ "delete-c_description": "Právo smazat veřejné místnosti",
+ "delete-d": "Smazat přímé zprávy",
+ "delete-d_description": "Právo smazat přímé zprávy",
+ "delete-message": "Smazat zprávu",
+ "delete-message_description": "Právo smazat zprávu v místnosti",
+ "delete-p": "Smazat soukromé místnosti",
+ "delete-p_description": "Právo smazat soukromé místnosti",
+ "delete-user": "Smazat uživatele",
+ "delete-user_description": "Právo smazat uživatele",
"Delete_message": "Smazat zprávu",
"Delete_my_account": "Smazat můj účet",
- "Delete_Room_Warning": "Odstranění místnosti smaže všechny zprávy poslané v rámci místnosti. Toto nelze vrátit zpět!",
- "Delete_User_Warning": "Odstranění uživatele smaže také všechny zprávy od daného uživatele. Toto nelze vrátit zpět!",
+ "Delete_Room_Warning": "Odstranění místnosti smaže všechny zprávy poslané v rámci místnosti. Tuto akci nelze vzít zpět!",
+ "Delete_User_Warning": "Odstranění uživatele smaže také všechny jeho zprávy. Tuto akci nelze vzít zpět!",
"Deleted": "Smazáno!",
"Department": "Oddělení",
"Department_removed": "Oddělení odstraněno",
@@ -362,12 +485,32 @@
"Desktop": "Plocha",
"Desktop_Notification_Test": "Test oznámení na ploše",
"Desktop_Notifications": "Oznámení na ploše",
+ "Desktop_Notifications_Default_Alert": "Výchozí upozornění oznámení na ploše",
"Desktop_Notifications_Disabled": "Oznámení na ploše jsou vypnuta. Změňte nastavení svého prohlížeče, pokud chcete oznámení povolit.",
"Desktop_Notifications_Duration": "Délka zobrazení notifikace",
"Desktop_Notifications_Duration_Description": "Délka zobrazení oznámení (v sekundách). Toto může ovlivnit nastevení OS X Oznamovacího centra. Zadejte 0 pro použítí výchozí nastavení prohlížeče/notifikačního centra OS X",
"Desktop_Notifications_Enabled": "Oznámení na ploše jsou povolena",
+ "Different_Style_For_User_Mentions": "Odlišný styl pro zmínky",
"Direct_message_someone": "Přímá zpráva někomu",
"Direct_Messages": "Přímé zprávy",
+ "Direct_Reply": "Přímá odpověď",
+ "Direct_Reply_Debug": "Debugovat přímou odpověď",
+ "Direct_Reply_Debug_Description": "[Pozor] Povolení Debug módu znamená zobrazení hesla v čitelné podobě v admin konzoli",
+ "Direct_Reply_Delete": "Smazat zachycené emaily",
+ "Direct_Reply_Enable": "Povolit přímou odpověď",
+ "Direct_Reply_Frequency": "Frekvenkce kontroly emailu",
+ "Direct_Reply_Frequency_Description": "(v minutách, výchozí/minimálně 2 minuty)",
+ "Direct_Reply_Host": "Hostitel pro přímé odpovědi",
+ "Direct_Reply_IgnoreTLS": "Ignorovat TLS",
+ "Direct_Reply_Password": "Heslo",
+ "Direct_Reply_Port": "Port pro přímé odpovědi",
+ "Direct_Reply_Protocol": "Protokol pro přímé odpovědi",
+ "Direct_Reply_Separator": "Oddělovač",
+ "Direct_Reply_Separator_Description": "[Upravte pouze pokud přesně víte co děláte - konzultujte dokumentaci] Separátor mezi hlavní a tagovací částí emailu",
+ "Direct_Reply_Username": "Uživatelské jméno",
+ "Direct_Reply_Username_Description": "Prosím použijte celý email, tagování není povoleno a bude přepsáno",
+ "Disable_Notifications": "Zakázat notifikace",
+ "Disable_two-factor_authentication": "Zakázat dvoufázové ověření",
"Display_offline_form": "Zobrazit offline formulář",
"Displays_action_text": "Zobrazuje text akce",
"Do_you_want_to_change_to_s_question": "Chcete změnit na %s? ",
@@ -375,18 +518,32 @@
"Domain_added": "Doména přidána",
"Domain_removed": "Doména odebrána",
"Domains": "Domény",
+ "Domains_allowed_to_embed_the_livechat_widget": "Čárkou oddělený seznam domén, kde se smí zobrazovat livechat. Pro povolení všech domén nechte prázdné",
"Download_Snippet": "Stáhnout",
"Drop_to_upload_file": "Pusťe soubor do okna pro jeho nahrání",
"Dry_run": "Zkouška",
"Dry_run_description": "Odešle pouze jeden e-mail, na stejnou adresu jako ve formuláři. K e-mailu musí patřit platný uživatel.",
"Duplicate_archived_channel_name": "Již existuje archivovaná místnost ' %s'",
- "Duplicate_archived_private_group_name": "Již existuje archivovaná privátní skupina s názvem ' %s'",
+ "Duplicate_archived_private_group_name": "Již existuje archivovaná soukromá skupina s názvem ' %s'",
"Duplicate_channel_name": "Místnost '%s' existuje",
- "Duplicate_private_group_name": "Privátní skupina s názvem ' %s' již existuje",
+ "Duplicate_private_group_name": "Soukromá skupina s názvem ' %s' již existuje",
"Duration": "Délka",
"Edit": "Editovat",
+ "edit-message": "Editovat zprávu",
+ "edit-message_description": "Právo editovat zprávu v místnosti",
+ "edit-other-user-active-status": "Právo měnit aktivaci uživatelů",
+ "edit-other-user-active-status_description": "Právo povolit nebo zakázat jiné uživatelské účty",
+ "edit-other-user-info": "Upravit informace uživatelů",
+ "edit-other-user-info_description": "Právo měnit jméno, uživatelské jméno nebo email jiným uživatelům",
+ "edit-other-user-password": "Měnit hesla uživatelů",
+ "edit-other-user-password_description": "Právo měnit heslo jiným uživatelům. Vyžaduje právo `Upravit informace uživatelů`",
+ "edit-privileged-setting": "Měnit nastavení",
+ "edit-privileged-setting_description": "Právo měnit nastavení",
+ "edit-room": "Upravit místnost",
+ "edit-room_description": "Právo měnit jméno, téma, typ (soukromá/veřejná) a stav (aktivní/archivovaná) místnosti",
"Edit_Custom_Field": "Upravit vlastní pole",
"Edit_Department": "Upravit oddělení",
+ "Edit_previous_message": "`%s` - Editovat předchozí zprávu",
"Edit_Trigger": "Upravit trigger",
"edited": "upraveno",
"Editing_room": "Úprava místnosti",
@@ -403,6 +560,7 @@
"Email_Notification_Mode_All": "Každá zmínka / Přímá zpráva",
"Email_Notification_Mode_Disabled": "Zakázáno",
"Email_or_username": "E-mail nebo uživatelské jméno",
+ "Email_Placeholder": "Zadejte svou e-mailovou adresu...",
"Email_subject": "Předmět",
"Email_verified": "Email ověřen",
"Emoji": "Emotikony",
@@ -410,14 +568,20 @@
"Empty_title": "Prázdný název",
"Enable": "Povolit",
"Enable_Desktop_Notifications": "Aktivovat oznámení na ploše",
- "Enabled": "Povoleno",
"Enable_Svg_Favicon": "Povolit SVG favikonu",
+ "Enable_two-factor_authentication": "Povolit dvoufázové ověření",
+ "Enabled": "Povoleno",
"Encrypted_message": "Šifrovaná zpráva",
"End_OTR": "Ukončit konverzaci mimo záznam",
"Enter_a_regex": "Zadejte regulární výraz",
"Enter_a_room_name": "Zadejte název místnosti",
"Enter_a_username": "Zadejte uživatelské jméno",
+ "Enter_Alternative": "Alternativní mód (odesílat po stisku Enter + Ctrl/Alt/Shift/CMD)",
+ "Enter_authentication_code": "Zadejte autentizační kód",
+ "Enter_Behaviour": "Chování klávesy enter",
+ "Enter_Behaviour_Description": "Mění zda se po stisknutí klávesy enter odesílá zpráva nebo přidává nový řádek",
"Enter_name_here": "Zadejte jméno",
+ "Enter_Normal": "Normální mód (odeslání po stisku klávesy enter)",
"Enter_to": "Enter",
"Error": "Chyba",
"error-action-not-allowed": "__action__ není povolena",
@@ -431,6 +595,7 @@
"error-could-not-change-username": "Nelze změnit uživatelské jméno",
"error-delete-protected-role": "Nelze odstranit chráněné role",
"error-department-not-found": "Oddělení nebylo nalezeno",
+ "error-direct-message-file-upload-not-allowed": "Sdílení souborů není v přímé konverzaci povoleno",
"error-duplicate-channel-name": "Místnost s názvem ' %s' již existuje",
"error-email-domain-blacklisted": "E-mailová doména není povolena",
"error-email-send-failed": "Nepodařilo se odeslat email: __message__",
@@ -452,7 +617,6 @@
"error-invalid-email-address": "Nevalidní email",
"error-invalid-file-height": "Neplatná výška souboru",
"error-invalid-file-type": "Neplatný typ souboru",
- "error-direct-message-file-upload-not-allowed": "Sdílení souborů není v přímé konverzaci povoleno",
"error-invalid-file-width": "Neplatná šířka souboru",
"error-invalid-from-address": "Špatná adresa FROM.",
"error-invalid-integration": "Neplatná integrace",
@@ -463,7 +627,7 @@
"error-invalid-redirectUri": "Neplatná URL přesměrování",
"error-invalid-role": "Neplatná role",
"error-invalid-room": "Neplatná místnost",
- "error-invalid-room-name": "__room_name__ není platný název místnosti, použijte pouze písmena, číslice, pomlčky a podtržítka",
+ "error-invalid-room-name": "__room_name__ není platný název místnosti",
"error-invalid-room-type": "__type__ není platný typ místnosti.",
"error-invalid-settings": "Neplatné nastavení",
"error-invalid-subscription": "Neplatné přihlášení",
@@ -487,63 +651,84 @@
"error-the-field-is-required": "Je vyžadováno pole __field__.",
"error-too-many-requests": "Chyba, příliš mnoho požadavků. Prosím zpomalte. Vyčkejte __seconds__ sekund před dalším pokusem.",
"error-user-is-not-activated": "Uživatel není aktivován",
+ "error-user-limit-exceeded": "Počet uživatelů, které chcete pozvat do #channel_name překračuje maximální počet nastavený administrátorem",
"error-user-not-in-room": "Uživatel není v této místnosti",
"error-user-registration-disabled": "Registrace je zakázána",
"error-user-registration-secret": "Registrace uživatele je povolena pouze přes tajnou URL",
"error-you-are-last-owner": "Jste poslední vlastníkem místnosti. Před opuštěním místnosti prosím nastavte nového vlastníka.",
"Error_changing_password": "Chyba změny hesla",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Chyba: Rocket.Chat vyžaduje tail oplogu pokud běží na více instancích.",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Prověřte, že je MongoDB v ReplicaSet módu a proměnná prostředí MONGO_OPLOG_URL je na aplikačním serveru nastavena správně",
"Esc_to": "Esc",
+ "Event_Trigger": "Vyvolání události",
+ "Event_Trigger_Description": "Zvolte jaký typ události vyvolá tuto odchozí webhook integraci",
"every_30_minutes": "Jednou za 30 minut",
"every_hour": "Jednou za hodinu",
"every_six_hours": "Jednou za 6 hodin",
+ "Everyone_can_access_this_channel": "Tato místnost je přístupná všem",
"Example_s": "Příklad: %s",
- "Exclude_Botnames": "Vyjmout boty",
+ "Exclude_Botnames": "Vyloučit boty",
"Exclude_Botnames_Description": "Nepřevádět v potaz zprávy botu, jejichž jména odpovídají výše uvedenému regulárnímu výrazu. Pokud je pole prázdné, budou převedeny zprávy všech botů",
"False": "Ne",
"Favorite_Rooms": "Aktivovat oblíbené místnosti",
"Favorites": "Oblíbené",
- "Features_Enabled": "Funkce Povoleny",
+ "Features_Enabled": "Povolené funkce",
"Field": "Pole",
"Field_removed": "Pole odebráno",
"Field_required": "Pole vyžadováno",
"File_exceeds_allowed_size_of_bytes": "Soubor překračuje povolenou velikost __size__ bajtů",
"File_not_allowed_direct_messages": "Sdílení souborů není v přímé konverzaci povoleno.",
"File_type_is_not_accepted": "Neplatný typ souboru",
+ "File_uploaded": "Soubor nahrán",
"FileUpload": "Nahrání souboru",
- "FileUpload_Enabled": "Nahrávání souborů povoleno",
"FileUpload_Disabled": "Nahrávání souborů je zakázáno.",
+ "FileUpload_Enabled": "Povolit nahrávání souborů",
"FileUpload_Enabled_Direct": "Nahrávání souborů povoleno v přímé konverzaci",
"FileUpload_File_Empty": "Soubor je prázdný",
"FileUpload_FileSystemPath": "Cesta pro nahrávané soubory",
+ "FileUpload_GoogleStorage_AccessId": "Přístupové Id Google Storage",
+ "FileUpload_GoogleStorage_AccessId_Description": "Zpravidla ve formátu emailu, např.: \"example-test@example.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Bucket v Google Storage",
+ "FileUpload_GoogleStorage_Bucket_Description": "Jméno bucketu do kterého nahrávat soubory.",
+ "FileUpload_GoogleStorage_Secret": "Google Storage Secret",
+ "FileUpload_GoogleStorage_Secret_Description": "Prosím říďte se těmito instrukcemi a výsledek vložte zde.",
"FileUpload_MaxFileSize": "Maximální velikost nahrávaného souboru (v bytech)",
"FileUpload_MediaType_NotAccepted": "Typ souboru nelze přijmout",
"FileUpload_MediaTypeWhiteList": "Povolené typy souborů",
"FileUpload_MediaTypeWhiteListDescription": "Čárkami oddělený seznam typů souborů. Pokud nechcete omezovat typy, ponechte pole prázdné.",
"FileUpload_ProtectFiles": "Chránit nahrané soubory",
"FileUpload_ProtectFilesDescription": "Pouze ověření uživatelé budou mít přístup",
- "FileUpload_S3_Acl": "Amazon S3 acl",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 název bucketu",
+ "FileUpload_S3_Acl": "Acl",
+ "FileUpload_S3_AWSAccessKeyId": "Přístupový klíč",
+ "FileUpload_S3_AWSSecretAccessKey": "Tajný klíč",
+ "FileUpload_S3_Bucket": "Název bucketu",
"FileUpload_S3_BucketURL": "URL Bucketu",
- "FileUpload_S3_CDN": "CDN doména",
+ "FileUpload_S3_CDN": "CDN doména pro stahování",
+ "FileUpload_S3_ForcePathStyle": "Vynutit Path Style",
"FileUpload_S3_Region": "Region",
+ "FileUpload_S3_SignatureVersion": "Verze Signature",
"FileUpload_S3_URLExpiryTimeSpan": "Časová expirace URL adres",
"FileUpload_S3_URLExpiryTimeSpan_Description": "Doba po které URL adresy z Amazon S3 nebudou platné (v sekundách) Musí být více než 5 sekund jinak bude ignorováno",
"FileUpload_Storage_Type": "Typ úložiště",
+ "First_Channel_After_Login": "Výchozí místnost po přihlášení",
"Flags": "Vlajky",
"Follow_social_profiles": "Sledujte naše sociální profily, forkněte si nás na githubu a sdílejte své myšlenky o rocket.chat app na našem Trello boardu.",
+ "Fonts": "Fonty",
"Food_and_Drink": "Jídlo & pití",
"Footer": "Zápatí",
+ "Footer_Direct_Reply": "Patička pro přímé odpovědi",
"For_your_security_you_must_enter_your_current_password_to_continue": "Pro vaši bezpečnost, je nutné znovu zadat heslo pro pokračování",
+ "force-delete-message": "Smazat zprávu",
+ "force-delete-message_description": "Právo smazat zprávu přes všechna omezení",
"Force_Disable_OpLog_For_Cache": "Vynucené vypnutí OpLogu pro cache",
"Force_Disable_OpLog_For_Cache_Description": "I pokud je dostupný OpLog se nebude používat pro synchronizaci cache",
"Force_SSL": "Vynutit SSL",
"Force_SSL_Description": "* Pozor! * volba _Vynutit SSL_ by nikdy neměla být používána s reverzní proxy. Máte-li reverzní proxy, řešte přesměrování tam. Tato možnost je pouze pro služby jako Heroku které toto neumožňují",
"Forgot_password": "Zapomněli jste heslo?",
"Forgot_Password_Description": "Můžete použít následující zástupné symboly: [Forgot_Password_Url] pro adresu stránky na obnovu hesla [name] pro celé jméno, [fname] pro křestní jméno a [lname] pro příjmení uživatele. [email] pro email uživatelé. [Site_Name] pro název a [Site_URL] pro a URL stránky. ",
- "Forgot_Password_Email_Subject": "[Site_Name] - Obnova Hesla",
"Forgot_Password_Email": "Klikněte na tento odkaz pro obnovení vašeho hesla.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Obnova Hesla",
+ "Forgot_password_section": "Zapomenuté heslo",
"Forward": "Přeposlat",
"Forward_chat": "Přeposlat konverzaci",
"Forward_to_department": "Přeposlat oddělení",
@@ -558,17 +743,43 @@
"Give_a_unique_name_for_the_custom_oauth": "Zadejte jedinečný název pro vlastní OAuth",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Pojmenujte jak se bude aplikace jmenovat pro Vaše uživatele.",
"Global": "Globální",
+ "Google_Vision_usage_limit_exceeded": "Kvóta pro použití Google Vision překročena",
+ "GoogleCloudStorage": "Google Cloud Storage",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "JSON klíč účtu služby. Více informací naleznete [zde](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "ID Google tag manageru",
+ "GoogleVision_Block_Adult_Images": "Blokovat obrázky nevhodné pro mladistvé",
+ "GoogleVision_Block_Adult_Images_Description": "Blokování nevhodných obrázků nebude fungovat po dosažení měsíční kvóty",
+ "GoogleVision_Current_Month_Calls": "Počet hovorů v aktuálním měsíci",
+ "GoogleVision_Enable": "Povolit Google Vision",
+ "GoogleVision_Max_Monthly_Calls": "Maximum hovorů v měsíci",
+ "GoogleVision_Max_Monthly_Calls_Description": "Zadejte 0 pro neomezený počet",
+ "GoogleVision_ServiceAccount": "Účet Google Vision",
+ "GoogleVision_ServiceAccount_Description": "Vytvořte serverový klíč (JSON formát) a vložte jej zde",
+ "GoogleVision_Type_Document": "Detekce textu dokumentu",
+ "GoogleVision_Type_Faces": "Detekce obličejů",
+ "GoogleVision_Type_Labels": "Detekce štítků/popisků",
+ "GoogleVision_Type_Landmarks": "Detekce orientačních bodů",
+ "GoogleVision_Type_Logos": "Detekce loga",
+ "GoogleVision_Type_Properties": "Detekce vlastností (barev)",
+ "GoogleVision_Type_SafeSearch": "Detekce SafeSearch",
+ "GoogleVision_Type_Similar": "Vyhledat podobné obrázky",
+ "Group_mentions_only": "Pouze notifikace skupiny",
"Guest_Pool": "Skupina hostů",
"Hash": "Hash",
"Header": "Hlavička",
+ "Header_and_Footer": "Hlavička a Patička",
+ "Helpers": "Nápovědy",
+ "Hex_Color_Preview": "Náhled barvy podle Hex kódu",
"Hidden": "Schovaný",
"Hide_Avatars": "Skrýt avatary",
"Hide_flextab": "Schovat pravou nabídku po kliknutí",
"Hide_Group_Warning": "Jste si jisti, že chcete skrýt skupiny \"%s\"?",
+ "Hide_Livechat_Warning": "Opravdu chcete skrýt LiveChat s \"%s\"?",
"Hide_Private_Warning": "Jste si jisti, že chcete skrýt diskusi s \"%s\"?",
+ "Hide_roles": "Schovat role",
"Hide_room": "Skrýt místnost",
"Hide_Room_Warning": "Jste si jisti, že chcete skrýt místnost \"%s\"?",
+ "Hide_Unread_Room_Status": "Schovat stav nepřečtených místností",
"Hide_usernames": "Skrýt uživatelská jména",
"Highlights": "Klíčová slova",
"Highlights_How_To": "Chcete-li být upozorněni, když někdo zmíní slovo nebo frázi, přidejte jej sem. Můžete oddělit slova nebo fráze čárkami. Velikost písmen nehraje roli",
@@ -583,8 +794,10 @@
"How_responsive_was_the_chat_agent": "Odpovídal operátor rychle?",
"How_satisfied_were_you_with_this_chat": "Jak jste byli celkově spokojeni?",
"How_to_handle_open_sessions_when_agent_goes_offline": "Co dělat s chaty když je operátor offline",
+ "If_this_email_is_registered": "Pokud je e-mail v naší databázi, odešleme na něj instrukce pro reset hesla. Pokud vám e-mail nepřijde během chvilky, prosím vraťte se a zkuste to znova.",
"If_you_are_sure_type_in_your_password": "Pokud si jste jisti, zadejte své heslo:",
"If_you_are_sure_type_in_your_username": "Pokud jste si jisti, zadejte své uživatelské jméno:",
+ "Iframe_Integration": "Iframe Integrace",
"Iframe_Integration_receive_enable": "Povolit příjem",
"Iframe_Integration_receive_enable_Description": "Povolit původnímu oknu odesílat požadavky na Rocket.Chat",
"Iframe_Integration_receive_origin": "Povolené domény",
@@ -593,13 +806,18 @@
"Iframe_Integration_send_enable_Description": "Odesílat události do původního okna",
"Iframe_Integration_send_target_origin": "Odesílat cílovou doménu",
"Iframe_Integration_send_target_origin_Description": "Jen stránky z povolených domén můžou čekat na události. `*` pro povolení všech domén. Lze vložit více hodnot oddělených `,`. Například `http://localhost,https://localhost`",
+ "IMAP_intercepter_already_running": "Zachytávání IMAP již běží",
+ "IMAP_intercepter_Not_running": "Zachytávání IMAP neběží",
+ "Impersonate_user": "Vydávat se za uživatele",
+ "Impersonate_user_description": "Pokud je povoleno, integrace posílá za uživatele, který ji vyvolal",
+ "Import": "Import",
"Importer_Archived": "Archivováno",
"Importer_CSV_Information": "CSV import vyžaduje specifický formát. Informace o tom, jak strukturovat váš zip soubor najdete v dokumentaci:",
- "Importer_HipChatEnterprise_Information": "Nahraný soubor musí být nešifrovaný tar.gz, Více informací naleznete v dokumentaci:",
- "Importer_HipChatEnterprise_BetaWarning": "Mějte prosím na paměti, že tato funkcionalita je stále ve vývoji, prosím nahlašte nám jakékoliv chyby přes github:",
"Importer_done": "Import dokončen!",
"Importer_finishing": "Dokončuji import.",
"Importer_From_Description": "Import dat __from__ do Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Mějte prosím na paměti, že tato funkcionalita je stále ve vývoji, prosím nahlašte nám jakékoliv chyby přes github:",
+ "Importer_HipChatEnterprise_Information": "Nahraný soubor musí být nešifrovaný tar.gz, Více informací naleznete v dokumentaci:",
"Importer_import_cancelled": "Import zrušen.",
"Importer_import_failed": "Došlo k chybě při importu.",
"Importer_importing_channels": "Importuji místnosti.",
@@ -615,7 +833,9 @@
"Importer_progress_error": "Nepodařilo se získat postup importu.",
"Importer_setup_error": "Při nastavování nástroje pro import došlo k chybě.",
"Importer_Source_File": "Výběr zdrojového souboru",
- "Incoming_Livechats": "Příchozí požadavky na livechat",
+ "Incoming_Livechats": "Příchozí požadavky na LiveChat",
+ "Incoming_WebHook": "Příchozí webhook",
+ "initials_avatar": "Avatar z iniciál jména uživatele",
"inline_code": "vlozeny_kod",
"Install_Extension": "Nainstalovat rozšíření",
"Install_FxOs": "Nainstalovat Rocket.Chat do Vašeho Firefoxu",
@@ -624,19 +844,51 @@
"Install_FxOs_follow_instructions": "Prosím potvrďte instalaci aplikace na Vašem přístroji (stiskněte tlačítko \"Install\" po výzvě).",
"Installation": "Instalace",
"Installed_at": "instalováno v",
+ "Instance_Record": "ID Instance",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Pokyny pro Vaše návštěvníky k vyplnění formulář pro odeslání zprávy",
- "Impersonate_user": "Vydávat se za uživatele",
- "Impersonate_user_description": "Pokud je povoleno, integrace posílá za uživatele, který ji vyvolal",
"Integration_added": "Integrace byla přidána",
+ "Integration_Advanced_Settings": "Pokročilé nastavení",
+ "Integration_History_Cleared": "Historie integrace smazána",
"Integration_Incoming_WebHook": "Příchozí WebHook Integrace",
"Integration_New": "Nová integrace",
"Integration_Outgoing_WebHook": "Odchozí WebHook Integrace",
+ "Integration_Outgoing_WebHook_History": "Historie odchozího webhooku",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Data předána integraci",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Data předána na URL",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Stacktrace chyby",
+ "Integration_Outgoing_WebHook_History_Http_Response": "HTTP odpověď",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "Chyba HTTP odpovědi",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Zprávy odeslané v přípravném kroku",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Zprávy odeslané v zpracovacím kroku",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Čas skončení s chybou",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Čas spuštění intergrace",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "Poslední spuštěný krok",
+ "Integration_Outgoing_WebHook_No_History": "Tento odchozí webhook ještě nemá žádnou zaznamenanou historii",
+ "Integration_Retry_Count": "Počet pokusů po neúspěšném volání",
+ "Integration_Retry_Count_Description": "Kolikrát by se integrace měla znova pokusit volat URL pokud byl první pokus neúspěšný?",
+ "Integration_Retry_Delay": "Čas prodlení opakování",
+ "Integration_Retry_Delay_Description": "Jaký algoritmus prodlení by se měl použít?10^x, 2^x nebo x*2",
+ "Integration_Retry_Failed_Url_Calls": "Znovu zavolat neúspěšná volání",
+ "Integration_Retry_Failed_Url_Calls_Description": "Měla by integrace po rozumnou dobu zkusit odeslat volání znova pokud se předtím nezdařilo?",
+ "Integration_Run_When_Message_Is_Edited": "Spustit při editaci",
+ "Integration_Run_When_Message_Is_Edited_Description": "Měla by být integrace spuštěna po editaci zprávy? Pokud volbu vypnete, integrace se bude spouštět pouze pro nové zprávy.",
"Integration_updated": "Integrace byla aktualizována",
+ "Integration_Word_Trigger_Placement": "Přepisování slov kdekoliv",
+ "Integration_Word_Trigger_Placement_Description": "Mělo by se vyvolat pokud je slovo umístěno jinde než na začátku?",
"Integrations": "Integrace",
"Integrations_for_all_channels": "Zadejte all_public_channels pro poslouchání nad všemi otevřenými místnostmi, all_private_groups pro všechny soukromé místnosti a all_direct_messages pro poslouchání přímých konverzací",
+ "Integrations_Outgoing_Type_FileUploaded": "Soubor nahrán",
+ "Integrations_Outgoing_Type_RoomArchived": "Místnost archivována",
+ "Integrations_Outgoing_Type_RoomCreated": "Místnost vytvořena (veřejná a soukromá)",
+ "Integrations_Outgoing_Type_RoomJoined": "Uživatel se přidal do místnosti",
+ "Integrations_Outgoing_Type_RoomLeft": "Uživatel opustil místnost",
+ "Integrations_Outgoing_Type_SendMessage": "Zpráva odeslána",
+ "Integrations_Outgoing_Type_UserCreated": "Uživatel vytvořen",
"InternalHubot": "Interní Hubot",
- "InternalHubot_ScriptsToLoad": "Načíst skripty",
- "InternalHubot_ScriptsToLoad_Description": "Prosím, zadejte čárkami oddělený seznam skriptů k načtení z https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_PathToLoadCustomScripts": "Složka odkud načíst skripty",
+ "InternalHubot_reload": "Znovu načíst skripty",
+ "InternalHubot_ScriptsToLoad": "Skripty k načtení",
+ "InternalHubot_ScriptsToLoad_Description": "Prosím, zadejte čárkami oddělený seznam skriptů k načtení z https://github.com/github/hubot-scripts/tree/master/src/scripts umístěných ve vaší složce",
"InternalHubot_Username_Description": "Musí být platné uživatelské jméno jednoho z botů registrovaných na tomto serveru.",
"Invalid_confirm_pass": "Hesla nesouhlasí",
"Invalid_email": "Zadaný e-mail je neplatný",
@@ -645,42 +897,54 @@
"Invalid_name": "Název nesmí být prázdný",
"Invalid_notification_setting_s": "Neplatné nastavení upozornění: %s",
"Invalid_pass": "Heslo nesmí být prázdné",
- "Invalid_room_name": "%s není platné jméno místnosti, použijte pouze písmena, číslice a pomlčky",
+ "Invalid_room_name": "%s není platné jméno místnosti.",
"Invalid_secret_URL_message": "Adresa URL je neplatná.",
+ "Invalid_setting_s": "Neplatné nastavení: %s",
+ "Invalid_two_factor_code": "Neplatný dvoufázový kód",
"invisible": "neviditelný",
"Invisible": "Neviditelný",
+ "Invitation": "Pozvánka",
"Invitation_HTML": "HTML tělo pozvánky",
"Invitation_HTML_Default": "Vítejte v [Site_Name] Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!
",
"Invitation_HTML_Description": "Můžete použít následující proměnné: [email] - adresátův e-mail. [Site_Name] a [Site_URL] název a URL aplikace. ",
"Invitation_Subject": "Předmět pozvánky",
"Invitation_Subject_Default": "Byli jste pozváni na [Site_Name]",
"Invite_user_to_join_channel": "Pozvat jednoho uživatele, aby se připojil k této místnosti",
+ "Invite_user_to_join_channel_all_from": "Pozvat všechny uživatele v [#channel] do této místnosti",
+ "Invite_user_to_join_channel_all_to": "Pozvat všechny uživatele v této místnosti do [#channel]",
"Invite_Users": "Pozvat uživatele",
- "is_also_typing": "také píše",
- "is_also_typing_female": "také píše",
- "is_also_typing_male": "také píše",
- "is_typing": "píše",
- "is_typing_female": "píše",
- "is_typing_male": "píše",
"IRC_Channel_Join": "Výstup JOIN příkazu",
"IRC_Channel_Leave": "Výstup PART příkazu",
- "IRC_Description": "Internet Relay Chat (IRC) je nástroj pro textovou komunikaci. Uživatelé komunikují otevřeně v unikátně pojmenovaných místnostech. IRC také podporuje přímé zprávy mezi dvěma uživateli a sdílení souborů. Tento modul integruje tyto vlastnosti do Rocket.Chatu.",
- "IRC_Enabled": "Pokusit se integrovat IRC. Změna vyžaduje restart Rocket.Chatu",
- "IRC_Private_Message": "Výstup PRIVMSG příkazu",
"IRC_Channel_Users": "Výstup NAMES příkazu",
"IRC_Channel_Users_End": "Konec výstupu NAMES příkazu",
+ "IRC_Description": "Internet Relay Chat (IRC) je nástroj pro textovou komunikaci. Uživatelé komunikují otevřeně v unikátně pojmenovaných místnostech. IRC také podporuje přímé zprávy mezi dvěma uživateli a sdílení souborů. Tento modul integruje tyto vlastnosti do Rocket.Chatu.",
+ "IRC_Enabled": "Pokusit se integrovat IRC. Změna vyžaduje restart Rocket.Chatu",
"IRC_Hostname": "IRC server ke kterému se připojit",
"IRC_Login_Fail": "Výstup nezdařeného připojení k IRC serveru",
"IRC_Login_Success": "Výstup úspěšného připojení k IRC serveru",
"IRC_Message_Cache_Size": "Limit cache pro zpracování odchozích zpráv",
"IRC_Port": "Port k připojení na IRC serveru",
+ "IRC_Private_Message": "Výstup PRIVMSG příkazu",
"IRC_Quit": "Výstup při rozpojení IRC session",
+ "is_also_typing": "také píše",
+ "is_also_typing_female": "také píše",
+ "is_also_typing_male": "také píše",
+ "is_typing": "píše",
+ "is_typing_female": "píše",
+ "is_typing_male": "píše",
+ "Issue_Links": "Odkazy na Issue tracker",
+ "IssueLinks_Incompatible": "Varování: nepovolujte tuto volbu současně s 'Náhled barvy podle Hex kódu'.",
+ "IssueLinks_LinkTemplate": "Šablona pro odkazy na issue",
+ "IssueLinks_LinkTemplate_Description": "Šablona pro odkazy na issue; %s bude nahrazeno číslem issue.",
"It_works": "Funguje to",
"italics": "kurzíva",
"Jitsi_Chrome_Extension": "ID Chrome rozšíření",
"Jitsi_Enable_Channels": "Povolit v místnostech",
"join": "Připojit",
+ "join-without-join-code": "Připojit se i do místností bez kódu",
+ "join-without-join-code_description": "Právo přeskočit připojit bez zadávání kódu do místností, které jej vyžadují",
"Join_audio_call": "Připojit k hovoru",
+ "Join_Chat": "Připojit k chatu",
"Join_default_channels": "Připojit se k výchozím místnostem",
"Join_the_Community": "Zapojte se do komunity",
"Join_the_given_channel": "Přidejte se k dané místnosti",
@@ -690,12 +954,26 @@
"Jump_to_first_unread": "Přejít na první nepřečtenou",
"Jump_to_message": "Přejít na zprávu",
"Jump_to_recent_messages": "Přejít na nedávné zprávy",
+ "Just_invited_people_can_access_this_channel": "Do této místnosti smí vstoupit pouze pozvaní lidé",
"Katex_Dollar_Syntax": "Povolit Dollarovou syntaxi",
"Katex_Dollar_Syntax_Description": "Povolit použití $$katex blok$$ aa $inline katex$ syntaxi",
"Katex_Enabled": "Katex povolen",
"Katex_Enabled_Description": "Umožnit použití Katex pro zápis matematiky ve zprávách",
"Katex_Parenthesis_Syntax": "Povolit Parenthesis syntaxi",
"Katex_Parenthesis_Syntax_Description": "Povolit použití \\[katex block\\] a \\(inline katex\\) syntaxi",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Upravit předchozí zprávu",
+ "Keyboard_Shortcuts_Keys_1": "Ctrl +p ",
+ "Keyboard_Shortcuts_Keys_2": "Šipka nahoru ",
+ "Keyboard_Shortcuts_Keys_3": "Command (nebo Alt ) + šipka doleva ",
+ "Keyboard_Shortcuts_Keys_4": "Command (nebo Alt ) + šipka nahoru ",
+ "Keyboard_Shortcuts_Keys_5": "Command (nebo Alt ) + šipka doprava ",
+ "Keyboard_Shortcuts_Keys_6": "Command (nebo Alt ) + šipka dolů ",
+ "Keyboard_Shortcuts_Keys_7": "Shift +Enter ",
+ "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "Přesunout na začátek zprávy",
+ "Keyboard_Shortcuts_Move_To_End_Of_Message": "Přesunout na konec zprávy",
+ "Keyboard_Shortcuts_New_Line_In_Message": "Nový řádek",
+ "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Otevřít místnost / Vyhledat uživatele",
+ "Keyboard_Shortcuts_Title": "Klávesové zkratky",
"Knowledge_Base": "Znalostní databáze",
"Label": "Štítek",
"Language": "Jazyk",
@@ -714,32 +992,41 @@
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Certifikát",
"LDAP_Connect_Timeout": "Prodleva připojení (ms)",
- "LDAP_Custom_Domain_Search": "Vyhledávání ve vlastní doméně",
- "LDAP_Custom_Domain_Search_Description": "JSON, který řídí vazby a informací o připojení a je ve tvaru: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Výchozí doména",
+ "LDAP_Default_Domain_Description": "Pokud je vyplněna, Výchozí doména bude použita pro vytvoření unikátního emailu pro ty uživatele, u kterých v LDAP chybí. Bude použit formát `username@default_domain` nebo `unique_id@default_domain`. Například `rocket.chat`",
"LDAP_Description": "LDAP je hierarchická databáze, kterou mnohé společnosti používají pro jednotné přihlášení - systém pro sdílení jednoho hesla mezi více webů a služeb. Pro pokročilé informace a příklady konfigurace se podívejte na naši wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "Základní doména",
- "LDAP_Domain_Base_Description": "Plně kvalifikovaný rozlišující název (DN) z podstromu LDAP, ve kterém chcete vyhledávat uživatele a skupiny. Můžete jich přidat tolik, kolik chcete; Nicméně, každá skupina musí být definována pod stejnou základní doménou jako uživatele, kteří do ní patří. Zadáte-li omezené skupiny uživatelů, budou použiti pouze uživatelé, kteří do těchto skupin patří. Doporučujeme použít nejvyšší úroveň vaší LDAP adresářové struktury jako svou základní doménu a použít vyhledávací filtr pro řízení přístupu.",
- "LDAP_Domain_Search_Filter": "Vyhledávací filtr domény",
- "LDAP_Domain_Search_Filter_Description": "Pokud je vyplněno, pouze uživatelé, kteří odpovídají tomuto filtru se budou moci přihlásit. Pokud není zadán žádný filtr, všichni uživatelé v rozsahu základní domény se budou moci přihlásit. Např Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Nebo pro OpenLDAP (rozšiřitelné vyhledávání) `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Kategorie vyhledávaného objektu domény",
- "LDAP_Domain_Search_Object_Category_Description": "*objectCategory* která identifikuje Vaše uživatele. Nechte prázdné pro *OpenLDAP*. Např `Person, atd.",
- "LDAP_Domain_Search_Object_Class": "Třída vyhledávaného objektu domény",
- "LDAP_Domain_Search_Object_Class_Description": "*objectClass* která identifikuje Vaše uživatele. Např `organizationalPerson`,` user`, `inetOrgPerson`, atd.",
- "LDAP_Domain_Search_Password": "Heslo do domény",
- "LDAP_Domain_Search_Password_Description": "Heslo pro uživatele domény vyhledávání.",
- "LDAP_Domain_Search_User": "Uživatel pro doménu vyhledávání",
- "LDAP_Domain_Search_User_Description": "Uživatel LDAP, přes kterého se provádí vyhledávání a ověřují ostatní uživatelé při přihlášení. Obvykle je to účet služby vytvořené speciálně pro integraci do třetích stran. Použijte plně kvalifikovaný název, jako například `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "ID uživatele domény",
- "LDAP_Domain_Search_User_ID_Description": "Atribut LDAP, který identifikuje uživatele LDAP, který se přihlašuje. Toto pole by mělo být `sAMAccountName` pro většinu instancí Active Directory, ale může být` uid` v jiných LDAP řešeních (například OpenLDAP). Můžete použít `mail` k identifikaci uživatele pomocí e-mailu nebo jakýkoliv jiný atribut, který chcete. Můžete použít více hodnot oddělených čárkou, která uživatelům umožňuje přihlášení pomocí více identifikátorů, jako jsou uživatelské jméno nebo e-mail.",
+ "LDAP_BaseDN": "Výchozí DN",
+ "LDAP_BaseDN_Description": "Plně kvalifikovaný rozlišující název (DN) z podstromu LDAP, ve kterém chcete vyhledávat uživatele a skupiny. Můžete jich přidat tolik, kolik chcete; Nicméně, každá skupina musí být definována pod stejnou základní doménou jako uživatele, kteří do ní patří. Zadáte-li omezené skupiny uživatelů, budou použiti pouze uživatelé, kteří do těchto skupin patří. Doporučujeme použít nejvyšší úroveň vaší LDAP adresářové struktury jako svou základní doménu a použít vyhledávací filtr pro řízení přístupu.",
+ "LDAP_User_Search_Field": "Prohledávané pole",
+ "LDAP_User_Search_Field_Description": "Atribut LDAP, který identifikuje uživatele LDAP, který se přihlašuje. Toto pole by mělo být `sAMAccountName` pro většinu instancí Active Directory, ale může být` uid` v jiných LDAP řešeních (například OpenLDAP). Můžete použít `mail` k identifikaci uživatele pomocí e-mailu nebo jakýkoliv jiný atribut, který chcete. Můžete použít více hodnot oddělených čárkou, která uživatelům umožňuje přihlášení pomocí více identifikátorů, jako jsou uživatelské jméno nebo e-mail.",
+ "LDAP_User_Search_Filter": "Filter",
+ "LDAP_User_Search_Filter_Description": "Pokud je vyplněno, pouze uživatelé, kteří odpovídají tomuto filtru se budou moci přihlásit. Pokud není zadán žádný filtr, všichni uživatelé v rozsahu základní domény se budou moci přihlásit. Např Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Nebo pro OpenLDAP (rozšiřitelné vyhledávání) `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_User_Search_Scope": "Rozsah",
+ "LDAP_Authentication": "Povolit",
+ "LDAP_Authentication_Password": "Heslo",
+ "LDAP_Authentication_UserDN": "Uživatelské DN",
+ "LDAP_Authentication_UserDN_Description": "Uživatel LDAP, přes kterého se provádí vyhledávání a ověřují ostatní uživatelé při přihlášení. Obvykle je to účet služby vytvořené speciálně pro integraci do třetích stran. Použijte plně kvalifikovaný název, jako například `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "Povolit",
"LDAP_Enable_Description": "Pokusit se použít LDAP pro autentizaci.",
"LDAP_Encryption": "Šifrování",
"LDAP_Encryption_Description": "Metoda šifrování používaná k zabezpečené komunikace se serverem LDAP. Jako příklady lze uvést `plain` (bez šifrování),` SSL/LDAPS` (šifrovaný od začátku), a `StartTLS` (Šifrovaná komunikaci až po připojení).",
+ "LDAP_Internal_Log_Level": "Úroveň vnitřního logování",
+ "LDAP_Group_Filter_Enable": "Povolit LDAP filtr uživatelské skupiny",
+ "LDAP_Group_Filter_Enable_Description": "Omezit přístup uživatelům z LDAP skupiny Hodí se pro OpenLDAP servery kde nelze použít *memberOf* filtr",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Atribut ID skupiny",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "Např.: *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute": "Atribut uživatele skupiny",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "Např.: *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format": "Formát uživatele skupiny",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "Např.: *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Jméno skupiny",
+ "LDAP_Group_Filter_Group_Name_Description": "Jméno skupiny do které uživatel patří",
+ "LDAP_Group_Filter_ObjectClass": "ObjectClass Skupiny",
+ "LDAP_Group_Filter_ObjectClass_Description": "*objectclass* která identifikuje skupiny. Např. OpenLDAP:groupOfUniqueNames",
"LDAP_Host": "Hostitel",
"LDAP_Host_Description": "Hostitel LDAP, například `ldap.example.com` nebo 10.0.0.30`.",
"LDAP_Idle_Timeout": "Prodleva nečinnosti (ms)",
- "LDAP_Import_Users": "Importovat LDAP uživatele",
+ "LDAP_Idle_Timeout_Description": "Kolik milisekund čekat po dokončení LDAP požadavku před uzavřením spojení. (Každý požadavek otevírá nové připojení)",
"LDAP_Import_Users_Description": "Pokud povoleno, všichni LDAP uživatelé budou naimportováni *POZOR* Nastavte filtr pokud chcete omezit počet uživatelů.",
"LDAP_Login_Fallback": "Alternativní login",
"LDAP_Login_Fallback_Description": "Pokud se přihlášení přes LDAP nepodaří použít místní/výchozí login. Může se hodit pokud je LDAP offline.",
@@ -747,34 +1034,39 @@
"LDAP_Merge_Existing_Users_Description": "*Upozornění!* Pokud importujete uživatele z LDAP a uživatel se stejným jménem již existuje, LDAP údaje a heslo budou přiřazeny tomuto uživateli",
"LDAP_Port": "Port",
"LDAP_Port_Description": "Port pro přístup k LDAP. např: `389` nebo `636` pro LDAPS",
+ "LDAP_Reconnect": "Znovu připojit",
+ "LDAP_Reconnect_Description": "Pokusit se znovu připojit automaticky pokud bylo při zpracování požadavků spojení přerušeno",
"LDAP_Reject_Unauthorized": "Odmítnout neoprávněné",
+ "LDAP_Reject_Unauthorized_Description": "Zakažte tuto volbu pro povolení neověřených certifikatů. Většinou je potřeba tuto volbu vypnout pokud se pracuje se self signed certifikáty",
"LDAP_Sync_User_Avatar": "Synchronizace uživatelských avatarů",
- "LDAP_Sync_User_Data": "Synchronizace dat",
- "LDAP_Sync_User_Data_Description": "Udržujte uživatelská data synchronizovaná se serverem po přihlášení (např: jméno, e-mail).",
+ "LDAP_Sync_Now": "Spustit synchronizaci na pozadí",
+ "LDAP_Sync_Now_Description": "Spustí **Synchronizaci na pozadí ** nyní místo vyčkání **Interval synchronizace na pozadí** i pokud je **Synchronizaci na pozadí** zakázána. Tato akce je asynchroní. Pro více informací o jejím průběhu zkontrolujte log",
+ "LDAP_Background_Sync": "Synchronizace na pozadí",
+ "LDAP_Background_Sync_Interval": "Interval synchronizace na pozadí",
+ "LDAP_Background_Sync_Interval_Description": "Interval mezi synchronizacemi. Například `every 24 hours` nebo `on the first day of the week`, více příkladů - [Cron Text Parser](http://bunkat.github.io/later/parsers.html#text)",
+ "LDAP_Background_Sync_Import_New_Users": "Synchronizace na pozadí importuje nové uživatele",
+ "LDAP_Background_Sync_Import_New_Users_Description": "Naimportuje všechny uživatele (podle filtrů) nalezených v LDAP a neexistují v Rocket.Chat",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated": "Synchronizace na pozadí upravuje existující uživatele",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated_Description": "Synchronizuje avatary, uživatelská pole, uživatelské jméno atd (podle vaší konfigurace) všech uživatelů importovaných z LDAP podle **Interval synchronizace na pozadí**",
+ "LDAP_Sync_User_Data": "Synchronizace uživatelských dat",
+ "LDAP_Sync_User_Data_Description": "Udržujte uživatelská data synchronizovaná se serverem po přihlášení nebo při **synchronizaci na pozadí** (např: jméno, e-mail).",
"LDAP_Sync_User_Data_FieldMap": "Mapa polí uživatelských dat",
- "LDAP_Sync_User_Data_FieldMap_Description": "Konfiguruje pole uživatelských dat (například e-mailu) v záznamu v LDAP. Například `{\" CN \":\" name \",\" mail \":\" email \"}` vybere jméno osoby z atributu CN, a jeho e-mail z atributu pošty. Volné pole obsahují `name` a `email`.",
- "LDAP_Sync_Users": "Synchronizovat Uživatele",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Konfiguruje pole uživatelských dat (například e-mailu) v záznamu v LDAP. Například `{\"cn\":\"name\", \"mail\":\"email\"}` vybere jméno osoby z atributu `cn`, a jeho e-mail z atributu `mail`. Lze používat proměnné například: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` použije kombinaci křestínho jména a příjmení pro pole `name` v Rocket.Chat. Dostupná pole Rocket.Chatu jsou `name`, a `email`.",
+ "LDAP_Search_Page_Size": "Počet výsledků vyhledávání na stránce",
+ "LDAP_Search_Page_Size_Description": "Maximální počet záznamů na každé stránce výsledků pro zpracování",
+ "LDAP_Search_Size_Limit": "Limit velikosti vyhledávání ",
+ "LDAP_Search_Size_Limit_Description": "Maximální počet všech výsledků. **Pozor** Měl by být větší než **Počet výsledků vyhledávání na stránce**",
"LDAP_Test_Connection": "Test připojení",
+ "LDAP_Timeout": "Časový limit (ms)",
+ "LDAP_Timeout_Description": "Kolik milisekund počkat na vyhledávání než bude vrácena chyba",
"LDAP_Unique_Identifier_Field": "Jedinečný identifikátor",
"LDAP_Unique_Identifier_Field_Description": "Která pole bude použita k propojení uživatelů LDAP a uživatelů Rocket.Chat. Můžete specifikovat více hodnot oddělených čárkou pro získání z LDAP záznamu. Výchozí hodnota je `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Použít vlastní doménové vyhledávání",
- "LDAP_Use_Custom_Domain_Search_Description": "Napište svůj vlastní filtr pro vyhledávání uživatelů v LDAP serveru.",
"LDAP_Username_Field": "Pole Uživatelského jména",
"LDAP_Username_Field_Description": "Které pole budou použity jako *Jméno* pro nové uživatele. Ponechte prázdné pro použítí jména z přihlašovací stránky. Můžete použít šablony a tagy jako například `#{givenName}.#{sn}`. Výchozí hodnota je `sAMAccountName`.",
- "LDAP_Group_Filter_Enable": "Povolit LDAP filtr uživatelské skupiny",
- "LDAP_Group_Filter_Enable_Description": "Omezit přístup uživatelům z LDAP skupiny Hodí se pro OpenLDAP servery kde nelze použít *memberOf* filtr",
- "LDAP_Group_Filter_ObjectClass": "ObjectClass Skupiny",
- "LDAP_Group_Filter_ObjectClass_Description": "*objectclass* která identifikuje skupiny. Např. OpenLDAP:groupOfUniqueNames",
- "LDAP_Group_Filter_Group_Id_Attribute": "Atribut ID skupiny",
- "LDAP_Group_Filter_Group_Id_Attribute_Description": "Např.: *OpenLDAP:*cn",
- "LDAP_Group_Filter_Group_Member_Attribute": "Atribut uživatele skupiny",
- "LDAP_Group_Filter_Group_Member_Attribute_Description": "Např.: *OpenLDAP:*uniqueMember",
- "LDAP_Group_Filter_Group_Member_Format": "Formát uživatele skupiny",
- "LDAP_Group_Filter_Group_Member_Format_Description": "Např.: *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
- "LDAP_Group_Filter_Group_Name": "Jméno skupiny",
- "LDAP_Group_Filter_Group_Name_Description": "Jméno skupiny do které uživatel patří",
+ "Execute_Synchronization_Now": "Spustit synchronizaci nyní",
"Least_Amount": "Nejmenším počet",
"Leave_Group_Warning": "Jste si jisti, že chcete opustit skupinu \"%s\"?",
+ "Leave_Livechat_Warning": "Opravdu chcete opustit LiveChat s \"%s\"?",
"Leave_Private_Warning": "Jste si jisti, že chcete opustit diskusi s \"%s\"?",
"Leave_room": "Opustit místnost",
"Leave_Room_Warning": "Jste si jisti, že chcete opustit místnost \"%s\"?",
@@ -782,26 +1074,25 @@
"line": "řádek",
"List_of_Channels": "Seznam místností",
"List_of_Direct_Messages": "Seznam přímých zpráv",
- "Livechat_agents": "Livechat operátoři",
- "Livechat_AllowedDomainsList": "Povolené domény pro Livechat",
- "Domains_allowed_to_embed_the_livechat_widget": "Čárkou oddělený seznam domén, kde se smí zobrazovat livechat. Pro povolení všech domén nechte prázdné",
- "Livechat_Dashboard": "Livechat Přehled",
- "Livechat_enabled": "Livechat povolen",
+ "Livechat_agents": "LiveChat operátoři",
+ "Livechat_AllowedDomainsList": "Domény na kterých povolit Livechat",
+ "Livechat_Dashboard": "LiveChat Přehled",
+ "Livechat_enabled": "LiveChat povolen",
"Livechat_forward_open_chats": "Předat otevřené chaty",
"Livechat_forward_open_chats_timeout": "Časový limit (v sekundách), pro předání chatů",
"Livechat_guest_count": "Počet hostů",
- "Livechat_Inquiry_Already_Taken": "Požadavek již vyřízen",
- "Livechat_managers": "Manažeři Livechatu",
+ "Livechat_Inquiry_Already_Taken": "LiveChat požadavek již vyřízen",
+ "Livechat_managers": "Manažeři LiveChat",
"Livechat_offline": "Livechat offline",
"Livechat_online": "Livechat online",
"Livechat_open_inquiery_show_connecting": "Zobrazit informaci o čekajícím připojení místo pole zprávy pokud uživatel ještě nebyl propojen s operátorem",
- "Livechat_Queue": "Livechat fronta",
- "Livechat_room_count": "Livechat počet místností",
- "Livechat_Routing_Method": "Metoda rozřazení livechatů",
+ "Livechat_Queue": "LiveChat fronta",
+ "Livechat_room_count": "Počet Livechat místností",
+ "Livechat_Routing_Method": "Metoda rozřazení LiveChat",
"Livechat_Take_Confirm": "Chcete převzít tohoto klienta",
- "Livechat_title": "Livechat název",
- "Livechat_title_color": "Livechat Barva pozadí názvu",
- "Livechat_Users": "Livechat Uživatelé",
+ "Livechat_title": "LiveChat název",
+ "Livechat_title_color": "LiveChat Barva pozadí názvu",
+ "Livechat_Users": "LiveChat Uživatelé",
"Load_more": "Načíst další",
"Loading...": "Načítání...",
"Loading_more_from_history": "Načítání více položek z historie",
@@ -818,16 +1109,31 @@
"Login_with": "Přihlášení pomocí %s",
"Logout": "Odhlásit se",
"Logout_Others": "Odhlášení ze všech ostatních míst",
+ "mail-messages": "Odeslat zprávy",
+ "mail-messages_description": "Právo odesílat zprávy",
"Mail_Message_Invalid_emails": "Vložili jste jeden nebo více neplatných e-mailů: %s",
"Mail_Message_Missing_to": "Musíte vybrat jednoho nebo více uživatelů nebo vložit jednu nebo více e-mailových adres oddělených čárkami.",
"Mail_Message_No_messages_selected_select_all": "Nejsou vybrány žádné zprávy. Chcete vybrat všechny viditelné zprávy?",
"Mail_Messages": "Odeslat zprávy",
"Mail_Messages_Instructions": "Kliknutím na zprávy vyberte ty, které chcete poslat e-mailem.",
"Mail_Messages_Subject": "Zde je vybraná část %s zpráv",
- "Mailer": "Odesílač",
+ "Mailer": "Odesílač mailů",
"Mailer_body_tags": "Je nutné použít [unsubscribe] pro vložení odkazu na odhlášení. Můžete také použít [name], [fname], [lname] pro uživatelské jméno, křestí jméno a příjmen nebo [email] pro e-mail uživatele.",
"Mailing": "Mailing",
"Make_Admin": "Změnit na Správce",
+ "Make_sure_you_have_a_copy_of_your_codes": "Pečlivě is uschovejte kopii svých kódů: __codes__ Pokud ztratíte přístup ke své autentizační aplikaci, můžete jeden z nich použít k přihlášení.",
+ "manage-assets": "Spravovat statické zdroje",
+ "manage-assets_description": "Právo upravovat serverové statické soubory",
+ "manage-emoji": "Spravovat emotikony",
+ "manage-emoji_description": "Právo měnit emotikony",
+ "manage-integrations": "Spravovat integrace",
+ "manage-integrations_description": "Právo měnit integrace",
+ "manage-oauth-apps": "Spravovat Oauth aplikace",
+ "manage-oauth-apps_description": "Právo měnit Oauth aplikace",
+ "manage-own-integrations": "Spravovat vlastní integrace",
+ "manage-own-integrations_description": "Právo pro uživatele vytvářet a editovat vlastní integrace a webhooky",
+ "manage-sounds": "Spravovat zvuky",
+ "manage-sounds_description": "Právo měnit zvuky",
"Manager_added": "Manažer přidán",
"Manager_removed": "Manažer odstraněn",
"Managing_assets": "Správa datových zdrojů",
@@ -838,18 +1144,29 @@
"MapView_GMapsAPIKey_Description": "Lze získat zdarma z Google Developers Console ",
"Mark_as_read": "Označit jako přečtené",
"Mark_as_unread": "Označit jako nepřečtené",
- "Markdown_Headers": "Markdownu nadpisy",
+ "Markdown_Headers": "Povolit markdown v nadpisech",
+ "Markdown_Marked_Breaks": "Povolit značky odřádkování",
+ "Markdown_Marked_GFM": "Povolit značky GFM",
+ "Markdown_Marked_Pedantic": "Povolit striktní značky",
+ "Markdown_Marked_SmartLists": "Povolit značky chytrých seznamů",
+ "Markdown_Marked_Smartypants": "Povolit Smartpants značky",
+ "Markdown_Marked_Tables": "Povolit značky tabulek",
+ "Markdown_Parser": "Parser markdownu",
"Markdown_SupportSchemesForLink": "Schémata používaná pro automatické odkazy markdown",
"Markdown_SupportSchemesForLink_Description": "Čárkami oddělený seznam povolených schémat",
"Max_length_is": "Maximální délka je %s",
"Members_List": "Seznam členů",
+ "mention-all": "Zmínit všechny",
+ "mention-all_description": "Právo použít `@all` zmínku",
"Mentions": "Zmínky",
"Mentions_default": "Zmínky (výchozí)",
+ "Mentions_only": "Pouze zmínky",
"Message": "Zpráva",
"Message_AllowBadWordsFilter": "Povolit filtrování sprostých slov",
"Message_AllowDeleting": "Povolit mazání zpráv",
"Message_AllowDeleting_BlockDeleteInMinutes": "Blokovat mazání zpráv po (n) minutách",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Zadáním hodnoty 0 vypnete blokování.",
+ "Message_AllowDirectMessagesToYourself": "Povolit uživatelům odesílat si přímé zprávy",
"Message_AllowEditing": "Umožnit editaci zpráv",
"Message_AllowEditing_BlockEditInMinutes": "Blokovat editaci zpráva po (n) minutách",
"Message_AllowEditing_BlockEditInMinutesDescription": "Zadáním hodnoty 0 vypnete blokování.",
@@ -860,6 +1177,9 @@
"Message_AllowUnrecognizedSlashCommand": "Povolit nerozpoznané lomítkové příkazy",
"Message_AlwaysSearchRegExp": "Vždy hledat pomocí regulárních výrazů",
"Message_AlwaysSearchRegExp_Description": "Doporučujeme nastavit `Ano` pokud Váš jazyk není podporován v textového vyhledávání MongoDB .",
+ "Message_Attachments": "Přílohy zprávy",
+ "Message_Attachments_GroupAttach": "Sjednotit tlačítka přílohy",
+ "Message_Attachments_GroupAttachDescription": "Zobrazi tlačítka přílohy jako rozklikávací menu, zabere méně místa na obrazovce",
"Message_AudioRecorderEnabled": "Záznam zvuku povolen",
"Message_AudioRecorderEnabledDescription": "Je třeba mít povolené `audio/wav` soubory v nabídce 'Nahrání souboru'",
"Message_BadWordsFilterList": "Přidat sprostá slova na černou listinu",
@@ -875,17 +1195,21 @@
"Message_HideType_ru": "Schovat zprávu o \"odebrání uživatele\"",
"Message_HideType_uj": "Schovat zprávu o \"připojení uživatele\"",
"Message_HideType_ul": "Schovat zprávu o \"odchodu uživatele\"",
- "Message_KeepHistory": "Udržovat historie zpráv",
+ "Message_KeepHistory": "Udržovat historii editace zprávy",
"Message_MaxAll": "Maximální velikost místnosti pro všechny zprávy",
- "Message_MaxAllowedSize": "Maximální povolená velikost zprávy",
+ "Message_MaxAllowedSize": "Maximální povolená velikost zprávy (počet znaků)",
"Message_pinning": "Připnutí zprávy",
+ "Message_QuoteChainLimit": "Maximální počet navazujících citací",
"Message_removed": "Zpráva odstraněna",
+ "Message_sent_by_email": "Zpráva odeslaná emailem",
"Message_SetNameToAliasEnabled": "Změnit uživatelské jméno ve zprávě na alias",
"Message_SetNameToAliasEnabled_Description": "Jen pokud již není nastaven alias. Alias u starých zpráv nebude změněn",
"Message_ShowDeletedStatus": "Zobrazit informaci o smazání",
"Message_ShowEditedStatus": "Zobrazit informaci o editaci",
"Message_ShowFormattingTips": "Zobrazit tipy na formátování",
"Message_starring": "Ohvězdičkování zprávy",
+ "Message_TimeAndDateFormat": "Formát data a času",
+ "Message_TimeAndDateFormat_Description": "Viz Moment.js ",
"Message_TimeFormat": "Formát času",
"Message_TimeFormat_Description": "Viz také: Moment.js ",
"Message_too_long": "Zpráva je příliš dlouhá",
@@ -893,9 +1217,9 @@
"Message_VideoRecorderEnabledDescription": "Vyžaduje přidání 'video/webm' mezi povolené typy souborů v nastavení",
"Messages": "Zprávy",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Zprávy, které jsou odesílány do příchozí WebHook integrace budou zveřejněny zde.",
- "Meta": "Meta",
- "Meta_fb_app_id": "Facebook App Id",
+ "Meta": "Meta informace",
"Meta_custom": "Vlastní meta tagy",
+ "Meta_fb_app_id": "Facebook App Id",
"Meta_google-site-verification": "Ověření stránek Google",
"Meta_language": "Jazyk",
"Meta_msvalidate01": "MSValidate.01",
@@ -903,37 +1227,47 @@
"Min_length_is": "Minimální délka je %s",
"minutes": "minuty",
"Mobile": "Mobilní",
+ "Mobile_Notifications_Default_Alert": "Výchozí upozornění mobilní notifikace",
"Monday": "Pondělí",
"Monitor_history_for_changes_on": "Sledovat historii na změny:",
"More_channels": "Více místností",
"More_direct_messages": "Více přímých konverzací",
"More_groups": "Více Soukromých skupin",
"More_unreads": "více nepřečtených",
+ "Move_beginning_message": "`%s` - Přejít na začátek zprávy",
+ "Move_end_message": "`%s` - Přejít na konec zprávy",
"Msgs": "Zpr",
"multi": "multi",
+ "multi_line": "více řádků",
+ "mute-user": "Ztišit uživatele",
+ "mute-user_description": "Právo ztišit jiné uživatele v aktuální místnosti",
"Mute_someone_in_room": "Ztlumit zprávy od někoho v místnosti",
"Mute_user": "Ztlumit uživatele",
"Muted": "Ztlumeno",
"My_Account": "Můj účet",
+ "My_location": "Moje poloha",
"n_messages": " %s zpráv",
"N_new_messages": " %s nových zpráv",
"Name": "Jméno",
"Name_cant_be_empty": "Jméno nemůže být prázdné",
"Name_of_agent": "Jméno operátora",
"Name_optional": "Jméno (volitelné)",
+ "Name_Placeholder": "Zadejte své jméno...",
"Navigation_History": "Navigace Historie (posledních 20 stran)",
"New_Application": "Nová aplikace",
"New_Custom_Field": "Nové vlastní pole",
"New_Department": "Nové oddělení",
"New_integration": "Nová integrace",
+ "New_line_message_compose_input": "`%s` - Přidat řádek v editačním okně",
"New_logs": "Nové logy",
"New_Message_Notification": "Oznámením o nové zprávě",
"New_messages": "Nové zprávy",
"New_password": "Nové heslo",
+ "New_Password_Placeholder": "Zadejte nové heslo...",
"New_role": "Nová role",
"New_Room_Notification": "Oznámení o nové místnosti",
- "New_videocall_request": "Nový požadavek videohovoru",
"New_Trigger": "Nový trigger",
+ "New_videocall_request": "Nový požadavek videohovoru",
"No_available_agents_to_transfer": "Žádní operátoři k dispozici",
"No_channel_with_name_%s_was_found": "Nebyla nalezena žádná místnost s názvem \"%s\" !",
"No_channels_yet": "Zatím nejste v žádné místnosti.",
@@ -941,13 +1275,14 @@
"No_Encryption": "Bez šifrování",
"No_group_with_name_%s_was_found": "Nebyla nalezena žádná soukromá skupina s názvem \"%s\" !",
"No_groups_yet": "Zatím nemáte žádné soukromé skupiny.",
- "No_livechats": "Nemáte žádné livechaty.",
+ "No_integration_found": "Pod zvoleným id nenalezena žádná integrace.",
+ "No_livechats": "Nemáte žádné LiveChaty.",
"No_mentions_found": "Nenalezeny žádné zmínky",
"No_pinned_messages": "Žádné zprávy nejsou připnuté",
"No_results_found": "Nebyly nalezeny žádné výsledky",
+ "No_snippet_messages": "Žádné předvolby",
"No_starred_messages": "Žádné zprávy s hvězdičkou",
"No_such_command": "Příkaz `__comand__` neexistuje",
- "No_snippet_messages": "Žádné předvolby",
"No_user_with_username_%s_was_found": "Nebyl nalezen žádný uživatel s uživatelským jménem \"%s\" !",
"Nobody_available": "Nikdo není dostupný",
"Node_version": "Verze Node",
@@ -958,10 +1293,16 @@
"Not_found_or_not_allowed": "Nenalezeno nebo není povoleno",
"Nothing": "Nic",
"Nothing_found": "Nic nalezeno",
+ "Notification_Desktop_Default_For": "Zobrazit oznámení na ploše",
"Notification_Duration": "Délka zobrazení oznámení",
+ "Notification_Mobile_Default_For": "Zasílat mobilní notifikace",
"Notifications": "Oznámení",
- "Notify_all_in_this_room": "Oznámit všem v této místnosti",
+ "Notifications_Max_Room_Members": "Maximální počet uživatelů v místnosti pro zakázání zmínky všech",
+ "Notifications_Max_Room_Members_Description": "Pokud počet uživatelů v místnosti překročí zadané číslo, notifikace všech (@all) nebude povolena. Uživatelé si toto nastavení mohou individuálně změnit. (0 možnost zakáže)",
+ "Notifications_Muted_Description": "Pokud ztišíte všechno, neuvidíte zvýrazněné místnosti s novými zprávami, krom zmínek. Ztišení notifikací přetěží nastavení notifikací v jednotlivých místnostech.",
+ "Notifications_Sound_Volume": "Hlasitost zvuku notifikace",
"Notify_active_in_this_room": "Notifikovat aktivní uživatele v místnosti",
+ "Notify_all_in_this_room": "Oznámit všem v této místnosti",
"Num_Agents": "# Operátorů",
"Number_of_messages": "Počet zpráv",
"OAuth_Application": "OAuth Aplikace",
@@ -971,30 +1312,38 @@
"Off_the_record_conversation": "Konverzace mimo záznam",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Konverzace mimo záznam není k dispozici pro Váš prohlížeč nebo zařízení.",
"Office_Hours": "Otevírací doba",
- "Office_Hours_Enabled": "Otevírací doba povolená",
+ "Office_hours_enabled": "Otevírací doba povolena",
+ "Office_hours_updated": "Otevírací doba aktualizována",
"Offline": "Offline",
- "Offline_DM_Email": "Přímá zpráva od __user__",
+ "Offline_DM_Email": "Předmět emailu přímé zprávy",
+ "Offline_Email_Subject_Description": "Můžete použít následující značky:[Site_Name] pro název aplikace, [Site_URL] pro URL aplikace, [User] pro uživatele a [Room] pro místnost ",
"Offline_form": "Offline formulář",
"Offline_form_unavailable_message": "Zpráva nedostupného offline formuláře",
"Offline_Link_Message": "PŘEJÍT NA ZPRÁVU",
- "Offline_Mention_Email": "Zmínka od __user__ v #__room__",
+ "Offline_Mention_All_Email": "Předmět emailu zmínky všech",
+ "Offline_Mention_Email": "Předmět emailu zmínky",
"Offline_message": "Offline zprávy",
"Offline_success_message": "Zpráva pro offline úspěšnou akci",
"Offline_unavailable": "Offline nedostupný",
"On": "Zapnuto",
"Online": "Online",
+ "Only_authorized_users_can_write_new_messages": "Pouze autorizovaní uživatelé mohou psát nové zprávy",
+ "Only_On_Desktop": "Desktopový mód (stisk klávesy enter odesílá pouze na desktopu)",
"Only_you_can_see_this_message": "Pouze Vy vidíte tuto zprávu",
"Oops!": "Oops",
"Open": "Otevřít",
+ "Open_channel_user_search": "`%s` - Otevřít místnost / Hledat uživatele",
"Open_days_of_the_week": "Otevírací doba přes týden",
"Open_Livechats": "Otevřené livechaty",
+ "Open_your_authentication_app_and_enter_the_code": "Otevřete autentizační aplikaci a zadejte vygenerovaný kód. Můžete použít jeden ze svých záložních kódů.",
"Opened": "Otevřený",
"Opened_in_a_new_window": "Otevřeno v novém okně",
"Opens_a_channel_group_or_direct_message": "Otevře místnost, skupinu nebo přímou zprávu",
"optional": "volitelný",
- "Use_minor_colors": "Použít nevýraznou barevnou baletu (ve výchozím stavu podědí výraznou paletu)",
"or": "nebo",
+ "Or_talk_as_anonymous": "Vydávat sezaanonyma",
"Order": "Objednat",
+ "Original": "Originál",
"OS_Arch": "Architektura OS",
"OS_Cpus": "Počet CPU OS",
"OS_Freemem": "Volná paměť OS",
@@ -1007,6 +1356,8 @@
"others": "ostatní",
"OTR": "OTR (konverzace mimo záznam)",
"OTR_is_only_available_when_both_users_are_online": "OTR je k dispozici pouze pokud jsou oba uživatelé online",
+ "Outgoing_WebHook": "Odchozí Webhook",
+ "Outgoing_WebHook_Description": "Získávejte data z Rocket.Chat v reálném čase.",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Přepsat URL, na které jsou nahrané soubory. Tato adresa se také používá pro stahování pokud není nastavena CDN",
"Page_title": "Titulku stránky",
"Page_URL": "URL stránky",
@@ -1018,9 +1369,19 @@
"People": "Lidé",
"Permalink": "Trvalý odkaz",
"Permissions": "Oprávnění",
+ "pin-message": "Připnout zprávu",
+ "pin-message_description": "Právo připnout zprávu",
"Pin_Message": "Připnout zprávu",
"Pinned_a_message": "Připnuta zpráva:",
"Pinned_Messages": "Připnuté zprávy",
+ "PiwikAdditionalTrackers": "Dalši Piwik stránky",
+ "PiwikAdditionalTrackers_Description": "Zde vložte další Piwik stránky a jejich ID v následujícím formátu:\n [ { \"trackerURL\" : \"https://moje.piwik.domena2/\", \"siteId\" : 2 }, { \"trackerURL\" : \"https://moje.piwik.domena3/\", \"siteId\" : 3 } ]",
+ "PiwikAnalytics_cookieDomain": "Všechny subdomény",
+ "PiwikAnalytics_cookieDomain_Description": "Sledovat uživatele napříč všemi subdoménami",
+ "PiwikAnalytics_domains": "Skrýt odchozí odkazy",
+ "PiwikAnalytics_domains_Description": "Pro report odchozích odkazů skrýt kliky na známé URL.\nDomény vkládejte na nový řádek bez oddělovacích znaků",
+ "PiwikAnalytics_prependDomain": "Přidat doménu",
+ "PiwikAnalytics_prependDomain_Description": "Přidat doménu do názvu stránky pro trackování",
"PiwikAnalytics_siteId_Description": "ID webu k identifikaci těchto stránek (Např: 17)",
"PiwikAnalytics_url_Description": "Url Piwik vaší instance, nezapomeňte zahrnout koncové lomítko. Příklad: //piwik.rocket.chat/",
"Placeholder_for_email_or_username_login_field": "Zástupný text pro pole e-mailu nebo uživatelského jména v přihlášení",
@@ -1028,13 +1389,14 @@
"Please_add_a_comment": "Prosím, přidejte komentář",
"Please_add_a_comment_to_close_the_room": "Pro uzavření místnosti prosím přidejte komentář",
"Please_answer_survey": "Věnujte prosím chvilku času ohodnocení chatu.",
+ "please_enter_valid_domain": "Prosím zadejte platnou doménu",
"Please_enter_value_for_url": "Prosím, zadejte URL Vašeho avataru.",
"Please_enter_your_new_password_below": "Níže zadejte své nové heslo:",
- "Please_enter_your_password": "Zadejte prosím heslo znovu",
- "please_enter_valid_domain": "Prosím zadejte platnou doménu",
+ "Please_enter_your_password": "Zadejte prosím své současné heslo",
"Please_fill_a_label": "Prosím, vyplňte štítek",
"Please_fill_a_name": "Prosím vyplňte název",
"Please_fill_a_username": "Prosím vyplňte uživatelské jméno",
+ "Please_fill_all_the_information": "Prosím vyplňte všechny informace",
"Please_fill_name_and_email": "Prosím vyplňte jméno a e-mail",
"Please_select_an_user": "Prosím vyberte uživatele",
"Please_select_enabled_yes_or_no": "Zvolte hodnotu pro povoleno",
@@ -1044,19 +1406,27 @@
"Please_wait_while_your_account_is_being_deleted": "Prosím čekejte, mažu Váš účet",
"Please_wait_while_your_profile_is_being_saved": "Počkejte prosím, ukládám Váš účet",
"Port": "Port",
+ "post-readonly": "Napsat do místnosti pouze ke čtení",
+ "post-readonly_description": "Právo napsat do místnosti pouze ke čtení",
"Post_as": "Odeslat jako",
"Post_to_Channel": "Odeslat do místnosti",
"Post_to_s_as_s": "Příspěvek do %s jako %s ",
"Preferences": "Nastavení",
"Preferences_saved": "Nastavení uloženo",
+ "preview-c-room": "Náhled veřejné místnosti",
+ "preview-c-room_description": "Právo zobrazit obsah veřejné místnosti před připojení do ní",
"Privacy": "Soukromí",
"Private": "Privátní",
+ "Private_Channel": "Privátní místnost",
"Private_Group": "Soukromá skupina",
"Private_Groups": "Soukromé skupiny",
"Private_Groups_list": "Seznam Soukromých skupin",
"Profile": "Profil",
+ "Profile_details": "Detail profilu",
+ "Profile_picture": "Profilový obrázek",
"Profile_saved_successfully": "Profil byl úspěšně uložen",
"Public": "Veřejné",
+ "Public_Channel": "Veřejná místnost",
"Push": "Notifikace",
"Push_apn_cert": "APN Certifikát",
"Push_apn_dev_cert": "APN DEV certifikát",
@@ -1080,6 +1450,7 @@
"quote": "citovat",
"Quote": "Citovat",
"Random": "Náhodný",
+ "RDStation_Token": "RD Station Token",
"React_when_read_only": "Povolit reakce",
"React_when_read_only_changed_successfully": "Povolit reakce po úspěšné změně povolení ke čtení",
"Reacted_with": "zanechal/a reakci",
@@ -1090,14 +1461,22 @@
"Read_only_group": "Skupina pouze pro čtení",
"Record": "Záznam",
"Redirect_URI": "URI Přesměrování",
- "Refresh_oauth_services": "Obnovit služby OAuth",
"Refresh_keys": "Obnovit klíče",
+ "Refresh_oauth_services": "Obnovit služby OAuth",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Po instalaci obnovte stránku aby sdílení stránky fungovalo",
+ "Regenerate_codes": "Přegenerovat záložní kódy",
"Register": "Zaregistrovat nový účet",
+ "Registration": "Registrace",
"Registration_Succeeded": "Registrace úspěšná",
+ "Registration_via_Admin": "Registrace přes Admin",
+ "Regular_Expressions": "Regulární výrazy",
"Release": "Verze",
+ "Reload": "Znovu načíst",
"Remove": "Odstranit",
+ "remove-user": "Odebrat uživatele",
+ "remove-user_description": "Právo odebrat uživatele z místnosti",
"Remove_Admin": "Odebrat Správce",
+ "Remove_as_leader": "Odebrat pozici vedoucího",
"Remove_as_moderator": "Odebrat moderátora",
"Remove_as_owner": "Odebrat vlastníka",
"Remove_custom_oauth": "Odebrat vlastní OAuth",
@@ -1110,27 +1489,32 @@
"Report_exclamation_mark": "Nahlásit!",
"Report_sent": "Nahlášení odesláno",
"Report_this_message_question_mark": "Nahlásit tuto zprávu?",
+ "Reporting": "Reporting",
"Require_password_change": "Vyžadovat změnu hesla",
"Resend_verification_email": "Opětovné zaslání ověřovacího e-mailu",
"Reset": "Obnovit",
- "Reset_section_settings": "Vymazat nastavení sekce",
"Reset_password": "Obnovit heslo",
+ "Reset_section_settings": "Obnovit výchozí nastavení sekce",
"Restart": "Restartovat",
"Restart_the_server": "Restartovat server",
+ "Retry_Count": "Počet opakování",
"Role": "Role",
"Role_Editing": "Editace Role",
"Role_removed": "Role odstraněna",
"Room": "Místnost",
+ "Room_announcement_changed_successfully": "Oznámení místnosti změněno",
"Room_archivation_state": "Stav",
"Room_archivation_state_false": "Aktivní",
"Room_archivation_state_true": "Archivovaná",
"Room_archived": "Místnost archivována",
+ "room_changed_announcement": "Oznámení místnosti změněno na __room_announcement__ uživatelem __user_by__ ",
"room_changed_description": "Popis místnosti změněn na: __room_description__ uživatelem __user_by__ ",
"room_changed_privacy": "__user_by__ změnil/a typ místnosti na: __room_type__ ",
"room_changed_topic": "__user_by__ změnil/a téma místnosti na: __room_topic__ ",
+ "Room_default_change_to_private_will_be_default_no_more": "Tato místnost je výchozí a pokud bude změněna na privátní, již nebude moci být mezi výchozími. Přesto změnit?",
"Room_description_changed_successfully": "Popis místnosti změněn",
- "Room_has_been_deleted": "Místnost smazána",
"Room_has_been_archived": "Místnost byla archivována",
+ "Room_has_been_deleted": "Místnost smazána",
"Room_has_been_unarchived": "Místnost již není archivována",
"Room_Info": "Informace o místnosti",
"room_is_blocked": "Místnost je blokována",
@@ -1139,31 +1523,42 @@
"Room_name_changed": "__user_by__ změnil/a jméno místnosti na: __room_name__ ",
"Room_name_changed_successfully": "Přejmenování místnosti proběhlo úspěšně",
"Room_not_found": "Místnost nebyla nalezena",
+ "Room_password_changed_successfully": "Heslo místnosti úspěšně změněno",
"Room_topic_changed_successfully": "Téma místnosti úspěšně změněno",
"Room_type_changed_successfully": "Typ místnosti úspěšně změněn",
+ "Room_type_of_default_rooms_cant_be_changed": "Tato místnost je výchozí a proto nelze změnit její typ. Výchozí místnosti může upravovat administrátor.",
"Room_unarchived": "Místnost odarchivována",
"Room_uploaded_file_list": "Seznam souborů",
"Room_uploaded_file_list_empty": "Žádné soubory k dispozici.",
"Rooms": "Místnosti",
+ "run-import": "Pustit import",
+ "run-import_description": "Právo spustit importovací proces",
+ "run-migration": "Pustit migraci",
+ "run-migration_description": "Právo spustit migraci",
"Running_Instances": "Spuštěných instancí",
"S_new_messages_since_s": "%s nových zprávy od %s",
+ "Same_Style_For_Mentions": "Stejný styl pro zmínky",
"SAML": "SAML",
"SAML_Custom_Cert": "Vlastní Certifikát",
"SAML_Custom_Entry_point": "Vlastní vstupní bod",
"SAML_Custom_Generate_Username": "Generovat uživatelské jméno",
"SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO přesměrovací URL",
"SAML_Custom_Issuer": "Vlastní vydavatel",
+ "SAML_Custom_Private_Key": "Obsah privátního klíče",
"SAML_Custom_Provider": "Vlastní poskytovatel",
"SAML_Custom_Public_Cert": "Obsah veřejného certifikátu",
- "SAML_Custom_Private_Key": "Obsah privátního klíče",
"Sandstorm_Powerbox_Share": "Sdílet Sandstorm grain",
"Saturday": "Sobota",
"Save": "Uložit",
+ "save-others-livechat-room-info": "Upravit informace LiveChat místnosti",
+ "save-others-livechat-room-info_description": "Právo upravit informace jiné LiveChat místnosti",
"Save_changes": "Uložit změny",
"Save_Mobile_Bandwidth": "Šetřit mobilní data",
"Save_to_enable_this_action": "Uložte pro povolení akce",
"Saved": "Uloženo",
"Saving": "Ukládání",
+ "Scan_QR_code": "V autentizační aplikace jako Google Authenticator, Authy nebo Duo naskenujte QR kód. Aplikace vám poté zobrazí 6-ti místný kód, který zadejte níže.",
+ "Scan_QR_code_alternative_s": "Pokud nemůžete naskenovat QR kód, můžete jej zadat ručně: __code__",
"Scope": "Rozsah",
"Screen_Share": "Sdílení obrazovky",
"Script_Enabled": "Skript Povolen",
@@ -1173,10 +1568,12 @@
"Search_Private_Groups": "Vyhledávání soukromých skupin",
"seconds": "sekundy",
"Secret_token": "Tajný token",
+ "Security": "Zabezpečení",
"Select_a_department": "Vyberte oddělení",
"Select_a_user": "Vyberte uživatele",
"Select_an_avatar": "Vyberte avatar",
"Select_file": "Zvolte soubor",
+ "Select_role": "Zvolit roli",
"Select_service_to_login": "Vyberte službu pro přihlášení k načtení obrázků nebo nahrejte obrázek přímo z Vašeho počítače",
"Select_user": "Vybrat uživatele",
"Select_users": "Vybrat uživatele",
@@ -1186,7 +1583,7 @@
"Send_a_test_mail_to_my_user": "Odeslat testovací zprávu na můj mail",
"Send_a_test_push_to_my_user": "Odeslat testovací notifikaci na má zařízení",
"Send_confirmation_email": "Zaslat potvrzovací e-mail",
- "Send_data_into_RocketChat_in_realtime": "Posílat data do Rocket.Chat v reálném čase.",
+ "Send_data_into_RocketChat_in_realtime": "Posílejte data do Rocket.Chat v reálném čase.",
"Send_email": "Odelat e-mail",
"Send_invitation_email": "Poslat pozvánku e-mailem",
"Send_invitation_email_error": "Zadejte platnou e-mailovou adresu.",
@@ -1200,6 +1597,16 @@
"Sending": "Odesílání ...",
"Served_By": "Poskytovatel",
"Service": "Služba",
+ "Service_account_key": "Klíč účty služby",
+ "set-moderator": "Nastavit moderátora",
+ "set-moderator_description": "Právo nastavit uživatele jako moderátora místnosti",
+ "set-owner": "Nastavit vlastníka",
+ "set-owner_description": "Právo nastavit uživatele jako vlastníka místnosti",
+ "set-react-when-readonly": "Reagovat na zprávy v místnostech ke čtení",
+ "set-react-when-readonly_description": "Právo reagovat na zprávy v místnostech pouze ke čtení",
+ "set-readonly": "Nastavit pouze ke čtení",
+ "set-readonly_description": "Právo změni místnost na pouze ke čtení",
+ "Set_as_leader": "Nastavit vedoucícho",
"Set_as_moderator": "Nastavit jako moderátora",
"Set_as_owner": "Nastavit jako vlastníka",
"Settings": "Nastavení",
@@ -1212,23 +1619,26 @@
"Show_more": "Zobrazit více",
"show_offline_users": "zobrazit offline uživatele",
"Show_on_registration_page": "Zobrazit na registrační stránce",
- "Show_only_online": "Pouze on-line",
+ "Show_only_online": "Ukázat pouze on-line",
"Show_preregistration_form": "Ukázat před-registrační formulář",
"Show_queue_list_to_all_agents": "Zobrazit frontu všech operátorů",
+ "Show_the_keyboard_shortcut_list": "Zobrazit klávesové zkratky",
"Showing_archived_results": " Zobrazeno %s archivovaných výsledků
",
"Showing_online_users": "Viditelných __total_showing__ z __total__ uživatelů",
"Showing_results": "Zobrazeno %s výsledků
",
+ "Sidebar_list_mode": "Mód postraního panelu",
+ "Sign_in_to_start_talking": "Pro konverzaci se přihlašte",
"since_creation": "od %s",
"Site_Name": "Jméno stránky",
"Site_Url": "URL stránky",
"Site_Url_Description": "Například: https://chat.domain.com/",
"Skip": "Přeskočit",
"SlackBridge_error": "SlackBridge narazil na chybu při importu zpráv ve %s: %s",
+ "SlackBridge_finish": "Slackbridge dokončil import zpráv ve %s. Prosím obnovte stránku pro zobrazení všech zpráv.",
"SlackBridge_Out_All": "Slackbridge Odesílat Vše",
"SlackBridge_Out_All_Description": "Odesílat zprávy ze všech místností které existují i na slacku a bot je v nich připojen",
"SlackBridge_Out_Channels": "Slackbridge Odesílat místnosti",
"SlackBridge_Out_Channels_Description": "Vyberte které místnosti budou odesílány",
- "SlackBridge_finish": "Slackbridge dokončil import zpráv ve %s. Prosím obnovte stránku pro zobrazení všech zpráv.",
"SlackBridge_Out_Enabled": "SlackBridge Odesáílání povoleno",
"SlackBridge_Out_Enabled_Description": "Zvolit zda by měl SlackBridge také odesílat zprávy zpět do Slacku",
"SlackBridge_start": "@%s spustil import přes SlackBridge ve `#%s`. Dáme vědět až to bude hotové.",
@@ -1255,20 +1665,28 @@
"SMTP_Port": "Port SMTP",
"SMTP_Test_Button": "Test nastavení SMTP",
"SMTP_Username": "Uživatelské jméno SMTP",
+ "snippet-message": "Šablona zprávy",
+ "snippet-message_description": "Právo vytvořit šablonu zprávy",
"Snippet_Added": "Vytvořeno v %s",
"Snippet_Messages": "Předvolené zprávy",
"Snippeted_a_message": "Vytvořena předvolená zpráva __snippetLink__",
+ "Sort_by_activity": "Řadit podle aktivity",
"Sound": "Zvuk",
+ "Sound_File_mp3": "Soubor zvuku (mp3)",
+ "Split_by_categories": "Rozdělit podle kategorií",
"SSL": "SSL",
"Star_Message": "Ohvězdičkovat zprávu",
"Starred_Messages": "Zprávy s hvězdičkou",
+ "Start": "Start",
"Start_audio_call": "Zavolat",
"Start_Chat": "Spustit chat",
"Start_of_conversation": "Začátek konverzace",
"Start_OTR": "Spustit OTR",
"Start_video_call": "Začít videohovor",
+ "Start_video_conference": "Zahájit videokonferenci?",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Napište %s pro uživatele nebo %s pro místnost. Např.: %s nebo %s",
"Started_At": "Zahájena v",
+ "Started_a_video_call": "Zahájil videohovor",
"Statistics": "Statistiky",
"Statistics_reporting": "Posílat statistiky do Rocket.Chat",
"Statistics_reporting_Description": "Zasláním svých statistik, nám pomáháte mít přehled o tom, kolik instancí se používá, zda se systém chová správně, takže jej můžeme dále vylepšovat. Nebojte, žádné důvěrné informace o uživatelích neodesíláme a všechny informace, které obdržíme, udržujeme v tajnosti.",
@@ -1282,12 +1700,18 @@
"Stats_Online_Users": "Online uživatelé",
"Stats_Total_Channels": "Celkový počet místností",
"Stats_Total_Direct_Messages": "Celkem přímých konverzací",
+ "Stats_Total_Livechat_Rooms": "Celkem Livechat místností",
"Stats_Total_Messages": "Celkem zpráv",
+ "Stats_Total_Messages_Channel": "Celkem zpráv ve veřejných místnostech",
+ "Stats_Total_Messages_Direct": "Celkem zpráv v přímých konverzacích",
+ "Stats_Total_Messages_Livechat": "Celkem zpráv v Livechatech",
+ "Stats_Total_Messages_PrivateGroup": "Celkem zpráv v soukromých skupinách",
"Stats_Total_Private_Groups": "Celkem Soukromých skupin",
"Stats_Total_Rooms": "Celkem místností",
"Stats_Total_Users": "Celkem uživatelů",
"Status": "Stav",
"Stop_Recording": "Zastavit záznam",
+ "Stream_Cast": "Stream cast",
"Stream_Cast_Address": "Adresa Stream Castu",
"Stream_Cast_Address_Description": "IP nebo Server vaší Rocket.Chat hlavního Stream Castu. Např. `192.168.1.1:3000` or `localhost:4000`",
"strike": "přeškrtnuté",
@@ -1300,10 +1724,14 @@
"Survey_instructions": "Hodnoťte každou otázku dle vaší spokojenosti, 1 - zcela NEspokojeni a 5 - zcela spokojeni.",
"Symbols": "Symboly",
"Sync_success": "Synchronizace úspěšná",
+ "Sync_in_progress": "Synchronizace probíhá",
"Sync_Users": "Synchronizace uživatelů",
"System_messages": "Systémové zprávy",
"Tag": "Tag",
"Take_it": "Převzít",
+ "TargetRoom": "Cílová místnost",
+ "TargetRoom_Description": "Místnost do které budou odeslány zprávy po spuštění dané události. Je povolena pouze jedna místnost, který musí existovat.",
+ "Team": "Team",
"Test_Connection": "Test připojení",
"Test_Desktop_Notifications": "Test Oznámení na ploše",
"Thank_you_exclamation_mark": "Děkujeme!",
@@ -1319,33 +1747,48 @@
"The_user_will_be_removed_from_s": "Uživatel bude odstraněn z %s",
"The_user_wont_be_able_to_type_in_s": "Uživatel nebude moci psát v %s",
"Theme": "Barevné nastavení",
- "theme-color-transparent-darker": "Průhledná tmavší",
- "theme-color-transparent-dark": "Průhledná tmavá",
- "theme-color-transparent-light": "Průhledná světlá",
- "theme-color-transparent-lighter": "Průhledná světlejší",
- "theme-color-transparent-lightest": "Průhledná nejsvětlejší",
+ "theme-color-component-color": "Barva komponenty",
"theme-color-content-background-color": "Barva pozadí obsahu",
+ "theme-color-custom-scrollbar-color": "Vlastní barva posuvníku",
+ "theme-color-error-color": "Barva chybové akce",
+ "theme-color-info-font-color": "Barva písma Informace",
+ "theme-color-link-font-color": "Barva písma odkazů",
+ "theme-color-pending-color": "Barva čekající akce",
+ "theme-color-primary-action-color": "Primární barva akce",
"theme-color-primary-background-color": "Primární Barva pozadí",
"theme-color-primary-font-color": "Primární Barva písma",
- "theme-color-primary-action-color": "Primární barva akce",
+ "theme-color-secondary-action-color": "Sekundární barva akce",
"theme-color-secondary-background-color": "Sekundární Barva pozadí",
"theme-color-secondary-font-color": "Sekundární Barva písma",
- "theme-color-secondary-action-color": "Sekundární barva akce",
- "theme-color-component-color": "Barva komponenty",
- "theme-color-success-color": "Barva zdařené akce",
- "theme-color-pending-color": "Barva čekající akce",
- "theme-color-error-color": "Barva chybové akce",
"theme-color-selection-color": "Barva výběru",
- "theme-color-tertiary-background-color": "Terciární Barva pozadí",
- "theme-color-tertiary-font-color": "Terciární Barva písma",
- "theme-color-link-font-color": "Barva písma odkazů",
- "theme-color-info-font-color": "Barva písma Informace",
- "theme-color-custom-scrollbar-color": "Vlastní barva posuvníku",
"theme-color-status-away": "Barva stavu 'pryč'",
"theme-color-status-busy": "Barva stavu 'zaneprázdněn'",
"theme-color-status-offline": "Barva stavu Offline",
"theme-color-status-online": "Barva stavu Online",
+ "theme-color-success-color": "Barva zdařené akce",
+ "theme-color-tertiary-background-color": "Terciární Barva pozadí",
+ "theme-color-tertiary-font-color": "Terciární Barva písma",
+ "theme-color-transparent-dark": "Průhledná tmavá",
+ "theme-color-transparent-darker": "Průhledná tmavší",
+ "theme-color-transparent-light": "Průhledná světlá",
+ "theme-color-transparent-lighter": "Průhledná světlejší",
+ "theme-color-transparent-lightest": "Průhledná nejsvětlejší",
"theme-color-unread-notification-color": "Barva Nepřečtených upozornění",
+ "theme-color-rc-color-error": "Chyba",
+ "theme-color-rc-color-error-light": "Chyba světlá",
+ "theme-color-rc-color-alert": "Upozornění",
+ "theme-color-rc-color-alert-light": "Upozornění světlá",
+ "theme-color-rc-color-success": "Provedeno",
+ "theme-color-rc-color-success-light": "Provedeno světlá",
+ "theme-color-rc-color-button-primary": "Tlačítko primární",
+ "theme-color-rc-color-button-primary-light": "Tlačítko primární světlá",
+ "theme-color-rc-color-primary": "Primární",
+ "theme-color-rc-color-primary-darkest": "Primární nejtmavší",
+ "theme-color-rc-color-primary-dark": "Primární tmavá",
+ "theme-color-rc-color-primary-light": "Primární světlá",
+ "theme-color-rc-color-primary-light-medium": "Primární středně světlá",
+ "theme-color-rc-color-primary-lightest": "Primární nejsvětlejší",
+ "theme-color-rc-color-content": "Obsah",
"theme-custom-css": "Vlastní CSS",
"theme-font-body-font-family": "Font obsahu",
"There_are_no_agents_added_to_this_department_yet": "Neexistují žádní operátoři v tomto oddělení",
@@ -1366,33 +1809,54 @@
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Chcete-li nainstalovat Rocket.Chat LiveChat na své webové stránky, zkopírujte & vložte tento kód před uzavírací tag </body> .",
"to_see_more_details_on_how_to_integrate": "pro zobrazení více detailů k integracím",
"To_users": "Uživatelům",
+ "Toggle_original_translated": "Zobrazit originál/překlad",
"Topic": "Téma",
- "Travel_and_Places": "Cestování & Místa",
"Transcript_Enabled": "Zeptat se po skončení chatu, zda uživateli odeslat kopii konverzace",
"Transcript_message": "Zpráva kterou zobrazit jako dotaz zda odeslat kopii konverzace",
- "Transcript_of_your_livechat_conversation": "Kopie Vaší livechat konverzace",
+ "Transcript_of_your_livechat_conversation": "Kopie Vaší LiveChat konverzace",
+ "Translated": "Přeloženo",
+ "Translations": "Překlady",
+ "Travel_and_Places": "Cestování & Místa",
"Trigger_removed": "Trigger odstraněn",
"Trigger_Words": "Klíčová slova",
"Triggers": "Trigery",
"True": "Ano",
"Tuesday": "Úterý",
+ "Two-factor_authentication": "Dvoufázové ověření",
+ "Two-factor_authentication_disabled": "Dvoufázová ověření zakázáno",
+ "Two-factor_authentication_enabled": "Dvoufázové ověření povoleno",
+ "Two-factor_authentication_is_currently_disabled": "Dvoufázové ověření je momentálně zakázáno",
+ "Two-factor_authentication_native_mobile_app_warning": "UPOZORNĚNÍ: Pokud povolíte dvoufázové ověření, nebudete se moci přihlásit přes nativní mobilní aplikace (Rocket.Chat+) dokud v těchto nebude 2FA implementována.",
"Type": "Typ",
"Type_your_email": "Zadejte svůj e-mail",
"Type_your_message": "Napište zprávu",
"Type_your_name": "Zadejte své jméno",
"Type_your_new_password": "Zadejte nové heslo",
+ "UI_Allow_room_names_with_special_chars": "Povolit speciální znaky v názvech místností",
+ "UI_Click_Direct_Message": "Kliknutím vytvořit přímou zprávu",
+ "UI_Click_Direct_Message_Description": "Přeskočit záložku profilu a přejít přímo do konverzace",
"UI_DisplayRoles": "Zobrazit Role",
"UI_Merge_Channels_Groups": "Sloučit privátní skupiny s místnostmi",
+ "UI_Unread_Counter_Style": "Styl počítadla nepřečtených zpráv",
+ "UI_Use_Name_Avatar": "Použít iniciály celého jména uživatele pro výchozí avatar",
+ "UI_Use_Real_Name": "Použít skutečné jméno",
"Unarchive": "Zrušit archivaci",
+ "unarchive-room": "Odarchivovat místnost",
+ "unarchive-room_description": "Právo odarchivovat místnost",
"Unblock_User": "Odblokovat uživatele",
"Unmute_someone_in_room": "Zrušit ztlumení někoho v místnosti",
"Unmute_user": "Zrušit ztlumení uživatele",
"Unnamed": "Nepojmenovaný",
"Unpin_Message": "Odepnout Zprávu",
- "Unread_Alert": "Nepřečtené upozornění",
+ "Unread_Count": "Počet nepřečtených",
+ "Unread_Count_DM": "Počet nepřečtených přímých zpráv",
+ "Unread_Messages": "Nepřečtěné zprávy",
"Unread_Rooms": "Nepřečtené místnosti",
"Unread_Rooms_Mode": "Mód Nepřečtených místností",
+ "Unread_Tray_Icon_Alert": "Ikona v oznamovací oblasti upozorňuje na nepřečtené zprávy",
"Unstar_Message": "Odebrat hvězdičku",
+ "Updated_at": "Poslední aktualizace",
+ "Upload_user_avatar": "Nahrát avatara",
"Upload_file_description": "Popis souboru",
"Upload_file_name": "Název souboru",
"Upload_file_question": "Nahrát soubor?",
@@ -1404,18 +1868,25 @@
"Use_Emojis": "Použít emotikony",
"Use_Global_Settings": "Použít obecné nastavení",
"Use_initials_avatar": "Použít iniciály Vašeho jména",
+ "Use_minor_colors": "Použít nevýraznou barevnou baletu (ve výchozím stavu podědí výraznou paletu)",
"Use_service_avatar": "Použijte avatar z %s",
"Use_this_username": "Použít toto uživatelské jméno",
"Use_uploaded_avatar": "Použít nahraný avatar",
"Use_url_for_avatar": "Použijte avatar z URL",
"Use_User_Preferences_or_Global_Settings": "Použít nastavení uživatele nebo obecné nastavení",
+ "User": "Uživatel",
+ "user-generate-access-token": "Přístupový token uživatelů",
+ "user-generate-access-token_description": "Právo vytvářet uživatelský přístupový token",
+ "User__username__is_now_a_leader_of__room_name_": "Uživatel __username__ je nyní vedoucím místnosti __room_name__",
"User__username__is_now_a_moderator_of__room_name_": "Uživatel __username__ je nyní moderátorem __room_name__",
"User__username__is_now_a_owner_of__room_name_": "Uživatel __username__ je nyní vlastníkem __room_name__",
+ "User__username__removed_from__room_name__leaders": "Uživatel __username__ byl odebrán z vedoucích místnosti __room_name__",
"User__username__removed_from__room_name__moderators": "Uživatel __username__ odebrán z moderátorů __room_name__",
"User__username__removed_from__room_name__owners": "Uživatel __username__ odebrán z vlastníků __room_name__",
"User_added": "Přidán uživatel",
"User_added_by": "__user_by__ přidal uživatele __user_added__ .",
"User_added_successfully": "Uživatel byl úspěšně přidán",
+ "User_and_group_mentions_only": "Pouze notifikace skupiny a uživatele",
"User_doesnt_exist": "Žádný uživatel `@%s`.",
"User_has_been_activated": "Uživatel byl aktivován",
"User_has_been_deactivated": "Uživatel byl deaktivován",
@@ -1423,6 +1894,7 @@
"User_has_been_muted_in_s": "Uživatel byl ztišen v %s",
"User_has_been_removed_from_s": "Uživatel byl odebrán z %s",
"User_Info": "Informace o uživateli",
+ "User_Interface": "Uživatelské rozhraní",
"User_is_blocked": "Uživatel je blokován",
"User_is_no_longer_an_admin": "Uživatel už není admin",
"User_is_now_an_admin": "Uživatel je nyní admin",
@@ -1435,6 +1907,7 @@
"User_left_male": "Opustil místnost",
"User_logged_out": "Uživatel je odhlášen",
"User_management": "Správa uživatelů",
+ "User_mentions_only": "Pouze notifikace Uživatele",
"User_muted": "Uživatel ztišen",
"User_muted_by": "Uživatel __user_muted__ ztlumen (uživatelem __user_by__. )",
"User_not_found": "Uživatel nenalezen",
@@ -1446,6 +1919,8 @@
"User_unmuted_by": "Uživatel __user_by__ zrušil ztlumení __user_unmuted__. ",
"User_unmuted_in_room": "Uživatel již není ztlumen",
"User_updated_successfully": "Uživatel úspěšně aktualizován",
+ "User_uploaded_file": "Nahrát soubor",
+ "User_uploaded_image": "Nahrát obrázek",
"Username": "Uživatelské jméno",
"Username_and_message_must_not_be_empty": "Uživatelské jméno a zpráva nesmí být prázdné.",
"Username_cant_be_empty": "Uživatelské jméno nemůže být prázdné",
@@ -1457,25 +1932,63 @@
"Username_invalid": "%s není platné uživatelské jméno, použijte pouze písmena, číslice, tečky, pomlčky a podtržítka",
"Username_is_already_in_here": "`@%s` už je zde.",
"Username_is_not_in_this_room": "Uživatel `#%s` není v této místnosti.",
+ "Username_Placeholder": "Zadejte uživatelská jména...",
"Username_title": "Registrovat uživatelské jméno",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ chce spustit OTR (konverzaci mimo záznam). Chcete ji přijmout?",
"Users": "Uživatelé",
+ "Users_added": "Uživatelé byli přidáni",
"Users_in_role": "Uživatelé v roli",
"UTF8_Names_Slugify": "Url podoba UTF8 jmen",
"UTF8_Names_Validation": "UTF8 validace jmen",
"UTF8_Names_Validation_Description": "Regulární výraz validující uživatelská jména a jména místností",
"Validate_email_address": "Validovat email",
+ "Verification": "Ověření",
"Verification_Description": "Můžete použít následující zástupné symboly: [Verification_Url] pro adresu potvrzení. [name] pro celé jméno, [fname] pro křestní jméno a [lname] pro příjmení uživatele. [email] pro email uživatelé. [Site_Name] pro název a [Site_URL] pro a URL stránky. ",
+ "Verification_Email": "Klikněte na tento odkaz pro potvrzení svého účtu.",
"Verification_email_sent": "Ověřovací email odeslán",
"Verification_Email_Subject": "[Site_Name] - Potvrďte svůj účet",
- "Verification_Email": "Klikněte na tento odkaz pro potvrzení svého účtu.",
"Verified": "Ověřený",
+ "Verify": "Ověřit",
"Version": "Verze",
"Video_Chat_Window": "Video chat",
"Video_Conference": "Video konference",
+ "Video_message": "Video zpráva",
"Videocall_declined": "Videohovor odmítnut",
"Videocall_enabled": "Videohovor povolen",
- "View_All": "Zobrazit vše",
+ "view-c-room": "Zobrazit veřejné místnosti",
+ "view-c-room_description": "Právo zobrazit veřejnou místnost",
+ "view-d-room": "Zobrazit soukromé zprávy",
+ "view-d-room_description": "Právo zobrazit soukromé zprávy",
+ "view-full-other-user-info": "Zobrazit veškeré informace uživatele",
+ "view-full-other-user-info_description": "Právo zobrazit veškeré informace uživatele včetně data vytvoření, posledního přihlášení, atd.",
+ "view-history": "Zobrazit historii",
+ "view-history_description": "Právo zobrazit historii místnosti",
+ "view-join-code": "Zobrazit kód místnosti",
+ "view-join-code_description": "Právo zobrazit kód místnosti",
+ "view-joined-room": "Zobrazit připojené místnosti",
+ "view-joined-room_description": "Právo zobrazit aktuálně připojené místnosti",
+ "view-l-room": "Zobrazit LiveChat místnosti",
+ "view-l-room_description": "Právo zobrazit LiveChat místnosti",
+ "view-livechat-manager": "Zobrazit LiveChat manažera",
+ "view-livechat-manager_description": "Právo zobrazit ostatní LiveChat manažery",
+ "view-livechat-rooms": "Zobrazit ostatní LiveChat místnosti",
+ "view-livechat-rooms_description": "Právo zobrazit ostatní LiveChat místnosti",
+ "view-logs": "Zobrazit logy",
+ "view-logs_description": "Právo zobrazit serverové logy",
+ "view-other-user-channels": "Zobrazit místnosti uživatelů",
+ "view-other-user-channels_description": "Právo zobrazit místnosti vlastněné ostatními uživateli",
+ "view-outside-room": "Zobrazit mimo povolenou místnost",
+ "view-p-room": "Zobrazit soukromou místnost",
+ "view-p-room_description": "Právo zobrazit soukromou místnost",
+ "view-privileged-setting": "Zobrazit nastavení",
+ "view-privileged-setting_description": "Právo zobrazit nastavení",
+ "view-room-administration": "Zobrazit administraci místností",
+ "view-room-administration_description": "Právo zobrazit statistiky veřejných i soukromých místností a přímých konverzací. Nezahrnuje právo zobrazit obsah nebo archiv.",
+ "view-statistics": "Zobrazit statistiky",
+ "view-statistics_description": "Právo zobrazit statistiky jako počet přihlášených uživatelů, počet místností, informace o operačním systému",
+ "view-user-administration": "Zobrazit administraci uživatelů",
+ "view-user-administration_description": "Zobrazit částečný seznam (pouze ke čtení) uživatelů přihlášených do systému. Přes toto právo nelze přistupovat k informacím ostatních uživatelů",
+ "View_All": "Zobrazit všechny členy",
"View_Logs": "Zobrazit logy",
"View_mode": "Režim zobrazení",
"View_mode_info": "Tím se změní místo, které zprávy zabírají na obrazovce.",
@@ -1507,13 +2020,13 @@
"Would_you_like_to_return_the_inquiry": "Chcete požadavek zamítnout?",
"Yes": "Ano",
"Yes_archive_it": "Ano archivovat",
- "Yes_unarchive_it": "Ano zrušit archivaci",
"Yes_clear_all": "Ano, vyčistit všechny!",
"Yes_delete_it": "Ano, smazat!",
"Yes_hide_it": "Ano, skrýt!",
"Yes_leave_it": "Ano, opustit!",
"Yes_mute_user": "Ano, ztišit!",
"Yes_remove_user": "Ano, odstranit!",
+ "Yes_unarchive_it": "Ano zrušit archivaci",
"You": "Vy",
"you_are_in_preview_mode_of": "Nacházíte se v režimu náhledu místnosti #__room_name__ ",
"You_are_logged_in_as": "Jste přihlášeni jako",
@@ -1522,8 +2035,9 @@
"You_can_search_using_RegExp_eg": "Můžete vyhledávat pomocí regulárních výrazů např.",
"You_can_use_an_emoji_as_avatar": "Můžete také použít emotikonu jako avatar.",
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Webhooky můžete použít pro jednoduchou integraci s Vaším CRM",
- "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Livechat místnost nelze opustit. Použijte prosím tlačítko zavřít.",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "LiveChat místnost nelze opustit. Použijte prosím tlačítko zavřít.",
"You_have_been_muted": "Byli jste ztišeni a nemůžete v této místnosti mluvit",
+ "You_have_n_codes_remaining": "Zbývá vám __number__ kódů.",
"You_have_not_verified_your_email": "Neověřili jste svůj e-mail.",
"You_have_successfully_unsubscribed": "Úspěšně jste se odhlásili z našeho seznamu.",
"You_must_join_to_view_messages_in_this_channel": "Pro zobrazení zpráv v této místnosti je třeba se připojit",
@@ -1547,4 +2061,4 @@
"your_message_optional": "vaše zpráva (nepovinná)",
"Your_password_is_wrong": "Vaše heslo je špatně!",
"Your_push_was_sent_to_s_devices": "Vaše notifikace byla odeslána do %s zařízení"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/de-AT.i18n.json b/packages/rocketchat-i18n/i18n/de-AT.i18n.json
index d5e5f6368e34a..5e723f4678fe6 100644
--- a/packages/rocketchat-i18n/i18n/de-AT.i18n.json
+++ b/packages/rocketchat-i18n/i18n/de-AT.i18n.json
@@ -1,5 +1,5 @@
{
- "#channel": "#Kanal",
+ "#channel": "#Raum",
"0_Errors_Only": "0 - nur Fehler",
"1_Errors_and_Information": "1 - Fehler und Informationen",
"2_Erros_Information_and_Debug": "2 - Fehler, Informationen und Debug-Meldungen",
@@ -27,8 +27,6 @@
"Accounts_AllowUserProfileChange": "Benutzern das Ändern des Profils erlauben",
"Accounts_AvatarResize": "Größe des Profilbilds anpassen",
"Accounts_AvatarSize": "Größe des Profilbilds",
- "Accounts_AvatarStorePath": "Speicherpfad des Profilbilds",
- "Accounts_AvatarStoreType": "Speichertyp des Profilbilds",
"Accounts_BlockedDomainsList": "Liste geblockter Domains",
"Accounts_BlockedDomainsList_Description": "Kommata getrennte Liste von geblockten Domains",
"Accounts_BlockedUsernameList": "Liste gesperrter Benutzernamen",
@@ -37,7 +35,7 @@
"Accounts_EmailVerification": "E-Mail-Verifizierung",
"Accounts_EmailVerification_Description": "Um diese Funktion nutzen zu können, stellen Sie bitte sicher, dass ihre SMTP-Einstellungen korrekt sind.",
"Accounts_Enrollment_Email": "Registrierungsmail",
- "Accounts_Enrollment_Email_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
",
+ "Accounts_Enrollment_Email_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
",
"Accounts_Enrollment_Email_Description": "Sie können die folgenden Platzhalter verwenden: [name], [fname], [lname] für den vollständigen Namen des Benutzers, Vornamen oder Nachnamen. [email] für die E-Mail-Adresse des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
"Accounts_Enrollment_Email_Subject_Default": "Willkommen zu [Site_Name]",
"Accounts_ForgetUserSessionOnWindowClose": "Benutzer Session vergessen, wenn Fenster geschlossen wird",
@@ -55,6 +53,7 @@
"Accounts_OAuth_Custom_id": "ID",
"Accounts_OAuth_Custom_Identity_Path": "Identitätspfad",
"Accounts_OAuth_Custom_Login_Style": "Anmeldungsart",
+ "Accounts_OAuth_Custom_Merge_Users": "BenutzerInnen zusammenführen",
"Accounts_OAuth_Custom_Scope": "Bereich",
"Accounts_OAuth_Custom_Secret": "Secret",
"Accounts_OAuth_Custom_Token_Path": "Pfad des Token",
@@ -91,10 +90,10 @@
"Accounts_OAuth_Twitter_callback_url": "Twitter-Callback-URL",
"Accounts_OAuth_Twitter_id": "Twitter-ID",
"Accounts_OAuth_Twitter_secret": "Twitter-Secret",
- "Accounts_OAuth_Wordpress": "Anmeldung über Wordpress",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress-Callback-URL",
+ "Accounts_OAuth_Wordpress": "Anmeldung über WordPress",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress-Callback-URL",
"Accounts_OAuth_Wordpress_id": "WordPress-ID",
- "Accounts_OAuth_Wordpress_secret": "Wordpress-Secret",
+ "Accounts_OAuth_Wordpress_secret": "WordPress-Secret",
"Accounts_PasswordReset": "Passwort zurücksetzen",
"Accounts_Registration_AuthenticationServices_Enabled": "Anmeldung mit Authentifizierungsdiensten",
"Accounts_RegistrationForm": "Anmeldeformular",
@@ -103,13 +102,13 @@
"Accounts_RegistrationForm_Public": "Öffentlich",
"Accounts_RegistrationForm_Secret_URL": "Geheime URL",
"Accounts_RegistrationForm_SecretURL": "Geheime URL für die Registrierungsseite",
- "Accounts_RegistrationForm_SecretURL_Description": "Sie müssen eine zufällige Zeichenfolge, die der Registrierungs-URL hinzugefügt wird, verwenden. Beispiel: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Sie müssen eine zufällige Zeichenfolge, die der Registrierungs-URL hinzugefügt wird, verwenden. Beispiel: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Namen für die Anmeldung verlangen",
"Accounts_RequirePasswordConfirmation": "Passwortbestätigung erforderlich",
"Accounts_ShowFormLogin": "Anmeldeformular zeigen",
"Accounts_UseDefaultBlockedDomainsList": "Standardliste für blockierte Domains verwenden",
"Accounts_UseDNSDomainCheck": "DNS-Domain-Check verwenden",
- "Accounts_UserAddedEmail_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
Sie können sich mit den folgenden Daten einloggen. E-Mail-Adresse: [email] Passwort: [password] Sie müssen Ihr Passwort möglicherweise nach dem ersten Login ändern.
",
+ "Accounts_UserAddedEmail_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
Sie können sich mit den folgenden Daten einloggen. E-Mail-Adresse: [email] Passwort: [password] Sie müssen Ihr Passwort möglicherweise nach dem ersten Login ändern.
",
"Accounts_UserAddedEmail_Description": "Sie können die folgenden Platzhalter verwenden: [name], [fname], [lname] für den vollständigen Namen des Benutzers, Vornamen oder Nachnamen. [email] für die E-Mail-Adresse des Benutzers. [password] für das Kennwort des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
"Accounts_UserAddedEmailSubject_Default": "Sie wurden auf [Site_Name] hinzugefügt",
"Activate": "Aktivieren",
@@ -118,12 +117,12 @@
"Add_agent": "Agent hinzufügen",
"Add_custom_oauth": "Benutzerdefiniertes OAuth-Konto hinzufügen",
"Add_manager": "Manager hinzufügen",
- "Add_user": "Benutzer hinzufügen",
- "Add_User": "Benutzer hinzufügen",
- "Add_users": "Benutzer hinzufügen",
+ "Add_user": "BenutzerIn hinzufügen",
+ "Add_User": "BenutzerIn hinzufügen",
+ "Add_users": "BenutzerInnen hinzufügen",
"Adding_OAuth_Services": "Hinzufügen von OAuth-Services",
"Adding_permission": "Berechtigung hinzufügen",
- "Adding_user": "Benutzer hinzufügen",
+ "Adding_user": "Füge BenutzerIn hinzu",
"Additional_emails": "Zusätzliche E-Mails",
"Additional_Feedback": "Zusätzliches Feedback",
"Administration": "Administration",
@@ -138,14 +137,16 @@
"All_messages": "Alle Nachrichten",
"Allow_Invalid_SelfSigned_Certs": "Ungültige und selbstsignierte SSL-Zertifikate erlauben",
"Allow_Invalid_SelfSigned_Certs_Description": "Ungültige und selbstsignierte SSL-Zertifikate für die Link-Validierung und die Vorschau zulassen",
+ "Allow_switching_departments": "Erlaube Besuchern das wechseln von Abeteilungen",
"Analytics_features_enabled": "Analyse - Funktionen aktiviert",
"Analytics_features_messages_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen eines Nutzer auf Nachrichten auf.",
"Analytics_features_rooms_Description": "Tracks benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen auf einem Kanal oder einer Gruppe (erstellen, verlassen, löschen).",
- "Analytics_features_users_Description": "Tracks benutzerdefinierte Ereignisse im Zusammenhang mit Maßnahmen im Zusammenhang mit Benutzer (Passwort-Reset-Zeiten, Profilbild ändern, etc).",
+ "Analytics_features_users_Description": "Zeichnet benutzerdefinierte Ereignisse auf (Passwort-Reset-Zeiten, Profilbild ändern, etc).",
"and": "und",
"And_more": "Und __length__ mehr",
"Animals_and_Nature": "Tiere & Natur",
"API": "API",
+ "API_Allow_Infinite_Count": "Erlauben, alles zu bekommen",
"API_Analytics": "Analytics",
"API_Embed": "Einbetten",
"API_EmbedDisabledFor": "Einbettungen für Benutzer deaktivieren",
@@ -159,7 +160,7 @@
"API_Gitlab_URL": "GitLab-URL",
"API_Token": "API-Token",
"API_User_Limit": "User Limit für das Hinzufügen aller Benutzer auf Kanal",
- "API_Wordpress_URL": "Wordpress-URL",
+ "API_Wordpress_URL": "WordPress-URL",
"Apiai_Key": "Api.ai Key",
"Apiai_Language": "Api.ai Sprache",
"Appearance": "Erscheinungsbild",
@@ -204,6 +205,7 @@
"Back_to_integrations": "Zurück zu Integrationen",
"Back_to_login": "Zurück zum Login",
"Back_to_permissions": "Zurück zu den Berechtigungen",
+ "Block_User": "BenutzerIn sperren",
"Body": "Body",
"bold": "fett",
"Branch": "Branch",
@@ -220,14 +222,14 @@
"CDN_PREFIX": "CDN-Präfix",
"Certificates_and_Keys": "Zertifikate und Schlüssel",
"Changing_email": "E-Mail-Adresse ändern",
- "channel": "Kanal",
- "Channel": "Kanal",
- "Channel_already_exist": "Der Kanal '#%s' ist bereits vorhanden.",
- "Channel_already_Unarchived": "Kanal mit dem Namen '#%s' ist bereits im unarchivierten Zustand",
- "Channel_Archived": "Kanal mit dem Namen '#%s' wurde erfolgreich archiviert",
- "Channel_doesnt_exist": "Der Kanal `#%s` existiert nicht.",
- "Channel_Unarchived": "Kanal mit dem Namen '#%s' ist nicht länger archiviert",
- "Channels": "Kanäle (für alle einsehbar)",
+ "channel": "Raum",
+ "Channel": "Raum",
+ "Channel_already_exist": "Der Raum '#%s' ist bereits vorhanden.",
+ "Channel_already_Unarchived": "Raum mit dem Namen '#%s' ist bereits im unarchivierten Zustand",
+ "Channel_Archived": "Raum mit dem Namen '#%s' wurde erfolgreich archiviert",
+ "Channel_doesnt_exist": "Der Raum `#%s` existiert nicht.",
+ "Channel_Unarchived": "Raum mit dem Namen '#%s' ist nicht länger archiviert",
+ "Channels": "Kanäle",
"Channels_list": "Liste der Kanäle",
"Chat_button": "Chatbutton",
"Chat_closed": "Chat geschlossen",
@@ -265,7 +267,7 @@
"Count": "Zähler",
"Cozy": "Angenehm",
"Create": "Erstellen",
- "Create_A_New_Channel": "Neuen Kanal einrichten",
+ "Create_A_New_Channel": "Neuen Raum einrichten",
"Create_new": "Neu erstellen",
"Created_at": "Erstellt am",
"Created_at_s_by_s": "Erstellt am %s von %s ",
@@ -317,7 +319,7 @@
"Drop_to_upload_file": "Ablegen, um Datei hochzuladen",
"Dry_run": "Probelauf",
"Dry_run_description": "Es wird nur eine E-Mail an die selbe Adresse wie im Feld Absender geschickt. Die E-Mailadresse muss einem gültigen Benutzer gehören.",
- "Duplicate_archived_channel_name": "Ein archivierter Kanal mit dem Namen '%s' existiert bereits.",
+ "Duplicate_archived_channel_name": "Ein archivierter Raum mit dem Namen '%s' existiert bereits.",
"Duplicate_archived_private_group_name": "Eine archivierte private Chatgruppe mit dem Namen '%s' existiert bereits.",
"Duplicate_channel_name": "Ein Chat mit dem Namen '%s' existiert bereits",
"Duplicate_private_group_name": "Eine private Chatgruppe mit dem Namen '%s' existiert bereits.",
@@ -327,7 +329,7 @@
"Edit_Department": "Abteilung bearbeiten",
"edited": "bearbeitet",
"Editing_room": "Raum bearbeiten",
- "Editing_user": "Benutzer bearbeiten",
+ "Editing_user": "Benutzern bearbeiten",
"Email": "E-Mail",
"Email_address_to_send_offline_messages": "E-Mail-Adresse zum Senden von Offline-Nachrichten",
"Email_already_exists": "Die E-Mail-Adresse existiert bereits.",
@@ -353,11 +355,12 @@
"Enter_a_room_name": "Raumnamen eingeben",
"Enter_a_username": "Geben Sie einen Benutzernamen ein",
"Enter_name_here": "Namen hier eingeben",
+ "Enter_Normal": "Normaler Modus (mit Eingabetaste senden)",
"Enter_to": "Enter-Taste: ",
"Error": "Fehler",
"error-action-not-allowed": "__action__ ist nicht erlaubt",
"error-application-not-found": "Anwendung nicht gefunden",
- "error-archived-duplicate-name": "Es gibt einen archivierten Kanal mit dem Namen '__room_name__'",
+ "error-archived-duplicate-name": "Es gibt einen archivierten Raum mit dem Namen '__room_name__'",
"error-avatar-invalid-url": "Ungültige Avatar-URL: __url__",
"error-avatar-url-handling": "Fehler beim Bearbeiten der Avatar-Einstellung von einer URL (__url__) für __username__",
"error-cant-invite-for-direct-room": "Nutzer können nicht in private Chaträume eingeladen werden.",
@@ -366,6 +369,7 @@
"error-could-not-change-username": "Konnte den Benutzernamen nicht ändern",
"error-delete-protected-role": "Eine geschützte Rolle kann nicht gelöscht werden.",
"error-department-not-found": "Abteilung konnte nicht gefunden werden.",
+ "error-direct-message-file-upload-not-allowed": "Dateiaustausch ist in direkten Nachrichten nicht möglich.",
"error-duplicate-channel-name": "Ein Kanal mit dem Namen '__channel_name__' existiert bereits.",
"error-email-domain-blacklisted": "Die Domain der E-Mail-Adresse ist blacklisted.",
"error-field-unavailable": "__field__ wird leider schon verwendet. ",
@@ -374,7 +378,7 @@
"error-input-is-not-a-valid-field": "__input__ ist kein gültiges __field__",
"error-invalid-arguments": "Ungültige Argumente",
"error-invalid-asset": "Ungültiger Wert",
- "error-invalid-channel": "Ungültiger Kanal.",
+ "error-invalid-channel": "Ungültiger Raum.",
"error-invalid-channel-start-with-chars": "Ungültiger Kanal. Beginnen Sie mit @ oder #",
"error-invalid-custom-field": "Ungültiges benutzerdefiniertes Feld",
"error-invalid-custom-field-name": "Unzulässiger Name für ein benutzerdefiniertes Feld. Benutze nur Buchstaben, Nummern, Binde- und Unterstriche.",
@@ -434,6 +438,7 @@
"File_type_is_not_accepted": "Feldtyp nicht akzeptiert.",
"FileUpload": "Dateien hochladen",
"FileUpload_Enabled": "Hochladen von Dateien aktivieren",
+ "FileUpload_Enabled_Direct": "Dateiaustausch ist in direkten Nachrichten möglich.",
"FileUpload_File_Empty": "Datei ist leer",
"FileUpload_FileSystemPath": "Systempfad",
"FileUpload_MaxFileSize": "Max. Größe für hochgeladene Dateien (in Bytes)",
@@ -458,6 +463,7 @@
"Force_SSL": "SSL erzwingen",
"Force_SSL_Description": "*Achtung!* _Force SSL_ solte niemals mit einem Reverse-Proxy verwendet werden. Falls Sie einen Reverse-Proxy verwenden, sollten Sie die Weiterleitung DORT einrichten. Dies Option existiert für Anwendungen wie Heroku, die keine Weiterleitungskonfigurationen für Reverse-Proxy erlauben.",
"Forgot_password": "Passwort vergessen?",
+ "Forward_to_user": "An BenutzerIn weiterleiten",
"Frequently_Used": "Häufig verwendet",
"From": "Absender",
"From_Email": "Absender",
@@ -522,7 +528,11 @@
"Integration_New": "Neue Integration",
"Integration_Outgoing_WebHook": "Ausgehende WebHook-Integration",
"Integration_updated": "Die Integration wurde aktualisiert.\n",
+ "Integration_Word_Trigger_Placement_Description": "Soll das auslösende Wort irgendwo im Satz stehen und nicht nur am Anfang? ",
"Integrations": "Integrationen",
+ "Integrations_Outgoing_Type_RoomJoined": "BenutzerIn hat den Raum betreten",
+ "Integrations_Outgoing_Type_RoomLeft": "BenutzerIn hat den Raum verlassen",
+ "Integrations_Outgoing_Type_UserCreated": "BenutzerIn angelegt.",
"InternalHubot": "Interner Hubot",
"InternalHubot_ScriptsToLoad": "Zu ladende Skripte",
"InternalHubot_ScriptsToLoad_Description": "Bitte geben Sie eine durch Kommata getrennte Liste von zu ladenden Skripten von https://github.com/github/hubot-scripts/tree/master/src/scripts an.",
@@ -543,8 +553,8 @@
"Invitation_HTML_Description": "Sie können die folgenden Platzhalter verwenden: [email] für den Empfänger der E-Mail. [Site_Name] und [Site_URL] jeweils für den Anwendungsnamen und die URL. ",
"Invitation_Subject": "Einladungsbetreff",
"Invitation_Subject_Default": "Sie wurden zu [Site_Name] eingeladen",
- "Invite_user_to_join_channel": "Benutzer in diesen Kanal einladen",
- "Invite_Users": "Benutzer einladen",
+ "Invite_user_to_join_channel": "Benutzer in diesen Raum einladen",
+ "Invite_Users": "BenutzerInnen einladen",
"is_also_typing": "schreibt auch",
"is_also_typing_female": "schreibt auch",
"is_also_typing_male": "schreibt auch",
@@ -558,7 +568,7 @@
"Join_audio_call": "Anruf beitreiten",
"Join_default_channels": "Standardkanälen beitreten",
"Join_the_Community": "Machen Sie mit!",
- "Join_the_given_channel": "Angegebenen Kanal beitreten",
+ "Join_the_given_channel": "Diesem Kanal beitreten",
"Join_video_call": "Videoanruf beitreten",
"Joined": "Beigetreten",
"Jump": "Springen",
@@ -588,24 +598,12 @@
"Layout_Terms_of_Service": "Nutzungsbedingungen",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA-Cert",
- "LDAP_Custom_Domain_Search": "Benutzerdefinierte Domainsuche",
- "LDAP_Custom_Domain_Search_Description": "Ein Teil aus JSON, welches Bindungs- und Verbindungsinformationen regelt und folgende Struktur besitzt: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Standard-Domain",
"LDAP_Description": "LDAP ist ein Frontend zu hierarchischen Datenbanken, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "Domainbasis",
- "LDAP_Domain_Base_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. SIe können so viele hinzufügen wie sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befindet. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, im Anwendungsbereich liegen. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um den Zugriff zu kontrollieren.",
- "LDAP_Domain_Search_Filter": "Filter der Domainsuche",
- "LDAP_Domain_Search_Filter_Description": "Wenn angegeben, wird nur Benutzern, die dem Filter entsprechen, erlaubt, sich anzumelden. Wenn kein Filter angegeben ist, werden sich alle Benutzer in dem Bereich der angegebenen Domainbasis anmelden können. Ein Beispiel für Active-Directory: `memberOf=cn=ROCKET_CHAT,ou=General Groups` Ein Beispiel für OpenLDAP (erweiterbare Übereinstimmungssuche): `ou:dn:=ROCKET_CHAT`",
- "LDAP_Domain_Search_Object_Category": "Objektkategorie der Domainsuche",
- "LDAP_Domain_Search_Object_Category_Description": "Die *objectCategory*, die Ihre Nutzer identifizert. Lassen Sie das Feld leer, um *OpenLDAP* zu aktivieren. Beispiel: `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Objektklasse der Domainsuche",
- "LDAP_Domain_Search_Object_Class_Description": "Die *objectclass*, die Ihre Nutzer identifizert. Beispiel: `organizationalPerson`, `user`, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Passwort der Domainsuche",
- "LDAP_Domain_Search_Password_Description": "Das Passwort für die Benuzer der Domainsuche",
- "LDAP_Domain_Search_User": "Domain Search User",
- "LDAP_Domain_Search_User_Description": "Der LDAP-Benutzer, der eine Benutzersuche durchführt, um andere Nutzer bei der Anmeldung zu authentifizieren. Dies ist in der Regel ein Servicekonto, welches für Drittintegrationen erstellt worden ist. Verwenden Sie einen vollen Namen, wie zum Beispiel `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search User ID",
- "LDAP_Domain_Search_User_ID_Description": "Das LDAP-Attribut, welches den LDAP-Benutzer identifiziert, der sich zu authentifizieren versucht. Das Feld ist für die meisten Active-Directory-Installationen `sAMAccountName`, für andere LDAP-Lösungen wie OpenLDAP kann dieses jedoch auch `uid` sein. Sie können aber auch `mail` verwenden, um Benutzer mit Ihrer E-Mail-Adresse zu identifizieren oder jedes Attribut, das Sie möchten. Sie können mehrere Werte, getrennt mit Kommata, verwenden, um es Benutzern zu erlauben, sich mit mehreren Kennungen anzumelden, wie zum Beispiel einem Benutzernamen und der E-Mail-Adresse.",
+ "LDAP_BaseDN_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. SIe können so viele hinzufügen wie sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befindet. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, im Anwendungsbereich liegen. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um den Zugriff zu kontrollieren.",
+ "LDAP_User_Search_Field_Description": "Das LDAP-Attribut, welches den LDAP-Benutzer identifiziert, der sich zu authentifizieren versucht. Das Feld ist für die meisten Active-Directory-Installationen `sAMAccountName`, für andere LDAP-Lösungen wie OpenLDAP kann dieses jedoch auch `uid` sein. Sie können aber auch `mail` verwenden, um Benutzer mit Ihrer E-Mail-Adresse zu identifizieren oder jedes Attribut, das Sie möchten. Sie können mehrere Werte, getrennt mit Kommata, verwenden, um es Benutzern zu erlauben, sich mit mehreren Kennungen anzumelden, wie zum Beispiel einem Benutzernamen und der E-Mail-Adresse.",
+ "LDAP_User_Search_Filter_Description": "Wenn angegeben, wird nur Benutzern, die dem Filter entsprechen, erlaubt, sich anzumelden. Wenn kein Filter angegeben ist, werden sich alle Benutzer in dem Bereich der angegebenen Domainbasis anmelden können. Ein Beispiel für Active-Directory: `memberOf=cn=ROCKET_CHAT,ou=General Groups` Ein Beispiel für OpenLDAP (erweiterbare Übereinstimmungssuche): `ou:dn:=ROCKET_CHAT`",
+ "LDAP_Authentication_UserDN_Description": "Der LDAP-Benutzer, der eine Benutzersuche durchführt, um andere Nutzer bei der Anmeldung zu authentifizieren. Dies ist in der Regel ein Servicekonto, welches für Drittintegrationen erstellt worden ist. Verwenden Sie einen vollen Namen, wie zum Beispiel `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "LDAP aktivieren",
"LDAP_Enable_Description": "LDAP für die Authentifizierung verwenden.",
"LDAP_Encryption": "Verschlüsselung",
@@ -620,12 +618,9 @@
"LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Beispiel: Name, E-Mail).",
"LDAP_Sync_User_Data_FieldMap": "Nutzerdaten-Feldkarte",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfigurieren Sie, wie Benutzer-Account-Felder (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden. Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen von dem cn-Attribut und die E-Mail-Adresse vom Mail-Attribut. Verfügbare Felder beinhalten den Namen und die E-Mail-Adresse.",
- "LDAP_Sync_Users": "Benutzer synchronisieren",
"LDAP_Test_Connection": "Testverbindung",
"LDAP_Unique_Identifier_Field": "Eindeutige Kennung des Felds",
"LDAP_Unique_Identifier_Field_Description": "Dieses Feld wird verwendet, um LDAP-Nutzer und Rocket.Chat-Nutzer zu verbinden. Sie können mehrere Kommata-getrennte Werte angeben, um die Werte vom LDAP-Eintrag zu erhalten. Der Standardwert ist `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`.",
- "LDAP_Use_Custom_Domain_Search": "Benutzerdefinierte Domainsuche verwenden",
- "LDAP_Use_Custom_Domain_Search_Description": "Schreiben Sie Ihren eigenen Filter, um Benutzer auf dem LDAP-Server zu suchen.",
"LDAP_Username_Field": "Nutzernamenfeld",
"LDAP_Username_Field_Description": "Geben Sie an, welches Feld als *Nutzername* für neue Benutzer verwendet werden soll. Lassen Sie das Feld leer, um den Nutzernamen zu verwenden, der auf der Anmeldeseite verwendet wird. Es können auch Template-Tags wie `#{givenNamen}.#{sn}` verwendet werden. Der Standardwert ist `sAMAccountName`.",
"Least_Amount": "Geringste Anzahl",
@@ -785,6 +780,7 @@
"Nothing_found": "Es wurde nichts gefunden.",
"Notification_Duration": "Dauer der Benachrichtigung",
"Notifications": "Benachrichtigungen",
+ "Notify_active_in_this_room": "Aktive Benutzer/innen benachrichtigen",
"Notify_all_in_this_room": "Alle Benutzer in diesem Raum benachrichtigen",
"Num_Agents": "# Agents",
"Number_of_messages": "Anzahl der Nachrichten",
@@ -794,7 +790,7 @@
"Off": "Aus",
"Off_the_record_conversation": "Off-the-record-Gespräche",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record-Gespräche sind für Ihren Browser oder Ihr Gerät nicht verfügbar.",
- "Office_Hours_Enabled": "Bürozeiten aktiviert",
+ "Office_hours_enabled": "Bürozeiten aktiviert",
"Offline": "Offline",
"Offline_DM_Email": "Private Nachricht von __user__ erhalten.",
"Offline_form": "Offline-Formular",
@@ -1064,7 +1060,7 @@
"Thank_you_exclamation_mark": "Vielen Dank!",
"Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung.",
"The_application_name_is_required": "Es muss ein Name für diese Anwendung angegeben werden.",
- "The_channel_name_is_required": "Ein Name für den Kanal muss angegeben werden.",
+ "The_channel_name_is_required": "Ein Name für den Raum muss angegeben werden.",
"The_emails_are_being_sent": "Die E-Mails werden gesendet.",
"The_field_is_required": "Das Feld %s ist erforderlich.",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Die automatische Skalierung der Bilder funktioniert nicht, da ImageMagick oder GraphicsMagick nicht auf dem Server installiert sind.",
@@ -1075,19 +1071,19 @@
"The_user_wont_be_able_to_type_in_s": "Der Benutzer kann nicht mehr in %s schreiben.",
"Theme": "Theme",
"theme-color-content-background-color": "Hintergrundfarbe des Inhalts",
+ "theme-color-custom-scrollbar-color": "Benutzerdefinierte Farbe der Scrollbar",
+ "theme-color-info-font-color": "Schriftfarbe von Informationen",
+ "theme-color-link-font-color": "Schriftfarbe des Links",
"theme-color-primary-background-color": "Primäre Hintergrundfarbe ",
"theme-color-primary-font-color": "Primäre Schriftfarbe",
"theme-color-secondary-background-color": "Sekundäre Hintergrundfarbe",
"theme-color-secondary-font-color": "Sekundäre Schriftfarbe",
- "theme-color-tertiary-background-color": "Tertiäre Hintergrundfarbe ",
- "theme-color-tertiary-font-color": "Tertiäre Schriftfarbe",
- "theme-color-link-font-color": "Schriftfarbe des Links",
- "theme-color-info-font-color": "Schriftfarbe von Informationen",
- "theme-color-custom-scrollbar-color": "Benutzerdefinierte Farbe der Scrollbar",
"theme-color-status-away": "Farbe des Status \"abwesend\"",
"theme-color-status-busy": "Farbe des Status \"beschäftigt\"",
"theme-color-status-offline": "Farbe des Status \"offline\"\n",
"theme-color-status-online": "Farbe des Status \"online\"",
+ "theme-color-tertiary-background-color": "Tertiäre Hintergrundfarbe ",
+ "theme-color-tertiary-font-color": "Tertiäre Schriftfarbe",
"theme-color-unread-notification-color": "Farbe von ungelesenen Benachrichtigungen",
"theme-custom-css": "Benutzerdefiniertes CSS",
"There_are_no_agents_added_to_this_department_yet": "Es wurden bisher keine Agenten zu dieser Abteilung hinzugefügt.",
@@ -1117,13 +1113,12 @@
"Type_your_name": "Geben Sie Ihren Namen ein",
"Type_your_new_password": "Geben Sie Ihr neues Passwort ein",
"UI_DisplayRoles": "Rollen anzeigen",
- "UI_Merge_Channels_Groups": "Private Gruppen mit Kanälen gemeinsam anzeigen",
+ "UI_Merge_Channels_Groups": "Private Gruppen mit öffentlichen Kanälen gemeinsam anzeigen",
"Unarchive": "Wiederherstellen",
"Unmute_someone_in_room": "Jemanden das Chatten in einem Raum wieder erlauben",
"Unmute_user": "Benutzern das Chatten erlauben ",
"Unnamed": "Unbenannt",
"Unpin_Message": "Nachicht nicht mehr fixieren",
- "Unread_Alert": "Über Ungelesenes benachrichtigen",
"Unread_Rooms": "Ungelesene Räume",
"Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
"Unstar_Message": "Markierung entfernen",
@@ -1156,9 +1151,9 @@
"User_Info": "Benutzerinformationen",
"User_is_no_longer_an_admin": "Der Benutzer ist kein Admin mehr.",
"User_is_now_an_admin": "Der Benutzer ist jetzt ein Admin.",
- "User_joined_channel": "Ist dem Kanal beigetreten.",
- "User_joined_channel_female": "Ist dem Kanal beigetreten.",
- "User_joined_channel_male": "Ist dem Kanal beigetreten.",
+ "User_joined_channel": "Ist dem Raum beigetreten.",
+ "User_joined_channel_female": "Ist dem Raum beigetreten.",
+ "User_joined_channel_male": "Ist dem Raum beigetreten.",
"User_left": "Benutzer.in __user_left__ hat den Kanal verlassen.",
"User_left_female": "Der Benutzer __user_left__ hat den Kanal verlassen.",
"User_left_male": "Der Benutzer __user_left__ hat den Kanal verlassen.",
@@ -1265,4 +1260,4 @@
"your_message_optional": "ihre optionale Nachricht",
"Your_password_is_wrong": "Falsches Passwort",
"Your_push_was_sent_to_s_devices": "Die Push-Nachricht wurde an %s Geräte gesendet."
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json
index 4270f720c9a2c..195ab20cf67e5 100644
--- a/packages/rocketchat-i18n/i18n/de.i18n.json
+++ b/packages/rocketchat-i18n/i18n/de.i18n.json
@@ -11,41 +11,52 @@
"__username__was_set__role__by__user_by_": "__username__ ist jetzt __role__, geändert durch __user_by__",
"Accept": "Akzeptieren",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Akzeptiere eingehende Livechat-Anfragen auch wenn kein Agent online ist",
- "Accept_with_no_online_agents": "Akzeptiere ohne Online Agenten",
+ "Accept_with_no_online_agents": "Auch annehmen, wenn keine Agenten online sind",
+ "access-mailer": "Zugriff auf den Mailer",
+ "access-mailer_description": "Berechtigung, Massen-E-Mails an alle Benutzer zu versenden.",
+ "access-permissions": "Zugriff auf die Berechtigungs-Übersicht",
+ "access-permissions_description": "Anpassen der Berechtigungen für die unterschiedlichen Rollen.",
"Access_not_authorized": "Der Zugriff ist nicht gestattet.",
"Access_Token_URL": "URL des Access-Token",
"Accessing_permissions": "Zugriff auf Berechtigungen",
"Account_SID": "Konto-SID",
"Accounts": "Konten",
+ "Accounts_AllowAnonymousRead": "Erlaube anonymes Lesen",
+ "Accounts_AllowAnonymousWrite": "Erlaube anonymes Schreiben",
"Accounts_AllowDeleteOwnAccount": "Benutzern erlauben, ihr Konto zu löschen",
"Accounts_AllowedDomainsList": "Liste von erlaubten Domains",
"Accounts_AllowedDomainsList_Description": "Durch Kommata getrennte Liste von erlaubten Domains",
"Accounts_AllowEmailChange": "Ändern der E-Mail-Adresse erlauben",
"Accounts_AllowPasswordChange": "Ändern des Passworts erlauben",
"Accounts_AllowUserAvatarChange": "Benutzern das Ändern des Profilbilds erlauben",
+ "Accounts_AllowRealNameChange": "Ändern des Namens erlauben",
"Accounts_AllowUsernameChange": "Ändern des Benutzernamens erlauben",
"Accounts_AllowUserProfileChange": "Benutzern das Ändern des Profils erlauben",
"Accounts_AvatarResize": "Größe des Profilbilds anpassen",
"Accounts_AvatarSize": "Größe des Profilbilds",
- "Accounts_AvatarStorePath": "Speicherpfad des Profilbilds",
- "Accounts_AvatarStoreType": "Speichertyp des Profilbilds",
"Accounts_BlockedDomainsList": "Liste geblockter Domains",
"Accounts_BlockedDomainsList_Description": "Kommata getrennte Liste von geblockten Domains",
"Accounts_BlockedUsernameList": "Liste gesperrter Benutzernamen",
"Accounts_BlockedUsernameList_Description": "Komma-getrennte Liste gesperrter Benutzernamen (case-insensitive)",
+ "Accounts_CustomFields_Description": "Ein gültiges JSON, in dem die Schlüssel Sprachkürzel sind, die wiederum Tupel von Schlüssel und Übersetzungen enthalten. Beispiel: \n{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n}",
+ "Accounts_CustomFieldsToShowInUserInfo": "Eigene Felder, die in der Benutzer-Information angezeigt werden sollen",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Vorschlag für Präfix des Standard-Benutzernamens ",
+ "Accounts_Default_User_Preferences_audioNotifications": "Akustische Benachrichtigung bei",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Desktop-Benachrichtigungen bei",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Mobile Benachrichtigungen bei",
"Accounts_denyUnverifiedEmail": "Nicht verifizierte E-Mail-Adressen ablehnen",
"Accounts_EmailVerification": "E-Mail-Verifizierung",
- "Accounts_EmailVerification_Description": "Um diese Funktion nutzen zu können, stellen Sie bitte sicher, dass ihre SMTP-Einstellungen korrekt sind.",
+ "Accounts_EmailVerification_Description": "Um diese Funktion nutzen zu können, stellen Sie bitte sicher, dass Ihre SMTP-Einstellungen korrekt sind.",
"Accounts_Enrollment_Email": "Registrierungsmail",
- "Accounts_Enrollment_Email_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
",
- "Accounts_Enrollment_Email_Description": "Sie können die folgenden Platzhalter verwenden: [name], [fname], [lname] für den vollständigen Namen des Benutzers, Vornamen oder Nachnamen. [email] für die E-Mail-Adresse des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
+ "Accounts_Enrollment_Email_Default": " Willkommen zu [Site_Name] Besuche [Site_URL] und probiere noch heute die beste Open-Source-Chat-Lösung aus.
",
+ "Accounts_Enrollment_Email_Description": "Sie können die folgenden Platzhalter verwenden: [name], [fname], [lname] für den vollständigen Namen, Vornamen oder Nachnamen des Benutzers. [email] für die E-Mail-Adresse des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsnamen und die URL. ",
"Accounts_Enrollment_Email_Subject_Default": "Willkommen zu [Site_Name]",
- "Accounts_ForgetUserSessionOnWindowClose": "Benutzer Session vergessen, wenn Fenster geschlossen wird",
+ "Accounts_ForgetUserSessionOnWindowClose": "Benutzer Session beenden, wenn das Fenster geschlossen wird",
"Accounts_Iframe_api_method": "API-Methode",
"Accounts_Iframe_api_url": "API-URL",
"Accounts_iframe_enabled": "aktiviert",
"Accounts_iframe_url": "iFrame-URL",
- "Accounts_LoginExpiration": "Ablauffrist der Anmeldung",
+ "Accounts_LoginExpiration": "Ablauffrist der Anmeldung in Tagen",
"Accounts_ManuallyApproveNewUsers": "Neue Benutzer manuell aktivieren",
"Accounts_OAuth_Custom_Authorize_Path": "Autorisierungspfad",
"Accounts_OAuth_Custom_Button_Color": "Buttonfarbe",
@@ -55,47 +66,57 @@
"Accounts_OAuth_Custom_id": "ID",
"Accounts_OAuth_Custom_Identity_Path": "Identitätspfad",
"Accounts_OAuth_Custom_Login_Style": "Anmeldungsart",
+ "Accounts_OAuth_Custom_Merge_Users": "Benutzer zusammenführen",
"Accounts_OAuth_Custom_Scope": "Bereich",
- "Accounts_OAuth_Custom_Secret": "Secret",
+ "Accounts_OAuth_Custom_Secret": "Geheimer Schlüssel",
"Accounts_OAuth_Custom_Token_Path": "Pfad des Token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token gesendet über",
+ "Accounts_OAuth_Custom_Username_Field": "Feld für Benutzernamen",
+ "Accounts_OAuth_Drupal": "Anmeldung über Drupal",
+ "Accounts_OAuth_Drupal_callback_url": "Drupal OAuth Redirect Url",
+ "Accounts_OAuth_Drupal_id": "Drupal oAuth2 Client ID",
+ "Accounts_OAuth_Drupal_secret": "Geheimer Drupal oAuth2 Client Schlüssel",
"Accounts_OAuth_Facebook": "Anmeldung über Facebook erlauben",
"Accounts_OAuth_Facebook_callback_url": "Facebook-Callback-URL",
"Accounts_OAuth_Facebook_id": "Facebook-App-ID",
- "Accounts_OAuth_Facebook_secret": "Facebook-Secret",
+ "Accounts_OAuth_Facebook_secret": "Geheimer Facebook Schlüssel ",
"Accounts_OAuth_Github": "OAuth aktivieren",
"Accounts_OAuth_Github_callback_url": "GitHub-Callback-URL",
"Accounts_OAuth_GitHub_Enterprise": "OAuth aktiviert",
"Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub-Enterprise-Callback-URL",
"Accounts_OAuth_GitHub_Enterprise_id": "Client-ID",
- "Accounts_OAuth_GitHub_Enterprise_secret": "Client-Secret",
+ "Accounts_OAuth_GitHub_Enterprise_secret": "Geheimer Client Schlüssel",
"Accounts_OAuth_Github_id": "Client-ID",
- "Accounts_OAuth_Github_secret": "Client-Secret",
+ "Accounts_OAuth_Github_secret": "Geheimer Client Schlüssel",
"Accounts_OAuth_Gitlab": "OAuth aktiviert",
"Accounts_OAuth_Gitlab_callback_url": "GitLab-Callback-URL",
"Accounts_OAuth_Gitlab_id": "GitLab-ID",
- "Accounts_OAuth_Gitlab_secret": "Client-Secret",
+ "Accounts_OAuth_Gitlab_secret": "Geheimer Client Schlüssel",
"Accounts_OAuth_Google": "Google-Anmeldung erlauben",
"Accounts_OAuth_Google_callback_url": "Google-Callback-URL",
"Accounts_OAuth_Google_id": "Google-ID",
- "Accounts_OAuth_Google_secret": "Google-Secret",
- "Accounts_OAuth_Linkedin": "Anmeldung über LinkedIn erlauben",
+ "Accounts_OAuth_Google_secret": "Geheimer Google Schlüssel",
+ "Accounts_OAuth_Linkedin": "LinkedIn-Anmeldung erlauben",
"Accounts_OAuth_Linkedin_callback_url": "LinkedIn-Callback-URL",
"Accounts_OAuth_Linkedin_id": "LinkedIn-ID",
- "Accounts_OAuth_Linkedin_secret": "Linkeding-Secret",
- "Accounts_OAuth_Meteor": "Anmeldung über Meteor erlauben",
+ "Accounts_OAuth_Linkedin_secret": "Geheimer LinkedIn Schlüssel",
+ "Accounts_OAuth_Meteor": "Meteor-Anmeldung erlauben",
"Accounts_OAuth_Meteor_callback_url": "Meteor-Callback-URL",
"Accounts_OAuth_Meteor_id": "Meteor-ID",
- "Accounts_OAuth_Meteor_secret": "Meteor-Secret",
- "Accounts_OAuth_Twitter": "Anmeldung über Twitter erlauben",
+ "Accounts_OAuth_Meteor_secret": "Geheimer Meteor Schlüssel",
+ "Accounts_OAuth_Proxy_host": "Proxy Host",
+ "Accounts_OAuth_Proxy_services": "Proxy Port",
+ "Accounts_OAuth_Twitter": "Anmeldung über Twitter",
"Accounts_OAuth_Twitter_callback_url": "Twitter-Callback-URL",
"Accounts_OAuth_Twitter_id": "Twitter-ID",
- "Accounts_OAuth_Twitter_secret": "Twitter-Secret",
- "Accounts_OAuth_Wordpress": "Anmeldung über Wordpress",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress-Callback-URL",
+ "Accounts_OAuth_Twitter_secret": "Geheimer Twitter Schlüssel",
+ "Accounts_OAuth_Wordpress": "WordPress-Anmeldung erlauben",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress-Callback-URL",
"Accounts_OAuth_Wordpress_id": "WordPress-ID",
- "Accounts_OAuth_Wordpress_secret": "Wordpress-Secret",
+ "Accounts_OAuth_Wordpress_secret": "Geheimer WordPress Schlüssel",
"Accounts_PasswordReset": "Passwort zurücksetzen",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Standardrolle bei Nutzung von Authentifizierungsdiensten",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Standardrollen, die Benutzern zugewiesen werden, wenn diese sich über Authentifizierungsdienste registrieren",
"Accounts_Registration_AuthenticationServices_Enabled": "Anmeldung mit Authentifizierungsdiensten",
"Accounts_RegistrationForm": "Anmeldeformular",
"Accounts_RegistrationForm_Disabled": "Deaktiviert",
@@ -103,100 +124,161 @@
"Accounts_RegistrationForm_Public": "Öffentlich",
"Accounts_RegistrationForm_Secret_URL": "Geheime URL",
"Accounts_RegistrationForm_SecretURL": "Geheime URL für die Registrierungsseite",
- "Accounts_RegistrationForm_SecretURL_Description": "Sie müssen eine zufällige Zeichenfolge, die der Registrierungs-URL hinzugefügt wird, angeben. Beispiel: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Gib eine zufällige Zeichenfolge, die der Registrierungs-URL hinzugefügt wird, an. Zum Beispiel: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Namen für die Anmeldung verlangen",
"Accounts_RequirePasswordConfirmation": "Passwortbestätigung erforderlich",
+ "Accounts_SearchFields": "Felder, die in der Suche berücksichtigt werden sollen",
+ "Accounts_SetDefaultAvatar": "Standard-Avatar setzen",
+ "Accounts_SetDefaultAvatar_Description": "Versuche Standard-Avatar über OAuth oder Gravatar zu bestimmen",
"Accounts_ShowFormLogin": "Anmeldeformular zeigen",
"Accounts_UseDefaultBlockedDomainsList": "Standardliste für blockierte Domains verwenden",
"Accounts_UseDNSDomainCheck": "DNS-Domain-Check verwenden",
- "Accounts_UserAddedEmail_Default": " Willkommen zu [Site_Name] Besuchen Sie [Site_URL] und probieren Sie noch heute die beste Open-Source-Chat-Lösung aus.
Sie können sich mit den folgenden Daten einloggen. E-Mail-Adresse: [email] Passwort: [password] Sie müssen Ihr Passwort möglicherweise nach dem ersten Login ändern.
",
+ "Accounts_UserAddedEmail_Default": " Willkommen zu [Site_Name] Besuche [Site_URL] und probiere noch heute die beste Open-Source-Chat-Lösung aus.
Du kannst Dich mit den folgenden Daten anmelden: E-Mail-Adresse: [email] Passwort: [password] Es kann sein, dass Du Dein Passwort nach der ersten Anmeldung ändern musst
",
"Accounts_UserAddedEmail_Description": "Sie können die folgenden Platzhalter verwenden: [name], [fname], [lname] für den vollständigen Namen des Benutzers, Vornamen oder Nachnamen. [email] für die E-Mail-Adresse des Benutzers. [password] für das Kennwort des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
- "Accounts_UserAddedEmailSubject_Default": "Sie wurden auf [Site_Name] hinzugefügt",
+ "Accounts_UserAddedEmailSubject_Default": "Du wurdest auf [Site_Name] hinzugefügt",
"Activate": "Aktivieren",
"Activity": "Aktivität",
"Add": "Hinzufügen",
+ "add-oauth-service": "OAuth-Dienst hinzufügen",
+ "add-oauth-service_description": "Berechtigung, einen neuen OAuth-Dienst hinzuzufügen",
+ "add-user": "Benutzer erstellen",
+ "add-user-to-any-c-room": "Füge Benutzer zu jedem öffentlichen Kanal hinzu",
+ "add-user-to-any-c-room_description": "Berechtigung, um Benutzer zu jedem öffentlichen Kanal hinzuzufügen",
+ "add-user-to-any-p-room": "Benutzer jedem privaten Kanal hinzufügen",
+ "add-user-to-any-p-room_description": "Berechtigung, Benutzer jedem privaten Kanal hinzuzufügen",
+ "add-user-to-joined-room": "Benutzer jedem beigetretenen Kanal hinzufügen",
+ "add-user-to-joined-room_description": "Berechtigung, Benutzer jedem beigetretenen Kanal hinzuzufügen",
+ "add-user_description": "Berechtigung, über den Benutzer-Bildschirm neue Nutzer anzulegen",
"Add_agent": "Agent hinzufügen",
"Add_custom_oauth": "Benutzerdefiniertes OAuth-Konto hinzufügen",
+ "Add_Domain": "Domain hinzufügen",
+ "Add_files_from": "Dateien hinzufügen von",
"Add_manager": "Manager hinzufügen",
- "Add_user": "Benutzer hinzufügen",
- "Add_User": "Benutzer hinzufügen",
- "Add_users": "Benutzer hinzufügen",
+ "Add_Role": "Rolle hinzufügen",
+ "Add_user": "BenutzerIn hinzufügen",
+ "Add_User": "BenutzerIn hinzufügen",
+ "Add_users": "BenutzerInnen hinzufügen",
"Adding_OAuth_Services": "Hinzufügen von OAuth-Services",
"Adding_permission": "Berechtigung hinzufügen",
- "Adding_user": "Benutzer hinzufügen",
+ "Adding_user": "Füge BenutzerIn hinzu",
"Additional_emails": "Zusätzliche E-Mails",
"Additional_Feedback": "Zusätzliches Feedback",
"Administration": "Administration",
+ "Adult_images_are_not_allowed": "Nicht-jugendfreie Bilder sind nicht erlaubt",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Nach der OAuth2-Authentifizierung werden die Benutzer auf diese URL weitergeleitet.",
"Agent": "Agent",
"Agent_added": "Der Agent wurde hinzugefügt.",
"Agent_removed": "Der Agent wurde gelöscht.",
"Alias": "Alias",
- "Alias_Format": "Alias Format",
+ "Alias_Format": "Alias-Format",
"Alias_Format_Description": "Nachricht von Slack mit einem Alias importieren; %s wird mit dem Benutzernamen ersetzt. Wenn Feld leer bleibt, wird kein Alias benutzt.",
+ "Alias_Set": "Alias setzen",
"All": "Alle",
"All_channels": "Alle Kanäle",
"All_logs": "Alle Protokolle",
"All_messages": "Alle Nachrichten",
+ "All_users_in_the_channel_can_write_new_messages": "Alle Benutzer in diesem Kanal dürfen Nachrichten schreiben",
"Allow_Invalid_SelfSigned_Certs": "Ungültige und selbstsignierte SSL-Zertifikate erlauben",
"Allow_Invalid_SelfSigned_Certs_Description": "Ungültige und selbstsignierte SSL-Zertifikate für die Link-Validierung und die Vorschau zulassen.",
- "Analytics_features_enabled": "Analyse - Funktionen aktiviert",
- "Analytics_features_messages_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen eines Nutzer auf Nachrichten auf.",
- "Analytics_features_rooms_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen in einem Kanal oder einer Gruppe (erstellen, verlassen, löschen) auf.",
- "Analytics_features_users_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Maßnahmen im Zusammenhang mit Benutzer (Passwort-Reset-Zeiten, Profilbild ändern, etc) auf.",
+ "Allow_switching_departments": "Erlaube Besuchern, Abteilungen zu wechseln",
+ "Always_open_in_new_window": "Immer in neuem Fenster öffnen",
+ "Analytics_features_enabled": "Aktivierte Funktionen",
+ "Analytics_features_messages_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen eines Nutzers in Nachrichten auf.",
+ "Analytics_features_rooms_Description": "Zeichnet benutzerdefinierte Ereignisse im Zusammenhang mit Aktionen in einem Kanal (erstellen, verlassen, löschen) auf.",
+ "Analytics_features_users_Description": "Zeichnet benutzerdefinierte Ereignisse (Passwort-Reset-Zeiten, Profilbild ändern, etc) auf.",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "Tracking ID",
"and": "und",
"And_more": "Und __length__ mehr",
"Animals_and_Nature": "Tiere & Natur",
+ "Announcement": "Ankündigung",
"API": "API",
+ "API_Allow_Infinite_Count": "Ergebnismenge nicht einschränken",
+ "API_Allow_Infinite_Count_Description": "Erlaube die Rückgabe von REST API Ergebnissen in einem einzigen Abruf",
"API_Analytics": "Analytics",
- "API_Embed": "Einbetten",
+ "API_CORS_Origin": "CORS Origin",
+ "API_Default_Count": "Standard Limit",
+ "API_Default_Count_Description": "Die Anzahl an Ergebnissen von REST API Anfragen, wenn kein Limit angegeben wurde.",
+ "API_Drupal_URL": "Drupal Server URL",
+ "API_Drupal_URL_Description": "Beispiel: https://domain.de (ohne abschließenden /)",
+ "API_Embed": "Link-Vorschauen einbetten",
+ "API_Embed_Description": "Eingebettete Link-Vorschau für Links, die von Benutzern gepostet wurden.",
+ "API_Embed_UserAgent": "User Agent des Requests übermitteln",
+ "API_EmbedCacheExpirationDays": "Tage bis zum Ablauf den eingebetteten Caches",
"API_EmbedDisabledFor": "Einbettungen für Benutzer deaktivieren",
- "API_EmbedDisabledFor_Description": "Durch Kommata getrennte Liste von Benutzernamen",
+ "API_EmbedDisabledFor_Description": "Kommaseparierte Liste von Benutzernamen zum Einbetten von Link-Vorschauen",
"API_EmbedIgnoredHosts": "Ignorierte Hosts einbetten",
"API_EmbedIgnoredHosts_Description": "Kommagetrennte Liste von Hosts oder CIDR-Adressen, z. B. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Sichere Ports",
"API_EmbedSafePorts_Description": "Kommagetrennte Liste der Ports, für die eine Vorschau erlaubt ist.",
+ "API_Enable_CORS": "CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "Endpunkt für den Verlauf von Direktnachrichten",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Aktiviere `/api/v1/im.history.others`. Hierüber ist es möglich, Direktnachrichten einzusehen, an denen der Benutzer nicht beteiligt ist.",
+ "API_Enable_Shields": "Aktiviere Shields",
+ "API_Enable_Shields_Description": "Mache Shields über `/api/v1/shield.svg` abrufbar",
"API_GitHub_Enterprise_URL": "Server-URL",
"API_GitHub_Enterprise_URL_Description": "Beispiel: http://domain.com (ohne Schrägstrich am Ende)",
"API_Gitlab_URL": "GitLab-URL",
+ "API_Shield_Types": "Shield Typen",
+ "API_Shield_Types_Description": "Shields-Typen. Konfiguration mit einer Komma-separierten-Liste. Optionen: `online`, `channel` oder `*` für \"Alles\"",
"API_Token": "API-Token",
- "API_User_Limit": "User Limit für das Hinzufügen aller Benutzer auf Kanal",
- "API_Wordpress_URL": "Wordpress-URL",
- "Apiai_Key": "Api.ai Key",
- "Apiai_Language": "Api.ai Sprache",
+ "API_Upper_Count_Limit": "Maximales Limit",
+ "API_Upper_Count_Limit_Description": "Max. Anzahl an Einträgen, die das REST API zurückliefen soll (sofern nicht weiter eingeschränkt)",
+ "API_User_Limit": "Limit für das Hinzufügen aller Benutzer zu einem Kanal",
+ "API_Wordpress_URL": "WordPress-URL",
+ "Apiai_Key": "Api.ai-Schlüssel",
+ "Apiai_Language": "Api.ai-Sprache",
"Appearance": "Erscheinungsbild",
"Application_added": "Die Anwendung wurde hinzugefügt.",
"Application_Name": "Name der Anwendung",
"Application_updated": "Die Anwendung wurde aktualisiert.",
- "Apply_and_refresh_all_clients": "Alle Clients anwenden und aktualisieren",
+ "Apply_and_refresh_all_clients": "Anwenden und alle Clients aktualisieren",
"Archive": "Archivieren",
+ "archive-room": "Kanal archivieren",
+ "archive-room_description": "Berechtigung, einen Kanal zu archivieren",
"are_also_typing": "schreiben auch",
"are_typing": "schreiben",
- "Are_you_sure": "Sind Sie sicher?",
- "Are_you_sure_you_want_to_delete_your_account": "Sind Sie sicher, dass Sie Ihr Konto löschen möchten?",
+ "Are_you_sure": "Bist Du sicher?",
+ "Are_you_sure_you_want_to_delete_your_account": "Bist Du sicher, dass Du Dein Konto löschen möchtest?",
+ "assign-admin-role": "Administratorrolle zuordnen",
+ "assign-admin-role_description": "Berechtigung, Administratorrolle zuzuordnen",
"Assign_admin": "Admin zuweisen",
"at": "am",
+ "AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Datei hochgeladen",
+ "Attribute_handling": "Behandlung von Eigenschaften",
+ "Audio_message": "Audio-Nachricht",
+ "Audio_Notification_Value_Description": "Dies kann einer der Standard-Töne (beep, chelle, ding, droplet, highbell, seasons) oder jeder eigene Ton sein",
+ "Audio_Notifications_Default_Alert": "Akustische Benachrichtigung bei",
+ "Audio_Notifications_Value": "Akustische Benachrichtigung: Ton",
"Auth_Token": "Auth-Token",
"Author": "Autor",
"Authorization_URL": "Autorisierungs-URL",
"Authorize": "Berechtigen",
+ "auto-translate": "Automatische Übersetzung",
+ "auto-translate_description": "Berechtigung, die automatische Überstzung zu verwenden",
"Auto_Load_Images": "Automatisches Laden der Bilder",
- "AutoLinker_Email": "AutoLinker E-Mail",
- "AutoLinker_Phone": "AutoLinker Telefonnummern",
+ "Auto_Translate": "Automatische Übersetzung",
+ "AutoLinker_Email": "AutoLinker für E-Mail-Adressen",
+ "AutoLinker_Phone": "AutoLinker für Telefonnummern",
"AutoLinker_Phone_Description": "Telefonnummern automatisch verlinken. z.B. `(123) 456-7890`",
- "AutoLinker_StripPrefix": "AutoLinker-Strip-Prefix",
+ "AutoLinker_StripPrefix": "AutoLinker Präfix entfernen",
"AutoLinker_StripPrefix_Description": "Kurze Anzeige. z.B. https://rocket.chat => rocket.chat",
- "AutoLinker_Urls_Scheme": "Schema des AutoLinker: // URLs",
+ "AutoLinker_Urls_Scheme": "Schema des AutoLinkers: // URLs",
"AutoLinker_Urls_TLD": "AutoLinker TLD-URLs",
"AutoLinker_Urls_www": "AutoLinker \"www\"-URLs",
"AutoLinker_UrlsRegExp": "AutoLinker RegExp für URLs",
+ "Automatic_Translation": "Automatische Übersetzung",
+ "AutoTranslate_Change_Language_Description": "Das Verändern der Option zur automatischen Übersetzung übersetzt keine Nachrichten aus der Vergangenheit.",
+ "AutoTranslate_Enabled": "Automatische Übersetzung",
+ "AutoTranslate_Enabled_Description": "Die Aktivierung der automatischen Übersetzung ermöglicht es Benutzern mit der entsprechenden Berechtigung (auto-translate, Nachrichten immer in Ihrer Sprache übersetzt zu lesen. Hierfür fallen potentiell Gebühren an (s. Google-Dokumentation .",
+ "AutoTranslate_GoogleAPIKey": "Google API-Schlüssel",
"Available": "Verfügbar",
"Available_agents": "Verfügbare Agenten",
"Avatar": "Profilbild",
"Avatar_changed_successfully": "Das Profilbild wurde erfolgreich geändert.",
"Avatar_URL": "URL des Profilbilds",
- "Avatar_url_invalid_or_error": "Die angegebene Internetadresse ist ungültig oder nicht verfügbar. Bitte versuchen Sie es mit einer anderen Internetadresse erneut.",
+ "Avatar_url_invalid_or_error": "Die angegebene Internetadresse ist ungültig oder nicht verfügbar. Bitte versuche es mit einer anderen Internetadresse erneut.",
"away": "abwesend",
"Away": "Abwesend",
"away_female": "abwesend",
@@ -205,66 +287,117 @@
"Away_male": "Abwesend",
"Back": "Zurück",
"Back_to_applications": "Zurück zu den Anwendungen",
- "Back_to_integrations": "Zurück zu Integrationen",
+ "Back_to_chat": "Zurück zum Chat",
+ "Back_to_integration_detail": "Zurück zu den Integrations-Details",
+ "Back_to_integrations": "Zurück zu den Integrationen",
"Back_to_login": "Zurück zum Login",
"Back_to_permissions": "Zurück zu den Berechtigungen",
- "Body": "Body",
+ "Backup_codes": "Backup-Schlüssel",
+ "ban-user": "Benutzer verbannen",
+ "ban-user_description": "Berechtigung, einen Benutzer aus einem Kanal zu verbannen",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta-Funktion: Basiert darauf, dass Video-Konferenzen aktiviert sind.",
+ "Block_User": "BenutzerIn sperren",
+ "Body": "Textkörper",
"bold": "fett",
- "bot_request": "Bot Anfrage",
+ "bot_request": "Bot-Anfrage",
"BotHelpers_userFields": "Benutzerfelder",
- "BotHelpers_userFields_Description": "CSV Datei mit Benutzerfeldern die von Bot-Methoden genutzt werden dürfen",
- "Branch": "Branch",
+ "BotHelpers_userFields_Description": "CSV-Datei mit Benutzerfeldern die von Bot-Methoden genutzt werden dürfen.",
+ "Branch": "Zweig",
+ "Broadcast_Connected_Instances": "Broadcast an verbundene Instanzen",
+ "Bugsnag_api_key": "Bugsnag API-Schlüssel",
+ "bulk-create-c": "Massen-Anlage von Kanälen",
+ "bulk-create-c_description": "Berechtigung zur Massen-Anlage von Kanälen",
+ "bulk-register-user": "Massen-Registrierung von Benutzern",
+ "bulk-register-user_description": "Berechtigung zur Massen-Registrierung von Benutzern",
"busy": "beschäftigt",
"Busy": "Beschäftigt",
"busy_female": "beschäftigt",
"Busy_female": "Beschäftigt",
"busy_male": "beschäftigt",
"Busy_male": "Beschäftigt",
- "by": "durch",
+ "by": "von",
+ "cache_cleared": "Zwischenspeicher gelöscht",
"Cancel": "Abbrechen",
"Cancel_message_input": "Abbrechen",
"Cannot_invite_users_to_direct_rooms": "Benutzer können nicht in private Nachrichtenräume eingeladen werden.",
+ "Cannot_open_conversation_with_yourself": "Ein Selbstgespräch kann nicht gestartet werden",
+ "CAS_autoclose": "Login-Popup automatisch schließen",
+ "CAS_base_url": "SSO-Base-URL",
+ "CAS_base_url_Description": "Basis-URL des externen Singe Sign On Services e.g: https://sso.example.undef/sso/",
"CAS_button_color": "Hintergrundfarbe des Login-Buttons",
"CAS_button_label_color": "Farbe des Login-Button-Texts",
"CAS_button_label_text": "Text des Login-Buttons",
+ "CAS_enabled": "Aktiviert",
+ "CAS_Login_Layout": "CAS-Login-Layout",
+ "CAS_login_url": "SSO-Login-URL",
+ "CAS_login_url_Description": "Login URL des externen Single-Sign-On Services, bspw. https://sso.example.undef/sso/login",
+ "CAS_popup_height": "Höhe des Login-Popups",
+ "CAS_popup_width": "Breite des Login-Popups",
+ "CAS_Sync_User_Data_Enabled": "Benutzerdaten immer synchronisieren",
+ "CAS_Sync_User_Data_Enabled_Description": "Beim Login immer CAS-Benutzerdaten in die entsprechenden Attribute synchronisieren. Hinweis: Attribute werden beim Anlegen des Kontos in jedem Fall synchronisiert.",
+ "CAS_Sync_User_Data_FieldMap": "Attribut-Map",
+ "CAS_Sync_User_Data_FieldMap_Description": "Verwenden Sie dieses JSON um interne Attribut (key) aus externen Attributen (value) zu erstellen. Externe Attribut-Namen, die mit '%' umschlossen sind, werden in value-Strings interpoliert. Beispiel: `{\\\"email\\\"\\\"%email%\\\", \\\"name\\\"\\\"%firstname%, %lastname%\\\"}` Die Attribut-Map wird immer interpoliert. In CAS 1.0 ist nur das `username`-Attribut verfügbar. Mögliche interne Attribute sind username, name, email, rooms; rooms ist eine Komma-separierte Liste von Räumen, denen der Benutzer nach der Erstellung seines Kontos hinzugefügt wird. Beispielsweise würde {\\\"rooms\\\" \\\"%Team%,%Abteilung%\\\"} CAS-basierte Nutzerkonten zu den Räumen mit den Namen Team und Abteilung hinzufügen.",
+ "CAS_version": "CAS Version",
+ "CAS_version_Description": "Verwenden Sie nur eine CAS-Version, die von Ihrem CAS-SSO-Provider unterstützt wird.",
"CDN_PREFIX": "CDN-Präfix",
"Certificates_and_Keys": "Zertifikate und Schlüssel",
+ "Change_Room_Type": "Ändere den Typ des Raums",
"Changing_email": "E-Mail-Adresse ändern",
"channel": "Kanal",
"Channel": "Kanal",
"Channel_already_exist": "Der Kanal '#%s' ist bereits vorhanden.",
+ "Channel_already_exist_static": "Der Kanal existiert bereits",
"Channel_already_Unarchived": "Kanal mit dem Namen '#%s' ist bereits im unarchivierten Zustand",
"Channel_Archived": "Kanal mit dem Namen '#%s' wurde erfolgreich archiviert",
+ "Channel_created": "Kanal `#%s` wurde angelegt.",
"Channel_doesnt_exist": "Der Kanal `#%s` existiert nicht.",
+ "Channel_name": "Kanalname",
+ "Channel_Name_Placeholder": "Bitte geben Sie einen Namen für den Kanal ein",
+ "Channel_to_listen_on": "Kanal, auf dem gehört werden soll",
"Channel_Unarchived": "Kanal mit dem Namen '#%s' ist nicht länger archiviert",
"Channels": "Kanäle",
+ "Channels_are_where_your_team_communicate": "In Kanälen kommuniziert Ihr Team.",
"Channels_list": "Liste der öffentlichen Kanäle",
- "Chat_button": "Chatbutton",
+ "Chat_button": "Chat-Button",
"Chat_closed": "Chat geschlossen",
"Chat_closed_successfully": "Chat erfolgreich geschlossen",
+ "Chat_Now": "Jetzt chatten",
"Chat_window": "Chatfenster",
"Chatops_Enabled": "ChatOps aktivieren",
"Chatops_Title": "ChatOps-Panel",
"Chatops_Username": "ChatOps-Benutzername",
"Choose_a_room": "Raum auswählen",
"Choose_messages": "Nachrichten auswählen",
- "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Wählen Sie den Alias, der vor dem Benutzernamen in den Nachrichten angezeigt wird.",
- "Choose_the_username_that_this_integration_will_post_as": "Wählen Sie den Benutzernamen, der die Integration veröffentlicht.",
- "Clear_all_unreads_question": "Möchten Sie alle ungelesenen Nachrichten löschen?",
+ "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Wählen Sie einen Alias, der vor dem Benutzernamen in Nachrichten angezeigt wird.",
+ "Choose_the_username_that_this_integration_will_post_as": "Wählen Sie den Benutzernamen, unter dem die Integration Nachrichten postet.",
+ "clean-channel-history": "Kanalhistorie löschen",
+ "clean-channel-history_description": "Berechtigung, die Historie aus Kanälen zu löschen",
+ "clear": "Löschen",
+ "Clear_all_unreads_question": "Möchtest Du alle ungelesenen Nachrichten löschen?",
+ "clear_cache_now": "Zwischenspeicher jetzt leeren",
+ "clear_history": "Verlauf löschen",
"Click_here": "Hier klicken",
+ "Click_here_for_more_info": "Für weitere Informationen hier klicken",
+ "Click_to_join": "Hier klicken um teilzunehmen!",
"Client_ID": "Client-ID",
- "Client_Secret": "Client-Secret",
+ "Client_Secret": "Client-Geheimnis",
"Clients_will_refresh_in_a_few_seconds": "Clients werden in wenigen Sekunden aktualisiert",
"close": "Schließen",
"Close": "Schließen",
+ "close-livechat-room": "Livechat-Raum schließen",
+ "close-livechat-room_description": "Berechtigung, den aktuellen Livechat-Raum zu schließen",
+ "close-others-livechat-room": "Livechat-Raum schließen",
+ "close-others-livechat-room_description": "Berechtigung, andere Livechat-Räume zu schließen",
"Closed": "Geschlossen",
"Closed_by_visitor": "Durch Besucher geschlossen",
"Closing_chat": "Schließe Chat",
"Collapse_Embedded_Media_By_Default": "Eingebettete Medien standardmäßig ausblenden",
"Color": "Farbe",
"Commands": "Befehle",
+ "Comment_to_leave_on_closing_session": "Kommentar, der beim Schließen einer Konversation hinterlassen wird",
"Compact": "Kompakt",
- "Confirm_password": "Bestätigen Sie Ihr Passwort.",
+ "Confirm_password": "Bestätige Dein Passwort",
+ "Content": "Inhalt",
"Conversation": "Gespräch",
"Conversation_closed": "Gespräch geschlossen: __comment__.",
"Convert_Ascii_Emojis": "ASCII zu Emoji konvertieren",
@@ -275,11 +408,23 @@
"Count": "Zähler",
"Cozy": "Angenehm",
"Create": "Erstellen",
- "Create_A_New_Channel": "Erstellen Sie einen neuen Kanal",
+ "create-c": "Öffentliche Kanäle anlegen",
+ "create-c_description": "Berechtigung, öffentliche Kanäle anzulegen",
+ "create-d": "Direktnachrichten anlegen",
+ "create-d_description": "Berechtigung, Direktnachrichten zu senden",
+ "create-p": "Private Kanäle anlegen",
+ "create-p_description": "Berechtigung, private Kanäle anzulegen",
+ "create-user": "Benutzer anlegen",
+ "create-user_description": "Berechtigung, Benutzer anzulegen",
+ "Create_A_New_Channel": "Kanal anlegen",
"Create_new": "Neu erstellen",
"Created_at": "Erstellt am",
"Created_at_s_by_s": "Erstellt am %s von %s ",
+ "Created_at_s_by_s_triggered_by_s": "Erstellt um %s von %s , angestoßen von %s ",
+ "CRM_Integration": "CRM-Integration",
+ "CROWD_Reject_Unauthorized": "Unauthorisierte ablehnen.",
"Current_Chats": "Aktuelle Chats",
+ "Current_Status": "Aktueller Status",
"Custom": "Benutzerdefiniert",
"Custom_Emoji": "Benutzerdefinierte Emoji",
"Custom_Emoji_Add": "Neuen Emoji hinzufügen",
@@ -289,21 +434,45 @@
"Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "Der benutzerdefinierte Emoji oder einer seiner Aliase wird bereits verwendet.",
"Custom_Emoji_Has_Been_Deleted": "Der benutzerdefinierte Emoji wurde gelöscht.",
"Custom_Emoji_Info": "Benutzerdefinierter-Emoji-Info",
- "Custom_Emoji_Updated_Successfully": "Benutzerdefinierter Emoji erfolgreich geupdatet.",
+ "Custom_Emoji_Updated_Successfully": "Benutzerdefinierter Emoji erfolgreich aktualisiert",
"Custom_Fields": "Benutzerdefinierte Felder",
- "Custom_oauth_helper": "Bei der Einrichtung muss eine Rückruf-URL angegeben werden. Benutze dafür folgende URL: %s ",
+ "Custom_oauth_helper": "Bei der Einrichtung Ihres OAuth-Providers muss eine Rückruf-URL angegeben werden. Benutzen Sie dafür folgende URL: %s ",
"Custom_oauth_unique_name": "Name des OAuth-Kontos",
- "Custom_Script_Logged_In": "Benutzerdefiniertes Script für angemeldete Benutzer",
- "Custom_Script_Logged_Out": "Benutzerdefiniertes Script für abgemeldete Benutzer",
+ "Custom_Script_Logged_In": "Benutzerdefiniertes Skript für angemeldete Benutzer",
+ "Custom_Script_Logged_Out": "Benutzerdefiniertes Skript für abgemeldete Benutzer",
+ "Custom_Scripts": "Benutzerdefinierte Skripte",
+ "Custom_Sound_Add": "Benutzerdefinierte Töne hinzufügen",
+ "Custom_Sound_Delete_Warning": "Ein gelöschter Ton kann nicht wiederhergestellt werden.",
+ "Custom_Sound_Error_Invalid_Sound": "Fehlerhafter Ton",
+ "Custom_Sound_Error_Name_Already_In_Use": "Der Name für den eigenen Ton wird schon verwendet.",
+ "Custom_Sound_Has_Been_Deleted": "Der eigene Ton wurde gelöscht.",
+ "Custom_Sound_Info": "Info zu eigenen Tönen",
+ "Custom_Sound_Saved_Successfully": "Der eigene Ton wurde erfolgreich gespeichert",
+ "Custom_Sounds": "Benutzerdefinierte Töne",
"Custom_Translations": "Benutzerdefinierte Übersetzungen",
+ "Custom_Translations_Description": "Ein gültiges JSON, in dem die Schlüssel Sprachkürzel sind, die wiederum Tupel von Schlüssel und Übersetzungen enthalten. Beispiel: {\\n \\\"en\\\" {\\n \\\"Channels\\\" \\\"Rooms\\\"\\n },\\n \\\"de\\\" {\\n \\\"Channels\\\" \\\"Räume\\\"\\n }\\n}",
+ "CustomSoundsFilesystem": "Dateisystem für benutzerdefinierte Töne",
"Dashboard": "Dashboard",
"Date": "Datum",
+ "Date_From": "Von",
+ "Date_to": "bis",
"days": "Tage",
"DB_Migration": "Datenbankmigration",
"DB_Migration_Date": "Datenbankmigrationsdatum",
"Deactivate": "Deaktivieren",
+ "Decline": "ablehnen",
"Default": "Voreinstellung",
"Delete": "Löschen",
+ "delete-c": "Öffentliche Kanäle löschen",
+ "delete-c_description": "Berechtigung, öffentliche Kanäle zu löschen",
+ "delete-d": "Direktnachrichten löschen",
+ "delete-d_description": "Berechtigung, Direktnachrichten zu löschen",
+ "delete-message": "Nachricht löschen",
+ "delete-message_description": "Berechtigung, eine Nachricht in einem Raum zu löschen",
+ "delete-p": "Private Kanäle löschen",
+ "delete-p_description": "Berechtigung, private Kanäle zu löschen",
+ "delete-user": "Benutzer löschen",
+ "delete-user_description": "Berechtigung, einen Benutzer zu löschen",
"Delete_message": "Nachricht löschen",
"Delete_my_account": "Mein Konto löschen",
"Delete_Room_Warning": "Beim Löschen eines Raums werden alle Nachrichten in diesem Raum unwiderruflich gelöscht.",
@@ -317,103 +486,154 @@
"Desktop": "Desktop",
"Desktop_Notification_Test": "Desktop-Benachrichtigungstest",
"Desktop_Notifications": "Desktop-Benachrichtigungen",
- "Desktop_Notifications_Disabled": "Desktop-Benachrichtigungen sind deaktiviert. Ändern Sie Ihre Browsereinstellungen, wenn Sie Benachrichtigungen erhalten wollen.",
+ "Desktop_Notifications_Default_Alert": "Desktop-Benachrichtigungen bei",
+ "Desktop_Notifications_Disabled": "Desktop-Benachrichtigungen sind deaktiviert. Ändere Deine Browsereinstellungen, wenn Du Benachrichtigungen erhalten möchtest.",
"Desktop_Notifications_Duration": "Desktop-Benachrichtigungsdauer",
- "Desktop_Notifications_Duration_Description": "Zeit in Sekunden für die Desktop-Benachrichtigungen angezeigt werden sollen. Dies kann OS X Notification Center beeinflussen. Geben Sie 0 ein, um die Standard-Browser-Einstellungen zu verwenden und OS X Notification Center nicht zu beeinflussen.",
+ "Desktop_Notifications_Duration_Description": "Die Anzeigedauer die Desktop-Benachrichtigungen in Sekunden. Dies kann das OS X Notification Center beeinflussen. Gibe 0 ein, um die Standard-Browser-Einstellungen zu verwenden und auch das OS X Notification Center nicht zu beeinflussen.",
"Desktop_Notifications_Enabled": "Desktop-Benachrichtigungen sind aktiviert.",
+ "Different_Style_For_User_Mentions": "Anderer Stil für Benutzer-Erwähnungen",
"Direct_message_someone": "Jemandem eine private Nachricht schicken",
"Direct_Messages": "Private Nachrichten",
- "Display_offline_form": "Offline Nachricht anzeigen",
- "Displays_action_text": "Zeigt Aktionstext",
- "Do_you_want_to_change_to_s_question": "Möchten Sie dies zu %s ändern?",
+ "Direct_Reply": "Direktantwort",
+ "Direct_Reply_Debug": "Direktantwort debuggen",
+ "Direct_Reply_Debug_Description": "[Achtung!] Das Aktivieren des Debug-Modus führt dazu, dass Ihr Passwort im Klartext in der Administrationskonsole erscheint.",
+ "Direct_Reply_Delete": "Abgefangene E-Mails löschen",
+ "Direct_Reply_Enable": "Direktantwort aktivieren",
+ "Direct_Reply_Frequency": "Frequenz, in der E-Mails überprüft werden",
+ "Direct_Reply_Frequency_Description": "(in Minuten, Standard/Minimum 2)",
+ "Direct_Reply_Host": "Host für Direktantworten",
+ "Direct_Reply_IgnoreTLS": "TLS ignorieren",
+ "Direct_Reply_Password": "Passwort",
+ "Direct_Reply_Port": "Port für Direktantworten",
+ "Direct_Reply_Protocol": "Protokoll für Direktantworten",
+ "Direct_Reply_Separator": "Trennzeichen",
+ "Direct_Reply_Separator_Description": "[Nur verändern, wenn Sie wirklich sicher sind, was Sie tun (s. Dokumentation)] Separator zwischen Base- und Tag-Teil der E-Mail",
+ "Direct_Reply_Username": "Benutzername",
+ "Direct_Reply_Username_Description": "Bitte verwenden Sie eine absolute E-Mail-Adresse. Tagging ist nicht erlaubt und würde überschrieben.",
+ "Disable_Notifications": "Benachrichtigungen deaktivieren",
+ "Disable_two-factor_authentication": "Zwei-Faktor-Authentifizierung deaktivieren",
+ "Display_offline_form": "Formular für Offline-Kontakt anzeigen",
+ "Displays_action_text": "Zeigt den Aktionstext",
+ "Do_you_want_to_change_to_s_question": "Möchtest Du dies zu %s ändern?",
"Domain": "Domain",
+ "Domain_added": "Domäne hinzugefügt",
+ "Domain_removed": "Domäne entfernt",
"Domains": "Domains",
+ "Domains_allowed_to_embed_the_livechat_widget": "Komma-separierte Liste der Domänen, in denen das Livechat-Widget eingebettet werden darf. Leer lassen, um keine Einschränkung vorzunehmen.",
+ "Download_Snippet": "Download",
"Drop_to_upload_file": "Ablegen, um Datei hochzuladen",
"Dry_run": "Probelauf",
- "Dry_run_description": "Es wird nur eine E-Mail an die selbe Adresse wie im Feld Absender geschickt. Die E-Mailadresse muss einem gültigen Benutzer gehören.",
+ "Dry_run_description": "Es wird nur eine E-Mail an die Adresse aus dem Feld \"Absender\" geschickt. Die E-Mail-Adresse muss zu einem gültigen Benutzer gehören.",
"Duplicate_archived_channel_name": "Ein archivierter Kanal mit dem Namen '%s' existiert bereits.",
- "Duplicate_archived_private_group_name": "Eine archivierte private Gruppe mit dem Namen '%s' existiert bereits.",
+ "Duplicate_archived_private_group_name": "Ein archivierter privater Kanal mit dem Namen '%s' existiert bereits.",
"Duplicate_channel_name": "Ein Kanal mit dem Namen '%s' existiert bereits",
- "Duplicate_private_group_name": "Eine private Gruppe mit dem Namen '%s' existiert bereits.",
+ "Duplicate_private_group_name": "Ein privater Kanal mit dem Namen '%s' existiert bereits.",
"Duration": "Dauer",
"Edit": "Bearbeiten",
+ "edit-message": "Nachricht bearbeiten",
+ "edit-message_description": "Berechtigung, eine Nachricht in einem Raum zu bearbeiten",
+ "edit-other-user-active-status": "Online-Status anderer Benutzer ändern",
+ "edit-other-user-active-status_description": "Berechtigung, den Online-Status anderer Benutzer zu ändern",
+ "edit-other-user-info": "Benutzer-Informationen Anderer ändern",
+ "edit-other-user-info_description": "Berechtigung, Benutzer-Informationen (Namen, Benutzernamen, E-Mail-Adresse) anderer Personen zu ändern",
+ "edit-other-user-password": "Passwort anderer Benutzer ändern",
+ "edit-other-user-password_description": "Berechtigung, das Passwort anderer Benutzer zu ändern. Dies erfordert die Berechtigung, die Benutzer-Informationen Anderer zu ändern.",
+ "edit-privileged-setting": "Besonders geschützte Einstellungen ändern",
+ "edit-privileged-setting_description": "Berechtigung, besonders geschützte Einstellungen zu ändern",
+ "edit-room": "Raum bearbeiten",
+ "edit-room_description": "Berechtigung, einen Raum zu bearbeiten (Name, Thema, Sichtbarkeit, Archivierung)",
"Edit_Custom_Field": "Benutzerdefinierte Felder bearbeiten",
"Edit_Department": "Abteilung bearbeiten",
+ "Edit_previous_message": "`%s` - Bearbeite vorherige Nachricht",
+ "Edit_Trigger": "Trigger bearbeiten",
"edited": "bearbeitet",
"Editing_room": "Raum bearbeiten",
- "Editing_user": "Benutzer bearbeiten",
+ "Editing_user": "BenutzerIn bearbeiten",
"Email": "E-Mail",
"Email_address_to_send_offline_messages": "E-Mail-Adresse zum Senden von Offline-Nachrichten",
"Email_already_exists": "Die E-Mail-Adresse existiert bereits.",
- "Email_body": "Nachricht",
+ "Email_body": "E-Mail Textkörper",
"Email_Change_Disabled": "Der Rocket.Chat-Administrator hat das Ändern der E-Mail-Adresse deaktiviert.",
- "Email_Footer_Description": "Sie können die folgenden Platzhalter verwenden: [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
+ "Email_Footer_Description": "Sie können die folgenden Platzhalter verwenden: [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
"Email_from": "Absender",
- "Email_Header_Description": "Sie können die folgenden Platzhalter verwenden: [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
+ "Email_Header_Description": "Sie können die folgenden Platzhalter verwenden: [Site_Name] und [Site_URL] für den Anwendungsname und die URL. ",
"Email_Notification_Mode": "Offline-E-Mail-Benachrichtigungen",
"Email_Notification_Mode_All": "Jede Erwähnung/DM",
"Email_Notification_Mode_Disabled": "deaktiviert",
"Email_or_username": "E-Mail-Adresse oder Nutzername",
+ "Email_Placeholder": "Bitte geben Sie Ihre E-Mail-Adresse ein",
"Email_subject": "Betreff",
"Email_verified": "Die E-Mail-Adresse wurde bestätigt.",
"Emoji": "Emoji",
- "Empty_title": "Es wurde kein Titel angegeben.",
+ "EmojiCustomFilesystem": "Dateisystem für eigene Emojis",
+ "Empty_title": "Leerer Titel",
"Enable": "Aktivieren",
- "Enable_Desktop_Notifications": "Aktivieren",
+ "Enable_Desktop_Notifications": "Desktop-Benachrichtigungen",
+ "Enable_Svg_Favicon": "SVG Favicon",
+ "Enable_two-factor_authentication": "Zwei-Faktor-Authentifizierung aktivieren",
"Enabled": "Aktiviert",
"Encrypted_message": "Verschlüsselte Nachricht",
"End_OTR": "OTR beenden",
- "Enter_a_regex": "Regex eingeben",
+ "Enter_a_regex": "Regulären Ausdruck eingeben",
"Enter_a_room_name": "Raumnamen eingeben",
"Enter_a_username": "Benutzernamen eingeben",
+ "Enter_Alternative": "Alternativer Modus (Senden mit Eingabetaste + Strg/Alt/Shift/Command)",
+ "Enter_authentication_code": "Dateisystem für eigene Emojis",
+ "Enter_Behaviour": "Verhalten der Eingabetaste:",
+ "Enter_Behaviour_Description": "Das verändert, ob die Eingabetaste eine Nachricht versendet oder einen Zeilenumbruch erzeugt",
"Enter_name_here": "Namen hier eingeben",
- "Enter_to": "Enter-Taste: ",
+ "Enter_Normal": "Normaler Modus (mit Eingabetaste senden)",
+ "Enter_to": "Eingabetaste: ",
"Error": "Fehler",
"error-action-not-allowed": "__action__ ist nicht erlaubt",
"error-application-not-found": "Anwendung nicht gefunden",
- "error-archived-duplicate-name": "Es gibt einen archivierten Kanal mit dem Namen '__room_name__'",
+ "error-archived-duplicate-name": "Es gibt bereits einen archivierten Kanal mit dem Namen '__room_name__'",
"error-avatar-invalid-url": "Ungültige Avatar-URL: __url__",
- "error-avatar-url-handling": "Fehler beim Bearbeiten der Avatar-Einstellung von einer URL (__url__) für __username__",
+ "error-avatar-url-handling": "Fehler beim Übernehmen des Avatars- von URL (__url__) für __username__",
"error-cant-invite-for-direct-room": "Nutzer können nicht in private Nachrichtenräume eingeladen werden.",
"error-could-not-change-email": "Konnte E-Mail-Adresse nicht ändern",
"error-could-not-change-name": "Konnte den Namen nicht ändern",
"error-could-not-change-username": "Konnte den Benutzernamen nicht ändern",
"error-delete-protected-role": "Eine geschützte Rolle kann nicht gelöscht werden.",
"error-department-not-found": "Abteilung konnte nicht gefunden werden.",
+ "error-direct-message-file-upload-not-allowed": "Dateiaustausch ist in direkten Nachrichten nicht möglich.",
"error-duplicate-channel-name": "Ein Kanal mit dem Namen '__channel_name__' existiert bereits.",
- "error-email-domain-blacklisted": "Die Domain der E-Mail-Adresse ist auf der Schwarzen Liste.",
+ "error-email-domain-blacklisted": "Die Domain der E-Mail-Adresse ist auf der schwarzen Liste.",
+ "error-email-send-failed": "Fehler beim Versuch, eine Email zu versenden: __message__",
"error-field-unavailable": "__field__ wird leider schon verwendet. ",
"error-file-too-large": "Die Datei ist zu groß",
- "error-importer-not-defined": "Der Importer wurde nicht richtig definiert, eine Importklasse fehlt.",
+ "error-importer-not-defined": "Der Importer wurde nicht richtig definiert, die Importklasse fehlt.",
"error-input-is-not-a-valid-field": "__input__ ist kein gültiges __field__",
"error-invalid-actionlink": "Ungültiger Aktionslink",
"error-invalid-arguments": "Ungültige Argumente",
- "error-invalid-asset": "Ungültiger Wert",
+ "error-invalid-asset": "Ungültiges Asset",
"error-invalid-channel": "Ungültiger Kanal.",
- "error-invalid-channel-start-with-chars": "Ungültiger Kanal. Beginnen Sie mit @ oder #",
+ "error-invalid-channel-start-with-chars": "Ungültiger Kanal. Beginne mit @ oder #",
"error-invalid-custom-field": "Ungültiges benutzerdefiniertes Feld",
- "error-invalid-custom-field-name": "Unzulässiger Name für ein benutzerdefiniertes Feld. Benutze nur Buchstaben, Nummern, Binde- und Unterstriche.",
+ "error-invalid-custom-field-name": "Unzulässiger Name für ein benutzerdefiniertes Feld. Benutzen Sie nur Buchstaben, Nummern, Binde- und Unterstriche.",
+ "error-invalid-date": "Das eingegebene Datum ist ungültig.",
"error-invalid-description": "Ungültige Beschreibung",
"error-invalid-domain": "Ungültige Domain",
"error-invalid-email": "Ungültige E-Mail-Adresse: __email__",
- "error-invalid-file-height": "Ungültige Dateihöhe",
+ "error-invalid-email-address": "Ungültige E-Mail-Adresse",
+ "error-invalid-file-height": "Ungültige Bildhöhe der Datei",
"error-invalid-file-type": "Ungültiges Dateiformat",
- "error-invalid-file-width": "Ungültige Dateibreite",
- "error-invalid-from-address": "Sie haben eine ungültige E-Mail-Adresse als Empfänger angegeben.",
+ "error-invalid-file-width": "Ungültige Bildhöhe der Datei",
+ "error-invalid-from-address": "Du hast eine ungültige E-Mail-Adresse als Empfänger angegeben.",
"error-invalid-integration": "Ungültige Integration",
"error-invalid-message": "Ungültige Nachricht",
"error-invalid-method": "Ungültige Methode",
"error-invalid-name": "Ungültiger Name",
"error-invalid-password": "Falsches Passwort",
- "error-invalid-redirectUri": "Ungültige redirectUri",
+ "error-invalid-redirectUri": "Ungültige Redirect-URI",
"error-invalid-role": "Ungültige Rolle",
"error-invalid-room": "Ungültiger Raum",
- "error-invalid-room-name": "%s ist kein zulässiger Raumname. Verwenden Sie nur Buchstaben, Zahlen oder Binde- und Unterstriche.",
+ "error-invalid-room-name": "%s ist kein zulässiger Raumname",
"error-invalid-room-type": "__type__ ist kein gültiger Raumtyp.",
"error-invalid-settings": "Ungültige Einstellungen übergeben",
"error-invalid-subscription": "Ungültiges Abonnement",
"error-invalid-token": "Ungültiger Token",
- "error-invalid-triggerWords": "Ungültige triggerWords",
+ "error-invalid-triggerWords": "Ungültiges Trigger-Wort",
"error-invalid-urls": "Ungültige URLs",
"error-invalid-user": "Ungültiger Benutzer",
"error-invalid-username": "Ungültiger Benutzername",
@@ -421,8 +641,8 @@
"error-message-deleting-blocked": "Nachrichten löschen ist gesperrt",
"error-message-editing-blocked": "Nachrichten bearbeiten ist gesperrt",
"error-message-size-exceeded": "Nachrichtengröße überschreitet Message_MaxAllowedSize",
- "error-missing-unsubscribe-link": "Sie müssen einen Link zum Abmelden vom Verteiler angeben.",
- "error-no-tokens-for-this-user": "Es liegen keine Token für diesen Benutzer vor.",
+ "error-missing-unsubscribe-link": "Du musst einen Link zum Abmelden vom Verteiler angeben.",
+ "error-no-tokens-for-this-user": "Es liegen keine Tokens für diesen Benutzer vor",
"error-not-allowed": "Nicht erlaubt",
"error-not-authorized": "Nicht berechtigt",
"error-push-disabled": "Push-Benachrichtigungen sind deaktiviert",
@@ -430,84 +650,140 @@
"error-role-in-use": "Die Rolle kann nicht gelöscht werden, da sie gerade verwendet wird.",
"error-role-name-required": "Ein Rollenname muss angegeben werden",
"error-the-field-is-required": "Das Feld __field__ ist erforderlich.",
- "error-too-many-requests": "Fehler, zu viele Anfragen. Bitte fahren Sie langsamer fort. Sie müssen __seconds__ Sekunden warten bevor Sie es erneut versuchen können.",
+ "error-too-many-requests": "Fehler, zu viele Anfragen. Bitte fahren Sie langsamer fort. Sie müssen __seconds__ Sekunden warten, bevor Sie es erneut versuchen können.",
"error-user-is-not-activated": "Der Benutzer ist nicht aktiviert.",
+ "error-user-limit-exceeded": "Die Anzahl der Benutzer, die Sie hinzufügen wollen, übersteigt das vom Administrator gesetzte Limit.",
"error-user-not-in-room": "Der Benutzer ist nicht in diesem Raum.",
"error-user-registration-disabled": "Benutzerregistrierung ist deaktiviert",
"error-user-registration-secret": "Benutzerregistrierung ist nur über geheime URL erlaubt",
- "error-you-are-last-owner": "Sie sind der letzte Besitzer. Bitte bestimmen Sie einen neuen Besitzer, bevor Sie den Raum verlassen.",
+ "error-you-are-last-owner": "Du bist der letzte Besitzer. Bitte bestimme einen neuen Besitzer, bevor Du den Raum verlässt.",
"Error_changing_password": "Fehler beim Ändern des Passwortes",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Fehler: Rocket.Chat erfordert Oplog-Tailing, wenn es auf mehreren Instanzen läuft",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Bitte stellen Sie sicher, dass die MongoDB als Replicaset konfiguriert ist und die Umgebungsvariable MONGO_OPLOG_URL korrekt auf Ihren Anwendungsservern gesetzt wurde.",
"Esc_to": "Esc: ",
+ "Event_Trigger": "Event Trigger",
+ "Event_Trigger_Description": "Bitte wählen Sie aus, welche Eventarten diesen ausgehenden Webhook auslösen",
"every_30_minutes": "alle 30 Minuten",
"every_hour": "stündlich",
"every_six_hours": "alle 6 Stunden",
+ "Everyone_can_access_this_channel": "Jeder kann auf diesen Kanal zugreifen",
"Example_s": "Beispiel: %s",
"Exclude_Botnames": "Bots ausschließen",
- "Exclude_Botnames_Description": "Keine Nachrichten von Bots verbreiten, welche dem RegEx oben entsprechen. Wenn Feld leer bleibt, werden alle Nachrichten verbreitet.",
+ "Exclude_Botnames_Description": "Keine Nachrichten von Bots verbreiten, deren Name dem oben genannten regulären Ausdruck entsprechen. Wenn das Feld leer bleibt, werden alle Nachrichten verbreitet.",
"False": "Nein",
- "Favorite_Rooms": "Favorisierte Räume aktivieren",
+ "Favorite_Rooms": "Favoriten-Räume aktivieren",
"Favorites": "Favoriten",
- "Features_Enabled": "Funktionen aktiviert",
+ "Features_Enabled": "Aktivierte Funktionen",
"Field": "Feld",
"Field_removed": "Feld entfernt",
"Field_required": "Feld erforderlich",
"File_exceeds_allowed_size_of_bytes": "Die Datei ist größer als das erlaubte Maximum von __size__ Bytes",
- "File_type_is_not_accepted": "Feldtyp nicht akzeptiert.",
+ "File_not_allowed_direct_messages": "Dateiaustausch ist in direkten Nachrichten nicht möglich.",
+ "File_type_is_not_accepted": "Dateityp wir nicht akzeptiert.",
+ "File_uploaded": "Datei hochgeladen",
"FileUpload": "Dateien hochladen",
+ "FileUpload_Disabled": "Datei Uploads ",
"FileUpload_Enabled": "Hochladen von Dateien aktivieren",
+ "FileUpload_Enabled_Direct": "Dateiaustausch ist in direkten Nachrichten möglich.",
"FileUpload_File_Empty": "Datei ist leer",
"FileUpload_FileSystemPath": "Systempfad",
+ "FileUpload_GoogleStorage_AccessId": "Google Storage Zugriffsschlüssel",
+ "FileUpload_GoogleStorage_AccessId_Description": "Der Zugriffsschlüssel liegt üblicherweise in Form einer E-Mail-Adresse vor, z. B. \"example-test@example.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Google Storage Bucket Name",
+ "FileUpload_GoogleStorage_Bucket_Description": "Der Name des Buckets, in welchen die Dateien hochgeladen werden sollen",
+ "FileUpload_GoogleStorage_Secret": "Google Storage Secret",
+ "FileUpload_GoogleStorage_Secret_Description": "Bitte folgen Sie diesen Anweisungen und fügen Sie das Ergebnis hier ein.",
"FileUpload_MaxFileSize": "Max. Größe für hochgeladene Dateien (in Bytes)",
- "FileUpload_MediaType_NotAccepted": "Medientypen werden nicht akzeptiert",
+ "FileUpload_MediaType_NotAccepted": "Medientyp wird nicht akzeptiert",
"FileUpload_MediaTypeWhiteList": "Erlaubte Medientypen",
- "FileUpload_MediaTypeWhiteListDescription": "Durch Kommata getrennte Liste von Medientypen. Um alle Medientypen zuzulassen, lassen Sie die Liste leer.",
+ "FileUpload_MediaTypeWhiteListDescription": "Kommaseparierte Liste von Medientypen. Um alle Medientypen zuzulassen, lassen Sie die Liste leer.",
"FileUpload_ProtectFiles": "Hochgeladene Dateien schützen",
- "FileUpload_ProtectFilesDescription": "Nur bestätigte Benutzer dürfen Dateien hochladen.",
- "FileUpload_S3_Acl": "Amazon S3 acI",
+ "FileUpload_ProtectFilesDescription": "Nur authentifizierte Benutzer dürfen Dateien hochladen.",
+ "FileUpload_S3_Acl": "Amazon S3 ACL",
"FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWS-Access-Key-ID",
"FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWS-Secret-Access-Key",
- "FileUpload_S3_Bucket": "Amazon S3 Bucketname",
+ "FileUpload_S3_Bucket": "Amazon S3 Bucket-Name",
"FileUpload_S3_BucketURL": "Bucket-URL",
"FileUpload_S3_CDN": "CDN-Domain für Downloads",
+ "FileUpload_S3_ForcePathStyle": "Pfad-Stil forcieren",
"FileUpload_S3_Region": "Region",
- "FileUpload_S3_URLExpiryTimeSpan": "Ablaufdatum für URLs",
- "FileUpload_S3_URLExpiryTimeSpan_Description": "Zeit nachdem Amazon S3 generierte URLs als nicht mehr gültig gelten. Wenn kleiner als fünf Sekunden, wird das Feld ignoriert.",
- "FileUpload_Storage_Type": "Speichertyp",
+ "FileUpload_S3_SignatureVersion": "Signaturversion",
+ "FileUpload_S3_URLExpiryTimeSpan": "Verfallsdatum für URLs",
+ "FileUpload_S3_URLExpiryTimeSpan_Description": "Zeit, nach der Amazon S3 generierte URLs als nicht mehr gültig gelten. Wird ignoriert, wenn weniger als fünf Sekunden konfiguriert wurde",
+ "FileUpload_Storage_Type": "Speicherort",
+ "First_Channel_After_Login": "Erster Kanal nach dem Login",
"Flags": "Flaggen",
- "Follow_social_profiles": "Folge uns in sozialen Netzwerken, fork uns auf GitHub und teile deine Gedanken über die Rocket.Chat-App auf unserem Trello-Board.",
+ "Follow_social_profiles": "Folge uns in sozialen Netzwerken, forke uns auf GitHub und teile deine Meinung und Gedanken über die Rocket.Chat-App auf unserem Trello-Board.",
+ "Fonts": "Schriften",
"Food_and_Drink": "Essen & Trinken",
"Footer": "Fußzeile",
- "For_your_security_you_must_enter_your_current_password_to_continue": "Geben Sie zu Ihrer Sicherheit Ihr aktuelles Passwort ein um fortzufahren.",
+ "Footer_Direct_Reply": "Footer, wenn Direktantworten aktiviert sind",
+ "For_your_security_you_must_enter_your_current_password_to_continue": "Zu Ihrer Sicherheit wird Ihr aktuelles Passwort benötigt, bevor Sie fortfahren können",
+ "force-delete-message": "Nachricht forciert löschen",
+ "force-delete-message_description": "Berechtigung, eine Nachricht ohne weitere Prüfungen zu löschen",
+ "Force_Disable_OpLog_For_Cache": "\"Disable OpLog\" für Cache erzwingen",
+ "Force_Disable_OpLog_For_Cache_Description": "Selbst wenn OpLog vorhanden ist, wird es nicht zum Synchronisieren des Caches verwendet",
"Force_SSL": "SSL erzwingen",
- "Force_SSL_Description": "*Achtung!* _Force SSL_ solte niemals mit einem Reverse-Proxy verwendet werden. Falls Sie einen Reverse-Proxy verwenden, sollten Sie die Weiterleitung DORT einrichten. Dies Option existiert für Anwendungen wie Heroku, die keine Weiterleitungskonfigurationen für Reverse-Proxy erlauben.",
+ "Force_SSL_Description": "*Achtung!* _Force SSL_ sollte niemals mit einem Reverse-Proxy verwendet werden. Falls Sie einen Reverse-Proxy verwenden, sollten Sie die Weiterleitung dort einrichten. Dies Option existiert für Anwendungen wie Heroku, die keine Weiterleitungskonfigurationen für Reverse-Proxy erlauben.",
"Forgot_password": "Passwort vergessen?",
+ "Forgot_Password_Description": "Sie können die folgenden Platzhalter verwenden: [Forgot_Password_Url] für die Passwort-Wiederherstellungs-URL. [name], [fname], [lname] für den vollstandigen Namen, Vornamen oder Nachnamen des Benutzers [email] für die E-Mail-Adresse des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsnamen und die URL der Anwendung ",
+ "Forgot_Password_Email": "Hier Klicken um das Passwort zurückzusetzen.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Passwort-Wiederherstellung",
+ "Forgot_password_section": "Passwort vergessen",
"Forward": "Weiterleiten",
"Forward_chat": "Chat weiterleiten",
"Forward_to_department": "An Abteilung weiterleiten",
- "Forward_to_user": "An Benutzer weiterleiten",
+ "Forward_to_user": "An BenutzerIn weiterleiten",
"Frequently_Used": "Häufig verwendet",
+ "Friday": "Freitag",
"From": "Absender",
- "From_Email": "Absender",
- "From_email_warning": "Warnung : Der Absender ist Gegenstand deiner Mail-Server-Einstellungen.",
+ "From_Email": "E-Mail-Absender",
+ "From_email_warning": "Warnung : Der Absender ist wird aus den Mail-Server-Einstellungen übernommen.",
"General": "Allgemeines",
- "github_no_public_email": "Sie haben keine öffentliche E-Mail-Adresse in Ihrem GitHub-Account.",
- "Give_a_unique_name_for_the_custom_oauth": "Geben Sie dem benutzerdefinierten OAuth-Konto einen eindeutigen Namen.",
- "Give_the_application_a_name_This_will_be_seen_by_your_users": "Geben Sie der Anwendung einen Namen. Die Nutzer können den Namen sehen.",
+ "github_no_public_email": "Du hast keine öffentliche E-Mail-Adresse in Deinem GitHub-Account.",
+ "Give_a_unique_name_for_the_custom_oauth": "Gib dem benutzerdefinierten OAuth-Konto einen eindeutigen Namen.",
+ "Give_the_application_a_name_This_will_be_seen_by_your_users": "Geben Sie der Anwendung einen Namen. Alle Nutzer können diesen Namen sehen.",
"Global": "Global",
+ "Google_Vision_usage_limit_exceeded": "Nutzungsbeschränkung für Google Vision erreicht",
+ "GoogleCloudStorage": "Google Cloud Speicher",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "Service-Konto SchlüsselDatei (JSON). Weiterführende Informationen dazu [hier](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "Google-Tag-Manager-ID",
- "Guest_Pool": "Gästepool",
+ "GoogleVision_Block_Adult_Images": "Nicht-jugendfreie Fotos blocken",
+ "GoogleVision_Block_Adult_Images_Description": "Das Blocken von nicht-jugendfreien Fotos wird nicht mehr funktionieren, sobald das monatliche Limit erreicht ist.",
+ "GoogleVision_Current_Month_Calls": "Aufrufe des aktuellen Monats",
+ "GoogleVision_Enable": "Google Vision",
+ "GoogleVision_Max_Monthly_Calls": "Maximale Anzahl der monatlichen Aufrufe",
+ "GoogleVision_Max_Monthly_Calls_Description": "0 für unendlich",
+ "GoogleVision_ServiceAccount": "Google Vision Service Konto",
+ "GoogleVision_ServiceAccount_Description": "Erstelle einen Server-Key (JSON Format) und kopiere den JSON-String hier hinein",
+ "GoogleVision_Type_Document": "Texterkennung für Dokumente",
+ "GoogleVision_Type_Faces": "Gesichtserkennung",
+ "GoogleVision_Type_Labels": "Erkennung von Etiketten",
+ "GoogleVision_Type_Landmarks": "Erkennung von Wahrzeichen",
+ "GoogleVision_Type_Logos": "Erkennung von Logos",
+ "GoogleVision_Type_Properties": "Erkennung von (Farb-) Eigenschaften",
+ "GoogleVision_Type_SafeSearch": "SafeSearch-Erkennung",
+ "GoogleVision_Type_Similar": "Ähnliche Bilder suchen",
+ "Group_mentions_only": "Nur Gruppen-Erwähnungen",
+ "Guest_Pool": "Gäste-Pool",
"Hash": "Hash",
"Header": "Kopfzeile",
+ "Header_and_Footer": "Kopf- und Fusszeile",
+ "Helpers": "Helfer",
+ "Hex_Color_Preview": "Farbvorschau (Hex)",
"Hidden": "Versteckt",
- "Hide_Avatars": "Avatar verstecken",
+ "Hide_Avatars": "Avatare verstecken",
"Hide_flextab": "Rechte Seitenleiste über Klick verstecken",
- "Hide_Group_Warning": "Sind sie sicher, die Gruppe\"%s\" zu verstecken?",
- "Hide_Private_Warning": "Sind sie sicher, das Gespräch mit \"%s\" zu verstecken?",
+ "Hide_Group_Warning": "Sind Sie sicher, dass Sie die Gruppe \"%s\" verstecken wollen?",
+ "Hide_Livechat_Warning": "Sind Sie sich sicher, dass Sie den Livechat mit \"%s\" ausblenden wollen?",
+ "Hide_Private_Warning": "Sind Sie sicher, dass Sie das Gespräch mit \"%s\" verstecken wollen?",
+ "Hide_roles": "Rollen nicht anzeigen",
"Hide_room": "Raum verstecken",
- "Hide_Room_Warning": "Sind sie sicher, den Raum \"%s\" zu verstecken?",
+ "Hide_Room_Warning": "Sind Sie sicher, dass Sie den Raum \"%s\" verstecken wollen?",
+ "Hide_Unread_Room_Status": "Ungelesen-Status des Raums nicht anzeigen",
"Hide_usernames": "Benutzernamen ausblenden",
"Highlights": "Hervorhebungen",
- "Highlights_How_To": "Um benachrichtigt zu werden, wenn ein Wort oder Ausdruck erwähnt wird, fügen Sie ihn hier hinzu. Sie können Wörter und Ausdrücke mit Kommata trennen. Die Wörter zur Hervorhebung beachten die Groß- und Kleinschreibung nicht.",
+ "Highlights_How_To": "Um benachrichtigt zu werden, wenn ein Wort oder Ausdruck erwähnt wird, fügen Sie ihn hier hinzu. Sie können Wörter und Ausdrücke mit Kommata trennen. Groß- und Kleinschreibung wird hierbei nicht berücksichtig.",
"Highlights_List": "Wörter hervorheben",
"History": "Chronik",
"Host": "Host",
@@ -515,19 +791,34 @@
"Hours": "Stunden",
"How_friendly_was_the_chat_agent": "Wie freundlich war der Chat-Agent?",
"How_knowledgeable_was_the_chat_agent": "Wie sachkundig war der Chat-Agent?",
+ "How_long_to_wait_after_agent_goes_offline": "Wartedauer, bevor ein Agent in den Offline-Modus übergeht",
"How_responsive_was_the_chat_agent": "Wie reaktionsschnell war der Chat-Agent?",
- "How_satisfied_were_you_with_this_chat": "Wie zufrieden waren Sie mit diesem Chat?",
- "If_you_are_sure_type_in_your_password": "Wenn Sie sich sicher sind, geben Sie ihr Passwort ein.",
+ "How_satisfied_were_you_with_this_chat": "Wie zufrieden warst Du mit diesem Chat?",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "Behandlung von offenen Konversationen, wenn ein Agent Offline geht",
+ "If_this_email_is_registered": "Wenn es sich um eine registrierte E-Mail-Adresse handelt, werden wir an diese eine Anleitung zum Zurücksetzen des Passworts senden. Sollten Sie in Kürzen keine E-Mail erhalten, kommen Sie wieder und versuchen Sie es noch einmal.",
+ "If_you_are_sure_type_in_your_password": "Wenn Sie sich sicher sind, geben Sie Ihr Passwort ein:",
"If_you_are_sure_type_in_your_username": "Wenn Sie sich sicher sind, geben Sie Ihren Benutzernamen ein:",
+ "Iframe_Integration": "Iframe-Integration",
"Iframe_Integration_receive_enable": "Empfang zulassen",
"Iframe_Integration_receive_enable_Description": "Erlaube dem übergeordneten Fenster (parent window) Befehle an Rocket.Chat zu senden.",
+ "Iframe_Integration_receive_origin": "Herkunft für Empfang",
"Iframe_Integration_receive_origin_Description": "Nur Seiten mit der angegebenen Herkunft erlauben Befehle abzusetzen. `*` für alle Seiten. Mehrere Werte können mittels `,` getrennt werden. Beispiel: `http://localhost,https://localhost`",
"Iframe_Integration_send_enable": "Senden zulassen",
"Iframe_Integration_send_enable_Description": "Sende Events an das übergeordnete Fenster (parent window)",
- "Importer_Archived": "archiviert",
+ "Iframe_Integration_send_target_origin": "URL des Ziels, an das gesendet werden soll",
+ "Iframe_Integration_send_target_origin_Description": "Herkunfts-URL (inkl. Protokoll-Präfix), an die die Befehle gesendet werden sollen (bspw. 'https://localhost', oder *, um ein Senden nicht einzuschränken",
+ "IMAP_intercepter_already_running": "IMAP intercepter läuft bereits",
+ "IMAP_intercepter_Not_running": "IMAP intercepter läuft nicht",
+ "Impersonate_user": "Benutzeridentität übernehmen",
+ "Impersonate_user_description": "Wenn aktiviert, erstellt die Integration Nachrichten mit der Identität des Benutzers der die Integration ausgelöst hat",
+ "Import": "Import",
+ "Importer_Archived": "Archiviert",
+ "Importer_CSV_Information": "Der CSV-Importer erfordert ein spezielles Format. Bitte lesen Sie die Dokumentation, wie die ZIP-Datei strukturiert sein muss:",
"Importer_done": "Die Daten wurden erfolgreich importiert!",
"Importer_finishing": "Import abgeschlossen.",
"Importer_From_Description": "Importiert Daten von __from__ nach Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Bitte beachten Sie, dass sich dieser Importer noch in der Entwicklung befindet. Bitte berichten Sie über Fehler auf GitHub: ",
+ "Importer_HipChatEnterprise_Information": "Die hoch geladene Datei muss ein nicht-verschlüsseltes tar.gz sein. Bitte lesen Sie die Dokumentation für weiterführende Informationen.",
"Importer_import_cancelled": "Der Import wurde abgebrochen.",
"Importer_import_failed": "Während des Importierens ist ein Fehler aufgetreten.",
"Importer_importing_channels": "Importiere die Kanäle.",
@@ -535,13 +826,17 @@
"Importer_importing_started": "Starte den Importer.",
"Importer_importing_users": "Importiere die Benutzer.",
"Importer_not_in_progress": "Der Importer läuft derzeit nicht.",
+ "Importer_not_setup": "Der Importer ist nich richtig konfiguriert. Er lieferte keine Daten zurück",
"Importer_Prepare_Restart_Import": "Import neu starten",
"Importer_Prepare_Start_Import": "Import starten",
- "Importer_Prepare_Uncheck_Archived_Channels": "Markierung für archivierte Kanäle entfernen",
- "Importer_Prepare_Uncheck_Deleted_Users": "Gelöschte Nutzer deaktivieren",
- "Importer_progress_error": "Fehler beim Erhalt des Verlaufs des Imports.",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Archivierte Kanäle ignorieren",
+ "Importer_Prepare_Uncheck_Deleted_Users": "Gelöschte Nutzer beim Import ignorieren",
+ "Importer_progress_error": "Konnte den Fortschritt des Imports nicht ermitteln.",
"Importer_setup_error": "Bei der Konfiguration des Importers ist ein Fehler aufgetreten.",
- "Incoming_Livechats": "Eingehende livechats",
+ "Importer_Source_File": "Auswahl der Quelldatei",
+ "Incoming_Livechats": "Eingehende Livechats",
+ "Incoming_WebHook": "Eingehender Webhook",
+ "initials_avatar": "Avatar aus Initialien",
"inline_code": "Code",
"Install_Extension": "Erweiterung installieren",
"Install_FxOs": "Rocket.Chat in deinem Firefox-Browser aktivieren",
@@ -550,62 +845,136 @@
"Install_FxOs_follow_instructions": "Bitte die Installation der App nach der Aufforderung mit \"Installieren\" bestätigen.",
"Installation": "Installation",
"Installed_at": "Installationsdatum",
- "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Anweisungen an Ihre Besucher: Füllen Sie das Formular aus, um eine Nachricht zu senden.",
+ "Instance_Record": "Datensatz",
+ "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Offline-Information für Ihre Benutzer, dass diese eine Nachricht hinterlassen können",
"Integration_added": "Die Integration wurde hinzugefügt.",
- "Integration_Incoming_WebHook": "Eingehende WebHook-Integration",
+ "Integration_Advanced_Settings": "Erweiterte Einstellungen",
+ "Integration_History_Cleared": "Integrationshistorie erfolgreich gelöscht",
+ "Integration_Incoming_WebHook": "Eingehender WebHook",
"Integration_New": "Neue Integration",
- "Integration_Outgoing_WebHook": "Ausgehende WebHook-Integration",
+ "Integration_Outgoing_WebHook": "Ausgehender Webhook",
+ "Integration_Outgoing_WebHook_History": "Historie für ausgehende Webhooks",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Daten, die an die Integration übergeben wurden",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Daten, die an die URL gesendet wurden",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Fehler Stacktrace",
+ "Integration_Outgoing_WebHook_History_Http_Response": "HTTP Response",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "HTTP Response Fehler",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Nachrichten, die vom Vorbereitungs-Schritt gesendet wurden",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Nachrichten, die vom Durchführungs-Schritt gesendet wurden",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Zeit des Fehlers oder der Beendigung",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Zeit, zu der die Integration ausgelöst wurde",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "Letzter Trigger-Schritt",
+ "Integration_Outgoing_WebHook_No_History": "Für diesen ausgehenden Webhook gibt es noch keine historischen Einträge",
+ "Integration_Retry_Count": "Anzahl der Wiederholungsversuche",
+ "Integration_Retry_Count_Description": "Wie häufig soll die Integration probiert werde, wenn der Aufruf der URL fehlschlägt?",
+ "Integration_Retry_Delay": "Verzögerung der Wiederholungsversuche",
+ "Integration_Retry_Delay_Description": "Welcher Verzögerungsalgorythmus soll verwendet werden? 10^x or 2^x or x*2",
+ "Integration_Retry_Failed_Url_Calls": "URL-Aufrufe fehlerhafter Wiederholungsversuche",
+ "Integration_Retry_Failed_Url_Calls_Description": "Soll es die Integration bei Fehlversuchen nach einer angemessen Zeit erneut versuchen?",
+ "Integration_Run_When_Message_Is_Edited": "Beim Bearbeiten ausführen",
+ "Integration_Run_When_Message_Is_Edited_Description": "Soll die Integration ausgeführt werden, wenn eine Nachricht bearbeitet wurde? Wenn diese Option deaktiviert wurde, wird sie nur für neue Nachrichten ausgeführt werden.",
"Integration_updated": "Die Integration wurde aktualisiert.\n",
+ "Integration_Word_Trigger_Placement": "Wörter können überall vorkommen",
+ "Integration_Word_Trigger_Placement_Description": "Soll das auslösende Wort irgendwo im Satz stehen können (und nicht nur am Anfang)? ",
"Integrations": "Integrationen",
+ "Integrations_for_all_channels": "Geben Sie all_public_channels für alle öffentlichen Kanäle ein , all_private_groups für alle privaten Gruppen und all_direct_messages für Direktnachrichten.",
+ "Integrations_Outgoing_Type_FileUploaded": "Hochgeladene Datei",
+ "Integrations_Outgoing_Type_RoomArchived": "Archivierter Raum",
+ "Integrations_Outgoing_Type_RoomCreated": "Erstellter Raum (öffentlich und privat)",
+ "Integrations_Outgoing_Type_RoomJoined": "Benutzer hat den Raum betreten",
+ "Integrations_Outgoing_Type_RoomLeft": "Benutzer hat den Raum verlassen",
+ "Integrations_Outgoing_Type_SendMessage": "Nachricht gesendet",
+ "Integrations_Outgoing_Type_UserCreated": "Benutzer angelegt",
"InternalHubot": "Interner Hubot",
+ "InternalHubot_PathToLoadCustomScripts": "Ordner, aus dem die Skripte geladen werden sollen",
+ "InternalHubot_reload": "Skripte erneut laden",
"InternalHubot_ScriptsToLoad": "Zu ladende Skripte",
- "InternalHubot_ScriptsToLoad_Description": "Bitte geben Sie eine durch Kommata getrennte Liste von zu ladenden Skripten von https://github.com/github/hubot-scripts/tree/master/src/scripts an.",
+ "InternalHubot_ScriptsToLoad_Description": "Bitte geben Sie eine durch Kommata getrennte Liste von zu ladenden Skripten aus Ihrem Ordner an.",
"InternalHubot_Username_Description": "Dies muss ein gültiger Benutzername eines auf dem Server registrierten Bots sein.",
"Invalid_confirm_pass": "Die Passwörter stimmen nicht überein.",
"Invalid_email": "Die eingegebene E-Mail-Adresse ist ungültig.",
"Invalid_Export_File": "Die angegebene Datei ist keine gültige %s Exportdatei.",
- "Invalid_Import_File_Type": "Ungültiges Dateiformat zum Importieren.",
+ "Invalid_Import_File_Type": "Ungültiges Import-Dateiformat .",
"Invalid_name": "Es muss ein Name angegeben werden.",
"Invalid_notification_setting_s": "Ungültige Benachrichtigungseinstellung: %s",
"Invalid_pass": "Es muss ein Passwort angegeben werden.",
- "Invalid_room_name": "%s ist kein zulässiger Raumname. Verwenden Sie nur Buchstaben, Zahlen oder Binde- und Unterstriche.",
+ "Invalid_room_name": "%s ist kein zulässiger Raumname",
"Invalid_secret_URL_message": "Die angegebene URL ist ungültig.",
+ "Invalid_setting_s": "Ungültige Einstellung: %s",
+ "Invalid_two_factor_code": "Fehlerhafter Zwei-Faktor-Code",
"invisible": "unsichtbar",
"Invisible": "Unsichtbar",
+ "Invitation": "Einladung",
"Invitation_HTML": "Einladungstext (HTML)",
- "Invitation_HTML_Default": " Sie wurden eingeladen zu [Site_Name] Besuchen Sie zu [Site_URL] und probieren Sie heute die beste verfügbare Open-Source-Chat-Lösung aus!
",
- "Invitation_HTML_Description": "Sie können die folgenden Platzhalter verwenden: [email] für den Empfänger der E-Mail. [Site_Name] und [Site_URL] jeweils für den Anwendungsnamen und die URL. ",
- "Invitation_Subject": "Einladungsbetreff",
- "Invitation_Subject_Default": "Sie wurden zu [Site_Name] eingeladen",
+ "Invitation_HTML_Default": " Du wurdest zu [Site_Name] eingeladen. Besuche [Site_URL] und probiere noch heute die beste Open-Source-Chat-Lösung aus!
",
+ "Invitation_HTML_Description": "Sie können die folgenden Platzhalter verwenden: [email] für den Empfänger der E-Mail. [Site_Name] und [Site_URL] jeweils für den Anwendungsnamen und die URL. ",
+ "Invitation_Subject": "Betreff der Einladung",
+ "Invitation_Subject_Default": "Du wurdest zu [Site_Name] eingeladen",
"Invite_user_to_join_channel": "Benutzer in diesen Kanal einladen",
- "Invite_Users": "Benutzer einladen",
+ "Invite_user_to_join_channel_all_from": "Alle Benutzer des Kanals [#channel] einladen, diesem Kanal zu folgen",
+ "Invite_user_to_join_channel_all_to": "Alle Benutzer dieses Kanals einladen, dem Kanal [#channel] zu folgen",
+ "Invite_Users": "BenutzerInnen einladen",
+ "IRC_Channel_Join": "Ausgabe des JOIN-Befehls",
+ "IRC_Channel_Leave": "Ausgabe des PART-Befehls",
+ "IRC_Channel_Users": "Ausgabe des NAMES-Befehls",
+ "IRC_Channel_Users_End": "Ende der Ausgabe des NAMES-Befehls",
+ "IRC_Description": "Internet Relay Chat (IRC) ist ein text-basiertes Gruppen-Kommunikations-Werkzeug. \nDieses Paket integriert IRC-Funktionalität in Rocket.Chat",
+ "IRC_Enabled": "Versuche, IRC in Rocket.Chat zu integrieren. Eine Änderung dieser Einstellung erfordert einen Neustart des Rocket.Chat Servers.",
+ "IRC_Hostname": "Der IRC-Host, zu dem verbunden werden soll",
+ "IRC_Login_Fail": "Ausgabe nach der fehlerhaften Verbindung zum IRC-Server",
+ "IRC_Login_Success": "Ausgabe nach der erfolgreichen Verbindung zum IRC-Server",
+ "IRC_Message_Cache_Size": "Cache-Limit für ausgehende Nachrichten",
+ "IRC_Port": "Port des IRC-Host, zu dem verbunden werden soll",
+ "IRC_Private_Message": "Ausgabe des PRIVMSG-Befehls",
+ "IRC_Quit": "Ausgabe beim Beenden einer IRC-Session",
"is_also_typing": "schreibt auch",
"is_also_typing_female": "schreibt auch",
"is_also_typing_male": "schreibt auch",
"is_typing": "schreibt",
"is_typing_female": "schreibt",
"is_typing_male": "schreibt",
+ "Issue_Links": "Issue-Tracker Links",
+ "IssueLinks_Incompatible": "Warnung: Aktivieren Sie diese Einstellung nicht Zusammen mit der Farbvorschau (Hex).",
+ "IssueLinks_LinkTemplate": "Vorlage für Issue-Verknüpfungen",
+ "IssueLinks_LinkTemplate_Description": "Vorlage für Issue-Verknüpfungen; %s wird mit der Issue-Nummer ersetzt werden.",
"It_works": "Es funktioniert",
"italics": "kursiv",
"Jitsi_Chrome_Extension": "Chrome Extension ID",
- "Jitsi_Enable_Channels": "Aktivieren in Kanälen",
+ "Jitsi_Enable_Channels": "In Kanälen aktivieren",
"join": "Beitreten",
- "Join_audio_call": "Anruf beitreiten",
+ "join-without-join-code": "Ohne Code beitreten",
+ "join-without-join-code_description": "Berechtigung, Kanäle mit Zutrittscode auch ohne Code zu betreten",
+ "Join_audio_call": "Anruf beitreten",
+ "Join_Chat": "Chat beitreten",
"Join_default_channels": "Standardkanälen beitreten",
"Join_the_Community": "Trete der Community bei",
- "Join_the_given_channel": "Angegebenen Kanal beitreten",
+ "Join_the_given_channel": "Diesem Kanal beitreten",
"Join_video_call": "Videoanruf beitreten",
"Joined": "Beigetreten",
"Jump": "Springen",
"Jump_to_first_unread": "Erste ungelesene Nachricht anzeigen",
"Jump_to_message": "Diese Nachricht im Chat anzeigen",
- "Jump_to_recent_messages": "Neue Nachricht im Chat anzeigen",
+ "Jump_to_recent_messages": "Erste neue Nachricht im Chat anzeigen",
+ "Just_invited_people_can_access_this_channel": "Nur eingeladene Benutzer können auf diesen Kanal zugreifen",
"Katex_Dollar_Syntax": "Dollar-Syntax erlauben",
"Katex_Dollar_Syntax_Description": "$$KaTeX Block$$ und $inline KaTeX$ Syntax erlauben",
"Katex_Enabled": "Katex ist aktiviert.",
- "Katex_Enabled_Description": "Erlauben von KaTeX für mathematischen Satz in Nachrichten",
+ "Katex_Enabled_Description": "Erlauben von KaTeX für mathematische Ausdrücke in Nachrichten",
"Katex_Parenthesis_Syntax": "Klammer-Syntax erlauben",
"Katex_Parenthesis_Syntax_Description": "\\[KaTeX Block\\] und \\ (inline KaTeX \\) Syntax erlauben",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Bearbeite vorherige Nachricht",
+ "Keyboard_Shortcuts_Keys_1": "Strg + p ",
+ "Keyboard_Shortcuts_Keys_2": "Pfeiltaste hoch ",
+ "Keyboard_Shortcuts_Keys_3": "Command (oder Alt ) + Pfeiltaste links ",
+ "Keyboard_Shortcuts_Keys_4": "Command (oder Alt ) + Pfeiltaste hoch ",
+ "Keyboard_Shortcuts_Keys_5": "Command (oder Alt ) + Pfeiltaste rechts ",
+ "Keyboard_Shortcuts_Keys_6": "Command (oder Alt ) + Pfeiltaste runter ",
+ "Keyboard_Shortcuts_Keys_7": "Shift + Eingabetaste ",
+ "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "An den Anfang der Nachricht springen",
+ "Keyboard_Shortcuts_Move_To_End_Of_Message": "Ans Ende der Nachricht springen",
+ "Keyboard_Shortcuts_New_Line_In_Message": "Zeilenumbruch einfügen",
+ "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Kanal öffnen / Nach Benutzer suchen",
+ "Keyboard_Shortcuts_Title": "Keyboard Shortcuts",
"Knowledge_Base": "Wissensbasis",
"Label": "Bezeichnung",
"Language": "Sprache",
@@ -623,240 +992,359 @@
"Layout_Terms_of_Service": "Nutzungsbedingungen",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA-Cert",
- "LDAP_Custom_Domain_Search": "Benutzerdefinierte Domainsuche",
- "LDAP_Custom_Domain_Search_Description": "Ein Teil aus JSON, welches Bindungs- und Verbindungsinformationen regelt und folgende Struktur besitzt: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "Verbindungs-Timeout (ms)",
"LDAP_Default_Domain": "Standard-Domain",
- "LDAP_Description": "LDAP ist ein Frontend zu hierarchischen Datenbanken, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "Domainbasis",
- "LDAP_Domain_Base_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. SIe können so viele hinzufügen wie sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befindet. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, im Anwendungsbereich liegen. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um den Zugriff zu kontrollieren.",
- "LDAP_Domain_Search_Filter": "Filter der Domainsuche",
- "LDAP_Domain_Search_Filter_Description": "Wenn angegeben, wird nur Benutzern, die dem Filter entsprechen, erlaubt, sich anzumelden. Wenn kein Filter angegeben ist, werden sich alle Benutzer in dem Bereich der angegebenen Domainbasis anmelden können. Ein Beispiel für Active-Directory: `memberOf=cn=ROCKET_CHAT,ou=General Groups` Ein Beispiel für OpenLDAP (erweiterbare Übereinstimmungssuche): `ou:dn:=ROCKET_CHAT`",
- "LDAP_Domain_Search_Object_Category": "Objektkategorie der Domainsuche",
- "LDAP_Domain_Search_Object_Category_Description": "Die *objectCategory*, die Ihre Nutzer identifizert. Lassen Sie das Feld leer, um *OpenLDAP* zu aktivieren. Beispiel: `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Objektklasse der Domainsuche",
- "LDAP_Domain_Search_Object_Class_Description": "Die *objectclass*, die Ihre Nutzer identifizert. Beispiel: `organizationalPerson`, `user`, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Passwort der Domainsuche",
- "LDAP_Domain_Search_Password_Description": "Das Passwort für die Benuzer der Domainsuche",
- "LDAP_Domain_Search_User": "Domain Search User",
- "LDAP_Domain_Search_User_Description": "Der LDAP-Benutzer, der eine Benutzersuche durchführt, um andere Nutzer bei der Anmeldung zu authentifizieren. Dies ist in der Regel ein Servicekonto, welches für Drittintegrationen erstellt worden ist. Verwenden Sie einen vollen Namen, wie zum Beispiel `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search User ID",
- "LDAP_Domain_Search_User_ID_Description": "Das LDAP-Attribut, welches den LDAP-Benutzer identifiziert, der sich zu authentifizieren versucht. Das Feld ist für die meisten Active-Directory-Installationen `sAMAccountName`, für andere LDAP-Lösungen wie OpenLDAP kann dieses jedoch auch `uid` sein. Sie können aber auch `mail` verwenden, um Benutzer mit Ihrer E-Mail-Adresse zu identifizieren oder jedes Attribut, das Sie möchten. Sie können mehrere Werte, getrennt mit Kommata, verwenden, um es Benutzern zu erlauben, sich mit mehreren Kennungen anzumelden, wie zum Beispiel einem Benutzernamen und der E-Mail-Adresse.",
- "LDAP_Enable": "LDAP aktivieren",
- "LDAP_Enable_Description": "LDAP für die Authentifizierung verwenden.",
+ "LDAP_Default_Domain_Description": "Wenn eine Standard-Domäne angegeben wurde, wird diese zur Erzeugung von E-Mail-Adressen verwendet, sofern keine E-Mail-Adresse aus dem LDAP importiert wurde. Die E-Mail wird konstruiert als `benutzername@standard-domäne` oder `unique_id@standard-domäne` Beispiel: `rocket.chat`",
+ "LDAP_Description": "LDAP ist eine hierarchische Datenbank, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
+ "LDAP_BaseDN": "Base DN",
+ "LDAP_BaseDN_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. Sie können so viele hinzufügen, wie Sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befinden. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, berücksichtigt. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um Einschränkungen vorzunehmen.",
+ "LDAP_User_Search_Field": "Suchfeld",
+ "LDAP_User_Search_Field_Description": "Das LDAP-Attribut, welches den LDAP-Benutzer identifiziert, der sich zu authentifizieren versucht. Das Feld ist für die meisten Active-Directory-Installationen `sAMAccountName`, für andere LDAP-Lösungen wie OpenLDAP kann dieses jedoch auch `uid` sein. Sie können aber auch `mail` verwenden, um Benutzer mit Ihrer E-Mail-Adresse zu identifizieren - oder jedes Attribut, das Sie möchten. Sie können mehrere Werte, getrennt mit Kommata, verwenden, um es Benutzern zu erlauben, sich mit mehreren Kennungen anzumelden, wie zum Beispiel einem Benutzernamen und der E-Mail-Adresse.",
+ "LDAP_User_Search_Filter": "Filter",
+ "LDAP_User_Search_Filter_Description": "Wenn angegeben, wird nur Benutzern, die dem Filter entsprechen, erlaubt, sich anzumelden. Wenn kein Filter angegeben ist, werden sich alle Benutzer in dem Bereich der angegebenen Domainbasis anmelden können. Ein Beispiel für Active-Directory: `memberOf=cn=ROCKET_CHAT,ou=General Groups` Ein Beispiel für OpenLDAP (erweiterbare Übereinstimmungssuche): `ou:dn:=ROCKET_CHAT`",
+ "LDAP_User_Search_Scope": "Scope",
+ "LDAP_Authentication": "Aktivieren",
+ "LDAP_Authentication_Password": "Passwort",
+ "LDAP_Authentication_UserDN": "User DN",
+ "LDAP_Authentication_UserDN_Description": "Der LDAP-Benutzer, der eine Benutzersuche durchführt, um andere Nutzer bei der Anmeldung zu authentifizieren. Dies ist in der Regel ein Servicekonto, welches für Drittintegrationen erstellt worden ist. Verwende einen vollen Namen, wie zum Beispiel `cn=Administrator,cn=Users,dc=Example,dc=com`.",
+ "LDAP_Enable": "LDAP",
+ "LDAP_Enable_Description": "LDAP zur Authentifizierung verwenden",
"LDAP_Encryption": "Verschlüsselung",
- "LDAP_Encryption_Description": "Die Verschlüsselungsmethode für sichere Kommunikation mit dem LDAP-Server. Die Beispiele enthalten `plain` (keine Verschlüsselung), `SSL/LDAPS` (von Anfang an verschlüsselt) und `StartTLS` (zur verschlüsselten Kommunikation wechseln, sobald verbunden)",
+ "LDAP_Encryption_Description": "Die Verschlüsselungsmethode für sichere Kommunikation mit dem LDAP-Server. Bspw. `plain` (keine Verschlüsselung), `SSL/LDAPS` (von Anfang an verschlüsselt) und `StartTLS` (zur verschlüsselten Kommunikation wechseln, sobald verbunden wurde)",
+ "LDAP_Internal_Log_Level": "Internes Log-Level",
+ "LDAP_Group_Filter_Enable": "LDAP Benutzergruppen-Filter",
+ "LDAP_Group_Filter_Enable_Description": "Zugriff auf LDAP-Benutzergruppe beschränken. Diese Option ist hilfreich bei OpenLDAP-Servern, die den *memberOf*-Filter nicht unterstützen.",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Group-ID-Attibut",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "Bspw. *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute": "Gruppenmitglieds-Attribut",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "Bspw. *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format": "Gruppenmitglieds-Format",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "Bspw. *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Gruppenname",
+ "LDAP_Group_Filter_Group_Name_Description": "Gruppe, zu der der Benutzer gehört",
+ "LDAP_Group_Filter_ObjectClass": "Gruppen-ObjectClass ",
+ "LDAP_Group_Filter_ObjectClass_Description": "Die *objectClass*, die Gruppen identifiziert. Bspw. OpenLDAP:groupOfUniqueNames",
"LDAP_Host": "LDAP-Host",
- "LDAP_Host_Description": "Der LDAP-Host, z.B. `ldap.example.com` oder `10.0.0.30`.",
- "LDAP_Import_Users": "Importiere LDAP-Benutzer",
- "LDAP_Merge_Existing_Users": "Verschmelze existierende Benutzer",
+ "LDAP_Host_Description": "Der LDAP-Host, bspw. `ldap.example.com` oder `10.0.0.30`.",
+ "LDAP_Idle_Timeout": "Idle Timeout (ms)",
+ "LDAP_Idle_Timeout_Description": "Die Wartezeit in Millisekunden, die nach der letzten LDAP-Operation gewartet werden soll, bevor die Verbindung beendet wird. Anmerkung: Jede Operation öffnet eine neue Verbindung",
+ "LDAP_Import_Users_Description": "Importiert alle gefundenen LDAP-Benutzer. *Achtung!* Filteroption angeben , um nicht zu viele Benutzer zu importieren",
+ "LDAP_Login_Fallback": "Login Fallback",
+ "LDAP_Login_Fallback_Description": "Wenn der Login mit Hilfe von LDAP nicht erfolgreich war versuchen, mit dem lokalen Konto anzumelden. Das kann hilfreich sein, falls LDAP nicht verfügbar war.",
+ "LDAP_Merge_Existing_Users": "Verschmelze mit existierenden Benutzern",
+ "LDAP_Merge_Existing_Users_Description": "*Achtung!* Wenn beim Import aus LDAP ein lokaler Benutzer mit gleichem Namen bereits existiert, wird der lokale Benutzer mit den Einstellungen aus LDAP aktualisiert.",
"LDAP_Port": "LDAP-Port",
- "LDAP_Port_Description": "Port für den Zugriff auf LDAP. Beispiel: Port 389 oder 636 für LDAPS",
+ "LDAP_Port_Description": "Port für den LDAP-Zugriff, bspw.Port 389 oder 636 für LDAPS",
+ "LDAP_Reconnect": "Erneut verbinden",
+ "LDAP_Reconnect_Description": "Versuche, erneut zu verbinden, wenn die Verbindung aus unbekanntem Grund unterbrochen wurde",
"LDAP_Reject_Unauthorized": "Unberechtigte ablehnen",
+ "LDAP_Reject_Unauthorized_Description": "Deaktiviere diese Option, um nicht-verifizierte Zertifikate zu akzeptieren. Ein Deaktivieren wird üblicherweise bei der Nutzung von selbst-signierten Zertifikaten benötigt.",
"LDAP_Sync_User_Avatar": "Profilbilder synchronisieren",
- "LDAP_Sync_User_Data": "Daten synchronisieren",
- "LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Beispiel: Name, E-Mail).",
- "LDAP_Sync_User_Data_FieldMap": "Nutzerdaten-Feldkarte",
- "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurieren Sie, wie Benutzer-Account-Felder (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden. Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen von dem cn-Attribut und die E-Mail-Adresse vom Mail-Attribut. Verfügbare Felder beinhalten den Namen und die E-Mail-Adresse.",
- "LDAP_Sync_Users": "Benutzer synchronisieren",
- "LDAP_Test_Connection": "Testverbindung",
- "LDAP_Unique_Identifier_Field": "Eindeutige Kennung des Felds",
- "LDAP_Unique_Identifier_Field_Description": "Dieses Feld wird verwendet, um LDAP-Nutzer und Rocket.Chat-Nutzer zu verbinden. Sie können mehrere Kommata-getrennte Werte angeben, um die Werte vom LDAP-Eintrag zu erhalten. Der Standardwert ist `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`.",
- "LDAP_Use_Custom_Domain_Search": "Benutzerdefinierte Domainsuche verwenden",
- "LDAP_Use_Custom_Domain_Search_Description": "Schreiben Sie Ihren eigenen Filter, um Benutzer auf dem LDAP-Server zu suchen.",
- "LDAP_Username_Field": "Nutzernamenfeld",
- "LDAP_Username_Field_Description": "Geben Sie an, welches Feld als *Nutzername* für neue Benutzer verwendet werden soll. Lassen Sie das Feld leer, um den Nutzernamen zu verwenden, der auf der Anmeldeseite verwendet wird. Es können auch Template-Tags wie `#{givenNamen}.#{sn}` verwendet werden. Der Standardwert ist `sAMAccountName`.",
+ "LDAP_Sync_Now": "Jetzt im Hintergrund synchronisieren",
+ "LDAP_Sync_Now_Description": "Führt jetzt eine **Synchronisierung im Hintergrund** aus, anstatt auf die nächste planmäßige Synchronisierung zu warten.\nDas funktioniert auch, wenn die Synchronisierung im Hintergrund deaktiviert ist. Die Aktion läuft asynchron ab, der Fortschritt kann im Log verfolgt werden.",
+ "LDAP_Background_Sync": "Synchronisierung im Hintergrund",
+ "LDAP_Background_Sync_Interval": "Interval für die Synchronisierung im Hintergrund",
+ "LDAP_Background_Sync_Interval_Description": "Das Intervall zwischen Synchronisierungen. Z. B. `every 24 hours` oder `on the first day of the week`. Weitere Beispiele unter [Cron Text Parser](http://bunkat.github.io/later/parsers.html#text)",
+ "LDAP_Background_Sync_Import_New_Users": "Synchronisierung neuer Benutzer im Hintergrund",
+ "LDAP_Background_Sync_Import_New_Users_Description": "Dies wird alle Benutzer entsprechend Deiner Filterkriterien importieren, die im LDAP aber noch nicht in Rocket.Chat vorhanden sind",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated": "Im Hintergrund eine Aktualisierung der bestehenden Benutzer ausführen",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated_Description": "Dies wird den Benutzernamen, den Avatar und alle weiteren Felder basierend auf Deiner Konfiguration aus dem LDAP bei jeder Synchronisierung aktualisieren",
+ "LDAP_Sync_User_Data": "Benutzerdaten synchronisieren",
+ "LDAP_Sync_User_Data_Description": "Bei der Anmeldung die Benutzerdaten mit dem Server synchronisieren (Bspw. Name, E-Mail-Adresse).",
+ "LDAP_Sync_User_Data_FieldMap": "Zuordnung der Benutzer-Attribute",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Konfigurieren Sie, wie Benutzer-Account-Eigenschaften (wie die E-Mail-Adresse) aus einem LDAP-Datensatz (falls gefunden) geladen werden. Beispiel: {\"cn\":\"name\", \"mail\":\"email\"} nimmt einen von Menschen lesbaren Namen aus dem cn-Attribut und die E-Mail-Adresse aus dem Mail-Attribut. Zusätzlich ist die Verwendung von Variablen möglich, wie z.B.: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }`. Hierbei wird eine Kombination des Vor- und Nachnamens verwendet. Verfügbare Felder in Rocket.Chat sind `name` und `email`.",
+ "LDAP_Search_Page_Size": "Seitengröße für die Suche",
+ "LDAP_Search_Page_Size_Description": "Die maximale Anzahl von Einträgen, die auf einmal verarbeitet werden",
+ "LDAP_Search_Size_Limit": "Maximale Treffer-Anzahl",
+ "LDAP_Search_Size_Limit_Description": "Die maximale Anzahl von Einträgen, die prozessiert werden. **Achtung**: Diese Zahle sollte größer als die **Seitengröße für die Suche** sein",
+ "LDAP_Test_Connection": "Verbindung prüfen",
+ "LDAP_Timeout": "Timeout (ms)",
+ "LDAP_Timeout_Description": "Wie lange auf ein Suchergebnis gewartet werden soll, bevor ein Fehler ausgegeben wird",
+ "LDAP_Unique_Identifier_Field": "Feld für eindeutige Identifizierung",
+ "LDAP_Unique_Identifier_Field_Description": "Dieses Feld wird verwendet, um LDAP-Nutzer und Rocket.Chat-Nutzer zu verbinden. Kommata-getrennte Werte können verwendet werden, um die Werte vom LDAP-Eintrag zu erhalten. Der Standardwert ist `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`.",
+ "LDAP_Username_Field": "Feld für den Benutzernamen",
+ "LDAP_Username_Field_Description": "Geben Sie an, welches Feld als *Benutzername* für neue Benutzer verwendet werden soll. Lassen Sie das Feld leer, um den Nutzernamen zu verwenden, der auf der Anmeldeseite verwendet wird. Es können auch Template-Tags wie `#{givenNamen}.#{sn}` verwendet werden. Der Standardwert ist `sAMAccountName`.",
+ "Execute_Synchronization_Now": "Jetzt eine Synchronisierung ausführen",
"Least_Amount": "Geringste Anzahl",
- "Leave_Group_Warning": "Sind sie sicher, die Gruppe \"%s\" zu verlassen?",
- "Leave_Private_Warning": "Sind sie sicher, das Gespräch mit \"%s\" zu verlassen?",
+ "Leave_Group_Warning": "Sind Sie sicher, dass Sie die Gruppe \"%s\" verlassen wollen?",
+ "Leave_Livechat_Warning": "Sind Sie sich sicher, dass Sie den Livechat mit \"%s\" verlassen wollen?",
+ "Leave_Private_Warning": "Sind Sie sicher, dass Sie das Gespräch mit \"%s\" verlassen wollen?",
"Leave_room": "Raum verlassen",
- "Leave_Room_Warning": "Sind sie sicher, den Raum \"%s\" zu verlassen?",
- "line": "Zeilen",
+ "Leave_Room_Warning": "Sind Sie sicher, dass Sie den Raum \"%s\" verlassen wollen?",
+ "Leave_the_current_channel": "Aktuellen Kanal verlassen",
+ "line": "Zeile",
"List_of_Channels": "Liste der Kanäle",
"List_of_Direct_Messages": "Liste der Direktnachrichten",
- "Livechat_agents": "LiveChat-Agent",
- "Livechat_Dashboard": "LiveChat-Dashboard",
- "Livechat_enabled": "LiveChat aktiviert",
- "Livechat_forward_open_chats": "Offene Chats weiter leiten",
- "Livechat_forward_open_chats_timeout": "Timeout (in Sekunden), um Chats weiterzuleiten",
+ "Livechat_agents": "Livechat-Agenten",
+ "Livechat_AllowedDomainsList": "Domänen, in denen der Livechat zulässig ist",
+ "Livechat_Dashboard": "Livechat-Dashboard",
+ "Livechat_enabled": "Livechat",
+ "Livechat_forward_open_chats": "Offene Chats weiterleiten",
+ "Livechat_forward_open_chats_timeout": "Timeout (in Sekunden), nach dem Chats weitergeleitet werden",
"Livechat_guest_count": "Gästezähler",
- "Livechat_managers": "LiveChat-Manager",
+ "Livechat_Inquiry_Already_Taken": "Livechat-Anfrage bereits übernommen",
+ "Livechat_managers": "Livechat-Manager",
"Livechat_offline": "Livechat offline",
"Livechat_online": "Livechat online",
- "Livechat_room_count": "Livechat-Raumanzahl",
- "Livechat_title": "LiveChat-Titel",
- "Livechat_title_color": "Hintergrundfarbe des LiveChat-Titels",
- "Livechat_Users": "LiveChat-Benutzer",
- "Load_more": "Mehr laden",
+ "Livechat_open_inquiery_show_connecting": "Die \"Verbinden\"-Nachricht anstatt des Eingabefeldes anzeigen, wenn der Gast nicht mit einem Agenten verbunden ist.",
+ "Livechat_Queue": "Livechat-Warteschlange",
+ "Livechat_room_count": "Anzahl der Livechat-Räume",
+ "Livechat_Routing_Method": "Livechat Routing-Methode",
+ "Livechat_Take_Confirm": "Wollen Sie diesen Kunden annehmen?",
+ "Livechat_title": "Livechat-Titel",
+ "Livechat_title_color": "Hintergrundfarbe des Livechat-Titels",
+ "Livechat_Users": "Livechat-Benutzer",
+ "Load_more": "Weitere laden",
"Loading...": "Wird geladen...",
- "Loading_more_from_history": "Mehr Nachrichten aus dem Verlauf anzeigen",
- "Loading_suggestion": "Vorschläge werden geladen...",
+ "Loading_more_from_history": "Weitere Nachrichten aus dem Verlauf anzeigen",
+ "Loading_suggestion": "Vorschläge werden geladen",
"Localization": "Lokalisierung",
+ "Log_Exceptions_to_Channel": "Ausnahmen in einen Kanal schreiben",
+ "Log_Exceptions_to_Channel_Description": "Name eines Kanals, der alle abgefangenen Ausnahmen aufnimmt. Leer lassen, um sie nur ins Anwendungslog zu schreiben.",
"Log_File": "Datei und Zeile anzeigen",
"Log_Level": "Loglevel",
- "Log_Package": "Paket zeigen",
- "Log_View_Limit": "Begrenzung der Logansicht",
- "Logged_out_of_other_clients_successfully": "Sie wurden erfolgreich von anderen Geräten abgemeldet.",
+ "Log_Package": "Paket anzeigen",
+ "Log_View_Limit": "Begrenzung der Log-Ansicht",
+ "Logged_out_of_other_clients_successfully": "Sie wurden erfolgreich von anderen Geräten abgemeldet",
"Login": "Anmelden",
"Login_with": "Anmelden mit %s",
"Logout": "Abmelden",
"Logout_Others": "Von anderen Geräten abmelden",
- "Mail_Message_Invalid_emails": "Sie haben eine oder mehrere ungültige E-Mail-Adressen angegeben: %s",
- "Mail_Message_Missing_to": "Sie müssen einen/mehrere Benutzer auswählen oder einen/mehrere E-Mail-Adressen durch Kommata getrennt angeben.",
- "Mail_Message_No_messages_selected_select_all": "Sie haben keine Nachrichten ausgewählt. Möchten Sie alle sichtbaren Nachrichten auswählen?",
+ "mail-messages": "Nachrichten per E-Mail versenden",
+ "mail-messages_description": "Berechtigung, Nachrichten per E-Mail zu versenden",
+ "Mail_Message_Invalid_emails": "Du hast eine oder mehrere ungültige E-Mail-Adressen angegeben: %s",
+ "Mail_Message_Missing_to": "Sie müssen einen/mehrere Benutzer auswählen oder eine/mehrere E-Mail-Adressen durch Kommata getrennt angeben.",
+ "Mail_Message_No_messages_selected_select_all": "Sie haben keine Nachrichten ausgewählt. Möchten Sie alle sichtbaren Nachrichten auswählen?",
"Mail_Messages": "Nachrichten per E-Mail senden",
- "Mail_Messages_Instructions": "Wählen Sie aus, welche Nachrichten Sie per E-Mail senden möchten, indem Sie die Nachrichten anklicken. ",
+ "Mail_Messages_Instructions": "Wähle die per E-Mail zu versendenden Nachrichten aus, indem Du die Nachrichten anklickst. ",
"Mail_Messages_Subject": "Hier ist ein ausgewählter Teil aus %s Nachrichten",
"Mailer": "Mailer",
- "Mailer_body_tags": "Sie müssen [unsubscribe] verwenden, um einen Link zum Abmelden aus dem Verteiler zur Verfügung zu stellen. Sie können [name] für den Vor- und Nachnamen, [fname] für den Vornamen oder [lname] für den Nachnamen des Benutzers verwenden. Ebenfalls können Sie [email] verwenden, um die E-Mail-Adresse des Benutzers anzugeben.",
+ "Mailer_body_tags": "Sie müssen [unsubscribe] verwenden, um einen Link zum Abmelden aus dem Verteiler zur Verfügung zu stellen. Sie können [name] für den vollständigen Namen, [fname] für den Vornamen oder [lname] für den Nachnamen des Benutzers verwenden. Ebenfalls können Sie [email] verwenden, um die E-Mail-Adresse des Benutzers anzugeben.",
"Mailing": "Mailing",
"Make_Admin": "Benutzer zum Admin ernennen",
- "Manager_added": "Der Manager wurde hinzugefügt.\n",
- "Manager_removed": "Der Manager wurde gelöscht.",
- "Managing_assets": "Assetverwaltung",
+ "Make_sure_you_have_a_copy_of_your_codes": "Stellen Sie sicher, dass Sie eine Kopie Ihrer Codes besitzen: __codes__ . Wenn Sie den Zugriff auf Ihre Authentifizierungs-App verlieden, können Sie sich mit Hilfe eines dieser Codes erneut anmelden.",
+ "manage-assets": "Assets verwalten",
+ "manage-assets_description": "Berechtigung, Assets (Stylesheets, Bilder, weitere Dateien) auf dem Server zu verwalten",
+ "manage-emoji": "Emojis verwalten",
+ "manage-emoji_description": "Berechtigung, Emojis zu verwalten",
+ "manage-integrations": "Integrationen verwalten",
+ "manage-integrations_description": "Berechtigung, die Integrationen des Servers zu verwalten",
+ "manage-oauth-apps": "OAuth-Anwendungen verwalten",
+ "manage-oauth-apps_description": "Berechtigung, OAuth-Anwendungen verwalten",
+ "manage-own-integrations": "Eigene Integrationen verwalten",
+ "manage-own-integrations_description": "Berechtigung, das Benutzer eigene Integrationen oder Webhooks erstellen und verwalten",
+ "manage-sounds": "Töne verwalten",
+ "manage-sounds_description": "Berechtigung, Töne zu verwalten",
+ "Manager_added": "Der Manager wurde hinzugefügt\n",
+ "Manager_removed": "Der Manager wurde gelöscht",
+ "Managing_assets": "Asset-Verwaltung",
"Managing_integrations": "Integrationsverwaltung",
+ "MapView_Enabled": "Kartenansicht",
+ "MapView_Enabled_Description": "Das Aktivieren der Kartenansicht sorgt dafür, dass ein Button zum Teilen des aktuellen Ortes links des Eingabefeldes angezeigt wird.",
+ "MapView_GMapsAPIKey": "Google Static Maps API Schlüssel",
+ "MapView_GMapsAPIKey_Description": "Dieser kann kostenlos aus der Google-Entwickler-Konsole bezogen werden.",
"Mark_as_read": "Als gelesen markieren",
"Mark_as_unread": "Als ungelesen markieren",
"Markdown_Headers": "Markdown-Überschriften",
- "Markdown_SupportSchemesForLink": "Markdown-Support-System für Links",
- "Markdown_SupportSchemesForLink_Description": "Kommata getrennte Liste von erlaubten Systemen",
+ "Markdown_Marked_Breaks": "Formatierte Umbrüche",
+ "Markdown_Marked_GFM": "Formatierung mit Github Flavoured Markdown (GFM)",
+ "Markdown_Marked_Pedantic": "Pedantisch Formatieren",
+ "Markdown_Marked_SmartLists": "Formatierte smarte Listen",
+ "Markdown_Marked_Smartypants": "Formatiere mit intelligenter Punktsetzung (\"Smartypants\")",
+ "Markdown_Marked_Tables": "Formatierte Tabellen",
+ "Markdown_Parser": "Markdown Parser",
+ "Markdown_SupportSchemesForLink": "Unterstützte Markdown- Schemata für Links",
+ "Markdown_SupportSchemesForLink_Description": "Kommata getrennte Liste von erlaubten Schemata",
+ "Max_length_is": "Maximale Länge ist %s",
"Members_List": "Mitglieder",
+ "mention-all": "Alle erwähnen",
+ "mention-all_description": "Berechtigung, @all zur Erwähnung aller Kanalmitglieder zu verwenden",
"Mentions": "Erwähnungen",
"Mentions_default": "Erwähnungen (Standard)",
+ "Mentions_only": "Nur Erwähnungen",
"Message": "Nachricht",
- "Message_AllowBadWordsFilter": "Wortfilter für Nachrichten aktivieren",
- "Message_AllowDeleting": "Das Löschen von Nachrichten erlauben",
- "Message_AllowDeleting_BlockDeleteInMinutes": "Das Löschen von Nachrichten nach (n) Minuten sperren",
- "Message_AllowDeleting_BlockDeleteInMinutes_Description": "Geben Sie 0 ein, um keine Sperre zu setzen.",
+ "Message_AllowBadWordsFilter": "Wortfilter für Nachrichten verwenden",
+ "Message_AllowDeleting": "Löschen von Nachrichten erlauben",
+ "Message_AllowDeleting_BlockDeleteInMinutes": "Löschen von Nachrichten nach (n) Minuten sperren",
+ "Message_AllowDeleting_BlockDeleteInMinutes_Description": "Geben Sie 0 ein, um keine Sperre zu setzen",
+ "Message_AllowDirectMessagesToYourself": "Selbstgespräche erlauben",
"Message_AllowEditing": "Die Bearbeitung von Nachrichten erlauben",
- "Message_AllowEditing_BlockEditInMinutes": "Bearbeiten von Nachrichten nach (in Minuten - 0 zum deaktivieren) blockieren ",
- "Message_AllowEditing_BlockEditInMinutesDescription": "Geben Sie eine 0 ein, um das Bearbeiten von Nachrichten jederzeit zu erlauben.",
- "Message_AllowPinning": "Das Fixieren von Nachrichten erlauben",
- "Message_AllowPinning_Description": "Benutzern das Fixieren von Nachrichten in Kanälen erlauben",
- "Message_AllowStarring": "Erlaube es, Nachrichten zu markieren",
- "Message_AlwaysSearchRegExp": "Beim Suchen immer RegExp verwenden",
- "Message_AlwaysSearchRegExp_Description": "Wir empfehlen `True` zu benutzen, wenn ihre Sprache für die MongoDB-Textsuche nicht unterstützt wird.",
+ "Message_AllowEditing_BlockEditInMinutes": "Bearbeiten von Nachrichten nach (n) Minuten sperren",
+ "Message_AllowEditing_BlockEditInMinutesDescription": "Gib 0 ein, um das Bearbeiten von Nachrichten unbegrenzt zu erlauben.",
+ "Message_AllowPinning": "Das Anheften von Nachrichten erlauben",
+ "Message_AllowPinning_Description": "Benutzern das Anheften von Nachrichten in Kanälen erlauben",
+ "Message_AllowSnippeting": "Erlauben, Snippets aus Nachrichten zu erstellen",
+ "Message_AllowStarring": "Erlaube es, Nachrichten als Favoriten zu markieren",
+ "Message_AllowUnrecognizedSlashCommand": "Unerkannte Slash-Kommandos erlauben",
+ "Message_AlwaysSearchRegExp": "Beim Suchen immer reguläre Ausdrücke verwenden",
+ "Message_AlwaysSearchRegExp_Description": "Wir empfehlen diese Option, wenn Ihre Sprache in der MongoDB-Textsuche nicht unterstützt wird.",
+ "Message_Attachments": "Nachrichten-Anhänge",
+ "Message_Attachments_GroupAttach": "Schaltflächen für Anhänge gruppieren",
+ "Message_Attachments_GroupAttachDescription": "Dies sorgt dafür, dass die Schaltflächen in einem erweiterbaren Menü untergebracht werden. So wird weniger Bildschirmplatz benötigt.",
"Message_AudioRecorderEnabled": "Audioaufnahme aktivieren",
- "Message_AudioRecorderEnabledDescription": "'audio/wav'-Dateien sind erforderlich, damit der Medientyp in den \"Dateien-Upload\"-Einstellungen akzeptiert wird.",
+ "Message_AudioRecorderEnabledDescription": "Dies erfoldert, dass 'audio/wav' ein erlaubter Medientyp in den \"Dateien-Upload\"-Einstellungen ist",
"Message_BadWordsFilterList": "Wörter zur Blacklist hinzufügen",
- "Message_BadWordsFilterListDescription": "Liste durch Kommata getrennter zu filternder Worte",
+ "Message_BadWordsFilterListDescription": "Kommaseparierte Liste zu filternder Worte",
"Message_DateFormat": "Datumsformat",
- "Message_DateFormat_Description": "Siehe auch: Moment.js ",
- "Message_deleting_blocked": "Diese Nachricht kann nicht mehr gelöscht werden.",
+ "Message_DateFormat_Description": "Für mögliche Formate s. Dokumentation von Moment.js ",
+ "Message_deleting_blocked": "Diese Nachricht kann nicht mehr gelöscht werden",
"Message_editing": "Bearbeiten von Nachrichten",
"Message_GroupingPeriod": "Gruppierungsdauer (in Sekunden)",
- "Message_GroupingPeriodDescription": "Nachrichten werden einer vorherigen Nachricht zugeordnet, wenn beide Nachrichten von dem gleichen Benutzer kommen und die abgelaufene Zeit kleiner als die mitgeteilte Zeit in Sekunden war.",
- "Message_HideType_au": "\"Benutzer hinzugeben\" Nachrichten verstecken",
- "Message_HideType_mute_unmute": "\"Benutzer stillgeschalten\" Nachrichten verstecken",
- "Message_HideType_ru": "\"Benutzer entfernt\" Nachrichten verstecken",
- "Message_HideType_uj": "\"Benutzer beigetreten\" Nachrichten verstecken",
- "Message_HideType_ul": "\"Benutzer verlassen\" Nachrichten verstecken",
- "Message_KeepHistory": "Nachrichtenverlauf behalten",
- "Message_MaxAll": "Maximale Kanalgröße für ALL Nachricht",
- "Message_MaxAllowedSize": "Maximal zulässige Größe der Nachrichten\n",
+ "Message_GroupingPeriodDescription": "Nachrichten werden einer vorherigen Nachricht zugeordnet, wenn beide Nachrichten von dem gleichen Benutzer kommen und die dazwischen liegende Dauer (in Sekunden) kleiner als die hier eingestellte war",
+ "Message_HideType_au": "\"Benutzer hinzugefügt\"-Nachricht deaktivieren",
+ "Message_HideType_mute_unmute": "\"Benutzer stillgeschaltet\"-Nachricht deaktivieren",
+ "Message_HideType_ru": "\"Benutzer entfernt\" -Nachricht deaktivieren",
+ "Message_HideType_uj": "\"Benutzer beigetreten\"-Nachricht deaktivieren",
+ "Message_HideType_ul": "\"Benutzer hat den Raum verlassen\"-Nachricht deaktivieren",
+ "Message_KeepHistory": "Bearbeitungshistorie für Nachrichten behalten",
+ "Message_MaxAll": "Maximale Kanalgröße für @all-Erwähnung",
+ "Message_MaxAllowedSize": "Maximal zulässige Größe der Nachrichten",
"Message_pinning": "Anpinnen von Nachrichten",
- "Message_removed": "Diese Nachricht wurde entfernt.",
- "Message_SetNameToAliasEnabled": "In Nachricht Alias als Benutzername setzen",
- "Message_SetNameToAliasEnabled_Description": "Nur wenn nicht als Alias gesetzt. Wird bei alten Nachrichten nicht geändert, falls Benutzer Name geändert hat.",
- "Message_ShowDeletedStatus": "Löschstatus zeigen",
- "Message_ShowEditedStatus": "Bearbeitungsstatus zeigen",
- "Message_ShowFormattingTips": "Formatierungstipps anzeigen",
- "Message_starring": "Markieren von Nachrichten",
+ "Message_QuoteChainLimit": "Maximale Anzahl von verketteten Zitaten",
+ "Message_removed": "Die Nachricht wurde entfernt",
+ "Message_sent_by_email": "Nachricht per E-Mail versendet",
+ "Message_SetNameToAliasEnabled": "Benutzernamen als Alias verwenden",
+ "Message_SetNameToAliasEnabled_Description": "Hat nur einen Effekt auf neue Nachrichten und falls kein expliziter Alias gesetzt wurde",
+ "Message_ShowDeletedStatus": "Löschstatus anzeigen",
+ "Message_ShowEditedStatus": "Bearbeitungsstatus anzeigen",
+ "Message_ShowFormattingTips": "Formatierungshilfe anzeigen",
+ "Message_starring": "Markieren von favorisierten Nachrichten",
+ "Message_TimeAndDateFormat": "Zeit- und Datumsformat",
+ "Message_TimeAndDateFormat_Description": "Für mögliche Formate s. Dokumentation von Moment.js ",
"Message_TimeFormat": "Zeitformat",
- "Message_TimeFormat_Description": "Siehe auch: Moment.js ",
- "Message_too_long": "Diese Nachricht ist zu lang.",
- "Message_VideoRecorderEnabled": "Videoaufnahmen eingeschaltet",
- "Message_VideoRecorderEnabledDescription": "Videoformat auf webm beim \"Datei hochladen\" einschränken? (Video abspielen funktioniert dann in fast allen Browsern)",
+ "Message_TimeFormat_Description": "Für mögliche Formate s. Dokumentation von Moment.js ",
+ "Message_too_long": "Die Nachricht ist zu lang",
+ "Message_VideoRecorderEnabled": "Videoaufnahme eingeschaltet",
+ "Message_VideoRecorderEnabledDescription": "Erfordert, dass der Medientyp 'video/webm' in den \"Datei-Upload\"-Einstellungen als Medientyp akzeptiert wird",
"Messages": "Nachrichten",
- "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Nachrichten, die an den eingehenden Webhook gesendet werden, werden hier veröffentlicht.",
+ "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Nachrichten, die an den eingehenden Webhook gesendet werden, werden hier veröffentlicht",
"Meta": "Metadaten",
+ "Meta_custom": "Benutzerdefinierte Meta-Tags",
"Meta_fb_app_id": "Facebook-App-ID",
"Meta_google-site-verification": "Google-Seiten-Verifizierung",
"Meta_language": "Sprache",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Roboter",
+ "Min_length_is": "Die minimale Länge beträgt %s",
"minutes": "Minuten",
+ "Mobile": "Mobil",
+ "Mobile_Notifications_Default_Alert": "Mobile Benachrichtigungen bei",
"Monday": "Montag",
- "Monitor_history_for_changes_on": "Verlaufsänderungen beobachten für",
- "More_channels": "Mehr Kanäle",
- "More_direct_messages": "Mehr Direktnachrichten",
- "More_groups": "Weitere private Gruppen",
- "More_unreads": "Mehr ungelesene Nachrichten",
+ "Monitor_history_for_changes_on": "Was soll für die Historie überwacht werden?",
+ "More_channels": "Weitere Kanäle",
+ "More_direct_messages": "Weitere Direktnachrichten",
+ "More_groups": "Weitere private Kanäle",
+ "More_unreads": "Weitere ungelesene Nachrichten",
+ "Move_beginning_message": "`%s` - Zum Anfang der Nachricht springen",
+ "Move_end_message": "`%s` - Zum Ende der Nachricht springen",
"Msgs": "Nachrichten",
"multi": "mehrere",
- "Mute_someone_in_room": "Jemanden das Chatten in einem Raum verbieten",
- "Mute_user": "Benutzern das Chatten verbieten",
+ "multi_line": "Mehrzeilig",
+ "mute-user": "Benutzer stumm schalten",
+ "mute-user_description": "Berechtigung, Benutzer in diesem Kanal stumm zu schalten",
+ "Mute_someone_in_room": "Jemandem in einem Raum das Chatten verbieten",
+ "Mute_user": "Einem Benutzer das Chatten verbieten",
"Muted": "Stumm geschaltet",
"My_Account": "Mein Konto",
+ "My_location": "Mein Ort",
"n_messages": "%s Nachrichten",
"N_new_messages": "%s neue Nachrichten",
"Name": "Name",
- "Name_cant_be_empty": "Es muss ein Name angegeben werden.",
- "Name_of_agent": "Name des Agents",
+ "Name_cant_be_empty": "Es muss ein Name angegeben werden",
+ "Name_of_agent": "Name des Agenten",
"Name_optional": "Name (optional)",
+ "Name_Placeholder": "Bitte geben Sie Ihren Namen ein",
"Navigation_History": "Navigationsverlauf",
"New_Application": "Neue Anwendung",
"New_Custom_Field": "Neues benutzerdefiniertes Feld",
"New_Department": "Neue Abteilung",
"New_integration": "Neue Integration",
- "New_logs": "Neue Logdateien",
+ "New_line_message_compose_input": "`%s` - Zeilenumbruch einfügen",
+ "New_logs": "Neue Logs",
"New_Message_Notification": "Neue-Nachricht-Benachrichtigung",
"New_messages": "Neue Nachrichten",
"New_password": "Neues Passwort",
+ "New_Password_Placeholder": "Bitte geben Sie ein neues Passwort ein",
"New_role": "Neue Rolle",
"New_Room_Notification": "Neuer-Raum-Benachrichtigung",
+ "New_Trigger": "Neuer Trigger",
+ "New_videocall_request": "Neuer Video-Anruf",
+ "No_available_agents_to_transfer": "Kein Agent verfügbar, an den übergeben werden kann",
"No_channel_with_name_%s_was_found": "Es wurde kein Kanal mit dem Namen \"%s\" gefunden!",
- "No_channels_yet": "Sie sind kein Mitglied eines Kanals.",
- "No_direct_messages_yet": "Sie haben keine Gespräche gestartet.",
+ "No_channels_yet": "Sie sind bisher kein Mitglied eines Kanals",
+ "No_direct_messages_yet": "Sie haben bisher keine Konversationen gestartet",
"No_Encryption": "Keine Verschlüsselung",
- "No_group_with_name_%s_was_found": "Es wurde keine private Gruppe mit dem Namen \"%s\" gefunden!",
- "No_groups_yet": "Sie sind kein Mitglied einer privaten Gruppe.",
- "No_livechats": "Kein LiveChat vorhanden.",
- "No_mentions_found": "Sie wurden bisher nirgendwo erwähnt.",
- "No_pinned_messages": "Es wurden bisher keine Nachrichten fixiert.",
- "No_results_found": "Keine Ergebnisse gefunden.",
- "No_starred_messages": "Es wurden bisher keine Nachrichten markiert.",
- "No_such_command": "Es gibt keinen Befehl: '/__command__'",
- "No_user_with_username_%s_was_found": "Es wurde kein Benutzer mit dem Namen \"%s\" gefunden!",
+ "No_group_with_name_%s_was_found": "Es wurde keine private Gruppe mit dem Namen \"%s\" gefunden!",
+ "No_groups_yet": "Sie sind kein Mitglied einer privaten Gruppe",
+ "No_integration_found": "Keine Integration unter der angegebenen ID",
+ "No_livechats": "Kein Livechat vorhanden",
+ "No_mentions_found": "Sie wurden bisher nirgendwo erwähnt",
+ "No_pinned_messages": "Es wurden bisher keine Nachrichten fixiert",
+ "No_results_found": "Keine Ergebnisse gefunden",
+ "No_snippet_messages": "Keine Snippets vorhanden",
+ "No_starred_messages": "Es wurden bisher keine Nachrichten favorisiert",
+ "No_such_command": "Es gibt keinen Befehl '/__command__'",
+ "No_user_with_username_%s_was_found": "Es wurde kein Benutzer mit dem Namen \"%s\" gefunden!",
"Nobody_available": "Es ist niemand verfügbar",
"Node_version": "Node-Version",
+ "None": "Keine",
"Normal": "Normal",
"Not_authorized": "Nicht berechtigt",
"Not_Available": "Nicht verfügbar",
- "Not_found_or_not_allowed": "Nicht gefunden oder nicht erlaubt.",
+ "Not_found_or_not_allowed": "Nicht gefunden oder nicht zugelassen",
"Nothing": "Nichts",
- "Nothing_found": "Es wurde nichts gefunden.",
+ "Nothing_found": "Es wurde nichts gefunden",
+ "Notification_Desktop_Default_For": "Desktop-Benachrichtigungen anzeigen für",
"Notification_Duration": "Benachrichtigungsdauer",
+ "Notification_Mobile_Default_For": "Mobile Benachrichtigungen anzeigen für",
"Notifications": "Benachrichtigungen",
+ "Notifications_Max_Room_Members": "Maximale Anzahl der Raummitglieder, ab der alle Nachrichten-Benachrichtigungen deaktiviert werden",
+ "Notifications_Max_Room_Members_Description": "Maximale Anzahl der Raummitglieder, ab der alle Benachrichtigungen deaktiviert werden. Benutzer können weiterhin die Einstellung für den Raum ändern, um auf individueller Basis alle Nachrichten zu erhalten (0 deaktiviert die Einstellung)",
+ "Notifications_Muted_Description": "Wenn Sie sich entscheiden, alles stumm zu schalten, werden Sie keine Kennzeichnungen für neue Nachrichten in der Liste sehen. Ausgenommen davon sind Erwähnungen. Das Stummschalten der Benachrichtigungen überschreibt die Benachrichtigungseinstellungen.",
+ "Notifications_Sound_Volume": "Lautstärke des Benachrichtigungstons",
+ "Notify_active_in_this_room": "Aktive Benutzer/innen benachrichtigen",
"Notify_all_in_this_room": "Alle Benutzer in diesem Raum benachrichtigen",
- "Num_Agents": "# Agents",
+ "Num_Agents": "# Agenten",
"Number_of_messages": "Nachrichtenanzahl",
"OAuth_Application": "OAuth-Anwendung",
"OAuth_Applications": "OAuth-Anwendungen",
"Objects": "Objekte",
"Off": "Aus",
"Off_the_record_conversation": "Off-the-record-Gespräche",
- "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record-Gespräche sind für Ihren Browser oder Ihr Gerät nicht verfügbar.",
+ "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record-Gespräche sind für Ihren Browser oder Ihr Gerät nicht verfügbar",
"Office_Hours": "Bürozeiten",
- "Office_Hours_Enabled": "Bürozeiten aktiviert",
+ "Office_hours_enabled": "Bürozeiten aktiviert",
+ "Office_hours_updated": "Bürozeiten aktualisiert",
"Offline": "Offline",
- "Offline_DM_Email": "Sie haben eine private Nachricht von __user__ erhalten.",
+ "Offline_DM_Email": "Du hast eine private Nachricht von __user__ erhalten.",
+ "Offline_Email_Subject_Description": "Sie können die folgenden Platzhalter verwenden:[Site_Name], [Site_URL], [User] & [Room] für den Anwendungsnamen, URL, Benutzernamen und Raumnamen. ",
"Offline_form": "Offline-Formular",
- "Offline_form_unavailable_message": "Nachricht, dass Offline Formular ungültig",
- "Offline_Mention_Email": "Sie wurden von __user__ in #__room__ erwähnt.",
+ "Offline_form_unavailable_message": "Nachricht, dass das Offline-Kontaktformular nicht verfügbar ist",
+ "Offline_Link_Message": "Zur Nachricht",
+ "Offline_Mention_All_Email": "E-Mail-Betreff für \"Alle Erwähnen\"",
+ "Offline_Mention_Email": "Sie wurden von __user__ in #__room__ erwähnt",
"Offline_message": "Offline-Nachricht",
- "Offline_success_message": "Nachricht, dass Offline Nachricht erfolgreich",
+ "Offline_success_message": "Nachricht, dass eine Offline-Nachricht erfolgreich war",
"Offline_unavailable": "offline - nicht verfügbar",
"On": "Ein",
"Online": "Online",
- "Only_you_can_see_this_message": "Nur Sie können diese Nachricht sehen.",
+ "Only_authorized_users_can_write_new_messages": "Nur Authentifizierte Benutzer können neue Nachrichten schreiben",
+ "Only_On_Desktop": "Desktop Modus (senden mit der Eingabeaste nur auf dem Desktop PC)",
+ "Only_you_can_see_this_message": "Nur Sie können diese Nachricht sehen",
"Oops!": "Hoppla",
"Open": "Öffnen",
- "Open_Livechats": "Öffne Livechats",
+ "Open_channel_user_search": "`%s` - Kanal öffnen / Nach Benutzer suchen",
+ "Open_days_of_the_week": "Offene Wochentage",
+ "Open_Livechats": "Offene Livechats",
+ "Open_your_authentication_app_and_enter_the_code": "Öffnen Sie Ihre Authentifizierungs-App und geben Sie den Code ein. Sie können auch einen Ihrer Backup-Codes verwenden",
"Opened": "Geöffnet",
- "Opens_a_channel_group_or_direct_message": "Eröffnet einen Kanal, eine Gruppe oder Direktnachrichten",
+ "Opened_in_a_new_window": "In einem neuem Fenster geöffnet",
+ "Opens_a_channel_group_or_direct_message": "Öffnet einen Kanal, eine Gruppe oder Direktnachrichten",
"optional": "optional",
"or": "oder",
+ "Or_talk_as_anonymous": "Oder schreiben Sie anonym",
"Order": "Auftrag",
+ "Original": "Original",
"OS_Arch": "Architektur",
"OS_Cpus": "CPU-Anzahl",
"OS_Freemem": "Freier Arbeitsspeicher",
@@ -867,56 +1355,79 @@
"OS_Type": "Betriebssystem",
"OS_Uptime": "Systemlaufzeit",
"others": "andere",
- "OTR": "OTR",
- "OTR_is_only_available_when_both_users_are_online": "OTR ist nur möglich, wenn beide Benutzer online sind.",
- "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL, wo die Dateien hochgeladen werden. Die URL wird auch für Downloads verwendet, wenn keine CDN angegeben wird.",
+ "OTR": "OTR (Off-The-Record)",
+ "OTR_is_only_available_when_both_users_are_online": "OTR ist nur möglich, wenn beide Benutzer online sind",
+ "Outgoing_WebHook": "Ausgehender Webhook",
+ "Outgoing_WebHook_Description": "Daten aus Rocket.Chat heraus versenden.",
+ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL, unter der die Dateien hochgeladen werden. Die URL wird auch für Downloads verwendet, wenn kein CDN angegeben wird",
"Page_title": "Seitentitel",
"Page_URL": "Seiten-URL",
"Password": "Passwort",
- "Password_Change_Disabled": "Der Administrator hat das Ändern des Passworts deaktiviert.",
- "Password_changed_successfully": "Das Passwort wurde erfolgreich geändert.",
+ "Password_Change_Disabled": "Der Administrator hat das Ändern des Passworts deaktiviert",
+ "Password_changed_successfully": "Das Passwort wurde erfolgreich geändert",
"Past_Chats": "Vergangene Chats",
"Payload": "Nutzdaten",
"People": "Menschen",
"Permalink": "Permalink",
"Permissions": "Berechtigungen",
- "Pin_Message": "Nachricht fixieren",
- "Pinned_a_message": "hat eine Nachricht angeheftet:",
- "Pinned_Messages": "Fixierte Nachrichten",
- "PiwikAnalytics_siteId_Description": "Die Website-ID zur Identifizierung dieser Website. Beispiel: 17",
- "PiwikAnalytics_url_Description": "Die Piwik URL benötigt ein trailing slash. Beispiel: //piwik.rocket.chat/",
- "Placeholder_for_email_or_username_login_field": "Platzhalter für das Feld der E-Mail-Adresse und des Benutzernamen",
- "Placeholder_for_password_login_field": "Platzhalter für das Feld des Anmeldepassworts",
- "Please_add_a_comment": "Bitte fügen Sie einen Kommentar hinzu",
- "Please_add_a_comment_to_close_the_room": "Bitte fügen Sie einen Kommentar hinzu, um den Raum zu schließen.",
- "Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Chat zu beantworten.",
- "Please_enter_value_for_url": "Bitte geben Sie eine URL für Ihr Profilbild ein.",
- "Please_enter_your_new_password_below": "Bitte geben Sie Ihr neues Passwort ein:",
+ "pin-message": "Nachricht anheften",
+ "pin-message_description": "Berechtigung, eine Nachricht in einem Kanal anzuheften",
+ "Pin_Message": "Nachricht anheften",
+ "Pinned_a_message": "Eine Nachricht wurde angeheftet:",
+ "Pinned_Messages": "Gepinnte Nachrichten",
+ "PiwikAdditionalTrackers": "Zusätzliche Piwik Websites",
+ "PiwikAdditionalTrackers_Description": "Gib hier weitere Piwik Website URLs und SiteIDs in folgendem Format an, wenn Du dieselben Daten in verschiedenen Piwik Instanzen tracken möchten: [ { \"trackerURL\" : \"https://my.piwik.domain2/\", \"siteId\" : 42 }, { \"trackerURL\" : \"https://my.piwik.domain3/\", \"siteId\" : 15 } ]",
+ "PiwikAnalytics_cookieDomain": "Alle Subdomains",
+ "PiwikAnalytics_cookieDomain_Description": "Besucher auf allen Subdomains aufzeichnen",
+ "PiwikAnalytics_domains": "Verberge ausgehende Links",
+ "PiwikAnalytics_domains_Description": "Verberge im Bericht über 'ausgehende Verweise' alle Klicks auf bekannte Alias-URLs. Tragen Sie pro Zeile einen Domainnamen ein, verwenden Sie dabei keine Trennzeichen.",
+ "PiwikAnalytics_prependDomain": "Domain voranstellen",
+ "PiwikAnalytics_prependDomain_Description": "Domain der Seite beim Tracken dem Seitentitel voranstellen",
+ "PiwikAnalytics_siteId_Description": "Die Site-ID zur Identifizierung dieser Website. Beispiel: 17",
+ "PiwikAnalytics_url_Description": "Die Piwik URL benötigt einen abschließenden Slash. Beispiel: //piwik.rocket.chat/",
+ "Placeholder_for_email_or_username_login_field": "Platzhalter für E-Mail-Adresse und den Benutzernamen",
+ "Placeholder_for_password_login_field": "Platzhalter für das Anmeldepassworts",
+ "Please_add_a_comment": "Bitte füge einen Kommentar hinzu",
+ "Please_add_a_comment_to_close_the_room": "Bitte fügen Sie einen Kommentar hinzu, um den Raum zu schließen",
+ "Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Chat zu beantworten",
+ "please_enter_valid_domain": "Bitte eine gültige Domain eingeben",
+ "Please_enter_value_for_url": "Bitte geben Sie eine URL für Ihr Profilbild ein",
+ "Please_enter_your_new_password_below": "Bitte gib neues Passwort ein:",
"Please_enter_your_password": "Bitte Passwort eingeben",
- "Please_fill_a_label": "Bitte Bezeichnung ausfüllen",
- "Please_fill_a_name": "Bitte geben Sie einen Namen ein.",
- "Please_fill_a_username": "Bitte geben Sie einen Benutzernamen ein.",
- "Please_fill_name_and_email": "Bitte geben Sie einen Namen und eine E-Mail-Adresse ein.",
- "Please_select_enabled_yes_or_no": "Bitte wählen Sie eine Option für \"aktiviert\".",
+ "Please_fill_a_label": "Bitte Bezeichner ausfüllen",
+ "Please_fill_a_name": "Bitte geben Sie einen Namen ein",
+ "Please_fill_a_username": "Bitte geben Sie einen Benutzernamen ein",
+ "Please_fill_all_the_information": "Bitte alle Informationen ausfüllen",
+ "Please_fill_name_and_email": "Bitte geben Sie einen Namen und eine E-Mail-Adresse ein",
+ "Please_select_an_user": "Bitte einen Benutzer auswählen",
+ "Please_select_enabled_yes_or_no": "Bitte wählen Sie aus, ob die Option aktiviert ist",
"Please_wait": "Bitte warten",
- "Please_wait_activation": "Bitte warten, der Vorgang kann einige Zeit in Anspruch nehmen.",
- "Please_wait_while_OTR_is_being_established": "Bitte warten Sie, während OTR gestartet wird.",
- "Please_wait_while_your_account_is_being_deleted": "Bitte warten Sie, während Ihr Konto gelöscht wird.",
- "Please_wait_while_your_profile_is_being_saved": "Bitte warten Sie, während ihr Profil gespeichert wird...",
+ "Please_wait_activation": "Bitte warten, das kann einige Zeit in Anspruch nehmen",
+ "Please_wait_while_OTR_is_being_established": "Bitte warten Sie, während OTR gestartet wird",
+ "Please_wait_while_your_account_is_being_deleted": "Bitte warten Sie, während Ihr Konto gelöscht wird",
+ "Please_wait_while_your_profile_is_being_saved": "Bitte warten Sie, während Ihr Profil gespeichert wird",
"Port": "Port",
+ "post-readonly": "Schreibgeschützt posten",
+ "post-readonly_description": "Berechtigung, in einen schreibgeschützten Kanal zu posten",
"Post_as": "Verschicken als",
"Post_to_Channel": "Im Kanal veröffentlichen",
"Post_to_s_as_s": "Versenden an %s als %s ",
"Preferences": "Einstellungen",
- "Preferences_saved": "Die Einstellungen wurden gespeichert.",
+ "Preferences_saved": "Die Einstellungen wurden gespeichert",
+ "preview-c-room": "Vorschau für öffentliche Kanäle",
+ "preview-c-room_description": "Berechtigung, den Inhalt eines öffentlichen Kanals einzusehen, bevor diesem beigetreten wird",
"Privacy": "Datenschutz",
- "Private": "privat",
- "Private_Group": "Private Gruppe",
- "Private_Groups": "Private Gruppen",
- "Private_Groups_list": "Liste aller privaten Gruppen",
+ "Private": "Privat",
+ "Private_Channel": "Privater Kanal",
+ "Private_Group": "Privater Kanal",
+ "Private_Groups": "Private Kanäle",
+ "Private_Groups_list": "Liste aller privaten Kanäle",
"Profile": "Profil",
+ "Profile_details": "Profildetails",
+ "Profile_picture": "Profilbild",
"Profile_saved_successfully": "Das Profil wurde erfolgreich gespeichert",
- "Public": "öffentlich",
+ "Public": "Öffentlich",
+ "Public_Channel": "Öffentlicher Kanal",
"Push": "Push-Nachrichten",
"Push_apn_cert": "APN-Cert",
"Push_apn_dev_cert": "APN-Dev-Cert",
@@ -931,144 +1442,225 @@
"Push_gcm_api_key": "GCM-API-Key",
"Push_gcm_project_number": "GCM-Projektnummer",
"Push_production": "Produktion",
- "Push_show_message": "Nachricht in der Benachrichtigung zeigen",
- "Push_show_username_room": "Kanal/Gruppe/Benutzername in der Benachrichtigung zeigen",
+ "Push_show_message": "Nachricht in der Benachrichtigung anzeigen",
+ "Push_show_username_room": "Kanal/Gruppe/Benutzername in der Benachrichtigung anzeigen",
"Push_test_push": "Test",
"Query": "Abfrage",
- "Query_description": "Zusätzliche Bedingungen für die Bestimmung, an welche Benutzer die E-Mails gesendet werden sollen. Ausgetragene Benutzer werden automatisch aus der Abfrage entfernt. Es muss ein gültiger JSON sein. Beispiel: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
+ "Query_description": "Zusätzliche Einschränkung, an welche Benutzer die E-Mail gesendet werden soll. Benutzer, die nicht benachrichtigt werden wollen, werden automatisch aus der Abfrage entfernt. Es muss ein gültiges JSON sein. Beispiel: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
"Queue": "Warteschlange",
- "quote": "Zitat",
+ "quote": "zitieren",
"Quote": "Zitieren",
"Random": "Zufällig",
+ "RDStation_Token": "RD Station Token",
+ "React_when_read_only": "Reaktionen erlauben",
+ "React_when_read_only_changed_successfully": "Reaktionen erlauben, wenn ein Kanal schreibgeschützt wurde",
"Reacted_with": "Reagierte mit",
"Reactions": "Reaktionen",
+ "Read_only": "Schreibgeschützt",
+ "Read_only_changed_successfully": "Erfolgreich schreibgeschützt",
+ "Read_only_channel": "Kanal schreibgeschützt",
+ "Read_only_group": "Schreibgeschützte Gruppe",
"Record": "Aufnehmen",
"Redirect_URI": "Weiterleitungs-URL",
"Refresh_keys": "Schlüssel aktualisieren",
- "Refresh_your_page_after_install_to_enable_screen_sharing": "Aktualisieren Sie die Seite nach der Installation, um die Bildschirmübertragung zu aktivieren.",
+ "Refresh_oauth_services": "OAuth Services aktualisieren",
+ "Refresh_your_page_after_install_to_enable_screen_sharing": "Aktualisieren Sie die Seite nach der Installation, um die Bildschirmübertragung zu aktivieren",
+ "Regenerate_codes": "Codes neu generieren",
"Register": "Neues Konto registrieren",
- "Registration_Succeeded": "Ihre Registrierung war erfolgreich.",
- "Release": "Veröffentlichung",
+ "Registration": "Registrierung",
+ "Registration_Succeeded": "Ihre Registrierung war erfolgreich",
+ "Registration_via_Admin": "Registrierung durch den Administrator",
+ "Regular_Expressions": "Reguläre Ausdrücke",
+ "Release": "Version",
+ "Reload": "Neu laden",
"Remove": "Entfernen",
- "Remove_Admin": "Admin entfernen",
+ "remove-user": "Benutzer entfernen",
+ "remove-user_description": "Berechtigung einen Benutzter aus einem Raum zu entfernen",
+ "Remove_Admin": "Administrator entfernen",
+ "Remove_as_leader": "Als Diskussionsleiter entfernen",
"Remove_as_moderator": "Moderatorenrechte entfernen",
- "Remove_as_owner": "als Besitzer entfernen",
+ "Remove_as_owner": "Als Besitzer entfernen",
"Remove_custom_oauth": "OAuth-Konto entfernen",
"Remove_from_room": "Aus dem Raum entfernen",
+ "Remove_last_admin": "Entferne den letzen Administrator",
"Remove_someone_from_room": "Jemanden aus dem Raum entfernen",
"Removed": "Entfernt",
+ "Reply": "Antwort",
"Report_Abuse": "Missbrauch melden",
"Report_exclamation_mark": "Melden!",
"Report_sent": "Bericht gesendet",
"Report_this_message_question_mark": "Diese Nachricht melden?",
+ "Reporting": "Berichtswesen",
"Require_password_change": "Passwortänderung verlangen",
"Resend_verification_email": "Bestätigungsmail erneut versenden",
"Reset": "Zurücksetzen",
"Reset_password": "Passwort zurücksetzen",
+ "Reset_section_settings": "Abschnittseinstellungen zurücksetzen",
"Restart": "Neustart",
- "Restart_the_server": "Server neustarten",
+ "Restart_the_server": "Server neu starten",
+ "Retry_Count": "Anzahl der Wiederholungsversuche",
"Role": "Rolle",
"Role_Editing": "Rolle bearbeiten",
- "Role_removed": "Die Rolle wurde entfernt.",
+ "Role_removed": "Die Rolle wurde entfernt",
"Room": "Raum",
+ "Room_announcement_changed_successfully": "Die Ankündigung des Raums wurde geändert",
"Room_archivation_state": "Status",
- "Room_archivation_state_false": "aktiv",
- "Room_archivation_state_true": "archiviert",
- "Room_archived": "Der Raum wurde archiviert.",
- "room_changed_description": "Raumbeschreibung geändert auf __room_description__ von __user_by__ ",
- "room_changed_privacy": "Der Raum wurde von __user_by__ zum/r __room_type__ geändert.",
- "room_changed_topic": "Das Thema des Raums wurde von __user_by__ zu __room_topic__ geändert.",
+ "Room_archivation_state_false": "Aktiv",
+ "Room_archivation_state_true": "Archiviert",
+ "Room_archived": "Der Raum wurde archiviert",
+ "room_changed_announcement": "Ankündigung des Raums wurde von __user_by__ zu __room_announcement__ geändert",
+ "room_changed_description": "Raumbeschreibung wurde von von __user_by__ zu __room_description__ geändert",
+ "room_changed_privacy": "Der Raum wurde von __user_by__ zum/r __room_type__ geändert",
+ "room_changed_topic": "Das Thema des Raums wurde von __user_by__ zu __room_topic__ geändert",
+ "Room_default_change_to_private_will_be_default_no_more": "Das ist ein Standardkanal. Die Änderung zu einer privaten Gruppe führt dazu, dass er dies nicht mehr ist. Wollen Sie fortfahren?",
"Room_description_changed_successfully": "Raumbeschreibung erfolgreich geändert",
- "Room_has_been_deleted": "Der Raum wurde gelöscht.",
- "Room_Info": "Raum",
- "Room_name_changed": "__user_by__ hat den Raumnamen zu __room_name__ geändert.",
- "Room_name_changed_successfully": "Der Raumname wurde erfolgreich geändert.",
- "Room_not_found": "Der Raum konnte nicht gefunden werden.",
- "Room_topic_changed_successfully": "Das Thema des Raums wurde erfolgreich geändert.",
- "Room_type_changed_successfully": "Der Raumtyp wurde erfolgreich geändert.",
- "Room_unarchived": "Der Raum wurde wiederhergestellt.",
+ "Room_has_been_archived": "Der Raum wurde archiviert",
+ "Room_has_been_deleted": "Der Raum wurde gelöscht",
+ "Room_has_been_unarchived": "Der Raum wurde aus dem Archiv geholt",
+ "Room_Info": "Rauminformation",
+ "room_is_blocked": "Der Raum ist blockiert",
+ "room_is_read_only": "Der Raum ist schreibgeschützt",
+ "room_name": "Raumname",
+ "Room_name_changed": "__user_by__ hat den Raumnamen zu __room_name__ geändert.",
+ "Room_name_changed_successfully": "Der Raumname wurde erfolgreich geändert",
+ "Room_not_found": "Raum konnte nicht gefunden werden",
+ "Room_password_changed_successfully": "Das Raum-Passwort wurde erfolgreich geändert",
+ "Room_topic_changed_successfully": "Das Thema des Raums wurde erfolgreich geändert",
+ "Room_type_changed_successfully": "Der Raumtyp wurde erfolgreich geändert",
+ "Room_type_of_default_rooms_cant_be_changed": "Das ist ein Standardraum, dessen Typ nicht geändert werden kann. Bitte sprechen Sie mit Ihrem Administrator",
+ "Room_unarchived": "Der Raum wurde aus dem Archiv geholt",
"Room_uploaded_file_list": "Dateien",
- "Room_uploaded_file_list_empty": "Es wurden noch keine Dateien hochgeladen.",
+ "Room_uploaded_file_list_empty": "Es wurden noch keine Dateien hochgeladen",
"Rooms": "Räume",
+ "run-import": "Import ausführen",
+ "run-import_description": "Berechtigung, Importe auszuführen",
+ "run-migration": "Migration ausführen",
+ "run-migration_description": "Berechtigung, Migrationen auszuführen",
"Running_Instances": "Laufende Instanzen",
"S_new_messages_since_s": "%s neue Nachrichten seit %s",
+ "Same_Style_For_Mentions": "Gleicher Stil für Erwähnungen",
"SAML": "SAML",
"SAML_Custom_Cert": "Benutzerdefiniertes Zertifikat",
- "SAML_Custom_Entry_point": "Einsprungspunkt",
+ "SAML_Custom_Entry_point": "Einstiegspunkt",
"SAML_Custom_Generate_Username": "Benutzernamen generieren",
+ "SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO Redirect URL",
"SAML_Custom_Issuer": "Benutzerdefinierter Aussteller",
+ "SAML_Custom_Logout_Behaviour": "Logout-Verhalten",
+ "SAML_Custom_Logout_Behaviour_Terminate_SAML_Session": "SAML-Session beenden",
+ "SAML_Custom_Logout_Behaviour_End_Only_RocketChat": "Nur von Rocket.Chat abmelden",
+ "SAML_Custom_Private_Key": "Privater Schlüssel",
"SAML_Custom_Provider": "Benutzerdefinierter Provider",
+ "SAML_Custom_Public_Cert": "Öffentliches Zertifikat",
+ "Sandstorm_Powerbox_Share": "Als Sandstorm Grain teilen",
"Saturday": "Samstag",
"Save": "Speichern",
+ "save-others-livechat-room-info": "Livechat-Informationen anderer Chats speichern",
+ "save-others-livechat-room-info_description": "Berechtigung, die Livechat-Informationen anderer Konversationen zu speichern",
"Save_changes": "Änderungen speichern",
"Save_Mobile_Bandwidth": "Mobiles Datenvolumen sparen",
- "Save_to_enable_this_action": "Speichern Sie die Angaben, um die Testverbindung zu ermöglichen.",
+ "Save_to_enable_this_action": "Speichern Sie, um die Aktion zu aktivieren",
"Saved": "Gespeichert",
"Saving": "Speichern",
+ "Scan_QR_code": "Scanne den QR-Code mit einer Authenticator-App (wie Google Authenticator, Authy oder Duo). Danach wird ein sechsstelliger Code angezeigt, den Sie unten eingeben müssen.",
+ "Scan_QR_code_alternative_s": "Wenn Du den QR-code nicht einscannen kannst, kannst Du ihn alternativ manuell eingeben: __code__",
"Scope": "Umfang",
"Screen_Share": "Bildschirmübertragung",
- "Script_Enabled": "Das Script ist aktiviert.",
+ "Script_Enabled": "Das Script wurde aktiviert",
"Search": "Suche",
- "Search_by_username": "Anhand des Nutzernamen suchen",
+ "Search_by_username": "Anhand des Nutzernamens suchen",
"Search_Messages": "Nachrichten durchsuchen",
- "Search_Private_Groups": "Durchsuche private Gruppen",
+ "Search_Private_Groups": "Durchsuche private Kanäle",
"seconds": "Sekunden",
- "Secret_token": "Secret token",
- "Select_a_department": "Wählen Sie eine Abteilung",
- "Select_a_user": "Wählen Sie einen Benutzer",
+ "Secret_token": "Geheimes Token",
+ "Security": "Sicherheit",
+ "Select_a_department": "Wähle eine Abteilung",
+ "Select_a_user": "Wähle einen Benutzer",
"Select_an_avatar": "Profilbild auswählen",
- "Select_file": "Datei wählen",
- "Select_service_to_login": "Wählen Sie einen Dienst zum Anmelden aus, um ein Bild auszuwählen oder ein Bild direkt von Ihrem Computer hochzuladen.",
+ "Select_file": "Datei auswählen",
+ "Select_role": "Eine Rolle auswählen",
+ "Select_service_to_login": "Wählen Sie einen Dienst zum Synchronisieren Ihres Profilbildes aus oder laden Sie ein Bild direkt von Ihrem Computer hoch ",
"Select_user": "Benutzer auswählen",
"Select_users": "Benutzer auswählen",
"Selected_agents": "Ausgewählte Agenten",
"Send": "Senden",
"Send_a_message": "Eine Nachricht schicken",
- "Send_a_test_mail_to_my_user": "Eine Test-E-Mail an die Benutzer senden",
+ "Send_a_test_mail_to_my_user": "Eine Test-E-Mail an mich senden",
"Send_a_test_push_to_my_user": "Eine Test-Push-Nachricht an mich senden",
"Send_confirmation_email": "Bestätigungsmail versenden",
- "Send_data_into_RocketChat_in_realtime": "Daten in Rocket.Chat in Echtzeit senden.",
+ "Send_data_into_RocketChat_in_realtime": "Daten an Rocket.Chat in Echtzeit senden",
"Send_email": "E-Mail senden",
"Send_invitation_email": "Einladung per E-Mail senden",
- "Send_invitation_email_error": "Sie haben keine gültige E-Mail-Adresse angegeben.",
- "Send_invitation_email_info": "Sie können mehrere Einladungen per E-Mail gleichzeitig absenden.",
- "Send_invitation_email_success": "Sie haben erfolgreich eine Einladung an folgende E-Mail-Adressen versendet:",
- "Send_request_on_chat_close": "Anfrage senden, um Chatraum zu schließen.",
- "Send_request_on_offline_messages": "Anfrage zu offline Nachrichten stellen",
- "Send_Test": "Sende Test",
+ "Send_invitation_email_error": "Du hast keine gültige E-Mail-Adresse angegeben.",
+ "Send_invitation_email_info": "Sie können mehrere Einladungen per E-Mail gleichzeitig absenden",
+ "Send_invitation_email_success": "Sie haben eine Einladung an folgende E-Mail-Adressen versendet:",
+ "Send_request_on_chat_close": "Nach dem Schließen des Chatraums einen Webhook anstoßen",
+ "Send_request_on_offline_messages": "Webhook bei Offline-Nachrichten anstoßen",
+ "Send_Test": "Test senden",
"Send_welcome_email": "Willkommens-E-Mail senden",
- "Send_your_JSON_payloads_to_this_URL": "Senden Sie Ihre JSON-Nutzlasten an diese URL.",
+ "Send_your_JSON_payloads_to_this_URL": "Senden Sie Ihre JSON-Nutzlasten an diese URL",
"Sending": "Senden...",
+ "Served_By": "Bedient von",
"Service": "Service",
+ "Service_account_key": "Service Account Schlüssel",
+ "set-moderator": "Moderator ernennen",
+ "set-moderator_description": "Berechtigung, andere Benutzer zum Moderator eines Kanals zu ernennen",
+ "set-owner": "Eigentümer ernennen",
+ "set-owner_description": "Berechtigung, andere Benutzer zum Eigentümer eines Kanals zu ernennen",
+ "set-react-when-readonly": "Reaktionen in einem schreibgeschützten Kanal erlauben",
+ "set-react-when-readonly_description": "Berechtigung, Reaktionen in einem schreibgeschützten Kanal zu erlauben",
+ "set-readonly": "Mit Schreibschutz versehem",
+ "set-readonly_description": "Berechtigung, einen Raum schreibgeschützt zu machen",
+ "Set_as_leader": "Zum Diskussionsleiter ernennen",
"Set_as_moderator": "Zum Moderator ernennen",
- "Set_as_owner": "zum Besitzer machen",
+ "Set_as_owner": "Zum Besitzer machen",
"Settings": "Einstellungen",
- "Settings_updated": "Die Einstellungen wurden aktualisiert.",
+ "Settings_updated": "Die Einstellungen wurden aktualisiert",
"Share_Location_Title": "Standort teilen?",
"Shared_Location": "Standort geteilt",
- "Should_be_a_URL_of_an_image": "Dies soll die URL des Bildes sein.",
- "Should_exists_a_user_with_this_username": "Der Benutzer muss bereits vorhanden sein.",
+ "Should_be_a_URL_of_an_image": "Sollte die URL eines Bildes sein",
+ "Should_exists_a_user_with_this_username": "Der Benutzer muss bereits vorhanden sein",
"Show_all": "Alle Nutzer zeigen",
- "Show_more": "Mehr Nutzer zeigen",
+ "Show_more": "Weitere Nutzer zeigen",
"show_offline_users": "Zeige Benutzer an, die offline sind",
- "Show_only_online": "Nur Online-Nutzer zeigen",
- "Show_preregistration_form": "Vorregistrierungsformular zeigen",
+ "Show_on_registration_page": "Auf der Registrierungsseite anzeigen",
+ "Show_only_online": "Nur Online-Benutzer anzeigen",
+ "Show_preregistration_form": "Vorregistrierungsformular anzeigen",
+ "Show_queue_list_to_all_agents": "Die Warteschlange allen Agenten anzeigen",
+ "Show_the_keyboard_shortcut_list": "Zeige die Liste der Keyboard-Shortcuts",
"Showing_archived_results": "%s archivierte Räume",
- "Showing_online_users": "__total_showing__ von __total__ Nutzer angezeigt",
+ "Showing_online_users": "__total_showing__ von __total__ Benutzern werden angezeigt",
"Showing_results": "%s Ergebnisse
",
+ "Sidebar_list_mode": "Sidebar-Kanallisten-Modus",
+ "Sign_in_to_start_talking": "Anmelden, um mit dem Chatten zu beginnen",
"since_creation": "seit %s",
"Site_Name": "Seitenname",
"Site_Url": "Website-URL",
"Site_Url_Description": "Beispiel: https://chat.domain.com/",
"Skip": "Überspringen",
+ "SlackBridge_error": "SlackBridge hat beim Import der Nachrichten einen Fehler gemeldet. %s: %s",
+ "SlackBridge_finish": "SlackBridge hat den Import aller Nachrichten um %s beendet. Bitte laden Sie die Seite neu, um sie einzusehen.",
+ "SlackBridge_Out_All": "Alles an SlackBridge senden",
+ "SlackBridge_Out_All_Description": "Nachrichten aller Kanäle, die in Slack existieren und denen der Bot beigetreten ist senden",
+ "SlackBridge_Out_Channels": "Kanäle für SlackBridge",
+ "SlackBridge_Out_Channels_Description": "Auswählen, welche Kanäle an Slack gesendet werden",
+ "SlackBridge_Out_Enabled": "SlackBridge Ausgang",
+ "SlackBridge_Out_Enabled_Description": "Ob die SlackBridge auch Nachrichten aus Rocket.Chat an Slack zurücksenden soll",
+ "SlackBridge_start": "@%s hat um `#%s` einen SlackBridge-Import gestartet. Wir werden Sie darüber informieren, sobald dieser beendet ist.",
"Slash_Gimme_Description": "Zeigt ༼ つ ◕_◕ ༽つ vor Ihrer Nachricht",
"Slash_LennyFace_Description": "Zeigt ( ͡° ͜ʖ ͡°) nach Ihrer Nachricht",
"Slash_Shrug_Description": "Zeigt ¯\\_(ツ)_/¯ am Ende der Nachricht",
"Slash_Tableflip_Description": "Zeigt (╯°□°)╯︵ ┻━┻",
"Slash_TableUnflip_Description": "Zeigt ┬─┬ ノ( ゜-゜ノ)",
- "Slash_Topic_Description": "Thema setzen",
- "Slash_Topic_Params": "Themennachricht",
- "Smarsh_Enabled": "Smarsh aktiviert",
+ "Slash_Topic_Description": "Thema definieren",
+ "Slash_Topic_Params": "Themen-Nachricht",
+ "Smarsh_Email": "Smarsh E-Mail",
+ "Smarsh_Email_Description": "Smarsh E-Mail-Adresse, an die die .eml-Datei gesendet werden soll.",
+ "Smarsh_Enabled": "Smarsh",
+ "Smarsh_Enabled_Description": "Ob der Smarsh-E-Mail-Konnektor aktiviert ist. Erfordert, dass \"Absender-E-Mail\" unter E-Mail -> SMTP konfiguriert ist.",
+ "Smarsh_Interval": "Smarsh-Intervall",
+ "Smarsh_Interval_Description": "Die Wartezeit, bevor die Konversation versendet wird. Erfordert, dass \"Absender-E-Mail\" unter E-Mail -> SMTP konfiguriert ist.",
+ "Smarsh_MissingEmail_Email": "Fehlende E-Mail-Adresse",
+ "Smarsh_MissingEmail_Email_Description": "Eine E-Mail-Adresse, die bei Benutzern ohne E-Mail-Adresse (üblicherweise Bots) angezeigt werden soll.",
"Smileys_and_People": "Gesichter & Personen",
"SMS_Enabled": "SMS aktiviert",
"SMTP": "SMTP",
@@ -1077,192 +1669,334 @@
"SMTP_Port": "SMTP-Port",
"SMTP_Test_Button": "SMTP-Einstellungen testen",
"SMTP_Username": "SMTP-Benutzername",
+ "snippet-message": "Nachrichten-Snippet",
+ "snippet-message_description": "Berechtigung, ein Nachrichten-Snippet zu erstellen",
+ "Snippet_Added": "Erstellt am %s",
+ "Snippet_Messages": "Nachrichten-Snippets",
+ "Snippeted_a_message": "Ein Snippet wurde erstellt: __snippetLink__",
+ "Sort_by_activity": "Nach Aktivität sortieren",
"Sound": "Ton",
+ "Sound_File_mp3": "Ton-Datei (.mp3)",
+ "Split_by_categories": "Nach Kategorien aufteilen",
"SSL": "SSL",
- "Star_Message": "Nachricht markieren",
- "Starred_Messages": "Markierte Nachrichten",
+ "Star_Message": "Nachricht favorisieren",
+ "Starred_Messages": "Favorisierte Nachrichten",
+ "Start": "Starten",
"Start_audio_call": "Anruf starten",
"Start_Chat": "Chat beginnen",
"Start_of_conversation": "Beginn des Gesprächs",
- "Start_OTR": "OTR beginnen",
+ "Start_OTR": "OTR starten",
"Start_video_call": "Videoanruf starten",
- "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Starten Sie mit %s für Nutzer oder %s für Kanäle. Beispiel: %s oder %s",
+ "Start_video_conference": "Eine Video-Konferenz starten?",
+ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Starte mit %s für Nutzer oder %s für Kanäle. Beispiel: %s oder %s",
"Started_At": "Gestartet um",
+ "Started_a_video_call": "Ein Video-Anruf wurde gestartet",
"Statistics": "Statistiken",
"Statistics_reporting": "Sende Statistiken an Rocket.Chat",
- "Statistics_reporting_Description": "Mit dem Senden Ihrer Statistiken helfen Sie uns herauszufinden wie viele Instanzen von Rocket.Chat eingesetzt werden und außerdem wie gut sich das System verhält, so können wir es weiter verbessern. Es werden keine Benutzerinformationen übertragen und die erhaltenen Daten werden vertraulich behandelt.",
+ "Statistics_reporting_Description": "Mit dem Senden Ihrer Statistiken helfen Sie uns herauszufinden, wie viele Instanzen von Rocket.Chat eingesetzt werden und wie gut sich das System verhält. So können wir es weiter verbessern. Es werden keine Benutzerinformationen übertragen und die erhaltenen Daten werden vertraulich behandelt.",
"Stats_Active_Users": "Aktive Benutzer",
"Stats_Avg_Channel_Users": "Durchschnittliche Benutzeranzahl pro Kanal",
- "Stats_Avg_Private_Group_Users": "Durchschnittliche Benutzeranzahl in privaten Gruppen",
+ "Stats_Avg_Private_Group_Users": "Durchschnittliche Benutzeranzahl in privaten Kanälen",
"Stats_Away_Users": "Abwesende Benutzer",
"Stats_Max_Room_Users": "Maximale Benutzeranzahl eines Raums",
"Stats_Non_Active_Users": "Nicht aktive Benutzer",
- "Stats_Offline_Users": "Benutzer offline",
- "Stats_Online_Users": "Benutzer online",
+ "Stats_Offline_Users": "Offline-Benutzer",
+ "Stats_Online_Users": "Online-Benutzer",
"Stats_Total_Channels": "Anzahl der Kanäle",
"Stats_Total_Direct_Messages": "Anzahl der privaten Nachrichtenräume",
+ "Stats_Total_Livechat_Rooms": "Gesamtzahl der Livechat-Räume",
"Stats_Total_Messages": "Anzahl aller Nachrichten",
- "Stats_Total_Private_Groups": "Anzahl der privaten Gruppen",
+ "Stats_Total_Messages_Channel": "Gesamtanzahl der Nachrichten in Kanälen",
+ "Stats_Total_Messages_Direct": "Gesamtanzahl der Nachrichten in Direktnachrichten",
+ "Stats_Total_Messages_Livechat": "Gesamtanzahl der Nachrichten in Livechats",
+ "Stats_Total_Messages_PrivateGroup": "Gesamtanzahl der Nachrichten in privaten Gruppen",
+ "Stats_Total_Private_Groups": "Anzahl der privaten Kanäle",
"Stats_Total_Rooms": "Anzahl der Räume",
"Stats_Total_Users": "Anzahl der Benutzer",
+ "Status": "Status",
"Stop_Recording": "Aufnahme stoppen",
+ "Stream_Cast": "Stream Cast",
+ "Stream_Cast_Address": "Stream Cast Adresse",
+ "Stream_Cast_Address_Description": "IP oder Host Ihres zentralen Stream Cast Servers inkl. Port, bspw. `192.168.1.1:3000` oder `localhost:4000`",
"strike": "durchgestrichen",
"Subject": "Betreff",
- "Submit": "Abschicken",
- "Success": "Dieser Vorgang war erfolgreich.",
+ "Submit": "Abssenden",
+ "Success": "Dieser Vorgang war erfolgreich",
"Success_message": "Erfolgsnachricht",
"Sunday": "Sonntag",
"Survey": "Umfrage",
- "Survey_instructions": "Bewerten Sie jede Frage nach Ihrer Zufriedenheit. 1 bedeutet, dass Sie völlig unzufrieden sind und 5 bedeutet, dass Sie vollständig zufrieden sind.",
+ "Survey_instructions": "Bewerten Sie jede Frage nach Ihrer Zufriedenheit. 1 bedeutet, dass Sie völlig frustriert sind. 5 bedeutet, dass Sie vollständig zufrieden sind.",
"Symbols": "Symbole",
- "Sync_success": "Die Synchronisierung war erfolgreich.",
+ "Sync_success": "Die Synchronisierung war erfolgreich",
+ "Sync_in_progress": "Eine Synchronisierung wird durchgeführt",
"Sync_Users": "Benutzer synchronisieren",
+ "System_messages": "Systemnachrichten",
"Tag": "Tag",
- "Test_Connection": "Testverbindung",
+ "Take_it": "Übernehmen",
+ "TargetRoom": "Ziel-Raum",
+ "TargetRoom_Description": "Der Raum, an den Nachrichten gesendet werden, wenn dieses Ereignis eintritt. Nur ein existierender Raum kann angegeben werden.",
+ "Team": "Team",
+ "Test_Connection": "Teste die Verbindung",
"Test_Desktop_Notifications": "Desktop-Benachrichtigungen testen",
"Thank_you_exclamation_mark": "Vielen Dank!",
- "Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung.",
- "The_application_name_is_required": "Es muss ein Name für diese Anwendung angegeben werden.",
- "The_channel_name_is_required": "Ein Name für den Kanal muss angegeben werden.",
- "The_emails_are_being_sent": "Die E-Mails werden gesendet.",
- "The_field_is_required": "Das Feld %s ist erforderlich.",
+ "Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung",
+ "The_application_name_is_required": "Es muss ein Name für diese Anwendung angegeben werden",
+ "The_channel_name_is_required": "Ein Name für den Kanal muss angegeben werden",
+ "The_emails_are_being_sent": "E-Mails werden gesendet",
+ "The_field_is_required": "Das Feld %s ist erforderlich",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Die automatische Skalierung der Bilder funktioniert nicht, da ImageMagick oder GraphicsMagick nicht auf dem Server installiert sind.",
- "The_redirectUri_is_required": "Es muss eine Weiterleitung-URL angegeben werden.",
+ "The_redirectUri_is_required": "Es muss eine Weiterleitungs-URL angegeben werden.",
"The_server_will_restart_in_s_seconds": "Der Server wird in %s Sekunden neu gestartet",
- "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Die Einstellung %s wurde zu %s konfiguriert und Sie greifen von %s zu!",
- "The_user_will_be_removed_from_s": "Der Benutzer wird von %s entfernt.",
- "The_user_wont_be_able_to_type_in_s": "Der Benutzer kann nicht mehr in %s schreiben.",
- "Theme": "Theme",
+ "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Die Einstellung %s wurde zu %s konfiguriert. Sie greifen von %s zu!",
+ "The_user_will_be_removed_from_s": "Der Benutzer wird aus %s entfernt",
+ "The_user_wont_be_able_to_type_in_s": "Der Benutzer kann nicht mehr in %s schreiben",
+ "Theme": "Visuelles Theme",
+ "theme-color-component-color": "Komponentenfarbe",
"theme-color-content-background-color": "Hintergrundfarbe des Inhalts",
+ "theme-color-custom-scrollbar-color": "Benutzerdefinierte Farbe der Scrollbar",
+ "theme-color-error-color": "Farbe für Fehler",
+ "theme-color-info-font-color": "Schriftfarbe von Informationen",
+ "theme-color-link-font-color": "Schriftfarbe von Links",
+ "theme-color-pending-color": "Farbe für Ausstehendes",
+ "theme-color-primary-action-color": "Primäre Aktionsfarbe",
"theme-color-primary-background-color": "Primäre Hintergrundfarbe ",
"theme-color-primary-font-color": "Primäre Schriftfarbe",
+ "theme-color-secondary-action-color": "Sekundäre Aktionsfarbe",
"theme-color-secondary-background-color": "Sekundäre Hintergrundfarbe",
"theme-color-secondary-font-color": "Sekundäre Schriftfarbe",
- "theme-color-tertiary-background-color": "Tertiäre Hintergrundfarbe ",
- "theme-color-tertiary-font-color": "Tertiäre Schriftfarbe",
- "theme-color-link-font-color": "Schriftfarbe des Links",
- "theme-color-info-font-color": "Schriftfarbe von Informationen",
- "theme-color-custom-scrollbar-color": "Benutzerdefinierte Farbe der Scrollbar",
+ "theme-color-selection-color": "Auswahlfarbe",
"theme-color-status-away": "Farbe des Status \"abwesend\"",
"theme-color-status-busy": "Farbe des Status \"beschäftigt\"",
"theme-color-status-offline": "Farbe des Status \"offline\"\n",
"theme-color-status-online": "Farbe des Status \"online\"",
+ "theme-color-success-color": "Farbe für Erfolg",
+ "theme-color-tertiary-background-color": "Tertiäre Hintergrundfarbe ",
+ "theme-color-tertiary-font-color": "Tertiäre Schriftfarbe",
+ "theme-color-transparent-dark": "Transparent dunkel",
+ "theme-color-transparent-darker": "Transparent dunkler",
+ "theme-color-transparent-light": "Transparent heller",
+ "theme-color-transparent-lighter": "Transparent hell",
+ "theme-color-transparent-lightest": "Transparent am hellsten",
"theme-color-unread-notification-color": "Farbe von ungelesenen Benachrichtigungen",
+ "theme-color-rc-color-error": "Fehler",
+ "theme-color-rc-color-error-light": "Fehler (hell)",
+ "theme-color-rc-color-alert": "Hinweis",
+ "theme-color-rc-color-alert-light": "Hinweis (hell)",
+ "theme-color-rc-color-success": "Erfolg",
+ "theme-color-rc-color-success-light": "Erfolg (hell)",
+ "theme-color-rc-color-button-primary": "Button Primär",
+ "theme-color-rc-color-button-primary-light": "Button Primär (hell)",
+ "theme-color-rc-color-primary": "Primär",
+ "theme-color-rc-color-primary-darkest": "Primär (am dunkelsten)",
+ "theme-color-rc-color-primary-dark": "Primär (dunkel)",
+ "theme-color-rc-color-primary-light": "Primär (hell)",
+ "theme-color-rc-color-primary-light-medium": "Primär (mittelhell)",
+ "theme-color-rc-color-primary-lightest": "Primär (am hellsten)",
+ "theme-color-rc-color-content": "Inhalt",
"theme-custom-css": "Benutzerdefiniertes CSS",
- "There_are_no_agents_added_to_this_department_yet": "Es wurden bisher keine Agenten zu dieser Abteilung hinzugefügt.",
- "There_are_no_integrations": "Es sind keine Integrationen vorhanden.",
- "There_are_no_users_in_this_role": "Es sind dieser Rolle keine Benutzer zugeordnet.",
- "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Diese E-Mail wurde bereits verschickt, aber noch nicht bestätigt. Bitte ändern Sie Ihr Passwort.",
- "This_is_a_desktop_notification": "Das ist eine Desktop-Benachrichtigung.",
- "This_is_a_push_test_messsage": "Dies ist eine Test-Push-Nachricht.",
+ "theme-font-body-font-family": "Schrift-Familie für den Textkörper",
+ "There_are_no_agents_added_to_this_department_yet": "Es wurden bisher keine Agenten zu dieser Abteilung hinzugefügt",
+ "There_are_no_applications": "Bisher wurden keine oAuth Anwendungen hinzugefügt.",
+ "There_are_no_integrations": "Es sind keine Integrationen vorhanden",
+ "There_are_no_users_in_this_role": "Es sind dieser Rolle keine Benutzer zugeordnet",
+ "This_conversation_is_already_closed": "Die Unterhaltung wurde bereits beendet",
+ "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Die E-Mail wurde bereits verschickt, aber noch nicht bestätigt. Bitte ändern Sie Ihr Passwort",
+ "This_is_a_desktop_notification": "Das ist eine Desktop-Benachrichtigung",
+ "This_is_a_push_test_messsage": "Dies ist eine Test-Push-Nachricht",
"This_room_has_been_archived_by__username_": "Dieser Raum wurde von __username__ archiviert",
- "This_room_has_been_unarchived_by__username_": "Dieser Raum wurde von __username__ unarchiviert",
+ "This_room_has_been_unarchived_by__username_": "Dieser Raum wurde von __username__ aus dem Archiv geholt",
"Thursday": "Donnerstag",
"Time_in_seconds": "Zeit in Sekunden",
"Title": "Titel",
"Title_bar_color": "Farbe der Titelleiste",
- "Title_bar_color_offline": "Titelbarfarbe ist offline.",
- "Title_offline": "Titel ist offline.",
- "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um den Rocket.Chat-LiveChat auf Ihrer Webseite zu installieren, kopieren und fügen Sie den Code über den letzten </body> -Tag Ihrer Seite ein.",
- "to_see_more_details_on_how_to_integrate": "um weitere Informationen zur Integration zu sehen.",
- "To_users": "An die Benutzer",
+ "Title_bar_color_offline": "Farbe der Offline-Titelleiste",
+ "Title_offline": "Titel wenn offline",
+ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um den Rocket.Chat-LiveChat auf Ihrer Webseite zu installieren, kopieren und fügen Sie den Code oberhalb des letzten </body> -Tags Ihrer Seite ein.",
+ "to_see_more_details_on_how_to_integrate": "um weitere Informationen zur Integration zu sehen",
+ "To_users": "An Benutzer",
+ "Toggle_original_translated": "Zwischen \"Original\" und \"Übersetzt\" wechseln",
"Topic": "Thema",
+ "Transcript_Enabled": "Frage Besucher, ob Sie nach dem Schließen des Livechats eine Mitschrift zugesandt bekommen möchten",
+ "Transcript_message": "Nachricht, die bei der Nachfrage bzgl. einer Mitschrift gesendet wird",
+ "Transcript_of_your_livechat_conversation": "Mitschrift Ihres Livechats",
+ "Translated": "Übersetzt",
+ "Translations": "Übersetzungen",
"Travel_and_Places": "Reisen & Orte",
- "Trigger_removed": "Auslöser entfernt",
- "Trigger_Words": "Trigger Words",
- "Triggers": "Auslöser",
+ "Trigger_removed": "Trigger entfernt",
+ "Trigger_Words": "Trigger-Wörter",
+ "Triggers": "Trigger",
"True": "Ja",
"Tuesday": "Dienstag",
+ "Two-factor_authentication": "Zwei-Faktor-Authentifizierung",
+ "Two-factor_authentication_disabled": "Zwei-Faktor-Authentifizierung deaktiviert",
+ "Two-factor_authentication_enabled": "Zwei-Faktor-Authentifizierung aktiviert",
+ "Two-factor_authentication_is_currently_disabled": "Zwei-Faktor-Authentifizierung ist momentan deaktiviert",
+ "Two-factor_authentication_native_mobile_app_warning": "WARNUNG: Nach der Aktivierung kannst du dich nicht mehr auf den mobilen Apps (Rocket.Chat+) einloggen, da dieses Feature dort noch nicht implementiert wurde.",
"Type": "Typ",
- "Type_your_email": "Geben Sie Ihre E-Mail-Adresse ein",
- "Type_your_message": "Geben Sie Ihre Nachricht ein",
- "Type_your_name": "Geben Sie Ihren Namen ein",
- "Type_your_new_password": "Geben Sie Ihr neues Passwort ein",
+ "Type_your_email": "Gib Deine E-Mail-Adresse ein",
+ "Type_your_message": "Gib Deine Nachricht ein",
+ "Type_your_name": "Gib Deinen Namen ein",
+ "Type_your_new_password": "Gib ein neues Passwort ein",
+ "UI_Allow_room_names_with_special_chars": "Sonderzeichen im Raumnamen erlauben",
+ "UI_Click_Direct_Message": "Anklicken, um eine Direktnachricht zu erstellen",
+ "UI_Click_Direct_Message_Description": "Den Profil-Tab überspringen und direkt zur Konversation gehen",
"UI_DisplayRoles": "Rollen anzeigen",
- "UI_Merge_Channels_Groups": "Führe private Gruppen und Kanäle zusammen",
- "Unarchive": "Wiederherstellen",
- "Unmute_someone_in_room": "Jemanden das Chatten in einem Raum wieder erlauben",
- "Unmute_user": "Benutzern das Chatten erlauben ",
+ "UI_Merge_Channels_Groups": "Führe private und öffentliche Kanäle zusammen",
+ "UI_Unread_Counter_Style": "Stil für den \"Ungelesen\"-Zähler",
+ "UI_Use_Name_Avatar": "Die Initialen des vollständigen Namens verwenden, um einen Standard-Avatar zu generieren",
+ "UI_Use_Real_Name": "Den echten Namen verwenden",
+ "Unarchive": "Aus dem Archiv holen",
+ "unarchive-room": "Raum aus dem Archiv holen",
+ "unarchive-room_description": "Berechtigung, einen Raum aus dem Archiv holen",
+ "Unblock_User": "Benutzer entsperren",
+ "Unmute_someone_in_room": "Jemandem das Chatten in einem Raum wieder erlauben",
+ "Unmute_user": "Benutzern das Chatten erlauben",
"Unnamed": "Unbenannt",
- "Unpin_Message": "Nachicht nicht mehr fixieren",
- "Unread_Alert": "Über Ungelesenes benachrichtigen",
+ "Unpin_Message": "Nachricht nicht mehr anheften",
+ "Unread_Count": "Zählen ungelesener Nachrichten",
+ "Unread_Count_DM": "Zählen ungelesener Direktnachrichten",
+ "Unread_Messages": "Ungelesene Nachrichten",
"Unread_Rooms": "Ungelesene Räume",
- "Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
- "Unstar_Message": "Markierung entfernen",
- "Upload_file_question": "Möchten Sie eine Datei hochladen?",
+ "Unread_Rooms_Mode": "Ungelesene Räume gruppiert anzeigen",
+ "Unread_Tray_Icon_Alert": "Ungelesen-Markierung in Statusleiste anzeigen",
+ "Unstar_Message": "Aus den Favoriten entfernen",
+ "Updated_at": "Aktualisiert am",
+ "Upload_user_avatar": "Avatar hochladen",
+ "Upload_file_description": "Dateibeschreibung",
+ "Upload_file_name": "Dateiname",
+ "Upload_file_question": "Möchtest Du eine Datei hochladen?",
"Uploading_file": "Datei wird hochgeladen...",
"Uptime": "Laufzeit",
"URL": "URL",
+ "URL_room_prefix": "URL-Präfix für Räume",
"Use_account_preference": "Kontoeinstellungen verwenden",
"Use_Emojis": "Emojis verwenden",
- "Use_Global_Settings": "Globale Einstellungen nutzen",
+ "Use_Global_Settings": "Globale Einstellungen verwenden",
"Use_initials_avatar": "Anfangsbuchstaben des Nutzernamens verwenden",
- "Use_service_avatar": "Benutze %s Profilbild",
- "Use_this_username": "Benutzen Sie folgenden Benutzernamen",
+ "Use_minor_colors": "\"Minor\" Farbpalette verwenden (Standard: Erben von den Hauptfarben",
+ "Use_service_avatar": "Verwende %s Profilbild",
+ "Use_this_username": "Benutzen Sie folgenden Nutzernamen",
"Use_uploaded_avatar": "Das hochgeladene Profilbild verwenden",
"Use_url_for_avatar": "URL für Profilbild verwenden",
- "Use_User_Preferences_or_Global_Settings": "Benutzerpräferenzen oder globale Einstellungen nutzen",
- "User__username__is_now_a_moderator_of__room_name_": "Der Benuzer __username__ ist jetzt ein Moderator des Raums __room_name__.",
- "User__username__is_now_a_owner_of__room_name_": "Benutzer __username__ ist jetzt ein Besitzer von __room_name__",
- "User__username__removed_from__room_name__moderators": "Der Benutzer __username__ wurde von einem Moderator aus __room_name__ entfernt.",
- "User__username__removed_from__room_name__owners": "Benutzer __username__ wurde als Besitzer von __room_name__ entfernt.",
- "User_added": "Der Benutzer __user_added__ wurde hinzugefügt.",
- "User_added_by": "Der Benutzer __user_added__ wurde von __user_by__ hinzugefügt.",
+ "Use_User_Preferences_or_Global_Settings": "Kontoeinstellungen oder globale Einstellungen verwenden",
+ "User": "Benutzer",
+ "user-generate-access-token": "Zugriffs-Token erzeugen",
+ "user-generate-access-token_description": "Berechtigung, Zugriffs-Tokens zu erzeugen",
+ "User__username__is_now_a_leader_of__room_name_": "Benutzer __username__ ist nun Diskussionsleiter für __room_name__",
+ "User__username__is_now_a_moderator_of__room_name_": "Der Benutzer __username__ ist jetzt ein Moderator von __room_name__",
+ "User__username__is_now_a_owner_of__room_name_": "Benutzer __username__ ist jetzt Besitzer von __room_name__",
+ "User__username__removed_from__room_name__leaders": "Benutzer __username__ wurde als Diskussionsleiter in __room_name__ entfernt",
+ "User__username__removed_from__room_name__moderators": "Der Benutzer __username__ wurde von einem Moderator aus __room_name__ entfernt",
+ "User__username__removed_from__room_name__owners": "Benutzer __username__ ist nicht mehr Besitzer von __room_name__",
+ "User_added": "Der Benutzer __user_added__ wurde hinzugefügt",
+ "User_added_by": "Der Benutzer __user_added__ wurde von __user_by__ hinzugefügt",
"User_added_successfully": "Benutzer erfolgreich hinzugefügt",
- "User_doesnt_exist": "Kein Benutzer mit dem Namen `@%s` vorhanden.",
- "User_has_been_activated": "Der Benutzer wurde aktiviert.",
- "User_has_been_deactivated": "Der Benutzer wurde deaktiviert.",
- "User_has_been_deleted": "Der Benutzer wurde gelöscht.",
- "User_has_been_muted_in_s": "Dem Nutzer wurde das Schreiben in %s verboten.",
- "User_has_been_removed_from_s": "Der Benutzer wurde von %s entfernt.",
+ "User_and_group_mentions_only": "Nur Benutzer- und Gruppenerwähnungen",
+ "User_doesnt_exist": "Kein Benutzer mit Namen `@%s` vorhanden",
+ "User_has_been_activated": "Benutzer wurde aktiviert",
+ "User_has_been_deactivated": "Benutzer wurde deaktiviert",
+ "User_has_been_deleted": "Benutzer wurde gelöscht",
+ "User_has_been_muted_in_s": "Dem Nutzer wurde das Schreiben in %s verboten",
+ "User_has_been_removed_from_s": "Der Benutzer wurde aus %s entfernt",
"User_Info": "Benutzerinformationen",
- "User_is_no_longer_an_admin": "Der Benutzer ist kein Admin mehr.",
- "User_is_now_an_admin": "Der Benutzer ist jetzt ein Admin.",
- "User_joined_channel": "Ist dem Kanal beigetreten.",
- "User_joined_channel_female": "Ist dem Kanal beigetreten.",
- "User_joined_channel_male": "Ist dem Kanal beigetreten.",
- "User_left": "Der Benutzer __user_left__ hat den Kanal verlassen.",
- "User_left_female": "Der Benutzer __user_left__ hat den Kanal verlassen.",
- "User_left_male": "Der Benutzer __user_left__ hat den Kanal verlassen.",
- "User_logged_out": "Der Benutzer wurde abgemeldet.",
+ "User_Interface": "User Interface",
+ "User_is_blocked": "Benutzer ist geblockt",
+ "User_is_no_longer_an_admin": "Der Benutzer ist kein Administrator mehr",
+ "User_is_now_an_admin": "Der Benutzer ist jetzt ein Administrator",
+ "User_is_unblocked": "Benutzer ist nicht mehr geblockt",
+ "User_joined_channel": "Ist dem Kanal beigetreten",
+ "User_joined_channel_female": "Ist dem Kanal beigetreten",
+ "User_joined_channel_male": "Ist dem Kanal beigetreten",
+ "User_left": "Benutzer __user_left__ hat den Kanal verlassen",
+ "User_left_female": "Benutzer __user_left__ hat den Kanal verlassen.",
+ "User_left_male": "Benutzer __user_left__ hat den Kanal verlassen.",
+ "User_logged_out": "Benutzer wurde abgemeldet",
"User_management": "Benutzerverwaltung",
- "User_muted_by": "Dem Benutzer __user_muted__ wurde das Chatten von __user_by__ verboten.",
- "User_not_found": "Der Benutzer konnte nicht gefunden werden.",
- "User_not_found_or_incorrect_password": "Entweder konnte der Benutzer nicht gefunden werden oder Sie haben ein falsches Passwort angegeben.",
+ "User_mentions_only": "Nur Benutzererwähnungen",
+ "User_muted": "Benutzer stumm geschaltet",
+ "User_muted_by": "Benutzer __user_muted__ wurde das Chatten von __user_by__ verboten",
+ "User_not_found": "Der Benutzer konnte nicht gefunden werden",
+ "User_not_found_or_incorrect_password": "Entweder konnte der Benutzer nicht gefunden werden oder Sie haben ein falsches Passwort angegeben",
"User_or_channel_name": "Benutzer- oder Kanalname",
- "User_removed": "Der Benutzer wurde gelöscht.",
- "User_removed_by": "Der Benutzer __user_removed__ wurde von __user_by__ entfernt.",
- "User_Settings": "Benutzereinstellungen",
- "User_unmuted_by": "Dem Benutzer __user_unmuted__ wurde das Chatten von __user_by__ wieder erlaubt. ",
- "User_unmuted_in_room": "Dem Benutzer wurde das Chatten wieder erlaubt.",
- "User_updated_successfully": "Der Benutzer wurde erfolgreich aktualisiert.",
+ "User_removed": "Benutzer wurde gelöscht",
+ "User_removed_by": "Benutzer __user_removed__ wurde von __user_by__ entfernt",
+ "User_Settings": "Kontoeinstellungen",
+ "User_unmuted_by": "Benutzer __user_unmuted__ wurde das Chatten von __user_by__ wieder erlaubt",
+ "User_unmuted_in_room": "Dem Benutzer wurde das Chatten wieder erlaubt",
+ "User_updated_successfully": "Benutzer wurde erfolgreich aktualisiert",
+ "User_uploaded_file": "Eine Datei hochladen",
+ "User_uploaded_image": "Ein Bild hochladen",
"Username": "Benutzername",
- "Username_and_message_must_not_be_empty": "Die Felder \"Benutzername\" und \"Nachricht\" dürfen nicht leer sein.",
- "Username_cant_be_empty": "Sie müssen einen Benutzernamen angeben.",
- "Username_Change_Disabled": "Der Administrator hat das Ändern von Benutzernamen deaktiviert.",
- "Username_denied_the_OTR_session": "__username__ hat die OTR-Session abgelehnt.",
- "Username_description": "Der Benutzername wird dazu benutzt, Sie in Nachrichten zu erwähnen.",
- "Username_doesnt_exist": "Der Benutzer \"%s\" existiert nicht.",
- "Username_ended_the_OTR_session": "__username__ hat die OTR-Session beendet.",
- "Username_invalid": "%s ist kein zulässiger Benutzername. Verwenden Sie nur Buchstaben, Zahlen, Punkte oder Binde- und Unterstriche.",
- "Username_is_already_in_here": "`@%s` wurde bereits hinzugefügt.",
- "Username_is_not_in_this_room": "Der Benutzer `#%s` ist nicht in diesem Raum.",
+ "Username_and_message_must_not_be_empty": "Benutzername und Nachricht müssen eingegeben werden",
+ "Username_cant_be_empty": "Sie müssen einen Benutzernamen angeben",
+ "Username_Change_Disabled": "Der Administrator hat das Ändern von Benutzernamen deaktiviert",
+ "Username_denied_the_OTR_session": "__username__ hat die OTR-Session abgelehnt",
+ "Username_description": "Der Benutzername wird dazu benutzt, um Sie in Nachrichten zu erwähnen",
+ "Username_doesnt_exist": "Benutzer \"%s\" existiert nicht",
+ "Username_ended_the_OTR_session": "__username__ hat die OTR-Session beendet",
+ "Username_invalid": "%s ist kein gültiger Benutzername. Verwende nur Buchstaben, Zahlen, Punkte oder Binde- und Unterstriche.",
+ "Username_is_already_in_here": "`@%s` wurde bereits hinzugefügt",
+ "Username_is_not_in_this_room": "Benutzer `#%s` ist nicht in diesem Raum",
+ "Username_Placeholder": "Bitte gib Benutzernamen ein...",
"Username_title": "Benutzernamen festlegen",
- "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ möchte ein OTR-Gespräch starten. Möchten Sie annehmen?",
+ "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ möchte ein OTR-Gespräch starten. Möchten Sie es annehmen?",
"Users": "Benutzer",
- "Users_in_role": "Zugeordnete Nutzer",
+ "Users_added": "Die Benutzer wurden hinzugefügt",
+ "Users_in_role": "Nutzer mit dieser Rolle",
"UTF8_Names_Slugify": "UTF8-Namen-Slugify",
"UTF8_Names_Validation": "UTF8-Namen-Verifizierung",
- "UTF8_Names_Validation_Description": "Erlauben Sie keine Sonderzeichen und Leerzeichen. Sie können - _ und . verwenden, aber nicht am Ende eines Namens.",
+ "UTF8_Names_Validation_Description": "Regulärer Ausdruck, der zur Validierung der Benutzer- und Kanalnamen verwendet wird",
+ "Validate_email_address": "E-Mail-Adresse bestätigen",
+ "Verification": "Überprüfung ",
+ "Verification_Description": "Sie können die folgenden Platzhalter verwenden: [[Verification_Url] für die Verifikations-URL [name], [fname], [lname] für den vollständigen Namen, Vornamen oder Nachnamen des Benutzers [email] für die E-Mail-Adresse des Benutzers. [Site_Name] und [Site_URL] für den Anwendungsnamen und die URL der Anwendung ",
+ "Verification_Email": "Klicken Sie hier , um Ihr Benutzerkonto zu bestätigen",
"Verification_email_sent": "Bestätigungsmail gesendet",
- "Verified": "Verifiziert",
+ "Verification_Email_Subject": "[Site_Name] - Bestätigen Sie Ihr Benutzerkonto",
+ "Verified": "Überprüft",
+ "Verify": "überprüfen",
"Version": "Version",
"Video_Chat_Window": "Video-Chat",
- "Videocall_declined": "Videoanruf abgelehnt.",
+ "Video_Conference": "Video-Konferenz",
+ "Video_message": "Videonachricht",
+ "Videocall_declined": "Videoanruf abgelehnt",
+ "Videocall_enabled": "Videoanruf aktiviert",
+ "view-c-room": "Öffentlichen Kanal anzeigen",
+ "view-c-room_description": "Berechtigung, öffentliche Kanäle einzusehen",
+ "view-d-room": "Direktnachrichten erhalten",
+ "view-d-room_description": "Berechtigung, Direktnachrichten zu erhalten",
+ "view-full-other-user-info": "Vollständige Benutzerinformation einsehen",
+ "view-full-other-user-info_description": "Berechtigung, die vollständigen Benutzerinformation anderer Benutzer einzusehen (inkl. Erstelldatum, letztem Login etc.)",
+ "view-history": "Historie anzeigen",
+ "view-history_description": "Berechtigung, die Kanal-Historie anzuzeigen",
+ "view-join-code": "Beitritts-Code anzeigen",
+ "view-join-code_description": "Berechtigung, den Beitritts-Code zu einem Kanal anzuzeigen",
+ "view-joined-room": "Beigetretenen Raum anzeigen",
+ "view-joined-room_description": "Berechtigung, einen Raum, dem der Benutzer angehört, anzuzeigen",
+ "view-l-room": "Zeige Livechat-Räume",
+ "view-l-room_description": "Berechtigung, Livechat-Räume zu sehen",
+ "view-livechat-manager": "Zeige Livechat-Manager",
+ "view-livechat-manager_description": "Berechtigung, andere Livechat-Manager zu sehen",
+ "view-livechat-rooms": "Zeige Livechat-Räume",
+ "view-livechat-rooms_description": "Berechtigung, andere Livechat-Räume einzusehen",
+ "view-logs": "Logs anzeigen",
+ "view-logs_description": "Berechtigung, die Server-Logs anzuzeigen",
+ "view-other-user-channels": "Räume anderer Benutzer anzeigen",
+ "view-other-user-channels_description": "Berechtigung, die Räume anderer Benutzer zu sehen",
+ "view-outside-room": "Raum außerhalb anzeigen",
+ "view-p-room": "Privaten Raum anzeigen",
+ "view-p-room_description": "Berechtigung, private Räume anzuzeigen",
+ "view-privileged-setting": "Besonders geschützte Einstellungen einsehen",
+ "view-privileged-setting_description": "Einstellungen anzeigen",
+ "view-room-administration": "Raum-Administration anzeigen",
+ "view-room-administration_description": "Berechtigung, Raumstatistiken zu öffentlichen, privaten und Direktnachrichten anzeigen. Beinhaltet nicht die Berechtigung, die Konversationen selbst oder Archive einzusehen.",
+ "view-statistics": "Statistiken anzeigen",
+ "view-statistics_description": "Berechtigung, Statistiken über das System einzusehen, bspw. Anzahl der angemeldeten Benutzer, Anzahl der Räume und Informationen zum Betriebssystem.",
+ "view-user-administration": "Benutzerverwaltung anzeigen",
+ "view-user-administration_description": "Berechtigung zu unvollständigen, schreibgeschützten Listen von anderen Benutzer, die derzeit am System angemeldet sind. Keine Details der Benutzerkonten können mit dieser Berechtigung eingesehen werden.",
"View_All": "Alle ansehen",
"View_Logs": "Logs anzeigen",
"View_mode": "Ansichts-Modus",
- "View_mode_info": "Dadurch ändert sich der Platzbedarf für Nachrichten auf dem Bildschirm.",
+ "View_mode_info": "Dadurch ändert sich der Platzbedarf für Nachrichten auf dem Bildschirm",
"Viewing_room_administration": "Raumadministration anzeigen",
"Visibility": "Sichtbarkeit",
"Visible": "Sichtbar",
@@ -1270,62 +2004,66 @@
"Visitor_Info": "Besucherinformation",
"Visitor_Navigation": "Besuchernavigation",
"Visitor_page_URL": "URL der Besucherseite",
- "Visitor_time_on_site": "Besucherzeit auf der Seite",
- "Wait_activation_warning": "Bevor Sie sich anmelden können, muss das Konto von einem Administrator manuell aktiviert werden.",
- "We_are_offline_Sorry_for_the_inconvenience": "Wir sind offline. Entschuldigen Sie die Unannehmlichkeiten.",
- "We_have_sent_password_email": "Wir haben Ihnen eine Anleitung zum Zurücksetzen des Passworts an Ihre E-Mail-Adresse gesendet. Wenn Sie keine E-Mail erhalten haben, versuchen Sie es bitte noch einmal.",
- "We_have_sent_registration_email": "Wir haben Ihnen eine Bestätigungsmail gesendet. Wenn Sie keine E-Mail erhalten haben, versuchen Sie es bitte noch einmal.",
+ "Visitor_time_on_site": "Besuchsdauer auf der Seite",
+ "Wait_activation_warning": "Bevor Sie sich anmelden können, muss das Konto von einem Administrator manuell aktiviert werden",
+ "Warnings": "Warnungen",
+ "We_are_offline_Sorry_for_the_inconvenience": "Wir sind offline. Bitte entschuldigen Sie die Unannehmlichkeiten.",
+ "We_have_sent_password_email": "Wir haben Dir eine Anleitung zum Zurücksetzen des Passworts an Deine E-Mail-Adresse gesendet. Wenn Du keine E-Mail erhalten hast, versuch es bitte noch einmal.",
+ "We_have_sent_registration_email": "Wir haben Dir eine Bestätigungsmail gesendet. Wenn Du keine E-Mail erhalten hast, versuch es bitte noch einmal.",
"Webhook_URL": "Webhook-URL",
"Webhooks": "Webhooks",
"WebRTC_Enable_Channel": "Für öffentliche Kanäle aktivieren",
"WebRTC_Enable_Direct": "Für private Nachrichten aktivieren",
"WebRTC_Enable_Private": "Für private Kanäle aktivieren",
"WebRTC_Servers": "STUN/TURN-Server",
- "WebRTC_Servers_Description": "Kommata-getrennte Liste von STUN- und TURN-Servern. Benutzernamen, Passwörter und Ports sind in diesen Formaten erlaubt: `username:password@stun:host:port` oder `username:password@turn:host:port",
+ "WebRTC_Servers_Description": "Kommaseparierte Liste von STUN- und TURN-Servern. Benutzernamen, Passwörter und Ports sind in diesen Formaten erlaubt: `username:password@stun:host:port` oder `username:password@turn:host:port",
"Wednesday": "Mittwoch",
"Welcome": "Willkommen, %s .",
"Welcome_to_the": "Willkommen bei",
- "Why_do_you_want_to_report_question_mark": "Warum möchten Sie das melden?",
+ "Why_do_you_want_to_report_question_mark": "Warum möchtest Du das melden?",
"will_be_able_to": "wird in der Lage sein,",
- "Would_you_like_to_return_the_inquiry": "Anfrage erwidern?",
+ "Would_you_like_to_return_the_inquiry": "Anfrage zurückgeben?",
"Yes": "Ja",
- "Yes_clear_all": "Ja!",
+ "Yes_archive_it": "Ja, archivieren!",
+ "Yes_clear_all": "Ja, alles löschen!",
"Yes_delete_it": "Ja!",
"Yes_hide_it": "Ja, verstecken!",
- "Yes_leave_it": "Ja!",
+ "Yes_leave_it": "Ja, verlassen!",
"Yes_mute_user": "Ja, Benutzer stumm schalten!\n",
- "Yes_remove_user": "Ja, Nutzer entfernen!",
- "You": "Sie",
- "you_are_in_preview_mode_of": "Sie befinden sich im Vorschaumodus des Kanals #__room_name__ .",
- "You_are_logged_in_as": "Sie sind angemeldet als",
- "You_are_not_authorized_to_view_this_page": "Sie sind nicht berechtigt, diese Seite zu sehen.",
- "You_can_change_a_different_avatar_too": "Sie können das aktuell verwendete Profilbild überschreiben, um von dieser Integration zu veröffentlichen.",
- "You_can_search_using_RegExp_eg": "Sie können RegExp zum Suchen verwenden. z.B.",
- "You_can_use_an_emoji_as_avatar": "Sie können auch einen Emoji als Profilbild verwenden.",
- "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Sie können webhooks verwenden, um den livechat mit Ihrem CRM zu integrieren.",
- "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Sie können keinen Livechat-Raum verlassen. Bitte verwenden Sie die Schaltfläche zum Schließen.",
- "You_have_been_muted": "Ihnen wurde das Chatten in diesem Raum verboten. ",
- "You_have_not_verified_your_email": "Sie haben Ihre E-Mail-Adresse nicht verifiziert.",
- "You_have_successfully_unsubscribed": "Sie haben sich erfolgreich von unserem Verteiler abgemeldet.",
+ "Yes_remove_user": "Ja, Benutzer entfernen!",
+ "Yes_unarchive_it": "Ja, aus dem Archiv holen!",
+ "You": "Du",
+ "you_are_in_preview_mode_of": "Sie befinden sich im Vorschaumodus des Kanals #__room_name__ ",
+ "You_are_logged_in_as": "Du bist angemeldet als",
+ "You_are_not_authorized_to_view_this_page": "Sie sind nicht berechtigt, diese Seite zu sehen",
+ "You_can_change_a_different_avatar_too": "Sie können für Post dieser Integration ein anderes Profilbild verwenden",
+ "You_can_search_using_RegExp_eg": "Sie können einen regulären Ausdruck zum Suchen verwenden. z.B.",
+ "You_can_use_an_emoji_as_avatar": "Sie können auch einen Emoji als Profilbild verwenden",
+ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Sie können Webhooks verwenden, um den Livechat mit Ihrem CRM zu integrieren.",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Sie können keinen Livechat-Raum verlassen. Bitte Schließen Sie die Anfrage ",
+ "You_have_been_muted": "Ihnen wurde das Chatten in diesem Raum verboten",
+ "You_have_n_codes_remaining": "Sie haben __number__ Codes übrig",
+ "You_have_not_verified_your_email": "Sie haben Ihre E-Mail-Adresse nicht verifiziert",
+ "You_have_successfully_unsubscribed": "Sie haben sich erfolgreich von unserem Verteiler abgemeldet",
"You_must_join_to_view_messages_in_this_channel": "Sie müssen dem Kanal beitreten, um Nachrichten darin lesen zu können",
- "You_need_confirm_email": "Sie müssen Ihre E-Mail-Adresse bestätigen!",
- "You_need_install_an_extension_to_allow_screen_sharing": "Sie müssen eine Erweiterung installieren, um eine Bildschirmübertragung zu starten.",
- "You_need_to_change_your_password": "Sie müssen ihr Passwort ändern.",
- "You_need_to_type_in_your_password_in_order_to_do_this": "Um diese Aktion auszuführen, müssen sie Ihr Passwort eingeben.",
- "You_need_to_type_in_your_username_in_order_to_do_this": "Sie müssen Ihren Benutzernamen angeben, um diese Aktion durchzuführen!",
- "You_need_to_verifiy_your_email_address_to_get_notications": "Sie müssen Ihre E-Mail-Adresse bestätigen, um Benachrichtigungen zu erhalten",
- "You_need_to_write_something": "Sie müssen etwas dazu schreiben!",
- "You_should_inform_one_url_at_least": "Sie müssen mindestens eine URL definieren.",
- "You_should_name_it_to_easily_manage_your_integrations": "Zur einfachen Verwaltung der Integrationen empfehlen wir, der Integration einen Namen zuzuordnen.",
- "You_will_not_be_able_to_recover": "Die Nachricht kann anschließend nicht wiederhergestellt werden.",
- "You_will_not_be_able_to_recover_file": "Das Wiederherstellen dieser Datei wird nicht möglich sein.",
- "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Sie werden keine E-Mail-Benachrichtigungen erhalten, da Sie ihre E-Mail-Adresse nicht verifiziert haben.",
- "Your_email_has_been_queued_for_sending": "Ihre E-Mail wird in Kürze gesendet werden.",
- "Your_entry_has_been_deleted": "Ihr Eintrag wurde gelöscht.",
- "Your_file_has_been_deleted": "Deine Datei wurde erfolgreich gelöscht.",
- "Your_mail_was_sent_to_s": "Ihre E-Mail wurde an %s gesendet.",
- "your_message": "ihre Nachricht",
- "your_message_optional": "ihre optionale Nachricht",
+ "You_need_confirm_email": "Sie müssen Ihre E-Mail-Adresse bestätigen, um sich anmelden zu können",
+ "You_need_install_an_extension_to_allow_screen_sharing": "Sie müssen eine Erweiterung installieren, um eine Bildschirmübertragung zu starten",
+ "You_need_to_change_your_password": "Sie müssen Ihr Passwort ändern",
+ "You_need_to_type_in_your_password_in_order_to_do_this": "Um diese Aktion auszuführen, müssen Sie Ihr Passwort eingeben",
+ "You_need_to_type_in_your_username_in_order_to_do_this": "Sie müssen Ihren Benutzernamen angeben, um diese Aktion auszuführen",
+ "You_need_to_verifiy_your_email_address_to_get_notications": "Sie müssen Ihre E-Mail-Adresse bestätigen, um Benachrichtigungen erhalten zu können",
+ "You_need_to_write_something": "Du solltest etwas schreiben!",
+ "You_should_inform_one_url_at_least": "Sie müssen mindestens eine URL angeben",
+ "You_should_name_it_to_easily_manage_your_integrations": "Zur einfacheren Verwaltung der Integrationen empfehlen wir, der Integration einen Namen zu geben.",
+ "You_will_not_be_able_to_recover": "Die Nachricht kann anschließend nicht wiederhergestellt werden",
+ "You_will_not_be_able_to_recover_file": "Das Wiederherstellen dieser Datei wird nicht möglich sein",
+ "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Sie werden keine E-Mail-Benachrichtigungen erhalten, da Sie Ihre E-Mail-Adresse nicht bestätigt haben",
+ "Your_email_has_been_queued_for_sending": "Ihre E-Mail wird in Kürze gesendet werden",
+ "Your_entry_has_been_deleted": "Ihr Eintrag wurde gelöscht",
+ "Your_file_has_been_deleted": "Ihre Datei wurde erfolgreich gelöscht",
+ "Your_mail_was_sent_to_s": "Ihre E-Mail wurde an %s gesendet",
+ "your_message": "Ihre Nachricht",
+ "your_message_optional": "Ihre optionale Nachricht",
"Your_password_is_wrong": "Falsches Passwort",
- "Your_push_was_sent_to_s_devices": "Die Push-Nachricht wurde an %s Geräte gesendet."
+ "Your_push_was_sent_to_s_devices": "Eine Push-Nachricht wurde an %s Geräte gesendet."
}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/el.i18n.json b/packages/rocketchat-i18n/i18n/el.i18n.json
index b3edc3db55290..27c08a19abfa8 100644
--- a/packages/rocketchat-i18n/i18n/el.i18n.json
+++ b/packages/rocketchat-i18n/i18n/el.i18n.json
@@ -6,6 +6,7 @@
"500": "Εσωτερικό Σφάλμα Διακομιστή",
"__username__is_no_longer__role__defined_by__user_by_": "__username__ is no longer __role__ by __user_by__",
"__username__was_set__role__by__user_by_": "__username__ was set __role__ by __user_by__",
+ "Accept": "Αποδοχή",
"Access_not_authorized": "Πρόσβαση δεν επιτρέπονται",
"Access_Token_URL": "Πρόσβαση Token URL",
"Accessing_permissions": "Πρόσβαση δικαιώματα",
@@ -21,8 +22,6 @@
"Accounts_AllowUserProfileChange": "Επιτρέψτε Προφίλ Χρήστη Αλλαγή",
"Accounts_AvatarResize": "Αλλαγή μεγέθους Avatars",
"Accounts_AvatarSize": "Avatar Μέγεθος",
- "Accounts_AvatarStorePath": "Path Avatar αποθήκευσης",
- "Accounts_AvatarStoreType": "Avatar Τύπος αποθήκευσης",
"Accounts_BlockedDomainsList": "Λίστα αποκλεισμένων τομέων",
"Accounts_BlockedDomainsList_Description": "Διαχωρισμένες με κόμμα λίστα των αποκλεισμένων περιοχών",
"Accounts_BlockedUsernameList": "Λίστα αποκλεισμένων Όνομα Χρήστη",
@@ -31,7 +30,7 @@
"Accounts_EmailVerification": "Επιβεβαίωση E-mail",
"Accounts_EmailVerification_Description": "Βεβαιωθείτε ότι έχετε τις σωστές ρυθμίσεις SMTP για να χρησιμοποιήσετε αυτήν τη λειτουργία",
"Accounts_Enrollment_Email": "Εγγραφή E-mail",
- "Accounts_Enrollment_Email_Default": " Καλωσήρθες στο [Site_Name] Πηγαίνετε στο [Site_URL] και δοκιμάστε την καλύτερη λύση συνομιλίας ανοικτού κώδικα που διατίθενται σήμερα!
",
+ "Accounts_Enrollment_Email_Default": " Καλωσήρθες στο [Site_Name] Πηγαίνετε στο [Site_URL] και δοκιμάστε την καλύτερη λύση συνομιλίας ανοικτού κώδικα που διατίθενται σήμερα!
",
"Accounts_Enrollment_Email_Description": "Μπορείτε να χρησιμοποιήσετε το [name], [fname], [lname] για το πλήρες όνομα του χρήστη, το όνομα ή το επώνυμο, αντίστοιχα. Μπορείτε να χρησιμοποιήσετε το [email] για το ηλεκτρονικό ταχυδρομείο του χρήστη.",
"Accounts_Enrollment_Email_Subject_Default": "Καλώς ήρθατε στο [Site_Name]",
"Accounts_Iframe_api_method": "Μέθοδος Api",
@@ -47,7 +46,8 @@
"Accounts_OAuth_Custom_Enable": "Καθιστώ ικανό",
"Accounts_OAuth_Custom_id": "Ταυτότητα",
"Accounts_OAuth_Custom_Identity_Path": "Path ταυτότητα",
- "Accounts_OAuth_Custom_Login_Style": "Είσοδος Style",
+ "Accounts_OAuth_Custom_Login_Style": "Τρόπος Εισόδου",
+ "Accounts_OAuth_Custom_Merge_Users": "Συγχώνευση χρηστ",
"Accounts_OAuth_Custom_Secret": "Μυστικό",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token αποστέλλονται μέσω",
@@ -71,8 +71,8 @@
"Accounts_OAuth_Google_callback_url": "Google επανάκλησης URL",
"Accounts_OAuth_Google_id": "Google Id",
"Accounts_OAuth_Google_secret": "Google Secret",
- "Accounts_OAuth_Linkedin": "LinkedIn Login",
- "Accounts_OAuth_Linkedin_callback_url": "Linkedin επανάκλησης URL",
+ "Accounts_OAuth_Linkedin": "LinkedIn Είσοδος",
+ "Accounts_OAuth_Linkedin_callback_url": "Linkedin URL Επανάκλησης",
"Accounts_OAuth_Linkedin_id": "LinkedIn Id",
"Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
"Accounts_OAuth_Meteor": "Meteor Login",
@@ -84,7 +84,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Είσοδος",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress επανάκλησης URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress επανάκλησης URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Επανακαθορισμός κωδικού",
@@ -95,12 +95,12 @@
"Accounts_RegistrationForm_Public": "Δημόσιο",
"Accounts_RegistrationForm_Secret_URL": "μυστική URL",
"Accounts_RegistrationForm_SecretURL": "Αίτηση Εγγραφής μυστικό URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Πρέπει να δώσετε μια τυχαία σειρά που θα προστεθούν στο URL της εγγραφής σας. Παράδειγμα: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Πρέπει να δώσετε μια τυχαία σειρά που θα προστεθούν στο URL της εγγραφής σας. Παράδειγμα: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Απαιτούν Όνομα Για Εγγραφή",
"Accounts_ShowFormLogin": "Εμφάνιση μορφής βασίζεται Σύνδεση",
"Accounts_UseDefaultBlockedDomainsList": "Χρήση προεπιλεγμένων λίστα αποκλεισμένων τομέων",
"Accounts_UseDNSDomainCheck": "Χρησιμοποιήστε DNS Τομέα Έλεγχος",
- "Accounts_UserAddedEmail_Default": " Καλωσήρθες στο [Site_Name] Πηγαίνετε στο [Site_URL] και δοκιμάστε την καλύτερη λύση συνομιλίας ανοικτού κώδικα που διατίθενται σήμερα!
Μπορείτε να συνδεθείτε χρησιμοποιώντας το email σας: [email] και τον κωδικό πρόσβασης: [password]. Μπορεί να σας ζητηθεί να το αλλάξετε μετά την πρώτη είσοδο σας.",
+ "Accounts_UserAddedEmail_Default": "
Καλωσήρθες στο [Site_Name] Πηγαίνετε στο [Site_URL] και δοκιμάστε την καλύτερη λύση συνομιλίας ανοικτού κώδικα που διατίθενται σήμερα!
Μπορείτε να συνδεθείτε χρησιμοποιώντας το email σας: [email] και τον κωδικό πρόσβασης: [password]. Μπορεί να σας ζητηθεί να το αλλάξετε μετά την πρώτη είσοδο σας.",
"Accounts_UserAddedEmail_Description": "Μπορείτε να χρησιμοποιήσετε τις παρακάτω αντικαταστάτες:
[name], [fname], [lname] για το πλήρες όνομα του χρήστη, το όνομα ή το επώνυμο, αντίστοιχα. [email] για το ηλεκτρονικό ταχυδρομείο του χρήστη. [password] για τον κωδικό πρόσβασης του χρήστη. [Site_Name] και [Site_URL] για το όνομα της εφαρμογής και τη διεύθυνση URL αντίστοιχα. ",
"Accounts_UserAddedEmailSubject_Default": "Μπορείτε έχουν προστεθεί στο [Site_Name]",
"Activate": "Θέτω εις ενέργειαν",
@@ -136,6 +136,7 @@
"and": "και",
"And_more": "Και πιο __length __",
"Animals_and_Nature": "Ζώα και Φύση",
+ "Announcement": "Ανακοίνωση",
"API": "API",
"API_Analytics": "Analytics",
"API_Embed": "Ενσωμάτωση",
@@ -569,24 +570,12 @@
"Layout_Terms_of_Service": "Όροι χρήσης",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Αναζήτηση προσαρμοσμένο τομέα",
- "LDAP_Custom_Domain_Search_Description": "Ένα κομμάτι του JSON που διέπει δεσμεύουν και σύνδεση πληροφορίες και είναι της μορφής: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "default Domain",
"LDAP_Description": "LDAP είναι μια ιεραρχική βάση δεδομένων που πολλές εταιρείες χρησιμοποιούν για να παρέχουν Single Sign On - μια εγκατάσταση για την κοινή χρήση ενός κωδικού πρόσβασης από πολλαπλές τοποθεσίες και υπηρεσίες. Για προχωρημένους πληροφορίες διαμόρφωσης και παραδείγματα, συμβουλευτείτε wiki μας: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "τομέα Βάσης",
- "LDAP_Domain_Base_Description": "Το πλήρως αναγνωρισμένο αποκλειστικό όνομα (DN) του υποδένδρο LDAP που θέλετε να αναζητήσετε χρήστες και ομάδες. Μπορείτε να προσθέσετε όσες θέλετε? Ωστόσο, κάθε ομάδα πρέπει να ορίζεται στην ίδια βάση τομέα με τους χρήστες που ανήκουν σε αυτήν. Εάν καθορίσετε κλειστές ομάδες χρηστών, μόνο οι χρήστες που ανήκουν σε αυτές τις ομάδες θα είναι στο πεδίο. Σας συνιστούμε να καθορίσετε το ανώτερο επίπεδο του δέντρου καταλόγου LDAP σας ως βάση το domain σας και να χρησιμοποιήσετε το φίλτρο αναζήτησης για να ελέγξετε την πρόσβαση.",
- "LDAP_Domain_Search_Filter": "Αναζήτηση Domain Φίλτρο",
- "LDAP_Domain_Search_Filter_Description": "Αν καθοριστεί, μόνο οι χρήστες που ταιριάζουν με αυτό το φίλτρο θα επιτραπεί να συνδεθείτε. Εάν δεν έχει καθοριστεί φίλτρου, όλοι οι χρήστες εντός του πεδίου εφαρμογής της συγκεκριμένης βάσης τομέα θα είναι σε θέση να συνδεθείτε. Π.χ. για Active Directory `MemberOf = cn = ROCKET_CHAT, ou = Γενική Groups`. Π.χ. για OpenLDAP (αναζήτηση επεκτάσιμη αγώνα) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Αναζήτηση Domain Object Κατηγορία",
- "LDAP_Domain_Search_Object_Category_Description": "Ο * objectCategory * που αναγνωρίζουν τους χρήστες σας. Αφήστε το κενό για * OpenLDAP *. Π.χ. `person`, κ.λπ.",
- "LDAP_Domain_Search_Object_Class": "Τομέα Class Αναζήτηση Αντικείμενο",
- "LDAP_Domain_Search_Object_Class_Description": "Ο * objectclass * που αναγνωρίζουν τους χρήστες σας. Π.χ. `organizationalPerson`,` Χρήστης των, `inetOrgPerson`, κ.λπ.",
- "LDAP_Domain_Search_Password": "Αναζήτηση Domain Κωδικός",
- "LDAP_Domain_Search_Password_Description": "Ο κωδικός πρόσβασης για το χρήστη αναζήτησης τομέα.",
- "LDAP_Domain_Search_User": "Αναζήτηση Domain User",
- "LDAP_Domain_Search_User_Description": "Ο χρήστης LDAP που εκτελεί αναζητήσεις του χρήστη για τον έλεγχο ταυτότητας σε άλλους χρήστες, όταν συνδεθείτε. Αυτό είναι συνήθως ένα λογαριασμό υπηρεσίας που δημιουργήθηκε ειδικά για την ενσωμάτωση τρίτων κατασκευαστών. Χρησιμοποιήστε ένα πλήρως αναγνωρισμένο όνομα, όπως `cn = διαχειριστή, CN = Users, dc = Παράδειγμα, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Αναζήτηση Domain Αναγνωριστικό χρήστη",
- "LDAP_Domain_Search_User_ID_Description": "Το χαρακτηριστικό LDAP που προσδιορίζει το χρήστη LDAP ο οποίος επιχειρεί έλεγχο ταυτότητας. Αυτό το πεδίο πρέπει να είναι `sAMAccountName` για τις εγκαταστάσεις πιο Active Directory, αλλά μπορεί να είναι` uid` για άλλες λύσεις LDAP, όπως OpenLDAP. Μπορείτε να χρησιμοποιήσετε το `mail` για την αναγνώριση των χρηστών μέσω e-mail ή οτιδήποτε άλλο χαρακτηριστικό που θέλετε. Μπορείτε να χρησιμοποιήσετε πολλές τιμές διαχωρισμένες με κόμμα για να επιτρέπει στους χρήστες να συνδεθείτε χρησιμοποιώντας πολλαπλές αναγνωριστικά, όπως το όνομα χρήστη ή e-mail.",
+ "LDAP_BaseDN_Description": "Το πλήρως αναγνωρισμένο αποκλειστικό όνομα (DN) του υποδένδρο LDAP που θέλετε να αναζητήσετε χρήστες και ομάδες. Μπορείτε να προσθέσετε όσες θέλετε? Ωστόσο, κάθε ομάδα πρέπει να ορίζεται στην ίδια βάση τομέα με τους χρήστες που ανήκουν σε αυτήν. Εάν καθορίσετε κλειστές ομάδες χρηστών, μόνο οι χρήστες που ανήκουν σε αυτές τις ομάδες θα είναι στο πεδίο. Σας συνιστούμε να καθορίσετε το ανώτερο επίπεδο του δέντρου καταλόγου LDAP σας ως βάση το domain σας και να χρησιμοποιήσετε το φίλτρο αναζήτησης για να ελέγξετε την πρόσβαση.",
+ "LDAP_User_Search_Field_Description": "Το χαρακτηριστικό LDAP που προσδιορίζει το χρήστη LDAP ο οποίος επιχειρεί έλεγχο ταυτότητας. Αυτό το πεδίο πρέπει να είναι `sAMAccountName` για τις εγκαταστάσεις πιο Active Directory, αλλά μπορεί να είναι` uid` για άλλες λύσεις LDAP, όπως OpenLDAP. Μπορείτε να χρησιμοποιήσετε το `mail` για την αναγνώριση των χρηστών μέσω e-mail ή οτιδήποτε άλλο χαρακτηριστικό που θέλετε. Μπορείτε να χρησιμοποιήσετε πολλές τιμές διαχωρισμένες με κόμμα για να επιτρέπει στους χρήστες να συνδεθείτε χρησιμοποιώντας πολλαπλές αναγνωριστικά, όπως το όνομα χρήστη ή e-mail.",
+ "LDAP_User_Search_Filter_Description": "Αν καθοριστεί, μόνο οι χρήστες που ταιριάζουν με αυτό το φίλτρο θα επιτραπεί να συνδεθείτε. Εάν δεν έχει καθοριστεί φίλτρου, όλοι οι χρήστες εντός του πεδίου εφαρμογής της συγκεκριμένης βάσης τομέα θα είναι σε θέση να συνδεθείτε. Π.χ. για Active Directory `MemberOf = cn = ROCKET_CHAT, ou = Γενική Groups`. Π.χ. για OpenLDAP (αναζήτηση επεκτάσιμη αγώνα) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Ο χρήστης LDAP που εκτελεί αναζητήσεις του χρήστη για τον έλεγχο ταυτότητας σε άλλους χρήστες, όταν συνδεθείτε. Αυτό είναι συνήθως ένα λογαριασμό υπηρεσίας που δημιουργήθηκε ειδικά για την ενσωμάτωση τρίτων κατασκευαστών. Χρησιμοποιήστε ένα πλήρως αναγνωρισμένο όνομα, όπως `cn = διαχειριστή, CN = Users, dc = Παράδειγμα, dc = com`.",
"LDAP_Enable": "Καθιστώ ικανό",
"LDAP_Enable_Description": "Προσπάθεια να χρησιμοποιούν το LDAP για έλεγχο ταυτότητας.",
"LDAP_Encryption": "κρυπτογράφηση",
@@ -601,12 +590,9 @@
"LDAP_Sync_User_Data_Description": "Κρατήστε τα δεδομένα των χρηστών σε συγχρονισμό με το διακομιστή για την είσοδο (π.χ. όνομα, διεύθυνση ηλεκτρονικού ταχυδρομείου).",
"LDAP_Sync_User_Data_FieldMap": "Πεδίου δεδομένων χρήστη Χάρτης",
"LDAP_Sync_User_Data_FieldMap_Description": "Διαμορφώστε το πώς τα πεδία λογαριασμού χρήστη (όπως το ηλεκτρονικό ταχυδρομείο) κατοικείται από τα επίπεδα ρεκόρ στα LDAP (αφού διαπίστωσε). Ως παράδειγμα, `{\" ΣΟ \":\" όνομα \",\" mail \":\" e-mail \"}` θα επιλέξουν τα ανθρώπινα αναγνώσιμο όνομα ενός ατόμου από το χαρακτηριστικό cn, και το ηλεκτρονικό ταχυδρομείο τους από το χαρακτηριστικό αλληλογραφίας. Διαθέσιμα πεδία περιλαμβάνουν `name`, και` email`.",
- "LDAP_Sync_Users": "Συγχρονισμός χρήστες",
"LDAP_Test_Connection": "δοκιμή σύνδεσης",
"LDAP_Unique_Identifier_Field": "Μοναδικό αναγνωριστικό πεδίο",
"LDAP_Unique_Identifier_Field_Description": "Ποιο πεδίο θα χρησιμοποιηθεί για να συνδέσει το χρήστη LDAP και του χρήστη Rocket.Chat. Μπορείτε να ενημερώσετε πολλαπλές τιμές διαχωρισμένες με κόμμα για να προσπαθήσει να πάρει την τιμή από LDAP ρεκόρ. Προεπιλεγμένη τιμή είναι `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Χρησιμοποιήστε Αναζήτηση Προσαρμοσμένο Τομέα",
- "LDAP_Use_Custom_Domain_Search_Description": "Γράψτε τη δική σας φίλτρο για να αναζητήσετε χρήστες στο διακομιστή LDAP.",
"LDAP_Username_Field": "Όνομα Χρήστη πεδίο",
"LDAP_Username_Field_Description": "Ποιο πεδίο θα πρέπει να χρησιμοποιηθεί ως * όνομα * για τους νέους χρήστες. Αφήστε το κενό για να χρησιμοποιήσετε το όνομα χρήστη ενήμερο για login σελίδα. Μπορείτε να χρησιμοποιήσετε ετικέτες πρότυπο πάρα πολύ, όπως το `#{givenName}.#{sn}`. Προεπιλεγμένη τιμή είναι `sAMAccountName`.",
"Leave_Group_Warning": "Είστε σίγουροι ότι θέλετε να αποχωρήσετε από την ομάδα \" %s\";",
@@ -1042,19 +1028,19 @@
"The_user_wont_be_able_to_type_in_s": "Ο χρήστης δεν θα είναι σε θέση να πληκτρολογήσετε %s",
"Theme": "Θέμα",
"theme-color-content-background-color": "Περιεχόμενο Χρώμα φόντου",
+ "theme-color-custom-scrollbar-color": "Έθιμο κύλισης Χρώμα",
+ "theme-color-info-font-color": "Πληροφορίες Χρώμα γραμματοσειράς",
+ "theme-color-link-font-color": "Σύνδεσμος Χρώμα γραμματοσειράς",
"theme-color-primary-background-color": "Πρωτοβάθμια Χρώμα φόντου",
"theme-color-primary-font-color": "Πρωτοβάθμια Χρώμα γραμματοσειράς",
"theme-color-secondary-background-color": "Δευτεροβάθμιο χρώμα φόντου",
"theme-color-secondary-font-color": "Δευτεροβάθμια Χρώμα γραμματοσειράς",
- "theme-color-tertiary-background-color": "Τριτοβάθμια χρώμα φόντου",
- "theme-color-tertiary-font-color": "Τριτοβάθμια χρώμα γραμματοσειράς",
- "theme-color-link-font-color": "Σύνδεσμος Χρώμα γραμματοσειράς",
- "theme-color-info-font-color": "Πληροφορίες Χρώμα γραμματοσειράς",
- "theme-color-custom-scrollbar-color": "Έθιμο κύλισης Χρώμα",
"theme-color-status-away": "Μακριά Χρώμα Κατάσταση",
"theme-color-status-busy": "Απασχολημένος Χρώμα Κατάσταση",
"theme-color-status-offline": "Offline Χρώμα Κατάσταση",
"theme-color-status-online": "Σε απευθείας σύνδεση Χρώμα Κατάσταση",
+ "theme-color-tertiary-background-color": "Τριτοβάθμια χρώμα φόντου",
+ "theme-color-tertiary-font-color": "Τριτοβάθμια χρώμα γραμματοσειράς",
"theme-color-unread-notification-color": "Αδιάβαστη Ειδοποιήσεις Χρώμα",
"theme-custom-css": "έθιμο CSS",
"There_are_no_agents_added_to_this_department_yet": "Δεν υπάρχουν παράγοντες που προστίθενται σε αυτό το τμήμα ακόμα.",
@@ -1225,4 +1211,4 @@
"Your_mail_was_sent_to_s": "mail σας στάλθηκε στο %s",
"Your_password_is_wrong": "Ο κωδικός πρόσβασής σας είναι λάθος!",
"Your_push_was_sent_to_s_devices": "ώθηση σας στάλθηκε σε συσκευές %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index a306a41053ef9..706fefe310ede 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -11,41 +11,62 @@
"__username__was_set__role__by__user_by_": "__username__ was set __role__ by __user_by__",
"Accept": "Accept",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Accept incoming livechat requests even if there are no online agents",
- "Accept_with_no_online_agents": "Accept with no online agents",
+ "Accept_with_no_online_agents": "Accept with No Online Agents",
+ "access-mailer": "Access Mailer Screen",
+ "access-mailer_description": "Permission to send mass email to all users.",
+ "access-permissions": "Access Permissions Screen",
+ "access-permissions_description": "Modify permissions for various roles.",
"Access_not_authorized": "Access not authorized",
"Access_Token_URL": "Access Token URL",
"Accessing_permissions": "Accessing permissions",
"Account_SID": "Account SID",
"Accounts": "Accounts",
- "Accounts_AllowDeleteOwnAccount": "Allow users to delete own account",
+ "Accounts_AllowAnonymousRead": "Allow Anonymous Read",
+ "Accounts_AllowAnonymousWrite": "Allow Anonymous Write",
+ "Accounts_AllowDeleteOwnAccount": "Allow Users to Delete Own Account",
"Accounts_AllowedDomainsList": "Allowed Domains List",
"Accounts_AllowedDomainsList_Description": "Comma-separated list of allowed domains",
"Accounts_AllowEmailChange": "Allow Email Change",
"Accounts_AllowPasswordChange": "Allow Password Change",
"Accounts_AllowUserAvatarChange": "Allow User Avatar Change",
+ "Accounts_AllowRealNameChange": "Allow Name Change",
"Accounts_AllowUsernameChange": "Allow Username Change",
"Accounts_AllowUserProfileChange": "Allow User Profile Change",
"Accounts_AvatarResize": "Resize Avatars",
"Accounts_AvatarSize": "Avatar Size",
- "Accounts_AvatarStorePath": "Avatar Storage Path",
- "Accounts_AvatarStoreType": "Avatar Storage Type",
"Accounts_BlockedDomainsList": "Blocked Domains List",
"Accounts_BlockedDomainsList_Description": "Comma-separated list of blocked domains",
"Accounts_BlockedUsernameList": "Blocked Username List",
"Accounts_BlockedUsernameList_Description": "Comma-separated list of blocked usernames (case-insensitive)",
- "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:{\n\t\"role\": {\n\t\t\"type\": \"select\",\n\t\t\"defaultValue\": \"student\",\n\t\t\"options\": [\"teacher\", \"student\"],\n\t\t\"required\": true,\n\t\t\"modifyRecordField\": {\n\t\t\t\"array\": true,\n\t\t\t\"field\": \"roles\"\n\t\t}\n\t},\n\t\"twitter\": {\n\t\t\"type\": \"text\",\n\t\t\"required\": true,\n\t\t\"minLength\": 2,\n\t\t\"maxLength\": 10\n\t}\n} ",
+ "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Custom Fields to Show in User Info",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Default Username Prefix Suggestion",
+ "Accounts_Default_User_Preferences": "Default User Preferences",
+ "Accounts_Default_User_Preferences_audioNotifications": "Audio Notifications Default Alert",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Desktop Notifications Default Alert",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Mobile Notifications Default Alert",
+ "Accounts_Default_User_Preferences_not_available": "Failed to retrieve User Preferences because they haven't been set up by the user yet",
"Accounts_denyUnverifiedEmail": "Deny unverified email",
"Accounts_EmailVerification": "Email Verification",
"Accounts_EmailVerification_Description": "Make sure you have correct SMTP settings to use this feature",
+ "Accounts_Email_Approved": "[name]Your account was approved.
",
+ "Accounts_Email_Activated": "[name]Your account was activated.
",
+ "Accounts_Email_Deactivated": "[name]Your account was deactivated.
",
+ "Accounts_Email_Approved_Subject": "Account approved",
+ "Accounts_Email_Activated_Subject": "Account activated",
+ "Accounts_Email_Deactivated_Subject": "Account deactivated",
"Accounts_Enrollment_Email": "Enrollment Email",
- "Accounts_Enrollment_Email_Default": "Welcome to [Site_Name] Go to [Site_URL] and try the best open source chat solution available today!
",
+ "Accounts_Enrollment_Email_Default": "Welcome to [Site_Name] Go to [Site_URL] and try the best open source chat solution available today!
",
"Accounts_Enrollment_Email_Description": "You may use the following placeholders: [name], [fname], [lname] for the user's full name, first name or last name, respectively. [email] for the user's email. [Site_Name] and [Site_URL] for the Application Name and URL respectively. ",
"Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]",
- "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close",
+ "Accounts_Admin_Email_Approval_Needed_Default": "The user [name] ([email]) has been registered.
Please check \"Administration -> Users\" to activate or delete it.
",
+ "Accounts_Admin_Email_Approval_Needed_With_Reason_Default": "The user [name] ([email]) has been registered.
Reason: [reason]
Please check \"Administration -> Users\" to activate or delete it.
",
+ "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval",
+ "Accounts_ForgetUserSessionOnWindowClose": "Forget User Session on Window Close",
"Accounts_Iframe_api_method": "Api Method",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "Enabled",
- "Accounts_iframe_url": "Iframe Url",
+ "Accounts_iframe_url": "Iframe URL",
"Accounts_LoginExpiration": "Login Expiration in Days",
"Accounts_ManuallyApproveNewUsers": "Manually Approve New Users",
"Accounts_OAuth_Custom_Authorize_Path": "Authorize Path",
@@ -61,10 +82,15 @@
"Accounts_OAuth_Custom_Secret": "Secret",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token Sent Via",
+ "Accounts_OAuth_Custom_Identity_Token_Sent_Via": "Identity Token Sent Via",
"Accounts_OAuth_Custom_Username_Field": "Username field",
+ "Accounts_OAuth_Drupal": "Drupal Login Enabled",
+ "Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 Redirect URI",
+ "Accounts_OAuth_Drupal_id": "Drupal oAuth2 Client ID",
+ "Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Client Secret",
"Accounts_OAuth_Facebook": "Facebook Login",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
- "Accounts_OAuth_Facebook_id": "Facebook App Id",
+ "Accounts_OAuth_Facebook_id": "Facebook App ID",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
"Accounts_OAuth_Github": "OAuth Enabled",
"Accounts_OAuth_Github_callback_url": "Github Callback URL",
@@ -90,15 +116,23 @@
"Accounts_OAuth_Meteor_callback_url": "Meteor Callback URL",
"Accounts_OAuth_Meteor_id": "Meteor Id",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Tokenpass": "Tokenpass Login",
+ "Accounts_OAuth_Tokenpass_callback_url": "Tokenpass Callback URL",
+ "Accounts_OAuth_Tokenpass_id": "Tokenpass Id",
+ "Accounts_OAuth_Tokenpass_secret": "Tokenpass Secret",
+ "Accounts_OAuth_Proxy_host": "Proxy Host",
+ "Accounts_OAuth_Proxy_services": "Proxy Services",
"Accounts_OAuth_Twitter": "Twitter Login",
"Accounts_OAuth_Twitter_callback_url": "Twitter Callback URL",
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Login",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Password Reset",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Default Roles for Authentication Services",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Default roles (comma-separated) users will be given when registering through authentication services",
"Accounts_Registration_AuthenticationServices_Enabled": "Registration with Authentication Services",
"Accounts_RegistrationForm": "Registration Form",
"Accounts_RegistrationForm_Disabled": "Disabled",
@@ -106,24 +140,37 @@
"Accounts_RegistrationForm_Public": "Public",
"Accounts_RegistrationForm_Secret_URL": "Secret URL",
"Accounts_RegistrationForm_SecretURL": "Registration Form Secret URL",
- "Accounts_RegistrationForm_SecretURL_Description": "You must provide a random string that will be added to your registration URL. Example: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "You must provide a random string that will be added to your registration URL. Example: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Require Name For Signup",
"Accounts_RequirePasswordConfirmation": "Require Password Confirmation",
+ "Accounts_SearchFields": "Fields to Consider in Search",
"Accounts_SetDefaultAvatar": "Set Default Avatar",
"Accounts_SetDefaultAvatar_Description": "Tries to determine default avatar based on OAuth Account or Gravatar",
- "Accounts_ShowFormLogin": "Show form-based Login",
+ "Accounts_ShowFormLogin": "Show Form-Based Login",
"Accounts_UseDefaultBlockedDomainsList": "Use Default Blocked Domains List",
"Accounts_UseDNSDomainCheck": "Use DNS Domain Check",
- "Accounts_UserAddedEmail_Default": "Welcome to [Site_Name] Go to [Site_URL] and try the best open source chat solution available today!
You may login using your email: [email] and password: [password]. You may be required to change it after your first login.",
+ "Accounts_UserAddedEmail_Default": "
Welcome to [Site_Name] Go to [Site_URL] and try the best open source chat solution available today!
You may login using your email: [email] and password: [password]. You may be required to change it after your first login.",
"Accounts_UserAddedEmail_Description": "You may use the following placeholders:
[name], [fname], [lname] for the user's full name, first name or last name, respectively. [email] for the user's email. [password] for the user's password. [Site_Name] and [Site_URL] for the Application Name and URL respectively. ",
"Accounts_UserAddedEmailSubject_Default": "You have been added to [Site_Name]",
"Activate": "Activate",
"Activity": "Activity",
"Add": "Add",
+ "add-oauth-service": "Add Oauth Service",
+ "add-oauth-service_description": "Permission to add a new Oauth service",
+ "add-user": "Add User",
+ "add-user-to-any-c-room": "Add User to Any Public Channel",
+ "add-user-to-any-c-room_description": "Permission to add a user to any public channel",
+ "add-user-to-any-p-room": "Add User to Any Private Channel",
+ "add-user-to-any-p-room_description": "Permission to add a user to any private channel",
+ "add-user-to-joined-room": "Add User to Any Joined Channel",
+ "add-user-to-joined-room_description": "Permission to add a user to a currently joined channel",
+ "add-user_description": "Permission to add new users to the server via users screen",
"Add_agent": "Add agent",
"Add_custom_oauth": "Add custom oauth",
"Add_Domain": "Add Domain",
+ "Add_files_from": "Add files from",
"Add_manager": "Add manager",
+ "Add_Role": "Add Role",
"Add_user": "Add user",
"Add_User": "Add User",
"Add_users": "Add users",
@@ -133,52 +180,73 @@
"Additional_emails": "Additional Emails",
"Additional_Feedback": "Additional Feedback",
"Administration": "Administration",
+ "Adult_images_are_not_allowed": "Adult images are not allowed",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "After OAuth2 authentication, users will be redirected to this URL",
"Agent": "Agent",
"Agent_added": "Agent added",
"Agent_removed": "Agent removed",
+ "Alerts": "Alerts",
"Alias": "Alias",
- "Alias_Format": "Alias format",
+ "Alias_Format": "Alias Format",
"Alias_Format_Description": "Import messages from Slack with an alias; %s is replaced by the username of the user. If empty, no alias will be used.",
"Alias_Set": "Alias Set",
"All": "All",
"All_channels": "All channels",
"All_logs": "All logs",
"All_messages": "All messages",
+ "All_users": "All users",
+ "All_added_tokens_will_be_required_by_the_user": "All added tokens will be required by the user",
+ "All_users_in_the_channel_can_write_new_messages": "All users in the channel can write new messages",
"Allow_Invalid_SelfSigned_Certs": "Allow Invalid Self-Signed Certs",
"Allow_Invalid_SelfSigned_Certs_Description": "Allow invalid and self-signed SSL certificate's for link validation and previews.",
- "Always_open_in_new_window": "Always open in new window",
+ "Alphabetical": "Alphabetical",
+ "Allow_switching_departments": "Allow Visitor to Switch Departments",
+ "Always_open_in_new_window": "Always Open in New Window",
"Analytics_features_enabled": "Features Enabled",
"Analytics_features_messages_Description": "Tracks custom events related to actions a user does on messages.",
"Analytics_features_rooms_Description": "Tracks custom events related to actions on a channel or group (create, leave, delete).",
"Analytics_features_users_Description": "Tracks custom events related to actions related to users (password reset times, profile picture change, etc).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "Tracking ID",
"and": "and",
"And_more": "And __length__ more",
"Animals_and_Nature": "Animals & Nature",
+ "Announcement": "Announcement",
"API": "API",
"API_Allow_Infinite_Count": "Allow Getting Everything",
"API_Allow_Infinite_Count_Description": "Should calls to the REST API be allowed to return everything in one call?",
"API_Analytics": "Analytics",
+ "API_CORS_Origin": "CORS Origin",
"API_Default_Count": "Default Count",
"API_Default_Count_Description": "The default count for REST API results if the consumer did not provided any.",
+ "API_Drupal_URL": "Drupal Server URL",
+ "API_Drupal_URL_Description": "Example: https://domain.com (excluding trailing slash)",
"API_Embed": "Embed Link Previews",
"API_Embed_Description": "Whether embedded link previews are enabled or not when a user posts a link to a website.",
- "API_EmbedCacheExpirationDays": "Embed cache expiration days",
+ "API_Embed_UserAgent": "Embed Request User Agent",
+ "API_EmbedCacheExpirationDays": "Embed Cache Expiration Days",
"API_EmbedDisabledFor": "Disable Embed for Users",
"API_EmbedDisabledFor_Description": "Comma-separated list of usernames to disable the embedded link previews.",
"API_EmbedIgnoredHosts": "Embed Ignored Hosts",
"API_EmbedIgnoredHosts_Description": "Comma-separated list of hosts or CIDR addresses, eg. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Safe Ports",
"API_EmbedSafePorts_Description": "Comma-separated list of ports allowed for previewing.",
+ "API_Enable_CORS": "Enable CORS",
"API_Enable_Direct_Message_History_EndPoint": "Enable Direct Message History Endpoint",
"API_Enable_Direct_Message_History_EndPoint_Description": "This enables the `/api/v1/im.history.others` which allows the viewing of direct messages sent by other users that the caller is not part of.",
+ "API_Enable_Shields": "Enable Shields",
+ "API_Enable_Shields_Description": "Enable shields available at `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "Server URL",
"API_GitHub_Enterprise_URL_Description": "Example: http://domain.com (excluding trailing slash)",
"API_Gitlab_URL": "GitLab URL",
+ "API_Shield_Types": "Shield Types",
+ "API_Shield_Types_Description": "Types of shields to enable as a comma separated list, choose from `online`, `channel` or `*` for all",
"API_Token": "API Token",
+ "API_Tokenpass_URL": "Tokenpass Server URL",
+ "API_Tokenpass_URL_Description": "Example: https://domain.com (excluding trailing slash)",
"API_Upper_Count_Limit": "Max Record Amount",
"API_Upper_Count_Limit_Description": "What is the maximum number of records the REST API should return (when not unlimited)?",
- "API_User_Limit": "User Limit for adding all Users to Channel",
+ "API_User_Limit": "User Limit for Adding All Users to Channel",
"API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Key",
"Apiai_Language": "Api.ai Language",
@@ -188,19 +256,35 @@
"Application_updated": "Application updated",
"Apply_and_refresh_all_clients": "Apply and refresh all clients",
"Archive": "Archive",
+ "archive-room": "Archive Room",
+ "archive-room_description": "Permission to archive a channel",
"are_also_typing": "are also typing",
"are_typing": "are typing",
"Are_you_sure": "Are you sure?",
"Are_you_sure_you_want_to_delete_your_account": "Are you sure you want to delete your account?",
+ "Are_you_sure_you_want_to_disable_Facebook_integration": "Are you sure you want to disable Facebook integration?",
+ "assign-admin-role": "Assign Admin Role",
+ "assign-admin-role_description": "Permission to assign the admin role to other users",
"Assign_admin": "Assigning admin",
"at": "at",
+ "At_least_one_added_token_is_required_by_the_user": "At least one added token is required by the user",
"AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "File Uploaded",
+ "Attribute_handling": "Attribute handling",
+ "Audio": "Audio",
+ "Audio_message": "Audio message",
+ "Audio_Notification_Value_Description": "Can be any custom sound or the default ones: beep, chelle, ding, droplet, highbell, seasons",
+ "Audio_Notifications_Default_Alert": "Audio Notifications Default Alert",
+ "Audio_Notifications_Value": "Default Message Notification Audio",
"Auth_Token": "Auth Token",
"Author": "Author",
+ "Author_Information": "Author Information",
"Authorization_URL": "Authorization URL",
"Authorize": "Authorize",
+ "auto-translate": "Auto Translate",
+ "auto-translate_description": "Permission to use the auto translate tool",
"Auto_Load_Images": "Auto Load Images",
+ "Auto_Translate": "Auto-Translate",
"AutoLinker_Email": "AutoLinker Email",
"AutoLinker_Phone": "AutoLinker Phone",
"AutoLinker_Phone_Description": "Automatically linked for Phone numbers. e.g. `(123)456-7890`",
@@ -210,6 +294,11 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URLs",
"AutoLinker_Urls_www": "AutoLinker 'www' URLs",
"AutoLinker_UrlsRegExp": "AutoLinker URL Regular Expression",
+ "Automatic_Translation": "Automatic Translation",
+ "AutoTranslate_Change_Language_Description": "Changing the auto-translate language does not translate previous messages.",
+ "AutoTranslate_Enabled": "Enable Auto-Translate",
+ "AutoTranslate_Enabled_Description": "Enabling auto-translation will allow people with the auto-translate permission to have all messages automatically translated into their selected language. Fees may apply, see Google's Documentation ",
+ "AutoTranslate_GoogleAPIKey": "Google API Key",
"Available": "Available",
"Available_agents": "Available agents",
"Avatar": "Avatar",
@@ -224,9 +313,15 @@
"Away_male": "Away",
"Back": "Back",
"Back_to_applications": "Back to applications",
+ "Back_to_chat": "Back to chat",
+ "Back_to_integration_detail": "Back to the integration detail",
"Back_to_integrations": "Back to integrations",
"Back_to_login": "Back to login",
+ "Back_to_Manage_Apps": "Back to Manage Apps",
"Back_to_permissions": "Back to permissions",
+ "Backup_codes": "Backup codes",
+ "ban-user": "Ban User",
+ "ban-user_description": "Permission to ban a user from a channel",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta feature. Depends on Video Conference to be enabled.",
"Block_User": "Block User",
"Body": "Body",
@@ -235,7 +330,13 @@
"BotHelpers_userFields": "User Fields",
"BotHelpers_userFields_Description": "CSV of user fields that can be accessed by bots helper methods.",
"Branch": "Branch",
+ "Broadcast_Connected_Instances": "Broadcast Connected Instances",
"Bugsnag_api_key": "Bugsnag API Key",
+ "Build_Environment": "Build Environment",
+ "bulk-create-c": "Bulk Create Channels",
+ "bulk-create-c_description": "Permission to create channels in bulk",
+ "bulk-register-user": "Bulk Create Channels",
+ "bulk-register-user_description": "Permission to create channels in bulk",
"busy": "busy",
"Busy": "Busy",
"busy_female": "busy",
@@ -247,41 +348,48 @@
"Cancel": "Cancel",
"Cancel_message_input": "Cancel",
"Cannot_invite_users_to_direct_rooms": "Cannot invite users to direct rooms",
- "CAS_autoclose": "Autoclose login popup",
+ "Cannot_open_conversation_with_yourself": "Cannot Direct Message with yourself",
+ "CAS_autoclose": "Autoclose Login Popup",
"CAS_base_url": "SSO Base URL",
"CAS_base_url_Description": "The base URL of your external SSO service e.g: https://sso.example.undef/sso/",
- "CAS_button_color": "Login button background color",
- "CAS_button_label_color": "Login button text color",
- "CAS_button_label_text": "Login button label",
+ "CAS_button_color": "Login Button Background Color",
+ "CAS_button_label_color": "Login Button Text Color",
+ "CAS_button_label_text": "Login Button Label",
"CAS_enabled": "Enabled",
+ "CAS_Login_Layout": "CAS Login Layout",
"CAS_login_url": "SSO Login URL",
"CAS_login_url_Description": "The login URL of your external SSO service e.g: https://sso.example.undef/sso/login",
- "CAS_popup_height": "Login popup height",
- "CAS_popup_width": "Login popup width",
- "CAS_Sync_User_Data_Enabled": "Always sync User data",
+ "CAS_popup_height": "Login Popup Height",
+ "CAS_popup_width": "Login Popup Width",
+ "CAS_Sync_User_Data_Enabled": "Always Sync User Data",
"CAS_Sync_User_Data_Enabled_Description": "Always synchronize external CAS User data into available attributes upon login. Note: Attributes are always synced upon account creation anyway.",
- "CAS_Sync_User_Data_FieldMap": "Attribute map",
+ "CAS_Sync_User_Data_FieldMap": "Attribute Map",
"CAS_Sync_User_Data_FieldMap_Description": "Use this JSON input to build internal attributes (key) from external attributes (value). External attribute names enclosed with '%' will interpolated in value strings. Example, `{\"email\":\"%email%\", \"name\":\"%firstname%, %lastname%\"}` The attribute map is always interpolated. In CAS 1.0 only the `username` attribute is available. Available internal attributes are: username, name, email, rooms; rooms is a comma separated list of rooms to join upon user creation e.g: {\"rooms\": \"%team%,%department%\"} would join CAS users on creation to their team and department channel.",
"CAS_version": "CAS Version",
"CAS_version_Description": "Only use a supported CAS version supported by your CAS SSO service.",
"CDN_PREFIX": "CDN Prefix",
"Certificates_and_Keys": "Certificates and Keys",
- "Changing_email": "Changing email",
"Change_Room_Type": "Changing the Room Type",
+ "Changing_email": "Changing email",
"channel": "channel",
"Channel": "Channel",
"Channel_already_exist": "The channel `#%s` already exists.",
- "Channel_created": "Channel `#%s` created.",
+ "Channel_already_exist_static": "The channel already exists.",
"Channel_already_Unarchived": "Channel with name `#%s` is already in Unarchived state",
"Channel_Archived": "Channel with name `#%s` has been archived successfully",
+ "Channel_created": "Channel `#%s` created.",
"Channel_doesnt_exist": "The channel `#%s` does not exist.",
+ "Channel_name": "Channel Name",
+ "Channel_Name_Placeholder": "Please enter channel name...",
"Channel_to_listen_on": "Channel to listen on",
"Channel_Unarchived": "Channel with name `#%s` has been Unarchived successfully",
"Channels": "Channels",
+ "Channels_are_where_your_team_communicate": "Channels are where your team communicate",
"Channels_list": "List of public channels",
"Chat_button": "Chat button",
"Chat_closed": "Chat closed",
"Chat_closed_successfully": "Chat closed successfully",
+ "Chat_Now": "Chat Now",
"Chat_window": "Chat window",
"Chatops_Enabled": "Enable Chatops",
"Chatops_Title": "Chatops Panel",
@@ -290,25 +398,36 @@
"Choose_messages": "Choose messages",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Choose the alias that will appear before the username in messages.",
"Choose_the_username_that_this_integration_will_post_as": "Choose the username that this integration will post as.",
+ "clean-channel-history": "Clean Channel History",
+ "clean-channel-history_description": "Permission to Clear the history from channels",
"clear": "Clear",
- "clear_cache_now": "Clear cache now",
"Clear_all_unreads_question": "Clear all unreads?",
+ "clear_cache_now": "Clear Cache Now",
+ "clear_history": "Clear History",
"Click_here": "Click here",
"Click_here_for_more_info": "Click here for more info",
+ "Click_to_join": "Click to Join!",
"Client_ID": "Client ID",
"Client_Secret": "Client Secret",
"Clients_will_refresh_in_a_few_seconds": "Clients will refresh in a few seconds",
"close": "close",
"Close": "Close",
+ "close-livechat-room": "Close Livechat Room",
+ "close-livechat-room_description": "Permission to close the current LiveChat channel",
+ "close-others-livechat-room": "Close Livechat Room",
+ "close-others-livechat-room_description": "Permission to close other LiveChat channels",
"Closed": "Closed",
"Closed_by_visitor": "Closed by visitor",
"Closing_chat": "Closing chat",
- "Collapse_Embedded_Media_By_Default": "Collapse embedded media by default",
+ "Collapse_Embedded_Media_By_Default": "Collapse Embedded Media by Default",
"Color": "Color",
+ "Contains_Security_Fixes": "Contains Security Fixes",
"Commands": "Commands",
- "Comment_to_leave_on_closing_session": "Comment to leave on closing session",
+ "Comment_to_leave_on_closing_session": "Comment to Leave on Closing Session",
+ "Common_Access": "Common Access",
"Compact": "Compact",
"Confirm_password": "Confirm your password",
+ "Content": "Content",
"Conversation": "Conversation",
"Conversation_closed": "Conversation closed: __comment__.",
"Convert_Ascii_Emojis": "Convert ASCII to Emoji",
@@ -319,13 +438,26 @@
"Count": "Count",
"Cozy": "Cozy",
"Create": "Create",
+ "create-c": "Create Public Channels",
+ "create-c_description": "Permission to create public channels",
+ "create-d": "Create Direct Messages",
+ "create-d_description": "Permission to start direct messages",
+ "create-p": "Create Private Channels",
+ "create-p_description": "Permission to create private channels",
+ "create-user": "Create User",
+ "create-user_description": "Permission to create users",
"Create_A_New_Channel": "Create a New Channel",
"Create_new": "Create new",
+ "Create_unique_rules_for_this_channel": "Create unique rules for this channel",
"Created_at": "Created at",
"Created_at_s_by_s": "Created at %s by %s ",
+ "Created_at_s_by_s_triggered_by_s": "Created at %s by %s triggered by %s ",
+ "CRM_Integration": "CRM Integration",
"CROWD_Reject_Unauthorized": "Reject Unauthorized",
"Current_Chats": "Current Chats",
+ "Current_Status": "Current Status",
"Custom": "Custom",
+ "Custom_agent": "Custom agent",
"Custom_Emoji": "Custom Emoji",
"Custom_Emoji_Add": "Add New Emoji",
"Custom_Emoji_Added_Successfully": "Custom emoji added successfully",
@@ -338,10 +470,21 @@
"Custom_Fields": "Custom Fields",
"Custom_oauth_helper": "When setting up your OAuth Provider, you'll have to inform a Callback URL. Use %s .",
"Custom_oauth_unique_name": "Custom oauth unique name",
- "Custom_Script_Logged_In": "Custom Script for logged in users",
- "Custom_Script_Logged_Out": "Custom Script for logged out users",
+ "Custom_Script_Logged_In": "Custom Script for Logged In Users",
+ "Custom_Script_Logged_Out": "Custom Script for Logged Out Users",
+ "Custom_Scripts": "Custom Scripts",
+ "Custom_Sound_Add": "Add Custom Sound",
+ "Custom_Sound_Delete_Warning": "Deleting a sound cannot be undone.",
+ "Custom_Sound_Error_Invalid_Sound": "Invalid sound",
+ "Custom_Sound_Error_Name_Already_In_Use": "The custom sound name is already in use.",
+ "Custom_Sound_Has_Been_Deleted": "The custom sound has been deleted.",
+ "Custom_Sound_Info": "Custom Sound Info",
+ "Custom_Sound_Saved_Successfully": "Custom sound saved successfully",
+ "Custom_Sounds": "Custom Sounds",
"Custom_Translations": "Custom Translations",
- "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:{\n\t\"en\": {\n\t\t\"key\": \"translation\"\n\t},\n\t\"pt\": {\n\t\t\"key\": \"tradução\"\n\t}\n} ",
+ "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
+ "Customize": "Customize",
+ "CustomSoundsFilesystem": "Custom Sounds Filesystem",
"Dashboard": "Dashboard",
"Date": "Date",
"Date_From": "From",
@@ -353,6 +496,16 @@
"Decline": "Decline",
"Default": "Default",
"Delete": "Delete",
+ "delete-c": "Delete Public Channels",
+ "delete-c_description": "Permission to delete public channels",
+ "delete-d": "Delete Direct Messages",
+ "delete-d_description": "Permission to delete direct messages",
+ "delete-message": "Delete Message",
+ "delete-message_description": "Permission to delete a message within a room",
+ "delete-p": "Delete Private Channels",
+ "delete-p_description": "Permission to delete private channels",
+ "delete-user": "Delete User",
+ "delete-user_description": "Permission to delete users",
"Delete_message": "Delete message",
"Delete_my_account": "Delete my account",
"Delete_Room_Warning": "Deleting a room will delete all messages posted within the room. This cannot be undone.",
@@ -366,19 +519,44 @@
"Desktop": "Desktop",
"Desktop_Notification_Test": "Desktop Notification Test",
"Desktop_Notifications": "Desktop Notifications",
+ "Desktop_Notifications_Default_Alert": "Desktop Notifications Default Alert",
"Desktop_Notifications_Disabled": "Desktop Notifications are Disabled. Change your browser preferences if you need Notifications enabled.",
"Desktop_Notifications_Duration": "Desktop Notifications Duration",
"Desktop_Notifications_Duration_Description": "Seconds to display desktop notification. This may affect OS X Notification Center. Enter 0 to use default browser settings and not affect OS X Notification Center.",
"Desktop_Notifications_Enabled": "Desktop Notifications are Enabled",
+ "Different_Style_For_User_Mentions": "Different style for user mentions",
"Direct_message_someone": "Direct message someone",
"Direct_Messages": "Direct Messages",
- "Display_offline_form": "Display offline form",
+ "Direct_Reply": "Direct Reply",
+ "Direct_Reply_Debug": "Debug Direct Reply",
+ "Direct_Reply_Debug_Description": "[Beware] Enabling Debug mode would display your 'Plain Text Password' in Admin console.",
+ "Direct_Reply_Delete": "Delete Intercepted Emails",
+ "Direct_Reply_Enable": "Enable Direct Reply",
+ "Direct_Reply_Frequency": "Email Check Frequency",
+ "Direct_Reply_Frequency_Description": "(in minutes, default/minimum 2)",
+ "Direct_Reply_Host": "Direct Reply Host",
+ "Direct_Reply_IgnoreTLS": "IgnoreTLS",
+ "Direct_Reply_Password": "Password",
+ "Direct_Reply_Port": "Direct_Reply_Port",
+ "Direct_Reply_Protocol": "Direct Reply Protocol",
+ "Direct_Reply_Separator": "Separator",
+ "Direct_Reply_Separator_Description": "[Alter only if you know exactly what you are doing, refer docs] Separator between base & tag part of email",
+ "Direct_Reply_Username": "Username",
+ "Direct_Reply_Username_Description": "Please use absolute email, tagging is not allowed, it would be over-written",
+ "Disable_Facebook_integration": "Disable Facebook integration",
+ "Disable_Notifications": "Disable Notifications",
+ "Disable_two-factor_authentication": "Disable two-factor authentication",
+ "Disabled": "Disabled",
+ "Display_unread_counter": "Display number of unread messages",
+ "Display_offline_form": "Display Offline Form",
"Displays_action_text": "Displays action text",
+ "Do_not_display_unread_counter": "Do not display any counter of this channel",
"Do_you_want_to_change_to_s_question": "Do you want to change to %s ?",
"Domain": "Domain",
"Domain_added": "domain Added",
"Domain_removed": "Domain Removed",
"Domains": "Domains",
+ "Domains_allowed_to_embed_the_livechat_widget": "Comma-separated list of domains allowed to embed the livechat widget. Leave blank to allow all domains.",
"Download_Snippet": "Download",
"Drop_to_upload_file": "Drop to upload file",
"Dry_run": "Dry run",
@@ -389,14 +567,27 @@
"Duplicate_private_group_name": "A Private Group with name '%s' exists",
"Duration": "Duration",
"Edit": "Edit",
+ "edit-message": "Edit Message",
+ "edit-message_description": "Permission to edit a message within a room",
+ "edit-other-user-active-status": "Edit Other User Active Status",
+ "edit-other-user-active-status_description": "Permission to enable or disable other accounts",
+ "edit-other-user-info": "Edit Other User Information",
+ "edit-other-user-info_description": "Permission to change other user’s name, username or email address.",
+ "edit-other-user-password": "Edit Other User Password",
+ "edit-other-user-password_description": "Permission to modify other user’s passwords. Requires edit-other-user-info permission.",
+ "edit-privileged-setting": "Edit privileged Setting",
+ "edit-privileged-setting_description": "Permission to edit settings",
+ "edit-room": "Edit Room",
+ "edit-room_description": "Permission to edit a room’s name, topic, type (private or public status) and status (active or archived)",
"Edit_Custom_Field": "Edit Custom Field",
"Edit_Department": "Edit Department",
+ "Edit_previous_message": "`%s` - Edit previous message",
"Edit_Trigger": "Edit Trigger",
"edited": "edited",
"Editing_room": "Editing room",
"Editing_user": "Editing user",
"Email": "Email",
- "Email_address_to_send_offline_messages": "Email address to send offline messages",
+ "Email_address_to_send_offline_messages": "Email Address to Send Offline Messages",
"Email_already_exists": "Email already exists",
"Email_body": "Email body",
"Email_Change_Disabled": "Your Rocket.Chat administrator has disabled the changing of email",
@@ -407,6 +598,8 @@
"Email_Notification_Mode_All": "Every Mention/DM",
"Email_Notification_Mode_Disabled": "Disabled",
"Email_or_username": "Email or username",
+ "Email_Placeholder": "Please enter your email address...",
+ "Email_Placeholder_any": "Please enter email addresses...",
"Email_subject": "Subject",
"Email_verified": "Email verified",
"Emoji": "Emoji",
@@ -414,18 +607,23 @@
"Empty_title": "Empty title",
"Enable": "Enable",
"Enable_Desktop_Notifications": "Enable Desktop Notifications",
- "Enabled": "Enabled",
"Enable_Svg_Favicon": "Enable SVG favicon",
+ "Enable_two-factor_authentication": "Enable two-factor authentication",
+ "Enabled": "Enabled",
+ "Enable_Auto_Away": "Enable Auto Away",
"Encrypted_message": "Encrypted message",
"End_OTR": "End OTR",
"Enter_a_regex": "Enter a regex",
"Enter_a_room_name": "Enter a room name",
"Enter_a_username": "Enter a username",
+ "Enter_Alternative": "Alternative mode (send with Enter + Ctrl/Alt/Shift/CMD)",
+ "Enter_authentication_code": "Enter authentication code",
+ "Enter_Behaviour": "Enter key Behaviour",
+ "Enter_Behaviour_Description": "This changes if the enter key will send a message or do a line break",
"Enter_name_here": "Enter name here",
+ "Enter_Normal": "Normal mode (send with Enter)",
"Enter_to": "Enter to",
"Error": "Error",
- "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: Rocket.Chat requires oplog tailing when running in multiple instances",
- "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Please make sure your MongoDB is on ReplicaSet mode and MONGO_OPLOG_URL environment variable is defined correctly on the application server",
"error-action-not-allowed": "__action__ is not allowed",
"error-application-not-found": "Application not found",
"error-archived-duplicate-name": "There's an archived channel with name '__room_name__'",
@@ -437,6 +635,7 @@
"error-could-not-change-username": "Could not change username",
"error-delete-protected-role": "Cannot delete a protected role",
"error-department-not-found": "Department not found",
+ "error-direct-message-file-upload-not-allowed": "File sharing not allowed in direct messages",
"error-duplicate-channel-name": "A channel with name '__channel_name__' exists",
"error-email-domain-blacklisted": "The email domain is blacklisted",
"error-email-send-failed": "Error trying to send email: __message__",
@@ -458,7 +657,6 @@
"error-invalid-email-address": "Invalid email address",
"error-invalid-file-height": "Invalid file height",
"error-invalid-file-type": "Invalid file type",
- "error-direct-message-file-upload-not-allowed": "File sharing not allowed in direct messages",
"error-invalid-file-width": "Invalid file width",
"error-invalid-from-address": "You informed an invalid FROM address.",
"error-invalid-integration": "Invalid integration",
@@ -469,7 +667,7 @@
"error-invalid-redirectUri": "Invalid redirectUri",
"error-invalid-role": "Invalid role",
"error-invalid-room": "Invalid room",
- "error-invalid-room-name": "__room_name__ is not a valid room name, use only letters, numbers, hyphens and underscores",
+ "error-invalid-room-name": "__room_name__ is not a valid room name",
"error-invalid-room-type": "__type__ is not a valid room type.",
"error-invalid-settings": "Invalid settings provided",
"error-invalid-subscription": "Invalid subscription",
@@ -493,19 +691,29 @@
"error-the-field-is-required": "The field __field__ is required.",
"error-too-many-requests": "Error, too many requests. Please slow down. You must wait __seconds__ seconds before trying again.",
"error-user-is-not-activated": "User is not activated",
+ "error-user-has-no-roles": "User has no roles",
+ "error-user-limit-exceeded": "The number of users you are trying to invite to #channel_name exceeds the limit set by the administrator",
"error-user-not-in-room": "User is not in this room",
"error-user-registration-disabled": "User registration is disabled",
- "error-user-limit-exceeded" : "The number of users you are trying to invite to #channel_name exceeds the limit set by the administrator",
"error-user-registration-secret": "User registration is only allowed via Secret URL",
"error-you-are-last-owner": "You are the last owner. Please set new owner before leaving the room.",
"Error_changing_password": "Error changing password",
+ "Error_loading_pages": "Error loading pages",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Error: Rocket.Chat requires oplog tailing when running in multiple instances",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Please make sure your MongoDB is on ReplicaSet mode and MONGO_OPLOG_URL environment variable is defined correctly on the application server",
"Esc_to": "Esc to",
+ "Event_Trigger": "Event Trigger",
+ "Event_Trigger_Description": "Select which type of event will trigger this Outgoing WebHook Integration",
"every_30_minutes": "Once every 30 minutes",
"every_hour": "Once every hour",
"every_six_hours": "Once every six hours",
+ "Everyone_can_access_this_channel": "Everyone can access this channel",
"Example_s": "Example: %s",
- "Exclude_Botnames": "Exclude bots",
+ "Exclude_Botnames": "Exclude Bots",
"Exclude_Botnames_Description": "Do not propagate messages from bots whose name matches the regular expression above. If left empty, all messages from bots will be propagated.",
+ "External_Service": "External Service",
+ "External_Queue_Service_URL": "External Queue Service URL",
+ "Facebook_Page": "Facebook Page",
"False": "False",
"Favorite_Rooms": "Enable Favorite Rooms",
"Favorites": "Favorites",
@@ -516,41 +724,61 @@
"File_exceeds_allowed_size_of_bytes": "File exceeds allowed size of __size__.",
"File_not_allowed_direct_messages": "File sharing not allowed in direct messages.",
"File_type_is_not_accepted": "File type is not accepted.",
+ "File_uploaded": "File uploaded",
"FileUpload": "File Upload",
- "FileUpload_Enabled": "File Uploads Enabled",
"FileUpload_Disabled": "File uploads are disabled.",
+ "FileUpload_Enabled": "File Uploads Enabled",
"FileUpload_Enabled_Direct": "File Uploads Enabled in Direct Messages ",
"FileUpload_File_Empty": "File empty",
"FileUpload_FileSystemPath": "System Path",
+ "FileUpload_GoogleStorage_AccessId": "Google Storage Access Id",
+ "FileUpload_GoogleStorage_AccessId_Description": "The Access Id is generally in an email format, for example: \"example-test@example.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Google Storage Bucket Name",
+ "FileUpload_GoogleStorage_Bucket_Description": "The name of the bucket which the files should be uploaded to.",
+ "FileUpload_GoogleStorage_Proxy": "Proxy",
+ "FileUpload_GoogleStorage_Proxy_Description": "Proxy all file transmissions through your server instead of direct access to the asset's URL",
+ "FileUpload_GoogleStorage_Secret": "Google Storage Secret",
+ "FileUpload_GoogleStorage_Secret_Description": "Please follow these instructions and paste the result here.",
"FileUpload_MaxFileSize": "Maximum File Upload Size (in bytes)",
"FileUpload_MediaType_NotAccepted": "Media Types Not Accepted",
"FileUpload_MediaTypeWhiteList": "Accepted Media Types",
"FileUpload_MediaTypeWhiteListDescription": "Comma-separated list of media types. Leave it blank for accepting all media types.",
- "FileUpload_ProtectFiles": "Protect uploaded files",
+ "FileUpload_ProtectFiles": "Protect Uploaded Files",
"FileUpload_ProtectFilesDescription": "Only authenticated users will have access",
- "FileUpload_S3_Acl": "Amazon S3 acl",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 bucket name",
+ "FileUpload_S3_Acl": "Acl",
+ "FileUpload_S3_AWSAccessKeyId": "Access Key",
+ "FileUpload_S3_AWSSecretAccessKey": "Secret Key",
+ "FileUpload_S3_Bucket": "Bucket name",
"FileUpload_S3_BucketURL": "Bucket URL",
- "FileUpload_S3_CDN": "CDN domain for downloads",
+ "FileUpload_S3_CDN": "CDN Domain for Downloads",
+ "FileUpload_S3_ForcePathStyle": "Force Path Style",
+ "FileUpload_S3_Proxy": "Proxy",
+ "FileUpload_S3_Proxy_Description": "Proxy all file transmissions through your server instead of direct access to the asset's URL",
"FileUpload_S3_Region": "Region",
- "FileUpload_S3_URLExpiryTimeSpan": "URLs expiration timespan",
+ "FileUpload_S3_SignatureVersion": "Signature Version",
+ "FileUpload_S3_URLExpiryTimeSpan": "URLs Expiration Timespan",
"FileUpload_S3_URLExpiryTimeSpan_Description": "Time after which Amazon S3 generated URLs will no longer be valid (in seconds). If set to less than 5 seconds, this field will be ignored.",
"FileUpload_Storage_Type": "Storage Type",
+ "First_Channel_After_Login": "First Channel After Login",
"Flags": "Flags",
"Follow_social_profiles": "Follow our social profiles, fork us on github and share your thoughts about the rocket.chat app on our trello board.",
+ "Fonts": "Fonts",
"Food_and_Drink": "Food & Drink",
"Footer": "Footer",
+ "Footer_Direct_Reply": "Footer When Direct Reply is Enabled",
+ "For_more_details_please_check_our_docs": "For more details please check our docs.",
"For_your_security_you_must_enter_your_current_password_to_continue": "For your security, you must enter your current password to continue",
- "Force_Disable_OpLog_For_Cache": "Force disable OpLog for Cache",
+ "force-delete-message": "Force Delete Message",
+ "force-delete-message_description": "Permission to delete a message bypassing all restrictions",
+ "Force_Disable_OpLog_For_Cache": "Force Disable OpLog for Cache",
"Force_Disable_OpLog_For_Cache_Description": "Will not use OpLog to sync cache even when it's available",
"Force_SSL": "Force SSL",
"Force_SSL_Description": "*Caution!* _Force SSL_ should never be used with reverse proxy. If you have a reverse proxy, you should do the redirect THERE. This option exists for deployments like Heroku, that does not allow the redirect configuration at the reverse proxy.",
"Forgot_password": "Forgot your password",
"Forgot_Password_Description": "You may use the following placeholders: [Forgot_Password_Url] for the password recovery URL. [name], [fname], [lname] for the user's full name, first name or last name, respectively. [email] for the user's email. [Site_Name] and [Site_URL] for the Application Name and URL respectively. ",
- "Forgot_Password_Email_Subject": "[Site_Name] - Password Recovery",
"Forgot_Password_Email": "Click here to reset your password.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Password Recovery",
+ "Forgot_password_section": "Forgot password",
"Forward": "Forward",
"Forward_chat": "Forward chat",
"Forward_to_department": "Forward to department",
@@ -565,18 +793,48 @@
"Give_a_unique_name_for_the_custom_oauth": "Give a unique name for the custom oauth",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Give the application a name. This will be seen by your users.",
"Global": "Global",
+ "Global_Search": "Global search",
+ "Google_Vision_usage_limit_exceeded": "Google Vision usage limit exceeded",
+ "GoogleCloudStorage": "Google Cloud Storage",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "Service account key JSON file. More information can be found [here](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
"GoogleTagManager_id": "Google Tag Manager Id",
+ "GoogleVision_Block_Adult_Images": "Block Adult Images",
+ "GoogleVision_Block_Adult_Images_Description": "Blocking adult images will not work once the monthly limit has been reached",
+ "GoogleVision_Current_Month_Calls": "Current Month Calls",
+ "GoogleVision_Enable": "Enable Google Vision",
+ "GoogleVision_Max_Monthly_Calls": "Max Monthly Calls",
+ "GoogleVision_Max_Monthly_Calls_Description": "Use 0 for unlimited",
+ "GoogleVision_ServiceAccount": "Google Vision Service Account",
+ "GoogleVision_ServiceAccount_Description": "Create a server key (JSON format) and paste the JSON content here",
+ "GoogleVision_Type_Document": "Document Text Detection",
+ "GoogleVision_Type_Faces": "Face Detection",
+ "GoogleVision_Type_Labels": "Labels Detection",
+ "GoogleVision_Type_Landmarks": "Landmarks Detection",
+ "GoogleVision_Type_Logos": "Logos Detection",
+ "GoogleVision_Type_Properties": "Properties (Color) Detection",
+ "GoogleVision_Type_SafeSearch": "SafeSearch Detection",
+ "GoogleVision_Type_Similar": "Search Similar Images",
+ "Group_by_Type": "Group by Type",
+ "Group_favorites": "Group favorites",
+ "Group_mentions_only": "Group mentions only",
"Guest_Pool": "Guest Pool",
"Hash": "Hash",
"Header": "Header",
+ "Header_and_Footer": "Header and Footer",
+ "Helpers": "Helpers",
+ "Hex_Color_Preview": "Hex Color Preview",
"Hidden": "Hidden",
"Hide_Avatars": "Hide Avatars",
- "Hide_flextab": "Hide right side bar with click",
+ "Hide_counter": "Hide counter",
+ "Hide_flextab": "Hide Right Sidebar with Click",
"Hide_Group_Warning": "Are you sure you want to hide the group \"%s\"?",
+ "Hide_Livechat_Warning": "Are you sure you want to hide the livechat with \"%s\"?",
"Hide_Private_Warning": "Are you sure you want to hide the discussion with \"%s\"?",
- "Hide_room": "Hide room",
+ "Hide_roles": "Hide Roles",
+ "Hide_room": "Hide Room",
"Hide_Room_Warning": "Are you sure you want to hide the room \"%s\"?",
- "Hide_usernames": "Hide usernames",
+ "Hide_Unread_Room_Status": "Hide Unread Room Status",
+ "Hide_usernames": "Hide Usernames",
"Highlights": "Highlights",
"Highlights_How_To": "To be notified when someone mentions a word or phrase, add it here. You can separate words or phrases with commas. Highlight Words are not case sensitive.",
"Highlights_List": "Highlight words",
@@ -586,27 +844,37 @@
"Hours": "Hours",
"How_friendly_was_the_chat_agent": "How friendly was the chat agent?",
"How_knowledgeable_was_the_chat_agent": "How knowledgeable was the chat agent?",
- "How_long_to_wait_after_agent_goes_offline": "How long to wait after agent goes offline",
+ "How_long_to_wait_after_agent_goes_offline": "How Long to Wait After Agent Goes Offline",
"How_responsive_was_the_chat_agent": "How responsive was the chat agent?",
"How_satisfied_were_you_with_this_chat": "How satisfied were you with this chat?",
- "How_to_handle_open_sessions_when_agent_goes_offline": "How to handle open sessions when agent goes offline",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "How to Handle Open Sessions When Agent Goes Offline",
+ "If_this_email_is_registered": "If this email is registered, we'll send instructions on how to reset your password. If you do not receive an email shortly, please come back and try again.",
"If_you_are_sure_type_in_your_password": "If you are sure type in your password:",
"If_you_are_sure_type_in_your_username": "If you are sure type in your username:",
+ "If_you_dont_have_one_send_an_email_to_omni_rocketchat_to_get_yours": "If you don't have one send an email to [omni@rocket.chat](mailto:omni@rocket.chat) to get yours.",
+ "Iframe_Integration": "Iframe Integration",
"Iframe_Integration_receive_enable": "Enable Receive",
"Iframe_Integration_receive_enable_Description": "Allow parent window to send commands to Rocket.Chat.",
- "Iframe_Integration_receive_origin": "Receive origins",
- "Iframe_Integration_receive_origin_Description": "Only pages with given origin will be able to send commands or `*` for all origins. You can use multiple values separated by `,`. Example `http://localhost,https://localhost`",
+ "Iframe_Integration_receive_origin": "Receive Origins",
+ "Iframe_Integration_receive_origin_Description": "Origins with protocol prefix, separated by commas, which are allowed to receive commands e.g. 'https://localhost, http://localhost', or * to allow receiving from anywhere.",
"Iframe_Integration_send_enable": "Enable Send",
"Iframe_Integration_send_enable_Description": "Send events to parent window",
- "Iframe_Integration_send_target_origin": "Send target origin",
- "Iframe_Integration_send_target_origin_Description": "Only pages with given origin will be able to listen to events or `*` for all origins. Example `http://localhost`",
+ "Iframe_Integration_send_target_origin": "Send Target Origin",
+ "Iframe_Integration_send_target_origin_Description": "Origin with protocol prefix, which commands are sent to e.g. 'https://localhost', or * to allow sending to anywhere.",
+ "IMAP_intercepter_already_running": "IMAP intercepter already running",
+ "IMAP_intercepter_Not_running": "IMAP intercepter Not running",
+ "Impersonate_next_agent_from_queue": "Impersonate next agent from queue",
+ "Impersonate_user": "Impersonate User",
+ "Impersonate_user_description": "When enabled, integration posts as the user that triggered integration",
+ "Import": "Import",
"Importer_Archived": "Archived",
"Importer_CSV_Information": "The CSV importer requires a specific format, please read the documentation for how to structure your zip file:",
- "Importer_HipChatEnterprise_Information": "The file uploaded must be a decrypted tar.gz, please read the documentation for further information:",
- "Importer_HipChatEnterprise_BetaWarning": "Please be aware that this import is still a work in progress, please report any errors which occur in GitHub:",
"Importer_done": "Importing complete!",
"Importer_finishing": "Finishing up the import.",
"Importer_From_Description": "Imports __from__ data into Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Please be aware that this import is still a work in progress, please report any errors which occur in GitHub:",
+ "Importer_HipChatEnterprise_Information": "The file uploaded must be a decrypted tar.gz, please read the documentation for further information:",
+ "Importer_Slack_Users_CSV_Information": "The file uploaded must be Slack's Users export file, which is a CSV file. See here for more information:",
"Importer_import_cancelled": "Import cancelled.",
"Importer_import_failed": "An error occurred while running the import.",
"Importer_importing_channels": "Importing the channels.",
@@ -623,28 +891,67 @@
"Importer_setup_error": "An error occurred while setting up the importer.",
"Importer_Source_File": "Source File Selection",
"Incoming_Livechats": "Incoming Livechats",
- "inline_code": "inline_code",
+ "Incoming_WebHook": "Incoming WebHook",
+ "initials_avatar": "Initials Avatar",
+ "inline_code": "inline code",
"Install_Extension": "Install Extension",
"Install_FxOs": "Install Rocket.Chat on your Firefox",
"Install_FxOs_done": "Great! You can now use Rocket.Chat via the icon on your homescreen. Have fun with Rocket.Chat!",
"Install_FxOs_error": "Sorry, that did not work as intended! The following error appeared:",
"Install_FxOs_follow_instructions": "Please confirm the app installation on your device (press \"Install\" when prompted).",
+ "Install_package": "Install package",
"Installation": "Installation",
"Installed_at": "Installed at",
+ "Instance_Record": "Instance Record",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instructions to your visitor fill the form to send a message",
- "Impersonate_user": "Impersonate User",
- "Impersonate_user_description": "When enabled, integration posts as the user that triggered integration",
"Integration_added": "Integration has been added",
+ "Integration_Advanced_Settings": "Advanced Settings",
+ "Integration_disabled": "Integration disabled",
+ "Integration_History_Cleared": "Integration History Successfully Cleared",
"Integration_Incoming_WebHook": "Incoming WebHook Integration",
"Integration_New": "New Integration",
"Integration_Outgoing_WebHook": "Outgoing WebHook Integration",
- "Integration_updated": "Integration has been updated",
+ "Integration_Outgoing_WebHook_History": "Outgoing WebHook Integration History",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Data Passed to Integration",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Data Passed to URL",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Error Stacktrace",
+ "Integration_Outgoing_WebHook_History_Http_Response": "HTTP Response",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "HTTP Response Error",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Messages Sent from Prepare Step",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Messages Sent from Process Response Step",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Time it Ended or Error'd",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Time Integration Triggered",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "Last Trigger Step",
+ "Integration_Outgoing_WebHook_No_History": "This outgoing webhook integration has yet to have any history recorded.",
+ "Integration_Retry_Count": "Retry Count",
+ "Integration_Retry_Count_Description": "How many times should the integration be tried if the call to the url fails?",
+ "Integration_Retry_Delay": "Retry Delay",
+ "Integration_Retry_Delay_Description": "Which delay algorithm should the retrying use? 10^x or 2^x or x*2",
+ "Integration_Retry_Failed_Url_Calls": "Retry Failed Url Calls",
+ "Integration_Retry_Failed_Url_Calls_Description": "Should the integration try a reasonable amount of time if the call out to the url fails?",
+ "Integration_Run_When_Message_Is_Edited": "Run On Edits",
+ "Integration_Run_When_Message_Is_Edited_Description": "Should the integration run when the message is edited? Setting this to false will cause the integration to only run on new messages.",
+ "Integration_updated": "Integration has been updated.",
+ "Integration_Word_Trigger_Placement": "Word Placement Anywhere",
+ "Integration_Word_Trigger_Placement_Description": "Should the Word be Triggered when placed anywhere in the sentence other than the beginning?",
"Integrations": "Integrations",
"Integrations_for_all_channels": "Enter all_public_channels to listen on all public channels, all_private_groups to listen on all private groups, and all_direct_messages to listen to all direct messages.",
+ "Integrations_Outgoing_Type_FileUploaded": "File Uploaded",
+ "Integrations_Outgoing_Type_RoomArchived": "Room Archived",
+ "Integrations_Outgoing_Type_RoomCreated": "Room Created (public and private)",
+ "Integrations_Outgoing_Type_RoomJoined": "User Joined Room",
+ "Integrations_Outgoing_Type_RoomLeft": "User Left Room",
+ "Integrations_Outgoing_Type_SendMessage": "Message Sent",
+ "Integrations_Outgoing_Type_UserCreated": "User Created",
"InternalHubot": "Internal Hubot",
- "InternalHubot_ScriptsToLoad": "Scripts to load",
- "InternalHubot_ScriptsToLoad_Description": "Please enter a comma separated list of scripts to load from https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_PathToLoadCustomScripts": "Folder to Load the Scripts",
+ "InternalHubot_reload": "Reload the scripts",
+ "InternalHubot_ScriptsToLoad": "Scripts to Load",
+ "InternalHubot_ScriptsToLoad_Description": "Please enter a comma separated list of scripts to load from your custom folder",
"InternalHubot_Username_Description": "This must be a valid username of a bot registered on your server.",
+ "InternalHubot_EnableForChannels": "Enable for Public Channels",
+ "InternalHubot_EnableForDirectMessages": "Enable for Direct Messages",
+ "InternalHubot_EnableForPrivateGroups": "Enable for Private Channels",
"Invalid_confirm_pass": "The password confirmation does not match password",
"Invalid_email": "The email entered is invalid",
"Invalid_Export_File": "The file uploaded isn't a valid %s export file.",
@@ -652,44 +959,56 @@
"Invalid_name": "The name must not be empty",
"Invalid_notification_setting_s": "Invalid notification setting: %s",
"Invalid_pass": "The password must not be empty",
- "Invalid_room_name": "%s is not a valid room name, use only letters, numbers, hyphens and underscores",
+ "Invalid_reason": "The reason to join must not be empty",
+ "Invalid_room_name": "%s is not a valid room name",
"Invalid_secret_URL_message": "The URL provided is invalid.",
+ "Invalid_setting_s": "Invalid setting: %s",
+ "Invalid_two_factor_code": "Invalid two factor code",
"invisible": "invisible",
"Invisible": "Invisible",
+ "Invitation": "Invitation",
"Invitation_HTML": "Invitation HTML",
"Invitation_HTML_Default": "You have been invited to [Site_Name] Go to [Site_URL] and try the best open source chat solution available today!
",
"Invitation_HTML_Description": "You may use the following placeholders: [email] for the recipient email. [Site_Name] and [Site_URL] for the Application Name and URL respectively. ",
"Invitation_Subject": "Invitation Subject",
"Invitation_Subject_Default": "You have been invited to [Site_Name]",
"Invite_user_to_join_channel": "Invite one user to join this channel",
+ "Invite_user_to_join_channel_all_from": "Invite all users from [#channel] to join this channel",
"Invite_user_to_join_channel_all_to": "Invite all users from this channel to join [#channel]",
- "Invite_user_to_join_channel_all_from": "Invite all users from [#channel] to join this channel",
"Invite_Users": "Invite Users",
- "is_also_typing": "is also typing",
- "is_also_typing_female": "is also typing",
- "is_also_typing_male": "is also typing",
- "is_typing": "is typing",
- "is_typing_female": "is typing",
- "is_typing_male": "is typing",
"IRC_Channel_Join": "Output of the JOIN command.",
"IRC_Channel_Leave": "Output of the PART command.",
- "IRC_Description": "Internet Relay Chat (IRC) is a text-based group communication tool. Users join uniquely named channels, or rooms, for open discussion. IRC also supports private messages between indivdiual users and file sharing capabilities. This package integrates these layers of functionality with Rocket.Chat.",
- "IRC_Enabled": "Attempt to integrate IRC support. Changing this value requires restarting Rocket.Chat.",
- "IRC_Private_Message": "Output of the PRIVMSG command.",
"IRC_Channel_Users": "Output of the NAMES command.",
"IRC_Channel_Users_End": "End of output of the NAMES command.",
+ "IRC_Description": "Internet Relay Chat (IRC) is a text-based group communication tool. Users join uniquely named channels, or rooms, for open discussion. IRC also supports private messages between individual users and file sharing capabilities. This package integrates these layers of functionality with Rocket.Chat.",
+ "IRC_Enabled": "Attempt to integrate IRC support. Changing this value requires restarting Rocket.Chat.",
"IRC_Hostname": "The IRC host server to connect to.",
"IRC_Login_Fail": "Output upon a failed connection to the IRC server.",
"IRC_Login_Success": "Output upon a successful connection to the IRC server.",
"IRC_Message_Cache_Size": "The cache limit for outbound message handling.",
"IRC_Port": "The port to bind to on the IRC host server.",
+ "IRC_Private_Message": "Output of the PRIVMSG command.",
"IRC_Quit": "Output upon quitting an IRC session.",
+ "is_also_typing": "is also typing",
+ "is_also_typing_female": "is also typing",
+ "is_also_typing_male": "is also typing",
+ "is_typing": "is typing",
+ "is_typing_female": "is typing",
+ "is_typing_male": "is typing",
+ "Issue_Links": "Issue tracker links",
+ "IssueLinks_Incompatible": "Warning: do not enable this and the 'Hex Color Preview' at the same time.",
+ "IssueLinks_LinkTemplate": "Template for issue links",
+ "IssueLinks_LinkTemplate_Description": "Template for issue links; %s will be replaced by the issue number.",
"It_works": "It works",
+ "Idle_Time_Limit": "Idle Time Limit",
"italics": "italics",
"Jitsi_Chrome_Extension": "Chrome Extension Id",
"Jitsi_Enable_Channels": "Enable in Channels",
"join": "Join",
+ "join-without-join-code": "Join Without Join Code",
+ "join-without-join-code_description": "Permission to bypass the join code in channels with join code enabled",
"Join_audio_call": "Join audio call",
+ "Join_Chat": "Join Chat",
"Join_default_channels": "Join default channels",
"Join_the_Community": "Join the Community",
"Join_the_given_channel": "Join the given channel",
@@ -699,12 +1018,27 @@
"Jump_to_first_unread": "Jump to first unread",
"Jump_to_message": "Jump to message",
"Jump_to_recent_messages": "Jump to recent messages",
+ "Just_invited_people_can_access_this_channel": "Just invited people can access this channel.",
"Katex_Dollar_Syntax": "Allow Dollar Syntax",
"Katex_Dollar_Syntax_Description": "Allow using $$katex block$$ and $inline katex$ syntaxes",
"Katex_Enabled": "Katex Enabled",
"Katex_Enabled_Description": "Allow using katex for math typesetting in messages",
"Katex_Parenthesis_Syntax": "Allow Parenthesis Syntax",
"Katex_Parenthesis_Syntax_Description": "Allow using \\[katex block\\] and \\(inline katex\\) syntaxes",
+ "Keep_default_user_settings": "Keep the default settings",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Edit previous message",
+ "Keyboard_Shortcuts_Keys_1": "Ctrl + p ",
+ "Keyboard_Shortcuts_Keys_2": "Up Arrow ",
+ "Keyboard_Shortcuts_Keys_3": "Command (or Alt ) + Left Arrow ",
+ "Keyboard_Shortcuts_Keys_4": "Command (or Alt ) + Up Arrow ",
+ "Keyboard_Shortcuts_Keys_5": "Command (or Alt ) + Right Arrow ",
+ "Keyboard_Shortcuts_Keys_6": "Command (or Alt ) + Down Arrow ",
+ "Keyboard_Shortcuts_Keys_7": "Shift + Enter ",
+ "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "Move to the beginning of the message",
+ "Keyboard_Shortcuts_Move_To_End_Of_Message": "Move to the end of the message",
+ "Keyboard_Shortcuts_New_Line_In_Message": "New line in message compose input",
+ "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Open Channel / User search",
+ "Keyboard_Shortcuts_Title": "Keyboard Shortcuts",
"Knowledge_Base": "Knowledge Base",
"Label": "Label",
"Language": "Language",
@@ -723,67 +1057,83 @@
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
"LDAP_Connect_Timeout": "Connection Timeout (ms)",
- "LDAP_Custom_Domain_Search": "Custom Domain Search",
- "LDAP_Custom_Domain_Search_Description": "A piece of JSON that governs bind and connection info and is of the form: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Default Domain",
+ "LDAP_Default_Domain_Description": "If provided the Default Domain will be used to create an unique email for users where email was not imported from LDAP. The email will be mounted as `username@default_domain` or `unique_id@default_domain`. Example: `rocket.chat`",
"LDAP_Description": "LDAP is a hierarchical database that many companies use to provide single sign on - a facility for sharing one password between multiple sites and services. For advanced configuration information and examples, please consult our wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Domain Base",
- "LDAP_Domain_Base_Description": "The fully qualified Distinguished Name (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use search filter to control access.",
- "LDAP_Domain_Search_Filter": "Domain Search Filter",
- "LDAP_Domain_Search_Filter_Description": "If specified, only users that match this filter will be allowed to log in. If no filter is specified, all users within the scope of the specified domain base will be able to sign in. E.g. for Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. E.g. for OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Category",
- "LDAP_Domain_Search_Object_Category_Description": "The *objectCategory* that identify your users. Leave empty for *OpenLDAP*. E.g. `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Domain Search Object Class",
- "LDAP_Domain_Search_Object_Class_Description": "The *objectclass* that identify your users. E.g. `organizationalPerson`, `user`, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Domain Search Password",
- "LDAP_Domain_Search_Password_Description": "The password for the domain search user.",
- "LDAP_Domain_Search_User": "Domain Search User",
- "LDAP_Domain_Search_User_Description": "The LDAP user that performs user lookups to authenticate other users when they sign in. This is typically a service account created specifically for third-party integrations. Use a fully qualified name, such as `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search User ID",
- "LDAP_Domain_Search_User_ID_Description": "The LDAP attribute that identifies the LDAP user who attempts authentication. This field should be `sAMAccountName` for most Active Directory installations, but it may be `uid` for other LDAP solutions, such as OpenLDAP. You can use `mail` to identify users by email or whatever attribute you want. You can use multiple values separated by comma to allow users to login using multiple identifiers like username or email.",
+ "LDAP_BaseDN": "Base DN",
+ "LDAP_BaseDN_Description": "The fully qualified Distinguished Name (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. Example: `ou=Users+ou=Projects,dc=Example,dc=com`. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use search filter to control access.",
+ "LDAP_User_Search_Field": "Search Field",
+ "LDAP_User_Search_Field_Description": "The LDAP attribute that identifies the LDAP user who attempts authentication. This field should be `sAMAccountName` for most Active Directory installations, but it may be `uid` for other LDAP solutions, such as OpenLDAP. You can use `mail` to identify users by email or whatever attribute you want. You can use multiple values separated by comma to allow users to login using multiple identifiers like username or email.",
+ "LDAP_User_Search_Filter": "Filter",
+ "LDAP_User_Search_Filter_Description": "If specified, only users that match this filter will be allowed to log in. If no filter is specified, all users within the scope of the specified domain base will be able to sign in. E.g. for Active Directory `memberOf=cn=ROCKET_CHAT,ou=General Groups`. E.g. for OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_User_Search_Scope": "Scope",
+ "LDAP_Authentication": "Enable",
+ "LDAP_Authentication_Password": "Password",
+ "LDAP_Authentication_UserDN": "User DN",
+ "LDAP_Authentication_UserDN_Description": "The LDAP user that performs user lookups to authenticate other users when they sign in. This is typically a service account created specifically for third-party integrations. Use a fully qualified name, such as `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "Enable",
"LDAP_Enable_Description": "Attempt to utilize LDAP for authentication.",
"LDAP_Encryption": "Encryption",
"LDAP_Encryption_Description": "The encryption method used to secure communications to the LDAP server. Examples include `plain` (no encryption), `SSL/LDAPS` (encrypted from the start), and `StartTLS` (upgrade to encrypted communication once connected).",
+ "LDAP_Internal_Log_Level": "Internal Log Level",
+ "LDAP_Group_Filter_Enable": "Enable LDAP User Group Filter",
+ "LDAP_Group_Filter_Enable_Description": "Restrict access to users in a LDAP group Useful for OpenLDAP servers without overlays that not permit *memberOf* filter",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Group ID Attribute",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "E.g. *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute": "Group Member Attribute",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "E.g. *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format": "Group Member Format",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "E.g. *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Group name",
+ "LDAP_Group_Filter_Group_Name_Description": "Group name to which it belong the user",
+ "LDAP_Group_Filter_ObjectClass": "Group ObjectClass",
+ "LDAP_Group_Filter_ObjectClass_Description": "The *objectclass* that identify the groups. E.g. OpenLDAP:groupOfUniqueNames",
"LDAP_Host": "Host",
"LDAP_Host_Description": "The LDAP host, e.g. `ldap.example.com` or `10.0.0.30`.",
"LDAP_Idle_Timeout": "Idle Timeout (ms)",
- "LDAP_Import_Users": "Import LDAP users",
+ "LDAP_Idle_Timeout_Description": "How many milliseconds wait after the latest LDAP operation until close the connection. (Each operation will open a new connection)",
"LDAP_Import_Users_Description": "It True sync process will be import all LDAP users *Caution!* Specify search filter to not import excess users.",
"LDAP_Login_Fallback": "Login Fallback",
"LDAP_Login_Fallback_Description": "If the login on LDAP is not successful try to login in default/local account system. Helps when the LDAP is down for some reason.",
- "LDAP_Merge_Existing_Users": "Merge existing users",
+ "LDAP_Merge_Existing_Users": "Merge Existing Users",
"LDAP_Merge_Existing_Users_Description": "*Caution!* When importing an user from LDAP and an user with same username already exists the LDAP info and password will be set into the existing user.",
"LDAP_Port": "Port",
"LDAP_Port_Description": "Port to access LDAP. eg: `389` or `636` for LDAPS",
+ "LDAP_Reconnect": "Reconnect",
+ "LDAP_Reconnect_Description": "Try to reconnect automatically when connection is interrupted by some reason while executing operations",
"LDAP_Reject_Unauthorized": "Reject Unauthorized",
+ "LDAP_Reject_Unauthorized_Description": "Disable this option to allow certificates that can not be verified. Usually Self Signed Certificates will require this option disabled to work",
"LDAP_Sync_User_Avatar": "Sync User Avatar",
- "LDAP_Sync_User_Data": "Sync Data",
- "LDAP_Sync_User_Data_Description": "Keep user data in sync with server on login (eg: name, email).",
+ "LDAP_Sync_Now": "Background Sync Now",
+ "LDAP_Sync_Now_Description": "Will execute the **Background Sync** now rather than wait the **Sync Interval** even if **Background Sync** is False. This Action is asynchronous, please see the logs for more information about the process",
+ "LDAP_Background_Sync": "Background Sync",
+ "LDAP_Background_Sync_Interval": "Background Sync Interval",
+ "LDAP_Background_Sync_Interval_Description": "The interval between synchronizations. Example `every 24 hours` or `on the first day of the week`, more examples at [Cron Text Parser](http://bunkat.github.io/later/parsers.html#text)",
+ "LDAP_Background_Sync_Import_New_Users": "Background Sync Import New Users",
+ "LDAP_Background_Sync_Import_New_Users_Description": "Will import all users (based on your filter criteria) that exists in LDAP and does not exists in Rocket.Chat",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated": "Background Sync Update Existing Users",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated_Description": "Will sync the avatar, fields, username, etc (based on your configuration) of all users already imported from LDAP on every **Sync Interval**",
+ "LDAP_Sync_User_Data": "Sync User Data",
+ "LDAP_Sync_User_Data_Description": "Keep user data in sync with server on **login** or on **background sync** (eg: name, email).",
"LDAP_Sync_User_Data_FieldMap": "User Data Field Map",
- "LDAP_Sync_User_Data_FieldMap_Description": "Configure how user account fields (like email) are populated from a record in LDAP (once found). As an example, `{\"cn\":\"name\", \"mail\":\"email\"}` will choose a person's human readable name from the cn attribute, and their email from the mail attribute. Available fields include `name`, and `email`.",
- "LDAP_Sync_Users": "Sync Users",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configure how user account fields (like email) are populated from a record in LDAP (once found). As an example, `{\"cn\":\"name\", \"mail\":\"email\"}` will choose a person's human readable name from the cn attribute, and their email from the mail attribute. Additionally it is possible to use variables, for example: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` uses a combination of the user's first name and last name for the rocket chat `name` field. Available fields in Rocket.Chat: `name`, `email` and `customFields`.",
+ "LDAP_Search_Page_Size": "Search Page Size",
+ "LDAP_Search_Page_Size_Description": "The maximum number of entries each result page will return to be processed",
+ "LDAP_Search_Size_Limit": "Search Size Limit",
+ "LDAP_Search_Size_Limit_Description": "The maximum number of entries to return. **Attention** This number should greater than **Search Page Size**",
"LDAP_Test_Connection": "Test Connection",
+ "LDAP_Timeout": "Timeout (ms)",
+ "LDAP_Timeout_Description": "How many mileseconds wait for a search result before return an error",
"LDAP_Unique_Identifier_Field": "Unique Identifier Field",
"LDAP_Unique_Identifier_Field_Description": "Which field will be used to link the LDAP user and the Rocket.Chat user. You can inform multiple values separated by comma to try to get the value from LDAP record. Default value is `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Use Custom Domain Search",
- "LDAP_Use_Custom_Domain_Search_Description": "Write your own filter to search users in the LDAP server.",
"LDAP_Username_Field": "Username Field",
"LDAP_Username_Field_Description": "Which field will be used as *username* for new users. Leave empty to use the username informed on login page. You can use template tags too, like `#{givenName}.#{sn}`. Default value is `sAMAccountName`.",
- "LDAP_Group_Filter_Enable": "Enable LDAP user group filter",
- "LDAP_Group_Filter_Enable_Description": "Restrict access to users in a LDAP group Useful for OpenLDAP servers without overlays that not permit *memberOf* filter",
- "LDAP_Group_Filter_ObjectClass": "Group ObjectClass",
- "LDAP_Group_Filter_ObjectClass_Description": "The *objectclass* that identify the groups. E.g. OpenLDAP:groupOfUniqueNames",
- "LDAP_Group_Filter_Group_Id_Attribute": "Group ID Attribute",
- "LDAP_Group_Filter_Group_Id_Attribute_Description": "E.g. *OpenLDAP:*cn",
- "LDAP_Group_Filter_Group_Member_Attribute": "Group Member Attribute",
- "LDAP_Group_Filter_Group_Member_Attribute_Description": "E.g. *OpenLDAP:*uniqueMember",
- "LDAP_Group_Filter_Group_Member_Format": "Group Member Format",
- "LDAP_Group_Filter_Group_Member_Format_Description": "E.g. *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
- "LDAP_Group_Filter_Group_Name": "Group name",
- "LDAP_Group_Filter_Group_Name_Description": "Group name to which it belong the user",
+ "Execute_Synchronization_Now": "Execute Synchronization Now",
+ "Lead_capture_email_regex": "Lead capture email regex",
+ "Lead_capture_phone_regex": "Lead capture phone regex",
"Least_Amount": "Least Amount",
"Leave_Group_Warning": "Are you sure you want to leave the group \"%s\"?",
+ "Leave_Livechat_Warning": "Are you sure you want to leave the livechat with \"%s\"?",
"Leave_Private_Warning": "Are you sure you want to leave the discussion with \"%s\"?",
"Leave_room": "Leave room",
"Leave_Room_Warning": "Are you sure you want to leave the room \"%s\"?",
@@ -792,29 +1142,39 @@
"List_of_Channels": "List of Channels",
"List_of_Direct_Messages": "List of Direct Messages",
"Livechat_agents": "Livechat agents",
- "Livechat_AllowedDomainsList": "Livechat allowed domains",
- "Domains_allowed_to_embed_the_livechat_widget": "Comma-separated list of domains allowed to embed the livechat widget. Leave blank to allow all domains.",
+ "Livechat_AllowedDomainsList": "Livechat Allowed Domains",
"Livechat_Dashboard": "Livechat Dashboard",
"Livechat_enabled": "Livechat enabled",
+ "Livechat_Facebook_Enabled": "Facebook integration enabled",
+ "Livechat_Facebook_API_Key": "OmniChannel API Key",
+ "Livechat_Facebook_API_Secret": "OmniChannel API Secret",
"Livechat_forward_open_chats": "Forward open chats",
"Livechat_forward_open_chats_timeout": "Timeout (in seconds) to forward chats",
- "Livechat_guest_count": "Guest counter",
+ "Livechat_guest_count": "Guest Counter",
"Livechat_Inquiry_Already_Taken": "Livechat inquiry already taken",
"Livechat_managers": "Livechat managers",
"Livechat_offline": "Livechat offline",
"Livechat_online": "Livechat online",
- "Livechat_open_inquiery_show_connecting": "Show connecting message instead of input when guest is not yet connected to an agent",
+ "Livechat_open_inquiery_show_connecting": "Show Connecting Message Instead of Input When Guest is Not Yet Connected to an Agent",
"Livechat_Queue": "Livechat Queue",
- "Livechat_room_count": "Livechat room count",
+ "Livechat_room_count": "Livechat Room Count",
"Livechat_Routing_Method": "Livechat Routing Method",
"Livechat_Take_Confirm": "Do you want to take this client?",
"Livechat_title": "Livechat Title",
"Livechat_title_color": "Livechat Title Background Color",
"Livechat_Users": "Livechat Users",
+ "Livestream_close": "Close Livestream",
+ "Livestream_not_found": "Livestream not available",
+ "Livestream_popout": "Open Livestream",
+ "Livestream_url": "Livestream source url",
+ "Livestream_url_incorrect": "Livestream url is incorrect",
+ "Livestream_source_changed_succesfully": "Livestream source changed successfully",
+ "Livestream_switch_to_room": "Switch to current room's livestream",
+ "Livestream_enable_audio_only": "Enable only audio mode",
"Load_more": "Load more",
"Loading...": "Loading...",
"Loading_more_from_history": "Loading more from history",
- "Loading_suggestion": "Loading suggestions...",
+ "Loading_suggestion": "Loading suggestions",
"Localization": "Localization",
"Log_Exceptions_to_Channel": "Log Exceptions to Channel",
"Log_Exceptions_to_Channel_Description": "A channel that will receive all captured exceptions. Leave empty to ignore exceptions.",
@@ -827,9 +1187,11 @@
"Login_with": "Login with %s",
"Logout": "Logout",
"Logout_Others": "Logout From Other Logged In Locations",
+ "mail-messages": "Mail Messages",
+ "mail-messages_description": "Permission to use the mail messages option",
"Mail_Message_Invalid_emails": "You have provided one or more invalid emails: %s",
"Mail_Message_Missing_to": "You must select one or more users or provide one or more email addresses, separated by commas.",
- "Mail_Message_No_messages_selected_select_all": "You haven't selected any messages. Would you like to select all visible messages?",
+ "Mail_Message_No_messages_selected_select_all": "You haven't selected any messages",
"Mail_Messages": "Mail Messages",
"Mail_Messages_Instructions": "Choose which messages you want to send via email by clicking the messages",
"Mail_Messages_Subject": "Here's a selected portion of %s messages",
@@ -837,6 +1199,21 @@
"Mailer_body_tags": "You must use [unsubscribe] for the unsubscription link. You may use [name], [fname], [lname] for the user's full name, first name or last name, respectively. You may use [email] for the user's email.",
"Mailing": "Mailing",
"Make_Admin": "Make Admin",
+ "Make_sure_you_have_a_copy_of_your_codes": "Make sure you have a copy of your codes: __codes__ If you lose access to your authenticator app, you can use one of these codes to log in.",
+ "manage-assets": "Manage Assets",
+ "manage-assets_description": "Permission to manage the server assets",
+ "manage-emoji": "Manage Emoji",
+ "manage-emoji_description": "Permission to manage the server emojis",
+ "manage-integrations": "Manage Integrations",
+ "manage-integrations_description": "Permission to manage the server integrations",
+ "manage-oauth-apps": "Manage Oauth Apps",
+ "manage-oauth-apps_description": "Permission to manage the server Oauth apps",
+ "manage-own-integrations": "Manage Own Integrations",
+ "manage-own-integrations_description": "Permition to allow users to create and edit their own integration or webhooks",
+ "manage-sounds": "Manage Sounds",
+ "manage-sounds_description": "Permission to manage the server sounds",
+ "Manage_Apps": "Manage Apps",
+ "Manage_the_App": "Manage the App",
"Manager_added": "Manager added",
"Manager_removed": "Manager removed",
"Managing_assets": "Managing assets",
@@ -845,20 +1222,34 @@
"MapView_Enabled_Description": "Enabling mapview will display a location share button on the left of the chat input field.",
"MapView_GMapsAPIKey": "Google Static Maps API Key",
"MapView_GMapsAPIKey_Description": "This can be obtained from the Google Developers Console for free.",
- "Mark_as_read": "Mark as read",
- "Mark_as_unread": "Mark as unread",
+ "Mark_as_read": "Mark As Read",
+ "Mark_as_unread": "Mark As Unread",
"Markdown_Headers": "Allow Markdown headers in messages",
+ "Markdown_Marked_Breaks": "Enable Marked Breaks",
+ "Markdown_Marked_GFM": "Enable Marked GFM",
+ "Markdown_Marked_Pedantic": "Enable Marked Pedantic",
+ "Markdown_Marked_SmartLists": "Enable Marked Smart Lists",
+ "Markdown_Marked_Smartypants": "Enable Marked Smartypants",
+ "Markdown_Marked_Tables": "Enable Marked Tables",
+ "Markdown_Parser": "Markdown Parser",
"Markdown_SupportSchemesForLink": "Markdown Support Schemes for Link",
"Markdown_SupportSchemesForLink_Description": "Comma-separated list of allowed schemes",
"Max_length_is": "Max length is %s",
"Members_List": "Members List",
+ "mention-all": "Mention All",
+ "mention-all_description": "Permission to use the @all mention",
+ "mention-here": "Mention Here",
+ "mention-here_description": "Permission to use the @here mention",
"Mentions": "Mentions",
"Mentions_default": "Mentions (default)",
+ "Mentions_only": "Mentions only",
+ "Merge_Channels": "Merge Channels",
"Message": "Message",
"Message_AllowBadWordsFilter": "Allow Message bad words filtering",
"Message_AllowDeleting": "Allow Message Deleting",
"Message_AllowDeleting_BlockDeleteInMinutes": "Block Message Deleting After (n) Minutes",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Enter 0 to disable blocking.",
+ "Message_AllowDirectMessagesToYourself": "Allow user direct messages to yourself",
"Message_AllowEditing": "Allow Message Editing",
"Message_AllowEditing_BlockEditInMinutes": "Block Message Editing After (n) Minutes",
"Message_AllowEditing_BlockEditInMinutesDescription": "Enter 0 to disable blocking.",
@@ -867,16 +1258,20 @@
"Message_AllowSnippeting": "Allow Message Snippeting",
"Message_AllowStarring": "Allow Message Starring",
"Message_AllowUnrecognizedSlashCommand": "Allow Unrecognized Slash Commands",
- "Message_AlwaysSearchRegExp": "Always search using RegExp",
+ "Message_AlwaysSearchRegExp": "Always Search Using RegExp",
"Message_AlwaysSearchRegExp_Description": "We recommend to set `True` if your language is not supported on MongoDB text search .",
+ "Message_Attachments": "Message Attachments",
+ "Message_Attachments_GroupAttach": "Group Attachment Buttons",
+ "Message_Attachments_GroupAttachDescription": "This groups the icons under an expandable menu. Takes up less screen space.",
"Message_AudioRecorderEnabled": "Audio Recorder Enabled",
"Message_AudioRecorderEnabledDescription": "Requires 'audio/wav' files to be an accepted media type within 'File Upload' settings.",
- "Message_BadWordsFilterList": "Add bad words to the blacklist",
+ "Message_BadWordsFilterList": "Add Bad Words to the Blacklist",
"Message_BadWordsFilterListDescription": "Add List of Comma-separated list of bad words to filter",
"Message_DateFormat": "Date Format",
"Message_DateFormat_Description": "See also: Moment.js ",
"Message_deleting_blocked": "This message cannot be deleted anymore",
"Message_editing": "Message editing",
+ "Message_GlobalSearch": "Global Search",
"Message_GroupingPeriod": "Grouping Period (in seconds)",
"Message_GroupingPeriodDescription": "Messages will be grouped with previous message if both are from the same user and the elapsed time was less than the informed time in seconds.",
"Message_HideType_au": "Hide \"User Added\" messages",
@@ -884,17 +1279,25 @@
"Message_HideType_ru": "Hide \"User Removed\" messages",
"Message_HideType_uj": "Hide \"User Join\" messages",
"Message_HideType_ul": "Hide \"User Leave\" messages",
- "Message_KeepHistory": "Keep per message editing history",
- "Message_MaxAll": "Maximum channel size for ALL message",
- "Message_MaxAllowedSize": "Maximum Allowed Message Size",
+ "Message_info": "Message info",
+ "Message_KeepHistory": "Keep Per Message Editing History",
+ "Message_MaxAll": "Maximum Channel Size for ALL Message",
+ "Message_MaxAllowedSize": "Maximum Allowed Characters Per Message",
"Message_pinning": "Message pinning",
+ "Message_QuoteChainLimit": "Maximum Number of Chained Quotes",
+ "Message_Read_Receipt_Enabled": "Show Read Receipts",
+ "Message_Read_Receipt_Store_Users": "Detailed Read Receipts",
+ "Message_Read_Receipt_Store_Users_Description": "Shows each user's read receipts",
"Message_removed": "Message removed",
- "Message_SetNameToAliasEnabled": "Set a user name to alias in message",
+ "Message_sent_by_email": "Message sent by Email",
+ "Message_SetNameToAliasEnabled": "Set a User Name to Alias in Message",
"Message_SetNameToAliasEnabled_Description": "Only if not already set alias. The old messages alias not changed if user has changed the name.",
"Message_ShowDeletedStatus": "Show Deleted Status",
"Message_ShowEditedStatus": "Show Edited Status",
"Message_ShowFormattingTips": "Show Formatting Tips",
"Message_starring": "Message starring",
+ "Message_TimeAndDateFormat": "Time and Date Format",
+ "Message_TimeAndDateFormat_Description": "See also: Moment.js ",
"Message_TimeFormat": "Time Format",
"Message_TimeFormat_Description": "See also: Moment.js ",
"Message_too_long": "Message too long",
@@ -903,63 +1306,80 @@
"Messages": "Messages",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Messages that are sent to the Incoming WebHook will be posted here.",
"Meta": "Meta",
- "Meta_fb_app_id": "Facebook App Id",
"Meta_custom": "Custom Meta Tags",
+ "Meta_fb_app_id": "Facebook App Id",
"Meta_google-site-verification": "Google Site Verification",
"Meta_language": "Language",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Robots",
"Min_length_is": "Min length is %s",
+ "Minimum_balance": "Minimum balance",
"minutes": "minutes",
"Mobile": "Mobile",
+ "Mobile_Notifications_Default_Alert": "Mobile Notifications Default Alert",
"Monday": "Monday",
- "Monitor_history_for_changes_on": "Monitor history for changes on",
+ "Monitor_history_for_changes_on": "Monitor History for Changes on",
"More_channels": "More channels",
"More_direct_messages": "More direct messages",
"More_groups": "More private groups",
"More_unreads": "More unreads",
+ "Move_beginning_message": "`%s` - Move to the beginning of the message",
+ "Move_end_message": "`%s` - Move to the end of the message",
"Msgs": "Msgs",
"multi": "multi",
+ "multi_line": "multi line",
+ "Mute_all_notifications": "Mute all notifications",
+ "mute-user": "Mute User",
+ "mute-user_description": "Permission to mute other users in the same channel",
+ "Mute_Focused_Conversations": "Mute Focused Conversations",
"Mute_someone_in_room": "Mute someone in the room",
"Mute_user": "Mute user",
"Muted": "Muted",
"My_Account": "My Account",
+ "My_location": "My location",
"n_messages": "%s messages",
"N_new_messages": "%s new messages",
"Name": "Name",
"Name_cant_be_empty": "Name can't be empty",
"Name_of_agent": "Name of agent",
"Name_optional": "Name (optional)",
+ "Name_Placeholder": "Please enter your name...",
"Navigation_History": "Navigation History",
"New_Application": "New Application",
"New_Custom_Field": "New Custom Field",
"New_Department": "New Department",
"New_integration": "New integration",
+ "New_line_message_compose_input": "`%s` - New line in message compose input",
"New_logs": "New logs",
"New_Message_Notification": "New Message Notification",
"New_messages": "New messages",
- "New_password": "New password",
+ "New_password": "New Password",
+ "New_Password_Placeholder": "Please enter new password...",
"New_role": "New role",
"New_Room_Notification": "New Room Notification",
- "New_videocall_request": "New videocall request",
"New_Trigger": "New Trigger",
+ "New_version_available_(s)": "New version available (%s)",
+ "New_videocall_request": "New Video Call Request",
"No_available_agents_to_transfer": "No available agents to transfer",
"No_channel_with_name_%s_was_found": "No channel with name \"%s\" was found!",
- "No_channels_yet": "You aren't part of any channel yet.",
- "No_direct_messages_yet": "You haven't started any conversations yet.",
+ "No_channels_yet": "You aren't part of any channel yet",
+ "No_direct_messages_yet": "No Direct Messages.",
"No_Encryption": "No Encryption",
"No_group_with_name_%s_was_found": "No private group with name \"%s\" was found!",
"No_groups_yet": "You have no private groups yet.",
- "No_livechats": "You have no livechats.",
+ "No_integration_found": "No integration found by the provided id.",
+ "No_livechats": "You have no livechats",
"No_mentions_found": "No mentions found",
+ "No_pages_yet_Try_hitting_Reload_Pages_button": "No pages yet. Try hitting \"Reload Pages\" button.",
+ "No_messages_yet": "No messages yet",
"No_pinned_messages": "No pinned messages",
"No_results_found": "No results found",
+ "No_snippet_messages": "No snippet",
"No_starred_messages": "No starred messages",
"No_such_command": "No such command: `/__command__`",
- "No_snippet_messages": "No snippet",
"No_user_with_username_%s_was_found": "No user with username \"%s\" was found!",
"Nobody_available": "Nobody available",
- "Node_version": "Node version",
+ "Node_version": "Node Version",
"None": "None",
"Normal": "Normal",
"Not_authorized": "Not authorized",
@@ -967,43 +1387,61 @@
"Not_found_or_not_allowed": "Not Found or Not Allowed",
"Nothing": "Nothing",
"Nothing_found": "Nothing found",
+ "Notification_Desktop_Default_For": "Show Desktop Notifications For",
"Notification_Duration": "Notification Duration",
+ "Notification_Mobile_Default_For": "Push Mobile Notifications For",
"Notifications": "Notifications",
- "Notify_all_in_this_room": "Notify all in this room",
+ "Notifications_Always_Notify_Mobile": "Always notify mobile",
+ "Notifications_Always_Notify_Mobile_Description": "Choose to always notify mobile device regardless of presence status.",
+ "Notifications_Duration": "Notifications_Duration",
+ "Notifications_Max_Room_Members": "Max Room Members Before Disabling All Message Notifications",
+ "Notifications_Max_Room_Members_Description": "Max number of members in room when notifications for all messages gets disabled. Users can still change per room setting to receive all notifications on an individual basis. (0 to disable)",
+ "Notifications_Muted_Description": "If you choose to mute everything, you won't see the room highlight in the list when there are new messages, except for mentions. Muting notifications will override notifications settings.",
+ "Notifications_Preferences": "Notifications Preferences",
+ "Notifications_Sound_Volume": "Notifications sound volume",
"Notify_active_in_this_room": "Notify active users in this room",
+ "Notify_all_in_this_room": "Notify all in this room",
"Num_Agents": "# Agents",
"Number_of_messages": "Number of messages",
"OAuth_Application": "OAuth Application",
"OAuth_Applications": "OAuth Applications",
"Objects": "Objects",
"Off": "Off",
- "Off_the_record_conversation": "Off-the-record Conversation",
- "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record conversation is not available for your browser or device.",
+ "Off_the_record_conversation": "Off-the-Record Conversation",
+ "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-Record conversation is not available for your browser or device.",
"Office_Hours": "Office Hours",
- "Office_Hours_Enabled": "Office Hours Enabled",
+ "Office_hours_enabled": "Office Hours Enabled",
+ "Office_hours_updated": "Office hours updated",
"Offline": "Offline",
- "Offline_DM_Email": "You have been direct messaged by __user__",
+ "Offline_DM_Email": "Direct Message Email Subject",
+ "Offline_Email_Subject_Description": "You may use the following placeholders:[Site_Name], [Site_URL], [User] & [Room] for the Application Name, URL, Username & Roomname respectively. ",
"Offline_form": "Offline form",
- "Offline_form_unavailable_message": "Offline form unavailable message",
+ "Offline_form_unavailable_message": "Offline Form Unavailable Message",
"Offline_Link_Message": "GO TO MESSAGE",
- "Offline_Mention_Email": "You have been mentioned by __user__ in #__room__",
+ "Offline_Mention_All_Email": "Mention All Email Subject",
+ "Offline_Mention_Email": "Mention Email Subject",
"Offline_message": "Offline message",
- "Offline_success_message": "Offline success message",
+ "Offline_success_message": "Offline Success Message",
"Offline_unavailable": "Offline unavailable",
"On": "On",
"Online": "Online",
+ "Only_authorized_users_can_write_new_messages": "Only authorized users can write new messages",
+ "Only_On_Desktop": "Desktop mode (only sends with enter on desktop)",
"Only_you_can_see_this_message": "Only you can see this message",
"Oops!": "Oops",
"Open": "Open",
+ "Open_channel_user_search": "`%s` - Open Channel / User search",
"Open_days_of_the_week": "Open Days of the Week",
"Open_Livechats": "Open Livechats",
+ "Open_your_authentication_app_and_enter_the_code": "Open your authentication app and enter the code. You can also use one of your backup codes.",
"Opened": "Opened",
"Opened_in_a_new_window": "Opened in a new window.",
"Opens_a_channel_group_or_direct_message": "Opens a channel, group or direct message",
"optional": "optional",
- "Use_minor_colors": "Use minor color palette (defaults inherit major colors)",
"or": "or",
+ "Or_talk_as_anonymous": "Or talk as anonymous",
"Order": "Order",
+ "Original": "Original",
"OS_Arch": "OS Arch",
"OS_Cpus": "OS CPU Count",
"OS_Freemem": "OS Free Memory",
@@ -1016,6 +1454,8 @@
"others": "others",
"OTR": "OTR",
"OTR_is_only_available_when_both_users_are_online": "OTR is only available when both users are online",
+ "Outgoing_WebHook": "Outgoing WebHook",
+ "Outgoing_WebHook_Description": "Get data out of Rocket.Chat in real-time.",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Override URL to which files are uploaded. This url also used for downloads unless a CDN is given",
"Page_title": "Page title",
"Page_URL": "Page URL",
@@ -1027,24 +1467,36 @@
"People": "People",
"Permalink": "Permalink",
"Permissions": "Permissions",
+ "pin-message": "Pin Message",
+ "pin-message_description": "Permission to pin a message in a channel",
"Pin_Message": "Pin Message",
"Pinned_a_message": "Pinned a message:",
"Pinned_Messages": "Pinned Messages",
+ "PiwikAdditionalTrackers": "Additional Piwik Sites",
+ "PiwikAdditionalTrackers_Description": "Enter addtitional Piwik website URLs and SiteIDs in the following format, if you wnat to track the same data into different websites: [ { \"trackerURL\" : \"https://my.piwik.domain2/\", \"siteId\" : 42 }, { \"trackerURL\" : \"https://my.piwik.domain3/\", \"siteId\" : 15 } ]",
+ "PiwikAnalytics_cookieDomain": "All Subdomains",
+ "PiwikAnalytics_cookieDomain_Description": "Track visitors across all subdomains",
+ "PiwikAnalytics_domains": "Hide Outgoing Links",
+ "PiwikAnalytics_domains_Description": "In the 'Outlinks' report, hide clicks to known alias URLs. Please insert one domain per line and do not use any separators.",
+ "PiwikAnalytics_prependDomain": "Prepend Domain",
+ "PiwikAnalytics_prependDomain_Description": "Prepend the site domain to the page title when tracking",
"PiwikAnalytics_siteId_Description": "The site id to use for identifying this site. Example: 17",
"PiwikAnalytics_url_Description": "The url where the Piwik resides, be sure to include the trailing slash. Example: //piwik.rocket.chat/",
- "Placeholder_for_email_or_username_login_field": "Placeholder for email or username login field",
- "Placeholder_for_password_login_field": "Placeholder for password login field",
+ "Placeholder_for_email_or_username_login_field": "Placeholder for Email or Username Login Field",
+ "Placeholder_for_password_login_field": "Placeholder for Password Login Field",
"Please_add_a_comment": "Please add a comment",
"Please_add_a_comment_to_close_the_room": "Please, add a comment to close the room",
"Please_answer_survey": "Please take a moment to answer a quick survey about this chat",
+ "please_enter_valid_domain": "Please enter a valid domain",
"Please_enter_value_for_url": "Please enter a value for the url of your avatar.",
"Please_enter_your_new_password_below": "Please enter your new password below:",
"Please_enter_your_password": "Please enter your password",
- "please_enter_valid_domain": "Please enter a valid domain",
"Please_fill_a_label": "Please fill a label",
"Please_fill_a_name": "Please fill a name",
"Please_fill_a_username": "Please fill a username",
+ "Please_fill_all_the_information": "Please fill all the information",
"Please_fill_name_and_email": "Please fill name and email",
+ "Please_go_to_the_Administration_page_then_Livechat_Facebook": "Please go to the Administration page then Livechat > Facebook",
"Please_select_an_user": "Please select an user",
"Please_select_enabled_yes_or_no": "Please select an option for Enabled",
"Please_wait": "Please wait",
@@ -1053,19 +1505,27 @@
"Please_wait_while_your_account_is_being_deleted": "Please wait while your account is being deleted...",
"Please_wait_while_your_profile_is_being_saved": "Please wait while your profile is being saved...",
"Port": "Port",
+ "post-readonly": "Post ReadOnly",
+ "post-readonly_description": "Permission to post a message in a read-only channel",
"Post_as": "Post as",
"Post_to_Channel": "Post to Channel",
"Post_to_s_as_s": "Post to %s as %s ",
"Preferences": "Preferences",
"Preferences_saved": "Preferences saved",
+ "preview-c-room": "Preview Public Channel",
+ "preview-c-room_description": "Permission to view the contents of a public channel before joining",
"Privacy": "Privacy",
"Private": "Private",
+ "Private_Channel": "Private Channel",
"Private_Group": "Private Group",
"Private_Groups": "Private Groups",
"Private_Groups_list": "List of Private Groups",
"Profile": "Profile",
+ "Profile_details": "Profile Details",
+ "Profile_picture": "Profile Picture",
"Profile_saved_successfully": "Profile saved successfully",
"Public": "Public",
+ "Public_Channel": "Public Channel",
"Push": "Push",
"Push_apn_cert": "APN Cert",
"Push_apn_dev_cert": "APN Dev Cert",
@@ -1080,8 +1540,8 @@
"Push_gcm_api_key": "GCM API Key",
"Push_gcm_project_number": "GCM Project Number",
"Push_production": "Production",
- "Push_show_message": "Show message in notification",
- "Push_show_username_room": "Show channel/group/username in notification",
+ "Push_show_message": "Show Message in Notification",
+ "Push_show_username_room": "Show Channel/Group/Username in Notification",
"Push_test_push": "Test",
"Query": "Query",
"Query_description": "Additional conditions for determining which users to send the email to. Unsubscribed users are automatically removed from the query. It must be a valid JSON. Example: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
@@ -1089,24 +1549,38 @@
"quote": "quote",
"Quote": "Quote",
"Random": "Random",
+ "RDStation_Token": "RD Station Token",
"React_when_read_only": "Allow Reacting",
"React_when_read_only_changed_successfully": "Allow reacting when read only changed successfully",
"Reacted_with": "Reacted with",
"Reactions": "Reactions",
+ "Read_by": "Read by",
"Read_only": "Read Only",
"Read_only_changed_successfully": "Read only changed successfully",
"Read_only_channel": "Read Only Channel",
"Read_only_group": "Read Only Group",
+ "Reason_To_Join": "Reason to Join",
+ "RealName_Change_Disabled": "Your Rocket.Chat administrator has disabled the changing of names",
+ "Receive_alerts": "Receive alerts",
"Record": "Record",
"Redirect_URI": "Redirect URI",
- "Refresh_oauth_services": "Refresh OAuth Services",
"Refresh_keys": "Refresh keys",
+ "Refresh_oauth_services": "Refresh OAuth Services",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Refresh your page after install to enable screen sharing",
+ "Regenerate_codes": "Regenerate codes",
"Register": "Register a new account",
+ "Registration": "Registration",
"Registration_Succeeded": "Registration Succeeded",
+ "Registration_via_Admin": "Registration via Admin",
+ "Regular_Expressions": "Regular Expressions",
"Release": "Release",
+ "Reload": "Reload",
+ "Reload_Pages": "Reload Pages",
"Remove": "Remove",
+ "remove-user": "Remove User",
+ "remove-user_description": "Permission to remove a user from a room",
"Remove_Admin": "Remove Admin",
+ "Remove_as_leader": "Remove as leader",
"Remove_as_moderator": "Remove as moderator",
"Remove_as_owner": "Remove as owner",
"Remove_custom_oauth": "Remove custom oauth",
@@ -1119,28 +1593,40 @@
"Report_exclamation_mark": "Report!",
"Report_sent": "Report sent",
"Report_this_message_question_mark": "Report this message?",
+ "Require_all_tokens": "Require all tokens",
+ "Require_any_token": "Require any token",
+ "Reporting": "Reporting",
"Require_password_change": "Require password change",
"Resend_verification_email": "Resend verification email",
"Reset": "Reset",
- "Reset_section_settings": "Reset section settings",
"Reset_password": "Reset password",
+ "Reset_section_settings": "Reset Section Settings",
"Restart": "Restart",
"Restart_the_server": "Restart the server",
+ "Retry_Count": "Retry Count",
+ "Apps": "Apps",
+ "App_Information": "App Information",
+ "App_Installation": "App Installation",
+ "Apps_Settings": "App's Settings",
"Role": "Role",
"Role_Editing": "Role Editing",
"Role_removed": "Role removed",
"Room": "Room",
+ "Room_announcement_changed_successfully": "Room announcement changed successfully",
"Room_archivation_state": "State",
"Room_archivation_state_false": "Active",
"Room_archivation_state_true": "Archived",
"Room_archived": "Room archived",
+ "room_changed_announcement": "Room announcement changed to: __room_announcement__ by __user_by__ ",
"room_changed_description": "Room description changed to: __room_description__ by __user_by__ ",
"room_changed_privacy": "Room type changed to: __room_type__ by __user_by__ ",
"room_changed_topic": "Room topic changed to: __room_topic__ by __user_by__ ",
+ "Room_default_change_to_private_will_be_default_no_more": "This is a default channel and changing it to a private group will cause it to no longer be a default channel. Do you want to proceed?",
"Room_description_changed_successfully": "Room description changed successfully",
- "Room_has_been_deleted": "Room has been deleted",
"Room_has_been_archived": "Room has been archived",
+ "Room_has_been_deleted": "Room has been deleted",
"Room_has_been_unarchived": "Room has been unarchived",
+ "Room_tokenpass_config_changed_successfully": "Room tokenpass configuration changed successfully",
"Room_Info": "Room Info",
"room_is_blocked": "This room is blocked",
"room_is_read_only": "This room is read only",
@@ -1148,31 +1634,47 @@
"Room_name_changed": "Room name changed to: __room_name__ by __user_by__ ",
"Room_name_changed_successfully": "Room name changed successfully",
"Room_not_found": "Room not found",
+ "Room_password_changed_successfully": "Room password changed successfully",
"Room_topic_changed_successfully": "Room topic changed successfully",
"Room_type_changed_successfully": "Room type changed successfully",
+ "Room_type_of_default_rooms_cant_be_changed": "This is a default room and the type can not be changed, please consult with your administrator.",
"Room_unarchived": "Room unarchived",
"Room_uploaded_file_list": "Files List",
"Room_uploaded_file_list_empty": "No files available.",
"Rooms": "Rooms",
+ "run-import": "Run Import",
+ "run-import_description": "Permission to run the importers",
+ "run-migration": "Run Migration",
+ "run-migration_description": "Permission to run the migrations",
"Running_Instances": "Running Instances",
+ "Runtime_Environment": "Runtime Environment",
"S_new_messages_since_s": "%s new messages since %s",
+ "Same_As_Token_Sent_Via": "Same as \"Token Sent Via\"",
+ "Same_Style_For_Mentions": "Same style for mentions",
"SAML": "SAML",
"SAML_Custom_Cert": "Custom Certificate",
"SAML_Custom_Entry_point": "Custom Entry Point",
"SAML_Custom_Generate_Username": "Generate Username",
"SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO Redirect URL",
"SAML_Custom_Issuer": "Custom Issuer",
+ "SAML_Custom_Logout_Behaviour": "Logout Behaviour",
+ "SAML_Custom_Logout_Behaviour_Terminate_SAML_Session": "Terminate SAML-session",
+ "SAML_Custom_Logout_Behaviour_End_Only_RocketChat": "Only log out from Rocket.Chat",
+ "SAML_Custom_Private_Key": "Private Key Contents",
"SAML_Custom_Provider": "Custom Provider",
- "SAML_Custom_Public_Cert": "Public cert contents",
- "SAML_Custom_Private_Key": "Private key contents",
+ "SAML_Custom_Public_Cert": "Public Cert Contents",
"Sandstorm_Powerbox_Share": "Share a Sandstorm grain",
"Saturday": "Saturday",
"Save": "Save",
+ "save-others-livechat-room-info": "Save Others Livechat Room Info",
+ "save-others-livechat-room-info_description": "Permission to save information from other livechat channels",
"Save_changes": "Save changes",
"Save_Mobile_Bandwidth": "Save Mobile Bandwidth",
"Save_to_enable_this_action": "Save to enable this action",
"Saved": "Saved",
"Saving": "Saving",
+ "Scan_QR_code": "Using an authenticator app like Google Authenticator, Authy or Duo, scan the QR code. It will display a 6 digit code which you need to enter below.",
+ "Scan_QR_code_alternative_s": "If you can't scan the QR code, you may enter code manually instead: __code__",
"Scope": "Scope",
"Screen_Share": "Screen Share",
"Script_Enabled": "Script Enabled",
@@ -1181,11 +1683,14 @@
"Search_Messages": "Search Messages",
"Search_Private_Groups": "Search Private Groups",
"seconds": "seconds",
- "Secret_token": "Secret token",
+ "Secret_token": "Secret Token",
+ "Security": "Security",
"Select_a_department": "Select a department",
"Select_a_user": "Select a user",
"Select_an_avatar": "Select an avatar",
+ "Select_an_option": "Select an option",
"Select_file": "Select file",
+ "Select_role": "Select a Role",
"Select_service_to_login": "Select a service to login to load your picture or upload one directly from your computer",
"Select_user": "Select user",
"Select_users": "Select users",
@@ -1201,14 +1706,26 @@
"Send_invitation_email_error": "You haven't provided any valid email address.",
"Send_invitation_email_info": "You can send multiple email invitations at once.",
"Send_invitation_email_success": "You have successfully sent an invitation email to the following addresses:",
- "Send_request_on_chat_close": "Send request on chat close",
- "Send_request_on_offline_messages": "Send request on offline messages",
+ "Send_request_on_chat_close": "Send Request on Chat Close",
+ "Send_request_on_lead_capture": "Send request on lead capture",
+ "Send_request_on_offline_messages": "Send Request on Offline Messages",
"Send_Test": "Send Test",
"Send_welcome_email": "Send welcome email",
"Send_your_JSON_payloads_to_this_URL": "Send your JSON payloads to this URL.",
"Sending": "Sending...",
+ "Sent_an_attachment": "Sent an attachment",
"Served_By": "Served By",
"Service": "Service",
+ "Service_account_key": "Service account key",
+ "set-moderator": "Set Moderator",
+ "set-moderator_description": "Permission to set other users as moderator of a channel",
+ "set-owner": "Set Owner",
+ "set-owner_description": "Permission to set other users as owner of a channel",
+ "set-react-when-readonly": "Set React When ReadOnly",
+ "set-react-when-readonly_description": "Permission to set the ability to react to messages in a read only channel",
+ "set-readonly": "Set ReadOnly",
+ "set-readonly_description": "Permission to set a channel to read only channel",
+ "Set_as_leader": "Set as leader",
"Set_as_moderator": "Set as moderator",
"Set_as_owner": "Set as owner",
"Settings": "Settings",
@@ -1217,30 +1734,39 @@
"Shared_Location": "Shared Location",
"Should_be_a_URL_of_an_image": "Should be a URL of an image.",
"Should_exists_a_user_with_this_username": "The user must already exist.",
- "Show_all": "Show all",
+ "Show_agent_email": "Show agent email",
+ "Show_all": "Show All",
+ "Show_Avatars": "Show Avatars",
+ "Show_counter": "Show counter",
+ "Show_room_counter_on_sidebar": "Show room counter on sidebar",
"Show_more": "Show more",
"show_offline_users": "show offline users",
"Show_on_registration_page": "Show on registration page",
- "Show_only_online": "Show only online",
- "Show_preregistration_form": "Show pre-registration form",
- "Show_queue_list_to_all_agents": "Show queue list to all agents",
+ "Show_only_online": "Show Online Only",
+ "Show_preregistration_form": "Show Pre-registration Form",
+ "Show_queue_list_to_all_agents": "Show Queue List to All Agents",
+ "Show_the_keyboard_shortcut_list": "Show the keyboard shortcut list",
"Showing_archived_results": "Showing %s archived results
",
"Showing_online_users": "Showing: __total_showing__ , Online: __online__, Total: __total__ users",
"Showing_results": "Showing %s results
",
+ "Sidebar": "Sidebar",
+ "Sidebar_list_mode": "Sidebar Channel List Mode",
+ "Sign_in_to_start_talking": "Sign in to start talking",
"since_creation": "since %s",
"Site_Name": "Site Name",
"Site_Url": "Site URL",
"Site_Url_Description": "Example: https://chat.domain.com/",
"Skip": "Skip",
"SlackBridge_error": "SlackBridge got an error while importing your messages at %s: %s",
+ "SlackBridge_finish": "SlackBridge has finished importing the messages at %s. Please reload to view all messages.",
"SlackBridge_Out_All": "SlackBridge Out All",
"SlackBridge_Out_All_Description": "Send messages from all channels that exist in Slack and the bot has joined",
"SlackBridge_Out_Channels": "SlackBridge Out Channels",
"SlackBridge_Out_Channels_Description": "Choose which channels will send messages back to Slack",
- "SlackBridge_finish": "SlackBridge has finished importing the messages at %s. Please reload to view all messages.",
"SlackBridge_Out_Enabled": "SlackBridge Out Enabled",
"SlackBridge_Out_Enabled_Description": "Choose whether SlackBridge should also send your messages back to Slack",
"SlackBridge_start": "@%s has started a SlackBridge import at `#%s`. We'll let you know when it's finished.",
+ "Slack_Users": "Slack's Users CSV",
"Slash_Gimme_Description": "Displays ༼ つ ◕_◕ ༽つ before your message",
"Slash_LennyFace_Description": "Displays ( ͡° ͜ʖ ͡°) after your message",
"Slash_Shrug_Description": "Displays ¯\\_(ツ)_/¯ after your message",
@@ -1264,22 +1790,30 @@
"SMTP_Port": "SMTP Port",
"SMTP_Test_Button": "Test SMTP Settings",
"SMTP_Username": "SMTP Username",
+ "snippet-message": "Snippet Message",
+ "snippet-message_description": "Permission to create snippet message",
+ "Snippet_name": "Snippet name",
"Snippet_Added": "Created on %s",
"Snippet_Messages": "Snippet Messages",
"Snippeted_a_message": "Created a snippet __snippetLink__",
+ "Sort_by_activity": "Sort by Activity",
"Sound": "Sound",
+ "Sound_File_mp3": "Sound File (mp3)",
"SSL": "SSL",
"Star_Message": "Star Message",
"Starred_Messages": "Starred Messages",
+ "Start": "Start",
"Start_audio_call": "Start audio call",
"Start_Chat": "Start Chat",
"Start_of_conversation": "Start of conversation",
"Start_OTR": "Start OTR",
"Start_video_call": "Start video call",
+ "Start_video_conference": "Start video conference?",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Start with %s for user or %s for channel. Eg: %s or %s",
"Started_At": "Started At",
+ "Started_a_video_call": "Started a Video Call",
"Statistics": "Statistics",
- "Statistics_reporting": "Send statistics to Rocket.Chat",
+ "Statistics_reporting": "Send Statistics to Rocket.Chat",
"Statistics_reporting_Description": "By sending your statistics, you'll help us identify how many instances of Rocket.Chat are deployed, as well as how good the system is behaving, so we can further improve it. Don't worry, as no user information is sent and all the information we receive is kept confidential.",
"Stats_Active_Users": "Active Users",
"Stats_Avg_Channel_Users": "Average Channel Users",
@@ -1291,12 +1825,20 @@
"Stats_Online_Users": "Online Users",
"Stats_Total_Channels": "Total Channels",
"Stats_Total_Direct_Messages": "Total Direct Message Rooms",
+ "Stats_Total_Livechat_Rooms": "Total Livechat Rooms",
"Stats_Total_Messages": "Total Messages",
+ "Stats_Total_Messages_Channel": "Total Messages in Channels",
+ "Stats_Total_Messages_Direct": "Total Messages in Direct Messages",
+ "Stats_Total_Messages_Livechat": "Total Messages in Livechats",
+ "Stats_Total_Messages_PrivateGroup": "Total Messages in Private Groups",
"Stats_Total_Private_Groups": "Total Private Groups",
"Stats_Total_Rooms": "Total Rooms",
"Stats_Total_Users": "Total Users",
"Status": "Status",
"Stop_Recording": "Stop Recording",
+ "Store_Last_Message": "Store Last Message",
+ "Store_Last_Message_Sent_per_Room": "Store last message sent on each room.",
+ "Stream_Cast": "Stream Cast",
"Stream_Cast_Address": "Stream Cast Address",
"Stream_Cast_Address_Description": "IP or Host of your Rocket.Chat central Stream Cast. E.g. `192.168.1.1:3000` or `localhost:4000`",
"strike": "strike",
@@ -1305,14 +1847,19 @@
"Success": "Success",
"Success_message": "Success message",
"Sunday": "Sunday",
+ "Support": "Support",
"Survey": "Survey",
"Survey_instructions": "Rate each question according to your satisfaction, 1 meaning you are completely unsatisfied and 5 meaning you are completely satisfied.",
"Symbols": "Symbols",
"Sync_success": "Sync success",
+ "Sync_in_progress": "Synchronization in progress",
"Sync_Users": "Sync Users",
"System_messages": "System Messages",
"Tag": "Tag",
"Take_it": "Take it!",
+ "TargetRoom": "Target Room",
+ "TargetRoom_Description": "The room where messages will be sent which are a result of this event being fired. Only one target room is allowed and it must exist.",
+ "Team": "Team",
"Test_Connection": "Test Connection",
"Test_Desktop_Notifications": "Test Desktop Notifications",
"Thank_you_exclamation_mark": "Thank you!",
@@ -1328,36 +1875,52 @@
"The_user_will_be_removed_from_s": "The user will be removed from %s",
"The_user_wont_be_able_to_type_in_s": "The user won't be able to type in %s",
"Theme": "Theme",
- "theme-color-transparent-darker": "Transparent Darker",
- "theme-color-transparent-dark": "Transparent Dark",
- "theme-color-transparent-light": "Transparent Light",
- "theme-color-transparent-lighter": "Transparent Lighter",
- "theme-color-transparent-lightest": "Transparent Lightest",
+ "theme-color-component-color": "Component Color",
"theme-color-content-background-color": "Content Background Color",
+ "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
+ "theme-color-error-color": "Error Color",
+ "theme-color-info-font-color": "Info Font Color",
+ "theme-color-link-font-color": "Link Font Color",
+ "theme-color-pending-color": "Pending Color",
+ "theme-color-primary-action-color": "Primary Action Color",
"theme-color-primary-background-color": "Primary Background Color",
"theme-color-primary-font-color": "Primary Font Color",
- "theme-color-primary-action-color": "Primary Action Color",
+ "theme-color-secondary-action-color": "Secondary Action Color",
"theme-color-secondary-background-color": "Secondary Background Color",
"theme-color-secondary-font-color": "Secondary Font Color",
- "theme-color-secondary-action-color": "Secondary Action Color",
- "theme-color-component-color": "Component Color",
- "theme-color-success-color": "Success Color",
- "theme-color-pending-color": "Pending Color",
- "theme-color-error-color": "Error Color",
"theme-color-selection-color": "Selection Color",
- "theme-color-tertiary-background-color": "Tertiary Background Color",
- "theme-color-tertiary-font-color": "Tertiary Font Color",
- "theme-color-link-font-color": "Link Font Color",
- "theme-color-info-font-color": "Info Font Color",
- "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
"theme-color-status-away": "Away Status Color",
"theme-color-status-busy": "Busy Status Color",
"theme-color-status-offline": "Offline Status Color",
"theme-color-status-online": "Online Status Color",
+ "theme-color-success-color": "Success Color",
+ "theme-color-tertiary-background-color": "Tertiary Background Color",
+ "theme-color-tertiary-font-color": "Tertiary Font Color",
+ "theme-color-transparent-dark": "Transparent Dark",
+ "theme-color-transparent-darker": "Transparent Darker",
+ "theme-color-transparent-light": "Transparent Light",
+ "theme-color-transparent-lighter": "Transparent Lighter",
+ "theme-color-transparent-lightest": "Transparent Lightest",
"theme-color-unread-notification-color": "Unread Notifications Color",
+ "theme-color-rc-color-error": "Error",
+ "theme-color-rc-color-error-light": "Error Light",
+ "theme-color-rc-color-alert": "Alert",
+ "theme-color-rc-color-alert-light": "Alert Light",
+ "theme-color-rc-color-success": "Success",
+ "theme-color-rc-color-success-light": "Success Light",
+ "theme-color-rc-color-button-primary": "Button Primary",
+ "theme-color-rc-color-button-primary-light": "Button Primary Light",
+ "theme-color-rc-color-primary": "Primary",
+ "theme-color-rc-color-primary-darkest": "Primary Darkest",
+ "theme-color-rc-color-primary-dark": "Primary Dark",
+ "theme-color-rc-color-primary-light": "Primary Light",
+ "theme-color-rc-color-primary-light-medium": "Primary Light Medium",
+ "theme-color-rc-color-primary-lightest": "Primary Lightest",
+ "theme-color-rc-color-content": "Content",
"theme-custom-css": "Custom CSS",
"theme-font-body-font-family": "Body Font Family",
"There_are_no_agents_added_to_this_department_yet": "There are no agents added to this department yet.",
+ "There_are_no_applications": "No oAuth Applications have been added yet.",
"There_are_no_integrations": "There are no integrations",
"There_are_no_users_in_this_role": "There are no users in this role.",
"This_conversation_is_already_closed": "This conversation is already closed.",
@@ -1375,57 +1938,102 @@
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "To install Rocket.Chat Livechat in your website, copy & paste this code above the last </body> tag on your site.",
"to_see_more_details_on_how_to_integrate": "to see more details on how to integrate.",
"To_users": "To Users",
+ "Toggle_original_translated": "Toggle original/translated",
+ "Token_Access": "Token Access",
+ "Token_Controlled_Access": "Token Controlled Access",
+ "Token_required": "Token required",
+ "Tokenpass_Channel_Label": "Tokenpass Channel",
+ "Tokenpass_Channels": "Tokenpass Channels",
+ "Tokens_Minimum_Needed_Balance": "Minimum needed token balance",
+ "Tokens_Minimum_Needed_Balance_Description": "Set minimum needed balance on each token. Blank or \"0\" for not limit.",
+ "Tokens_Minimum_Needed_Balance_Placeholder": "Balance value",
+ "Tokens_Required": "Tokens required",
+ "Tokens_Required_Input_Description": "Type one or more tokens asset names separated by comma.",
+ "Tokens_Required_Input_Error": "Invalid typed tokens.",
+ "Tokens_Required_Input_Placeholder": "Tokens asset names",
"Topic": "Topic",
- "Travel_and_Places": "Travel & Places",
- "Transcript_Enabled": "Ask visitor if they would like a transcript after chat closed",
- "Transcript_message": "Message to show when asking about transcript",
+ "Transcript_Enabled": "Ask Visitor if They Would Like a Transcript After Chat Closed",
+ "Transcript_message": "Message to Show When Asking About Transcript",
"Transcript_of_your_livechat_conversation": "Transcript of your livechat conversation.",
+ "Translated": "Translated",
+ "Translations": "Translations",
+ "Travel_and_Places": "Travel & Places",
"Trigger_removed": "Trigger removed",
"Trigger_Words": "Trigger Words",
"Triggers": "Triggers",
"True": "True",
"Tuesday": "Tuesday",
+ "Turn_ON": "Turn ON",
+ "Turn_OFF": "Turn OFF",
+ "Two-factor_authentication": "Two-factor authentication",
+ "Two-factor_authentication_disabled": "Two-factor authentication disabled",
+ "Two-factor_authentication_enabled": "Two-factor authentication enabled",
+ "Two-factor_authentication_is_currently_disabled": "Two-factor authentication is currently disabled",
+ "Two-factor_authentication_native_mobile_app_warning": "WARNING: Once you enable this, you will not be able to login on the native mobile apps (Rocket.Chat+) using your password until they implement the 2FA.",
"Type": "Type",
"Type_your_email": "Type your email",
"Type_your_message": "Type your message",
"Type_your_name": "Type your name",
"Type_your_new_password": "Type your new password",
+ "UI_Allow_room_names_with_special_chars": "Allow Special Characters in Room Names",
+ "UI_Click_Direct_Message": "Click to Create Direct Message",
+ "UI_Click_Direct_Message_Description": "Skip opening profile tab, instead go straight to conversation",
"UI_DisplayRoles": "Display Roles",
- "UI_Merge_Channels_Groups": "Merge private groups with channels",
- "UI_Use_Name_Avatar": "Use full name initials to generate default avatar",
+ "UI_Merge_Channels_Groups": "Merge Private Groups with Channels",
+ "UI_Unread_Counter_Style": "Unread Counter Style",
+ "UI_Use_Name_Avatar": "Use Full Name Initials to Generate Default Avatar",
+ "UI_Use_Real_Name": "Use Real Name",
"Unarchive": "Unarchive",
+ "unarchive-room": "Unarchive Room",
+ "unarchive-room_description": "Permission to unarchive channels",
"Unblock_User": "Unblock User",
+ "Uninstall": "Uninstall",
"Unmute_someone_in_room": "Unmute someone in the room",
"Unmute_user": "Unmute user",
"Unnamed": "Unnamed",
"Unpin_Message": "Unpin Message",
- "Unread_Alert": "Unread Alert",
+ "Unread_on_top" : "Unread on top",
+ "Unread_Count": "Unread Count",
+ "Unread_Count_DM": "Unread Count for Direct Messages",
+ "Unread_Messages": "Unread Messages",
"Unread_Rooms": "Unread Rooms",
"Unread_Rooms_Mode": "Unread Rooms Mode",
+ "Unread_Tray_Icon_Alert": "Unread Tray Icon Alert",
"Unstar_Message": "Remove Star",
+ "Updated_at": "Updated at",
+ "Update_your_RocketChat": "Update your Rocket.Chat",
+ "Upload_user_avatar": "Upload avatar",
"Upload_file_description": "File description",
"Upload_file_name": "File name",
"Upload_file_question": "Upload file?",
"Uploading_file": "Uploading file...",
"Uptime": "Uptime",
"URL": "URL",
- "URL_room_prefix": "URL room prefix",
+ "URL_room_prefix": "URL Room Prefix",
"Use_account_preference": "Use account preference",
"Use_Emojis": "Use Emojis",
"Use_Global_Settings": "Use Global Settings",
"Use_initials_avatar": "Use your username initials",
+ "Use_minor_colors": "Use minor color palette (defaults inherit major colors)",
"Use_service_avatar": "Use %s avatar",
"Use_this_username": "Use this username",
"Use_uploaded_avatar": "Use uploaded avatar",
- "Use_url_for_avatar": "Use url for avatar",
+ "Use_url_for_avatar": "Use URL for avatar",
"Use_User_Preferences_or_Global_Settings": "Use User Preferences or Global Settings",
+ "User": "User",
+ "user-generate-access-token": "User Generate Access Token",
+ "user-generate-access-token_description": "Permission for users to generate access tokens",
+ "User__username__is_now_a_leader_of__room_name_": "User __username__ is now a leader of __room_name__",
"User__username__is_now_a_moderator_of__room_name_": "User __username__ is now a moderator of __room_name__",
"User__username__is_now_a_owner_of__room_name_": "User __username__ is now a owner of __room_name__",
+ "User__username__removed_from__room_name__leaders": "User __username__ removed from __room_name__ leaders",
"User__username__removed_from__room_name__moderators": "User __username__ removed from __room_name__ moderators",
"User__username__removed_from__room_name__owners": "User __username__ removed from __room_name__ owners",
"User_added": "User added",
"User_added_by": "User __user_added__ added by __user_by__ .",
"User_added_successfully": "User added successfully",
+ "User_and_group_mentions_only": "User and group mentions only",
+ "User_default": "User default",
"User_doesnt_exist": "No user exists by the name of `@%s`.",
"User_has_been_activated": "User has been activated",
"User_has_been_deactivated": "User has been deactivated",
@@ -1433,6 +2041,7 @@
"User_has_been_muted_in_s": "User has been muted in %s",
"User_has_been_removed_from_s": "User has been removed from %s",
"User_Info": "User Info",
+ "User_Interface": "User Interface",
"User_is_blocked": "User is blocked",
"User_is_no_longer_an_admin": "User is no longer an admin",
"User_is_now_an_admin": "User is now an admin",
@@ -1445,6 +2054,7 @@
"User_left_male": "Has left the channel.",
"User_logged_out": "User is logged out",
"User_management": "User Management",
+ "User_mentions_only": "User mentions only",
"User_muted": "User Muted",
"User_muted_by": "User __user_muted__ muted by __user_by__ .",
"User_not_found": "User not found",
@@ -1453,9 +2063,13 @@
"User_removed": "User removed",
"User_removed_by": "User __user_removed__ removed by __user_by__ .",
"User_Settings": "User Settings",
+ "user_sent_an_attachment": "__user__ sent an attachment",
"User_unmuted_by": "User __user_unmuted__ unmuted by __user_by__ .",
"User_unmuted_in_room": "User unmuted in room",
"User_updated_successfully": "User updated successfully",
+ "User_uploaded_file": "Uploaded a file",
+ "User_uploaded_image": "Uploaded an image",
+ "User_Presence": "User Presence",
"Username": "Username",
"Username_and_message_must_not_be_empty": "Username and message must not be empty.",
"Username_cant_be_empty": "The username cannot be empty",
@@ -1467,6 +2081,12 @@
"Username_invalid": "%s is not a valid username, use only letters, numbers, dots, hyphens and underscores",
"Username_is_already_in_here": "`@%s` is already in here.",
"Username_is_not_in_this_room": "The user `#%s` is not in this room.",
+ "Username_Placeholder": "Please enter usernames...",
+ "Username_already_exist": "Username already exists. Please try another username.",
+ "User_sent_a_message_on_channel": "__username__ sent a message on __channel__ :",
+ "User_uploaded_a_file_on_channel": "__username__ uploaded a file on __channel__ :",
+ "User_sent_a_message_to_you": "__username__ sent you a message:",
+ "User_uploaded_a_file_to_you": "__username__ sent you a file:",
"Username_title": "Register username",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ wants to start OTR. Do you want to accept?",
"Users": "Users",
@@ -1475,20 +2095,56 @@
"UTF8_Names_Slugify": "UTF8 Names Slugify",
"UTF8_Names_Validation": "UTF8 Names Validation",
"UTF8_Names_Validation_Description": "RegExp that will be used to validate usernames and channel names",
- "Validate_email_address": "Validate email address",
+ "Validate_email_address": "Validate Email Address",
+ "Verification": "Verification",
"Verification_Description": "You may use the following placeholders: [Verification_Url] for the verification URL. [name], [fname], [lname] for the user's full name, first name or last name, respectively. [email] for the user's email. [Site_Name] and [Site_URL] for the Application Name and URL respectively. ",
+ "Verification_Email": "Click here to verify your account.",
"Verification_email_sent": "Verification email sent",
"Verification_Email_Subject": "[Site_Name] - Verify your account",
- "Verification_Email": "Click here to verify your account.",
"Verified": "Verified",
+ "Verify": "Verify",
"Version": "Version",
"Video_Chat_Window": "Video Chat",
"Video_Conference": "Video Conference",
- "Videocall_declined": "Videocall declined.",
- "Videocall_enabled": "Videocall enabled",
- "View_All": "View All",
+ "Video_message": "Video message",
+ "Videocall_declined": "Video Call Declined.",
+ "Videocall_enabled": "Video Call Enabled",
+ "view-c-room": "View Public Channel",
+ "view-c-room_description": "Permission to view public channels",
+ "view-d-room": "View Direct Messages",
+ "view-d-room_description": "Permission to view direct messages",
+ "view-full-other-user-info": "View Full Other User Info",
+ "view-full-other-user-info_description": "Permission to view full profile of other users including account creation date, last login, etc.",
+ "view-history": "View History",
+ "view-history_description": "Permission to view the channel history",
+ "view-join-code": "View Join Code",
+ "view-join-code_description": "Permission to view the channel join code",
+ "view-joined-room": "View Joined Room",
+ "view-joined-room_description": "Permission to view the currently joined channels",
+ "view-l-room": "View Livechat Rooms",
+ "view-l-room_description": "Permission to view livechat channels",
+ "view-livechat-manager": "View Livechat Manager",
+ "view-livechat-manager_description": "Permission to view other livechat managers",
+ "view-livechat-rooms": "View Livechat Rooms",
+ "view-livechat-rooms_description": "Permission to view other livechat channels",
+ "view-logs": "View Logs",
+ "view-logs_description": "Permission to view the server logs ",
+ "view-other-user-channels": "View Other User Channels",
+ "view-other-user-channels_description": "Permission to view channels owned by other users",
+ "view-outside-room": "View Outside Room",
+ "view-p-room": "View Private Room",
+ "view-p-room_description": "Permission to view private channels",
+ "view-privileged-setting": "View Privileged Setting",
+ "view-privileged-setting_description": "Permission to view settings",
+ "view-room-administration": "View Room Administration",
+ "view-room-administration_description": "Permission to view public, private and direct message statistics. Does not include the ability to view conversations or archives",
+ "view-statistics": "View Statistics",
+ "view-statistics_description": "Permission to view system statistics such as number of users logged in, number of rooms, operating system information",
+ "view-user-administration": "View User Administration",
+ "view-user-administration_description": "Permission to partial, read-only list view of other user accounts currently logged into the system. No user account information is accessible with this permission",
+ "View_All": "View All Members",
"View_Logs": "View Logs",
- "View_mode": "View mode",
+ "View_mode": "View Mode",
"View_mode_info": "This changes the amount of space messages take up on screen.",
"Viewing_room_administration": "Viewing room administration",
"Visibility": "Visibility",
@@ -1510,6 +2166,7 @@
"WebRTC_Enable_Private": "Enable for Private Channels",
"WebRTC_Servers": "STUN/TURN Servers",
"WebRTC_Servers_Description": "A list of STUN and TURN servers separated by comma. Username, password and port are allowed in the format `username:password@stun:host:port` or `username:password@turn:host:port`.",
+ "Website": "Website",
"Wednesday": "Wednesday",
"Welcome": "Welcome %s .",
"Welcome_to_the": "Welcome to the",
@@ -1518,13 +2175,14 @@
"Would_you_like_to_return_the_inquiry": "Would you like to return the inquiry?",
"Yes": "Yes",
"Yes_archive_it": "Yes, archive it!",
- "Yes_unarchive_it": "Yes, unarchive it!",
"Yes_clear_all": "Yes, clear all!",
"Yes_delete_it": "Yes, delete it!",
"Yes_hide_it": "Yes, hide it!",
"Yes_leave_it": "Yes, leave it!",
"Yes_mute_user": "Yes, mute user!",
"Yes_remove_user": "Yes, remove user!",
+ "Yes_unarchive_it": "Yes, unarchive it!",
+ "yesterday": "yesterday",
"You": "You",
"you_are_in_preview_mode_of": "You are in preview mode of channel #__room_name__ ",
"You_are_logged_in_as": "You are logged in as",
@@ -1535,8 +2193,10 @@
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "You can use webhooks to easily integrate livechat with your CRM.",
"You_cant_leave_a_livechat_room_Please_use_the_close_button": "You can't leave a livechat room. Please, use the close button.",
"You_have_been_muted": "You have been muted and cannot speak in this room",
+ "You_have_n_codes_remaining": "You have __number__ codes remaining.",
"You_have_not_verified_your_email": "You have not verified your email.",
"You_have_successfully_unsubscribed": "You have successfully unsubscribed from our Mailling List.",
+ "You_have_to_set_an_API_token_first_in_order_to_use_the_integration": "You have to set an API token first in order to use the integration.",
"You_must_join_to_view_messages_in_this_channel": "You must join to view messages in this channel",
"You_need_confirm_email": "You need to confirm your email to login!",
"You_need_install_an_extension_to_allow_screen_sharing": "You need install an extension to allow screen sharing",
@@ -1558,4 +2218,4 @@
"your_message_optional": "your message (optional)",
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/eo.i18n.json b/packages/rocketchat-i18n/i18n/eo.i18n.json
new file mode 100644
index 0000000000000..33e75430feb74
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/eo.i18n.json
@@ -0,0 +1,3 @@
+{
+ "#channel": "#kanalo"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/es.i18n.json b/packages/rocketchat-i18n/i18n/es.i18n.json
index 66cf244ca4ee9..a485b292475ac 100644
--- a/packages/rocketchat-i18n/i18n/es.i18n.json
+++ b/packages/rocketchat-i18n/i18n/es.i18n.json
@@ -1,7 +1,7 @@
{
"#channel": "#canal",
"0_Errors_Only": "0 - Sólo Errores",
- "1_Errors_and_Information": "1 - Errores y Información",
+ "1_Errors_and_Information": "1 - Errores e Información",
"2_Erros_Information_and_Debug": "2 - Errores, Información y Depuración ",
"403": "Prohibido",
"500": "Error interno del servidor",
@@ -12,11 +12,17 @@
"Accept": "Aceptar",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Aceptar solicitudes entrantes de chat en vivo aunque no haya agentes en línea",
"Accept_with_no_online_agents": "Aceptar sin agentes en línea",
+ "access-mailer": "Acceso a la Pantalla de Correo",
+ "access-mailer_description": "Permiso para enviar correo electrónico masivo a todos los usuarios.",
+ "access-permissions": "Acceso a la Pantalla de Permisos",
+ "access-permissions_description": "Modificar permisos para varios roles.",
"Access_not_authorized": "Acceso no autorizado",
"Access_Token_URL": "URL de Token de Acceso",
"Accessing_permissions": "Accediendo a los permisos",
"Account_SID": "Cuenta SID",
"Accounts": "Cuentas",
+ "Accounts_AllowAnonymousRead": "Permitir Lectura Anónima",
+ "Accounts_AllowAnonymousWrite": "Permitir Escritura Anónima",
"Accounts_AllowDeleteOwnAccount": "Permitir a los usuarios eliminar su propia cuenta",
"Accounts_AllowedDomainsList": "Lista de Dominios Permitidos",
"Accounts_AllowedDomainsList_Description": "Lista separada por comas de los dominios permitidos ",
@@ -27,19 +33,20 @@
"Accounts_AllowUserProfileChange": "Permitir al Usuario modificar su Perfil",
"Accounts_AvatarResize": "Cambiar el Tamaño de los Avatars",
"Accounts_AvatarSize": "Tamaño de Avatar",
- "Accounts_AvatarStorePath": "Ruta de almacenamiento de los avatares",
- "Accounts_AvatarStoreType": "Tipo de Almacenamiento de Avatar",
"Accounts_BlockedDomainsList": "Lista de dominios bloqueados",
"Accounts_BlockedDomainsList_Description": "Lista de dominios bloqueados separada por comas",
"Accounts_BlockedUsernameList": "Lista de nombres de usuario bloqueados",
"Accounts_BlockedUsernameList_Description": "Lista de nombres de usuarios bloqueados separada por comas (no distingue mayúsculas y minúsculas)",
+ "Accounts_CustomFieldsToShowInUserInfo": "Campos Personalizados para Mostrar en la Información del Usuario",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Sugerencia de Prefijo de Nombre de Usuario Predeterminado",
"Accounts_denyUnverifiedEmail": "Denegar correo electrónico sin verificar",
"Accounts_EmailVerification": "Verificación de correo electrónico",
"Accounts_EmailVerification_Description": "Asegúrese de que tiene la configuración SMTP correcta para usar esta característica",
"Accounts_Enrollment_Email": "Correo Electrónico de Inscripción ",
- "Accounts_Enrollment_Email_Default": " Bienvenido a [Site_Name] Ve a [Site_URL] y prueba la mejor solución de chat de código abierto disponible en la actualidad!
",
+ "Accounts_Enrollment_Email_Default": " Bienvenido a [Site_Name] Ve a [Site_URL] y prueba la mejor solución de chat de código abierto disponible en la actualidad!
",
"Accounts_Enrollment_Email_Description": "Puedes utilizar los siguientes marcadores: [name], [fname], [lname] para el nombre completo, nombre o apellidos, respectivamente. [email] para el correo electrónico del usuario [Site_Name] y [Site_URL] para el nombre del sitio web y la URL, respectivamente. ",
"Accounts_Enrollment_Email_Subject_Default": "Bienvenido a [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "Olvidar la sesión de usuario al cerrar la ventana",
"Accounts_Iframe_api_method": "Método API",
"Accounts_Iframe_api_url": "URL de la API",
"Accounts_iframe_enabled": "Habilitado",
@@ -54,11 +61,13 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "Ruta de Identidad",
"Accounts_OAuth_Custom_Login_Style": "Estilos del login",
+ "Accounts_OAuth_Custom_Merge_Users": "Fusionar usuarios",
"Accounts_OAuth_Custom_Scope": "Ámbito (scope)",
"Accounts_OAuth_Custom_Secret": "Secreto",
"Accounts_OAuth_Custom_Token_Path": "Ruta del Token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token enviado vía",
"Accounts_OAuth_Custom_Username_Field": "Campo de Nombre de Usuario",
+ "Accounts_OAuth_Drupal": "Inicio de sesión Drupal habilitado",
"Accounts_OAuth_Facebook": "Iniciar de sesión con Facebook",
"Accounts_OAuth_Facebook_callback_url": "URL de retorno (callback) de Facebook",
"Accounts_OAuth_Facebook_id": "App Id de Facebook",
@@ -87,6 +96,8 @@
"Accounts_OAuth_Meteor_callback_url": "URL de retorno (callback) de Meteor",
"Accounts_OAuth_Meteor_id": "Id de Meteor",
"Accounts_OAuth_Meteor_secret": "Secreto de Meteor",
+ "Accounts_OAuth_Proxy_host": "Anfitrión Proxy",
+ "Accounts_OAuth_Proxy_services": "Servicios de Proxy",
"Accounts_OAuth_Twitter": "Iniciar Sesión con Twitter",
"Accounts_OAuth_Twitter_callback_url": "URL de retorno (callback) de Twitter",
"Accounts_OAuth_Twitter_id": "Id de Twitter",
@@ -96,6 +107,8 @@
"Accounts_OAuth_Wordpress_id": "Id de Wordpress",
"Accounts_OAuth_Wordpress_secret": "Secreto de Wordpress",
"Accounts_PasswordReset": "Restablecer Contraseña",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Roles predeterminados para Servicios de Autenticación",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Los roles de usuario predeterminados (separados por coma) serán dados cuando se registren a través de los servicios de autenticación",
"Accounts_Registration_AuthenticationServices_Enabled": "Registro mediante Servicios de Autenticación",
"Accounts_RegistrationForm": "Formulario de Registro",
"Accounts_RegistrationForm_Disabled": "Deshabilitado",
@@ -103,20 +116,37 @@
"Accounts_RegistrationForm_Public": "Publico",
"Accounts_RegistrationForm_Secret_URL": "URL Secreto",
"Accounts_RegistrationForm_SecretURL": "URL Secreto del Fomulario de Registro",
- "Accounts_RegistrationForm_SecretURL_Description": "Debe proporcionar una cadena de texto aleatorio que se añadirá al URL de registro. Ejemplo: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Debe proporcionar una cadena de texto aleatorio que se añadirá al URL de registro. Ejemplo: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Requerir un Nombre para el Registro",
+ "Accounts_RequirePasswordConfirmation": "Solicitar Confirmación de Contraseña",
+ "Accounts_SearchFields": "Campos a Considerar en la Búsqueda",
+ "Accounts_SetDefaultAvatar": "Establecer avatar predeterminado",
+ "Accounts_SetDefaultAvatar_Description": "Tratar de determinar el avatar predeterminado basado en la cuenta OAuth o Gravatar",
"Accounts_ShowFormLogin": "Mostrar Inicio de sesión basado en formulario",
"Accounts_UseDefaultBlockedDomainsList": "Usar lista predeterminada de dominios bloqueados",
"Accounts_UseDNSDomainCheck": "Utilizar la comprobación de dominio DNS",
- "Accounts_UserAddedEmail_Default": " Bienvenido a [Site_Name] Ve a [Site_URL] y prueba la mejor solución de chat de código abierto disponible en la actualidad!
Puede iniciar sesión utilizando su correo electrónico: [email] y contraseña: [password]. Se le puede solicitar que lo cambie al iniciar sesion por primera vez.
",
+ "Accounts_UserAddedEmail_Default": " Bienvenido a [Site_Name] Ve a [Site_URL] y prueba la mejor solución de chat de código abierto disponible en la actualidad!
Puede iniciar sesión utilizando su correo electrónico: [email] y contraseña: [password]. Se le puede solicitar que lo cambie al iniciar sesion por primera vez.
",
"Accounts_UserAddedEmail_Description": "Es posible utilizar los siguientes marcadores: [name], [fname], [lname] para el nombre completo del usuario, el nombre o el apellido, respectivamente. [email] para el correo electrónico del usuario. [password] para la contraseña del usuario. [Site_Name] y [Site_URL] para el nombre de la aplicación y la URL, respectivamente. ",
"Accounts_UserAddedEmailSubject_Default": "Has sido añadido a [Site_Name]",
"Activate": "Activar",
"Activity": "Actividad",
"Add": "Agregar",
+ "add-oauth-service": "Agregar Servicio Oauth",
+ "add-oauth-service_description": "Permiso para agregar un nuevo servicio Oauth",
+ "add-user": "Añadir Usuario",
+ "add-user-to-any-c-room": "Añadir Usuario a Cualquier Canal Público",
+ "add-user-to-any-c-room_description": "Permiso para agregar un usuario a cualquier canal público",
+ "add-user-to-any-p-room": "Añadir Usuario a Cualquier Canal Privado",
+ "add-user-to-any-p-room_description": "Permiso para añadir un usuario a cualquier canal privado",
+ "add-user-to-joined-room": "Añadir Usuario a Cualquier Canal Unido",
+ "add-user-to-joined-room_description": "Permiso para agregar un usuario a un canal actualmente unido",
+ "add-user_description": "Permiso para agregar nuevos usuarios al servidor a través de la pantalla de usuarios",
"Add_agent": "Agregar agente",
"Add_custom_oauth": "Agregar oauth personalizado",
+ "Add_Domain": "Agregar Dominio",
+ "Add_files_from": "Añadir archivos desde",
"Add_manager": "Agregar supervisor",
+ "Add_Role": "Agregar Rol",
"Add_user": "Agregar Usuario",
"Add_User": "Añadir usuario",
"Add_users": "Agrerar usuarios",
@@ -126,6 +156,7 @@
"Additional_emails": "Correos electrónicos adicionales",
"Additional_Feedback": "Retroalimentación adicional",
"Administration": "Administración",
+ "Adult_images_are_not_allowed": "No se permiten imágenes para adultos",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Después de la autenticación OAuth2, los usuarios serán redirigidos a esta URL",
"Agent": "Agente",
"Agent_added": "Agente agregado",
@@ -133,32 +164,53 @@
"Alias": "Alias",
"Alias_Format": "Formato del alias",
"Alias_Format_Description": "Importar mensajes desde Slack con un alias; %s se sustituirá por el nombre de usuario del usuario. Si se deja en blanco, no se utilizará ningún alias.",
+ "Alias_Set": "Establecer alias",
"All": "Todo",
"All_channels": "Todos los canales",
"All_logs": "Todos los registros",
"All_messages": "Todos los mensajes",
+ "All_users_in_the_channel_can_write_new_messages": "Todos los usuarios del canal pueden escribir nuevos mensajes",
"Allow_Invalid_SelfSigned_Certs": "Permitir Certificados Auto-Firmados Invalidos",
"Allow_Invalid_SelfSigned_Certs_Description": "Permitir certificados SSL autofirmados e invalidos para validación de enlaces y vistas previas.",
+ "Allow_switching_departments": "Permitir al visitante cambiar de departamentos",
+ "Always_open_in_new_window": "Abrir siempre en una nueva ventana",
"Analytics_features_enabled": "Características habilitadas",
"Analytics_features_messages_Description": "Monitoriza eventos personalizados relacionados con acciones que un usuario hace en los mensajes.",
"Analytics_features_rooms_Description": "Monitoriza eventos personalizados relacionados con acciones en un canal o grupo (crear, salir, eliminar).",
"Analytics_features_users_Description": "Monitoriza eventos personalizados relacionados con las acciones relacionadas con los usuarios (tiempo de restablecimiento de contraseña, cambio de avatar, etc.).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "ID de seguimiento",
"and": "y",
"And_more": "Y __length__ mas",
"Animals_and_Nature": "Animales y Naturaleza",
+ "Announcement": "Anuncio",
"API": "API",
+ "API_Allow_Infinite_Count": "Permitir obtener todo",
+ "API_Allow_Infinite_Count_Description": "¿Debería permitirse que las llamadas a la API REST devuelvan todo en una sola llamada?",
"API_Analytics": "Analiticas",
+ "API_CORS_Origin": "Origen del CORS",
+ "API_Default_Count": "Contador por defecto",
+ "API_Default_Count_Description": "El valor predeterminado para los resultados de REST API si el consumidor no proporcionó ninguno.",
+ "API_Drupal_URL": "URL del Servidor Drupal",
+ "API_Drupal_URL_Description": "Ejemplo: https://domain.com (sin incluir la barra diagonal)",
"API_Embed": "Incrustar (embed)",
+ "API_EmbedCacheExpirationDays": "Días de Vencimiento de Caché Embebido",
"API_EmbedDisabledFor": "Deshabilitar el insertar vinculos para los Usuarios",
"API_EmbedDisabledFor_Description": "Lista separada por comas de nombres de usuarios ",
"API_EmbedIgnoredHosts": "Incrusta hosts ignorados",
"API_EmbedIgnoredHosts_Description": "Lista de equipos o direcciones CIDR, separada por comas. Ej: localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Puertos seguros",
"API_EmbedSafePorts_Description": "Lista de puertos permitidos para la previsualización, separada por comas.",
- "API_GitHub_Enterprise_URL": "URL del Servidor",
+ "API_Enable_CORS": "Habilitar CORS",
+ "API_Enable_Shields": "Activar escudos",
+ "API_Enable_Shields_Description": "Activar los escudos disponibles en `/api/v1/shields. svg`",
+ "API_GitHub_Enterprise_URL": "URL del servidor",
"API_GitHub_Enterprise_URL_Description": "Ejemplo: http://domain.com (sin incluir la diagonal final)",
"API_Gitlab_URL": "URL de GitLab",
+ "API_Shield_Types": "Tipos de Escudo",
"API_Token": "API Token",
+ "API_Upper_Count_Limit": "Cantidad máxima de registro",
+ "API_Upper_Count_Limit_Description": "¿Cuál es el número máximo de registros que debe devolver la API REST (cuando no es ilimitado)?",
"API_User_Limit": "Límite de usuarios para añadir todos los usuarios al canal",
"API_Wordpress_URL": "URL de Wordpress",
"Apiai_Key": "Clave Api.ai",
@@ -169,16 +221,31 @@
"Application_updated": "Aplicación actualizada",
"Apply_and_refresh_all_clients": "Aplicar y refrescar todos los clientes",
"Archive": "Archivo",
+ "archive-room": "Archivar Room",
+ "archive-room_description": "Permiso para archivar un canal",
"are_also_typing": "también están escribiendo",
"are_typing": "están escribiendo",
"Are_you_sure": "Estás seguro?",
"Are_you_sure_you_want_to_delete_your_account": "¿Estás seguro de que quieres eliminar tu cuenta?",
+ "assign-admin-role": "Asignar Rol de Administrador",
+ "assign-admin-role_description": "Permiso para asignar el rol admin a otros usuarios",
+ "Assign_admin": "Asignando administrador",
"at": "en",
+ "AtlassianCrowd": "Atlassian Crowd",
+ "Attachment_File_Uploaded": "Archivo subido",
+ "Attribute_handling": "Manejo de atributos",
+ "Audio_message": "Mensaje de audio",
+ "Audio_Notification_Value_Description": "Puede ser cualquier sonido personalizado o por defecto: beep, chelle, ding, droplet, highbell, seasons",
+ "Audio_Notifications_Default_Alert": "Alerta Predeterminada para Notificaciones de Audio",
+ "Audio_Notifications_Value": "Audio de notificación de mensaje predeterminado",
"Auth_Token": "Auth Token",
"Author": "Autor",
"Authorization_URL": "URL de Autorización",
"Authorize": "Autorizar",
+ "auto-translate": "Autotraducir",
+ "auto-translate_description": "Permiso para utilizar la herramienta de traducción automática",
"Auto_Load_Images": "Cargar automáticamente las imagenes",
+ "Auto_Translate": " Traducción Automática",
"AutoLinker_Email": "AutoLinker Correo Electrónico",
"AutoLinker_Phone": "AutoLinker Teléfono",
"AutoLinker_Phone_Description": "Enlazada automáticamente los números de teléfono. Ej:`(123) 456-7890`",
@@ -186,27 +253,39 @@
"AutoLinker_StripPrefix_Description": "Presentación corta. Ej: https://rocket.chat => rocket.chat",
"AutoLinker_Urls_Scheme": "AutoLinker Scheme:// URLs",
"AutoLinker_Urls_TLD": "AutoLinker URLs TLD",
- "AutoLinker_Urls_www": "AutoLinker URLs 'www'",
- "AutoLinker_UrlsRegExp": "AutoLinker URL de expresiones regulares",
+ "AutoLinker_Urls_www": "Enlaces Automáticos en URLs 'www'",
+ "AutoLinker_UrlsRegExp": "Enlaces Automáticos en URL de expresiones regulares",
+ "Automatic_Translation": "Traducción automática",
+ "AutoTranslate_Change_Language_Description": "Cambiar el idioma de la traducción automática no traduce los mensajes anteriores.",
+ "AutoTranslate_Enabled": "Habilitar Traducción Automática",
+ "AutoTranslate_GoogleAPIKey": "Clave de la API de Google",
"Available": "Disponible",
"Available_agents": "Agentes disponibles",
"Avatar": "Avatar",
"Avatar_changed_successfully": "Avatar cambiado correctamente",
"Avatar_URL": "URL del Avatar",
- "Avatar_url_invalid_or_error": "El url proporcionado es invalido o no es accesible. Por favor intente otra vez, pero con un url diferente.",
+ "Avatar_url_invalid_or_error": "El url proporcionado es inválido o no es accesible. Por favor intente otra vez, pero con un url diferente.",
"away": "lejos",
"Away": "Lejos",
"away_female": "ausente",
"Away_female": "Ausente",
"away_male": "ausente",
"Away_male": "Ausente",
- "Back": "Atras",
+ "Back": "Atrás",
"Back_to_applications": "Volver a las aplicaciones",
- "Back_to_integrations": "De regreso a integraciones",
+ "Back_to_chat": "Volver al chat",
+ "Back_to_integration_detail": "Volver al detalle de la integración",
+ "Back_to_integrations": "Volver a integraciones",
"Back_to_login": "Volver a identificarse",
"Back_to_permissions": "Regresar a permisos",
+ "Backup_codes": "Respaldar códigos",
+ "ban-user": "Prohibir Usuario",
+ "ban-user_description": "Permiso para prohibir a un usuario de un canal",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Característica beta. Depende de la videoconferencia para habilitarlo.",
+ "Block_User": "Bloquear Usuario",
"Body": "Cuerpo",
"bold": "negrita",
+ "BotHelpers_userFields": "Campos de Usuario",
"Branch": "Rama",
"busy": "ocupado",
"Busy": "Ocupado",
@@ -215,23 +294,36 @@
"busy_male": "ocupado",
"Busy_male": "Ocupado",
"by": "por",
+ "cache_cleared": "Caché borrado",
"Cancel": "Cancelar",
"Cancel_message_input": "Cancelar",
"Cannot_invite_users_to_direct_rooms": "No se puede invitar a los usuarios a las salas directas",
+ "CAS_autoclose": "Cierre Automático de la ventana emergente de Inicio de Sesión",
+ "CAS_button_color": "Color de fondo para el botón de inicio de sesión",
+ "CAS_button_label_color": "Color del texto del botón de inicio de sesión",
+ "CAS_button_label_text": "Etiqueta del botón de inicio de sesión",
+ "CAS_enabled": "Habilitado",
+ "CAS_popup_height": "Alto de de Ventana Emergente de Inicio de Sesión",
+ "CAS_popup_width": "Ancho de Ventana Emergente de Inicio de Sesión",
+ "CAS_Sync_User_Data_Enabled": "Siempre sincronizar los Datos de Usuario",
"CDN_PREFIX": "Prefijo de CDN",
"Certificates_and_Keys": "Certificados y Llaves",
+ "Change_Room_Type": "Cambiar el Tipo de Sala",
"Changing_email": "Cambiando correo electrónico",
+ "channel": "canal",
"Channel": "Canal",
"Channel_already_exist": "El canal '#% s' ya existe.",
- "Channel_already_Unarchived": "El canal con nombre `#% s` ya está en estado Desarchivado.",
- "Channel_Archived": "El canal con nombre `#% s` se ha archivado correctamente.",
- "Channel_doesnt_exist": "El canal `#%s` no existe",
+ "Channel_already_Unarchived": "El canal con nombre `#%s` ya está en estado Desarchivado",
+ "Channel_Archived": "El canal con nombre `#%s` ha sido archivado con éxito",
+ "Channel_doesnt_exist": "El canal `#%s` no existe",
+ "Channel_name": "Nombre del Canal",
+ "Channel_Name_Placeholder": "Por favor ingrese el nombre del canal...",
"Channel_Unarchived": "El canal con nombre `#% s` se ha desarchivado correctamente.",
"Channels": "Canales",
"Channels_list": "Lista de canales públicos",
"Chat_button": "Botón de chat",
"Chat_closed": "Chat cerrado",
- "Chat_closed_successfully": "Chat cerrado correctamente",
+ "Chat_closed_successfully": "Chat cerrado con éxito",
"Chat_window": "Ventana de chat",
"Chatops_Enabled": "Habilitar Chatops",
"Chatops_Title": "Panel de Chatops",
@@ -240,8 +332,12 @@
"Choose_messages": "Elija mensajes",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Elige el alias que aparecerá antes del nombre de usuario en los mensajes.",
"Choose_the_username_that_this_integration_will_post_as": "Elige el nombre de usuario con el cual esta integración publicara.",
+ "clear": "Borrar",
"Clear_all_unreads_question": "Borrar todos los mensajes no leídos?",
+ "clear_cache_now": "Borrar caché ahora",
+ "clear_history": "Borrar Historial",
"Click_here": "Haga clic aquí",
+ "Click_here_for_more_info": "Cliquea aquí para más información",
"Client_ID": "Cliente ID",
"Client_Secret": "Cliente Secreto",
"Clients_will_refresh_in_a_few_seconds": "Los clientes se refrescaran en unos pocos segundos",
@@ -255,6 +351,7 @@
"Commands": "Comandos",
"Compact": "Compacto",
"Confirm_password": "Confirma tu contraseña",
+ "Content": "Contenido",
"Conversation": "Conversación",
"Conversation_closed": "Conversación cerrada: __comment__.",
"Convert_Ascii_Emojis": "Convierte ASCII a Emoji",
@@ -265,25 +362,42 @@
"Count": "Contar",
"Cozy": "Acogedor",
"Create": "Crear",
+ "create-d": "Crear Mensajes Directos",
+ "create-user": "Crear usuario",
+ "create-user_description": "Permiso para crear usuarios",
"Create_A_New_Channel": "Crear un nuevo canal",
"Create_new": "Crear nuevo",
"Created_at": "Creado en",
"Created_at_s_by_s": "Creado a las %s por %s ",
"Current_Chats": "Chats actuales",
+ "Current_Status": "Estado actual",
"Custom": "Personalizado",
"Custom_Fields": "Campos Personalizados",
"Custom_oauth_helper": "Mientras configura el Proveedor de OAuth, tendra que establecer un URL de Devolucion. Use %s .",
"Custom_oauth_unique_name": "Nombre único de oauth personalizado",
"Custom_Script_Logged_In": "Script personalizado para los usuarios que han iniciado sesión",
"Custom_Script_Logged_Out": "Script personalizado para los usuarios que han cerrado sesión",
+ "Custom_Scripts": "Scripts Personalizados",
+ "Custom_Sound_Add": "Agregar Sonido Personalizado",
+ "Custom_Sound_Error_Invalid_Sound": "Sonido no válido",
+ "Custom_Sound_Error_Name_Already_In_Use": "El nombre de sonido personalizado ya está siendo utilizado.",
+ "Custom_Sound_Has_Been_Deleted": "El sonido personalizado ha sido borrado.",
+ "Custom_Sound_Info": "Información de Sonido Personalizado",
+ "Custom_Sound_Saved_Successfully": "Sonido personalizado guardado con éxito",
+ "Custom_Sounds": "Sonidos Personalizados",
+ "Custom_Translations": "Traducciones Personalizadas",
"Dashboard": "Tablero",
"Date": "Fecha",
+ "Date_From": "Desde",
+ "Date_to": "hasta",
"days": "días",
"DB_Migration": "Migración de bases de datos",
"DB_Migration_Date": "Fecha de migración de base de datos",
"Deactivate": "Desactivar",
"Default": "Por defecto",
"Delete": "Eliminar",
+ "delete-message": "Eliminar mensaje",
+ "delete-user": "Eliminar usuario",
"Delete_message": "Borrar mensaje",
"Delete_my_account": "Borrar mi cuenta",
"Delete_Room_Warning": "Eliminar un sala de chat eliminara todos los mensajes de la sala. Esto no se puede deshacer",
@@ -303,10 +417,16 @@
"Desktop_Notifications_Enabled": "Las Notificaciones de Escritorio están Habilitadas",
"Direct_message_someone": "Mensaje directo a alguien",
"Direct_Messages": "Mensajes Directos",
+ "Direct_Reply_Password": "Contraseña",
+ "Direct_Reply_Separator": "Separador",
+ "Direct_Reply_Username": "Nombre de usuario",
+ "Disable_Notifications": "Deshabilitar notificaciones",
"Display_offline_form": "Mostrar formulario fuera línea",
"Displays_action_text": "Mostrar texto de la acción",
"Do_you_want_to_change_to_s_question": "Desea cambiar a %s ",
"Domain": "Dominio",
+ "Domain_added": "dominio Agregado",
+ "Domain_removed": "Dominio Borrado",
"Domains": "Dominios",
"Drop_to_upload_file": "Arrastra aqui para subir el archivo",
"Dry_run": "Funcionamiento en seco",
@@ -326,7 +446,7 @@
"Email_address_to_send_offline_messages": "Dirección de correo electrónico para enviar mensajes fuera de línea",
"Email_already_exists": "El correo electrónico ya existe",
"Email_body": "Cuerpo del Correo electrónico",
- "Email_Change_Disabled": "Su administrador ha deshabilitado el hacer cambios de correo electrónico",
+ "Email_Change_Disabled": "Su administrador ha deshabilitado el cambio de correo electrónico",
"Email_Footer_Description": "Es posible utilizar los siguientes marcadores: [Site_Name] y [Site_URL] para el nombre de la aplicación y la URL, respectivamente. ",
"Email_from": "De",
"Email_Header_Description": "Es posible utilizar los siguientes marcadores: [Site_Name] y [Site_URL] para el nombre de la aplicación y la URL, respectivamente. ",
@@ -337,56 +457,62 @@
"Email_subject": "Asunto",
"Email_verified": "Correo electrónico verificado",
"Emoji": "Emoji",
- "Empty_title": "Titulo Vacio",
+ "EmojiCustomFilesystem": "Sistema de Archivos Emoji Personalizado",
+ "Empty_title": "Titulo Vacío",
"Enable": "Habilitar",
"Enable_Desktop_Notifications": "Habilitar Notificaciones de Escritorio",
+ "Enable_Svg_Favicon": "Habilitar favicon SVG",
"Enabled": "Habilitado",
"Encrypted_message": "Mensaje cifrado",
"End_OTR": "Finalizar OTR",
"Enter_a_regex": "Introduzca un regex",
"Enter_a_room_name": "Introduzca un nombre de sala",
- "Enter_a_username": "Ingrese un nombre de usuario",
- "Enter_name_here": "Introduce el nombre aquí",
+ "Enter_a_username": "Introduzca un nombre de usuario",
+ "Enter_name_here": "Introduzca nombre aquí",
+ "Enter_Normal": "Modo normal(enviar con Enter)",
"Enter_to": "Entrar a",
"Error": "Error",
"error-action-not-allowed": "__action__ no está permitido",
"error-application-not-found": "Aplicación no encontrada",
- "error-archived-duplicate-name": "Hay un canal de archivado con el nombre '__room_name__'",
- "error-avatar-invalid-url": "URL del avatar no válido: __url__",
+ "error-archived-duplicate-name": "Hay un canal archivado con el nombre '__room_name__'",
+ "error-avatar-invalid-url": "URL de avatar inválida: __url__",
"error-avatar-url-handling": "Error durante la manipulación de ajuste de imagen de usuario desde una dirección URL (__url__) para __username__",
"error-cant-invite-for-direct-room": "No se puede invitar al usuario salas directos",
"error-could-not-change-email": "No se pudo cambiar de correo electrónico",
"error-could-not-change-name": "No se pudo cambiar el nombre",
"error-could-not-change-username": "No se pudo cambiar nombre de usuario",
- "error-delete-protected-role": "No puede eliminar un rol protegido",
+ "error-delete-protected-role": "No se puede eliminar un rol protegido",
"error-department-not-found": "Departamento no encontrado",
+ "error-direct-message-file-upload-not-allowed": "No se permite compartir archivos en mensajes directos",
"error-duplicate-channel-name": "Un canal con el nombre '__channel_name__' ya existe",
- "error-email-domain-blacklisted": "El dominio de correo electrónico en una lista negra",
+ "error-email-domain-blacklisted": "El dominio de correo electrónico está en una lista negra",
"error-field-unavailable": "__field__ ya está en uso :(",
"error-file-too-large": "El archivo es demasiado grande",
- "error-importer-not-defined": "El importador no se definió correctamente, no se encuentra la clase de importación.",
- "error-input-is-not-a-valid-field": "__input__ no es un __field__ válida",
- "error-invalid-actionlink": "enlace de acción no válida",
- "error-invalid-arguments": "Los argumentos inválidos",
+ "error-importer-not-defined": "El importador no se definió correctamente, no se encuentra la Clase de Importación.",
+ "error-input-is-not-a-valid-field": "__input__ no es un __field__ válido",
+ "error-invalid-actionlink": "Enlace de acción inválido",
+ "error-invalid-arguments": "Argumentos inválidos",
"error-invalid-asset": "Activo invalido",
"error-invalid-channel": "Canal no válido.",
"error-invalid-channel-start-with-chars": "Canal no válido. Comience con @ o #",
"error-invalid-custom-field": "Campo personalizado no válido",
"error-invalid-custom-field-name": "No válido nombre de campo personalizado. Utilice sólo letras, números, guiones y guiones bajos.",
+ "error-invalid-date": "Fecha inválida.",
"error-invalid-description": "Descripción no valida",
"error-invalid-domain": "Dominio no válido",
"error-invalid-email": "__email__ email no es válido",
+ "error-invalid-email-address": "Dirección de correo inválida",
"error-invalid-file-height": "Altura Invalida de Archivo",
"error-invalid-file-type": "Tipo Invalido de Archivo",
"error-invalid-file-width": "Anchura Invalida de Archivo",
"error-invalid-from-address": "Ha ingresado una dirección invalida en el campo De",
- "error-invalid-integration": "la integración no válido",
- "error-invalid-message": "mensaje no válido",
- "error-invalid-method": "método no válido",
+ "error-invalid-integration": "Integración inválida",
+ "error-invalid-message": "Mensaje inválido",
+ "error-invalid-method": "Método inválido",
"error-invalid-name": "Nombre inválido",
- "error-invalid-password": "Contraseña invalida",
+ "error-invalid-password": "Contraseña inválida",
"error-invalid-redirectUri": "inválida redirectUri",
- "error-invalid-role": "función no válida",
+ "error-invalid-role": "Role inválido",
"error-invalid-room": "Sala no válida",
"error-invalid-room-name": " %s no es un nombre válido de Sala, utilice sólo letras, números, guiones y guiones bajos",
"error-invalid-room-type": "__type__ no es un tipo valido de Sala.",
@@ -418,8 +544,11 @@
"error-you-are-last-owner": "Usted es el último propietario. Por favor, establezca un nuevo propietario antes de salir de la Sala.",
"Error_changing_password": "Error al cambiar de contraseña",
"Esc_to": "Esc a",
+ "every_30_minutes": "Una vez cada 30 minutos",
+ "every_hour": "Una vez por hora",
+ "every_six_hours": "Una vez cada seis horas",
"Example_s": "Ejemplo: %s",
- "Exclude_Botnames": "Excluir bots",
+ "Exclude_Botnames": "Excluir Bots",
"Exclude_Botnames_Description": "No propagar los mensajes de bots cuyos nombres coincidan con la expresión regular. Se se deja en blanco, todos los mensajes de los bots se propagarán.",
"False": "Falso",
"Favorite_Rooms": "Habilitar salas favoritas",
@@ -428,6 +557,7 @@
"Field": "Campo",
"Field_removed": "Campo eliminado",
"File_exceeds_allowed_size_of_bytes": "El archivo supera el tamaño permitido de __size__ ",
+ "File_type_is_not_accepted": "El tipo de archivo no es admitido.",
"FileUpload": "Subir archivos",
"FileUpload_Enabled": "Habilitar subir archivos",
"FileUpload_File_Empty": "Archivo Vacio",
@@ -439,28 +569,30 @@
"FileUpload_ProtectFiles": "Proteger archivos cargados",
"FileUpload_ProtectFilesDescription": "Únicamente usuarios autenticados tendrán acceso ",
"FileUpload_S3_Acl": "Amazon S3 acl",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyID",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 bucket name",
+ "FileUpload_S3_AWSAccessKeyId": "Access Key",
+ "FileUpload_S3_AWSSecretAccessKey": "Secret Key",
+ "FileUpload_S3_Bucket": "Nombre de Bucket",
"FileUpload_S3_BucketURL": "Bucket URL",
- "FileUpload_S3_CDN": "Dominio CDN para descargas",
+ "FileUpload_S3_CDN": "Dominio CDN para Descargas",
"FileUpload_S3_Region": "Región",
- "FileUpload_S3_URLExpiryTimeSpan": "Caducidad de las URLs",
+ "FileUpload_S3_URLExpiryTimeSpan": "Tiempo de caducidad de las URLs",
"FileUpload_S3_URLExpiryTimeSpan_Description": "Tiempo después el cual las direcciones de Amazon S3 generadas dejarán de ser válidas (en segundos). Si se establece a menos de 5 segundos, este campo será ignorado.",
"FileUpload_Storage_Type": "Tipo de Almacenamiento",
"Flags": "Indicadores",
"Follow_social_profiles": "Sigue nuestros perfiles sociales, realiza un fork en github y comparte tus pensamientos acerca de la aplicación rocket.chat en nuestro tablero de Trello.",
+ "Fonts": "Fuentes",
"Food_and_Drink": "Comer y beber",
"Footer": "Pie de página",
"For_your_security_you_must_enter_your_current_password_to_continue": "Para su seguridad, debe volver a introducir su contraseña para continuar",
"Force_SSL": "Forzar SSL",
"Force_SSL_Description": "* Precaución! * _Force SSL_ nunca debe ser usado con proxy inverso. Si usted tiene un proxy inverso, debería hacer la redirección AHÍ. Esta opción existe para los despliegues como Heroku, que no permite la configuración de redirección en el proxy inverso.",
"Forgot_password": "Olvidaste tu contraseña",
- "Forward": "Remitir",
- "Forward_chat": "Remitir chat",
- "Forward_to_department": "Remitir al departamento",
- "Forward_to_user": "Remitir al usuario",
+ "Forward": "Reenviar",
+ "Forward_chat": "Reenviar chat",
+ "Forward_to_department": "Reenviar a departamento",
+ "Forward_to_user": "Reenviar a usuario",
"Frequently_Used": "Usado frecuentemente",
+ "Friday": "Viernes",
"From": "De",
"From_Email": "De Correo electrónico",
"From_email_warning": "Advertencia : El campo De esta sujeto a la configuración en tu servidor de correo.",
@@ -473,9 +605,10 @@
"Guest_Pool": "Pool de invitados",
"Hash": "Hash",
"Header": "Encabezado",
+ "Header_and_Footer": "Encabezado y Pie de página",
"Hidden": "Oculto",
"Hide_Avatars": "Ocultar avatares",
- "Hide_flextab": "Esconder barra lateral derecha al hacer clic",
+ "Hide_flextab": "Ocultar Barra Lateral Derecha con un Click",
"Hide_Group_Warning": "¿Seguro que desea ocultar el grupo \" %s\"?",
"Hide_Private_Warning": "¿Está seguro de que desea ocultar la discusión con \" %s\"?",
"Hide_room": "Ocultar sala",
@@ -487,6 +620,7 @@
"History": "Historial",
"Host": "Anfitrión",
"hours": "horas",
+ "Hours": "Horas",
"How_friendly_was_the_chat_agent": "Ha sido amable el agente de chat?",
"How_knowledgeable_was_the_chat_agent": "Cuánto sabía el agente de chat?",
"How_responsive_was_the_chat_agent": "Cómo de rápido ha respondido nuestro agente de chat?",
@@ -494,41 +628,49 @@
"If_you_are_sure_type_in_your_password": "Si está seguro escriba su contraseña:",
"If_you_are_sure_type_in_your_username": "Si está seguro ingrese su nombre de usuario:",
"Importer_Archived": "Archivado",
- "Importer_done": "Importación completa!",
- "Importer_finishing": "Finalizar la importación.",
+ "Importer_CSV_Information": "El importador de CSV requiere un formato específico; lea la documentación sobre cómo estructurar su archivo zip:",
+ "Importer_done": "¡Importación terminada!",
+ "Importer_finishing": "Finalizando la importación.",
"Importer_From_Description": "Las importaciones __from datos __ 's en Rocket.Chat.",
"Importer_import_cancelled": "Importación cancelada.",
"Importer_import_failed": "Se produjo un error durante la ejecución de la importación.",
- "Importer_importing_channels": "La importación de los canales.",
- "Importer_importing_messages": "La importación de los mensajes.",
- "Importer_importing_started": "A partir de la importación.",
- "Importer_importing_users": "La importación de los usuarios.",
+ "Importer_importing_channels": "Importando los canales.",
+ "Importer_importing_messages": "Importando los mensajes.",
+ "Importer_importing_started": "Iniciando la importación.",
+ "Importer_importing_users": "Importando los usuarios.",
"Importer_not_in_progress": "El importador actualmente no se está ejecutando.",
- "Importer_Prepare_Restart_Import": "reinicio de importación",
- "Importer_Prepare_Start_Import": "comenzar a importar",
- "Importer_Prepare_Uncheck_Archived_Channels": "Canales archivados desactive los campos",
- "Importer_Prepare_Uncheck_Deleted_Users": "Los usuarios desmarque eliminados",
+ "Importer_not_setup": "El importador no está configurado correctamente, ya que no devolvió ningún dato.",
+ "Importer_Prepare_Restart_Import": "Reiniciar importación",
+ "Importer_Prepare_Start_Import": "Iniciar importación",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Descarmar Channel archivados",
+ "Importer_Prepare_Uncheck_Deleted_Users": "Desmarcar usuarios eliminados",
"Importer_progress_error": "No se pudo obtener el progreso de la importación.",
"Importer_setup_error": "Se produjo un error al configurar el importador.",
+ "Importer_Source_File": "Selección del archivo de origen",
"Incoming_Livechats": "LiveChats entrantes",
"inline_code": "inline_code",
- "Install_Extension": "Instalar extension",
- "Install_FxOs": "Instalar Rocket.Chat en Firefox",
- "Install_FxOs_done": "Grandioso! Ya puedes comenzar a utilizar Rocket.Chat mediante el icono de tu Escritorio. Diviértete usando Rocket.Chat!",
- "Install_FxOs_error": "Sentimos que no funcionara como es debido! Apareció el siguiente error:",
+ "Install_Extension": "Instalar Extensión",
+ "Install_FxOs": "Instalar Rocket.Chat en su Firefox",
+ "Install_FxOs_done": "Genial! Ya puede comenzar a usarRocket.Chat mediante el ícono en su Escritorio. ¡Diviértase usando Rocket.Chat!",
+ "Install_FxOs_error": "Lo sentimos, ¡eso no funcionó como se esperaba! El siguiente error apareció:",
"Install_FxOs_follow_instructions": "Por favor confirma la instalación de la aplicación en tu dispositivo (presione \"Instalar\" cuando se le solicite).",
"Installation": "Instalación ",
"Installed_at": "instalado en",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instrucciones a sus visitantes llenan el formulario para enviar un mensaje",
"Integration_added": "La Integración ha sido añadida",
+ "Integration_Advanced_Settings": "Ajustes Avanzados",
"Integration_Incoming_WebHook": "Integración WebHook de Entrada",
"Integration_New": "Nueva Integración",
"Integration_Outgoing_WebHook": "Integración web hook saliente",
"Integration_updated": "La Integración ha sido actualizada",
"Integrations": "Integraciones",
+ "Integrations_Outgoing_Type_FileUploaded": "Archivo Subido",
+ "Integrations_Outgoing_Type_RoomArchived": "chat archivado",
+ "Integrations_Outgoing_Type_RoomCreated": "chat creado(público y privado)",
+ "Integrations_Outgoing_Type_RoomJoined": "Usuario se ha unido al chat",
"InternalHubot": "hubot interna",
- "InternalHubot_ScriptsToLoad": "Secuencias de comandos para cargar",
- "InternalHubot_ScriptsToLoad_Description": "Por favor, introduzca una lista separada por comas de secuencias de comandos para cargar desde https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_ScriptsToLoad": "Scripts a Cargar",
+ "InternalHubot_ScriptsToLoad_Description": "Por favor introduzca una lista separada por comas de scripts a cargar desde su carpeta personalizada ",
"InternalHubot_Username_Description": "Este debe ser un nombre de usuario válido de un bot registrado en su servidor.",
"Invalid_confirm_pass": "La confirmación de la contraseña no coincide con la contraseña",
"Invalid_email": "El e-mail ingresado es invalido",
@@ -539,15 +681,21 @@
"Invalid_pass": "La contraseña no debe estar vacia",
"Invalid_room_name": "%s no es un nombre de sala válido, use solo letras, números y guiones",
"Invalid_secret_URL_message": "El URL proporcionado es invalido.",
+ "Invalid_setting_s": "Configuración no válida: %s",
"invisible": "invisible",
"Invisible": "Invisible",
+ "Invitation": "Invitación",
"Invitation_HTML": "HTML de la Invitación",
"Invitation_HTML_Default": " Se le ha invitado a [Site_Name] Ir a [Site_URL] y probar la mejor solución de chat de código abierto disponibles en la actualidad!
",
"Invitation_HTML_Description": "Es posible utilizar los siguientes marcadores: [email] para el correo electrónico del destinatario. [Site_Name] y [Site_URL] para el nombre de la aplicación y la URL, respectivamente. ",
"Invitation_Subject": "Asunto de la Invitación",
"Invitation_Subject_Default": "Se le ha invitado a [Site_Name]",
"Invite_user_to_join_channel": "Invitar a un usuario a unirse a este canal",
+ "Invite_user_to_join_channel_all_from": "Invitar a todos los usuarios de [#channell] para unirse a este canal",
+ "Invite_user_to_join_channel_all_to": "Invitar a todos los usuarios de este canal a unirse a [#channel]",
"Invite_Users": "Invitar Usuarios",
+ "IRC_Channel_Join": "Salida del comando JOIN",
+ "IRC_Channel_Leave": "Salida del comando PART",
"is_also_typing": "también esta escribiendo",
"is_also_typing_female": "tambien esta escribiendo",
"is_also_typing_male": "tambien esta escribiendo",
@@ -592,51 +740,37 @@
"Layout_Terms_of_Service": "Términos del Servicio",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Dominio Personalizado de Busqueda",
- "LDAP_Custom_Domain_Search_Description": "Un pedazo de JSON que gobierna se unen y la conexión y la información es de la forma: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "Tiempo de espera de conexión(ms)",
"LDAP_Default_Domain": "Dominio Predeterminado",
"LDAP_Description": "LDAP es una base de datos jerárquica que muchas empresas utilizan para proporcionar inicio de sesión único - una instalación para compartir una contraseña entre múltiples sitios y servicios. Para obtener información avanzada de configuración y ejemplos, consulte nuestra wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Dominio Base",
- "LDAP_Domain_Base_Description": "El nombre completo (DN) de un sub-árbol LDAP que desea buscar usuarios y grupos. Se pueden añadir tantos como quiera; sin embargo, cada grupo se debe definir en la misma base de dominio que los usuarios que pertenecen a la misma. Si especifica los grupos de usuarios restringidos, sólo los usuarios que pertenecen a esos grupos serán de alcance. Recomendamos que se especifica el nivel superior del árbol de directorios LDAP como su base de dominio y utiliza filtro de búsqueda para controlar el acceso.",
- "LDAP_Domain_Search_Filter": "Filtro del Dominio de Busqueda",
- "LDAP_Domain_Search_Filter_Description": "Si se les permitirá especificados, sólo los usuarios que coincidan con este filtro para iniciar sesión. Si no se especifica ningún filtro, todos los usuarios dentro del alcance de la base de dominio especificado serán capaces de iniciar sesión. Por ejemplo, para Active Directory `memberOf = cn = ROCKET_CHAT, ou = Groups` general. Por ejemplo, para OpenLDAP (búsqueda de coincidencia de extensible) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Contraseña del Dominio de Busqueda",
- "LDAP_Domain_Search_Object_Category_Description": "El objectCategory * * que identifican a los usuarios. Dejar en blanco para OpenLDAP * *. Por ejemplo, `Person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Clase de dominio de búsqueda de objetos",
- "LDAP_Domain_Search_Object_Class_Description": "La clase de objeto * * que identifican a los usuarios. Por ejemplo, `organizationalPerson`,` usuario de la red, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Búsqueda de dominio contraseña",
- "LDAP_Domain_Search_Password_Description": "La contraseña para el usuario de búsqueda de dominios.",
- "LDAP_Domain_Search_User": "Búsqueda de dominio del usuario",
- "LDAP_Domain_Search_User_Description": "El usuario LDAP que realiza búsquedas de usuario para autenticar a otros usuarios cuando inician sesión en. Esta es normalmente una cuenta de servicio creado específicamente para integraciones de terceros. Utilizar un nombre completo, como `cn = Administrador, cn = Users, dc = ejemplo, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Dominio de búsqueda ID de usuario",
- "LDAP_Domain_Search_User_ID_Description": "El atributo LDAP que identifica al usuario que intente LDAP autenticación. Este campo debe ser `sAMAccountName` para la mayoría de las instalaciones de Active Directory, pero puede ser` uid` para otras soluciones LDAP, como OpenLDAP. Puede utilizar `mail` para identificar a los usuarios por correo electrónico o cualquier atributo que desee. Se pueden utilizar varios valores separados por comas para permitir a los usuarios acceder usando múltiples identificadores como nombre de usuario o correo electrónico.",
- "LDAP_Enable": "Habilitado",
+ "LDAP_BaseDN_Description": "El nombre completo (DN) de un sub-árbol LDAP que desea buscar usuarios y grupos. Se pueden añadir tantos como quiera; sin embargo, cada grupo se debe definir en la misma base de dominio que los usuarios que pertenecen a la misma. Si especifica los grupos de usuarios restringidos, sólo los usuarios que pertenecen a esos grupos serán de alcance. Recomendamos que se especifica el nivel superior del árbol de directorios LDAP como su base de dominio y utiliza filtro de búsqueda para controlar el acceso.",
+ "LDAP_User_Search_Field_Description": "El atributo LDAP que identifica al usuario que intente LDAP autenticación. Este campo debe ser `sAMAccountName` para la mayoría de las instalaciones de Active Directory, pero puede ser` uid` para otras soluciones LDAP, como OpenLDAP. Puede utilizar `mail` para identificar a los usuarios por correo electrónico o cualquier atributo que desee. Se pueden utilizar varios valores separados por comas para permitir a los usuarios acceder usando múltiples identificadores como nombre de usuario o correo electrónico.",
+ "LDAP_User_Search_Filter_Description": "Si se les permitirá especificados, sólo los usuarios que coincidan con este filtro para iniciar sesión. Si no se especifica ningún filtro, todos los usuarios dentro del alcance de la base de dominio especificado serán capaces de iniciar sesión. Por ejemplo, para Active Directory `memberOf = cn = ROCKET_CHAT, ou = Groups` general. Por ejemplo, para OpenLDAP (búsqueda de coincidencia de extensible) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "El usuario LDAP que realiza búsquedas de usuario para autenticar a otros usuarios cuando inician sesión en. Esta es normalmente una cuenta de servicio creado específicamente para integraciones de terceros. Utilizar un nombre completo, como `cn = Administrador, cn = Users, dc = ejemplo, dc = com`.",
+ "LDAP_Enable": "Habilitar",
"LDAP_Enable_Description": "Intentar utilizar LDAP como método de autenticación ",
"LDAP_Encryption": "Cifrado",
"LDAP_Encryption_Description": "Metodo de cifrado usado para la comunicación segura hacia el servidor LDAP. Algunos ejemplos 'sin cifrado', 'SSL/LDAPS (cifrado desde el inicio), y 'StartTLS' ( actualizar a comunicaciónes cifradas una ves conectado).",
"LDAP_Host": "Servidor",
- "LDAP_Host_Description": "Servidor LDAP, ejem. `ldap.example.com` o`10.0.0.30`.",
+ "LDAP_Host_Description": "Servidor LDAP, ej. `ldap.example.com` o`10.0.0.30`.",
"LDAP_Port": "Puerto",
"LDAP_Port_Description": "Puerto para acceder a LDAP. ej. `389` o `636` para LDAPS",
"LDAP_Reject_Unauthorized": "rechazar no autorizada",
- "LDAP_Sync_User_Avatar": "Sincronizar Avatar del usuario",
- "LDAP_Sync_User_Data": "Sincronizar Datos",
+ "LDAP_Sync_User_Avatar": "Sincronizar Avatar del Usuario",
+ "LDAP_Sync_User_Data": "Sincronizar Datos de Usuario",
"LDAP_Sync_User_Data_Description": "Mantener los datos del usuario en sincronía con el servidor al iniciar sesión (ej: nombre, correo electrónico). ",
- "LDAP_Sync_User_Data_FieldMap": "Mapa de campos de datos de usuario",
+ "LDAP_Sync_User_Data_FieldMap": "Mapa de Campos de Datos de Usuario",
"LDAP_Sync_User_Data_FieldMap_Description": "Configurar como los campos de cuenta de usuario ( como el correo electrónico) son llenados desde un registro en LDAP (una vez encontrados). A modo de ejemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` elegira el nombre legible de una persona desde el atributo cn, y su correo electrónico desde el atributo de correo electrónico. Campos disponibles `nombre` y `correo electrónico`.",
- "LDAP_Sync_Users": "Sincronizar Usuarios",
"LDAP_Test_Connection": "Probar Conexión ",
- "LDAP_Unique_Identifier_Field": "Campo de Identificador Único ",
+ "LDAP_Unique_Identifier_Field": "Campo Identificador Único ",
"LDAP_Unique_Identifier_Field_Description": "Qué campo se utilizará para vincular al usuario LDAP y el usuario Rocket.Chat. Puede informar a varios valores separados por una coma para tratar de obtener el valor del registro de LDAP. El valor por defecto es `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueid, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Usar la búsqueda de dominio personalizado",
- "LDAP_Use_Custom_Domain_Search_Description": "Escribir su propio filtro para buscar a los usuarios en el servidor LDAP.",
"LDAP_Username_Field": "Campo de Nombre de Usuario",
"LDAP_Username_Field_Description": "Qué campo se utilizará como nombre de usuario * * para los nuevos usuarios. Dejar en blanco para usar el nombre de usuario informado en la página de inicio de sesión. Puede utilizar etiquetas de plantilla también, como `#{givenName}.#{sn}`. El valor por defecto es `sAMAccountName`.",
- "Least_Amount": "Menor cantidad",
- "Leave_Group_Warning": "¿Seguro que quieres dejar el grupo \" %s\"?",
- "Leave_Private_Warning": "¿Seguro que quieres salir de la discusión con \" %s\"?",
+ "Least_Amount": "Menor Cantidad",
+ "Leave_Group_Warning": "¿Seguro que quieres dejar el grupo \"%s\"?",
+ "Leave_Private_Warning": "¿Seguro que quieres salir de la discusión con \"%s\"?",
"Leave_room": "Salir de la sala",
- "Leave_Room_Warning": "¿Seguro que quieres salir de la Sala \" %s\"?",
+ "Leave_Room_Warning": "¿Seguro que quieres salir de la sala \"%s\"?",
"line": "línea",
"List_of_Channels": "Lista de Canales",
"List_of_Direct_Messages": "Lista de mensajes directos",
@@ -670,7 +804,7 @@
"Login": "Iniciar Sesión",
"Login_with": "Inicia sesión con %s",
"Logout": "Cerrar sesión",
- "Logout_Others": "Cerrar sesión en todos los lugares donde se ha abierto una",
+ "Logout_Others": "Cerrar Sesión en Todos los Lugares Donde se ha abierto una",
"Mail_Message_Invalid_emails": "Ha proporcionado uno o mas correos electronicos invalidos %s",
"Mail_Message_Missing_to": "Debe seleccionar uno o más usuarios o proporcionar una o más direcciones de correo electrónico, separadas por comas.",
"Mail_Message_No_messages_selected_select_all": "No ha seleccionado ningún mensaje. ¿Le gustaría seleccionar todos los mensajes visibles?",
@@ -680,35 +814,37 @@
"Mailer": "Remitente",
"Mailer_body_tags": "Debe utilizar [unsubscribe] para el enlace de anulación de la suscripción. Es posible utilizar [name], [fname], [lname] para el nombre completo del usuario, nombre o apellido, respectivamente. Es posible utilizar [email] para el correo electrónico del usuario.",
"Mailing": "Envío",
- "Make_Admin": "Crear admin",
+ "Make_Admin": "Hacer Administrador",
"Manager_added": "Supervisor agregado",
"Manager_removed": "Supervisor eliminado",
"Managing_assets": "La gestión de activos",
"Managing_integrations": "La gestión de integraciones",
- "Mark_as_read": "Marcar como leído",
- "Mark_as_unread": "Marcar como no leído",
- "Markdown_Headers": "Encabezados Markdown",
+ "Mark_as_read": "Marcar Como Leído",
+ "Mark_as_unread": "Marcar Como No Leído",
+ "Markdown_Headers": "Permitir Encabezados Markdown en mensajes",
"Markdown_SupportSchemesForLink": "Planes de apoyo de rebajas de Enlace",
"Markdown_SupportSchemesForLink_Description": "Lista separada por comas de los esquemas permitidos",
"Members_List": "Lista de Miembros",
"Mentions": "Menciones",
"Mentions_default": "Menciones (por defecto)",
"Message": "Mensaje",
- "Message_AllowBadWordsFilter": "Permitir el filtrado de lenguaje en los Mensajes",
+ "Message_AllowBadWordsFilter": "Permitir el filtrado de malas palabras en los Mensajes",
"Message_AllowDeleting": "Permitir la eliminación de mensajes",
"Message_AllowDeleting_BlockDeleteInMinutes": "Bloquear la Eliminación de Mensajes Despues de (n) Minutos",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Introduzca 0 para desactivar el bloqueo.",
+ "Message_AllowDirectMessagesToYourself": "Permita mensajes directos del usuario a usted mismo",
"Message_AllowEditing": "Permitir la edición de mensajes",
"Message_AllowEditing_BlockEditInMinutes": "Bloquear la Edicion de Mensajes Despues de (n) Minutos",
"Message_AllowEditing_BlockEditInMinutesDescription": "Ingrese 0 para deshabilitar el bloqueo.",
"Message_AllowPinning": "Permitir que se fijen/anclen los mensajes",
"Message_AllowPinning_Description": "Permitir que los mensajes se puedan anclar a cualquier canal.",
"Message_AllowStarring": "Permitir Destacar un Mensaje",
+ "Message_AllowUnrecognizedSlashCommand": "Permitir Comandos Slash no Reconocidos",
"Message_AlwaysSearchRegExp": "Siempre buscar utilizando RegExp",
"Message_AlwaysSearchRegExp_Description": "Recomendamos establecer `TRUE si el idioma no es compatible con la búsqueda de texto MongoDB .",
"Message_AudioRecorderEnabled": "Grabadora de audio habilitada",
"Message_AudioRecorderEnabledDescription": "Requiere que los archivos del tipo 'audio/wav' sean un tipo de archivo valido dentro de las opciones de 'Carga de Archivos'.",
- "Message_BadWordsFilterList": "Añadir malas palabras a la lista negra",
+ "Message_BadWordsFilterList": "Añadir Malas Palabras a la Lista Negra",
"Message_BadWordsFilterListDescription": "Añadir Lista de lista separada por comas de malas palabras para filtrar",
"Message_DateFormat": "Formato de fecha",
"Message_DateFormat_Description": "Ver también: Moment.js ",
@@ -727,6 +863,7 @@
"Message_ShowEditedStatus": "Mostrar el estado de edición",
"Message_ShowFormattingTips": "Mostrar Sugerencias de Formato",
"Message_starring": "Mensaje Destacado",
+ "Message_TimeAndDateFormat": "Formato de Fecha y Hora",
"Message_TimeFormat": "Formato de tiempo",
"Message_TimeFormat_Description": "Ver también: Moment.js ",
"Message_too_long": "Mensaje demasiado largo",
@@ -737,33 +874,33 @@
"Meta": "Meta",
"Meta_fb_app_id": "App Id de Facebook",
"Meta_google-site-verification": "Verificación del sitio de Google (Google Site Verification)",
- "Meta_language": "Lenguaje",
+ "Meta_language": "Idioma",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Robots",
"minutes": "minutos",
"Monitor_history_for_changes_on": "Monitoriza el historial de cambios en",
"More_channels": "Más canales",
"More_direct_messages": "Más mensajes directos",
- "More_groups": "Mas grupos privados",
- "More_unreads": "Mas sin leer",
+ "More_groups": "Más grupos privados",
+ "More_unreads": "Más no leídos",
"Msgs": "Mensajes",
"multi": "multi",
"Mute_someone_in_room": "Silenciar a alguien en la sala",
- "Mute_user": "Silenciar Usuario",
+ "Mute_user": "Silenciar usuario",
"Muted": "Silenciado",
- "My_Account": "Mi cuenta",
+ "My_Account": "Mi Cuenta",
"n_messages": "%s mensajes",
"N_new_messages": " %s nuevos mensajes",
"Name": "Nombre",
- "Name_cant_be_empty": "El Nombre no puede estar vacio",
- "Name_of_agent": "Nombre del Agente",
+ "Name_cant_be_empty": "El nombre no puede estar vacío",
+ "Name_of_agent": "Nombre del agente",
"Name_optional": "Nombre (opcional)",
"Navigation_History": "Historial de navegación",
"New_Application": "Nueva aplicación",
"New_Custom_Field": "Nuevo campo personalizado",
"New_Department": "Nuevo Departamento",
"New_integration": "Nueva integración ",
- "New_logs": "nuevos registros",
+ "New_logs": "Nuevos registros",
"New_Message_Notification": "Nueva notificación de mensajes",
"New_messages": "Nuevos mensajes",
"New_password": "Nueva contraseña",
@@ -773,7 +910,7 @@
"No_channel_with_name_%s_was_found": "Ningún canal con el nombre \"%s\" ha sido encontrado!",
"No_channels_yet": "Todavía no eres parte de un canal.",
"No_direct_messages_yet": "No has comenzado ninguna conversación aún\n",
- "No_Encryption": "sin cifrado",
+ "No_Encryption": "Sin Cifrado",
"No_group_with_name_%s_was_found": "Ningún grupo privado con el nombre \"%s\" ha sido encontrado!",
"No_groups_yet": "Aún no tienes grupos privados.",
"No_livechats": "No tienes ningun chat en tiempo real (Livechat).",
@@ -793,6 +930,7 @@
"Nothing_found": "No se encontró nada",
"Notification_Duration": "Duración de la notificación",
"Notifications": "Notificaciones",
+ "Notifications_Sound_Volume": "Volumen del sonido de las notificaciones",
"Notify_all_in_this_room": "Notificar a todos en este canal",
"Num_Agents": "# de Agentes",
"Number_of_messages": "Número de mensajes",
@@ -810,7 +948,7 @@
"Offline_Mention_Email": "Usted ha sido mencionado por __user__ en #__room__",
"Offline_message": "Mensaje fuera de línea",
"Offline_success_message": "Mensaje fuera de línea correcto",
- "Offline_unavailable": "disponible sin conexión",
+ "Offline_unavailable": "No disponible sin conexión",
"On": "Activar",
"Online": "Conectado",
"Only_you_can_see_this_message": "Solo tú puedes ver este mensaje",
@@ -839,9 +977,9 @@
"Page_URL": "URL de la página",
"Password": "Contraseña",
"Password_Change_Disabled": "Tu administrador de Rocket.Chat ha deshabilitado la opción para cambiar contraseñas.",
- "Password_changed_successfully": "La contraseña fue cambiada con éxito",
+ "Password_changed_successfully": "Contraseña cambiada con éxito",
"Past_Chats": "Los chats últimos",
- "Payload": "Carga útil",
+ "Payload": "Payload",
"People": "Gente",
"Permalink": "Permalink",
"Permissions": "Permisos",
@@ -850,21 +988,21 @@
"Pinned_Messages": "Mensajes Fijados",
"PiwikAnalytics_siteId_Description": "La Identificación del sitio a utilizar para la identificación de este sitio. Ejemplo: 17",
"PiwikAnalytics_url_Description": "La url donde reside el Piwik, asegúrese de incluir la barra probando. Ejemplo: //piwik.rocket.chat/",
- "Placeholder_for_email_or_username_login_field": "Marcador de posición para el campo de correo electrónico o nombre de usuario de inicio de sesión",
- "Placeholder_for_password_login_field": "Marcador de posición para el campo de la contraseña de inicio de sesión",
- "Please_add_a_comment": "Por favor, añadir un comentario",
- "Please_add_a_comment_to_close_the_room": "Por favor, agrega un comentario para cerrar la Sala",
- "Please_answer_survey": "Por favor, tómese un momento para responder una encuesta rápida sobre este chat",
- "Please_enter_value_for_url": "Por favor, introduzca un valor para la url de su avatar.",
- "Please_enter_your_new_password_below": "Por favor, introduzca a continuación su nueva contraseña:",
+ "Placeholder_for_email_or_username_login_field": "Placeholder para el campo Email o Nombre de Usuario de Inicio de Sesión",
+ "Placeholder_for_password_login_field": "Placeholder para el Campo Contraseña de Inicio de Sesión",
+ "Please_add_a_comment": "Por favor, agregue un comentario",
+ "Please_add_a_comment_to_close_the_room": "Por favor, agregue un comentario para cerrar la sala",
+ "Please_answer_survey": "Por favor tómese un momento para responder una breve encuesta sobre este chat",
+ "Please_enter_value_for_url": "Por favor introduzca un valor para la url de su avatar.",
+ "Please_enter_your_new_password_below": "Por favor introduzca a continuación su nueva contraseña:",
"Please_enter_your_password": "Por favor ingrese su contraseña",
- "Please_fill_a_label": "Por favor llene una etiqueta",
- "Please_fill_a_name": "Por favor introduzca su nombre",
- "Please_fill_a_username": "Por favor ingrese un nombre de usuario",
- "Please_fill_name_and_email": "Por favor introduzca su usuario y correo electrónico. ",
+ "Please_fill_a_label": "Por favor introduzca una etiqueta",
+ "Please_fill_a_name": "Por favor introduzca un nombre",
+ "Please_fill_a_username": "Por favor introduzca un nombre de usuario",
+ "Please_fill_name_and_email": "Por favor introduzca nombre y correo electrónico",
"Please_select_enabled_yes_or_no": "Por favor elija una opción para Habilitar",
"Please_wait": "Por favor espere",
- "Please_wait_activation": "Por favor espere, esto puede tomar algún tiempo.",
+ "Please_wait_activation": "Por favor espere, ésto puede tomar algún tiempo.",
"Please_wait_while_OTR_is_being_established": "Por favor espere mientras se está estableciendo OTR",
"Please_wait_while_your_account_is_being_deleted": "Por favor, espere mientras se elimina su cuenta ...",
"Please_wait_while_your_profile_is_being_saved": "Por favor, espere mientras que su perfil se guarda ...",
@@ -928,8 +1066,9 @@
"Report_this_message_question_mark": "Reportar este mensaje?",
"Require_password_change": "Requerir el cambio de contraseña",
"Resend_verification_email": "Reenviar correo electrónico de verificación",
- "Reset": "Reiniciar",
- "Reset_password": "Reiniciar password",
+ "Reset": "Restablecer",
+ "Reset_password": "Restablecer contraseña",
+ "Reset_section_settings": "Restablecer la Configuración de la Sección",
"Restart": "Reiniciar",
"Restart_the_server": "Reiniciar el servidor",
"Role": "Rol",
@@ -945,13 +1084,13 @@
"room_changed_topic": "Tema del la sala cambiado a: __room_topic__ por __user_by__ ",
"Room_description_changed_successfully": "Descripción de la sala cambiada correctamente",
"Room_has_been_deleted": "La Sala ha sido eliminada",
- "Room_Info": "Info de la Sala",
+ "Room_Info": "Información de la Sala",
"Room_name_changed": "El nombre de la sala ha sido cambiado a: __room_name__ por __user_by__ ",
- "Room_name_changed_successfully": "El nombre de la Sala fue cambiado con éxito",
+ "Room_name_changed_successfully": "Nombre de sala cambiado con éxito",
"Room_not_found": "Sala no encontrada",
"Room_topic_changed_successfully": "tema de Sala cambiado con éxito",
"Room_type_changed_successfully": "Tipo de Sala cambiado correctamente",
- "Room_unarchived": "sala no archivada",
+ "Room_unarchived": "Sala no archivada",
"Room_uploaded_file_list": "Lista de Archivos",
"Room_uploaded_file_list_empty": "Ningún archivo disponible.",
"Rooms": "Salas",
@@ -965,17 +1104,17 @@
"SAML_Custom_Provider": "Proveedor Personalizado",
"Save": "Guardar",
"Save_changes": "Guardar cambios",
- "Save_Mobile_Bandwidth": "Ahorrar ancho de banda Movil",
- "Save_to_enable_this_action": "Guardar para permitir esta acción",
+ "Save_Mobile_Bandwidth": "Ahorrar Ancho de Banda Móvil",
+ "Save_to_enable_this_action": "Guarde para habilitar esta acción",
"Saved": "Guardado",
"Saving": "Guardando",
"Scope": "Alcance",
"Screen_Share": "Compartir Pantalla",
- "Script_Enabled": "Guión Habilitado",
+ "Script_Enabled": "Script Habilitado",
"Search": "Buscar",
"Search_by_username": "Búsqueda por nombre de usuario",
"Search_Messages": "Buscar Mensajes",
- "Search_Private_Groups": "Grupos privados",
+ "Search_Private_Groups": "Buscar Grupos privados",
"seconds": "segundos",
"Secret_token": "Token secreto",
"Select_a_department": "Seleccionar un departamento",
@@ -1010,12 +1149,12 @@
"Settings_updated": "Se han actualización las opciones ",
"Should_be_a_URL_of_an_image": "Debe de ser un URL de una imagen. ",
"Should_exists_a_user_with_this_username": "Ya debe existir el usuario.",
- "Show_all": "Mostrar todo",
+ "Show_all": "Mostrar todos",
"Show_more": "Mostrar más",
"show_offline_users": "Mostrar usuarios desconectados",
"Show_only_online": "Mostrar sólo en linea",
- "Show_preregistration_form": "Mostrar formulario de inscripción previa",
- "Show_queue_list_to_all_agents": "Mostrar la cola de todos los agentes",
+ "Show_preregistration_form": "Mostrar formulario de Preinscripción",
+ "Show_queue_list_to_all_agents": "Mostrar Lista de Cola a Todos los Agentes",
"Showing_archived_results": " Mostrando resultados archivados %s
",
"Showing_online_users": "Mostrando: __total_showing__ En linea: __online__ Total:__total__ ",
"Showing_results": "Mostrando %s resultados
",
@@ -1030,11 +1169,11 @@
"Slash_Tableflip_Description": "Muestra ° (╯ ° □ °) ╯( ┻━┻",
"Slash_TableUnflip_Description": "Muestra ┬─┬ ノ (゜ - ゜ ノ)",
"Slash_Topic_Description": "Establecer tema",
- "Slash_Topic_Params": "mensaje del tema",
- "Smileys_and_People": "Smileys e personas",
- "SMS_Enabled": "Activar SMS",
+ "Slash_Topic_Params": "Mensaje del tema",
+ "Smileys_and_People": "Sonrisas y Personas",
+ "SMS_Enabled": "SMS Habilitado",
"SMTP": "SMTP",
- "SMTP_Host": "Anfitrión SMTP",
+ "SMTP_Host": "Servidor SMTP",
"SMTP_Password": "Contraseña SMTP",
"SMTP_Port": "Puerto SMTP",
"SMTP_Test_Button": "Prueba de valores de SMTP",
@@ -1043,15 +1182,15 @@
"SSL": "SSL",
"Star_Message": "Destacar un Mensaje",
"Starred_Messages": "Mensajes Destacados",
- "Start_audio_call": "Iniciar llamada",
- "Start_Chat": "Iniciar chat",
+ "Start_audio_call": "Iniciar llamada de audio",
+ "Start_Chat": "Iniciar Chat",
"Start_of_conversation": "Inicio de la conversación",
- "Start_OTR": "Inicio OTR",
+ "Start_OTR": "Iniciar OTR",
"Start_video_call": "Iniciar video llamada",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Inicia con %s para un usuario o %s para un canal. Ej: %s o %s",
"Started_At": "Empezó a las",
"Statistics": "Estadisticas",
- "Statistics_reporting": "Enviar estadísticas de Rocket.Chat",
+ "Statistics_reporting": "Enviar Estadísticas a Rocket.Chat",
"Statistics_reporting_Description": "Mediante el envío de sus estadísticas, usted ayudará a identificar cómo se implementan muchos casos de Rocket.Chat, así como lo bien que el sistema se está comportando, por lo que puede mejorar aún más. No se preocupe, ya que no envíe información de usuario y toda la información que recibimos se mantiene confidencial.",
"Stats_Active_Users": "Usuarios Activos",
"Stats_Avg_Channel_Users": "Promedio de usuarios por canal",
@@ -1069,7 +1208,7 @@
"Stats_Total_Users": "Total de Usuarios",
"Stop_Recording": "Detener Grabacion",
"strike": "strike",
- "Subject": "Tema",
+ "Subject": "Asunto",
"Submit": "Enviar",
"Success": "Exito",
"Success_message": "Mensaje correcto",
@@ -1077,46 +1216,46 @@
"Survey_instructions": "Califique cada pregunta de acuerdo a su nivel de satisfacción, 1 para completamente insatisfecho y 5 para completamente satisfecho.",
"Symbols": "símbolos",
"Sync_success": "el éxito de sincronización",
- "Sync_Users": "Los usuarios de sincronización",
+ "Sync_Users": "Sincronizar Usuarios",
"Tag": "Etiqueta",
"Take_it": "¡Tómalo!",
"Test_Connection": "Conexión de prueba",
"Test_Desktop_Notifications": "Prueba las notificaciones de escritorio",
"Thank_you_exclamation_mark": "¡Gracias!",
- "Thank_you_for_your_feedback": "Gracias por su comentario.",
- "The_application_name_is_required": "Se requiere que el nombre de la aplicación",
+ "Thank_you_for_your_feedback": "Gracias por su comentario",
+ "The_application_name_is_required": "El nombre de la aplicación es requerido",
"The_channel_name_is_required": "El nombre del canal es requerido",
- "The_emails_are_being_sent": "Los correos electrónicos están siendo enviados",
- "The_field_is_required": "El campo %s es obligatorio",
+ "The_emails_are_being_sent": "Los correos electrónicos están siendo enviados.",
+ "The_field_is_required": "El campo %s es requerido.",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "El ajuste de tamaño de las imágenes no funcionara porque no detectamos ImageMagick o GraphicsMagick instalados en su servidor.",
"The_redirectUri_is_required": "El Uri de redireccionamiento es requerido",
- "The_server_will_restart_in_s_seconds": "El servidor se reiniciara en %s segundos",
+ "The_server_will_restart_in_s_seconds": "El servidor se reiniciará en %s segundos",
"The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "La configuración %s está configurado para %s y está accediendo desde %s! ",
"The_user_will_be_removed_from_s": "El usuario sera eliminado de %s",
"The_user_wont_be_able_to_type_in_s": "El usuario no podra introducir datos en %s",
"Theme": "Tema",
"theme-color-content-background-color": "Color de fondo del contenido",
- "theme-color-primary-background-color": "Color primario del fondo ",
- "theme-color-primary-font-color": "Color primario del texto",
- "theme-color-secondary-background-color": "Color secundario del fondo",
- "theme-color-secondary-font-color": "Color secundario del texto",
- "theme-color-tertiary-background-color": "Color de fondo terciario",
- "theme-color-tertiary-font-color": "Color de fuente terciaria",
- "theme-color-link-font-color": "Color del texto de los Hipervinculos",
- "theme-color-info-font-color": "Color del texto de Información",
"theme-color-custom-scrollbar-color": "Barra de desplazamiento de color personalizado",
- "theme-color-status-away": "Color del estado Ausente",
+ "theme-color-info-font-color": "Color del Texto de Información",
+ "theme-color-link-font-color": "Color del Texto de los Enlaces",
+ "theme-color-primary-background-color": "Color de Fondo Primario",
+ "theme-color-primary-font-color": "Color de Texto Primario",
+ "theme-color-secondary-background-color": "Color de Fondo Secundario",
+ "theme-color-secondary-font-color": "Color de Texto Secundario",
+ "theme-color-status-away": "Color de Estado Ausente",
"theme-color-status-busy": "Color de Estado Ocupado",
- "theme-color-status-offline": "Color del estado Desconectado",
- "theme-color-status-online": "Color del estado Conectado",
- "theme-color-unread-notification-color": "Sin leer Notificaciones color",
+ "theme-color-status-offline": "Color de Estado Desconectado",
+ "theme-color-status-online": "Color de Estado Conectado",
+ "theme-color-tertiary-background-color": "Color de Fondo Terciario",
+ "theme-color-tertiary-font-color": "Color de fuente Terciario",
+ "theme-color-unread-notification-color": "Color de Notificaciones No Leídas",
"theme-custom-css": "CSS personalizado",
- "There_are_no_agents_added_to_this_department_yet": "Todavia no hay ningún agente agregado a este departamento.",
+ "There_are_no_agents_added_to_this_department_yet": "Todavía no hay agentes agregados a este departamento.",
"There_are_no_integrations": "No hay integraciones",
- "There_are_no_users_in_this_role": "No hay ningún usuario en este rol",
+ "There_are_no_users_in_this_role": "No hay ningún usuario en este rol.",
"This_conversation_is_already_closed": "La conversación ya está cerrada.",
"This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Este correo electrónico ya se ha utilizado y no se ha verificado. Por favor, cambie su contraseña.",
- "This_is_a_desktop_notification": "Se trata de una notificación de escritorio",
+ "This_is_a_desktop_notification": "Ésto es una notificación de escritorio",
"This_is_a_push_test_messsage": "Este es un mensaje de prueba push",
"This_room_has_been_archived_by__username_": "Esta sala ha sido archivada por __username__",
"This_room_has_been_unarchived_by__username_": "Esta Sala ha sido UNARCHIVED por __username__",
@@ -1127,7 +1266,7 @@
"Title_offline": "título desconectado",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar Rocket.Chat Livechat en su sitio web, copia y pega este código por encima de la última etiqueta body> en su sitio.",
"to_see_more_details_on_how_to_integrate": "ver más detalles sobre cómo integrar.",
- "To_users": "para los usuarios",
+ "To_users": "Para los Usuarios",
"Topic": "Tema",
"Travel_and_Places": "Viajes y Lugares",
"Trigger_removed": "gatillo eliminado",
@@ -1139,24 +1278,23 @@
"Type_your_message": "Escribe tu mensaje",
"Type_your_name": "Escriba su nombre",
"Type_your_new_password": "Escriba la nueva contraseña",
- "UI_DisplayRoles": "Funciones de visualización",
- "UI_Merge_Channels_Groups": "Unir grupos privados con canales",
+ "UI_DisplayRoles": "Mostrar Roles",
+ "UI_Merge_Channels_Groups": "Unir grupos privados con Canales",
"Unarchive": "Desarchivar",
"Unmute_someone_in_room": "De-silenciar a alguien en la sala",
"Unmute_user": "Des-silenciar usuario",
"Unnamed": "Sin nombre",
"Unpin_Message": "Desfijar Mensaje",
- "Unread_Alert": "Alerta de no leídos",
"Unread_Rooms": "Salas sin leer",
"Unread_Rooms_Mode": "Modo Salas sin leer",
"Unstar_Message": "Eliminar Destacado",
"Upload_file_question": "Subir archivo?",
- "Uploading_file": "Subiendo Archivo...",
+ "Uploading_file": "Subiendo archivo...",
"Uptime": "el tiempo de actividad",
"URL": "URL",
- "Use_account_preference": "Use cuenta la preferencia",
+ "Use_account_preference": "Usar la preferencia de cuenta",
"Use_Emojis": "Usar Emojis",
- "Use_Global_Settings": "Usar configuración global",
+ "Use_Global_Settings": "Usar la Configuración Global",
"Use_initials_avatar": "Usar las iniciales de tu nombre de usuario",
"Use_service_avatar": "Usar %s avatar",
"Use_this_username": "Usar este nombre de usuario",
@@ -1175,16 +1313,16 @@
"User_has_been_deactivated": "El usuario ha sido desactivado",
"User_has_been_deleted": "El usuario ha sido eliminado",
"User_has_been_muted_in_s": "El usuario ha sido silenciado en %s",
- "User_has_been_removed_from_s": "El usuario ha sido eliminado en %s",
- "User_Info": "Info de Usuario",
+ "User_has_been_removed_from_s": "El usuario ha sido eliminado de %s",
+ "User_Info": "Información del Usuario",
"User_is_no_longer_an_admin": "El usuario ya no es un administrador",
- "User_is_now_an_admin": "El usuario ahora es un administrador",
+ "User_is_now_an_admin": "El usuario es ahora un administrador",
"User_joined_channel": "Se ha unido al canal.",
"User_joined_channel_female": "Se ha unido al canal",
- "User_joined_channel_male": "Se ha unido al canal",
+ "User_joined_channel_male": "Se ha unido al canal.",
"User_left": "__user_left__ ha salido del canal.",
- "User_left_female": "Ha salido del canal",
- "User_left_male": "Ha salido del canal",
+ "User_left_female": "Ha salido del canal.",
+ "User_left_male": "Ha salido del canal.",
"User_logged_out": "El usuario está desconectado",
"User_management": "Administracion de Usuarios",
"User_muted_by": "__user_muted__ Usuario ha silenciado por __user_by__. ",
@@ -1193,17 +1331,17 @@
"User_or_channel_name": "Nombre de usuario o canal",
"User_removed": "Usuario eliminado",
"User_removed_by": "El usuario __user_removed__ ha sido eliminado por __user_by__ .",
- "User_Settings": "Opciones de usuario",
+ "User_Settings": "Opciones de Usuario",
"User_unmuted_by": "__user_unmuted__ Usuario desactivar el silencio __user_by__. ",
- "User_unmuted_in_room": "Activado sonido del usuario en la sala",
- "User_updated_successfully": "Usuario actualizado exitosamente",
- "Username": "Nombre de usuario",
+ "User_unmuted_in_room": "Usuario silenciado en la sala",
+ "User_updated_successfully": "Usuario actualizado con éxito",
+ "Username": "Nombre de Usuario",
"Username_and_message_must_not_be_empty": "Nombre de usuario y el mensaje no debe estar vacío.",
"Username_cant_be_empty": "El nombre de usuario no puede estar vacío",
"Username_Change_Disabled": "Su administrador de Rocket.Chat ha des habilitado el cambio de nombres de usuario",
"Username_denied_the_OTR_session": "__username__ negó la sesión OTR",
"Username_description": "El nombre de usuario se utiliza para permitir que otros te mencionen en los mensajes.",
- "Username_doesnt_exist": "El usuario `%s` no existe.",
+ "Username_doesnt_exist": "El monbre de usuario `%s` no existe.",
"Username_ended_the_OTR_session": "__username__ terminó la sesión OTR",
"Username_invalid": "%s no es un nombre de usuario válido, usa solo letras, números, puntos y guiones",
"Username_is_already_in_here": "`@%s` ya esta aqui.",
@@ -1216,10 +1354,10 @@
"UTF8_Names_Validation": "Validación de Nombres UTF8",
"UTF8_Names_Validation_Description": "No se permiten caracteres especiales ni espacios. Puede user - _ y . pero no al final de un nombre.",
"Verification_email_sent": "Verificación de correo electrónico enviado",
- "Verified": "verificado",
+ "Verified": "Verificado",
"Version": "Versión",
"Video_Chat_Window": "Video chat",
- "View_All": "Ver todo",
+ "View_All": "Ver Todos los Miembros",
"View_Logs": "Ver Registros",
"View_mode": "Modo de vista",
"View_mode_info": "Esto cambia la cantidad de mensajes espacio ocupan en la pantalla.",
@@ -1244,19 +1382,19 @@
"WebRTC_Servers_Description": "Una lista de servidores STUN y TURN separadas por comas. Nombre de usuario, contraseña y el puerto están permitidos en el formato 'nombre de usuario: contraseña @ paralizante: host: port` o `nombre de usuario: contraseña @ a su vez: host: port`.",
"Welcome": "Bienvenido %s .",
"Welcome_to_the": "Bienvenido a la",
- "Why_do_you_want_to_report_question_mark": "¿Por qué quieres reportar?",
+ "Why_do_you_want_to_report_question_mark": "¿Por qué quiere reportar?",
"will_be_able_to": "será capaz de",
"Would_you_like_to_return_the_inquiry": "Quieres retornar la solicitud?",
"Yes": "Sí",
- "Yes_clear_all": "Si, borrar todos!",
- "Yes_delete_it": "¡Sí, eliminalo!",
- "Yes_hide_it": "Sí, ocultarlo!",
- "Yes_leave_it": "Sí, lo dejas!",
- "Yes_mute_user": "Si, silenciar usuario!",
- "Yes_remove_user": "Si, eliminar usuario!",
+ "Yes_clear_all": "Si, ¡borrar todo!",
+ "Yes_delete_it": "Sí, ¡eliminarlo!",
+ "Yes_hide_it": "Sí, ¡ocultarlo!",
+ "Yes_leave_it": "Sí, ¡déjarlo!",
+ "Yes_mute_user": "Sí, ¡silenciar usuario!",
+ "Yes_remove_user": "Si, ¡eliminar usuario!",
"You": "Tú",
"you_are_in_preview_mode_of": "Estás en modo vista previa del canal #__room_name__ ",
- "You_are_logged_in_as": "Has iniciado sesión como",
+ "You_are_logged_in_as": "Ha iniciado sesión como",
"You_are_not_authorized_to_view_this_page": "No está autorizado para ver esta página.",
"You_can_change_a_different_avatar_too": "Puedes anular el avatar usado para publicar desde esta integración.",
"You_can_search_using_RegExp_eg": "Puede buscar utilizando RegExp. por ejemplo",
@@ -1276,12 +1414,12 @@
"You_should_inform_one_url_at_least": "Debe definir al menos una URL.",
"You_should_name_it_to_easily_manage_your_integrations": "Nombralo para poder administrar fácilmente sus integraciones",
"You_will_not_be_able_to_recover": "No podrás recuperar este mensaje!",
- "You_will_not_be_able_to_recover_file": "Usted no será capaz de recuperar este archivo!",
+ "You_will_not_be_able_to_recover_file": "No será capaz de recuperar este archivo!",
"You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "No recibirá notificaciones por correo electrónico, ya que no ha comprobado su correo electrónico.",
- "Your_email_has_been_queued_for_sending": "Su correo electrónico ha puesto en cola para enviar",
+ "Your_email_has_been_queued_for_sending": "Su correo electrónico se ha puesto en cola para envío",
"Your_entry_has_been_deleted": "Tu entrada ha sido eliminada",
- "Your_file_has_been_deleted": "Tu archivo ha sido eliminado.",
+ "Your_file_has_been_deleted": "Su archivo ha sido eliminado.",
"Your_mail_was_sent_to_s": "Su correo electrónico fue enviado a %s",
- "Your_password_is_wrong": "Su contraseña es incorrecta!",
+ "Your_password_is_wrong": "¡Su contraseña es incorrecta!",
"Your_push_was_sent_to_s_devices": "Su push fue enviado a los dispositivos %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/fa.i18n.json b/packages/rocketchat-i18n/i18n/fa.i18n.json
index 040e0fbb69747..a3d27daec5a58 100644
--- a/packages/rocketchat-i18n/i18n/fa.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fa.i18n.json
@@ -1,188 +1,199 @@
{
- "0_Errors_Only": "0 - خطاها فقط",
+ "#channel": "#کانال",
+ "0_Errors_Only": "0 - فقط خطاها ",
"1_Errors_and_Information": "1 - خطاها و اطلاعات",
- "2_Erros_Information_and_Debug": "2 - Erros، اطلاعات و اشکال زدایی",
+ "2_Erros_Information_and_Debug": "2 - خطاها، اطلاعات و اشکال زدایی",
"403": "ممنوع",
"500": "خطای داخلی سرور",
- "__username__is_no_longer__role__defined_by__user_by_": "_نام کاربری_ است که دیگر __role__، توسط __user_by__",
- "__username__was_set__role__by__user_by_": "_نام کاربری_ __role__ توسط __user_by__ تعیین شد",
- "Access_not_authorized": "دسترسی مجاز",
- "Access_Token_URL": "URL دسترسی به رمز",
- "Accessing_permissions": "دسترسی به مجوز",
+ "@username": "@username",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ دیگر توسط __user_by__ __role__ نمی شود",
+ "__username__was_set__role__by__user_by_": "__username__ توسط __user_by__ به عنوان __role__ تعیین شد",
+ "Accept": "قبول",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "قبول درخواست های ورودی چت آنلاین حتی اگر هیچ عامل آنلاینی وجود نداشته باشد",
+ "Accept_with_no_online_agents": "قبول بدون عاملین آنلاین",
+ "access-mailer": "Access Mailer Screen",
+ "Access_not_authorized": "دسترسی مجاز نمی باشد",
+ "Access_Token_URL": "دسترسی به آدرس توکن",
+ "Accessing_permissions": "مجوزهای دسترسی",
"Account_SID": "حساب SID",
- "Accounts": "حساب ها",
+ "Accounts": "حسابها",
+ "Accounts_AllowAnonymousRead": "اجازه خواندن گمنام",
+ "Accounts_AllowAnonymousWrite": "اجازه نوشتن گمنام",
"Accounts_AllowDeleteOwnAccount": "اجازه به کاربران برای حذف حساب کاربری خود",
- "Accounts_AllowedDomainsList": "فهرست دامنههای مجاز",
- "Accounts_AllowedDomainsList_Description": "جدا شده با کاما از دامنه مجاز",
- "Accounts_AllowEmailChange": "اجازه می دهد ایمیل تغییر",
+ "Accounts_AllowedDomainsList": "فهرست دامنههای مجاز",
+ "Accounts_AllowedDomainsList_Description": "لیست کاما جدا از دامنه های مجاز",
+ "Accounts_AllowEmailChange": "اجازه تغییر ایمیل",
"Accounts_AllowPasswordChange": "اجازه تغییر رمز ورود",
- "Accounts_AllowUserAvatarChange": "کاربر اجازه می دهد آواتار تغییر",
- "Accounts_AllowUsernameChange": "اجازه می دهد نام کاربری تغییر",
- "Accounts_AllowUserProfileChange": "کاربر اجازه می دهد مشخصات تغییر",
+ "Accounts_AllowUserAvatarChange": "اجازه به کاربر برای تغییر آواتار",
+ "Accounts_AllowUsernameChange": "اجازه به کاربر برای تغییر نام کاربری",
+ "Accounts_AllowUserProfileChange": "اجازه به کاربر برای تغییر پروفایل",
"Accounts_AvatarResize": "تغییر اندازه آواتار ها",
- "Accounts_AvatarSize": "آواتار حجم",
- "Accounts_AvatarStorePath": "مسیر آواتار ذخیره سازی",
- "Accounts_AvatarStoreType": "آواتار نوع ذخیره سازی",
- "Accounts_BlockedDomainsList": "مسدود شده فهرست دامنه",
- "Accounts_BlockedDomainsList_Description": "جدا شده با کاما از حوزه های مسدود شده",
- "Accounts_BlockedUsernameList": "مسدود شده نام کاربری",
- "Accounts_BlockedUsernameList_Description": "جدا شده با کاما از نام های کاربری مسدود شده (حروف حساس)",
- "Accounts_denyUnverifiedEmail": "انکار ایمیل تأیید نشده",
+ "Accounts_AvatarSize": "اندازه آواتار ",
+ "Accounts_BlockedDomainsList": "لیست دامنه های مسدود شده",
+ "Accounts_BlockedDomainsList_Description": "لیست کاما جدا از دامنه های مسدود شده",
+ "Accounts_BlockedUsernameList": "لیست نام های کاربری مسدود شده",
+ "Accounts_BlockedUsernameList_Description": "لیست کاما جدا از نام های کاربری مسدود شده (غیر حساس به کوچکی و بزرگی حروف)",
+ "Accounts_denyUnverifiedEmail": "رد ایمیل تأیید نشده",
"Accounts_EmailVerification": "تأیید پست الکترونیکی",
- "Accounts_EmailVerification_Description": "اطمینان حاصل کنید که تنظیمات SMTP صحیح برای استفاده از این ویژگی",
- "Accounts_Enrollment_Email": "ثبت نام پست الکترونیک",
- "Accounts_Enrollment_Email_Default": " خوش آمدید به [Site_Name] برو به [Site_URL] و سعی کنید بهترین راه حل چت منبع باز امروز در دسترس است!
",
- "Accounts_Enrollment_Email_Description": "شما ممکن است [name]، [fname] برای نام کامل کاربر، نام اول یا نام خانوادگی، به ترتیب استفاده کنید، [lname]. ممکن است [email] برای ایمیل کاربر استفاده کنید.",
- "Accounts_Enrollment_Email_Subject_Default": "به استقبال [Site_Name]",
- "Accounts_Iframe_api_method": "روش API",
- "Accounts_Iframe_api_url": "URL API",
+ "Accounts_EmailVerification_Description": "برای استفاده از این ویژگی SMTP باید تنظیم شده باشد",
+ "Accounts_Enrollment_Email": "ثبت نام با ایمیل",
+ "Accounts_Enrollment_Email_Default": " خوش آمدید به [Site_Name] به [Site_URL] بروید و بهترین راه حل چت منبع باز را که امروزه در دسترس است امتحان کنید!
",
+ "Accounts_Enrollment_Email_Description": "می توانید از این مکان نماها استفاده کنید: [name], [fname], [lname] به ترتیب برای نام کامل، نام کوچک و نام بزرگ کاربر. [email] برای ایمیل کاربر. [Site_Name] و [Site_URL] به ترتیب برای نام و آدرس برنامه.",
+ "Accounts_Enrollment_Email_Subject_Default": "به [Site_Name] خوش آمدید",
+ "Accounts_Iframe_api_method": "متد API",
+ "Accounts_Iframe_api_url": "آدرس API",
"Accounts_iframe_enabled": "فعال",
- "Accounts_iframe_url": "از iframe آدرس",
- "Accounts_LoginExpiration": "انقضا ورود در روز",
+ "Accounts_iframe_url": "آدرس Iframe",
+ "Accounts_LoginExpiration": "انقضای ورود به روز",
"Accounts_ManuallyApproveNewUsers": "تأیید دستی کاربران جدید",
- "Accounts_OAuth_Custom_Authorize_Path": "اجازه راه",
+ "Accounts_OAuth_Custom_Authorize_Path": "مسیر احراز هویت",
"Accounts_OAuth_Custom_Button_Color": "رنگ دکمه",
- "Accounts_OAuth_Custom_Button_Label_Color": "رنگ دکمه متن",
+ "Accounts_OAuth_Custom_Button_Label_Color": "رنگ متن دکمه",
"Accounts_OAuth_Custom_Button_Label_Text": "متن دکمه",
- "Accounts_OAuth_Custom_Enable": "قادر ساختن",
+ "Accounts_OAuth_Custom_Enable": "فعال",
"Accounts_OAuth_Custom_id": "شناسه",
"Accounts_OAuth_Custom_Identity_Path": "مسیر هویت",
"Accounts_OAuth_Custom_Login_Style": "سبک ورود",
- "Accounts_OAuth_Custom_Secret": "راز",
- "Accounts_OAuth_Custom_Token_Path": "مسیر نشانه رمز",
- "Accounts_OAuth_Custom_Token_Sent_Via": "رمز ارسال شده از طریق",
- "Accounts_OAuth_Facebook": "ورود به فیس بوک",
- "Accounts_OAuth_Facebook_callback_url": "URL فیس بوک مخاطبین",
- "Accounts_OAuth_Facebook_id": "شناسه فیس بوک نرم افزار",
- "Accounts_OAuth_Facebook_secret": "فیس بوک راز",
- "Accounts_OAuth_Github": "OAuth فعال",
- "Accounts_OAuth_Github_callback_url": "URL گیتهاب مخاطبین",
- "Accounts_OAuth_GitHub_Enterprise": "OAuth فعال",
- "Accounts_OAuth_GitHub_Enterprise_callback_url": "URL گیتهاب شرکت نوع مخاطبین",
+ "Accounts_OAuth_Custom_Secret": "رمز",
+ "Accounts_OAuth_Custom_Token_Path": "مسیر توکن",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "توکن فرستاده شد با",
+ "Accounts_OAuth_Facebook": "صفحه ورود فیس بوک",
+ "Accounts_OAuth_Facebook_callback_url": "آدرس Callback فیسبوک",
+ "Accounts_OAuth_Facebook_id": "شناسه برنامه فیسبوک",
+ "Accounts_OAuth_Facebook_secret": "رمز فیسبوک",
+ "Accounts_OAuth_Github": "OAuth فعال است",
+ "Accounts_OAuth_Github_callback_url": "آدرس Callback گیت هاب",
+ "Accounts_OAuth_GitHub_Enterprise": "OAuth فعال است",
+ "Accounts_OAuth_GitHub_Enterprise_callback_url": "آدرس Callback گیت هاب تجاری",
"Accounts_OAuth_GitHub_Enterprise_id": "شناسه مشتری",
- "Accounts_OAuth_GitHub_Enterprise_secret": "مشتری راز",
+ "Accounts_OAuth_GitHub_Enterprise_secret": "رمز مشتری",
"Accounts_OAuth_Github_id": "شناسه مشتری",
- "Accounts_OAuth_Github_secret": "مشتری راز",
- "Accounts_OAuth_Gitlab": "OAuth فعال",
- "Accounts_OAuth_Gitlab_callback_url": "URL GitLab مخاطبین",
- "Accounts_OAuth_Gitlab_id": "GitLab ها",
- "Accounts_OAuth_Gitlab_secret": "مشتری راز",
- "Accounts_OAuth_Google": "ورود به سیستم Google",
- "Accounts_OAuth_Google_callback_url": "URL گوگل مخاطبین",
- "Accounts_OAuth_Google_id": "گوگل ID",
- "Accounts_OAuth_Google_secret": "گوگل راز",
- "Accounts_OAuth_Linkedin": "لینک ورود",
- "Accounts_OAuth_Linkedin_callback_url": "URL لینک مخاطبین",
- "Accounts_OAuth_Linkedin_id": "لینک ها",
- "Accounts_OAuth_Linkedin_secret": "ارتباط با راز",
- "Accounts_OAuth_Meteor": "شهاب ورود",
- "Accounts_OAuth_Meteor_callback_url": "URL شهاب مخاطبین",
- "Accounts_OAuth_Meteor_id": "شهاب ها",
- "Accounts_OAuth_Meteor_secret": "شهاب راز",
- "Accounts_OAuth_Twitter": "توییتر ورود",
- "Accounts_OAuth_Twitter_callback_url": "URL توییتر مخاطبین",
- "Accounts_OAuth_Twitter_id": "توییتر ID",
- "Accounts_OAuth_Twitter_secret": "توییتر راز",
- "Accounts_OAuth_Wordpress": "وردپرس ورود",
- "Accounts_OAuth_Wordpress_callback_url": "URL وردپرس مخاطبین",
- "Accounts_OAuth_Wordpress_id": "کد وردپرس",
- "Accounts_OAuth_Wordpress_secret": "وردپرس راز",
+ "Accounts_OAuth_Github_secret": "رمز مشتری",
+ "Accounts_OAuth_Gitlab": "OAuth فعال است",
+ "Accounts_OAuth_Gitlab_callback_url": "آدرس Callback گیت هاب",
+ "Accounts_OAuth_Gitlab_id": "شناسه GitLab",
+ "Accounts_OAuth_Gitlab_secret": "رمز مشتری",
+ "Accounts_OAuth_Google": "صفحه لاگین گوگل",
+ "Accounts_OAuth_Google_callback_url": "آدرس Callback گوگل",
+ "Accounts_OAuth_Google_id": "شناسه گوگل",
+ "Accounts_OAuth_Google_secret": "رمز گوگل",
+ "Accounts_OAuth_Linkedin": "صفحه ورود Linkedin",
+ "Accounts_OAuth_Linkedin_callback_url": "آدرس Callback Linkedin",
+ "Accounts_OAuth_Linkedin_id": "شناسه Linkedin",
+ "Accounts_OAuth_Linkedin_secret": "رمز Linkedin",
+ "Accounts_OAuth_Meteor": "صفحه لاگین Meteor",
+ "Accounts_OAuth_Meteor_callback_url": "آدرس Callback Meteor",
+ "Accounts_OAuth_Meteor_id": "شناسه Meteor",
+ "Accounts_OAuth_Meteor_secret": "رمز Meteor",
+ "Accounts_OAuth_Twitter": "صفحه ورود توییتر",
+ "Accounts_OAuth_Twitter_callback_url": "آدرس Callback توییتر",
+ "Accounts_OAuth_Twitter_id": "شناسه توییتر",
+ "Accounts_OAuth_Twitter_secret": "رمز توییتر",
+ "Accounts_OAuth_Wordpress": "لاگین وردپرس",
+ "Accounts_OAuth_Wordpress_callback_url": "آدرس Callback وردپرس",
+ "Accounts_OAuth_Wordpress_id": "شناسه وردپرس",
+ "Accounts_OAuth_Wordpress_secret": "رمز وردپرس",
"Accounts_PasswordReset": "تنظیم مجدد رمز عبور",
- "Accounts_Registration_AuthenticationServices_Enabled": "ثبت نام با خدمات احراز هویت",
+ "Accounts_Registration_AuthenticationServices_Enabled": "ثبت نام با خدمات تأیید هویت",
"Accounts_RegistrationForm": "فرم ثبت نام",
- "Accounts_RegistrationForm_Disabled": "معلول",
- "Accounts_RegistrationForm_LinkReplacementText": "فرم ثبت نام لینک جایگزین متن",
+ "Accounts_RegistrationForm_Disabled": "غیر فعال",
+ "Accounts_RegistrationForm_LinkReplacementText": "متن جایگزین لینک فرم ثبت نام",
"Accounts_RegistrationForm_Public": "عمومی",
- "Accounts_RegistrationForm_Secret_URL": "URL راز",
- "Accounts_RegistrationForm_SecretURL": "فرم ثبت نام راز URL",
- "Accounts_RegistrationForm_SecretURL_Description": "شما باید یک رشته تصادفی است که به URL ثبت نام خود را اضافه فراهم می کند. به عنوان مثال: https://demo.rocket.chat/register/[secret_hash]",
- "Accounts_RequireNameForSignUp": "نیاز به نام برای ثبت نام",
- "Accounts_ShowFormLogin": "ورود مبتنی بر فرم نمایش",
- "Accounts_UseDefaultBlockedDomainsList": "استفاده از پیش فرض مسدود شده فهرست دامنه",
- "Accounts_UseDNSDomainCheck": "استفاده از چک DNS دامنه",
- "Accounts_UserAddedEmail_Default": " خوش آمدید به [Site_Name] برو به [Site_URL] و سعی کنید بهترین راه حل چت منبع باز امروز در دسترس است!
[email] و رمز عبور: [password] شما ممکن است با استفاده از ایمیل خود وارد شوید. شما ممکن است لازم باشد به آن پس از اولین ورود خود را تغییر دهید.",
- "Accounts_UserAddedEmail_Description": "شما ممکن است متغیرهایی زیر استفاده کنید:
[name]، [fname]، [lname] برای نام کاربر کامل، نام اول یا نام خانوادگی، به ترتیب. [email] برای ایمیل کاربر. [password] برای رمز عبور کاربر است. [Site_Name] و [Site_URL] برای نام نرم افزار و URL است. ",
- "Accounts_UserAddedEmailSubject_Default": "شما باید به آن اضافه شده است [Site_Name]",
+ "Accounts_RegistrationForm_Secret_URL": "آدرس مخفی",
+ "Accounts_RegistrationForm_SecretURL": "آدرس مخفی فرم ثبت نام",
+ "Accounts_RegistrationForm_SecretURL_Description": "باید رشته ای اتفاقی را برای اضافه شدن به آدرس ثبت نام تعیین کنید. برای مثال: https://open.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "برای ثبت نام به نام نیاز است",
+ "Accounts_ShowFormLogin": "نمایش فرم لاگین",
+ "Accounts_UseDefaultBlockedDomainsList": "استفاده از لیست پیش فرض دامنه های مسدود شده",
+ "Accounts_UseDNSDomainCheck": "استفاده از امکان بررسی دامنه DNS",
+ "Accounts_UserAddedEmail_Default": " خوش آمدید به [Site_Name] برو به [Site_URL] و سعی کنید بهترین راه حل چت منبع باز امروز در دسترس است!
[email] و رمز عبور: [password] شما ممکن است با استفاده از ایمیل خود وارد شوید. شما ممکن است لازم باشد به آن پس از اولین ورود خود را تغییر دهید.",
+ "Accounts_UserAddedEmail_Description": "شما ممکن است متغیرهایی زیر استفاده کنید:
[name]، [fname]، [lname] برای نام کاربر کامل، نام اول یا نام خانوادگی، به ترتیب. [email] برای ایمیل کاربر. [password] برای رمز عبور کاربر است. [Site_Name] و [Site_URL] برای نام نرم افزار و URL است. ",
+ "Accounts_UserAddedEmailSubject_Default": "شما به [Site_Name] اضافه شده اید",
"Activate": "فعال کردن",
"Activity": "فعالیت",
"Add": "اضافه کردن",
"Add_agent": "اضافه کردن عامل",
- "Add_custom_oauth": "اضافه کردن OAuth حفظ سفارشی",
- "Add_manager": "اضافه کردن بدهید",
+ "Add_custom_oauth": "اضافه کردن oauth سفارشی",
+ "Add_files_from": "بارگذاری فایل از",
+ "Add_manager": "اضافه کردن مدیر",
"Add_user": "اضافه کردن کاربر",
"Add_User": "اضافه کردن کاربر",
"Add_users": "اضافه کردن کاربران",
- "Adding_OAuth_Services": "اضافه کردن خدمات OAuth تأیید",
- "Adding_permission": "اضافه کردن اجازه",
- "Adding_user": "کاربران اضافه کردن",
- "Additional_emails": "اضافی ایمیل",
+ "Adding_OAuth_Services": "اضافه کردن سرویس های OAuth",
+ "Adding_permission": "اضافه کردن مجوز",
+ "Adding_user": "اضافه کردن کاربر",
+ "Additional_emails": "ایمیل های اضافی",
"Additional_Feedback": "بازخورد اضافی",
"Administration": "مدیریت",
- "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "پس از احراز هویت از OAuth2، کاربران خواهد شد به این URL هدایت",
- "Agent_added": "عامل اضافه شده",
- "Agent_removed": "عامل حذف",
+ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "پس از تأیید هویت OAuth2 کاربران به این آدرس هدایت خواهند شد",
+ "Agent_added": "عامل اضافه شده است",
+ "Agent_removed": "عامل حذف شده است",
"Alias": "نام مستعار",
"All": "همه",
- "All_channels": "تمام کانال های",
- "All_logs": "تمام سیاهههای",
- "All_messages": "همه پیام",
- "Allow_Invalid_SelfSigned_Certs": "اجازه می دهد نامعتبر خود امضا Certs ارسل",
- "Allow_Invalid_SelfSigned_Certs_Description": "اجازه می دهد به گواهینامه SSL نامعتبر و خود امضا برای اعتبار سنجی لینک و پیش نمایش.",
+ "All_channels": "همه کانال ها",
+ "All_logs": "همه لاگ ها",
+ "All_messages": "همه پیام ها",
+ "All_users_in_the_channel_can_write_new_messages": "همه اعضا می توانند پیام جدید بنویسند",
+ "Allow_Invalid_SelfSigned_Certs": "گواهینامه های غیر معتبر مجازند",
+ "Allow_Invalid_SelfSigned_Certs_Description": "گواهینامه های غیر معتبر برای پیش نمایش ها و تأیید لینک ها مجازند.",
"Analytics_features_enabled": "ویژگی های فعال",
- "Analytics_features_messages_Description": "آهنگ حوادث سفارشی مربوط به اعمال یک کاربر را در پیام.",
+ "Analytics_features_messages_Description": "آهنگ حوادث سفارشی مربوط به اعمال یک کاربر روی پیام ها.",
"Analytics_features_rooms_Description": "آهنگ حوادث سفارشی مربوط به اقدامات در یک کانال یا گروه (ایجاد، ترک، حذف).",
"Analytics_features_users_Description": "آهنگ حوادث سفارشی مربوط به اقدامات مربوط به کاربران (بار تنظیم مجدد رمز عبور، تغییر تصویر پروفایل، و غیره).",
"and": "و",
- "And_more": "و __length بیشتر __",
+ "And_more": "و __length__ بیشتر",
"Animals_and_Nature": "حیوانات و طبیعت",
"API": "API",
"API_Analytics": "تجزیه و تحلیل ترافیک",
- "API_Embed": "قراردادن",
+ "API_Embed": "قرار دادن پیش نمایش لینک ها",
"API_EmbedDisabledFor": "قراردادن غیر فعال کردن برای کاربران",
- "API_EmbedDisabledFor_Description": "فهرست کاما جدا از نام های کاربری",
- "API_EmbedIgnoredHosts": "میزبان نادیده جاسازی",
- "API_EmbedIgnoredHosts_Description": "کاما از هم جدا لیستی از میزبان و یا آدرس CIDR، به عنوان مثال. localhost را، 127.0.0.1، 10.0.0.0/8، 172.16.0.0/12، 192.168.0.0/16",
- "API_EmbedSafePorts": "بنادر امن",
- "API_EmbedSafePorts_Description": "کاما از هم جدا لیستی از پورت های مجاز برای پیش نمایش.",
+ "API_EmbedDisabledFor_Description": "لیست کاما جدا از کاربران فاقد امکان پیش نمایش لینک ها",
+ "API_EmbedIgnoredHosts": "تعبیه کردن هاست های نادیده گرفته شده",
+ "API_EmbedIgnoredHosts_Description": "لیست کاما جدا از میزبان و یا آدرس CIDR، به عنوان مثال. localhost را، 127.0.0.1، 10.0.0.0/8، 172.16.0.0/12، 192.168.0.0/16",
+ "API_EmbedSafePorts": "پورت های امن",
+ "API_EmbedSafePorts_Description": "لیست کاما جدا از پورت های مجاز برای پیش نمایش.",
"API_GitHub_Enterprise_URL": "URL سرور",
- "API_GitHub_Enterprise_URL_Description": "به عنوان مثال: http://domain.com (به جز علامت)",
+ "API_GitHub_Enterprise_URL_Description": "مثال: http://domain.com (بدون اسلش آخری)",
"API_Gitlab_URL": "URL GitLab",
- "API_Token": "API رمز",
- "API_User_Limit": "محدود کاربران برای اضافه کردن همه کاربران به کانال",
+ "API_Token": "توکن API",
+ "API_User_Limit": "محدودیت کاربر برای اضافه کردن همه کاربران به کانال",
"API_Wordpress_URL": "URL وردپرس",
- "Apiai_Key": "Api.ai کلیدی",
- "Apiai_Language": "Api.ai زبان",
+ "Apiai_Key": "کلید Api.ai",
+ "Apiai_Language": "زبان Api.ai",
"Appearance": "ظاهر",
"Application_added": "نرم افزار اضافه شده",
"Application_Name": "نام نرم افزار",
- "Application_updated": "نرم افزار به روز",
- "Apply_and_refresh_all_clients": "درخواست و تازه کردن تمام مشتریان",
+ "Application_updated": "نرم افزار به روز رسانی شد",
+ "Apply_and_refresh_all_clients": "اعمال کن و تمامی کاربران را رفرش کن",
"Archive": "بایگانی",
- "are_also_typing": "همچنین تایپ",
+ "are_also_typing": "همچنین در حال تایپ کردن",
"are_typing": "در حال تایپ کردن",
- "Are_you_sure": "شما مطمئن هستید؟",
- "Are_you_sure_you_want_to_delete_your_account": "آیا شما مطمئن هستید که میخواهید حساب خود را حذف کنید؟",
+ "Are_you_sure": "آیا مطمئن هستید؟",
+ "Are_you_sure_you_want_to_delete_your_account": "آیا شما مطمئن هستید که می خواهید حساب کاربری خود را حذف کنید؟",
"at": "در",
- "Auth_Token": "تایید رمز",
+ "Audio_message": "پیام صوتی",
+ "Audio_Notifications_Default_Alert": "هشدار پیشفرض اعلان های صوتی",
+ "Audio_Notifications_Value": "پیام پیشفرض اعلان صوتی",
+ "Auth_Token": "Auth Token",
"Author": "نویسنده",
- "Authorization_URL": "URL مجوز",
- "Authorize": "اجازه دادن",
- "Auto_Load_Images": "بار خودکار تصاویر",
- "AutoLinker_Email": "AutoLinker ایمیل",
- "AutoLinker_Phone": "AutoLinker تلفن",
- "AutoLinker_Phone_Description": "به صورت خودکار برای شماره تلفن در ارتباط است. به عنوان مثال `(123) 456-7890`",
- "AutoLinker_StripPrefix": "AutoLinker نوار پیشوند",
- "AutoLinker_StripPrefix_Description": "نمایش کوتاه. به عنوان مثال https://rocket.chat => rocket.chat",
- "AutoLinker_Urls_Scheme": "AutoLinker طرح: // URL ها",
- "AutoLinker_Urls_TLD": "آدرس ها AutoLinker TLD",
- "AutoLinker_Urls_www": "آدرس ها AutoLinker www از",
- "AutoLinker_UrlsRegExp": "AutoLinker URL عبارت منظم",
+ "Authorization_URL": "آدرس احراز هویت",
+ "Authorize": "مجوز دادن",
+ "Auto_Load_Images": "تصاویر با قابلیت بارگیری خودکار",
+ "AutoLinker_Email": "ایمیل AutoLinker",
+ "AutoLinker_Phone": "تلفن AutoLinker",
+ "AutoLinker_Phone_Description": "به صورت خودکار برای شماره های تلفن لینک شده است. مثال: `(123) 456-7890`",
+ "AutoLinker_StripPrefix": "نوار پیشوند AutoLinker",
+ "AutoLinker_StripPrefix_Description": "نمایش کوتاه. مثال: https://rocket.chat => rocket.chat",
+ "AutoLinker_Urls_Scheme": "آدرس های AutoLinker Scheme:// ",
+ "AutoLinker_Urls_TLD": "آدرس های AutoLinker TLD",
+ "AutoLinker_Urls_www": "آدرس های AutoLinker www",
+ "AutoLinker_UrlsRegExp": "AutoLinker URL Regular Expression",
"Available": "در دسترس",
- "Available_agents": "عوامل موجود",
+ "Available_agents": "عامل های موجود",
"Avatar": "آواتار",
- "Avatar_changed_successfully": "آواتار موفقیت تغییر",
- "Avatar_URL": "URL آواتار",
- "Avatar_url_invalid_or_error": "URL ارائه نامعتبر است و یا در دسترس نیست. لطفا دوباره امتحان کنید، اما با یک آدرس متفاوت است.",
+ "Avatar_changed_successfully": "آواتار با موفقیت تعویض شد",
+ "Avatar_URL": "آدرس آواتار",
+ "Avatar_url_invalid_or_error": "آدرس وارد شده قابل دسترسی نیست یا غلط است. لطفا با آدرس دیگری امتحان کنید.",
"away": "دور",
"Away": "دور",
"away_female": "دور",
@@ -190,12 +201,13 @@
"away_male": "دور",
"Away_male": "دور",
"Back": "بازگشت",
- "Back_to_applications": "بازگشت به برنامه های کاربردی",
- "Back_to_integrations": "برگشت به یکپارچگی",
+ "Back_to_applications": "بازگشت به برنامه ها",
+ "Back_to_integrations": "بازگشت به یکپارچگی ها",
"Back_to_login": "بازگشت به صفحه ورود",
- "Back_to_permissions": "برگشت به مجوز",
- "Body": "بدن",
- "bold": "جسور",
+ "Back_to_permissions": "بازگشت به مجوزها",
+ "Block_User": "مسدود کردن کاربر",
+ "Body": "محتوا",
+ "bold": "برجسته",
"Branch": "شاخه",
"busy": "مشغول",
"Busy": "مشغول",
@@ -204,167 +216,179 @@
"busy_male": "مشغول",
"Busy_male": "مشغول",
"by": "توسط",
- "Cancel": "لغو کردن",
- "Cancel_message_input": "لغو کردن",
- "Cannot_invite_users_to_direct_rooms": "می تواند کاربران را به طور مستقیم اتاق دعوت",
- "CDN_PREFIX": "CDN پیشوند",
- "Certificates_and_Keys": "گواهینامه ها و کلید",
- "Changing_email": "ایمیل تغییر",
+ "Cancel": "لغو",
+ "Cancel_message_input": "لغو",
+ "Cannot_invite_users_to_direct_rooms": "امکان دعوت کاربران به تماس های مستقیم وجود ندارد",
+ "CDN_PREFIX": "پیشوند CDN",
+ "Certificates_and_Keys": "گواهینامه ها و کلیدها",
+ "Changing_email": "تغییر ایمیل",
"Channel": "کانال",
- "Channel_already_exist": "کانال '#٪ s' را قبل وجود دارد.",
- "Channel_already_Unarchived": "کانال با نام `#٪ s` در حال حاضر در دولت از بایگانی خارج شد",
- "Channel_Archived": "کانال با نام `#٪ s` با موفقیت بایگانی شده است",
+ "Channel_already_exist": "کانال `#%s` از قبل وجود دارد.",
+ "Channel_already_Unarchived": "کانال `#%s` در حال حاضر آرشیو نشده است",
+ "Channel_Archived": "کانال `#%s` با موفقیت آرشیو شد",
"Channel_doesnt_exist": "کانال `# %s` وجود ندارد.",
- "Channel_Unarchived": "کانال با نام `#٪ s` با موفقیت از بایگانی خارج شده",
- "Channels": "کانال",
+ "Channel_name": "نام کانال",
+ "Channel_Name_Placeholder": "لطفا نام کانال را وارد کنید...",
+ "Channel_Unarchived": "کانال `#%s` با موفقیت از آرشیو خارج شد",
+ "Channels": "کانال ها",
+ "Channels_are_where_your_team_communicate": "کانال جایی است که افراد با یکدیگر تعامل می کنند",
"Channels_list": "لیست کانال های عمومی",
"Chat_button": "دکمه چت",
- "Chat_closed": "چت بسته",
- "Chat_closed_successfully": "چت با موفقیت بسته",
+ "Chat_closed": "چت بسته است",
+ "Chat_closed_successfully": "چت با موفقیت بسته شد",
"Chat_window": "پنجره چت",
"Chatops_Enabled": "فعال کردن Chatops",
- "Chatops_Title": "Chatops پنل",
- "Chatops_Username": "Chatops نام کاربری",
+ "Chatops_Title": "پنل Chatops",
+ "Chatops_Username": "نام کاربری Chatops",
"Choose_a_room": "انتخاب یک اتاق",
- "Choose_messages": "انتخاب پیام",
+ "Choose_messages": "انتخاب پیام ها",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "نام مستعار که قبل از نام کاربری در پیام ظاهر خواهد شد را انتخاب نمایید.",
- "Choose_the_username_that_this_integration_will_post_as": "نام کاربری که این ادغام به عنوان پست را انتخاب کنید.",
- "Clear_all_unreads_question": "پاک کردن تمام unreads؟",
+ "Choose_the_username_that_this_integration_will_post_as": "نام کاربری را که این یکپارچه سازی به عنوان آن ارسال خواهد شد انتخاب کنید.",
+ "Clear_all_unreads_question": "پاک کردن همه ناخوانده ها؟",
"Click_here": "اینجا کلیک کنید",
+ "Click_to_join": "برای پیوستن کلیک کنید!",
"Client_ID": "شناسه مشتری",
- "Client_Secret": "مشتری راز",
- "Clients_will_refresh_in_a_few_seconds": "مشتریان در چند ثانیه تازه کردن",
+ "Client_Secret": "رمز مشتری",
+ "Clients_will_refresh_in_a_few_seconds": "مشتریان طی چند ثانیه رفرش خواهند شد",
"close": "بستن",
"Closed": "بسته",
- "Closing_chat": "چت بسته شدن",
- "Collapse_Embedded_Media_By_Default": "سقوط رسانه های جاسازی شده به طور پیش فرض",
+ "Closing_chat": "در حال بستن چت",
+ "Collapse_Embedded_Media_By_Default": "قبض رسانه های جاسازی شده به طور پیش فرض",
"Color": "رنگ",
"Commands": "دستورات",
"Compact": "جمع و جور",
- "Confirm_password": "تکرار رمز عبور خود را",
- "Conversation": "گفتگو",
- "Conversation_closed": "مکالمات بسته: __comment__.",
- "Convert_Ascii_Emojis": "تبدیل ASCII به از Emoji",
- "Copied": "کپی",
- "Copy": "نسخه",
- "Copy_to_clipboard": "کپی به کلیپ بورد",
- "COPY_TO_CLIPBOARD": "کپی به کلیپ بورد",
+ "Confirm_password": "رمز عبور خود را تأیید کنید",
+ "Conversation": "مکالمه",
+ "Conversation_closed": "مکالمه بسته: __comment__.",
+ "Convert_Ascii_Emojis": "تبدیل ASCII به Emoji",
+ "Copied": "کپی شد",
+ "Copy": "کپی",
+ "Copy_to_clipboard": "کپی در کلیپبورد",
+ "COPY_TO_CLIPBOARD": "کپی در کلیپبورد",
"Count": "شمردن",
- "Cozy": "گرم و نرم",
- "Create": "ايجاد كردن",
+ "Cozy": "Cozy",
+ "Create": "ايجاد",
"Create_A_New_Channel": "ایجاد یک کانال جدید",
- "Create_new": "ایجاد جدید",
+ "Create_new": "ایجاد (جدید)",
"Created_at": "ایجاد شده در",
"Created_at_s_by_s": "ایجاد در %s توسط %s ",
- "Current_Chats": "چت در حال حاضر",
+ "Current_Chats": "چت های کنونی",
"Custom": "سفارشی",
- "Custom_Fields": "موضوعات سفارشی",
- "Custom_oauth_helper": "هنگامی که راه اندازی ارائه دهنده OAuth حفظ خود را، شما باید به اطلاع یک URL مخاطبین. استفاده کنید %s را .",
- "Custom_oauth_unique_name": "نام منحصر به فرد از OAuth سفارشی",
- "Custom_Script_Logged_In": "سفارشی اسکریپت برای کاربران وارد شده",
- "Custom_Script_Logged_Out": "سفارشی اسکریپت برای کاربران سیستم خارج",
+ "Custom_Fields": "فیلدهای سفارشی",
+ "Custom_oauth_helper": ".در حال تنظیم OAuth Provider شما، شما باید یک آدرس Callback بدهید. با %s ",
+ "Custom_oauth_unique_name": "نام یکتای oauth سفارشی",
+ "Custom_Script_Logged_In": "اسکریپت سفارشی برای کاربران وارد شده",
+ "Custom_Script_Logged_Out": "اسکریپت سفارشی برای کاربران خارج شده",
"Dashboard": "داشبورد",
"Date": "تاریخ",
"days": "روزها",
- "DB_Migration": "مهاجرت پایگاه داده",
- "DB_Migration_Date": "پایگاه تاریخ مهاجرت",
+ "DB_Migration": "انتقال پایگاه داده",
+ "DB_Migration_Date": "تاریخ انتقال پایگاه داده",
"Deactivate": "از کار انداختن",
- "Default": "به طور پیش فرض",
+ "Default": "پیش فرض",
"Delete": "حذف کردن",
"Delete_message": "حذف پیام",
"Delete_my_account": "حذف حساب کاربری من",
- "Delete_Room_Warning": "حذف یک اتاق تمام پیغام های ارسال شده در داخل اتاق را حذف کنید. این قابل بازگشت نیست.",
- "Delete_User_Warning": "حذف یک کاربر تمام پیام ها از آن کاربران نیز حذف کنید. این قابل بازگشت نیست.",
- "Deleted": "حذف شده!",
- "Department_removed": "وزارت حذف",
- "Departments": "گروه ها",
- "Deployment_ID": "ID استقرار",
+ "Delete_Room_Warning": "حذف یک اتاق تمام پیغام های ارسال شده در داخل اتاق را حذف می کند. این کار قابل بازگشت نیست.",
+ "Delete_User_Warning": "حذف یک کاربر تمام پیام های ارسال شده آن کاربر را حذف می کند. این کار قابل بازگشت نیست.",
+ "Deleted": "حذف شد!",
+ "Department_removed": "بخش حذف شد",
+ "Departments": "بخش ها",
+ "Deployment_ID": "شناسه بخش",
"Description": "شرح",
"Desktop": "دسکتاپ",
- "Desktop_Notification_Test": "تست هشدار از طریق دسکتاپ",
- "Desktop_Notifications": "اعلان های دسک تاپ",
- "Desktop_Notifications_Disabled": "اعلان های دسک تاپ غیر فعال هستند. تغییر تنظیمات مرورگر خود را اگر شما نیاز به اطلاعیه را فعال کنید.",
- "Desktop_Notifications_Duration": "اطلاعیه مدت",
- "Desktop_Notifications_Duration_Description": "ثانیه به نمایش اطلاع رسانی دسکتاپ. این ممکن است مرکز اطلاع رسانی OS X را تحت تاثیر قرار. را وارد کنید 0 برای استفاده از تنظیمات پیش فرض مرورگر و سیستم عامل مرکز X هشدار از طریق تاثیر نمی گذارد.",
- "Desktop_Notifications_Enabled": "اعلانهای دسکتاپ را فعال کنید",
- "Direct_message_someone": "کسی پیام مستقیم",
- "Direct_Messages": "پیام مستقیم",
- "Display_offline_form": "فرم آنلاین ها",
+ "Desktop_Notification_Test": "تست هشدار دسکتاپ",
+ "Desktop_Notifications": "هشدارهای دسکتاپ",
+ "Desktop_Notifications_Default_Alert": "هشدار پیشفرض اعلان های دسکتاپ",
+ "Desktop_Notifications_Disabled": "هشدارهای دسکتاپ غیر فعال هستند. در صورت تمایل به فعال سازی تنظیمات مرورگر خود را تغییر دهید.",
+ "Desktop_Notifications_Duration": "مدت زمان هشدارهای دسکتاپ",
+ "Desktop_Notifications_Duration_Description": "ثانیه برای نمایش هشدارهای دسکتاپ. ممکن است روی تنظیمات OS X تأثیر بگذارد. برای اعمال تنظیمات پیشفرض مرورگر، صفر (۰) وارد کنید.",
+ "Desktop_Notifications_Enabled": "هشدارهای دسکتاپ فعال شده است",
+ "Direct_message_someone": "پیام مستقیم به دیگران",
+ "Direct_Messages": "پیام های مستقیم",
+ "Disable_Notifications": "غیر فعال کردن اعلانات",
+ "Disable_two-factor_authentication": "غیر فعال کردن تایید هویت دومرحله ای",
+ "Display_offline_form": "نمایش فرم آفلاین",
"Displays_action_text": "نمایش متن عمل",
- "Do_you_want_to_change_to_s_question": "آیا شما می خواهید به تغییر به %s؟ ",
+ "Do_you_want_to_change_to_s_question": "آیا میخواهید به %s تغییر دهید؟",
"Domain": "دامنه",
- "Domains": "دامنه",
- "Drop_to_upload_file": "رها کردن برای آپلود فایل",
- "Dry_run": "تمرین جنگی",
- "Dry_run_description": "تنها ارسال یک ایمیل به آدرس همان است که در از. ایمیل باید به یک کاربر معتبر تعلق دارند.",
- "Duplicate_archived_channel_name": "آرشیو کانال با نام » %s 'را وجود دارد",
- "Duplicate_archived_private_group_name": "شخصی گروه بایگانی با نام » %s 'را وجود دارد",
- "Duplicate_channel_name": "یک کانال با نام »٪ s 'را وجود دارد",
- "Duplicate_private_group_name": "یک گروه خصوصی با نام « %s 'را وجود دارد",
+ "Domains": "دامنه ها",
+ "Drop_to_upload_file": "برای آپلود رها کنید",
+ "Dry_run": "اجرای آزمایشی",
+ "Dry_run_description": "تنها یک ایمیل به آدرس موجود در فرم ارسال خواهد شد. ایمیل باید متعلق به یک کاربر معتبر باشد.",
+ "Duplicate_archived_channel_name": "یک کانال آرشیو شده با نام `#%s` وجود دارد",
+ "Duplicate_archived_private_group_name": "یک گروه خصوصی آرشیو شده با نام '%s' وجود دارد",
+ "Duplicate_channel_name": "یک کانال با نام '%s' وجود دارد",
+ "Duplicate_private_group_name": "گروهی خصوصی با نام '%s' وجود دارد",
+ "Duration": "مدت زمان",
"Edit": "ویرایش",
- "Edit_Custom_Field": "ویرایش سفارشی درست",
- "Edit_Department": "وزارت ویرایش",
+ "Edit_Custom_Field": "ویرایش فیلد سفارشی",
+ "Edit_Department": "ویرایش بخش",
"edited": "ویرایش شده",
- "Editing_room": "اتاق تدوین",
- "Editing_user": "کاربران در حال ویرایش",
- "Email": "پست الکترونیک",
- "Email_address_to_send_offline_messages": "آدرس ایمیل برای ارسال پیام های آفلاین",
- "Email_already_exists": "ایمیل وجود دارد",
- "Email_body": "ایمیل بدن",
- "Email_Change_Disabled": "مدیر Rocket.Chat خود را تغییر ایمیل را غیرفعال کرده است",
- "Email_Footer_Description": "شما ممکن است متغیرهایی زیر استفاده کنید: [Site_Name] و [Site_URL] برای نام نرم افزار و URL است. ",
- "Email_from": "از جانب",
- "Email_Header_Description": "شما ممکن است متغیرهایی زیر استفاده کنید: [Site_Name] و [Site_URL] برای نام نرم افزار و URL است. ",
- "Email_Notification_Mode": "آگاه سازی ایمیل آفلاین",
- "Email_Notification_Mode_All": "هر اشاره / DM",
- "Email_Notification_Mode_Disabled": "معلول",
+ "Editing_room": "ویرایش اتاق",
+ "Editing_user": "ویرایش کاربر",
+ "Email": "ایمیل",
+ "Email_address_to_send_offline_messages": "آدرس ایمیل جهت ارسال پیام های آفلاین",
+ "Email_already_exists": "ایمیل از قبل وجود دارد",
+ "Email_body": "بدنه ایمیل",
+ "Email_Change_Disabled": "مدیریت Rocket.Chat تغییر ایمیل را غیر فعال کرده است",
+ "Email_Footer_Description": "میتوانید از مکان نماهای زیر استفاده کنید: [Site_Name] و [Site_URL] به ترتیب برای نام و آدرس برنامه. ",
+ "Email_from": "از",
+ "Email_Header_Description": "میتوانید از مکان نماهای زیر استفاده کنید: [Site_Name] و [Site_URL] به ترتیب برای نام و آدرس برنامه. ",
+ "Email_Notification_Mode": "هشدارهای آفلاین ایمیلی",
+ "Email_Notification_Mode_All": "هر اشاره/DM",
+ "Email_Notification_Mode_Disabled": "غیر فعال شد",
"Email_or_username": "ایمیل یا نام کاربری",
"Email_subject": "موضوع",
- "Email_verified": "ایمیل تایید",
- "Emoji": "از Emoji",
+ "Email_verified": "ایمیل تایید شد",
+ "Emoji": "شکلک",
"Empty_title": "عنوان خالی",
- "Enable": "قادر ساختن",
- "Enable_Desktop_Notifications": "اعلانهای دسکتاپ را فعال",
- "Enabled": "فعال",
+ "Enable": "فعال",
+ "Enable_Desktop_Notifications": "هشدارهای دسکتاپ را فعال کن",
+ "Enable_two-factor_authentication": "فعال کردن تایید هویت دومرحله ای",
+ "Enabled": "فعال شد",
"Encrypted_message": "پیام رمز شده",
- "End_OTR": "پایان OTR",
- "Enter_a_regex": "یک regex را وارد کنید",
- "Enter_a_room_name": "نام اتاق را وارد کنید",
- "Enter_a_username": "نام کاربری را وارد کنید",
- "Enter_name_here": "نام اینجا وارد کنید",
- "Enter_to": "را وارد کنید به",
+ "End_OTR": "پایان مکالمه محرمانه",
+ "Enter_a_regex": "یک regex وارد کنید",
+ "Enter_a_room_name": "نام یک اتاق را وارد کنید",
+ "Enter_a_username": "یک نام کاربری وارد کنید",
+ "Enter_Alternative": "حالت جایگزین (ارسال با Enter + Ctrl/Alt/Shift/CMD)",
+ "Enter_Behaviour": "عملکرد کلید Enter",
+ "Enter_name_here": "نام را اینجا وارد کنید",
+ "Enter_Normal": "حالت عادی (ارسال با Enter)",
+ "Enter_to": "ورود به ",
"Error": "خطا",
"error-action-not-allowed": "__action__ مجاز نیست",
"error-application-not-found": "برنامه یافت نشد",
- "error-archived-duplicate-name": "یک کانال آرشیو با نام \"__room_name__ وجود دارد",
- "error-avatar-invalid-url": "URL نماد نامعتبر: __url__",
- "error-avatar-url-handling": "خطا در هنگام دست زدن به تنظیم آواتار ها از یک URL (__url__) برای _نام کاربری_",
- "error-cant-invite-for-direct-room": "می توانید کاربران را به اتاق دعوت مستقیم",
- "error-could-not-change-email": "می تواند تغییر ایمیل",
- "error-could-not-change-name": "می تواند نام را تغییر دهید",
- "error-could-not-change-username": "می تواند نام کاربری را تغییر دهید",
- "error-delete-protected-role": "می تواند نقش محافظت شده را حذف",
- "error-department-not-found": "وزارت یافت نشد",
- "error-duplicate-channel-name": "یک کانال با نام » %s 'را وجود دارد",
+ "error-archived-duplicate-name": "یک کانال بایگانی شده با نام '__room_name__' وجود دارد",
+ "error-avatar-invalid-url": "آدرس آواتار نامعتبر: __url__",
+ "error-avatar-url-handling": "هنگام تنظیم آواتار __username__ از آدرس __url__ خطا رخ داد",
+ "error-cant-invite-for-direct-room": "امکان دعوت کاربران به تماس های مستقیم وجود ندارد",
+ "error-could-not-change-email": "ایمیل تغییر نکرد",
+ "error-could-not-change-name": "نام تغییر نکرد",
+ "error-could-not-change-username": "نام کاربری تغییر نکرد",
+ "error-delete-protected-role": "نمی توان نقش محافظت شده را پاک کرد",
+ "error-department-not-found": "بخش یافت نشد",
+ "error-duplicate-channel-name": "یک کانال با نام '__channel_name__' وجود دارد",
"error-email-domain-blacklisted": "دامنه ایمیل در لیست سیاه است",
"error-field-unavailable": "__field__ قبلا استفاده شده است :(",
"error-file-too-large": "فایل خیلی بزرگ است",
- "error-importer-not-defined": "وارد کننده درست تعریف نشده بود، آن را از دست رفته کلاس واردات.",
- "error-input-is-not-a-valid-field": "__input__ است __field__ معتبر نیست",
+ "error-importer-not-defined": "وارد کننده درست تعریف نشده است.",
+ "error-input-is-not-a-valid-field": "__input__ یک __field__ صحیح نیست",
"error-invalid-actionlink": "لینک اقدام نامعتبر",
"error-invalid-arguments": "آرگومان های نامعتبر",
"error-invalid-asset": "دارایی نامعتبر",
- "error-invalid-channel": "کانال نامعتبر است.",
- "error-invalid-channel-start-with-chars": "کانال نامعتبر است. با @ شروع و یا #",
- "error-invalid-custom-field": "زمینه های سفارشی نامعتبر",
- "error-invalid-custom-field-name": "نام زمینه سفارشی نامعتبر است. استفاده از حروف تنها، اعداد، خط فاصله و زیرین.",
+ "error-invalid-channel": "کانال نامعتبر.",
+ "error-invalid-channel-start-with-chars": "کانال نامعتبر. با @ یا # شروع می شود.",
+ "error-invalid-custom-field": "فیلد سفارشی نامعتبر",
+ "error-invalid-custom-field-name": "نام فیلد سفارشی نامعتبر است. تنها ار حروف، اعداد و خطوط فاصله استفاده شود.",
"error-invalid-description": "توضیحات نامعتبر",
"error-invalid-domain": "دامنه نامعتبر",
"error-invalid-email": "__email__ ایمیل نامعتبر",
"error-invalid-file-height": "ارتفاع فایل نامعتبر",
"error-invalid-file-type": "نوع فایل نامعتبر",
"error-invalid-file-width": "عرض فایل نامعتبر",
- "error-invalid-from-address": "شما را از آدرس نامعتبر آگاه است.",
+ "error-invalid-from-address": "آدرس FROM نامعتبری وارد کرده اید.",
"error-invalid-integration": "ادغام نامعتبر",
"error-invalid-message": "پیام نامعتبر",
"error-invalid-method": "روش نامعتبر",
@@ -373,217 +397,211 @@
"error-invalid-redirectUri": "نامعتبر redirectUri",
"error-invalid-role": "نقش نامعتبر",
"error-invalid-room": "اتاق نامعتبر",
- "error-invalid-room-name": " %s از نام اتاق معتبر نیست، استفاده از حروف تنها، اعداد، خط فاصله و زیرین",
- "error-invalid-room-type": "__type__ از نوع اتاق معتبر نیست.",
- "error-invalid-settings": "تنظیمات نامعتبر ارائه",
+ "error-invalid-room-name": "__room_name__ نام معتبری برای اتاق نیست",
+ "error-invalid-room-type": "__type__ نوع معتبری برای اتاق نیست",
+ "error-invalid-settings": "تنظیمات نامعتبر است",
"error-invalid-subscription": "اشتراک نامعتبر",
- "error-invalid-token": "کد نامعتبر",
- "error-invalid-triggerWords": "triggerWords نامعتبر",
- "error-invalid-urls": "URL های نامعتبر",
+ "error-invalid-token": "توکن نامعتبر",
+ "error-invalid-triggerWords": "triggerWordهای غیر معتبر",
+ "error-invalid-urls": "آدرس های نا معتبر",
"error-invalid-user": "کاربر نامعتبر",
"error-invalid-username": "نام کاربری نامعتبر",
- "error-invalid-webhook-response": "آدرس اینترنتی webhook با وضعیت دیگر از 200 پاسخ",
- "error-message-deleting-blocked": "پیام حذف مسدود شده",
- "error-message-editing-blocked": "ویرایش پیام مسدود شده",
- "error-message-size-exceeded": "اندازه پیام بیش از Message_MaxAllowedSize",
- "error-missing-unsubscribe-link": "شما باید [unsubscribe] لینک فراهم می کند.",
- "error-no-tokens-for-this-user": "هیچ نشانه برای این کاربر وجود دارد",
- "error-not-allowed": "ممنوع",
+ "error-invalid-webhook-response": "آدرس webhook جوابی به غیر از کد ۲۰۰ می دهد",
+ "error-message-deleting-blocked": "حذف پیام مسدود شده است",
+ "error-message-editing-blocked": "ویرایش پیام مسدود شده است",
+ "error-message-size-exceeded": "اندازه پیام از Message_MaxAllowedSize بیشتر است",
+ "error-missing-unsubscribe-link": "شما می بایست لینک [unsubscribe] را وارد کنید.",
+ "error-no-tokens-for-this-user": "هیچ توکنی برای این کاربر وجود ندارد",
+ "error-not-allowed": "اجازه داده نشده",
"error-not-authorized": "غیر مجاز",
- "error-push-disabled": "فشار غیر فعال است",
- "error-remove-last-owner": "این آخرین مالک است. لطفا یک مالک جدید قبل از حذف یک تنظیم شده است.",
- "error-role-in-use": "می توانید نقش را حذف کنید زیرا در حال استفاده است",
+ "error-push-disabled": "Push غیر فعال است",
+ "error-remove-last-owner": "این آخرین مالک است. لطفا قبل از حذف آن، مالک جدیدی تعیین کنید.",
+ "error-role-in-use": "نمی توانید نقش را حذف کنید زیرا در حال استفاده است",
"error-role-name-required": "نام نقش مورد نیاز است",
- "error-the-field-is-required": "__field__ فیلد الزامی است.",
- "error-too-many-requests": "خطا، درخواست های زیادی. لطفا آرامتر. شما باید __seconds__ ثانیه قبل از تلاش دوباره صبر کنید.",
+ "error-the-field-is-required": "فیلد __field__ الزامی است.",
+ "error-too-many-requests": "خطا! لطفا آرامتر! شما باید __seconds__ ثانیه صبر و دوباره سعی کنید.",
"error-user-is-not-activated": "کاربر فعال نیست",
"error-user-not-in-room": "کاربر در این اتاق نیست",
"error-user-registration-disabled": "ثبت نام کاربر غیر فعال است",
- "error-user-registration-secret": "ثبت نام کاربر تنها از طریق URL راز اجازه",
- "error-you-are-last-owner": "شما آخرین مالک هستند. لطفا مالک جدید قبل از خروج از اتاق تنظیم شده است.",
- "Error_changing_password": "تغییر پسورد",
- "Esc_to": "Esc را برای",
+ "error-user-registration-secret": "ثبت نام کاربران تنها از طریق آدرس مخفی (Secret URL) امکان پذیر است",
+ "error-you-are-last-owner": "شما آخرین مالک هستید. لطفا مالک جدیدی قبل از خروج از اتاق مشخص کنید.",
+ "Error_changing_password": "خطا هنگام تغییر رمز عبور",
+ "Esc_to": "Esc برای",
+ "Everyone_can_access_this_channel": "همه به این کانال دسترسی دارند",
"Example_s": "به عنوان مثال: %s",
- "False": "غلط",
+ "False": "خیر",
"Favorite_Rooms": "فعال کردن اتاق های مورد علاقه",
- "Favorites": "مورد علاقه های شما",
- "Features_Enabled": "ویژگی های فعال",
- "Field": "رشته",
- "Field_removed": "درست حذف",
- "File_exceeds_allowed_size_of_bytes": "فایل بیشتر حجم مجاز بایت __size__",
+ "Favorites": "موارد مورد علاقه",
+ "Features_Enabled": "ویژگی ها فعال شد",
+ "Field": "فیلد",
+ "Field_removed": "فیلد حذف شد",
+ "File_exceeds_allowed_size_of_bytes": "حجم فایل بیشتر از مقدار مجاز __size__ است.",
"FileUpload": "آپلود فایل",
- "FileUpload_Enabled": "ارسال فایل فعال",
+ "FileUpload_Enabled": "آپلود فایل فعال شد",
"FileUpload_File_Empty": "فایل خالی",
"FileUpload_FileSystemPath": "مسیر سیستم",
- "FileUpload_MaxFileSize": "حداکثر حجم آپلود فایل (در بایت)",
- "FileUpload_MediaType_NotAccepted": "انواع رسانه پذیرفته نشده",
+ "FileUpload_MaxFileSize": "حداکثر حجم آپلود فایل (به بایت)",
+ "FileUpload_MediaType_NotAccepted": "فرمت های فایل غیر مجاز",
"FileUpload_MediaTypeWhiteList": "انواع رسانه های پذیرفته شده",
- "FileUpload_MediaTypeWhiteListDescription": "کاما از هم جدا لیستی از انواع رسانه ها. ترک آن را خالی برای پذیرش انواع رسانه ها.",
- "FileUpload_ProtectFiles": "حفاظت از فایل های آپلود شده",
- "FileUpload_ProtectFilesDescription": "تنها کاربران تصدیق خواهد دسترسی دارند",
- "FileUpload_S3_Acl": "لیگ قهرمانان آسیا آمازون S3",
- "FileUpload_S3_AWSAccessKeyId": "آمازون S3 AWSAccessKeyId",
- "FileUpload_S3_AWSSecretAccessKey": "آمازون S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "آمازون S3 نام سطل",
- "FileUpload_S3_BucketURL": "URL سطل",
- "FileUpload_S3_CDN": "دامنه CDN برای دریافت",
+ "FileUpload_MediaTypeWhiteListDescription": "لیست کاما جدا از فرمت های فایل. برای پذیرفتن همه فرمت ها آن را خالی بگذارید.",
+ "FileUpload_ProtectFiles": "از فایل های بارگذاری شده حفاظت شود",
+ "FileUpload_ProtectFilesDescription": "تنها کاربران تعیین هویت شده دسترسی خواهند داشت",
+ "FileUpload_S3_Acl": "Acl",
+ "FileUpload_S3_AWSAccessKeyId": "کلید دستیابی",
+ "FileUpload_S3_AWSSecretAccessKey": "کلید رمز",
+ "FileUpload_S3_Bucket": "نام Bucket",
+ "FileUpload_S3_BucketURL": "آدرس Bucket",
+ "FileUpload_S3_CDN": "دامنه CDN برای دانلودها",
"FileUpload_S3_Region": "منطقه",
"FileUpload_Storage_Type": "نوع ذخیره سازی",
- "Flags": "پرچم",
- "Follow_social_profiles": "دنبال پروفایل های اجتماعی ما، چنگال ما در github و به اشتراک گذاری افکار خود را در مورد برنامه rocket.chat در هیئت مدیره trello ما است.",
- "Food_and_Drink": "غذا نوشیدنی",
- "Footer": "بالا و پایین صفحه",
- "For_your_security_you_must_enter_your_current_password_to_continue": "برای امنیت شما، شما باید رمز عبور خود را دوباره وارد کنید به ادامه",
- "Force_SSL": "استفاده از SSL",
- "Force_SSL_Description": "* توجه * _Force SSL_ هرگز نباید با پروکسی معکوس استفاده می شود. اگر شما از یک پروکسی معکوس، شما باید تغییر مسیر وجود دارد انجام. این گزینه برای استقرار مانند Heroku، که پیکربندی تغییر مسیر در پروکسی معکوس اجازه نمی دهد وجود دارد.",
- "Forgot_password": "رمز عبور خود را فراموش کرده",
+ "Flags": "پرچم ها",
+ "Follow_social_profiles": "ما را در شبکه های اجتماعی دنبال و در گیت هاب فورک کنید و نظرات خود را در مورد Rocket.chat با ما در میان بگذارید.",
+ "Food_and_Drink": "غذا و نوشیدنی",
+ "Footer": "پاورقی",
+ "For_your_security_you_must_enter_your_current_password_to_continue": "برای حفظ امنیت، باید گذرواژه فعلیتان را برای ادامه وارد کنید",
+ "Force_SSL": "اجباری کردن SSL",
+ "Force_SSL_Description": "*توجه!* _Force SSL_ هرگز نباید با پراکسی معکوس استفاده شود. اگر پراکسی معکسو دارید باید تغییر مسیر را آنجا پیکربندی کنید. این گزینه صرفا برای استفاده مثلا Heroku وجود دارد که اجازه تغییر مسیر را در پراکسی معکوس نمی دهد.",
+ "Forgot_password": "فراموشی رمز عبور",
"Frequently_Used": "اغلب استفاده می شود",
- "From": "از جانب",
+ "From": "از",
"From_Email": "از ایمیل",
- "From_email_warning": "هشدار: این زمینه از موضوع را به تنظیمات سرور پست الکترونیکی خود را است.",
+ "From_email_warning": "هشدار : فیلد از به تنظیمات سرور میل شما بستگی دارد.",
"General": "عمومی",
- "github_no_public_email": "شما به هیچ عنوان ایمیل ایمیل عمومی در حساب github خود را نمی",
- "Give_a_unique_name_for_the_custom_oauth": "یک نام منحصر به فرد برای OAuth حفظ سفارشی",
- "Give_the_application_a_name_This_will_be_seen_by_your_users": "به نرم افزار یک نام. این خواهد بود که توسط کاربران شما دیده می شود.",
- "Global": "جهانی",
- "GoogleTagManager_id": "گوگل ID مدیر برچسب",
- "Hash": "مخلوط",
+ "github_no_public_email": "شما هیچ ایمیلی به عنوان ایمیل عمومی در اکانت گیت هابتان ندارید",
+ "Give_a_unique_name_for_the_custom_oauth": "یک نام یکتا به oauth سفارشی بدهید",
+ "Give_the_application_a_name_This_will_be_seen_by_your_users": "یک نام به برنامه بدهید. کاربران آن را مشاهده خواهند کرد.",
+ "Global": "سراسری",
+ "GoogleTagManager_id": "شناسه Tag Manager گوگل",
+ "Hash": "هش",
"Header": "سربرگ",
"Hidden": "پنهان",
- "Hide_Group_Warning": "آیا مطمئن هستید که می خواهید برای مخفی گروه \" %s\" را؟",
- "Hide_Private_Warning": "آیا شما مطمئن هستید که میخواهید برای مخفی کردن بحث با \" %s\" را؟",
- "Hide_room": "مخفی کردن اتاق",
- "Hide_Room_Warning": "آیا مطمئن هستید که می خواهید برای مخفی در اتاق \" %s\" را؟",
- "Hide_usernames": "مخفی کردن نامهای کاربری",
- "Highlights": "های لایت",
- "Highlights_How_To": "مطلع می شود وقتی کسی اشاره یک کلمه یا عبارت، آن را در اینجا اضافه کنید. شما می توانید کلمات یا عبارات با کاما از هم جدا کنید. واژه های برجسته حروف حساس نیست.",
- "Highlights_List": "کلمات برجسته",
+ "Hide_Avatars": "پنهان کردن آواتارها",
+ "Hide_Group_Warning": "آیا بابت پنهان کردن گروه \"%s\" مطمئن هستید؟",
+ "Hide_Private_Warning": "آیا بابت پنهان کردن مکالمه با \"%s\" مطمئن هستید؟",
+ "Hide_roles": "پنهان کردن نقش ها",
+ "Hide_room": "پنهان کردن اتاق",
+ "Hide_Room_Warning": "آیا بابت پنهان کردن اتاق \"%s\" مطمئنید؟",
+ "Hide_Unread_Room_Status": "عدم نمایش وضعیت خوانده نشده برای این اتاق",
+ "Hide_usernames": "مخفی کردن نام های کاربری",
+ "Highlights": "نشان شده ها",
+ "Highlights_How_To": "برای مطلع شدن از زمانی که کسی به کلمه یا عبارتی اشاره می کند آن را اینجا وارد کنید. می توانید کلمات یا عبارات را با کاما جدا کنید. کلمات نشان شده به بزرگی و کوچکی حروف حساس نیستند.",
+ "Highlights_List": "کلمات نشان شده",
"History": "تاریخ",
"Host": "میزبان",
"hours": "ساعت ها",
- "How_friendly_was_the_chat_agent": "عامل چت چگونه دوستانه بود؟",
- "How_knowledgeable_was_the_chat_agent": "عامل چت چگونه آگاه بود؟",
- "How_responsive_was_the_chat_agent": "عامل چت چگونه پاسخگو بود؟",
- "How_satisfied_were_you_with_this_chat": "چگونه رضایت شما را با این چت بود؟",
- "If_you_are_sure_type_in_your_password": "اگر شما مطمئن نوع رمز عبور خود را عبارتند از:",
- "If_you_are_sure_type_in_your_username": "اگر شما مطمئن نوع کاربری خود را عبارتند از:",
- "Importer_Archived": "آرشیو",
- "Importer_done": "واردات کامل!",
- "Importer_finishing": "تا پایان واردات.",
- "Importer_From_Description": "واردات __from داده __ را به Rocket.Chat.",
- "Importer_import_cancelled": "واردات لغو شده است.",
- "Importer_import_failed": "در حالی که در حال اجرا واردات خطایی رخ داد.",
- "Importer_importing_channels": "واردات کانال.",
- "Importer_importing_messages": "واردات پیام است.",
- "Importer_importing_started": "شروع واردات.",
- "Importer_importing_users": "واردات از کاربران است.",
- "Importer_not_in_progress": "وارد کننده در حال حاضر در حال اجرا نیست.",
- "Importer_Prepare_Restart_Import": "راه اندازی مجدد واردات",
- "Importer_Prepare_Start_Import": "شروع وارد",
- "Importer_Prepare_Uncheck_Archived_Channels": "کانال های آرشیو شده لغو انتخاب",
- "Importer_Prepare_Uncheck_Deleted_Users": "کاربران لغو انتخاب حذف",
- "Importer_progress_error": "برای به دست آوردن پیشرفت برای واردات شکست خورده است.",
- "Importer_setup_error": "در حالی که راه اندازی وارد خطایی رخ داد.",
- "inline_code": "inline_code",
- "Install_Extension": "نصب برنامه افزودنی",
- "Install_FxOs": "نصب Rocket.Chat در فایرفاکس خود را",
- "Install_FxOs_done": "عالی! شما هم اکنون می توانید Rocket.Chat از طریق آیکون بر روی صفحه اصلی خود را. آن لذت ببرید با Rocket.Chat!",
- "Install_FxOs_error": "با عرض پوزش، که کار نمی کند به عنوان در نظر گرفته شده! خطای زیر ظاهر می شود:",
- "Install_FxOs_follow_instructions": "لطفا نصب و راه اندازی برنامه بر روی دستگاه را اعلام (مطبوعات \"نصب\" وقتی از شما خواسته).",
+ "How_friendly_was_the_chat_agent": "عامل چت چقدر دوستانه بود؟",
+ "How_knowledgeable_was_the_chat_agent": "عامل چت چقدر آگاه بود؟",
+ "How_responsive_was_the_chat_agent": "عامل چت چقدر پاسخگو بود؟",
+ "How_satisfied_were_you_with_this_chat": "چه میزان از این چت راضی بودید؟",
+ "If_you_are_sure_type_in_your_password": "اگر مطمئن هستید رمز خود را وارد کنید:",
+ "If_you_are_sure_type_in_your_username": "اگر مطمئنید نام کاربری خود را وارد کنید:",
+ "Importer_Archived": "بایگانی شد",
+ "Importer_done": "وارد کردن تمام شد!",
+ "Importer_finishing": "پایان دادن به وارد کردن.",
+ "Importer_From_Description": "داده های __from__ را وارد Rocket.chat می کند.",
+ "Importer_import_cancelled": "وارد کردن لغو شد.",
+ "Importer_import_failed": "هنگام وارد کردن خطایی رخ داد.",
+ "Importer_importing_channels": "وارد کردن کانال ها.",
+ "Importer_importing_messages": "وارد کردن پیام ها.",
+ "Importer_importing_started": "شروع وارد کردن.",
+ "Importer_importing_users": "وارد کردن کاربران.",
+ "Importer_not_in_progress": "وارد کننده در حال اجرا نیست.",
+ "Importer_Prepare_Restart_Import": "راه اندازی مجدد وارد کردن",
+ "Importer_Prepare_Start_Import": "شروع وارد کردن",
+ "Importer_Prepare_Uncheck_Archived_Channels": "لغو انتخاب کانال های بایگانی شده",
+ "Importer_Prepare_Uncheck_Deleted_Users": "لغو انتخاب کابران پاک شده",
+ "Importer_progress_error": "ناموفق در آغاز وارد کردن.",
+ "Importer_setup_error": "هنگام تنظیم وارد کننده خطایی رخ داد.",
+ "inline_code": "کدِ در خط",
+ "Install_Extension": "نصب افزودنی",
+ "Install_FxOs": "Rocket.Chat را روی فایرفاکس نصب کنید",
+ "Install_FxOs_done": "اکنون می توانید از Rocket.Chat با آیکون روی صفحه استفاده کنید",
+ "Install_FxOs_error": "متأسفانه آن طور که باید عمل نکرد! خطای زیر رخ داد:",
+ "Install_FxOs_follow_instructions": "لطفا نصب برنامه را روی دستگاه خود تأیید کنید (\"install\" را فشار دهید).",
"Installation": "نصب و راه اندازی",
"Installed_at": "نصب شده در",
- "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "دستورالعمل ها را به بازدید کننده خود را پر کردن فرم برای ارسال یک پیام",
+ "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "دستور العمل ها برای کسانی که فرم را برای ارسال یک پیام پر می کنند.",
"Integration_added": "ادغام اضافه شده است",
"Integration_Incoming_WebHook": "ادغام WebHook ورودی",
"Integration_New": "یکپارچه سازی جدید",
"Integration_Outgoing_WebHook": "ادغام WebHook خروجی",
- "Integration_updated": "ادغام به روز شده است",
- "Integrations": "یکپارچگی",
+ "Integration_updated": "ادغام به روز شده است.",
+ "Integrations": "ادغام ها",
+ "Integrations_Outgoing_Type_RoomLeft": "کاربر اتاق را ترک کرد",
"InternalHubot": "Hubot داخلی",
- "InternalHubot_ScriptsToLoad": "اسکریپت برای بارگذاری",
- "InternalHubot_ScriptsToLoad_Description": "لطفا یک لیست کاما از هم جدا از اسکریپت برای بارگذاری از https://github.com/github/hubot-scripts/tree/master/src/scripts وارد کنید",
- "InternalHubot_Username_Description": "این باید یک نام کاربری معتبر از یک ربات ثبت نام بر روی سرور خود باشد.",
- "Invalid_confirm_pass": "تایید رمز عبور رمز عبور مطابقت ندارد",
+ "InternalHubot_ScriptsToLoad": "اسکریپت ها برای بارگذاری",
+ "InternalHubot_ScriptsToLoad_Description": "لطفا یک لیست کاما جدا از اسکریپت ها برای بارگذاری از پوشه سفارشی خود وارد کنید",
+ "InternalHubot_Username_Description": "این باید یک نام کاربری صحیح از یک بات ثبت شده روی سرور باشد.",
+ "Invalid_confirm_pass": "تأییدیه رمز عبور با رمز عبور اصلی مطابقت ندارد.",
"Invalid_email": "ایمیل وارد شده نامعتبر است",
- "Invalid_Export_File": "فایل آپلود شده است٪ معتبر بازدید کنندگان فایل صادرات است.",
- "Invalid_Import_File_Type": "نوع فایل واردات نامعتبر است.",
+ "Invalid_Export_File": "فایل آپلود شده فایل معتبر %s نیست.",
+ "Invalid_Import_File_Type": "نوع فایل وارد شده نامعتبر است.",
"Invalid_name": "نام نباید خالی باشد",
- "Invalid_notification_setting_s": "تنظیمات اطلاع رسانی نامعتبر: %s",
+ "Invalid_notification_setting_s": "تنظیمات هشدار نامعتبر: %s",
"Invalid_pass": "رمز عبور نباید خالی باشد",
- "Invalid_room_name": " %s از نام اتاق معتبر نیست، استفاده از حروف تنها، اعداد، خط فاصله و زیرین",
- "Invalid_secret_URL_message": "URL ارائه نامعتبر است.",
- "invisible": "نامرئی",
- "Invisible": "نامرئی",
- "Invitation_HTML": "دعوت HTML",
- "Invitation_HTML_Default": " شما باید به دعوت شده است [Site_Name] برو به [Site_URL] و سعی کنید بهترین راه حل چت منبع باز امروز در دسترس است!
",
- "Invitation_HTML_Description": "شما ممکن است متغیرهایی زیر استفاده کنید: [email] برای ایمیل گیرنده. [Site_Name] و [Site_URL] برای نام نرم افزار و URL است. ",
- "Invitation_Subject": "دعوت نامه تم",
- "Invitation_Subject_Default": "شما باید به دعوت شده است [Site_Name]",
+ "Invalid_room_name": "%s نام معتبری برای اتاق نیست",
+ "Invalid_secret_URL_message": "آدرس ارائه شده معتبر نیست.",
+ "invisible": "پنهان",
+ "Invisible": "پنهان",
+ "Invitation_HTML": "HTML دعوتنامه",
+ "Invitation_HTML_Default": "شما به [Site_Name] دعوت شده اید. به [Site_URL] رفته و بهترین برنامه چت متن باز را امتحان کنید!
",
+ "Invitation_HTML_Description": "می توانید از مکان نماهای زیر استفاده کنید: [email] برای گیرنده ایمیل. [Site_Name] و [Site_URL] به ترتیب برای نام و آدرس برنامه. ",
+ "Invitation_Subject": "عنوان دعوت نامه",
+ "Invitation_Subject_Default": "شما به [Site_Name] دعوت شده اید",
"Invite_user_to_join_channel": "دعوت از یک کاربر برای پیوستن به این کانال",
"Invite_Users": "دعوت از کاربران",
- "is_also_typing": "همچنین تایپ",
- "is_also_typing_female": "همچنین تایپ",
- "is_also_typing_male": "همچنین تایپ",
- "is_typing": "در حال تایپ کردن",
- "is_typing_female": "در حال تایپ کردن",
- "is_typing_male": "در حال تایپ کردن",
+ "is_also_typing": "هم می نویسد",
+ "is_also_typing_female": "هم می نویسد",
+ "is_also_typing_male": "هم می نویسد",
+ "is_typing": "می نویسد",
+ "is_typing_female": "می نویسد",
+ "is_typing_male": "می نویسد",
"It_works": "کار می کند",
"italics": "کج (ایتالیک)",
- "Jitsi_Chrome_Extension": "کد برنامه افزودنی Chrome",
- "Jitsi_Enable_Channels": "فعال کردن در کانال",
+ "Jitsi_Chrome_Extension": "کد افزونه کروم",
+ "Jitsi_Enable_Channels": "فعال کردن در Channelها",
"join": "پیوستن",
- "Join_audio_call": "اضافه کردن تماس های صوتی",
- "Join_default_channels": "اضافه کردن کانال های پیش فرض",
- "Join_the_Community": "تاریخ جامعه",
- "Join_the_given_channel": "اضافه کردن کانال داده",
+ "Join_audio_call": "پیوستن به تماس صوتی",
+ "Join_default_channels": "پیوستن به کانال های پیشفرض",
+ "Join_the_Community": "پیوستن به جامعه",
+ "Join_the_given_channel": "پیوستن به این کانال",
"Join_video_call": "پیوستن به تماس ویدیویی",
"Joined": "پیوسته",
"Jump": "پرش",
- "Jump_to_first_unread": "پرش به خوانده نشده اولین",
+ "Jump_to_first_unread": "پرش به اولین خوانده نشده",
"Jump_to_message": "پرش به پیام",
"Jump_to_recent_messages": "پرش به پیام های اخیر",
- "Katex_Dollar_Syntax": "اجازه دلار نحو",
- "Katex_Dollar_Syntax_Description": "اجازه می دهد با استفاده از $ $ $ $ بلوک KAtex دارای و $ $ گرامرهای KAtex دارای درون خطی",
- "Katex_Enabled": "KAtex دارای فعال",
- "Katex_Enabled_Description": "اجازه می دهد با استفاده از KAtex دارای برای نوشتن فرمولها در پیام",
- "Katex_Parenthesis_Syntax": "اجازه می دهد پرانتز نحو",
- "Katex_Parenthesis_Syntax_Description": "اجازه می دهد با استفاده از \\ [بلوک KAtex دارای \\] و \\ (خطی KAtex دارای \\) سینتکس",
+ "Just_invited_people_can_access_this_channel": "تنها افراد دعوت شده به این کانال دسترسی دارند.",
+ "Katex_Dollar_Syntax": "اجازه Dollar Syntax",
+ "Katex_Dollar_Syntax_Description": "اجازه استفاده از $$katex block$$ و $inline katex$",
+ "Katex_Enabled": "Katex فعال است",
+ "Katex_Enabled_Description": "اجازه استفاده از katex برای ریاضیات در پیام ها",
+ "Katex_Parenthesis_Syntax": "اجازه استفاده از پرانتز",
+ "Katex_Parenthesis_Syntax_Description": "اجازه استفاده از \\[katex block\\] و \\(inline katex\\)",
"Knowledge_Base": "دانش محور",
"Label": "برچسب",
"Language": "زبان",
"Language_Version": "نسخه انگلیسی",
"Last_login": "آخرین ورود به سیستم",
- "Last_Message_At": "تاریخ و زمان آخرین در",
- "Last_seen": "آخرین فعالیت",
+ "Last_Message_At": "آخرین پیام در",
+ "Last_seen": "آخرین مشاهده",
"Layout": "طرح",
- "Layout_Home_Body": "صفحه اصلی بدن",
- "Layout_Home_Title": "صفحه اصلی عنوان",
- "Layout_Login_Terms": "ورود به شرایط",
+ "Layout_Home_Body": "بدنه صفحه اول",
+ "Layout_Home_Title": "عنوان صفحه اول",
+ "Layout_Login_Terms": "ضوابط ورود",
"Layout_Privacy_Policy": "سیاست حفظ حریم خصوصی",
- "Layout_Sidenav_Footer": "سمت ناوبری پاورقی",
- "Layout_Sidenav_Footer_description": "اندازه بالا و پایین صفحه 260 X 70px",
+ "Layout_Sidenav_Footer": "Side Navigation Footer",
+ "Layout_Sidenav_Footer_description": "اندازه پاورقی ۲۶۰ در ۷۰ پیکسل است",
"Layout_Terms_of_Service": "شرایط استفاده از خدمات",
"LDAP": "LDAP",
- "LDAP_CA_Cert": "CA بزنید",
- "LDAP_Custom_Domain_Search": "جستجو سفارشی دامنه",
- "LDAP_Custom_Domain_Search_Description": "قطعه ای از JSON که بر اتصال و اتصال اطلاعات و فرم: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
- "LDAP_Default_Domain": "به طور پیش فرض دامنه",
+ "LDAP_CA_Cert": "گواهینامه CA",
+ "LDAP_Default_Domain": "دامنه پیشفرض",
"LDAP_Description": "یک مرکز برای به اشتراک گذاری یک رمز عبور بین سایت و خدمات مختلف - LDAP یک پایگاه داده سلسله مراتبی است که بسیاری از شرکت ها برای ارائه یکبار ورود به سیستم است. https://rocket.chat/docs/administrator-guides/authentication/ldap/: برای کسب اطلاعات پیکربندی پیشرفته و نمونه، لطفا ویکی ما مشورت کنید.",
- "LDAP_Domain_Base": "پایه دامنه",
- "LDAP_Domain_Base_Description": "نام کامل برجسته (DN) از یک زیر درخت LDAP شما می خواهید به جستجو برای کاربران و گروه. شما می توانید به عنوان بسیاری از شما می خواهم اضافه کنید. با این حال، هر گروه باید در پایه دامنه به عنوان کاربران که متعلق به آن تعریف شود. اگر شما گروه های کاربری محدود مشخص، تنها کاربران که متعلق به آن گروه در دامنه باشد. ما توصیه می کنیم که شما در سطح بالا از LDAP درخت دایرکتوری خود را مشخص کنید به عنوان پایه دامنه خود و استفاده از فیلتر جستجو برای کنترل دسترسی.",
- "LDAP_Domain_Search_Filter": "دامنه جستجو فیلتر",
- "LDAP_Domain_Search_Filter_Description": "اگر مشخص، تنها کاربران که مطابقت دارند این فیلتر اجازه خواهد داشت به سیستم وارد شوید. اگر هیچ فیلتر مشخص است، تمام کاربران در محدوده پایه دامنه مشخص قادر خواهد بود به سیستم وارد شوید. به عنوان مثال برای اکتیو دایرکتوری `memberOf = CN = ROCKET_CHAT، OU = عمومی Groups`. به عنوان مثال برای اوپنالدپ (جستجو بازی های درب) `OU: DN: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "دامنه جستجو شی رده",
- "LDAP_Domain_Search_Object_Category_Description": "* به objectCategory * که شناسایی کاربران خود را. خالی به * اوپنالدپ *. به عنوان مثال `person`، و غیره",
- "LDAP_Domain_Search_Object_Class": "دامنه کلاس جستجو شی",
- "LDAP_Domain_Search_Object_Class_Description": "* به objectclass * که شناسایی کاربران خود را. به عنوان مثال `organizationalPerson`،` user`، `inetOrgPerson`، و غیره",
- "LDAP_Domain_Search_Password": "دامنه جستجو رمز عبور",
- "LDAP_Domain_Search_Password_Description": "رمز عبور برای کاربر جستجوی دامنه.",
- "LDAP_Domain_Search_User": "دامنه جستجو کاربر",
- "LDAP_Domain_Search_User_Description": "کاربر LDAP که انجام جستجوها کاربران برای تأیید هویت کاربران دیگر زمانی که آنها وارد شوید. این یک حساب خدمات به طور خاص برای یکپارچگی شخص ثالث ایجاد شده است به طور معمول. استفاده از یک نام کاملا مناسب، مانند `CN = مدیر، CN = کاربران، DC = به عنوان مثال، DC = com`.",
- "LDAP_Domain_Search_User_ID": "دامنه جستجو ID کاربر",
- "LDAP_Domain_Search_User_ID_Description": "ویژگی LDAP LDAP که شناسایی کاربران که تلاش احراز هویت. در این زمینه باید `شود sAMAccountName` برای نصب فعال ترین دایرکتوری، اما ممکن است` uid` برای راه حل های دیگر LDAP، مانند OpenLDAP. شما می توانید `mail` برای شناسایی کاربران از طریق ایمیل و یا هر ویژگی شما می خواهید استفاده کنید. شما می توانید چندین مقدار را جدا شده توسط کاما به کاربران اجازه ورود با استفاده از شناسههای متعدد مانند نام کاربری یا ایمیل استفاده کنید.",
- "LDAP_Enable": "قادر ساختن",
+ "LDAP_BaseDN_Description": "نام کامل برجسته (DN) از یک زیر درخت LDAP شما می خواهید به جستجو برای کاربران و گروه. شما می توانید به عنوان بسیاری از شما می خواهم اضافه کنید. با این حال، هر گروه باید در پایه دامنه به عنوان کاربران که متعلق به آن تعریف شود. اگر شما گروه های کاربری محدود مشخص، تنها کاربران که متعلق به آن گروه در دامنه باشد. ما توصیه می کنیم که شما در سطح بالا از LDAP درخت دایرکتوری خود را مشخص کنید به عنوان پایه دامنه خود و استفاده از فیلتر جستجو برای کنترل دسترسی.",
+ "LDAP_User_Search_Field_Description": "ویژگی LDAP LDAP که شناسایی کاربران که تلاش احراز هویت. در این زمینه باید `شود sAMAccountName` برای نصب فعال ترین دایرکتوری، اما ممکن است` uid` برای راه حل های دیگر LDAP، مانند OpenLDAP. شما می توانید `mail` برای شناسایی کاربران از طریق ایمیل و یا هر ویژگی شما می خواهید استفاده کنید. شما می توانید چندین مقدار را جدا شده توسط کاما به کاربران اجازه ورود با استفاده از شناسههای متعدد مانند نام کاربری یا ایمیل استفاده کنید.",
+ "LDAP_User_Search_Filter_Description": "اگر مشخص، تنها کاربران که مطابقت دارند این فیلتر اجازه خواهد داشت به سیستم وارد شوید. اگر هیچ فیلتر مشخص است، تمام کاربران در محدوده پایه دامنه مشخص قادر خواهد بود به سیستم وارد شوید. به عنوان مثال برای اکتیو دایرکتوری `memberOf = CN = ROCKET_CHAT، OU = عمومی Groups`. به عنوان مثال برای اوپنالدپ (جستجو بازی های درب) `OU: DN: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "کاربر LDAP که انجام جستجوها کاربران برای تأیید هویت کاربران دیگر زمانی که آنها وارد شوید. این یک حساب خدمات به طور خاص برای یکپارچگی شخص ثالث ایجاد شده است به طور معمول. استفاده از یک نام کاملا مناسب، مانند `CN = مدیر، CN = کاربران، DC = به عنوان مثال، DC = com`.",
+ "LDAP_Enable": "فعال کردن",
"LDAP_Enable_Description": "تلاش برای استفاده از LDAP برای احراز هویت.",
"LDAP_Encryption": "رمزگذاری",
"LDAP_Encryption_Description": "روش رمزگذاری مورد استفاده برای تامین امنیت ارتباطات به سرور LDAP. مثالها عبارتند از `plain` (بدون رمزنگاری)،` SSL / LDAPS` (رمزگذاری از شروع)، و `StartTLS` (ارتقا به ارتباط رمزگذاری شده یک بار متصل).",
@@ -597,22 +615,19 @@
"LDAP_Sync_User_Data_Description": "حفظ اطلاعات کاربران در همگام سازی با سرور در ورود (به عنوان مثال: نام، ایمیل).",
"LDAP_Sync_User_Data_FieldMap": "کاربر داده نقشه درست",
"LDAP_Sync_User_Data_FieldMap_Description": "پیکربندی زمینه حساب کاربری (مانند ایمیل) از یک رکورد در LDAP جمعیت (یک بار). به عنوان مثال، `{\" CN \":\" نام \"،\" ایمیل \":\" ایمیل \"}` خواهد نام یک شخص قابل خواندن توسط انسان از ویژگی CN، و ایمیل خود را از ویژگی های ایمیل را انتخاب نمایید. زمینه های موجود عبارتند از `name` و` email`.",
- "LDAP_Sync_Users": "کاربران همگام سازی",
"LDAP_Test_Connection": "اتصال تست",
"LDAP_Unique_Identifier_Field": "شناسه منحصر به فرد درست",
"LDAP_Unique_Identifier_Field_Description": "که درست استفاده خواهد شد به لینک کاربران LDAP و کاربر Rocket.Chat است. شما می توانید چندین مقدار را جدا شده توسط کاما اطلاع به تلاش برای بدست آوردن مقدار از رکورد LDAP. مقدار پیش فرض است `objectGUID، آی بی ام-entryUUID، GUID، dominoUNID، nsuniqueId، uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "استفاده از جستجو سفارشی دامنه",
- "LDAP_Use_Custom_Domain_Search_Description": "ارسال فیلتر خود را به کاربران جستجو در سرور LDAP.",
"LDAP_Username_Field": "نام کاربری درست",
"LDAP_Username_Field_Description": "که درست خواهد شد به عنوان * نام کاربری * برای کاربران جدید استفاده می شود. خالی بگذارید به استفاده از نام کاربری آگاهانه در صفحه ورود. شما می توانید تگ های قالب بیش از حد استفاده کنید، مانند `#{givenName}.#{sn}`. مقدار پیش فرض است `sAMAccountName`.",
- "Leave_Group_Warning": "آیا مطمئن هستید که می خواهید گروه \" %s\" را ترک کنند؟",
- "Leave_Private_Warning": "مطمئنید که می خواهید بحث با \" %s\" را ترک کنند؟",
- "Leave_room": "خروج از اتاق",
- "Leave_Room_Warning": "آیا مطمئن هستید که می خواهید به ترک اتاق \" %s\" را؟",
+ "Leave_Group_Warning": "آیا واقعا می خواهید گروه \"%s\" را ترک کنید؟",
+ "Leave_Private_Warning": "آیا واقعا می خواهید مکالمه با \"%s\" را ترک کنید؟",
+ "Leave_room": "ترک اتاق",
+ "Leave_Room_Warning": "آیا واقعا می خواهید اتاق \"%s\" را ترک کنید؟",
"line": "خط",
- "List_of_Channels": "لیست کانال",
+ "List_of_Channels": "لیست Channelها",
"List_of_Direct_Messages": "فهرست پیام های مستقیم",
- "Livechat_agents": "عوامل livechat در",
+ "Livechat_agents": "عامل های Livechat",
"Livechat_Dashboard": "داشبورد livechat در",
"Livechat_enabled": "livechat در فعال",
"Livechat_forward_open_chats": "چت رو به جلو باز",
@@ -626,40 +641,41 @@
"Livechat_title_color": "عنوان livechat در رنگ پس زمینه",
"Livechat_Users": "کاربران livechat در",
"Load_more": "بارگیری بیشتر",
- "Loading...": "در حال بارگذاری ...",
- "Loading_more_from_history": "بارگیری بیش از تاریخ",
- "Loading_suggestion": "بارگذاری پیشنهادات ...",
+ "Loading...": "در حال بارگیری...",
+ "Loading_more_from_history": "بارگیری بیشتر از تاریخچه",
+ "Loading_suggestion": "بارگیری پیشنهادها",
"Localization": "بومی سازی",
"Log_File": "نمایش فایل ها و خط",
"Log_Level": "سطح ورود",
"Log_Package": "نمایش بسته بندی",
"Log_View_Limit": "ورود مشخصات محدود",
- "Logged_out_of_other_clients_successfully": "از سیستم خارج از مشتریان دیگر موفقیت",
+ "Logged_out_of_other_clients_successfully": "از نشست های دیگر با موفقیت خارج شد",
"Login": "ورود",
"Login_with": "ورود با %s",
- "Logout": "خروج از سیستم",
- "Logout_Others": "خروج از دیگر وارد شده در مکان های",
- "Mail_Message_Invalid_emails": "شما ایمیل یک یا نامعتبر ارائه کرده اند: %s را",
- "Mail_Message_Missing_to": "شما باید یک یا چند کاربر را انتخاب کنید و یا ارائه یک یا چند آدرس ایمیل، با کاما جدا شده.",
- "Mail_Message_No_messages_selected_select_all": "هیچ پیامی برای شما انتخاب نشده. دوست دارید را انتخاب کنید همه پیام قابل مشاهده است؟",
+ "Logout": "خروج",
+ "Logout_Others": "خروج از نشست های دیگر",
+ "Mail_Message_Invalid_emails": "یک یا چند ایمیل نامعتبر ارائه کرده اید: %s",
+ "Mail_Message_Missing_to": "باید یک یا چند کاربر را انتخاب و یا یک یا چند ایمیل وارد کنید (جدا شده با کاما).",
+ "Mail_Message_No_messages_selected_select_all": "هیچ پیامی را انتخاب نکرده اید. می خواهید همه پیام های قابل مشاهده را انتخاب کنید)select all (؟",
"Mail_Messages": "پیام های پست الکترونیکی",
- "Mail_Messages_Instructions": "را انتخاب کنید که پیام های شما می خواهید برای ارسال از طریق ایمیل را با کلیک کردن پیام",
- "Mail_Messages_Subject": "در اینجا یک بخش انتخاب شده از %s پیام است",
- "Mailer": "نامه رسان",
+ "Mail_Messages_Instructions": "روی پیامی که می خواهید با ایمیل بفرستید کلیک کنید",
+ "Mail_Messages_Subject": "اینجا قسمتی از پیام های %s است",
+ "Mailer": "ایمیل کننده",
"Mailer_body_tags": "شما باید [unsubscribe] برای لینک لغو عضویت استفاده کنید. شما ممکن است [name]، [fname] برای نام کامل کاربر، نام اول یا نام خانوادگی، به ترتیب استفاده کنید، [lname]. ممکن است [email] برای ایمیل کاربر استفاده کنید.",
- "Mailing": "پستی",
- "Make_Admin": "ساختن مدیر",
- "Manager_added": "مدیر اضافه",
- "Manager_removed": "مدیر حذف",
- "Managing_assets": "مدیریت دارایی های",
- "Managing_integrations": "مدیریت یکپارچگی",
- "Mark_as_read": "به عنوان خوانده شده علامت بزن",
+ "Mailing": "ایمیل کردن",
+ "Make_Admin": "مدیر کردن",
+ "Manager_added": "مدیر اضافه شد",
+ "Manager_removed": "مدیر حذف شد",
+ "Managing_assets": "مدیریت دارایی ها",
+ "Managing_integrations": "مدیریت یکپارچگی ها",
+ "Mark_as_read": "تبدیل به خوانده شده",
+ "Mark_as_unread": "تبدیل به خوانده نشده",
"Markdown_Headers": "مدل های نشانه گذاری سرصفحه",
"Markdown_SupportSchemesForLink": "طرح های پشتیبانی مدل های نشانه گذاری برای لینک",
"Markdown_SupportSchemesForLink_Description": "جدا شده با کاما از طرح اجازه",
"Members_List": "فهرست کاربران",
- "Mentions": "اشاره",
- "Mentions_default": "اشاره (پیش فرض)",
+ "Mentions": "اشاره ها",
+ "Mentions_default": "اشاره ها (پیش فرض)",
"Message": "پیام",
"Message_AllowBadWordsFilter": "اجازه می دهد پیام کلمات بد فیلتر",
"Message_AllowDeleting": "اجازه می دهد پیام حذف",
@@ -668,12 +684,12 @@
"Message_AllowEditing": "اجازه می دهد پیام ویرایش",
"Message_AllowEditing_BlockEditInMinutes": "بلوک پیام ویرایش پس از (N) دقیقه",
"Message_AllowEditing_BlockEditInMinutesDescription": "را وارد کنید 0 برای غیر فعال کردن مسدود کردن.",
- "Message_AllowPinning": "اجازه می دهد پیام سنجاق",
+ "Message_AllowPinning": "اجازه دادن سنجاق کردن پیام",
"Message_AllowPinning_Description": "اجازه می دهد پیام به به هر یک از کانال های دوخته شود.",
"Message_AllowStarring": "اجازه می دهد پیام بازیگران",
"Message_AlwaysSearchRegExp": "همیشه با استفاده از استقبال میکنم جستجو",
"Message_AlwaysSearchRegExp_Description": "ما توصیه می کنیم به مجموعه ای `True` اگر زبان شما در پشتیبانی نمی جستجو در متن مانگودیبی .",
- "Message_AudioRecorderEnabled": "ضبط صوتی را فعال کنید",
+ "Message_AudioRecorderEnabled": "ضبط صوتی فعال شد",
"Message_AudioRecorderEnabledDescription": "نیاز به 'صوتی / WAV، فایل ها را به یک نوع رسانه مورد قبول در تنظیمات، آپلود فایل.",
"Message_BadWordsFilterList": "اضافه کردن کلمات بد را به لیست سیاه",
"Message_BadWordsFilterListDescription": "اضافه کردن فهرست جدا شده با کاما از کلمات بد برای فیلتر",
@@ -686,7 +702,7 @@
"Message_KeepHistory": "حفظ تاریخچه پیام",
"Message_MaxAll": "حداکثر اندازه کانال برای تمام پیام",
"Message_MaxAllowedSize": "حداکثر اندازه مجاز پیام",
- "Message_pinning": "پیام سنجاق",
+ "Message_pinning": "سنجاق پیام",
"Message_removed": "پیام حذف",
"Message_ShowDeletedStatus": "نمایش وضعیت حذف",
"Message_ShowEditedStatus": "نمایش وضعیت ویرایش",
@@ -704,14 +720,18 @@
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "روبات",
"minutes": "دقایق",
+ "Mobile": "تلفن همراه",
+ "Mobile_Notifications_Default_Alert": "هشدار پیشفرض اعلان های تلفن همراه",
"More_channels": "کانال های بیشتر",
"More_direct_messages": "پیام های مستقیم بیشتر",
"More_groups": "گروه بیشتر خصوصی",
"More_unreads": "unreads بیشتر",
"Msgs": "پیام های",
"multi": "چند",
- "Mute_someone_in_room": "کسی بیصدا کردن در اتاق",
- "Mute_user": "کاربران بیصدا",
+ "mute-user": "صامت کردن کاربر",
+ "mute-user_description": "مجوز صامت کردن کاربران دیگر در یک کانال",
+ "Mute_someone_in_room": "صامت کردن کسی در اتاق",
+ "Mute_user": "صامت کردن کاربر",
"Muted": "خاموش",
"My_Account": "حساب من",
"n_messages": " %s پیام",
@@ -726,37 +746,44 @@
"New_Department": "وزارت جدید",
"New_integration": "یکپارچه سازی جدید",
"New_logs": "سیاهههای مربوط جدید",
- "New_Message_Notification": "پیام جدید هشدار از طریق",
+ "New_Message_Notification": "اعلان پیام جدید",
"New_messages": "پیام های جدید",
- "New_password": "رمز عبور جدید",
+ "New_password": "کلمه عبور جدید",
"New_role": "نقش جدید",
- "New_Room_Notification": "هشدار از طریق اتاق جدید",
+ "New_Room_Notification": "اعلان اتاق جدید",
"No_channel_with_name_%s_was_found": "کانالی با نام \" %s\" را پیدا نشد!",
- "No_channels_yet": "شما بخشی از هر کانال نکرده است.",
- "No_direct_messages_yet": "شما هر گونه مکالمات آغاز نکرده است.",
+ "No_channels_yet": "شما در حال عضو هیچ کانالی نیستید.",
+ "No_direct_messages_yet": "بدون تماس مستقیم",
"No_Encryption": "بدون رمزگذاری",
"No_group_with_name_%s_was_found": "هیچ گروهی خصوصی با نام \" %s\" را پیدا نشد!",
"No_groups_yet": "شما هیچ گروه های خصوصی است.",
"No_livechats": "شما هیچ livechats.",
- "No_mentions_found": "بدون اشاره یافت",
- "No_pinned_messages": "هیچ پیام دوخته",
+ "No_mentions_found": "هیچ اشاره ای یافت نشد",
+ "No_pinned_messages": "پیام سنجاق شده ای نیست",
"No_results_found": "نتیجه ای پیدا نشد",
- "No_starred_messages": "بدون پیام های ستاره دار",
+ "No_starred_messages": "پیام ستاره داری نیست",
"No_user_with_username_%s_was_found": "هیچ کاربر با نام کاربری \" %s\" را پیدا نشد!",
"Node_version": "نسخه گره",
+ "None": "هیچکدام",
+ "Normal": "عادی",
"Not_authorized": "غیر مجاز",
"Not_Available": "در دسترس نیست",
"Not_found_or_not_allowed": "یافت نشد و یا مجاز نیست",
- "Nothing": "هیچ چی",
+ "Nothing": "هیچ چیز",
"Nothing_found": "چیزی پیدا نشد",
- "Notifications": "اطلاعیه",
+ "Notification_Desktop_Default_For": "نمایش اعلان های دسکتاپ برای",
+ "Notification_Duration": "مدت زمان اعلان",
+ "Notification_Mobile_Default_For": "Push Notificationهای تلفن همراه",
+ "Notifications": "اعلانات",
+ "Notifications_Sound_Volume": "میزان صدای اعلان ها",
"Notify_all_in_this_room": "به اطلاع همه در این اتاق",
"Num_Agents": "# نمایندگی",
"Number_of_messages": "تعداد پیام ها",
"OAuth_Application": "OAuth تأیید نرم افزار",
"OAuth_Applications": "نرم افزار OAuth تأیید",
"Objects": "اشیاء",
- "Off_the_record_conversation": "خارج از رکورد مکالمات",
+ "Off": "خاموش",
+ "Off_the_record_conversation": "مکالمه محرمانه (Off-the-record)",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "خارج از ضبط مکالمات برای مرورگر یا دستگاه شما در دسترس نیست.",
"Offline": "آفلاین",
"Offline_DM_Email": "شما مستقیم توسط __user__ پیام ارسال شده است",
@@ -766,7 +793,10 @@
"Offline_message": "آفلاین",
"Offline_success_message": "پیام موفقیت آفلاین",
"Offline_unavailable": "آفلاین در دسترس نیست",
+ "On": "روشن",
"Online": "آنلاین",
+ "Only_authorized_users_can_write_new_messages": "تنها اعضای خاص می توانند پیام جدید بنویسند",
+ "Only_On_Desktop": "حالت دسکتاپ (تنها با enter روی دسکتاپ می فرستد)",
"Only_you_can_see_this_message": "فقط شما میتوانید به این پیام را مشاهده",
"Oops!": "اوه",
"Open": "باز کن",
@@ -783,20 +813,20 @@
"OS_Type": "نوع سیستم عامل",
"OS_Uptime": "سیستم عامل آپ تایم",
"others": "دیگران",
- "OTR": "OTR",
- "OTR_is_only_available_when_both_users_are_online": "OTR تنها در دسترس است که هر دو کاربران آنلاین",
+ "OTR": "مکالمه محرمانه",
+ "OTR_is_only_available_when_both_users_are_online": "تنها زمانی در دسترس است که دو طرف آنلاین باشند.",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL نادیده گرفتن که فایل های آپلود شده است. این URL نیز برای دریافت مگر اینکه یک CDN استفاده شده است",
"Password": "کلمه عبور",
- "Password_Change_Disabled": "مدیر Rocket.Chat خود را تغییر کلمه عبور را غیرفعال کرده است",
+ "Password_Change_Disabled": "مدیر Rocket.chat تغییر کلمه عبور را غیر فعال کرده است",
"Password_changed_successfully": "رمز عبور با موفقیت تغییر",
"Past_Chats": "گفتگو های گذشته",
"Payload": "ظرفیت ترابری",
"People": "مردم",
- "Permalink": "permalink مشاهده مکالمات",
+ "Permalink": "لینک ثابت",
"Permissions": "مجوز",
- "Pin_Message": "پین پیام",
- "Pinned_a_message": "دوخته یک پیام:",
- "Pinned_Messages": "پیام دوخته",
+ "Pin_Message": "سنجاق کردن پیام",
+ "Pinned_a_message": "سنجاق کردن یک پیام:",
+ "Pinned_Messages": "پیام های سنجاق شده",
"PiwikAnalytics_siteId_Description": "شناسه سایت برای استفاده برای شناسایی این سایت. به عنوان مثال: 17",
"PiwikAnalytics_url_Description": "آدرس که در آن به Piwik ساکن، مطمئن شوید که شامل اسلش محاکمه. به عنوان مثال: //piwik.rocket.chat/",
"Placeholder_for_email_or_username_login_field": "نگهدارنده برای ایمیل و یا ورود نام کاربری درست",
@@ -814,23 +844,28 @@
"Please_select_enabled_yes_or_no": "لطفا یک گزینه برای فعال را انتخاب کنید",
"Please_wait": "لطفا صبر کنید",
"Please_wait_activation": "لطفا صبر کنید، این می تواند برخی از زمان.",
- "Please_wait_while_OTR_is_being_established": "لطفا صبر کنید در حالی که OTR در حال استقرار",
+ "Please_wait_while_OTR_is_being_established": "در حال استقرار OTR. لطفا منتظر بمانید",
"Please_wait_while_your_account_is_being_deleted": "لطفا صبر کنید در حالی که حساب شما در حال حذف ...",
- "Please_wait_while_your_profile_is_being_saved": "لطفا صبر کنید در حالی که مشخصات خود را در حال ذخیره ...",
+ "Please_wait_while_your_profile_is_being_saved": "ذخیره سازی نمایه شما. لطفا شکیبا باشید...",
"Port": "بندر",
"Post_as": "ارسال به عنوان",
"Post_to_Channel": "ارسال به کانال",
"Post_to_s_as_s": "ارسال به %s به عنوان %s ",
"Preferences": "تنظیمات",
- "Preferences_saved": "تنظیمات ذخیره شده",
+ "Preferences_saved": "تنظیمات ذخیره شد",
+ "preview-c-room": "پیش نمایش کانال عمومی",
"Privacy": "حریم خصوصی",
"Private": "خصوصی",
+ "Private_Channel": "کانال خصوصی",
"Private_Group": "گروه خصوصی",
"Private_Groups": "گروه های خصوصی",
"Private_Groups_list": "فهرست گروه های خصوصی",
- "Profile": "مشخصات",
- "Profile_saved_successfully": "مشخصات موفقیت ذخیره",
+ "Profile": "نمایه",
+ "Profile_details": "جزئیات نمایه",
+ "Profile_picture": "تصویر نمایه",
+ "Profile_saved_successfully": "نمایه با موفقیت ذخیره شد",
"Public": "عمومی",
+ "Public_Channel": "کانال عمومی",
"Push": "فشار دادن",
"Push_apn_cert": "APN بزنید",
"Push_apn_dev_cert": "APN نویس بزنید",
@@ -855,9 +890,10 @@
"Random": "تصادفی",
"Reacted_with": "واکنش نشان داد با",
"Reactions": "واکنش",
+ "Read_only_channel": "کانال فقط خواندنی",
"Record": "رکورد",
"Redirect_URI": "تغییر مسیر URI",
- "Refresh_keys": "کلید تازه کردن",
+ "Refresh_keys": "تجدید کلیدها",
"Refresh_your_page_after_install_to_enable_screen_sharing": "تازه کردن صفحه خود را پس از نصب برای فعال کردن اشتراک گذاری صفحه نمایش",
"Register": "ثبت نام کاربر جدید",
"Registration_Succeeded": "ثبت نام پیش",
@@ -870,6 +906,7 @@
"Remove_from_room": "حذف از اتاق",
"Remove_someone_from_room": "حذف فرد از اتاق",
"Removed": "حذف شده",
+ "Reply": "پاسخ دادن",
"Report_Abuse": "گزارش سوءاستفاده",
"Report_exclamation_mark": "گزارش!",
"Report_sent": "گزارش ارسال گردیده",
@@ -892,13 +929,14 @@
"room_changed_topic": "توسط __user_by__ __room_topic__: موضوع اتاق به تغییر",
"Room_has_been_deleted": "اتاق حذف شده است",
"Room_Info": "اطلاعات اتاق",
+ "room_is_blocked": "این اتاق مسدود شده است",
"Room_name_changed": "توسط __user_by__ __room_name__: نام اتاق به تغییر",
"Room_name_changed_successfully": "نام اتاق موفقیت تغییر",
"Room_not_found": "اتاق یافت نشد",
"Room_topic_changed_successfully": "موضوع اتاق موفقیت تغییر",
"Room_type_changed_successfully": "نوع اتاق موفقیت تغییر",
"Room_unarchived": "اتاق بایگانی خارج شد",
- "Room_uploaded_file_list": "لیست فایل های",
+ "Room_uploaded_file_list": "لیست فایل ها",
"Room_uploaded_file_list_empty": "بدون فایل های موجود.",
"Rooms": "اتاق",
"Running_Instances": "اجرای نمونههای",
@@ -909,21 +947,22 @@
"SAML_Custom_Generate_Username": "تولید نام کاربری",
"SAML_Custom_Issuer": "صادرکننده سفارشی",
"SAML_Custom_Provider": "ارائه دهنده سفارشی",
- "Save": "صرفه جویی",
+ "Save": "ذخیره",
"Save_changes": "ذخیره تغییرات",
- "Save_Mobile_Bandwidth": "صرفه جویی پهنای باند موبایل",
+ "Save_Mobile_Bandwidth": "صرفه جویی پهنای باند تلفن همراه",
"Save_to_enable_this_action": "ذخیره برای فعال کردن این اقدام",
- "Saved": "ذخیره",
- "Saving": "صرفه جویی در",
+ "Saved": "ذخیره شد",
+ "Saving": "در حال ذخیره سازی",
"Scope": "محدوده",
"Screen_Share": "صفحه نمایش به اشتراک",
"Script_Enabled": "اسکریپت فعال",
- "Search": "جستجو کردن",
+ "Search": "جست و جو",
"Search_by_username": "جستجو بر اساس نام کاربری",
- "Search_Messages": "پیام های جستجو",
+ "Search_Messages": "جست و جوی پیام ها",
"Search_Private_Groups": "جستجوی گروه ها شخصی",
"seconds": "ثانیه",
"Secret_token": "علامت رمز",
+ "Security": "امنیت",
"Select_a_department": "انتخاب بخش",
"Select_an_avatar": "یک نماد را انتخاب کنید",
"Select_file": "فایل را انتخاب کنید",
@@ -933,8 +972,8 @@
"Selected_agents": "عوامل انتخاب شده",
"Send": "ارسال",
"Send_a_message": "ارسال یک پیام",
- "Send_a_test_mail_to_my_user": "ارسال یک ایمیل به آزمون کاربر من",
- "Send_a_test_push_to_my_user": "ارسال یک فشار آزمون به کاربر من",
+ "Send_a_test_mail_to_my_user": "ارسال یک ایمیل تستی به من",
+ "Send_a_test_push_to_my_user": "ارسال یک push تستی به من",
"Send_confirmation_email": "ارسال ایمیل تایید",
"Send_data_into_RocketChat_in_realtime": "ارسال داده ها را به Rocket.Chat در زمان واقعی است.",
"Send_email": "ایمیل بفرست",
@@ -954,14 +993,15 @@
"Settings": "تنظیمات",
"Settings_updated": "تنظیمات به روز رسانی",
"Should_be_a_URL_of_an_image": "باید یک URL از یک تصویر.",
- "Should_exists_a_user_with_this_username": "کاربر در حال حاضر باید وجود داشته باشد.",
- "Show_all": "نمایش همه",
+ "Should_exists_a_user_with_this_username": "این کاربر باید وجود داشته باشد.",
+ "Show_all": "همه را نشان بده",
"Show_more": "بیشتر نشان بده، اطلاعات بیشتر",
- "Show_only_online": "نمایش فقط آنلاین",
+ "Show_only_online": "فقط آنلاین ها را نشان بده",
"Show_preregistration_form": "فرم پیش ثبت نام",
"Showing_archived_results": " نمایش نتایج: از آرشیو %s را
",
- "Showing_online_users": "نمایش __total_showing__ از __total__ کاربران",
+ "Showing_online_users": "نمایش: __total_showing__, آنلاین: __online__, تعداد کل: __total__",
"Showing_results": " نمایش نتایج: از %s را
",
+ "Sidebar_list_mode": "شیوه نمایش کانال های نوار کناری",
"since_creation": "از %s را",
"Site_Name": "نام سایت",
"Site_Url": "آدرس سایت",
@@ -984,15 +1024,16 @@
"SMTP_Username": "SMTP نام کاربری",
"Sound": "صدا",
"SSL": "SSL",
- "Star_Message": "پیام ستاره",
+ "Star_Message": "ستاره دار کردن پیام",
"Starred_Messages": "پیام های ستاره دار",
"Start_audio_call": "شروع تماس صوتی",
"Start_Chat": "شروع چت",
"Start_of_conversation": "شروع مکالمه",
- "Start_OTR": "شروع OTR",
+ "Start_OTR": "شروع مکالمه محرنامه",
"Start_video_call": "شروع تماس ویدیویی",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "شروع با %s برای کاربر یا %s برای کانال. به عنوان مثال: %s یا %s",
"Started_At": "آغاز شده در",
+ "Started_a_video_call": "یک مکالمه ویدیویی را آغاز کرد",
"Statistics": "آمار",
"Statistics_reporting": "ارسال آمار به Rocket.Chat",
"Statistics_reporting_Description": "با ارسال آمار خود را، شما به ما کمک کند شناسایی که چگونه بسیاری از موارد از Rocket.Chat مستقر هستند، و همچنین چقدر خوب سیستم رفتار، بنابراین ما بیشتر می توانید آن را بهبود بخشد. نگران نباشید، به عنوان هیچ اطلاعات کاربر فرستاده می شود و تمام اطلاعات که دریافت می کنیم محرمانه نگه داشته.",
@@ -1023,44 +1064,46 @@
"Sync_Users": "کاربران همگام سازی",
"Tag": "برچسب",
"Test_Connection": "اتصال تست",
- "Test_Desktop_Notifications": "آزمون های دسک تاپ",
+ "Test_Desktop_Notifications": "امتحان اعلان های دسکتاپ",
"Thank_you_exclamation_mark": "متشکرم!",
"Thank_you_for_your_feedback": "با تشکر از شما برای نظرات شما",
"The_application_name_is_required": "نام نرم افزار مورد نیاز است",
- "The_channel_name_is_required": "نام کانال مورد نیاز است",
+ "The_channel_name_is_required": "نام کانال نیاز است",
"The_emails_are_being_sent": "ایمیل در حال ارسال.",
"The_field_is_required": "زمینه به %s مورد نیاز است.",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "تغییر اندازه تصویر به کار نخواهد کرد زیرا ما نمی توانیم تشخیص ImageMagick را یا GraphicsMagick بر روی سرور خود نصب شده است.",
"The_redirectUri_is_required": "redirectUri مورد نیاز است",
"The_server_will_restart_in_s_seconds": "سرور در %s ثانیه راه اندازی مجدد خواهد",
"The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "تنظیمات %s در به %s پیکربندی و شما از %s دسترسی!",
- "The_user_will_be_removed_from_s": "کاربر خواهد شد از %s حذف",
- "The_user_wont_be_able_to_type_in_s": "کاربر نمی خواهد قادر به تایپ در %s",
+ "The_user_will_be_removed_from_s": "کاربر از %s حذف خواهد شد",
+ "The_user_wont_be_able_to_type_in_s": "کاربر قادر به نوشتن در %s نخواهد بود",
"Theme": "موضوع",
"theme-color-content-background-color": "محتوای رنگ پس زمینه",
+ "theme-color-custom-scrollbar-color": "سفارشی نمایشمیلهلغزش رنگ",
+ "theme-color-info-font-color": "اطلاعات رنگ قلم",
+ "theme-color-link-font-color": "لینک رنگ قلم",
+ "theme-color-primary-action-color": "رنگ اولیه عملیات",
"theme-color-primary-background-color": "اولیه رنگ پس زمینه",
"theme-color-primary-font-color": "اولیه رنگ قلم",
"theme-color-secondary-background-color": "ثانویه رنگ پس زمینه",
"theme-color-secondary-font-color": "ثانویه رنگ قلم",
- "theme-color-tertiary-background-color": "دوران سوم رنگ پس زمینه",
- "theme-color-tertiary-font-color": "دوران سوم رنگ قلم",
- "theme-color-link-font-color": "لینک رنگ قلم",
- "theme-color-info-font-color": "اطلاعات رنگ قلم",
- "theme-color-custom-scrollbar-color": "سفارشی نمایشمیلهلغزش رنگ",
"theme-color-status-away": "وضعیت دور رنگ",
"theme-color-status-busy": "وضعیت مشغول رنگ",
"theme-color-status-offline": "وضعیت: آفلاین رنگ",
"theme-color-status-online": "وضعیت رنگ",
+ "theme-color-tertiary-background-color": "دوران سوم رنگ پس زمینه",
+ "theme-color-tertiary-font-color": "دوران سوم رنگ قلم",
"theme-color-unread-notification-color": "خوانده نشده اطلاعیه رنگ",
"theme-custom-css": "CSS سفارشی",
"There_are_no_agents_added_to_this_department_yet": "هیچ عوامل اضافه شده به این بخش وجود ندارد.",
"There_are_no_integrations": "هیچ یکپارچگی وجود دارد",
"There_are_no_users_in_this_role": "هیچ کاربری در این نقش وجود دارد.",
"This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "این ایمیل قبلا استفاده شده است و تأیید نشده است. لطفا رمز عبور خود را تغییر دهید.",
- "This_is_a_desktop_notification": "این اعلان دسکتاپ",
+ "This_is_a_desktop_notification": "این یک اعلان دسکتاپ است",
"This_is_a_push_test_messsage": "این messsage آزمون فشار است",
"This_room_has_been_archived_by__username_": "این اتاق شده است _نام کاربری_ آرشیو",
"This_room_has_been_unarchived_by__username_": "این اتاق شده است _نام کاربری_ از بایگانی خارج شد",
+ "Thursday": "پنج شنبه",
"Time_in_seconds": "زمان در ثانیه",
"Title": "عنوان",
"Title_bar_color": "رنگ نوار عنوان",
@@ -1074,80 +1117,93 @@
"Trigger_removed": "ماشه حذف",
"Trigger_Words": "کلمات محرک",
"Triggers": "محرک های",
- "True": "درست",
+ "True": "بله",
+ "Two-factor_authentication": "تایید هویت دومرحله ای",
+ "Two-factor_authentication_disabled": "تایید هویت دومرحله ای غیر فعال است",
+ "Two-factor_authentication_enabled": "تایید هویت دومرحله ای فعال است",
+ "Two-factor_authentication_is_currently_disabled": "تایید هویت دومرحله ای فعلا غیر فعال است",
+ "Two-factor_authentication_native_mobile_app_warning": "هشدار: وقتی این را فعال کنید دیگر قادر به ورود از طریق برنامه های موبایل نخواهید بود.",
"Type": "نوع",
"Type_your_email": "نوع ایمیل خود را",
"Type_your_message": "نوع پیام خود را",
"Type_your_name": "نامتان را بنویسید",
- "Type_your_new_password": "رمز عبور جدید خود را تایپ کنید",
+ "Type_your_new_password": "کلمه عبور جدید را وارد کنید",
"UI_DisplayRoles": "نقش ها",
- "UI_Merge_Channels_Groups": "ادغام گروه های خصوصی با کانال",
+ "UI_Merge_Channels_Groups": "ادغام گروه های خصوصی با کانال ها",
"Unarchive": "لغو بایگانی",
+ "Unblock_User": "آشتی کردن با کاربر",
"Unmute_someone_in_room": "کسی باصدا کردن در اتاق",
- "Unmute_user": "کاربران باصدا کردن",
+ "Unmute_user": "غیر صامت کردن کاربر",
"Unnamed": "که نامش ذکر نشده",
- "Unpin_Message": "پیام لغو پین",
+ "Unpin_Message": "حذف سنجاق",
"Unread_Rooms": "اتاق خوانده نشده",
"Unread_Rooms_Mode": "حالت اتاق خوانده نشده",
+ "Unread_Tray_Icon_Alert": "نمایش هشدار Tray Icon برای پیام های خوانده نشده",
"Unstar_Message": "حذف ستاره",
"Upload_file_question": "آپلود فایل؟",
"Uploading_file": "آپلود فایل ...",
"Uptime": "آپ تایم",
"URL": "URL",
- "Use_account_preference": "استفاده از همه حساب",
- "Use_Emojis": "استفاده از Emojis",
- "Use_initials_avatar": "استفاده از حروف اول نام کاربری خود را",
+ "URL_room_prefix": "پیشوند آدرس اتاق",
+ "Use_account_preference": "استفاده از تنظیمات حساب",
+ "Use_Emojis": "استفاده از شکلک ها",
+ "Use_Global_Settings": "استفاده از تنظیمات عمومی",
+ "Use_initials_avatar": "استفاده از حروف اول نام کاربری",
"Use_service_avatar": "استفاده از %s آواتار ها",
"Use_this_username": "با استفاده از این نام کاربری",
"Use_uploaded_avatar": "استفاده از نماد های آپلود",
"Use_url_for_avatar": "استفاده از URL برای نماد",
- "User__username__is_now_a_moderator_of__room_name_": "_نام کاربری_ کاربر در حال حاضر به ناظم از __room_name__",
- "User__username__is_now_a_owner_of__room_name_": "_نام کاربری_ کاربر در حال حاضر صاحب __room_name__",
- "User__username__removed_from__room_name__moderators": "_نام کاربری_ کاربر از مدیران __room_name__ حذف",
- "User__username__removed_from__room_name__owners": "_نام کاربری_ کاربر از صاحبان __room_name__ حذف",
- "User_added": "اضافه شده توسط کاربر",
- "User_added_by": "__user_added__ کاربر اضافه شده توسط __user_by__. ",
+ "Use_User_Preferences_or_Global_Settings": "استفاده از تنظیمات حساب یا تنظیمات کلی",
+ "User__username__is_now_a_moderator_of__room_name_": "__username__ از حالا مدیر __room_name__ است",
+ "User__username__is_now_a_owner_of__room_name_": "__username__ از الان صاحب __room_name__ است",
+ "User__username__removed_from__room_name__moderators": "__username__ از __room_name__ مدیران حذف شد",
+ "User__username__removed_from__room_name__owners": "__username__ از __room_name__ مالکان حذف شد",
+ "User_added": "کاربر اضافه شد",
+ "User_added_by": "کاربر __user_by__ __user_added__ را اضافه کرد.",
"User_added_successfully": "کاربر با موفقیت اضافه شد",
- "User_doesnt_exist": "کاربری با نام `@ %s` وجود دارد.",
+ "User_doesnt_exist": "کاربری با نام `@%s` وجود ندارد.",
"User_has_been_activated": "کاربر فعال شده است",
"User_has_been_deactivated": "کاربر غیر فعال شده است",
"User_has_been_deleted": "کاربر حذف شده است",
- "User_has_been_muted_in_s": "کاربر شده است به در %s خاموش",
+ "User_has_been_muted_in_s": "کاربر در %s صامت شده است",
"User_has_been_removed_from_s": "کاربر از %s حذف شده است",
"User_Info": "اطلاعات کاربر",
- "User_is_no_longer_an_admin": "کاربر دیگر یک مدیر",
- "User_is_now_an_admin": "کاربر در حال حاضر به یک مدیر",
- "User_joined_channel": "کانال پیوسته است.",
- "User_joined_channel_female": "کانال پیوسته است.",
- "User_joined_channel_male": "کانال پیوسته است.",
+ "User_is_no_longer_an_admin": "کاربر دیگر مدیر نیست",
+ "User_is_now_an_admin": "کاربر حالا یک مدیر است",
+ "User_joined_channel": "به کانال پیوسته است.",
+ "User_joined_channel_female": "به کانال پیوسته است.",
+ "User_joined_channel_male": "به کانال پیوسته است.",
"User_left": "کانال را ترک کرده است.",
"User_left_female": "کانال را ترک کرده است.",
"User_left_male": "کانال را ترک کرده است.",
- "User_logged_out": "کاربر وارد شده است را",
+ "User_logged_out": "کاربر خارج شده است",
"User_management": "مدیریت کاربر",
"User_muted_by": "__user_muted__ کاربر خاموش شده توسط __user_by__. ",
"User_not_found": "کاربر یافت نشد",
- "User_not_found_or_incorrect_password": "کاربر یافت نشد و یا رمز عبور اشتباه",
- "User_or_channel_name": "کاربر یا کانال نام",
- "User_removed": "کاربر حذف",
- "User_removed_by": "__user_removed__ کاربر حذف شده توسط __user_by__. ",
+ "User_not_found_or_incorrect_password": "کاربر یافت نشد یا کلمه عبور اشتباه است",
+ "User_or_channel_name": "نام کاربر یا کانال",
+ "User_removed": "کاربر حذف شد",
+ "User_removed_by": "کاربر __user_by__ __user_removed__ را حذف کرد.",
"User_Settings": "تنظیمات کاربر",
"User_unmuted_by": "__user_unmuted__ کاربر لغو شد توسط __user_by__. ",
- "User_unmuted_in_room": "کاربر نادیده در اتاق",
- "User_updated_successfully": "کاربر با موفقیت به روز",
+ "User_unmuted_in_room": "کاربر در اتاق غیر صامت شد",
+ "User_updated_successfully": "کاربر با موفقیت به روز شد",
+ "User_uploaded_file": "یک فایل آپلود شد",
+ "User_uploaded_image": "یک عکس آپلود شد",
"Username": "نام کاربری",
"Username_and_message_must_not_be_empty": "نام کاربری و پیام نباید خالی باشد.",
"Username_cant_be_empty": "نام کاربری نمی تواند خالی باشد",
- "Username_Change_Disabled": "مدیر Rocket.Chat خود را تغییر نام های کاربری را غیرفعال کرده است",
- "Username_denied_the_OTR_session": "_نام کاربری_ را تکذیب کرد جلسه OTR",
+ "Username_Change_Disabled": "مدیر Rocket.chat تغییر نام کاربری را غیر فعال کرده است",
+ "Username_denied_the_OTR_session": "__username__ نشست OTR را رد کرد",
"Username_description": "نام کاربری استفاده شده است به دیگران اجازه می دهد به شما اشاره در پیام است.",
"Username_doesnt_exist": "نام کاربری ` %s` وجود ندارد.",
- "Username_ended_the_OTR_session": "_نام کاربری_ به پایان رسید جلسه OTR",
+ "Username_ended_the_OTR_session": "__username__ نشست OTR را بست",
"Username_invalid": " %s است یک نام کاربری معتبر نیست، استفاده از تنها حروف، اعداد، نقطه، خط فاصله و زیرین",
- "Username_is_already_in_here": "`@ %s` در حال حاضر در اینجا.",
- "Username_is_not_in_this_room": "کاربر `# %s` است در این اتاق نیست.",
+ "Username_is_already_in_here": "`@%s` در حال حاضر اینجاست.",
+ "Username_is_not_in_this_room": "`#%s` در این اتاق نیست.",
+ "Username_Placeholder": "لطفا نام کاربران را وارد کنید...",
"Username_title": "ثبت نام نام کاربری",
- "Username_wants_to_start_otr_Do_you_want_to_accept": "_نام کاربری_ می خواهد برای شروع OTR. آیا می خواهید به قبول می کنید؟",
+ "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ درخواست OTR می دهد. آیا قبل می کنید؟",
"Users": "کاربران",
"Users_in_role": "کاربران در نقش",
"UTF8_Names_Slugify": "UTF8 نام slugify را",
@@ -1156,10 +1212,15 @@
"Verification_email_sent": "ایمیل تأیید",
"Verified": "تایید شده",
"Version": "نسخه",
- "Video_Chat_Window": "ویدئو چت",
+ "Video_Chat_Window": "ویدیو چت",
+ "Video_Conference": "ویدیو کنفرانس",
+ "Video_message": "پیام ویدویی",
+ "Videocall_declined": "تماس ویدیویی رد شد",
+ "Videocall_enabled": "تماس ویدیویی فعال شد",
+ "view-c-room": "مشاهده کانال عمومی",
"View_All": "مشاهده همه",
"View_Logs": "نمایش سیاهههای مربوط",
- "View_mode": "حالت نمایش",
+ "View_mode": "شیوه نمایش",
"View_mode_info": "این تغییر مقدار از پیام های فضایی را بر روی صفحه نمایش.",
"Viewing_room_administration": "دولت اتاق نمایش",
"Visibility": "دید",
@@ -1170,55 +1231,63 @@
"Visitor_page_URL": "URL صفحه های بازدید کننده",
"Visitor_time_on_site": "زمان بازدید کنندگان در سایت",
"Wait_activation_warning": "قبل از اینکه شما می توانید وارد شوید، حساب خود را باید به صورت دستی توسط مدیر فعال می شود.",
+ "Warnings": "اخطارها",
"We_are_offline_Sorry_for_the_inconvenience": "ما آنلاین نیست. با عرض پوزش برای ناراحتی.",
"We_have_sent_password_email": "ما به شما یک ایمیل با دستورالعمل تنظیم مجدد رمز عبور ارسال کرده اند. اگر شما یک ایمیل را دریافت نمی در مدت کوتاهی، لطفا دوباره و دوباره امتحان کنید.",
"We_have_sent_registration_email": "ما به شما یک ایمیل برای تایید ثبت نام خود را فرستاده اند. اگر شما یک ایمیل را دریافت نمی در مدت کوتاهی، لطفا دوباره و دوباره امتحان کنید.",
- "Webhook_URL": "URL Webhook",
+ "Webhook_URL": "آدرس Webhook",
"Webhooks": "Webhooks",
"WebRTC_Enable_Channel": "فعال کردن برای کانال های عمومی",
"WebRTC_Enable_Direct": "فعال کردن برای پیام های مستقیم",
"WebRTC_Enable_Private": "فعال کردن برای کانال خصوصی",
"WebRTC_Servers": "سرور بی حس کردن / روشن",
"WebRTC_Servers_Description": "یک لیست از بی حس کردن و روشن کردن سرور جداشده با کاما. رمز عبور @ بی حس کردن:: نام کاربری و رمز پورت در فرمت `نام کاربری اجازه میزبان: port` یا` نام کاربری: رمز عبور @ نوبه خود: میزبان: port`.",
+ "Wednesday": "چهارشنبه",
"Welcome": "خوش آمدید به %s. ",
"Welcome_to_the": "خوش آمدید به",
"Why_do_you_want_to_report_question_mark": "چرا شما می خواهید به گزارش؟",
"will_be_able_to": "قادر خواهد بود تا",
+ "Would_you_like_to_return_the_inquiry": "تمایل دارید به پرس و جو بازگردید؟",
"Yes": "بله",
+ "Yes_archive_it": "بلی بایگانی کن",
"Yes_clear_all": "بله، پاک کردن تمام!",
"Yes_delete_it": "بله، آن را حذف کنید!",
"Yes_hide_it": "بله، آن را پنهان!",
"Yes_leave_it": "بله، آن را ترک کنید!",
- "Yes_mute_user": "بله، کاربر قطع!",
- "Yes_remove_user": "بله، حذف کاربر!",
+ "Yes_mute_user": "بله کاربر را صامت کن!",
+ "Yes_remove_user": "بله، کاربر را حذف کن!",
+ "Yes_unarchive_it": "بلی از بایگانی خارج کن",
"You": "شما",
"you_are_in_preview_mode_of": "شما در حالت پیش نمایش از کانال # __room_name__ هستند",
"You_are_logged_in_as": "شما وارد شدید با عنوان",
"You_are_not_authorized_to_view_this_page": "شما به این صفحه مجاز است.",
"You_can_change_a_different_avatar_too": "شما می توانید نماد مورد استفاده برای ارسال از این ادغام را لغو کنید.",
- "You_can_search_using_RegExp_eg": "شما می توانید با استفاده از استقبال میکنم جستجو کنید. به عنوان مثال",
+ "You_can_search_using_RegExp_eg": "می توانید با RegExp جست و جو کنید. مثال:",
"You_can_use_an_emoji_as_avatar": "شما همچنین می توانید از Emoji به عنوان یک نماد استفاده کنید.",
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "شما می توانید webhooks به راحتی ادغام livechat با CRM خود استفاده کنید.",
"You_cant_leave_a_livechat_room_Please_use_the_close_button": "شما می توانید یک اتاق livechat در ترک نمی کند. لطفا، با استفاده از دکمه نزدیک است.",
"You_have_been_muted": "شما نادیده گرفته شده است و نمی تواند در این اتاق صحبت",
"You_have_not_verified_your_email": "شما ایمیل خود را تایید نمی کند.",
"You_have_successfully_unsubscribed": "شما با موفقیت از فهرست Mailling ما لغو شده است.",
+ "You_must_join_to_view_messages_in_this_channel": "شما برای دیدن پیامهای این کانال باید عضو شوید",
"You_need_confirm_email": "شما نیاز به تایید ایمیل خود را برای ورود!",
"You_need_install_an_extension_to_allow_screen_sharing": "شما نیاز به نصب یک فرمت به اجازه به اشتراک گذاری صفحه نمایش",
"You_need_to_change_your_password": "شما نیاز به تغییر رمز عبور خود را",
"You_need_to_type_in_your_password_in_order_to_do_this": "شما نیاز به تایپ رمز عبور خود را به منظور انجام این کار!",
"You_need_to_type_in_your_username_in_order_to_do_this": "شما نیاز به تایپ در نام کاربری خود را به منظور انجام این کار!",
- "You_need_to_verifiy_your_email_address_to_get_notications": "شما نیاز به تأیید آدرس ایمیل خود را برای دریافت اطلاعیه",
+ "You_need_to_verifiy_your_email_address_to_get_notications": "برای دریافت اعلان ها از طریق ایمیل باید آن را تایید کنید",
"You_need_to_write_something": "شما نیاز به نوشتن چیزی!",
"You_should_inform_one_url_at_least": "شما باید حداقل یک URL را تعریف کنیم.",
"You_should_name_it_to_easily_manage_your_integrations": "شما باید نام آن را به راحتی مدیریت یکپارچگی خود را.",
"You_will_not_be_able_to_recover": "شما نمی خواهد قادر به بازیابی این ارسال!",
"You_will_not_be_able_to_recover_file": "شما نمی خواهد قادر به بازیابی این فایل!",
- "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "شما اطلاعیه ایمیل دریافت نمی کند چرا که شما از پست الکترونیک خود را تایید نمی کند.",
+ "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "چون ایمیل خود را تایید نکرده اید اعلان های ایمیلی را دریافت نمی کنید",
"Your_email_has_been_queued_for_sending": "ایمیل شما برای ارسال صف",
"Your_entry_has_been_deleted": "ورود شما حذف شده است.",
"Your_file_has_been_deleted": "فایل شما حذف شده است.",
"Your_mail_was_sent_to_s": "پست الکترونیکی خود را به %s ارسال شد",
+ "your_message": "پیام شما",
+ "your_message_optional": "پیام شما(انتخابی)",
"Your_password_is_wrong": "رمز عبور خود را اشتباه است!",
"Your_push_was_sent_to_s_devices": "فشار خود را به دستگاه %s را ارسال شد"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/fi.i18n.json b/packages/rocketchat-i18n/i18n/fi.i18n.json
index 2b0f459d43b82..e668e23641179 100644
--- a/packages/rocketchat-i18n/i18n/fi.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fi.i18n.json
@@ -6,7 +6,8 @@
"403": "Kielletty",
"500": "Sisäinen palvelinvirhe",
"@username": "@käyttäjä",
- "__username__is_no_longer__role__defined_by__user_by_": "__username__ ei ole enää __role__ (__user_by__)",
+ "@username_message": "@käyttäjä ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ ei ole enää __role__ (__user_by__ toimesta)",
"__username__was_set__role__by__user_by_": "__user_by__ muutti käyttäjän __username__ rooliksi __role__ ",
"Accept": "Hyväksy",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Hyväksy sisääntulevat livechatit vaikka agentteja ei ole paikalla",
@@ -16,27 +17,27 @@
"Accessing_permissions": "Pääsyn käyttöoikeudet",
"Account_SID": "Tilin SID",
"Accounts": "Käyttäjätilit",
+ "Accounts_AllowAnonymousRead": "Salli lukeminen anonyymeille",
+ "Accounts_AllowAnonymousWrite": "Salli kirjoitus anonyymeille",
"Accounts_AllowDeleteOwnAccount": "Salli käyttäjien poistaa oma tunnuksensa",
"Accounts_AllowedDomainsList": "Lista sallituista domaineista",
"Accounts_AllowedDomainsList_Description": "Pilkuilla eroteltu luettelo sallituista verkkotunnuksia",
- "Accounts_AllowEmailChange": "Salli sähköpostin vaihtaminen",
+ "Accounts_AllowEmailChange": "Salli sähköpostiosoitteen vaihtaminen",
"Accounts_AllowPasswordChange": "Salli salasanan vaihto",
"Accounts_AllowUserAvatarChange": "Salli käyttäjän avatarin muutos",
"Accounts_AllowUsernameChange": "Salli käyttäjätunnuksen muuttaminen",
"Accounts_AllowUserProfileChange": "Salli käyttäjän profiilin muutos",
"Accounts_AvatarResize": "Muuta avatarien kokoa",
"Accounts_AvatarSize": "Avatarin koko",
- "Accounts_AvatarStorePath": "Avatarin tallennuspolku",
- "Accounts_AvatarStoreType": "Avatarien tallennusmuoto",
- "Accounts_BlockedDomainsList": "Estettyjen verkkotunnusten lista",
- "Accounts_BlockedDomainsList_Description": "Pilkuilla eroteltu lista estetyistä verkkotunnuksista",
+ "Accounts_BlockedDomainsList": "Estettyjen domainien lista",
+ "Accounts_BlockedDomainsList_Description": "Pilkuilla eroteltu lista estetyistä domaineista",
"Accounts_BlockedUsernameList": "Estettyjen käyttäjätunnusten lista",
- "Accounts_BlockedUsernameList_Description": "Pilkuilla erotettu luettelo estetyistä käyttäjätunnuksia (kirjainkoosta riippumaton)",
+ "Accounts_BlockedUsernameList_Description": "Pilkuilla erotettu luettelo estetyistä käyttäjätunnuksista (kirjainkoosta riippumaton)",
"Accounts_denyUnverifiedEmail": "Estä vahvistamaton sähköpostiosoite",
"Accounts_EmailVerification": "Sähköpostiosoitteen vahvistaminen",
"Accounts_EmailVerification_Description": "Varmista, että käytät oikeita SMTP-asetuksia tätä ominaisuutta varten",
"Accounts_Enrollment_Email": "Kirjautumissähköposti",
- "Accounts_Enrollment_Email_Default": " Tervetuloa sivustolle [Site_Name] Siirry osoitteeseen [Site_URL] ja kokeile parasta avoimen lähdekoodin chat ratkaisua tänään!
",
+ "Accounts_Enrollment_Email_Default": " Tervetuloa sivustolle [Site_Name] Siirry osoitteeseen [Site_URL] ja kokeile parasta avoimen lähdekoodin chat ratkaisua tänään!
",
"Accounts_Enrollment_Email_Description": "Voit käyttää seuraavia placeholdereita [name], [fname], [lname] käyttäjän koko nimen, etunimen tai sukunimen paikalla. [Site_Name] ja [Site_URL] sivuston nimen ja osoitteen paikalla ",
"Accounts_Enrollment_Email_Subject_Default": "Tervetuloa sivustolle [Site_Name]",
"Accounts_Iframe_api_method": "API metodi",
@@ -89,9 +90,9 @@
"Accounts_OAuth_Twitter_id": "Twitter ID",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress-kirjautuminen",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress ID",
- "Accounts_OAuth_Wordpress_secret": "Wordpress Secret",
+ "Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Salasanan nollaus",
"Accounts_Registration_AuthenticationServices_Enabled": "Rekisteröinti autentikointipalveluiden kautta",
"Accounts_RegistrationForm": "Rekisteröintilomake",
@@ -105,7 +106,7 @@
"Accounts_ShowFormLogin": "Näytä lomakepohjainen kirjautuminen",
"Accounts_UseDefaultBlockedDomainsList": "Käytä Estettyjen Verkkotunnusten Oletuslistaa",
"Accounts_UseDNSDomainCheck": "Varmista Toimialueen DNS",
- "Accounts_UserAddedEmail_Default": " Tervetuloa sivustolle [Site_Name] Mene [Site_URL] ja kokeile parasta avoimen lähdekoodin chat ratkaisua tänään!
Voit kirjautua käyttäen sähköpostiasi: [email] ja salasanaa: [password]. Voit joutua muuttamaan salasanasi ensimmäisen kirjautumisen jälkeen.
",
+ "Accounts_UserAddedEmail_Default": " Tervetuloa sivustolle [Site_Name] Mene [Site_URL] ja kokeile parasta avoimen lähdekoodin chat ratkaisua tänään!
Voit kirjautua käyttäen sähköpostiasi: [email] ja salasanaa: [password]. Voit joutua muuttamaan salasanasi ensimmäisen kirjautumisen jälkeen.
",
"Accounts_UserAddedEmail_Description": "Voit käyttää seuraavia placeholdereita: [name], [fname], [lname] käyttäjän koko nimen, etunimen tai sukunimen paikalla. [email] käyttäjän sähköpostiosoitteena. [password] käyttäjän salasanana. [Site_Name] ja [Site_URL] sivuston nimen ja osoitteen paikalla. ",
"Accounts_UserAddedEmailSubject_Default": "Sinut on lisätty sivustolle [Site_Name]",
"Activate": "Aktivoi",
@@ -213,6 +214,7 @@
"Cancel": "Peruuta",
"Cancel_message_input": "Peruuta",
"Cannot_invite_users_to_direct_rooms": "Et voi kutsua käyttäjiä yksityisviesteihin",
+ "CAS_Sync_User_Data_FieldMap_Description": "Käytä tätä JSON syötettä rakentaessa sisäiset määritteet (avain) ulkoisista määritteistä (arvo). Ulkoisien määritteiden nimet suljettuna '%' merkkien väliin lisätään arvo teksteihin. Esimerkiksi, `{\"email\":\"%email%\", \"name\":\"%firstname%, %lastname%\"}` Määrite kartta on aina lisätty. CAS 1.0:ssa vain `username` määrite on saatavilla. Saatavilla olevat sisäiset määritteet ovat: username, name, email, rooms; rooms on pilkuilla erotettu lista huoneista joihin liittyä käyttäjää lisättäessä, esimerkiksi: {\"rooms\": \"%team%,%department%\"} liittyisi CAS käyttäjät niitä luotaessa heidän tiimi ja osasto kanavalle.",
"CDN_PREFIX": "CDN etuliite",
"Certificates_and_Keys": "Sertifikaatit ja avaimet",
"Changing_email": "Vaihdetaan sähköposti",
@@ -466,6 +468,7 @@
"Give_a_unique_name_for_the_custom_oauth": "Anna yksilöllinen nimi mukautettua oauth varten",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Anna sovelluksen nimi. Käyttäjät näkevät tämän.",
"Global": "Yleinen",
+ "Global_Search": "Hae kaikilta kanavilta",
"GoogleTagManager_id": "Google Tag Manager Id",
"Guest_Pool": "Vieraspooli",
"Hash": "Hash",
@@ -589,24 +592,12 @@
"Layout_Terms_of_Service": "Käyttöehdot",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Mukautettu domain-haku",
- "LDAP_Custom_Domain_Search_Description": "JSONin palanen, joka säätelee bindin ja yhteyden tietoja ja on muotoa: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Oletusverkkotunnus",
"LDAP_Description": "LDAP on laajasti käytössä oleva hierarkinen tietokantapalvelu, jolla organisaatioiden palveluille mahdollistetaan kertakirjautuminen (SSO).\nMääritystiedot ja esimerkit, katso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "Domain Base",
- "LDAP_Domain_Base_Description": "The fully qualified Distinguished Name (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use search filter to control access.",
- "LDAP_Domain_Search_Filter": "Verkkotunnusten hakusuodatin",
- "LDAP_Domain_Search_Filter_Description": "Mikäli määritelty, vain tätä suodatinta vastaavat käyttäjät voivat kirjautua sisään. Jos suodatinta ei ole määritetty, kaikki käyttäjät määritetyn toimialueen puitteissa voivat kirjautua sisään. Esim. Active Directorylle `MEMBEROF = cn = ROCKET_CHAT, ou = General Groups`. Esim. OpenLDAP:lle (extensible match search) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Verkkotunnushaun olion kategoria",
- "LDAP_Domain_Search_Object_Category_Description": "*olion kategoria* käyttäjien tunnistamiseksi. Jätä tyhjäksi *OpenLDAPille*. Esim. `person` tms.",
- "LDAP_Domain_Search_Object_Class": "Verkkotunnushaun olion luokka",
- "LDAP_Domain_Search_Object_Class_Description": "*olion luokka* käyttäjien tunnistamiseksi. Esim. `organizationalPerson`, `user`, `inetOrgPerson` tms.",
- "LDAP_Domain_Search_Password": "Verkkotunnushaun salasana",
- "LDAP_Domain_Search_Password_Description": "Salasana verkkotunnushaun käyttäjälle.",
- "LDAP_Domain_Search_User": "Verkkotunnushaun käyttäjä",
- "LDAP_Domain_Search_User_Description": "LDAP käyttäjä, joka suorittaa käyttäjähaut muiden käyttäjien varmentamiseksi, kun he kirjautuvat sisään. Tämä on tyypillisesti nimenomaan kolmannen osapuolen integraatioita varten luotu tili. Käytä täysin varmistettua nimeä, kuten `cn = Ylläpitäjä, cn = Users, dc = Esimerkki, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Verkkotunnushaun käyttäjän tunniste",
- "LDAP_Domain_Search_User_ID_Description": "LDAP-määrite, joka yksilöi LDAP- käyttäjän, joka yrittää todennusta. Tämän kentän tulisi olla `sAMAccountName` useimmille Active Directory- asennuksille, mutta se voi olla` uid` muille LDAP ratkaisuille, kuten OpenLDAP:lle. Voit käyttää `mail`- tunnistusta käyttäjät tunnistukseen sähköpostitse tai mitä tahansa muuta attribuuttia. Voit käyttää useita arvoja, pilkuilla eroteltuna, jotta käyttäjät voivat kirjautua käyttämällä useita tunnisteita, kuten käyttäjätunnusta tai sähköpostiosoitetta.",
+ "LDAP_BaseDN_Description": "The fully qualified Distinguished Name (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use search filter to control access.",
+ "LDAP_User_Search_Field_Description": "LDAP-määrite, joka yksilöi LDAP- käyttäjän, joka yrittää todennusta. Tämän kentän tulisi olla `sAMAccountName` useimmille Active Directory- asennuksille, mutta se voi olla` uid` muille LDAP ratkaisuille, kuten OpenLDAP:lle. Voit käyttää `mail`- tunnistusta käyttäjät tunnistukseen sähköpostitse tai mitä tahansa muuta attribuuttia. Voit käyttää useita arvoja, pilkuilla eroteltuna, jotta käyttäjät voivat kirjautua käyttämällä useita tunnisteita, kuten käyttäjätunnusta tai sähköpostiosoitetta.",
+ "LDAP_User_Search_Filter_Description": "Mikäli määritelty, vain tätä suodatinta vastaavat käyttäjät voivat kirjautua sisään. Jos suodatinta ei ole määritetty, kaikki käyttäjät määritetyn toimialueen puitteissa voivat kirjautua sisään. Esim. Active Directorylle `MEMBEROF = cn = ROCKET_CHAT, ou = General Groups`. Esim. OpenLDAP:lle (extensible match search) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "LDAP käyttäjä, joka suorittaa käyttäjähaut muiden käyttäjien varmentamiseksi, kun he kirjautuvat sisään. Tämä on tyypillisesti nimenomaan kolmannen osapuolen integraatioita varten luotu tili. Käytä täysin varmistettua nimeä, kuten `cn = Ylläpitäjä, cn = Users, dc = Esimerkki, dc = com`.",
"LDAP_Enable": "Kytke LDAP päälle",
"LDAP_Enable_Description": "Käytä LDAPia autentikointiin",
"LDAP_Encryption": "Salaus",
@@ -621,12 +612,9 @@
"LDAP_Sync_User_Data_Description": "Pidä käyttäjädata synkronoituna palvelimelta kirjautumishetkellä (esim nimi, sähköposti)",
"LDAP_Sync_User_Data_FieldMap": "Käyttäjätietojen kohdistus",
"LDAP_Sync_User_Data_FieldMap_Description": "Määrittää, miten käyttäjätietojen kentät tuodaan LDAP-palvelimelta.\nEsimerkiksi, {\"cn\":\"name\", \"mail\":\"email\"} -määritys tuo käyttäjän nimen cn-tiedosta ja sähköpostin email-tiedosta. Käytettävissä olevat kentät ovat \"name\" ja \"email\".",
- "LDAP_Sync_Users": "Synkronoi käyttäjät",
"LDAP_Test_Connection": "Testaa yhteys",
"LDAP_Unique_Identifier_Field": "Uniikin tunnisteen kenttä",
"LDAP_Unique_Identifier_Field_Description": "Kenttä, jota käytetään liittämään LDAP käyttäjä ja Rocket.Chat käyttäjä. Voit ilmoittaa useita arvoja pilkuilla erotettuna yrittääksesi saada arvon LDAP-tiedoista. Oletusarvo on `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Käytä mukautettua verkkotunnushakua",
- "LDAP_Use_Custom_Domain_Search_Description": "Kirjoita oma suodatin etsiäksesi käyttäjiä LDAP-palvelimelta.",
"LDAP_Username_Field": "Käyttäjänimikenttä",
"LDAP_Username_Field_Description": "Uusille käyttäjille *käyttäjätunnuksena* käytetty kenttä. Jätä tyhjäksi käyttääksesi kirjautumissivulla näytettyä käyttäjätunnusta. Voit myös käyttää template-tageja myös kuten `#{givenName}.#{sn}`. Oletusarvo on `sAMAccountName`.",
"Least_Amount": "Pienin määrä",
@@ -828,7 +816,7 @@
"OS_Uptime": "OS Päälläoloaika",
"others": "muut",
"OTR": "OTR",
- "OTR_is_only_available_when_both_users_are_online": "OTR on käytettävissä vain, kun molemmat käyttäjät ovat verkossa",
+ "OTR_is_only_available_when_both_users_are_online": "OTR on käytettävissä vain, kun molemmat käyttäjät ovat online",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Ohitus-URL johon tiedostot siirretään. Tätä urlia käytetään myös latauksia varten ellei erillistä CDN:ää syötetty",
"Page_title": "Sivun otsikko",
"Page_URL": "Sivun URL",
@@ -1008,7 +996,7 @@
"Show_all": "Näytä kaikki",
"Show_more": "Näytä lisää",
"show_offline_users": "Näytä käyttäjät, jotka ovat offline",
- "Show_only_online": "Näytä vain verkossa",
+ "Show_only_online": "Näytä vain onlinessä olevat",
"Show_preregistration_form": "Näytä esirekisteröintilomake",
"Show_queue_list_to_all_agents": "Näytä jonolista kaikille agenteille",
"Showing_archived_results": "Näytetään %s arkistoitua tulosta
",
@@ -1091,19 +1079,19 @@
"The_user_wont_be_able_to_type_in_s": "Käyttäjä ei pysty kirjoittamaan %s",
"Theme": "Ulkoasu",
"theme-color-content-background-color": "Sisällön taustaväri",
+ "theme-color-custom-scrollbar-color": "Vierityspalkin väri (custom)",
+ "theme-color-info-font-color": "Infon fontin väri",
+ "theme-color-link-font-color": "Linkin fontin väri",
"theme-color-primary-background-color": "Ensisijainen taustaväri",
"theme-color-primary-font-color": "Ensisijainen fontin väri",
"theme-color-secondary-background-color": "Toissijainen taustaväri",
"theme-color-secondary-font-color": "Toissijainen fontin väri",
- "theme-color-tertiary-background-color": "Tertiäärinen (se kolmas) taustaväri",
- "theme-color-tertiary-font-color": "Tertiäärinen (se kolmas) fontin väri",
- "theme-color-link-font-color": "Linkin fontin väri",
- "theme-color-info-font-color": "Infon fontin väri",
- "theme-color-custom-scrollbar-color": "Vierityspalkin väri (custom)",
"theme-color-status-away": "Poissa-tilan väri",
"theme-color-status-busy": "Varattu-tilan väri",
"theme-color-status-offline": "Offline-tilan väri",
"theme-color-status-online": "Online-tilan väri",
+ "theme-color-tertiary-background-color": "Tertiäärinen (se kolmas) taustaväri",
+ "theme-color-tertiary-font-color": "Tertiäärinen (se kolmas) fontin väri",
"theme-color-unread-notification-color": "Lukemattomien ilmoitusten väri",
"theme-custom-css": "Mukautettu CSS",
"There_are_no_agents_added_to_this_department_yet": "Yhtään agenttia ei ole vielä lisätty tähän osastoon.",
@@ -1277,4 +1265,4 @@
"Your_mail_was_sent_to_s": "Sähköpostisi lähetettiin, vastaanottajana %s",
"Your_password_is_wrong": "Salasanasi on väärin!",
"Your_push_was_sent_to_s_devices": "Push-viestisi lähetettiin %s laitteeseen"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/fr.i18n.json b/packages/rocketchat-i18n/i18n/fr.i18n.json
index fa6f7648f5143..eb28f22ecb89a 100644
--- a/packages/rocketchat-i18n/i18n/fr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fr.i18n.json
@@ -2,24 +2,26 @@
"#channel": "#canal",
"0_Errors_Only": "0 - Erreurs seulement",
"1_Errors_and_Information": "1 - Erreurs et informations",
- "2_Erros_Information_and_Debug": "2 - Erreurs, informations et debug",
+ "2_Erros_Information_and_Debug": "2 - Erreurs, informations et débogage ",
"403": "Interdit",
"500": "Erreur interne au serveur",
"@username": "@nomdutilisateur",
- "@username_message": "@nomdutilisateur",
+ "@username_message": "@nomdutilisateur ",
"__username__is_no_longer__role__defined_by__user_by_": "__user_by__ a retiré le rôle __role__ à __username__",
"__username__was_set__role__by__user_by_": "__user_by__ a donné le rôle __role__ à __username__",
"Accept": "Accepter",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Accepter les demande de chat en direct même si il n'y a pas d'assistant en ligne",
- "Accept_with_no_online_agents": "Accepter sans assistant enligne",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Accepter les demandes de chat en ligne même si il n'y a pas d'agent en ligne",
+ "Accept_with_no_online_agents": "Accepter sans agent en ligne",
"Access_not_authorized": "Accès non autorisé",
"Access_Token_URL": "URL du jeton d'accès",
"Accessing_permissions": "Accès aux permissions",
"Account_SID": "SID du compte",
"Accounts": "Comptes",
+ "Accounts_AllowAnonymousRead": "Autoriser la lecture anonyme",
+ "Accounts_AllowAnonymousWrite": "Autoriser l'écriture anonyme",
"Accounts_AllowDeleteOwnAccount": "Autoriser les utilisateurs à supprimer leur propre compte",
"Accounts_AllowedDomainsList": "Liste des domaines autorisés",
- "Accounts_AllowedDomainsList_Description": "Liste des domaines autorisés (séparés par des virgules)",
+ "Accounts_AllowedDomainsList_Description": "Liste des domaines autorisés, séparés par des virgules",
"Accounts_AllowEmailChange": "Autoriser le changement d'adresse e-mail",
"Accounts_AllowPasswordChange": "Autoriser le changement de mot de passe",
"Accounts_AllowUserAvatarChange": "Autoriser le changement d'avatar",
@@ -27,18 +29,18 @@
"Accounts_AllowUserProfileChange": "Autoriser la modification de profil",
"Accounts_AvatarResize": "Redimensionner les avatars",
"Accounts_AvatarSize": "Taille de l'avatar",
- "Accounts_AvatarStorePath": "Chemin de stockage des avatars",
- "Accounts_AvatarStoreType": "Type de stockage des avatars",
"Accounts_BlockedDomainsList": "Liste des domaines bloqués",
"Accounts_BlockedDomainsList_Description": "Liste de domaines bloqués, séparés par des virgules",
"Accounts_BlockedUsernameList": "Liste des noms d'utilisateurs bloqués",
- "Accounts_BlockedUsernameList_Description": "Liste de noms d'utilisateurs bloqués (insensible à la casse), séparée par des virgules",
- "Accounts_CustomFields_Description": "Devrait être un JSON valide où les clés sont les noms des champs contenant un dictionnaire de champs de paramétrage. Exemple :\n{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"eleve\",\n \"options\": [\"enseignant\", \"eleve\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_BlockedUsernameList_Description": "Liste de noms d'utilisateurs bloqués (insensible à la casse), séparés par des virgules",
+ "Accounts_CustomFields_Description": "Devrait être un JSON valide où les clés sont les noms des champs contenant un dictionnaire de champs de paramétrage. Exemple : \n{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"eleve\",\n \"options\": [\"enseignant\", \"eleve\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Suggestion par défaut du préfixe du nom d'utilisateur",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Alterte notification de bureau par défaut",
"Accounts_denyUnverifiedEmail": "Refuser les e-mails non vérifiés",
"Accounts_EmailVerification": "Vérification de l'adresse e-mail",
"Accounts_EmailVerification_Description": "Vous devez avoir des paramètres SMTP corrects pour utiliser cette fonctionnalité",
"Accounts_Enrollment_Email": "E-mail d'inscription",
- "Accounts_Enrollment_Email_Default": " Bienvenue à [Site_Name] Allez sur [Site_URL] et essayer la meilleure solution de chat open source disponible aujourd'hui!
",
+ "Accounts_Enrollment_Email_Default": " Bienvenue à [Site_Name] Allez sur [Site_URL] et essayer la meilleure solution de chat open source disponible aujourd'hui!
",
"Accounts_Enrollment_Email_Description": "Vous pouvez utiliser, respectivement, [name], [fname], [lname] pour le nom complet , le prénom et le nom de famille de l'utilisateur. Vous pouvez utiliser [email] pour l'adresse e-mail de l'utilisateur. [Site_Name] et [Site_URL] pour les noms de l'application et l'URL. ",
"Accounts_Enrollment_Email_Subject_Default": "Bienvenue sur [Site_Name]",
"Accounts_ForgetUserSessionOnWindowClose": "Ne pas se souvenir de la session utilisateur lors de la fermeture de la fenêtre",
@@ -57,45 +59,48 @@
"Accounts_OAuth_Custom_Identity_Path": "URL d'identification",
"Accounts_OAuth_Custom_Login_Style": "Style de la page de connexion",
"Accounts_OAuth_Custom_Merge_Users": "Fusionner les utilisateurs",
- "Accounts_OAuth_Custom_Scope": "Scope",
+ "Accounts_OAuth_Custom_Scope": "Portée",
"Accounts_OAuth_Custom_Secret": "Secret",
"Accounts_OAuth_Custom_Token_Path": "URL de Token",
"Accounts_OAuth_Custom_Token_Sent_Via": "Jeton envoyé via",
"Accounts_OAuth_Custom_Username_Field": "Champ nom d'utilisateur",
+ "Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Client Secret",
"Accounts_OAuth_Facebook": "Connexion avec Facebook",
"Accounts_OAuth_Facebook_callback_url": "Facebook URL de Callback",
"Accounts_OAuth_Facebook_id": "ID Facebook App ",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
- "Accounts_OAuth_Github": "Connexion avec GitHub",
+ "Accounts_OAuth_Github": "OAuth activé",
"Accounts_OAuth_Github_callback_url": "GitHub URL de Callback",
"Accounts_OAuth_GitHub_Enterprise": "OAuth activé",
"Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub Entreprise URL de Callback",
- "Accounts_OAuth_GitHub_Enterprise_id": "GitHub Entreprise ID",
- "Accounts_OAuth_GitHub_Enterprise_secret": "GitHub Entreprise Secret",
- "Accounts_OAuth_Github_id": "ID client",
- "Accounts_OAuth_Github_secret": "GitHub Secret",
+ "Accounts_OAuth_GitHub_Enterprise_id": "ID Client",
+ "Accounts_OAuth_GitHub_Enterprise_secret": "Secret Client",
+ "Accounts_OAuth_Github_id": "ID Client",
+ "Accounts_OAuth_Github_secret": "Client Secret",
"Accounts_OAuth_Gitlab": "OAuth activé",
"Accounts_OAuth_Gitlab_callback_url": "GitLab URL de Callback",
"Accounts_OAuth_Gitlab_id": "ID GitLab",
- "Accounts_OAuth_Gitlab_secret": "Mot de passe client",
+ "Accounts_OAuth_Gitlab_secret": "Client Secret",
"Accounts_OAuth_Google": "Connexion avec Google",
"Accounts_OAuth_Google_callback_url": "Google URL de Callback",
- "Accounts_OAuth_Google_id": "ID Google ",
+ "Accounts_OAuth_Google_id": "ID Google ",
"Accounts_OAuth_Google_secret": "Secret Google",
"Accounts_OAuth_Linkedin": "Connexion avec LinkedIn",
- "Accounts_OAuth_Linkedin_callback_url": "URL de Callback LinkedIn ",
+ "Accounts_OAuth_Linkedin_callback_url": "LinkedIn URL de Callback",
"Accounts_OAuth_Linkedin_id": "ID LinkedIn",
"Accounts_OAuth_Linkedin_secret": "Secret LinkedIn ",
"Accounts_OAuth_Meteor": "Connexion avec Meteor",
- "Accounts_OAuth_Meteor_callback_url": "URL de Callback Meteor",
+ "Accounts_OAuth_Meteor_callback_url": "Meteor URL de Callback",
"Accounts_OAuth_Meteor_id": "ID Meteor ",
- "Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Meteor_secret": "Secret Meteor ",
+ "Accounts_OAuth_Proxy_host": "Hôte proxy",
+ "Accounts_OAuth_Proxy_services": "Services proxy",
"Accounts_OAuth_Twitter": "Connexion avec Twitter",
- "Accounts_OAuth_Twitter_callback_url": "URL de Callback Twitter ",
+ "Accounts_OAuth_Twitter_callback_url": "Twitter URL de Callback",
"Accounts_OAuth_Twitter_id": "ID Twitter",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "Connexion avec WordPress",
- "Accounts_OAuth_Wordpress_callback_url": "URL de Callback WordPress",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress URL de Callback",
"Accounts_OAuth_Wordpress_id": "ID WordPress",
"Accounts_OAuth_Wordpress_secret": "Secret WordPress",
"Accounts_PasswordReset": "Réinitialisation du mot de passe",
@@ -106,7 +111,7 @@
"Accounts_RegistrationForm_Public": "Public",
"Accounts_RegistrationForm_Secret_URL": "URL secrète",
"Accounts_RegistrationForm_SecretURL": "URL secrète du formulaire d'inscription",
- "Accounts_RegistrationForm_SecretURL_Description": "Vous devez fournir une chaîne de caractères aléatoire qui sera ajoutée à votre URL d'inscription. Exemple: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Vous devez fournir une chaîne de caractères aléatoire qui sera ajoutée à votre URL d'inscription. Exemple: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Exiger un nom pour s'inscrire",
"Accounts_RequirePasswordConfirmation": "Confirmation du mot de passe requise",
"Accounts_SetDefaultAvatar": "Définir l'avatar par défaut",
@@ -114,63 +119,80 @@
"Accounts_ShowFormLogin": "Afficher le formulaire de connexion",
"Accounts_UseDefaultBlockedDomainsList": "Utiliser la liste de domaines bloqués par défaut ",
"Accounts_UseDNSDomainCheck": "Utiliser la vérification de Domaine du DNS",
- "Accounts_UserAddedEmail_Default": " Bienvenue sur [Site_Name] Allez sur [Site_URL] et essayer la meilleure solution de chat open source disponible aujourd'hui!
Vous pouvez vous connecter en utilisant votre email: [email] et mot de passe: [password]. Vous pouvez être amené à le changer après votre première connexion.
",
+ "Accounts_UserAddedEmail_Default": " Bienvenue sur [Site_Name] Allez sur [Site_URL] et essayer la meilleure solution de chat open source disponible aujourd'hui!
Vous pouvez vous connecter en utilisant votre email: [email] et mot de passe: [password]. Vous pouvez être amené à le changer après votre première connexion.
",
"Accounts_UserAddedEmail_Description": "Vous pouvez utiliser les variables suivantes : [name], [fname], [lname] respectivement pour le nom complet de l'utilisateur, son prénom ou son nom, [email] pour son adresse e-mail de l'utilisateur, [password] pour sson mot de passe, [Site_Name] et [Site_URL] pour le nom de l'application et son URL respectivement. ",
"Accounts_UserAddedEmailSubject_Default": "Vous avez été ajouté à [Site_Name]",
"Activate": "Activer",
"Activity": "Activité",
"Add": "Ajouter",
- "Add_agent": "Ajouter un assistant",
+ "add-oauth-service_description": "Permission d'ajouter un nouveau service Oauth",
+ "add-user": "Ajouter un utilisateur",
+ "add-user-to-any-c-room": "Ajouter un utilisateur à un canal public",
+ "add-user-to-any-c-room_description": "Permission pour ajouter un utilisateur à un canal public",
+ "add-user-to-any-p-room": "Ajouter un utilisateur à un canal privé",
+ "add-user-to-any-p-room_description": "Permission pour ajouter un utilisateur à un canal privé",
+ "Add_agent": "Ajouter d'un assistant",
"Add_custom_oauth": "Ajouter un OAuth personnalisé",
- "Add_Domain": "Ajouter domaine",
+ "Add_Domain": "Ajouter un domaine",
+ "Add_files_from": "Ajouter des fichiers depuis",
"Add_manager": "Ajouter un manager",
+ "Add_Role": "Ajouter un rôle",
"Add_user": "Ajouter un utilisateur",
"Add_User": "Ajouter un utilisateur",
- "Add_users": "Ajouter plusieurs utilisateurs",
+ "Add_users": "Ajouter des utilisateurs",
"Adding_OAuth_Services": "Ajout de services OAuth",
- "Adding_permission": "Ajout une permission",
+ "Adding_permission": "Ajout d'une permission",
"Adding_user": "Ajout d'un utilisateur",
- "Additional_emails": "Adresses e-mail suplémentaires",
+ "Additional_emails": "Adresses e-mail supplémentaires",
"Additional_Feedback": "Commentaires supplémentaires",
"Administration": "Administration",
+ "Adult_images_are_not_allowed": "Les images pour adultes ne sont pas autorisées",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Après l'authentification par OAuth2, les utilisateurs seront redirigés vers cette URL",
- "Agent": "Assistant",
- "Agent_added": "Assistant ajouté",
- "Agent_removed": "Assistant retiré",
+ "Agent": "Agent",
+ "Agent_added": "Agent ajouté",
+ "Agent_removed": "Assistant supprimé",
"Alias": "Alias",
- "Alias_Format": "format d'alias",
- "Alias_Format_Description": "Importer les messages de Slack avec un alias; %s est remplacé par le nom d'utilisateur. Si laissé vide, aucun alias ne sera utilisé.",
+ "Alias_Format": "Format d'alias",
+ "Alias_Format_Description": "Importer les messages de Slack avec un alias ; %s est remplacé par le nom d'utilisateur. Si laissé vide, aucun alias ne sera utilisé.",
"Alias_Set": "Définir alias",
"All": "Tous",
"All_channels": "Tous les canaux",
"All_logs": "Tous les journaux",
"All_messages": "Tous les messages",
+ "All_users_in_the_channel_can_write_new_messages": "Tous les utilisateur peuvent écrire des nouveaux messages",
"Allow_Invalid_SelfSigned_Certs": "Autoriser les certificats auto-signés invalides",
"Allow_Invalid_SelfSigned_Certs_Description": "Autoriser les certificats SSL invalides et auto-signés pour la validation des liens et leurs prévisualisations.",
+ "Allow_switching_departments": "Autoriser les visiteurs a changé de département",
"Always_open_in_new_window": "Toujours ouvrir dans une nouvelle fenêtre",
- "Analytics_features_enabled": "Fonctionnalités activées.",
+ "Analytics_features_enabled": "Fonctionnalités activées",
"Analytics_features_messages_Description": "Suivre les événements personnalisés liés aux actions d'un utilisateur sur des messages.",
"Analytics_features_rooms_Description": "Suivre les événements personnalisés liés aux actions sur un canal ou un groupe (créer, quitter, supprimer).",
"Analytics_features_users_Description": "Suivre les événements personnalisés liés à des actions liées aux utilisateurs (nombre de réinitialisations de mot de passe, changements d'image de profil, etc.).",
+ "Analytics_Google": "Google Analytics",
"and": "et",
"And_more": "et encore __length__",
"Animals_and_Nature": "Faune et flore",
+ "Announcement": "Annonce",
"API": "API",
"API_Allow_Infinite_Count": "Autoriser à tout recevoir",
"API_Allow_Infinite_Count_Description": "Autoriser les appels REST API à tout retourner en une seule réponse ?",
"API_Analytics": "Métriques",
"API_Default_Count": "Quantité par défaut",
- "API_Embed": "Intégration",
- "API_Embed_Description": "Détermine si les prévisualisations de liens sont activées ou non lorsqu'un utilisateur publie une URL.",
+ "API_Drupal_URL": "Drupal URL du serveur",
+ "API_Drupal_URL_Description": "Exemple : https://domaine.com (ne pas mettre le / de fin)",
+ "API_Embed": "Aperçu des liens intégrés",
+ "API_Embed_Description": "Détermine si les prévisualisations de liens sont activées ou non lorsqu'un utilisateur publie un lien vers un site web.",
"API_EmbedCacheExpirationDays": "Durée d'expiration du cache embarqué (en jours)",
"API_EmbedDisabledFor": "Désactiver l'intégration pour les utilisateurs",
- "API_EmbedDisabledFor_Description": "Liste de noms d'utilisateurs séparés par des virgules",
+ "API_EmbedDisabledFor_Description": "Liste de noms d'utilisateurs séparés par des virgules pour désactiver les aperçus de liens intégrés.",
"API_EmbedIgnoredHosts": "Hôtes à ne pas intégrer",
"API_EmbedIgnoredHosts_Description": "Liste des hôtes ou des adresses CIDR, séparés par des virgules. Par exemple : localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Ports approuvés",
"API_EmbedSafePorts_Description": "Liste des ports autorisés pour la prévisualisation, séparés par des virgules.",
+ "API_Enable_CORS": "Activer CORS",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Ceci active `/api/v1/im.history.others`qui permet la visualisation des messages privés envoyés par tous les utilisateurs.",
"API_GitHub_Enterprise_URL": "URL du serveur",
- "API_GitHub_Enterprise_URL_Description": "Exemple: http://domain.com (sans slash final)",
+ "API_GitHub_Enterprise_URL_Description": "Exemple : http://domain.com (sans slash final)",
"API_Gitlab_URL": "URL GitLab",
"API_Token": "Jeton API",
"API_Upper_Count_Limit": "Nombre maximum d'enregistrements",
@@ -185,31 +207,43 @@
"Application_updated": "Application mise à jour",
"Apply_and_refresh_all_clients": "Appliquer et rafraîchir tous les clients",
"Archive": "Archiver",
+ "archive-room": "Archiver un canal",
+ "archive-room_description": "Permission d'archiver un canal",
"are_also_typing": "sont également en train d'écrire",
"are_typing": "sont en train d'écrire",
"Are_you_sure": "Êtes-vous sûr(e) ?",
"Are_you_sure_you_want_to_delete_your_account": "Êtes-vous sûr(e) de vouloir supprimer votre compte ?",
+ "assign-admin-role": "Donner le rôle d'administrateur",
+ "assign-admin-role_description": "Permission de donner le rôle d'administrateur aux autres utilisateurs",
"Assign_admin": "Attribution d'un administrateur",
"at": "à",
"AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Fichier envoyé",
+ "Audio_message": "Message audio",
"Auth_Token": "Jeton d'Auth",
"Author": "Auteur",
"Authorization_URL": "URL d’autorisation",
"Authorize": "Autoriser",
+ "auto-translate": "Traduction automatique",
+ "auto-translate_description": "Permission d'utiliser l'outil de traduction automatique",
"Auto_Load_Images": "Charger automatiquement les images",
- "AutoLinker_Email": "AutoLinker sur les adresses e-mail",
- "AutoLinker_Phone": "AutoLinker sur les numéros de téléphone",
+ "Auto_Translate": "Traduction automatique",
+ "AutoLinker_Email": "Lien automatique sur les adresses e-mail",
+ "AutoLinker_Phone": "Lien automatique sur les numéros de téléphone",
"AutoLinker_Phone_Description": "Lier automatiquement les numéros de téléphone. par exemple `(123) 456-7890`",
"AutoLinker_StripPrefix": "AutoLinker Strip Prefix",
"AutoLinker_StripPrefix_Description": "Affichage court. e.g. https://rocket.chat => rocket.chat",
- "AutoLinker_Urls_Scheme": "AutoLinker Scheme: // URLs",
+ "AutoLinker_Urls_Scheme": "Lien automatique sur le schéma : // URLs",
"AutoLinker_Urls_TLD": "URL TLD de l'AutoLinker",
- "AutoLinker_Urls_www": "URL 'www' de l'AutoLinker",
- "AutoLinker_UrlsRegExp": "AutoLinker URL Expression régulière",
+ "AutoLinker_Urls_www": "Lien automatique si URL contenant 'www'",
+ "AutoLinker_UrlsRegExp": "Lien automatique si URL dans expression régulière",
+ "Automatic_Translation": "Traduction automatique",
+ "AutoTranslate_Enabled": "Activer la traduction automatique",
+ "AutoTranslate_Enabled_Description": "Activer la traduction automatique permettra aux utilisateurs disposant de la permission auto-translate d'avoir l'ensemble des messages traduits automatiquement dans leur langue. Des frais peuvent s'appliquer, voir la documentation Google ",
+ "AutoTranslate_GoogleAPIKey": "Clef API Google",
"Available": "Disponible",
"Available_agents": "Assistants disponibles",
- "Avatar": "Modifier l'avatar",
+ "Avatar": "Avatar",
"Avatar_changed_successfully": "Avatar modifié avec succès",
"Avatar_URL": "URL de l'avatar",
"Avatar_url_invalid_or_error": "L'URL est invalide ou non accessible. Essayez de nouveau, mais avec une URL différente.",
@@ -221,17 +255,20 @@
"Away_male": "Absent",
"Back": "Retour",
"Back_to_applications": "Retour aux applications",
+ "Back_to_chat": "Retour au tchat",
"Back_to_integrations": "Retour aux intégrations",
"Back_to_login": "Retourner à l'écran de connexion",
"Back_to_permissions": "Retour aux permissions",
- "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Fonctionnalité Beta. Dépend de l'activation de la fonction Vidéo Conférence.",
+ "ban-user": "Bannir l'utilisateur",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Fonctionnalité en test. Dépend de l'activation de la fonction Vidéo Conférence.",
"Block_User": "Bloquer utilisateur",
"Body": "Corps",
"bold": "gras",
"bot_request": "Requête de bot",
"BotHelpers_userFields": "Champs utilisateur",
- "BotHelpers_userFields_Description": "CSV des champs utilisateurs accessibles par les méthodes d'aide des bots",
+ "BotHelpers_userFields_Description": "CSV des champs utilisateurs accessibles par les méthodes d'aide des bots.",
"Branch": "Branche",
+ "Bugsnag_api_key": "Clef d'API Bugsnag",
"busy": "occupé",
"Busy": "Occupé",
"busy_female": "occupée",
@@ -239,10 +276,10 @@
"busy_male": "occupé",
"Busy_male": "Occupé",
"by": "par",
- "cache_cleared": "Effacer le cache",
+ "cache_cleared": "Cache effacé",
"Cancel": "Annuler",
"Cancel_message_input": "Annuler",
- "Cannot_invite_users_to_direct_rooms": "Impossible d'inviter des utilisateurs dans les salons privés",
+ "Cannot_invite_users_to_direct_rooms": "Impossible d'inviter des utilisateurs dans les discussions privées",
"CAS_autoclose": "Fermer automatiquement la fenêtre popup de connexion",
"CAS_base_url": "URL de base pour SSO",
"CAS_base_url_Description": "URL de base pour votre service externe de connexion SSO, par exemple: http://sso.example.com/sso/",
@@ -251,29 +288,37 @@
"CAS_button_label_text": "Bouton de connexion, texte / label",
"CAS_enabled": "Activé",
"CAS_login_url": "URL de login SSO",
- "CAS_login_url_Description": "URL de connexion pour votre service externe de connexion SSO, par exemple: http://sso.example.com/sso/",
+ "CAS_login_url_Description": "URL de connexion pour votre service externe de connexion SSO, par exemple : http://sso.example.com/sso/",
"CAS_popup_height": "Hauteur de la fenêtre popup de connexion",
"CAS_popup_width": "Largeur de la fenêtre popup de connexion",
- "CAS_Sync_User_Data_Enabled": "Toujours syncroniser les données utilisateur",
+ "CAS_Sync_User_Data_Enabled": "Toujours synchroniser les données utilisateur",
+ "CAS_Sync_User_Data_Enabled_Description": "Toujours synchroniser les données externes de l'utilisateur CAS avec les attributs disponibles après connexion. Note : dans tous les cas, les attributs sont toujours synchronisés après la création du compte.",
"CAS_Sync_User_Data_FieldMap": "Attributs de carte",
"CAS_version": "Version CAS",
+ "CAS_version_Description": "Utiliser seulement une version de CAS supportée par votre service CAS SSO",
"CDN_PREFIX": "Préfixe CDN",
"Certificates_and_Keys": "Certificats et clés",
+ "Change_Room_Type": "Modification du type de salon",
"Changing_email": "Modification des adresses e-mail",
- "Change_Room_Type": "Changer le type de salon",
"channel": "canal",
"Channel": "Canal",
"Channel_already_exist": "Le canal '#% s' existe déjà.",
- "Channel_already_Unarchived": "Canal avec le nom `#% s` est déjà dans l'état Désarchivées",
- "Channel_Archived": "Canal avec le nom `#% s` a été archivé avec succès",
+ "Channel_already_exist_static": "Le canal existe déjà",
+ "Channel_already_Unarchived": "Canal avec le nom `#%s` est déjà dans l'état désarchivé",
+ "Channel_Archived": "Canal avec le nom `#%s` a été archivé avec succès",
+ "Channel_created": "Canal `#%s` créé",
"Channel_doesnt_exist": "Le canal `#%s` n'existe pas.",
- "Channel_Unarchived": "Canal avec le nom `#% s` a été plus archivée",
+ "Channel_name": "Nom du canal",
+ "Channel_to_listen_on": "Canal à écouter",
+ "Channel_Unarchived": "Canal avec le nom `#%s` a été désarchivé avec succès",
"Channels": "Canaux",
+ "Channels_are_where_your_team_communicate": "Les canaux sont les lieux où votre équipe communique.",
"Channels_list": "Liste des canaux publics",
- "Chat_button": "bouton chat",
+ "Chat_button": "Bouton chat",
"Chat_closed": "Chat fermé",
"Chat_closed_successfully": "Chat fermé avec succès",
- "Chat_window": "fenêtre de chat",
+ "Chat_Now": "Discuter maintenant",
+ "Chat_window": "Fenêtre de chat",
"Chatops_Enabled": "Activer Chatops",
"Chatops_Title": "Panneau de contrôle des Chatops",
"Chatops_Username": "Nom d'utilisateur Chatops",
@@ -282,15 +327,16 @@
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Choisissez l'alias qui apparaitra avant le nom d'utilisateur dans les messages.",
"Choose_the_username_that_this_integration_will_post_as": "Choisir le nom d'utilisateur que cette intégration va utiliser pour publier.",
"clear": "Effacer/Nettoyer",
- "clear_cache_now": "Effacer le cache maintenant",
"Clear_all_unreads_question": "Marquer tout comme lu ?",
+ "clear_cache_now": "Effacer le cache maintenant",
+ "clear_history": "Effacer l'historique",
"Click_here": "Cliquez ici",
"Click_here_for_more_info": "Cliquer ici pour plus d'information",
"Client_ID": "ID du client",
- "Client_Secret": "Secret du client",
+ "Client_Secret": "Secret Client",
"Clients_will_refresh_in_a_few_seconds": "Les clients vont être rechargés dans quelques secondes",
"close": "fermer",
- "Close": "Fermer",
+ "Close": "Fermeture",
"Closed": "Fermé",
"Closed_by_visitor": "Fermé par le visiteur",
"Closing_chat": "Fermeture du chat",
@@ -300,9 +346,10 @@
"Comment_to_leave_on_closing_session": "Commentaire à laisser lors de la fermeture de session",
"Compact": "Compact",
"Confirm_password": "Confirmez votre mot de passe",
+ "Content": "Contenu",
"Conversation": "Conversation",
"Conversation_closed": "Conversation fermée : __comment__.",
- "Convert_Ascii_Emojis": "Convertir le code ASCII en Emoji",
+ "Convert_Ascii_Emojis": "Convertir le code ASCII en émoticône",
"Copied": "Copié",
"Copy": "Copier",
"Copy_to_clipboard": "Copier dans le presse-papier",
@@ -310,113 +357,132 @@
"Count": "Nombre",
"Cozy": "Confortable",
"Create": "Créer",
- "Create_A_New_Channel": "Créer une nouvelle chaîne",
+ "Create_A_New_Channel": "Créer un nouveau canal",
"Create_new": "Créer nouveau",
"Created_at": "Créé le",
- "Created_at_s_by_s": "Créé à %s par %s ",
+ "Created_at_s_by_s": "Créé le %s par %s ",
+ "CRM_Integration": "Intégration CRM (GRC)",
"CROWD_Reject_Unauthorized": "Rejeter si non-autorisé",
"Current_Chats": "Discussions actuelles",
+ "Current_Status": "Statut actuel",
"Custom": "Personnalisé",
"Custom_Emoji": "Emoticône personnalisée",
"Custom_Emoji_Add": "Ajouter une nouvelle émoticône",
- "Custom_Emoji_Added_Successfully": "Emoji personnalisé ajouté avec succès",
- "Custom_Emoji_Delete_Warning": "Effacer un emoji ne peut pas être annulé.",
- "Custom_Emoji_Error_Invalid_Emoji": "émoticône non valide",
- "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "L'émoji personnalisé ou un de ses alias est déjà en cours d'utilisation.",
- "Custom_Emoji_Has_Been_Deleted": "L'émoji personnalisé a été effacé.",
- "Custom_Emoji_Info": "Information sur l'émoji personnalisé",
- "Custom_Emoji_Updated_Successfully": "Emoji personnalisé mis à jour avec succès",
- "Custom_Fields": "Champs Personnalisés",
+ "Custom_Emoji_Added_Successfully": "Emoticône personnalisée ajouté avec succès",
+ "Custom_Emoji_Delete_Warning": "Effacer une émoticône est irréversible.",
+ "Custom_Emoji_Error_Invalid_Emoji": "Emoticône non valide",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "L'émoticône personnalisée ou un de ses alias est déjà en cours d'utilisation.",
+ "Custom_Emoji_Has_Been_Deleted": "L'émoticône personnalisée a été effacé.",
+ "Custom_Emoji_Info": "Information sur l'émoticône personnalisée",
+ "Custom_Emoji_Updated_Successfully": "Emoticône personnalisée mise à jour avec succès",
+ "Custom_Fields": "Champs personnalisés",
"Custom_oauth_helper": "Lorsque vous configurez votre service OAuth, vous devez indiquer une URL pour le Callback. Utilisez %s ",
"Custom_oauth_unique_name": "Nom unique de l'OAuth personnalisé",
"Custom_Script_Logged_In": "Script personnalisé pour les utilisateurs connectés",
"Custom_Script_Logged_Out": "Script personnalisé pour les utilisateurs déconnectés",
+ "Custom_Scripts": "Scripts personnalisés",
+ "Custom_Sound_Add": "Ajouter un son personnalisé",
+ "Custom_Sound_Delete_Warning": "La suppression d'un son est irréversible.",
+ "Custom_Sound_Error_Invalid_Sound": "Son invalide",
+ "Custom_Sound_Error_Name_Already_In_Use": "Le nom de son personnalisé est déjà utilisé",
+ "Custom_Sound_Has_Been_Deleted": "Le son personnalisé a été supprimé.",
+ "Custom_Sound_Info": "Information du son personalisé",
+ "Custom_Sound_Saved_Successfully": "Son personnalisé enregistré avec succès",
+ "Custom_Sounds": "Son personnalisés",
"Custom_Translations": "Traductions personnalisées",
- "Custom_Translations_Description": "Devrait être un JSON valide où les clefs sont des langues conenant un dictionnaire de clefs et de traductions.\nExemple:{\n \"en\": {\n \"key\": \"translation\"\n },\n \"fr\": {\n \"key\": \"traduction\"\n }\n} ",
+ "Custom_Translations_Description": "Devrait être un JSON valide où les clefs sont des langues conenant un dictionnaire de clefs et de traductions.\nExemple:{\n \"en\": {\n \"key\": \"translation\"\n },\n \"fr\": {\n \"key\": \"traduction\"\n }\n} ",
+ "CustomSoundsFilesystem": "Système de fichier des sons personnalisés",
"Dashboard": "Tableau de bord",
"Date": "Date",
"Date_From": "De",
"Date_to": "à",
"days": "jours",
- "DB_Migration": "Base de données de migration",
- "DB_Migration_Date": "Base de données de migration date",
+ "DB_Migration": "Mise à jour de la base de données",
+ "DB_Migration_Date": "Date de mise à jour de la base de données",
"Deactivate": "Désactiver",
"Decline": "Refuser",
"Default": "Défaut",
"Delete": "Supprimer",
- "Delete_message": "Suppression de messages",
+ "Delete_message": "Supprimer le message",
"Delete_my_account": "Supprimer mon compte",
- "Delete_Room_Warning": "Supprimer un salon supprimera également tous les messages postés dans le salon. Cela ne peut pas être annulé.",
- "Delete_User_Warning": "Supprimer un utilisateur va également supprimer tous les messages de celui-ci. Cette action ne peut être annulée.",
+ "Delete_Room_Warning": "Supprimer un salon supprimera également tous les messages postés dans le salon. Cette action est irréversible.",
+ "Delete_User_Warning": "Supprimer un utilisateur va également supprimer tous les messages de celui-ci. Cette action est irréversible.",
"Deleted": "Supprimé !",
- "Department": "Département",
- "Department_removed": "Département supprimé",
+ "Department": "Service",
+ "Department_removed": "Service supprimé",
"Departments": "Départements",
"Deployment_ID": "ID de déploiement",
"Description": "Description",
"Desktop": "Bureau",
"Desktop_Notification_Test": "Test des notifications sur le bureau",
"Desktop_Notifications": "Notifications sur le bureau",
+ "Desktop_Notifications_Default_Alert": "Alterte notification de bureau par défaut",
"Desktop_Notifications_Disabled": "Les notifications du bureau sont désactivées, Modifiez les préférences de votre navigateur si vous avez besoin de les activer.",
"Desktop_Notifications_Duration": "Durée des notifications",
"Desktop_Notifications_Duration_Description": "Secondes pour afficher une notification de bureau. Cela peut affecter le Centre de Notification de OS X. Entrez 0 pour utiliser les paramètres du navigateur par défaut et ne pas affecter le Centre de Notification de OS X.",
"Desktop_Notifications_Enabled": "Les notifications sur le bureau sont activées",
+ "Different_Style_For_User_Mentions": "Style différent pour les mentions utilisateurs",
"Direct_message_someone": "Envoyer un message privé à quelqu'un",
- "Direct_Messages": "Messages privés",
+ "Direct_Messages": "Messages Privés",
+ "Direct_Reply": "Réponse directe",
+ "Direct_Reply_Debug": "Deboguer la réponse directe",
"Display_offline_form": "Affichage formulaire hors ligne",
"Displays_action_text": "Texte d'affichage",
- "Do_you_want_to_change_to_s_question": "Voulez-vous changer pour %s ?",
+ "Do_you_want_to_change_to_s_question": "Voulez-vous changer pour %s ?",
"Domain": "Domaine",
"Domain_added": "Domaine ajouté",
- "Domain_removed": "Domaine retiré",
+ "Domain_removed": "Domaine supprimé",
"Domains": "Domaines",
+ "Domains_allowed_to_embed_the_livechat_widget": "Liste des domaines autorisés à intégrer le widget de chat en direct, séparés par des virgules. Laissez vide pour autoriser tous les domaines. ",
"Download_Snippet": "Telecharger",
- "Drop_to_upload_file": "Glissez-déposez pour transférer un fichier",
+ "Drop_to_upload_file": "Glissez-déposez pour envoyer un fichier",
"Dry_run": "Essai à vide",
"Dry_run_description": "Envoi un unique e-mail, à l'adresse de l'expéditeur. L'adresse e-mail doit appartenir à un utilisateur valide.",
- "Duplicate_archived_channel_name": "Un canal archivé avec le nom '%s' existe",
- "Duplicate_archived_private_group_name": "Un Groupe Privé archivé avec le nom '%s' existe",
- "Duplicate_channel_name": "Un canal avec le nom '% s' existe",
+ "Duplicate_archived_channel_name": "Un canal archivé avec le nom '#%s' existe",
+ "Duplicate_archived_private_group_name": "Un groupe privé archivé avec le nom '%s' existe",
+ "Duplicate_channel_name": "Un canal avec le nom '%s' existe",
"Duplicate_private_group_name": "Un groupe privé avec le nom '%s' existe déjà",
"Duration": "Durée",
"Edit": "Modifier",
"Edit_Custom_Field": "Modifier le champ personnalisé",
- "Edit_Department": "Éditer le département",
+ "Edit_Department": "Éditer le service",
"Edit_Trigger": "Éditer le déclencheur",
"edited": "modifié",
- "Editing_room": "Modification des salons",
+ "Editing_room": "Modification du salon",
"Editing_user": "Modification des utilisateurs",
"Email": "E-mail",
"Email_address_to_send_offline_messages": "Adresse e-mail pour envoyer les messages hors ligne",
"Email_already_exists": "L'adresse e-mail existe déjà",
"Email_body": "Corps du message",
"Email_Change_Disabled": "Votre administrateur de Rocket.Chat a désactivé le changement d'adresse e-mail",
- "Email_Footer_Description": "Vous pouvez utiliser les variables suivantes: [Site_Name] et [Site_URL] pour le nom de l'application et URL respectivement. ",
+ "Email_Footer_Description": "Vous pouvez utiliser les variables suivantes: [Site_Name] et [Site_URL] pour le nom de l'application et URL respectivement. ",
"Email_from": "De",
- "Email_Header_Description": "Vous pouvez utiliser les variables suivantes: [Site_Name] et [Site_URL] pour le nom de l'application et URL respectivement. ",
+ "Email_Header_Description": "Vous pouvez utiliser les variables suivantes: [Site_Name] et [Site_URL] pour le nom de l'application et URL respectivement. ",
"Email_Notification_Mode": "Notifications hors-ligne par e-mail",
"Email_Notification_Mode_All": "Toutes les Mentions/MP",
"Email_Notification_Mode_Disabled": "Désactivé",
- "Email_or_username": "Adresse email ou nom d'utilisateur",
+ "Email_or_username": "Adresse e-mail ou nom d'utilisateur",
"Email_subject": "Sujet",
"Email_verified": "Adresse e-mail vérifiée",
- "Emoji": "Emoji",
- "EmojiCustomFilesystem": "Système de fichier d'émoticones personnalisés",
+ "Emoji": "Emoticône ",
+ "EmojiCustomFilesystem": "Système de fichier d'émoticônes personnalisés",
"Empty_title": "Titre vide",
"Enable": "Activer",
"Enable_Desktop_Notifications": "Activer les notifications sur le bureau",
- "Enabled": "Activé",
"Enable_Svg_Favicon": "Activer les favicon en format SVG",
+ "Enabled": "Activé",
"Encrypted_message": "Message chiffré",
"End_OTR": "Arrêter OTR",
- "Enter_a_regex": "Entrez une expression rationnelle",
+ "Enter_a_regex": "Saisissez une expression rationnelle",
"Enter_a_room_name": "Saisissez un nom de salon",
- "Enter_a_username": "Entrez un nom d'utilisateur",
+ "Enter_a_username": "Saisissez un nom d'utilisateur",
+ "Enter_Alternative": "Mode alternatif (envoyé avec Entrée + Ctrl/Alt/Shift/CMD)",
+ "Enter_Behaviour": "Comportement de la touche Entrée",
+ "Enter_Behaviour_Description": "Cela change si la touche Entrée enverra un message ou ajoutera un retour à la ligne",
"Enter_name_here": "Saisissez le nom ici",
+ "Enter_Normal": "Mode normal (envoyé avec Entrée)",
"Enter_to": "Entrée pour",
"Error": "Erreur",
- "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Erreur: Rocket.chat requiert l'activation de la fonction \"oplog tailing\" lorsqu'il fonctionne sur plusieurs instances",
- "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Veuillez vous assurer que MongoDB est en mode ReplicaSet et que la variable d'environnement MONGO_OPLOG_URL est définie correctement sur le serveur de l'application",
"error-action-not-allowed": "__action__ n'est pas autorisée",
"error-application-not-found": "Application introuvable",
"error-archived-duplicate-name": "Il y a un canal archivé avec le nom '__room_name__'",
@@ -427,29 +493,29 @@
"error-could-not-change-name": "Impossible de modifier le nom",
"error-could-not-change-username": "Impossible de modifier le nom d'utilisateur",
"error-delete-protected-role": "Impossible de supprimer un rôle protégé",
- "error-department-not-found": "Département introuvable",
+ "error-department-not-found": "Service introuvable",
+ "error-direct-message-file-upload-not-allowed": "L'envoi de fichier n'est pas autorisé dans les messages privés",
"error-duplicate-channel-name": "Un canal avec le nom '__channel_name__' existe déjà",
"error-email-domain-blacklisted": "Le domaine de l'adresse e-mail est sur liste noire",
- "error-email-send-failed": "Erreur lors de la tentative d'envoi d'email: __message__",
+ "error-email-send-failed": "Erreur lors de la tentative d'envoi d'e-mail : __message__",
"error-field-unavailable": "__field__ est déjà utilisé :(",
"error-file-too-large": "Le fichier est trop lourd",
"error-importer-not-defined": "L'importateur n'a pas été défini correctement, il manque la classe Import.",
"error-input-is-not-a-valid-field": "__input__ n'est pas un __field__ valide",
- "error-invalid-actionlink": "lien d'action non valide",
+ "error-invalid-actionlink": "Lien d'action non valide",
"error-invalid-arguments": "Arguments non valides",
"error-invalid-asset": "Ressource invalide",
"error-invalid-channel": "Canal non valide.",
"error-invalid-channel-start-with-chars": "Canal non valide. Commencez par @ ou #",
"error-invalid-custom-field": "Champ personnalisé invalide",
- "error-invalid-custom-field-name": "Nom de champ personnalisé invalide. Utilisez des lettres, des chiffres et des tirets (milieu et bas).",
+ "error-invalid-custom-field-name": "Nom de champ personnalisé invalide. Utilisez uniquement des lettres, des chiffres et des tirets (milieu et bas).",
"error-invalid-date": "Date fournie invalide.",
"error-invalid-description": "Description non valide",
"error-invalid-domain": "Domaine non valide",
"error-invalid-email": "Adresse e-mail __email__ non valide",
- "error-invalid-email-address": "Adresse email invalide",
+ "error-invalid-email-address": "Adresse e-mail invalide",
"error-invalid-file-height": "Hauteur du fichier non valide",
"error-invalid-file-type": "Type de fichier non valide",
- "error-direct-message-file-upload-not-allowed": "L'envoi de fichier n'est pas autorisé dans les messages directs",
"error-invalid-file-width": "Largeur du fichier non valide",
"error-invalid-from-address": "Vous avez entré un expéditeur invalide (champ De).",
"error-invalid-integration": "Intégration non valide",
@@ -457,7 +523,7 @@
"error-invalid-method": "Méthode non valide",
"error-invalid-name": "Nom invalide",
"error-invalid-password": "Mot de passe invalide",
- "error-invalid-redirectUri": "redirectUri invalide",
+ "error-invalid-redirectUri": "URI de redirection invalide",
"error-invalid-role": "Rôle non valide",
"error-invalid-room": "Salon invalide",
"error-invalid-room-name": "__room_name__ n'est pas un nom de salon valide, vous ne pouvez utiliser que des lettres, des nombres et des tirets (milieu et bas).",
@@ -484,12 +550,16 @@
"error-the-field-is-required": "Le champ __field__ est obligatoire.",
"error-too-many-requests": "Erreur, trop de demandes. Ralentissez, s'il vous plaît. Vous devez attendre __seconds__ secondes avant de réessayer.",
"error-user-is-not-activated": "L'utilisateur n'est pas activé",
+ "error-user-limit-exceeded": "Le nombre d'utilisateurs que vous essayez d'inviter pour #channel_name dépasse le nombre autorisé par l'administrateur",
"error-user-not-in-room": "L'utilisateur n'est pas dans ce salon.",
"error-user-registration-disabled": "L'inscription des nouveaux utilisateurs est désactivée",
"error-user-registration-secret": "L'inscription des utilisateurs n'est autorisée que depuis une URL Secrète",
"error-you-are-last-owner": "Vous êtes le dernier propriétaire. Veuillez choisir un nouveau propriétaire avant de quitter le salon.",
"Error_changing_password": "Erreur lors du changement de mot de passe",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Erreur: Rocket.chat requiert l'activation de la fonction \"oplog tailing\" lorsqu'il fonctionne sur plusieurs instances",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Veuillez vous assurer que MongoDB est en mode ReplicaSet et que la variable d'environnement MONGO_OPLOG_URL est définie correctement sur le serveur de l'application",
"Esc_to": "Échap pour",
+ "Event_Trigger_Description": "Sélectionner quel type d'événements déclencheront cette intégration WebHook Sortant",
"every_30_minutes": "Une fois toutes les 30 minutes",
"every_hour": "Une fois par heure",
"every_six_hours": "Une fois toutes les 6 heures",
@@ -499,24 +569,27 @@
"False": "Non",
"Favorite_Rooms": "Activer les salons favoris",
"Favorites": "Favoris",
- "Features_Enabled": "Caractéristiques Enabled",
+ "Features_Enabled": "Fonctionnalités activées",
"Field": "Champ",
"Field_removed": "Champ supprimé",
"Field_required": "Champs requis",
- "File_exceeds_allowed_size_of_bytes": "Le fichier dépasse la taille maximale autorisée : __size__ octets",
- "File_not_allowed_direct_messages": "L'envoi de fichier n'est pas autorisé dans les messages directs.",
- "File_type_is_not_accepted": "Ce tye de fichier n'est pas accepté.",
+ "File_exceeds_allowed_size_of_bytes": "Le fichier dépasse la taille maximale autorisée : __size__. ",
+ "File_not_allowed_direct_messages": "L'envoi de fichier n'est pas autorisé dans les messages privés.",
+ "File_type_is_not_accepted": "Ce type de fichier n'est pas accepté.",
+ "File_uploaded": "Fichier envoyé",
"FileUpload": "Envoi de fichiers",
- "FileUpload_Enabled": "Envois de fichiers activés",
"FileUpload_Disabled": "L'envoi de fichiers n'est pas activé.",
- "FileUpload_Enabled_Direct": "L'envoi de fichiers est activé dans les messages directs",
+ "FileUpload_Enabled": "Envois de fichiers activés",
+ "FileUpload_Enabled_Direct": "L'envoi de fichiers est activé dans les messages privés",
"FileUpload_File_Empty": "Fichier vide",
"FileUpload_FileSystemPath": "Chemin d'accès",
+ "FileUpload_GoogleStorage_Secret": "Secret Google Storage",
+ "FileUpload_GoogleStorage_Secret_Description": "Merci de suivre ces instructions et copiez le résultat ici.",
"FileUpload_MaxFileSize": "Taille maximale pour l'envoi de fichier (en octets)",
- "FileUpload_MediaType_NotAccepted": "Types de Fichiers Non Acceptés",
+ "FileUpload_MediaType_NotAccepted": "Types de fichiers non acceptés",
"FileUpload_MediaTypeWhiteList": "Types de média acceptés",
"FileUpload_MediaTypeWhiteListDescription": "Liste des types de média (séparés par des virgules). Laisser vide pour accepter tous les types de media.",
- "FileUpload_ProtectFiles": "Protéger les fichiers uploadés",
+ "FileUpload_ProtectFiles": "Protéger les fichiers envoyés",
"FileUpload_ProtectFilesDescription": "Seuls les utilisateurs authentifiés auront accès",
"FileUpload_S3_Acl": "Amazon S3 acl",
"FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
@@ -530,19 +603,21 @@
"FileUpload_Storage_Type": "Type de stockage",
"Flags": "Drapeaux",
"Follow_social_profiles": "Suivez-nous sur les réseaux sociaux, clonez le projet sur GitHub et partagez vos idées à propos de Rocket.Chat sur notre tableau Trello.",
+ "Fonts": "Polices",
"Food_and_Drink": "Nourriture & Boissons",
- "Footer": "Bas de page",
+ "Footer": "Pied de page",
"For_your_security_you_must_enter_your_current_password_to_continue": "Pour votre sécurité, vous devez ré-entrer votre mot de passe pour continuer",
"Force_Disable_OpLog_For_Cache": "Forcer la désactivation de la fonction OpLog pour le cache",
"Force_Disable_OpLog_For_Cache_Description": "N'utlisera pas la fonction OpLog pour syncroniser le cache même si elle est disponible.",
"Force_SSL": "Forcer l'utilisation de SSL",
"Force_SSL_Description": "*Attention !* _ForceSSL_ ne devrait jamais être utilisé avec un reverse proxy. Si vous utilisez un reverse proxy, vous devriez y gérer la redirection. Cette option existe pour des déploiements tels que Heroku, qui n'autorisent pas la configuration de redirection au niveau des reverse proxy.",
"Forgot_password": "Mot de passe oublié",
- "Forgot_Password_Email_Subject": "[Site_Name] - Récupération du mot de passe",
"Forgot_Password_Email": "Cliquez ici pour remettre à zéro votre mot de passe.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Récupération du mot de passe",
+ "Forgot_password_section": "Mot de passe oublié",
"Forward": "Transmettre",
"Forward_chat": "Transmettre la conversation",
- "Forward_to_department": "Transmettre au département",
+ "Forward_to_department": "Transmettre au service",
"Forward_to_user": "Transmettre à l'utilisateur",
"Frequently_Used": "Fréquemment utilisé",
"Friday": "Vendredi",
@@ -557,56 +632,63 @@
"GoogleTagManager_id": "Google Tag Manager ID",
"Guest_Pool": "Invités en attente",
"Hash": "Hachage",
- "Header": "En-tête",
+ "Header": "Entête",
+ "Header_and_Footer": "Entêtes et Pied de page",
"Hidden": "Caché",
"Hide_Avatars": "Masquer les avatars",
- "Hide_flextab": "Cacher le volet de réglages du canal par un clique",
- "Hide_Group_Warning": "Êtes-vous sûr(e) de vouloir cacher le groupe \"%s\" ?",
- "Hide_Private_Warning": "Êtes-vous sûr(e) de vouloir cacher la discussion avec \"%s\" ?",
- "Hide_room": "Cacher le salon",
- "Hide_Room_Warning": "Êtes-vous sûr(e) de vouloir cacher le salon \"%s\" ?",
- "Hide_usernames": "Cacher les noms d'utilisateur",
+ "Hide_flextab": "Masquer le volet de réglages du canal par un clique",
+ "Hide_Group_Warning": "Êtes-vous sûr(e) de vouloir masquer le groupe \"%s\" ?",
+ "Hide_Private_Warning": "Êtes-vous sûr(e) de vouloir masquer la discussion avec \"%s\" ?",
+ "Hide_roles": "Masquer les rôles",
+ "Hide_room": "Masquer le salon",
+ "Hide_Room_Warning": "Êtes-vous sûr(e) de vouloir masquer le salon \"%s\" ?",
+ "Hide_usernames": "Masquer les noms d'utilisateur",
"Highlights": "Mises en avant",
- "Highlights_How_To": "Pour être notifié(e) lorsque quelqu'un écrit un mot ou une phrase spécifique, ajoutez le/la ici. Vous pouvez les séparer par une virgule. Les termes surveillés ne sont pas sensibles à la casse.",
+ "Highlights_How_To": "Pour être notifié(e) lorsque quelqu'un écrit un mot ou une phrase spécifique, ajoutez le/la ici. Vous pouvez les séparer par des virgules. Les termes surveillés ne sont pas sensibles à la casse.",
"Highlights_List": "Mots surveillés",
"History": "Historique",
"Host": "Hôte",
"hours": "heures",
"Hours": "Heures",
- "How_friendly_was_the_chat_agent": "L'assistant du chat était-il amical ?",
- "How_knowledgeable_was_the_chat_agent": "L'assistant du chat était-il clair ?",
+ "How_friendly_was_the_chat_agent": "Votre interlocuteur était-il amical ?",
+ "How_knowledgeable_was_the_chat_agent": "Votre interlocuteur était-il clair ?",
"How_long_to_wait_after_agent_goes_offline": "Délai d'attente après que l'agent soit hors ligne",
- "How_responsive_was_the_chat_agent": "L'assistant du chat avait-il des réponses adaptées ?",
+ "How_responsive_was_the_chat_agent": "Votre interlocuteur avait-il des réponses adaptées ?",
"How_satisfied_were_you_with_this_chat": "Étiez-vous satisfait de ce chat?",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "Comment gérer les sessions ouvertes lorsque l'asistant passe hors ligne",
+ "If_this_email_is_registered": "Si cet e-mail est enregistré, les instructions pour réinitialiser votre mot de passe vous serons envoyées. Si vous ne recevez pas d'email rapidement, merci de revenir et d'essayer à nouveau.",
"If_you_are_sure_type_in_your_password": "Si vous êtes sûr(e), entrez votre mot de passe :",
"If_you_are_sure_type_in_your_username": "Si vous êtes certain(e), saisissez votre nom d'utilisateur :",
+ "Iframe_Integration": "Intégration Iframe",
"Iframe_Integration_receive_enable": "Activer la réception",
- "Iframe_Integration_receive_enable_Description": "Autoriser la fenêtre parente à envoyer des commandes à Rocket.Chat",
+ "Iframe_Integration_receive_enable_Description": "Autoriser la fenêtre parente à envoyer des commandes à Rocket.Chat.",
"Iframe_Integration_receive_origin": "Recevoir les origines",
"Iframe_Integration_receive_origin_Description": "Seules les pages ayant une origine donnée seront autorisée à envoyer des commandes ou `*` pour toutes les origines. Vous pouvez utiliser de multiples valeurs séparées par des` ,`. Exemple : `http://localhost,https://localhost`",
"Iframe_Integration_send_enable": "Activer l'envoi",
"Iframe_Integration_send_enable_Description": "Envoyer les événements à la fenêtre parente",
"Iframe_Integration_send_target_origin": "Envoyer la cible origine",
"Iframe_Integration_send_target_origin_Description": "Seules les pages ayant une origine donnée seront autorisée à recevoir des commandes ou `*` pour toutes les origines. Exemple : `http://localhost`",
+ "Impersonate_user": "Incarner l'utilisateur",
"Importer_Archived": "Archivé",
"Importer_done": "Importation réussie !",
- "Importer_finishing": "Finalisation de l'importation",
+ "Importer_finishing": "Finalisation de l'importation.",
"Importer_From_Description": "Importer les données de __from__ dans Rocket.Chat.",
- "Importer_import_cancelled": "Importation annulée",
- "Importer_import_failed": "Un erreur est survenue pendant l'importation.",
+ "Importer_import_cancelled": "Importation annulée.",
+ "Importer_import_failed": "Un erreur est survenue lors de l'importation.",
"Importer_importing_channels": "Importation des canaux.",
"Importer_importing_messages": "Importation des messages.",
"Importer_importing_started": "Début de l'importation.",
"Importer_importing_users": "Importation des utilisateurs.",
- "Importer_not_in_progress": "L'importateur n'est pas en cours d'exécution.",
+ "Importer_not_in_progress": "L'import n'est pas en cours d'exécution.",
"Importer_Prepare_Restart_Import": "Recommencer l’Importation",
"Importer_Prepare_Start_Import": "Commencer l'Importation",
- "Importer_Prepare_Uncheck_Archived_Channels": "Désélectionner les Canaux Archivés",
- "Importer_Prepare_Uncheck_Deleted_Users": "Désélectionner les Utilisateurs Supprimés",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Désélectionner les canaux archivés",
+ "Importer_Prepare_Uncheck_Deleted_Users": "Désélectionner les utilisateurs supprimés",
"Importer_progress_error": "Impossible d'obtenir l'état de l'importation.",
"Importer_setup_error": "Une erreur est survenue lors du paramétrage de l'importateur.",
"Importer_Source_File": "Sélection du fichier source",
- "Incoming_Livechats": "Arrivée de nouveaux Livechats",
+ "Incoming_Livechats": "Arrivée de nouveaux chats en direct",
+ "Incoming_WebHook": "WebHook entrant",
"inline_code": "Ligne de code",
"Install_Extension": "Installer l'extension",
"Install_FxOs": "Installez Rocket.Chat dans votre Firefox",
@@ -616,47 +698,73 @@
"Installation": "Installation",
"Installed_at": "installé à",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instructions à votre visiteur de remplir le formulaire pour envoyer un message",
- "Impersonate_user": "Incarner l'utilisateur",
"Integration_added": "L'intégration a été ajoutée",
+ "Integration_Advanced_Settings": "Paramètres avancés",
"Integration_Incoming_WebHook": "Intégration WebHook Entrant",
"Integration_New": "Nouvelle intégration",
"Integration_Outgoing_WebHook": "Intégration WebHook Sortant",
+ "Integration_Outgoing_WebHook_History": "Historique de l'intégration WebHook Sortant",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Données passées pour intégration",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Données passées pour URL",
+ "Integration_Outgoing_WebHook_History_Http_Response": "Réponse HTTP",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "Erreur Réponse HTTP",
+ "Integration_Outgoing_WebHook_No_History": "L'intégration WebHook sortant n'a pas encore d'historique enregistré.",
"Integration_updated": "L'intégration a été mise à jour",
"Integrations": "Intégrations",
+ "Integrations_for_all_channels": "Entrez all_public_channels pour écouter sur tous les canaux publics, all_private_groups pour écouter sur tous les groupes privés, et all_direct_messages pour écouter sur tous les messages privés.",
+ "Integrations_Outgoing_Type_FileUploaded": "Fichier envoyé",
+ "Integrations_Outgoing_Type_RoomArchived": "Salon archivé",
+ "Integrations_Outgoing_Type_RoomCreated": "Salon créé (public et privé)",
+ "Integrations_Outgoing_Type_RoomJoined": "L'utilisateur a rejoint le salon",
+ "Integrations_Outgoing_Type_RoomLeft": "L'utilisateur a quitté le salon",
+ "Integrations_Outgoing_Type_SendMessage": "Message envoyé",
+ "Integrations_Outgoing_Type_UserCreated": "Utilisateur créé",
"InternalHubot": "Hubot interne",
"InternalHubot_ScriptsToLoad": "Scripts à charger",
"InternalHubot_ScriptsToLoad_Description": "Veuillez entrer une liste de scripts séparés par des virgules à charger depuis https://github.com/github/hubot-scripts/tree/master/src/scripts",
"InternalHubot_Username_Description": "Cela doit être un nom d'utilisateur valide d'un bot enregistré sur votre serveur.",
"Invalid_confirm_pass": "Les mots de passe renseignés ne sont pas les mêmes",
"Invalid_email": "L'adresse e-mail saisie est invalide",
- "Invalid_Export_File": "Le fichier transmis n'est pas un fichier d'exportation valide de %s",
+ "Invalid_Export_File": "Le fichier envoyé n'est pas un fichier d'exportation valide de %s",
"Invalid_Import_File_Type": "Format du fichier d'importation invalide.",
"Invalid_name": "Le nom doit être renseigné",
"Invalid_notification_setting_s": "Paramètre de notification invalide : %s",
"Invalid_pass": "Le mot de passe doit être renseigné",
"Invalid_room_name": "%s n'est pas un nom de salon valide. Utilisez uniquement des lettres, des chiffres et des tirets (milieu et bas)",
"Invalid_secret_URL_message": "L'URL fournie est invalide.",
+ "Invalid_setting_s": "Paramètre invalide : %s",
"invisible": "invisible",
"Invisible": "Invisible",
+ "Invitation": "Invitation",
"Invitation_HTML": "Contenu HTML de l'invitation",
"Invitation_HTML_Default": "Vous avez été invité à rejoindre [Site_Name] Accédez à [Site_URL] et essayez la meilleure solution de chat open source disponible aujourd'hui !
",
- "Invitation_HTML_Description": "Vous pouvez utiliser les variables suivantes :[email] pour l'adresse e-mail du destinataire, [Site_Name] et [Site_URL] pour le nom de l'application et son URL respectivement. ",
+ "Invitation_HTML_Description": "Vous pouvez utiliser les variables suivantes :[email] pour l'adresse e-mail du destinataire, [Site_Name] et [Site_URL] pour le nom de l'application et son URL respectivement. ",
"Invitation_Subject": "Sujet de l'invitation",
"Invitation_Subject_Default": "Vous avez été invité à [Site_Name]",
"Invite_user_to_join_channel": "Inviter un utilisateur à rejoindre le canal",
+ "Invite_user_to_join_channel_all_from": "Inviter tous les utilisateurs de [#channel] à rejoindre ce salon",
+ "Invite_user_to_join_channel_all_to": "Inviter tous les utilisateurs de ce canal à rejoindre [#channel]",
"Invite_Users": "Inviter des utilisateurs",
+ "IRC_Channel_Join": "Sortie de la commande JOIN.",
+ "IRC_Channel_Leave": "Sortie de la commande PART.",
+ "IRC_Channel_Users": "Sortie de la commande NAMES.",
+ "IRC_Channel_Users_End": "Fin de sortie de la commande NAMES.",
+ "IRC_Hostname": "Le serveur d'hôte IRC auquel se connecter.",
+ "IRC_Login_Fail": "Sortie après une connexion échouée au serveur IRC.",
+ "IRC_Login_Success": "Sortie après une connexion réussie au serveur IRC.",
+ "IRC_Private_Message": "Sortie de la commande PRIVMSG.",
+ "IRC_Quit": "Sortie après avoir quitté une session IRC.",
"is_also_typing": "est également en train d'écrire",
"is_also_typing_female": "est également en train d'écrire",
"is_also_typing_male": "est également en train d'écrire",
"is_typing": "est en train d'écrire",
"is_typing_female": "est en train d'écrire",
"is_typing_male": "est en train d'écrire",
- "IRC_Hostname": "Le serveur d'hôte IRC auquel se sonnecter",
"It_works": "Ça marche",
"italics": "italique",
"Jitsi_Chrome_Extension": "Chrome Extension Id",
"Jitsi_Enable_Channels": "Activer dans les canaux",
- "join": "Rejoindre\n",
+ "join": "Rejoindre",
"Join_audio_call": "Rejoindre l'appel audio",
"Join_default_channels": "Rejoindre les canaux par défaut",
"Join_the_Community": "Rejoignez la communauté",
@@ -668,11 +776,11 @@
"Jump_to_message": "Aller au message",
"Jump_to_recent_messages": "Aller aux messages récents",
"Katex_Dollar_Syntax": "Autoriser Dollar Syntaxe",
- "Katex_Dollar_Syntax_Description": "Autoriser avec $$ bloc Katex $$ et $ Katex inline $ syntaxes",
+ "Katex_Dollar_Syntax_Description": "Autoriser les syntaxes : $$bloc katex$$ et $katex inline$",
"Katex_Enabled": "Katex activé",
"Katex_Enabled_Description": "Autoriser l' utilisation Katex pour les mathématiques photocomposition dans les messages",
"Katex_Parenthesis_Syntax": "Autoriser Parenthesis Syntaxe",
- "Katex_Parenthesis_Syntax_Description": "Autoriser l'utilisation \\ [bloc Katex \\] et \\ (inline Katex \\) syntaxes",
+ "Katex_Parenthesis_Syntax_Description": "Autoriser les syntaxes : \\[bloc katex\\] et \\(inline katex\\)",
"Knowledge_Base": "Base de connaissances",
"Label": "Label",
"Language": "Langue",
@@ -690,72 +798,63 @@
"Layout_Terms_of_Service": "Conditions de service",
"LDAP": "LDAP",
"LDAP_CA_Cert": "Certificat CA (Autorité de certification)",
- "LDAP_Custom_Domain_Search": "Domaine de recherche personnalisé",
- "LDAP_Custom_Domain_Search_Description": "Un bout de JSON qui contrôle la liaison et la connexion et qui a le format :{\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domaine par défaut",
- "LDAP_Description": "Un LDAP est une base de données hiérarchique que de nombreuses entreprises utilisent pour fournir une authentification unique à travers leurs services - l'utilisateur partage un mot de passe entre plusieurs sites et services. Pour avoir plus d'informations sur la configuration avancée et voir des exemples, consulter notre wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/ .",
- "LDAP_Domain_Base": "Domaine de base",
- "LDAP_Domain_Base_Description": "Le chemin complet du Distinguished Name (DN) d'un sous arbre LDAP dans lequel vous souhaitez chercher les utilisateurs et les groupes. Vous pouvez en ajouter autant que vous voulez ; cependant, chaque groupe doit être défini dans le même domaine de base que les utilisateurs qui le composent. Si vous spécifiez des restrictions sur des groupes d'utilisateurs, seuls les utilisateurs appartenant à ces groupes seront dans le périmètre de la recherche. Nous recommandons de spécifier le top level de votre arbre LDAP en tant que domaine de base et d'utiliser le filtre de recherche pour contrôler l'accès.",
- "LDAP_Domain_Search_Filter": "Filtre pour la recherche dans le domaine",
- "LDAP_Domain_Search_Filter_Description": "Si renseigné, seuls les utilisateurs qui correspondent à ce filtre seront autorisés à se connecter. Si aucun filtre n'est spécifié, tous les utilisateurs dans le spectre du domaine de base spécifié seront capable de se connecter. Exemple pour ActiveDirectory : `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Exemple pour OpenLDAP (recherche étendue de correspondance) : `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Catégorie d'objet pour la recherche dans le domaine",
- "LDAP_Domain_Search_Object_Category_Description": "L'*objectCategory* qui identifie vos utilisateurs. Laisser vide pour *OpenLDAP*. Par exemple : `personne`, etc.",
- "LDAP_Domain_Search_Object_Class": "Classe d'objet pour la recherche dans le domaine",
- "LDAP_Domain_Search_Object_Class_Description": "L'*objectClass* qui identifie vos utilisateurs. Par exemple : `organizationalPerson`, `user`, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Mot de passe pour la recherche dans le domaine",
- "LDAP_Domain_Search_Password_Description": "Le mot de passe pour l'utilisateur utilisé pour la recherche dans le domaine.",
- "LDAP_Domain_Search_User": "Utilisateur pour la recherche dans le domaine",
- "LDAP_Domain_Search_User_Description": "L'utilisateur LDAP qui réalise les recherches d'utilisateur pour authentifier les autres utilisateurs quand ils se connectent. Il s'agit typiquement d'un compte de service créé spécialement pour l'intégration de tierces parties. Utilisez un nom complet, tel que `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "ID de l'utilisateur pour la recherche dans le domaine",
- "LDAP_Domain_Search_User_ID_Description": "L'attribut LDAP qui identifie l'utilisateur LDAP qui essaye de s'authentifier. Ce champ est `sAMAccountName` pour la plupart des installations Active Directory, mais cela peut être `uid` pour d'autres solutions de LDAP, comme OpenLDAP. Vous pouvez utiliser `mail` pour identifier les utilisateurs par leur adresse e-mail ou n'importe quel autre attribut que vous souhaitez. Vous pouvez utiliser plusieurs valeurs séparées par des virgules pour permettre aux utilisateur de s'identifier en utilisant plusieurs identifiants comme le nom d'utilisateur ou l'adresse e-mail.",
- "LDAP_Enable": "Activer LDAP",
+ "LDAP_Description": "Un LDAP est une base de données hiérarchique que de nombreuses entreprises utilisent pour fournir une authentification unique à travers leurs services - l'utilisateur partage un mot de passe entre plusieurs sites et services. Pour avoir plus d'informations sur la configuration avancée et voir des exemples, consulter notre wiki : https://rocket.chat/docs/administrator-guides/authentication/ldap/ .",
+ "LDAP_BaseDN_Description": "Le chemin complet du Distinguished Name (DN) d'un sous arbre LDAP dans lequel vous souhaitez chercher les utilisateurs et les groupes. Vous pouvez en ajouter autant que vous voulez ; cependant, chaque groupe doit être défini dans le même domaine de base que les utilisateurs qui le composent. Si vous spécifiez des restrictions sur des groupes d'utilisateurs, seuls les utilisateurs appartenant à ces groupes seront dans le périmètre de la recherche. Nous recommandons de spécifier le top level de votre arbre LDAP en tant que domaine de base et d'utiliser le filtre de recherche pour contrôler l'accès.",
+ "LDAP_User_Search_Field_Description": "L'attribut LDAP qui identifie l'utilisateur LDAP qui essaye de s'authentifier. Ce champ est `sAMAccountName` pour la plupart des installations Active Directory, mais cela peut être `uid` pour d'autres solutions de LDAP, comme OpenLDAP. Vous pouvez utiliser `mail` pour identifier les utilisateurs par leur adresse e-mail ou n'importe quel autre attribut que vous souhaitez. Vous pouvez utiliser plusieurs valeurs séparées par des virgules pour permettre aux utilisateur de s'identifier en utilisant plusieurs identifiants comme le nom d'utilisateur ou l'adresse e-mail.",
+ "LDAP_User_Search_Filter_Description": "Si renseigné, seuls les utilisateurs qui correspondent à ce filtre seront autorisés à se connecter. Si aucun filtre n'est spécifié, tous les utilisateurs dans le spectre du domaine de base spécifié seront capable de se connecter. Exemple pour ActiveDirectory : `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Exemple pour OpenLDAP (recherche étendue de correspondance) : `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "L'utilisateur LDAP qui réalise les recherches d'utilisateur pour authentifier les autres utilisateurs quand ils se connectent. Il s'agit typiquement d'un compte de service créé spécialement pour l'intégration de tierces parties. Utilisez un nom complet, tel que `cn=Administrator,cn=Users,dc=Example,dc=com`.",
+ "LDAP_Enable": "Activer",
"LDAP_Enable_Description": "Essayer d'utiliser LDAP pour l'authentification.",
"LDAP_Encryption": "Chiffrement",
"LDAP_Encryption_Description": "La méthode de chiffrement utilisée pour sécuriser les communications avec le serveur LDAP. Parmi les exemples on trouve `plain` (pas de chiffrement), `SSL/LDAPS` (chiffrement dès le début) et `StartTLS` (chiffrement une fois la connexion établie).",
+ "LDAP_Group_Filter_Enable": "Activer le filtre des utilisateurs sur un groupe LDAP",
+ "LDAP_Group_Filter_Enable_Description": "Restreint l'accès aux utilisateurs d'un groupe LDAP Utile pour les serveurs OpenLDAP sans recouvrement qui ne permettent pas le filtre *memberOf* ",
+ "LDAP_Group_Filter_Group_Name": "Nom du groupe",
+ "LDAP_Group_Filter_Group_Name_Description": "Groupe auquel appartient l'utilisateur",
"LDAP_Host": "Hôte",
"LDAP_Host_Description": "L'hôte LDAP, par exemple `ldap.exemple.com` ou `10.0.0.30`.",
- "LDAP_Import_Users": "Importer les utilisateurs LDAP",
- "LDAP_Import_Users_Description": "Si VRAI les processus de synchronisation importeront l'ensemble des utilisateurs LDAP \n\n*Attention !* Spécifiez les filtres de recherche pour ne pas importer trop d'utilisateurs.",
+ "LDAP_Import_Users_Description": "Si OUI les processus de synchronisation importeront l'ensemble des utilisateurs LDAP \n*Attention !* Spécifiez les filtres de recherche pour ne pas importer trop d'utilisateurs.",
+ "LDAP_Login_Fallback": "Login Fallback",
+ "LDAP_Login_Fallback_Description": "Si l'authentification LDAP échoue, essaye de se connecter avec un compte local. Aide quand le LDAP est inaccessible.",
"LDAP_Merge_Existing_Users": "Fusionner les utilisateurs existants",
"LDAP_Merge_Existing_Users_Description": "*Attention !* Si vous importez un utilisateur depuis le LDAP et qu'un utilisateur avec le même nom existe déjà, les informations et le mot de passe du LDAP lui seront attribués.",
- "LDAP_Port": "Port LDAP",
- "LDAP_Port_Description": "Port pour accéder au LDAP ( ex : 389 ou 636 pour LDAPS)",
+ "LDAP_Port": "Port",
+ "LDAP_Port_Description": "Port pour accéder au LDAP (ex : 389 ou 636 pour LDAPS)",
"LDAP_Reject_Unauthorized": "Rejeter les personnes non autorisées",
- "LDAP_Sync_User_Avatar": "Synchronisation de l' Avatar Utilisateur",
+ "LDAP_Sync_User_Avatar": "Synchronisation de l'avatar utilisateur",
"LDAP_Sync_User_Data": "Synchronisation des données",
- "LDAP_Sync_User_Data_Description": "Garder les données de l'utilisateur synchronisées avec celles du serveur lors de la connexion (par exemple: nom, adresse e-mail).",
+ "LDAP_Sync_User_Data_Description": "Garder les données de l'utilisateur synchronisées avec celles du serveur lors de la connexion (par exemple : nom, adresse e-mail).",
"LDAP_Sync_User_Data_FieldMap": "Liste des champs utilisateur",
- "LDAP_Sync_User_Data_FieldMap_Description": "Configurer la façon dont les champs de compte utilisateur (comme l'adresse e-mail) sont remplis à partir d'un enregistrement dans l'annuaire LDAP (une fois trouvé). À titre d'exemple, {\"cn\": \"nom\", \"mail\": \"email\"} choisira le nom lisible d'une personne à partir de l'attribut cn, et son adresse e-mail à partir de l'attribut mail. Les champs disponibles comprennent le nom et l'adresse e-mail.",
- "LDAP_Sync_Users": "Synchronisation des Utilisateurs",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configurer la façon dont les champs de compte utilisateur (comme l'adresse e-mail) sont remplis à partir d'un enregistrement dans l'annuaire LDAP (une fois trouvé). À titre d'exemple, {\"cn\": \"nom\", \"mail\": \"email\"} choisira le nom lisible d'une personne à partir de l'attribut cn, et son adresse e-mail à partir de l'attribut mail. Les champs disponibles comprennent `name`et `email`.",
"LDAP_Test_Connection": "Tester la connexion",
"LDAP_Unique_Identifier_Field": "Champ de l'identifiant unique",
"LDAP_Unique_Identifier_Field_Description": "Le champ utilisé pour lier l'utilisateur LDAP à l'utilisateur Rocket.Chat. Vous pouvez renseigner plusieurs valeurs séparées par des virgules pour obtenir la valeur depuis l'enregistrement LDAP. La valeur par défaut est `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Utiliser la recherche personnalisée dans le domaine",
- "LDAP_Use_Custom_Domain_Search_Description": "Écrivez vos propres filtres pour rechercher les utilisateurs dans le serveur LDAP.",
"LDAP_Username_Field": "Champs du nom d'utilisateur",
- "LDAP_Username_Field_Description": "Le champ qui sera utilisé en tant que *nom d'utilisateur* pour les nouveaux utilisateurs. Laisser vide pour utiliser le nom d'utilisateur renseigné sur la page de connexion. La valeur par défaut est `sAMAccountName`.",
- "LDAP_Group_Filter_Group_Name": "Nom du groupe",
+ "LDAP_Username_Field_Description": "Champ utilisé en tant que *nom d'utilisateur* pour les nouveaux utilisateurs. Laisser vide pour utiliser le nom d'utilisateur renseigné sur la page de connexion. Vous pouvez aussi utiliser un modèle à base de tags, comme `#{givenName}.#{sn}`. La valeur par défaut est `sAMAccountName`.",
"Least_Amount": "Le minimum",
"Leave_Group_Warning": "Êtes-vous sûr(e) de vouloir quitter le groupe \"%s\" ?",
"Leave_Private_Warning": "Êtes-vous sûr(e) de vouloir quitter la discussion avec \"%s\" ?",
"Leave_room": "Quitter le salon",
"Leave_Room_Warning": "Êtes-vous sûr(e) de vouloir quitter le salon \"%s\" ?",
+ "Leave_the_current_channel": "Quitter le salon",
"line": "ligne",
- "List_of_Channels": "Liste des chaînes",
- "List_of_Direct_Messages": "Liste des Messages Privés",
+ "List_of_Channels": "Liste des canaux",
+ "List_of_Direct_Messages": "Liste des messages privés",
"Livechat_agents": "Assistants du chat en direct",
+ "Livechat_AllowedDomainsList": "Domaines autorisés pour le chat en direct",
"Livechat_Dashboard": "Tableau de bord du chat en direct",
"Livechat_enabled": "Chat en direct activé",
- "Livechat_forward_open_chats": "chats Forward ouverts",
"Livechat_forward_open_chats_timeout": "Timeout (en secondes) de transmettre les chats",
"Livechat_guest_count": "Compteur d'invités",
- "Livechat_Inquiry_Already_Taken": "Demande de Livechat déjà prise en compte",
+ "Livechat_Inquiry_Already_Taken": "Demande de chat en direct déjà prise en compte",
"Livechat_managers": "Managers du chat en direct",
- "Livechat_offline": "Live Chat hors ligne",
- "Livechat_online": "Live Chat en ligne",
- "Livechat_Queue": "File d'attente de Livechat",
- "Livechat_room_count": "Livechat room count",
- "Livechat_Routing_Method": "Méthode de routage du Livechat",
+ "Livechat_offline": "Chat en direct hors ligne",
+ "Livechat_online": "Chat en direct en ligne",
+ "Livechat_open_inquiery_show_connecting": "Afficher le message de connexion au lieu de la zone de saisie lorsque l'invité n'est pas encore en relation avec un assistant",
+ "Livechat_Queue": "File d'attente de Chat en direct",
+ "Livechat_room_count": "Nombre de salons de chat en direct",
+ "Livechat_Routing_Method": "Méthode de routage du chat en direct",
"Livechat_Take_Confirm": "Voulez-vous répondre à ce client ?",
"Livechat_title": "Titre du chat en direct",
"Livechat_title_color": "Couleur d'arrière plan du titre du chat en direct",
@@ -781,11 +880,11 @@
"Mail_Messages_Instructions": "Choisissez les messages que vous souhaitez envoyer par e-mail en cliquant dessus",
"Mail_Messages_Subject": "Voici une sélection de messages de \"%s\"",
"Mailer": "Envoi d'e-mail",
- "Mailer_body_tags": "Vous devez utiliser [unsubscribe] pour le lien de désinscription. Vous pouvez utiliser [name], [fname], [lname] pour le nom complet de l'utilisateur, le prénom et le nom de famille respectivement. Vous pouvez utiliser [email] pour l'adresse e-mail de l'utilisateur.",
+ "Mailer_body_tags": "Vous devez utiliser [unsubscribe] pour le lien de désinscription. Vous pouvez utiliser respectivement [name], [fname], [lname] pour le nom complet de l'utilisateur, le prénom et le nom de famille. Vous pouvez utiliser [email] pour l'adresse e-mail de l'utilisateur.",
"Mailing": "E-mailing",
"Make_Admin": "Promouvoir administrateur",
"Manager_added": "Manager ajouté",
- "Manager_removed": "Manager retiré",
+ "Manager_removed": "Manager supprimé",
"Managing_assets": "Gestion des ressources",
"Managing_integrations": "Gestion des intégrations",
"MapView_Enabled": "Activer Mapview",
@@ -799,6 +898,8 @@
"Markdown_SupportSchemesForLink_Description": "Liste de schémas séparés par des virgules",
"Max_length_is": "La longueur maximale est %s",
"Members_List": "Liste des membres",
+ "mention-all": "Mention @all",
+ "mention-all_description": "Autorisation d'utiliser la mention @all",
"Mentions": "Mentions",
"Mentions_default": "Mentions (défaut)",
"Message": "Message",
@@ -812,36 +913,43 @@
"Message_AllowPinning": "Autoriser l'épinglement de message",
"Message_AllowPinning_Description": "Autoriser les messages à être épinglés à n'importe quel canal.",
"Message_AllowStarring": "Autoriser les favoris pour les messages",
- "Message_AlwaysSearchRegExp": "Toujours rechercher l'aide de RegExp",
- "Message_AlwaysSearchRegExp_Description": "Nous vous recommandons de mettre `true` si votre langue ne sont pas pris en charge sur MongoDB recherche de texte .",
+ "Message_AlwaysSearchRegExp": "Toujours rechercher en utilisant des expressions régulières",
+ "Message_AlwaysSearchRegExp_Description": "Nous vous recommandons de mettre `Oui` si votre langue ne sont pas pris en charge sur MongoDB recherche de texte .",
"Message_AudioRecorderEnabled": "Enregistrement audio activé",
- "Message_AudioRecorderEnabledDescription": "Nécessite que les fichiers de type « audio/wav » soient acceptés en tant que média dans les réglages d'envoi de fichiers.",
+ "Message_AudioRecorderEnabledDescription": "Nécessite que le type de média « audio/wav » soit accepté dans les paramètres d'envoi des fichiers.",
"Message_BadWordsFilterList": "Ajouter des mots interdits à la liste noire",
- "Message_BadWordsFilterListDescription": "Ajouter une liste séparée par des virgules de mots interdits au filtre",
- "Message_DateFormat": "Format de Date",
+ "Message_BadWordsFilterListDescription": "Ajouter une liste de mots interdits au filtre, séparés par des virgules ",
+ "Message_DateFormat": "Format de la date",
"Message_DateFormat_Description": "Voir aussi : Moment.js ",
"Message_deleting_blocked": "Ce message ne peut plus être supprimé",
"Message_editing": "Édition des messages",
"Message_GroupingPeriod": "Période de regroupement (en secondes)",
"Message_GroupingPeriodDescription": "Les messages seront regroupés avec les messages précédents si ils sont du même utilisateur et si le temps écoulé est inférieur au temps indiqué en secondes.",
+ "Message_HideType_au": "Masquer les messages \"Utilisateur ajouté\"",
+ "Message_HideType_mute_unmute": "Masquer les messages \"Utilisateur rendu muet / a retrouvé la parole\"",
+ "Message_HideType_ru": "Masquer les messages \"Utilisateur éjecté\"",
+ "Message_HideType_uj": "Masquer les messages \"L'utilisateur a rejoint\"",
+ "Message_HideType_ul": "Masquer les messages \"L'utilisateur a quitté\"",
"Message_KeepHistory": "Conserver l'historique des messages",
"Message_MaxAll": "Taille de canal maximale pour le message ALL",
"Message_MaxAllowedSize": "Taille maximale d'un message",
"Message_pinning": "Épingler des messages",
"Message_removed": "Message supprimé",
- "Message_SetNameToAliasEnabled": "Changer le nom d'utilisateur pour un alias dans le message",
+ "Message_SetNameToAliasEnabled": "Définir un nom d'utilisateur utilisé comme alias dans les messages",
"Message_SetNameToAliasEnabled_Description": "Seulement si vous n'avez pas mis un alias. Les anciens messages alias ne sont pas changé si l'utilisateur a changé le nom",
"Message_ShowDeletedStatus": "Afficher le statut de suppression",
"Message_ShowEditedStatus": "Afficher le statut de modification",
"Message_ShowFormattingTips": "Afficher les astuces de mise en forme",
"Message_starring": "Mettre un message en favoris",
- "Message_TimeFormat": "Format de la date et heure",
+ "Message_TimeAndDateFormat": "Format de l'heure et de la date",
+ "Message_TimeAndDateFormat_Description": "Voir aussi : Moment.js ",
+ "Message_TimeFormat": "Format de l'heure",
"Message_TimeFormat_Description": "Voir aussi : Moment.js ",
"Message_too_long": "Message trop long",
"Message_VideoRecorderEnabled": "Enregistreur vidéo activé",
- "Message_VideoRecorderEnabledDescription": "Nécéssite que le type de média \"video/webm\" soit accepté dans les paramètres d'envoi des fichiers.",
+ "Message_VideoRecorderEnabledDescription": "Nécessite que le type de média \"video/webm\" soit accepté dans les paramètres d'envoi des fichiers.",
"Messages": "Messages",
- "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Les messages envoyés au WebHook Entrant seront postés ici",
+ "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Les messages envoyés au WebHook Entrant seront postés ici.",
"Meta": "Meta",
"Meta_fb_app_id": "App ID Facebook",
"Meta_google-site-verification": "Google Site Verification",
@@ -853,7 +961,7 @@
"Monday": "Lundi",
"Monitor_history_for_changes_on": "Surveiller l'historique des changements sur",
"More_channels": "Plus de canaux",
- "More_direct_messages": "Plus de Messages Privés",
+ "More_direct_messages": "Plus de messages privés",
"More_groups": "Davantage de groupes",
"More_unreads": "Davantage de messages non lus",
"Msgs": "Messages",
@@ -866,12 +974,12 @@
"N_new_messages": "%s nouveaux messages",
"Name": "Nom",
"Name_cant_be_empty": "Le nom ne peut pas être vide",
- "Name_of_agent": "Nom de l'assistant",
+ "Name_of_agent": "Nom de l'agent",
"Name_optional": "Nom (optionnel)",
"Navigation_History": "Historique de navigation",
"New_Application": "Nouvelle application",
"New_Custom_Field": "Nouveau champ personnalisé",
- "New_Department": "Nouveau département",
+ "New_Department": "Nouveau service",
"New_integration": "Nouvelle intégration",
"New_logs": "Nouveaux journaux",
"New_Message_Notification": "Notification de nouveau message",
@@ -879,10 +987,12 @@
"New_password": "Nouveau mot de passe",
"New_role": "Nouveau rôle",
"New_Room_Notification": "Notification de nouveau salon",
- "No_available_agents_to_transfer": "Aucun assistant disponible pour le transfert",
+ "New_Trigger": "Nouveau déclencheur",
+ "New_videocall_request": "Nouvelle demande d'appel vidéo",
+ "No_available_agents_to_transfer": "Aucun agent disponible pour le transfert",
"No_channel_with_name_%s_was_found": "Aucun canal nommé \"%s\" n'a été trouvé !",
"No_channels_yet": "Vous ne faites partie d’aucun canal pour le moment.",
- "No_direct_messages_yet": "Vous n'avez pris part à aucune discussion privée pour le moment.",
+ "No_direct_messages_yet": "Vous n'avez pris part à aucune discussion pour le moment.",
"No_Encryption": "Pas de Chiffrement",
"No_group_with_name_%s_was_found": "Aucun groupe privé nommé \"%s\" n'a été trouvé !",
"No_groups_yet": "Vous n'avez pas encore de groupes privés.",
@@ -895,6 +1005,7 @@
"No_user_with_username_%s_was_found": "Aucun utilisateur nommé \"%s\" n'a été trouvé !",
"Nobody_available": "Personne n'est disponible",
"Node_version": "Version de Node",
+ "None": "Aucun",
"Normal": "Normal",
"Not_authorized": "Non autorisé",
"Not_Available": "Indisponible",
@@ -903,6 +1014,7 @@
"Nothing_found": "Aucun résultat",
"Notification_Duration": "Durée de la notification",
"Notifications": "Notifications",
+ "Notify_active_in_this_room": "Notifier les utilisateurs actifs (connectés) de ce canal",
"Notify_all_in_this_room": "Notifiez tout le monde dans ce salon",
"Num_Agents": "# Assistants",
"Number_of_messages": "Nombre de messages",
@@ -913,27 +1025,32 @@
"Off_the_record_conversation": "Conversation chiffrée et non enregistrée (Off-the-record)",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "La conversation chiffrée et non enregistrée (Off-the-record) n'est pas disponible pour votre navigateur ou appareil.",
"Office_Hours": "Heures de bureau",
- "Office_Hours_Enabled": "Heures de bureau activées",
+ "Office_hours_enabled": "Heures de bureau activées",
+ "Office_hours_updated": "Heures de bureau modifiées",
"Offline": "Hors ligne",
- "Offline_DM_Email": "|__site__] Vous avez reçu des messages privés de __user__",
- "Offline_form": "forme Hors ligne",
- "Offline_form_unavailable_message": "forme Offline Message indisponible",
- "Offline_Link_Message": "Aller au message",
- "Offline_Mention_Email": "Vous avez été mentionné par __user__ dans le salon #__room__",
- "Offline_message": "un message Hors ligne",
- "Offline_success_message": "message de succès hors ligne",
- "Offline_unavailable": "Offline indisponible",
+ "Offline_DM_Email": "Vous avez reçu des messages privés de __user__",
+ "Offline_form": "Formulaire hors ligne",
+ "Offline_form_unavailable_message": "Message indisponible du formulaire hors ligne",
+ "Offline_Link_Message": "ALLER AU MESSAGE",
+ "Offline_Mention_All_Email": "Objet de l'email avec la mention @all",
+ "Offline_Mention_Email": "Objet de l'email de mention",
+ "Offline_message": "Message hors ligne",
+ "Offline_success_message": "Message de succès hors ligne",
+ "Offline_unavailable": "Hors ligne indisponible",
"On": "Allumé",
"Online": "Connecté",
+ "Only_On_Desktop": "Mode Bureau (envoyé seulement quand Entrée sur le bureau)",
"Only_you_can_see_this_message": "Vous seul pouvez voir ce message",
"Oops!": "Oups",
- "Open": "Ouvrir",
+ "Open": "Ouverture",
"Open_days_of_the_week": "Jours d'ouverture",
- "Open_Livechats": "Ouvrir les Livechats",
+ "Open_Livechats": "Ouvrir les chats en direct",
"Opened": "Ouvert",
+ "Opened_in_a_new_window": "Ouvert dans une nouvelle fenêtre.",
"Opens_a_channel_group_or_direct_message": "Ouvre un canal, un groupe ou un message direct",
"optional": "facultatif",
"or": "ou",
+ "Or_talk_as_anonymous": "Ou discutez de manière anonyme",
"Order": "Ordre",
"OS_Arch": "Architecture",
"OS_Cpus": "Nombre de CPU",
@@ -942,11 +1059,12 @@
"OS_Platform": "Plate-forme",
"OS_Release": "Version",
"OS_Totalmem": "Mémoire totale",
- "OS_Type": "Type",
+ "OS_Type": "Type Système d'exploitation",
"OS_Uptime": "Durée de fonctionnement",
"others": "autres",
"OTR": "Conversation chiffrée (OTR)",
"OTR_is_only_available_when_both_users_are_online": "OTR est disponible uniquement lorsque les deux utilisateurs sont connectés",
+ "Outgoing_WebHook": "WebHook sortant",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Modifier l'URL vers laquelle les fichiers sont téléversés. Cette URL est également utilisée pour les téléchargements sauf si un CDN a été configuré",
"Page_title": "Titre de la page",
"Page_URL": "URL de la page",
@@ -965,25 +1083,27 @@
"PiwikAnalytics_url_Description": "L'URL où le Piwik réside, assurez-vous d'inclure la barre trialing. Exemple: //piwik.rocket.chat/",
"Placeholder_for_email_or_username_login_field": "Texte de remplacement pour l'adresse e-mail ou le nom d'utilisateur à la connexion",
"Placeholder_for_password_login_field": "Texte de remplacement pour le mot de passe",
- "Please_add_a_comment": "S'il vous plaît ajouter un commentaire",
- "Please_add_a_comment_to_close_the_room": "S'il vous plaît, ajouter un commentaire à fermer la chambre",
- "Please_answer_survey": "S'il vous plait , prenez un moment pour répondre à un court sondage à propos de ce chat ",
+ "Please_add_a_comment": "Merci d'ajouter un commentaire",
+ "Please_add_a_comment_to_close_the_room": "Merci d'ajouter un commentaire pour fermer le salon",
+ "Please_answer_survey": "Merci de prendre un moment pour répondre à un court sondage à propos de cette conversation",
+ "please_enter_valid_domain": "Merci d'entrer un domaine valide",
"Please_enter_value_for_url": "Veuillez entrer l'url de votre avatar.",
"Please_enter_your_new_password_below": "Veuillez écrire votre nouveau mot de passe ci-dessous :",
- "Please_enter_your_password": "Veuillez ré-entrer votre mot de passe",
+ "Please_enter_your_password": "Veuillez entrer votre mot de passe",
"Please_fill_a_label": "Veuillez entrer une étiquette",
"Please_fill_a_name": "Veuillez saisir un nom",
"Please_fill_a_username": "Veuillez enter un nom d'utilisateur",
"Please_fill_name_and_email": "Veuillez remplir le nom et l'adresse e-mail",
- "Please_select_enabled_yes_or_no": "Veuillez choisir une option pour Activé",
+ "Please_select_an_user": "Merci de sélectionner un utilisateur",
+ "Please_select_enabled_yes_or_no": "Veuillez choisir une option pour \"Activé\"",
"Please_wait": "Veuillez patienter",
"Please_wait_activation": "Veuillez patienter, cela peut prendre un peu de temps.",
"Please_wait_while_OTR_is_being_established": "Veuillez patienter pendant l'établissement de l'OTR",
- "Please_wait_while_your_account_is_being_deleted": "Veuillez patienter pendant que votre compte est supprimé...",
- "Please_wait_while_your_profile_is_being_saved": "Veuillez patienter pendant que votre profil est enregistré ...",
+ "Please_wait_while_your_account_is_being_deleted": "Veuillez patienter pendant la suppression de votre compte...",
+ "Please_wait_while_your_profile_is_being_saved": "Veuillez patienter pendant l'enregistrement de votre profil...",
"Port": "Port",
"Post_as": "Publié en tant que",
- "Post_to_Channel": "Publié sur le Canal",
+ "Post_to_Channel": "Publié sur le canal",
"Post_to_s_as_s": "Publié sur %s en tant que %s ",
"Preferences": "Préférences",
"Preferences_saved": "Préférences enregistrées",
@@ -1018,24 +1138,37 @@
"quote": "citation",
"Quote": "Citation",
"Random": "Aléatoire",
- "Reacted_with": "mis en réaction avec",
+ "React_when_read_only": "Autoriser les réactions",
+ "React_when_read_only_changed_successfully": "Autoriser les réactions en lecture seule",
+ "Reacted_with": "a réagi avec",
"Reactions": "Réactions",
+ "Read_only": "Lecture seule",
+ "Read_only_changed_successfully": "Passage en lecture seule réussi",
+ "Read_only_channel": "Canal en lecture seule",
+ "Read_only_group": "Groupe en lecture seule",
"Record": "Enregistrer",
"Redirect_URI": "URI de redirection",
"Refresh_keys": "Rafraîchir les clefs",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Actualisez votre page après l'installation pour permettre le partage d'écran",
+ "Regenerate_codes": "Regénérer les codes",
"Register": "Créer un nouveau compte",
+ "Registration": "Enregistrement",
"Registration_Succeeded": "Enregistrement réussi",
+ "Registration_via_Admin": "Enregistrement par un administrateur",
+ "Regular_Expressions": "Expressions régulières",
"Release": "Version",
- "Remove": "Supprimer",
+ "Reload": "Recharger",
+ "Remove": "Retirer",
+ "remove-user": "Retirer l'utilisateur",
"Remove_Admin": "Supprimer administrateur",
- "Remove_as_moderator": "Retirer de la modération",
- "Remove_as_owner": "Retirer de la liste des propriétaires",
+ "Remove_as_moderator": "Supprimer de la liste des modérateurs",
+ "Remove_as_owner": "Supprimer de la liste des propriétaires",
"Remove_custom_oauth": "Supprimer l'OAuth personnalisé ",
"Remove_from_room": "Éjecter du salon",
"Remove_last_admin": "Retrait du dernier administrateur",
"Remove_someone_from_room": "Éjecter quelqu'un du salon",
- "Removed": "Retiré",
+ "Removed": "Supprimé",
+ "Reply": "Répondre",
"Report_Abuse": "Signaler un abus",
"Report_exclamation_mark": "Signaler !",
"Report_sent": "Signalement envoyé",
@@ -1044,22 +1177,27 @@
"Resend_verification_email": "Renvoyer l'e-mail de vérification",
"Reset": "Réinitialiser",
"Reset_password": "Réinitialiser le mot de passe",
+ "Reset_section_settings": "Réinitialiser les paramètres de la section",
"Restart": "Redémarrer",
"Restart_the_server": "Redémarrer le serveur",
"Role": "Rôle",
"Role_Editing": "Édition des rôles",
- "Role_removed": "Rôle retiré",
+ "Role_removed": "Rôle supprimé",
"Room": "Salon",
+ "Room_announcement_changed_successfully": "Annonce du salon modifiée avec succès",
"Room_archivation_state": "État",
"Room_archivation_state_false": "Actif",
"Room_archivation_state_true": "Archivé",
"Room_archived": "Salon archivé",
- "room_changed_description": "La description de la salle a été changé en __room_description__ par __user_by__ ",
+ "room_changed_announcement": "L'annonce du salon a été modifié en : __room_announcement__ par __user_by__ ",
+ "room_changed_description": "Description du salon modifiée pour : __room_description__ par __user_by__ ",
"room_changed_privacy": "Type du salon changé pour : __room_type__ par __user_by__ ",
"room_changed_topic": "Sujet du salon changé pour : __room_topic__ by __user_by__ ",
- "Room_description_changed_successfully": "La description de la salle a été modifiée avec succès",
+ "Room_default_change_to_private_will_be_default_no_more": "Modifier ce canal en groupe privé fera qu'il ne sera plus un canal par défaut. Etes vous sûr de vouloir continuer ?",
+ "Room_description_changed_successfully": "Description de la salle modifiée avec succès",
+ "Room_has_been_archived": "Le salon a été archivé",
"Room_has_been_deleted": "Le salon a été supprimé",
- "Room_has_been_unarchived": "Le salon a été archivé",
+ "Room_has_been_unarchived": "Le salon a été désarchivé",
"Room_Info": "Informations sur le salon",
"room_is_blocked": "Le salon est bloqué",
"room_is_read_only": "Le salon est en lecture seule",
@@ -1067,8 +1205,10 @@
"Room_name_changed": "Nom du salon changé en : __room_name__ par __user_by__ ",
"Room_name_changed_successfully": "Nom du salon modifié avec succès",
"Room_not_found": "Salon introuvable",
+ "Room_password_changed_successfully": "Mot de passe du salon modifié avec succès",
"Room_topic_changed_successfully": "Sujet du salon modifié avec succès",
"Room_type_changed_successfully": "Type du salon modifié avec succès",
+ "Room_type_of_default_rooms_cant_be_changed": "C'est un salon par défaut et le type ne peut être modifié, merci de contacter un administrateur.",
"Room_unarchived": "Salon désarchivé",
"Room_uploaded_file_list": "Liste des fichiers",
"Room_uploaded_file_list_empty": "Aucun fichier disponible.",
@@ -1081,7 +1221,9 @@
"SAML_Custom_Generate_Username": "Générer le nom d'utilisateur",
"SAML_Custom_IDP_SLO_Redirect_URL": "URL de redirection IDP SLO",
"SAML_Custom_Issuer": "Émetteur personnalisé",
+ "SAML_Custom_Private_Key": "Contenu de la clé privée",
"SAML_Custom_Provider": "Fournisseur personnalisé",
+ "SAML_Custom_Public_Cert": "Contenu du certificat public",
"Sandstorm_Powerbox_Share": "Partager une graine Sandstorm",
"Saturday": "Samedi",
"Save": "Enregistrer",
@@ -1096,10 +1238,11 @@
"Search": "Recherche",
"Search_by_username": "Rechercher par nom d'utilisateur",
"Search_Messages": "Rechercher dans les messages",
- "Search_Private_Groups": "Rechercher dans les Groupes Privés",
+ "Search_Private_Groups": "Rechercher dans les groupes privés",
"seconds": "secondes",
- "Secret_token": "jeton secret",
- "Select_a_department": "Sélectionner un département",
+ "Secret_token": "Jeton secret",
+ "Security": "Sécurité",
+ "Select_a_department": "Sélectionner un service",
"Select_a_user": "Sélectionner un utilisateur",
"Select_an_avatar": "Choisissez un avatar",
"Select_file": "Sélectionnez le fichier",
@@ -1110,15 +1253,15 @@
"Send": "Envoyer",
"Send_a_message": "Envoyez un message",
"Send_a_test_mail_to_my_user": "Envoyer un e-mail de test à mon utilisateur",
- "Send_a_test_push_to_my_user": "Envoyer une notification test aux utilisateurs",
- "Send_confirmation_email": "Envoyer un email de confirmation",
+ "Send_a_test_push_to_my_user": "Envoyer une notification test à mon utilisateur",
+ "Send_confirmation_email": "Envoyer un e-mail de confirmation",
"Send_data_into_RocketChat_in_realtime": "Envoyer des données dans Rocket.Chat en temps réel",
"Send_email": "Envoyer l'e-mail",
"Send_invitation_email": "Envoyer un e-mail d'invitation",
"Send_invitation_email_error": "Vous n'avez pas fourni d'adresse e-mail valide.",
"Send_invitation_email_info": "Vous pouvez envoyer plusieurs e-mails d'invitation à la fois.",
"Send_invitation_email_success": "Vous avez envoyé avec succès un e-mail d'invitation aux adresses suivantes :",
- "Send_request_on_chat_close": "Envoyer une demande sur le chat à proximité",
+ "Send_request_on_chat_close": "Envoyer une demande sur la fermeture du chat",
"Send_request_on_offline_messages": "Envoyer une demande sur les messages hors ligne",
"Send_Test": "Envoyer un test",
"Send_welcome_email": "Envoyer un e-mail de bienvenue",
@@ -1131,9 +1274,10 @@
"Settings": "Paramètres",
"Settings_updated": "Paramètres mis à jour",
"Share_Location_Title": "Partager votre position ?",
- "Shared_Location": "Dossier partagé",
+ "Shared_Location": "Position partagée",
"Should_be_a_URL_of_an_image": "Doit être l'URL d'une image.",
- "Should_exists_a_user_with_this_username": "L'utilisateur doit déjà exister",
+ "Should_exists_a_user_with_this_username": "L'utilisateur doit déjà exister.",
+ "Show_agent_email": "Afficher le email de l'agent",
"Show_all": "Afficher tout",
"Show_more": "Afficher plus",
"show_offline_users": "montrer les utilisateur hors-ligne",
@@ -1144,12 +1288,16 @@
"Showing_archived_results": "Affichage de %s résultats archivés
",
"Showing_online_users": "__total_showing__ utilisateur(s) affichés sur un total de __total__",
"Showing_results": "%s résultat(s)
",
+ "Sign_in_to_start_talking": "Connectez vous pour commencer à discuter",
"since_creation": "depuis %s",
"Site_Name": "Nom du site",
"Site_Url": "URL du site",
"Site_Url_Description": "Exemple : https://chat.domain.com/",
"Skip": "Passer",
"SlackBridge_error": "SlackBridge a eu une erreur durant l'importation de vos messages at %s: %s",
+ "SlackBridge_Out_All_Description": "Envoyer les messages de tous les canaux qui existent dans Slack et le bot a rejoint",
+ "SlackBridge_Out_Channels_Description": "Choisissez les canaux qui envoient les messages à Slack",
+ "SlackBridge_Out_Enabled_Description": "Choisissez si SlackBridge doit également envoyer vos messages à Slack",
"Slash_Gimme_Description": "Affiche (つ ◕_◕) つ avant votre message",
"Slash_LennyFace_Description": "Affiche (͡ ° ͜ʖ ͡ °) après votre message",
"Slash_Shrug_Description": "Affiche ¯ \\ _ (ツ) _ / ¯ après votre message",
@@ -1157,8 +1305,14 @@
"Slash_TableUnflip_Description": "Affiche ┬─┬ ノ (゜ - ゜ ノ)",
"Slash_Topic_Description": "Définir le sujet",
"Slash_Topic_Params": "message Sujet",
+ "Smarsh_Email": "Smarsh e-mail",
+ "Smarsh_Email_Description": "Smarsh e-mail à qui envoyer le fichier .eml",
"Smarsh_Enabled": "Activer Smarsh",
- "Smarsh_MissingEmail_Email": "Email manquant",
+ "Smarsh_Enabled_Description": "Le connecteur Smarsh eml est-il activé ou non ? (a besoin que le champ 'De' soit renseigné dans E-mail -> SMTP).",
+ "Smarsh_Interval": "Interval Smarsh",
+ "Smarsh_Interval_Description": "Le temps à attendre avant d'envoyer les messages (a besoin que le champ 'De' soit renseigné dans E-mail -> SMTP).",
+ "Smarsh_MissingEmail_Email": "E-mail manquant",
+ "Smarsh_MissingEmail_Email_Description": "L'e-mail à montrer pour un utilisateur quand l'adresse est manquante, généralement pour les comptes des bots.",
"Smileys_and_People": "Émojis & Portraits",
"SMS_Enabled": "SMS activés",
"SMTP": "SMTP",
@@ -1169,15 +1323,16 @@
"SMTP_Username": "Nom d'utilisateur SMTP",
"Snippet_Added": "Créer le %s",
"Sound": "Alertes sonores",
+ "Sound_File_mp3": "Fichier audio (mp3)",
"SSL": "SSL",
"Star_Message": "Mettre en favoris",
"Starred_Messages": "Messages favoris",
- "Start_audio_call": "Démarrer l'appel audio",
+ "Start_audio_call": "Démarrer un appel audio",
"Start_Chat": "Démarrer un chat",
"Start_of_conversation": "Début de la conversation",
"Start_OTR": "Démarrer une conversation chiffrée (OTR)",
- "Start_video_call": "Démarrer l'appel vidéo",
- "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Débuter avec %s pour l'utilisateur ou %s pour canal. Ex: %s ou %s",
+ "Start_video_call": "Démarrer un appel vidéo",
+ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Débuter avec %s pour l'utilisateur ou %s pour le canal. Ex: %s ou %s",
"Started_At": "Démarré(e) à",
"Statistics": "Statistiques",
"Statistics_reporting": "Envoyer des statistiques à Rocket.Chat",
@@ -1192,7 +1347,11 @@
"Stats_Online_Users": "Utilisateurs en ligne",
"Stats_Total_Channels": "Nombre total de canaux",
"Stats_Total_Direct_Messages": "Nombre total de discussions privées",
+ "Stats_Total_Livechat_Rooms": "Nombre total de salons de chat en direct",
"Stats_Total_Messages": "Nombre total de messages",
+ "Stats_Total_Messages_Channel": "Nombre total de messages dans les canaux",
+ "Stats_Total_Messages_Direct": "Nombre total de messages dans les discussions privées",
+ "Stats_Total_Messages_Livechat": "Nombre total de messages de chat en direct",
"Stats_Total_Private_Groups": "Nombre total de groupes privés",
"Stats_Total_Rooms": "Nombre total de salons",
"Stats_Total_Users": "Nombre total d'utilisateurs",
@@ -1208,111 +1367,130 @@
"Survey_instructions": "Notez chaque question en fonction de votre satisfaction, 1 signifiant que vous êtes très insatisfait et 5 que vous êtes entièrement satisfait.",
"Symbols": "Symboles",
"Sync_success": "Synchronisation réussie",
- "Sync_Users": "Synchronisation des Utilisateurs",
- "Tag": "Étiquette",
+ "Sync_Users": "Synchronisation des utilisateurs",
+ "Tag": "Tag",
"Take_it": "Je prends !",
"Test_Connection": "Tester la connexion",
"Test_Desktop_Notifications": "Tester les notifications sur le bureau",
"Thank_you_exclamation_mark": "Merci !",
"Thank_you_for_your_feedback": "Merci pour votre retour",
"The_application_name_is_required": "Le nom de l'application est requis",
- "The_channel_name_is_required": "Le canal doit être nommé",
+ "The_channel_name_is_required": "Le nom du canal est obligatoire",
"The_emails_are_being_sent": "Les e-mails sont en cours d'envoi.",
"The_field_is_required": "Le champ %s est requis.",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Le redimensionnement d'image ne fonctionnera pas car nous ne pouvons pas détecter d'installation d'ImageMagick ou de GraphicsMagick sur votre serveur.",
"The_redirectUri_is_required": "L'URI de redirection est requise",
"The_server_will_restart_in_s_seconds": "Le serveur redémarrera dans %s secondes",
"The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Le réglage %s est configuré pour %s et vous accédez à partir de %s !",
- "The_user_will_be_removed_from_s": "L'utilisateur sera éjecté de %s",
+ "The_user_will_be_removed_from_s": "L'utilisateur sera retiré de %s",
"The_user_wont_be_able_to_type_in_s": "L'utilisateur ne pourra pas écrire dans %s",
"Theme": "Thème",
+ "theme-color-component-color": "Couleur du composant",
"theme-color-content-background-color": "Couleur d'arrière plan du contenu",
+ "theme-color-custom-scrollbar-color": "Couleur personnalisée de la barre de défilement",
+ "theme-color-error-color": "Couleur d'erreur",
+ "theme-color-info-font-color": "Couleur de la police des informations",
+ "theme-color-link-font-color": "Couleur de la police des liens",
+ "theme-color-pending-color": "Couleur en attente",
+ "theme-color-primary-action-color": "Couleur de l'action primaire",
"theme-color-primary-background-color": "Couleur d'arrière plan principale",
"theme-color-primary-font-color": "Couleur de la police principale",
+ "theme-color-secondary-action-color": "Couleur de l'action secondaire",
"theme-color-secondary-background-color": "Couleur d'arrière plan secondaire",
"theme-color-secondary-font-color": "Couleur de police secondaire",
- "theme-color-tertiary-background-color": "Couleur de fond tertiaire (contenu)",
- "theme-color-tertiary-font-color": "Couleur de police tertiaire (contenu)",
- "theme-color-link-font-color": "Couleur de la police des liens",
- "theme-color-info-font-color": "Couleur de la police des informations",
- "theme-color-custom-scrollbar-color": "Couleur personnalisée de la barre de défilement",
"theme-color-status-away": "Couleur du statut \"Absent\"",
"theme-color-status-busy": "Couleur du statut \"Occupé\"",
"theme-color-status-offline": "Couleur du statut \"Hors-ligne\"",
"theme-color-status-online": "Couleur du statut \"Connecté\"",
+ "theme-color-success-color": "Couleur de succès",
+ "theme-color-tertiary-background-color": "Couleur de fond tertiaire (contenu)",
+ "theme-color-tertiary-font-color": "Couleur de police tertiaire (contenu)",
"theme-color-unread-notification-color": "Couleur des notifications non-lues",
"theme-custom-css": "CSS personnalisé",
"theme-font-body-font-family": "Famille de police du body",
- "There_are_no_agents_added_to_this_department_yet": "Il n'y a pas d'assistant ajouté à ce département pour le moment",
+ "There_are_no_agents_added_to_this_department_yet": "Il n'y a pas d'assistant ajouté à ce département pour le moment.",
"There_are_no_integrations": "Il n'y a aucune intégration",
"There_are_no_users_in_this_role": "Il n'y a aucun utilisateur avec ce rôle.",
- "This_conversation_is_already_closed": "Ces conversation a déjà été fermée.",
+ "This_conversation_is_already_closed": "Cette conversation a déjà été fermée.",
"This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Cette adresse e-mail a déjà été utilisée et n'a pas été vérifiée. Veuillez changer votre mot de passe.",
"This_is_a_desktop_notification": "Ceci est une notification sur le bureau.",
"This_is_a_push_test_messsage": "Ceci est une notification de test",
- "This_room_has_been_archived_by__username_": "Cette chambre a été archivé par __username__",
- "This_room_has_been_unarchived_by__username_": "Cette chambre a été désarchivée par __username__",
+ "This_room_has_been_archived_by__username_": "Ce salon a été archivé par __username__",
+ "This_room_has_been_unarchived_by__username_": "Ce salon a été désarchivé par __username__",
"Thursday": "Jeudi",
"Time_in_seconds": "Temps en secondes",
"Title": "Titre",
"Title_bar_color": "Couleur de la barre de titre",
- "Title_bar_color_offline": "Titre couleur de la barre hors-ligne",
+ "Title_bar_color_offline": "Couleur de la barre de titre hors-ligne",
"Title_offline": "Titre déconnecté",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Pour installer le chat en direct Rocket.Chat (Livechat) sur votre site web, copiez-collez ce code au dessus de la dernière balise </body> du site.",
"to_see_more_details_on_how_to_integrate": "pour plus de détails sur la façon d'intégrer.",
"To_users": "Pour les utilisateurs",
+ "Toggle_original_translated": "Basculer original/traduit",
"Topic": "Sujet",
+ "Transcript_Enabled": "Demandez au visiteur s'ils souhaitent une transcription après la fermeture du chat",
+ "Transcript_of_your_livechat_conversation": "Transcription de votre conversation",
+ "Translated": "Traduit",
+ "Translations": "Traductions",
"Travel_and_Places": "Voyages & Lieux",
- "Trigger_removed": "Déclencheur retiré",
+ "Trigger_removed": "Déclencheur supprimé",
"Trigger_Words": "Mots déclencheurs",
"Triggers": "Déclencheurs",
"True": "Oui",
"Tuesday": "Mardi",
"Type": "Type",
- "Type_your_email": "Tapez votre e-mail",
- "Type_your_message": "Tapez votre message",
- "Type_your_name": "Tapez votre nom",
- "Type_your_new_password": "Écrivez votre nouveau mot de passe",
+ "Type_your_email": "Entrez votre e-mail",
+ "Type_your_message": "Entrez votre message",
+ "Type_your_name": "Entrez votre nom",
+ "Type_your_new_password": "Entrez votre nouveau mot de passe",
+ "UI_Click_Direct_Message": "Cliquer pour commercer une discussion privée",
+ "UI_Click_Direct_Message_Description": "N'ouvrez pas les onglets de profils, allez directement à la discussion",
"UI_DisplayRoles": "Afficher les rôles",
- "UI_Merge_Channels_Groups": "Fusionner les groupes privés avec chaînes",
+ "UI_Merge_Channels_Groups": "Fusionner les groupes privés avec canaux",
"Unarchive": "Désarchiver",
+ "Unblock_User": "Débloquer",
"Unmute_someone_in_room": "Rendre la parole à quelqu'un dans ce salon",
"Unmute_user": "Rendre la parole",
"Unnamed": "Sans nom",
- "Unpin_Message": "Détacher ce message",
- "Unread_Alert": "Alerte non lue",
+ "Unpin_Message": "Désépingler ce message",
+ "Unread_Messages": "Messages non lus",
"Unread_Rooms": "Salons contenant des messages non-lus",
"Unread_Rooms_Mode": "Mode des salons non-lus",
"Unstar_Message": "Supprimer des favoris",
- "Upload_file_question": "Transférer le fichier ?",
+ "Upload_file_description": "Description du fichier",
+ "Upload_file_name": "Nom du fichier",
+ "Upload_file_question": "Envoyer le fichier ?",
"Uploading_file": "Envoi du fichier en cours...",
- "Uptime": "uptime",
+ "Uptime": "Durée de fonctionnement",
"URL": "URL",
"Use_account_preference": "Préférence du compte utilisateur",
- "Use_Emojis": "Utiliser les Emojis",
+ "Use_Emojis": "Utiliser les émoticônes",
"Use_Global_Settings": "Utiliser les paramètres globaux",
"Use_initials_avatar": "Utiliser les initiales de votre nom d'utilisateur",
"Use_service_avatar": "Utiliser l'avatar %s",
"Use_this_username": "Utilisez ce nom d'utilisateur",
- "Use_uploaded_avatar": "Utiliser l'avatar transmis",
+ "Use_uploaded_avatar": "Utiliser l'avatar envoyé",
"Use_url_for_avatar": "Utilisez l'URL pour l'avatar",
"Use_User_Preferences_or_Global_Settings": "Utiliser les préférences utilisateur ou les paramètres globaux",
- "User__username__is_now_a_moderator_of__room_name_": "L'utilisateur __username__ est désormais un modérateur du salon __room_name__.",
- "User__username__is_now_a_owner_of__room_name_": "L'utilisateur __username__ est désormais un propriétaire du salon __room_name__.",
+ "User__username__is_now_a_moderator_of__room_name_": "L'utilisateur __username__ est désormais un modérateur du salon __room_name__",
+ "User__username__is_now_a_owner_of__room_name_": "L'utilisateur __username__ est désormais un propriétaire du salon __room_name__",
"User__username__removed_from__room_name__moderators": "L'utilisateur __username__ n'est plus modérateur du salon __room_name__.",
"User__username__removed_from__room_name__owners": "L'utilisateur __username__ n'est plus propriétaire du salon __room_name__.",
- "User_added": "L'utilisateur __user_added__ a été ajouté",
+ "User_added": "Utilisateur ajouté",
"User_added_by": "L'utilisateur __user_added__ a été ajouté par __user_by__ .",
"User_added_successfully": "Utilisateur ajouté avec succès",
- "User_doesnt_exist": "Aucun utilisateur nommé `@%s` existe.",
+ "User_doesnt_exist": "Aucun utilisateur nommé `@%s` existant.",
"User_has_been_activated": "L'utilisateur a été activé",
"User_has_been_deactivated": "L'utilisateur a été désactivé",
"User_has_been_deleted": "L'utilisateur a été supprimé",
"User_has_been_muted_in_s": "L'utilisateur a été rendu muet dans %s",
- "User_has_been_removed_from_s": "L'utilisateur a été éjecté de %s",
+ "User_has_been_removed_from_s": "L'utilisateur a été retiré de %s",
"User_Info": "Informations sur l'utilisateur",
+ "User_Interface": "Interface utilisateur",
+ "User_is_blocked": "L'utilisateur est bloqué",
"User_is_no_longer_an_admin": "L'utilisateur n'est plus un administrateur",
"User_is_now_an_admin": "L'utilisateur est désormais un administrateur",
+ "User_is_unblocked": "L'utilisateur est débloqué",
"User_joined_channel": "A rejoint le canal.",
"User_joined_channel_female": "A rejoint le canal.",
"User_joined_channel_male": "A rejoint le canal.",
@@ -1320,13 +1498,14 @@
"User_left_female": "A quitté le canal.",
"User_left_male": "A quitté le canal.",
"User_logged_out": "L'utilisateur est déconnecté",
- "User_management": "Gestion des Utilisateurs",
+ "User_management": "Gestion des utilisateurs",
+ "User_muted": "Utilisateur rendu muet",
"User_muted_by": "L'utilisateur __user_muted__ a été rendu muet par __user_by__ .",
"User_not_found": "Utilisateur introuvable",
"User_not_found_or_incorrect_password": "Utilisateur introuvable ou mot de passe incorrect",
"User_or_channel_name": "Nom d'utilisateur ou de canal",
- "User_removed": "Utilisateur retiré",
- "User_removed_by": "L'utilisateur __user_removed__ a été éjecté par __user_by__ .",
+ "User_removed": "Utilisateur ejecté",
+ "User_removed_by": "L'utilisateur __user_removed__ a été retiré par __user_by__ .",
"User_Settings": "Paramètres utilisateur",
"User_unmuted_by": "L'utilisateur __user_by__ a rendu la parole à __user_unmuted__ .",
"User_unmuted_in_room": "L'utilisateur a retrouvé la parole dans ce salon",
@@ -1337,7 +1516,7 @@
"Username_Change_Disabled": "L'administrateur de votre Rocket.Chat a désactivé la possibilité de changer de nom d'utilisateur",
"Username_denied_the_OTR_session": "__username__ a refusé la session OTR",
"Username_description": "Le nom d'utilisateur est utilisé pour permettre à d'autres personnes de vous mentionner dans leurs messages.",
- "Username_doesnt_exist": "L'utilisateur `#%s` n'existe pas.",
+ "Username_doesnt_exist": "L'utilisateur `%s` n'existe pas.",
"Username_ended_the_OTR_session": "__username__ a terminé la session OTR",
"Username_invalid": "%s n'est pas un nom d'utilisateur valide, utilisez uniquement des lettres, des chiffres, des points et des tirets (milieu et bas)",
"Username_is_already_in_here": "`@%s` est déjà présent.",
@@ -1345,18 +1524,27 @@
"Username_title": "Enregistrer un nom d'utilisateur",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ veut démarrer une conversation chiffrée (OTR). Voulez-vous accepter ?",
"Users": "Utilisateurs",
+ "Users_added": "Les utilisateurs ont été ajoutés",
"Users_in_role": "Utilisateurs ayant ce rôle",
"UTF8_Names_Slugify": "Utiliser un slug (texte court) pour les noms UTF-8",
"UTF8_Names_Validation": "Validation UTF8 des Noms",
- "UTF8_Names_Validation_Description": "N’autorise pas les caractères spéciaux et les espaces. Vous pouvez utilisez - _ et . (tiret du milieu, tiret du bas et point) mais pas à la fin du nom",
+ "UTF8_Names_Validation_Description": "Expression régulière utilisée pour valider les noms des utilisateurs et des canaux",
+ "Validate_email_address": "Valider l'adresse e-mail",
+ "Verification": "Vérification",
+ "Verification_Email": "Cliquez ici pour vérifier votre compte.",
"Verification_email_sent": "E-mail de vérification envoyé",
+ "Verification_Email_Subject": "[Nom_du_site] - Vérifiez votre compte",
"Verified": "Vérifié(e)",
+ "Verify": "Vérifier",
"Version": "Version",
"Video_Chat_Window": "Video Chat",
+ "Video_Conference": "Vidéo Conférence",
+ "Videocall_declined": "Appel vidéo refusé",
+ "Videocall_enabled": "Appel vidéo activé",
"View_All": "Voir tous",
"View_Logs": "Voir les logs (journaux)",
"View_mode": "Mode d'affichage",
- "View_mode_info": "Cela modifie la quantité de messages de l'espace prenne à l'écran.",
+ "View_mode_info": "Cela modifie l'espace pris par les messages à l'écran.",
"Viewing_room_administration": "Accès à la gestion des salons",
"Visibility": "Visibilité",
"Visible": "Visible",
@@ -1365,11 +1553,12 @@
"Visitor_Navigation": "Navigation visiteur",
"Visitor_page_URL": "Page d'accueil du visiteur (URL)",
"Visitor_time_on_site": "Temps des visiteurs sur le site",
- "Wait_activation_warning": "Avant de pouvoir vous connecter, votre compte doit être manuellement activé par un administrateur.",
+ "Wait_activation_warning": "Avant de pouvoir vous connecter, votre compte doit être activé manuellement par un administrateur.",
+ "Warnings": "Avertissements",
"We_are_offline_Sorry_for_the_inconvenience": "Nous sommes hors ligne. Désolé pour le désagrément.",
"We_have_sent_password_email": "Nous vous avons envoyé un e-mail avec des instructions pour réinitialiser votre mot de passe. Si vous ne le recevez pas dans quelques minutes, veuillez réessayer.",
"We_have_sent_registration_email": "Nous vous avons envoyé un e-mail afin que vous confirmiez votre inscription. Si vous ne le recevez pas dans quelques minutes, veuillez réessayer.",
- "Webhook_URL": "webhook URL",
+ "Webhook_URL": "Webhook URL",
"Webhooks": "Webhooks",
"WebRTC_Enable_Channel": "Activer pour les canaux publics",
"WebRTC_Enable_Direct": "Activer pour les messages privés",
@@ -1383,26 +1572,28 @@
"will_be_able_to": "sera capable de",
"Would_you_like_to_return_the_inquiry": "Voulez-vous retourner le dossier ?",
"Yes": "Oui",
- "Yes_clear_all": "Oui, marquez tout comme lu !",
- "Yes_delete_it": "Oui, je confirme la suppression !",
- "Yes_hide_it": "Oui, je veux le cacher !",
+ "Yes_archive_it": "Oui, archive le !",
+ "Yes_clear_all": "Oui, marque tout comme lu !",
+ "Yes_delete_it": "Oui, supprime le !",
+ "Yes_hide_it": "Oui, masque le !",
"Yes_leave_it": "Oui, je veux partir !",
- "Yes_mute_user": "Oui, rendre l'utilisateur muet !",
- "Yes_remove_user": "Oui, éjecter l'utilisateur !",
- "You": "Toi",
+ "Yes_mute_user": "Oui, rend muet l'utilisateur !",
+ "Yes_remove_user": "Oui, éjecte l'utilisateur !",
+ "Yes_unarchive_it": "Oui, désarchive le !",
+ "You": "Vous",
"you_are_in_preview_mode_of": "Aperçu du salon #__room_name__ ",
"You_are_logged_in_as": "Vous êtes connecté en tant que",
"You_are_not_authorized_to_view_this_page": "Vous n'avez pas l'autorisation de voir cette page.",
- "You_can_change_a_different_avatar_too": "Vous pouvez ignorer l'avatar utilisé pour publier depuis cette intégration.",
- "You_can_search_using_RegExp_eg": "Vous pouvez rechercher en utilisant RegExp. par exemple",
- "You_can_use_an_emoji_as_avatar": "Vous pouvez également utiliser un emoji comme avatar.",
- "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Vous pouvez utiliser webhooks d'intégrer facilement livechat avec votre CRM.",
- "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Vous ne pouvez pas quitter une salle de livechat. S'il vous plaît, utilisez le bouton de fermeture.",
+ "You_can_change_a_different_avatar_too": "Vous pouvez écraser l'avatar utilisé pour publier depuis cette intégration.",
+ "You_can_search_using_RegExp_eg": "Vous pouvez rechercher en utilisant une expression régulière. par exemple",
+ "You_can_use_an_emoji_as_avatar": "Vous pouvez également utiliser une émoticone comme avatar.",
+ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Vous pouvez utiliser les webhooks pour intégrer facilement un chat en direct avec votre CRM.",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Vous ne pouvez pas quitter un chat en direct. S'il vous plaît, utilisez le bouton de fermeture.",
"You_have_been_muted": "Vous avez été rendu muet et ne pouvez donc pas parler dans ce salon",
"You_have_not_verified_your_email": "Vous n'avez pas vérifié votre adresse e-mail.",
"You_have_successfully_unsubscribed": "Vous êtes désabonné avec succès de notre liste de diffusion.",
"You_must_join_to_view_messages_in_this_channel": "Vous devez rejoindre ce canal pour voir les messages",
- "You_need_confirm_email": "Vous devez confirmer votre adresse email pour vous connecter !",
+ "You_need_confirm_email": "Vous devez confirmer votre adresse e-mail pour vous connecter !",
"You_need_install_an_extension_to_allow_screen_sharing": "Vous devez installer une extension pour permettre le partage d'écran",
"You_need_to_change_your_password": "Vous devez changer votre mot de passe.",
"You_need_to_type_in_your_password_in_order_to_do_this": "Vous devez entrer votre mot de passe pour faire ceci !",
@@ -1418,6 +1609,8 @@
"Your_entry_has_been_deleted": "Ce message a été supprimé.",
"Your_file_has_been_deleted": "Votre fichier a été supprimé.",
"Your_mail_was_sent_to_s": "Votre e-mail a été envoyé à %s",
+ "your_message": "votre message",
+ "your_message_optional": "votre message (optionnel)",
"Your_password_is_wrong": "Votre mot de passe est incorrect !",
"Your_push_was_sent_to_s_devices": "Votre notification a été envoyée à %s appareils"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/he.i18n.json b/packages/rocketchat-i18n/i18n/he.i18n.json
index 459b1008f5f8b..10f6619bd9c59 100644
--- a/packages/rocketchat-i18n/i18n/he.i18n.json
+++ b/packages/rocketchat-i18n/i18n/he.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "אפשר למשתמש לשנות את הפרופיל",
"Accounts_AvatarResize": "שנה את גודל תמונת הפרופיל",
"Accounts_AvatarSize": "גודל תמונת הפרופיל",
- "Accounts_AvatarStorePath": "נתיב תמונת הפרופיל",
- "Accounts_AvatarStoreType": "סוג אחסון תמונת פרופיל",
"Accounts_BlockedDomainsList": "רשימת דומיינים חסומים",
"Accounts_BlockedDomainsList_Description": "רשימה מופרדת בפסיקים של דומיינים חסומים",
"Accounts_BlockedUsernameList": "רשימת משתמש חסום",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "אימות דוא״ל",
"Accounts_EmailVerification_Description": "בדוק שיש לך הגדרות SMTP נכונות כדי להשתמש בתכונה זו",
"Accounts_Enrollment_Email": "אימייל הרשמה",
- "Accounts_Enrollment_Email_Default": " ברוך הבא ל [Site_Name] עבור אל [Site_URL] ולנסות פתרון הצ'אט פתוח המקור הטוב ביותר הזמינים כיום!
",
+ "Accounts_Enrollment_Email_Default": " ברוך הבא ל [Site_Name] עבור אל [Site_URL] ולנסות פתרון הצ'אט פתוח המקור הטוב ביותר הזמינים כיום!
",
"Accounts_Enrollment_Email_Description": "אתה יכול להשתמש [name], [fname], [lname] עבור השם המלא של המשתמש, שם פרטי או שם משפחה, בהתאמה. אתה יכול להשתמש [email] עבור הדוא\"ל של המשתמש.",
"Accounts_Enrollment_Email_Subject_Default": "ברוכים הבאים [Site_name]",
"Accounts_Iframe_api_method": "שיטת Api",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "ציבורי",
"Accounts_RegistrationForm_Secret_URL": "כתובת סודית",
"Accounts_RegistrationForm_SecretURL": "סיסמת כתובת טופס הרישום",
- "Accounts_RegistrationForm_SecretURL_Description": "אתה חייב לספק מחרוזת אקראית שתתווסף לכתובת הרישום שלך. לדוגמה:https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "אתה חייב לספק מחרוזת אקראית שתתווסף לכתובת הרישום שלך. לדוגמה:https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "נדרש שם לרישום",
"Accounts_ShowFormLogin": "טופס מבוסס צג כניסה",
"Accounts_UseDefaultBlockedDomainsList": "השתמש בברירת מחדל רשימת Domains חסימה",
"Accounts_UseDNSDomainCheck": "הסימון השתמש דומיין DNS",
- "Accounts_UserAddedEmail_Default": " ברוך הבא ל [Site_Name] עבור אל [Site_URL] ולנסות פתרון הצ'אט פתוח המקור הטוב ביותר הזמינים כיום!
אתה יכול להתחבר באמצעות הדוא\"ל שלך: [email] וסיסמא: [סיסמא]. ייתכן שתידרש לשנות את זה לאחר ההתחברות הראשונה שלך.",
+ "Accounts_UserAddedEmail_Default": "
ברוך הבא ל [Site_Name] עבור אל [Site_URL] ולנסות פתרון הצ'אט פתוח המקור הטוב ביותר הזמינים כיום!
אתה יכול להתחבר באמצעות הדוא\"ל שלך: [email] וסיסמא: [סיסמא]. ייתכן שתידרש לשנות את זה לאחר ההתחברות הראשונה שלך.",
"Accounts_UserAddedEmail_Description": "הנך רשאי להשתמש המשתנים הבאים:
[name], [fname], [lname] עבור השם המלא של המשתמש, שם פרטי או שם משפחה, בהתאמה. [email] עבור הדוא\"ל של המשתמש. [password] להזין את הסיסמה של המשתמש. [Site_Name] ו [Site_URL] עבור שם היישום וה- URL בהתאמה. ",
"Accounts_UserAddedEmailSubject_Default": "אתה נוספת [Site_Name]",
"Activate": "הפעל",
@@ -567,24 +565,12 @@
"Layout_Terms_of_Service": "תנאי השירות",
"LDAP": "LDAP",
"LDAP_CA_Cert": "Cert CA",
- "LDAP_Custom_Domain_Search": "חיפוש הדומיין המותאם אישית",
- "LDAP_Custom_Domain_Search_Description": "חתיכת JSON, השולטת מידע לאגד וחיבור והוא מהצורה: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "ברירת המחדל של תחום",
"LDAP_Description": "LDAP הוא מסד נתונים היררכיים כי חברות רבות להשתמש בו כדי לספק כניסה יחידה - מתקן לשיתוף סיסמא אחת בין אתרים ושירותים רבים. לקבלת מידע תצורה מתקדמת ודוגמאות, היועץ wiki שלנו: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "מאגר דומיין",
- "LDAP_Domain_Base_Description": "השם הייחודי מלא (DN) של עץ משנה LDAP אתה רוצה לחפש משתמשים וקבוצות. אתה יכול להוסיף כמה שאתה רוצה; עם זאת, כל קבוצה חייבת להיות מוגדרת באותו הבסיס מושלם בתור המשתמשים ששייכים אליו. אם תציין קבוצות משתמש מוגבלות, רק משתמשים השייכים לקבוצות אלו יהיו בהיקפה. אנו ממליצים לציין את הרמה העליונה של ספריית עץ LDAP שלך כבסיס התחום שלך ולהשתמש במסנן חיפוש כדי לשלוט בגישה.",
- "LDAP_Domain_Search_Filter": "סנן חיפוש דומיין",
- "LDAP_Domain_Search_Filter_Description": "אם צויין, רק משתמשים התואמים מסנן זה יורשו להיכנס. אם אין מסנן מצוין, כל המשתמשים בתחולת בבסיס התחום שצוין יוכלו להיכנס. למשל עבור Active Directory `memberOf = cn = ROCKET_CHAT, ou = כללי Groups`. לדוגמא עבור OpenLDAP (חיפוש בהתאמה להרחבה) `ou: DN: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "קטגורית אובייקט חיפוש דומיין",
- "LDAP_Domain_Search_Object_Category_Description": "הסימן * * objectCategory שמזהים המשתמשים שלך. השאר ריק עבור OpenLDAP * *. לדוגמא `person`, וכו '",
- "LDAP_Domain_Search_Object_Class": "כיתת אובייקט חיפוש דומיין",
- "LDAP_Domain_Search_Object_Class_Description": "הסימן * * objectClass שמזהים המשתמשים שלך. לדוגמא `organizationalPerson`,` user`, `inetOrgPerson`, וכו '",
- "LDAP_Domain_Search_Password": "סיסמא חיפוש דומיין",
- "LDAP_Domain_Search_Password_Description": "הסיסמה עבור משתמש תחום החיפוש.",
- "LDAP_Domain_Search_User": "משתמש חיפוש דומיין",
- "LDAP_Domain_Search_User_Description": "משתמש LDAP שמבצע חיפושי משתמש כדי לאמת משתמשים אחרים כאשר הם נכנסים. זה בדרך כלל חשבון שירות שנוצרו במיוחד עבור ואינטגרציות צד שלישי. השתמש בשם מלא, כגון `cn = מנהל, cn = Users, dc = דוגמא, dc = com`.",
- "LDAP_Domain_Search_User_ID": "זיהוי משתמש חיפוש דומיין",
- "LDAP_Domain_Search_User_ID_Description": "התכונה של LDAP המזהה את המשתמש LDAP שמנסה אימות. שדה זה צריך להיות `sAMAccountName` להתקנות של Active Directory ביותר, אבל זה עשוי להיות` uid` לפתרונות LDAP אחרים, כגון OpenLDAP. אתה יכול להשתמש `mail` לזהות משתמשים בדוא\"ל או כל תכונה שאתה רוצה. תוכל להשתמש בערכים מרובים המופרדים בפסיק כדי לאפשר למשתמשים להתחבר באמצעות מזהים מרובים כמו שם משתמש או דוא\"ל.",
+ "LDAP_BaseDN_Description": "השם הייחודי מלא (DN) של עץ משנה LDAP אתה רוצה לחפש משתמשים וקבוצות. אתה יכול להוסיף כמה שאתה רוצה; עם זאת, כל קבוצה חייבת להיות מוגדרת באותו הבסיס מושלם בתור המשתמשים ששייכים אליו. אם תציין קבוצות משתמש מוגבלות, רק משתמשים השייכים לקבוצות אלו יהיו בהיקפה. אנו ממליצים לציין את הרמה העליונה של ספריית עץ LDAP שלך כבסיס התחום שלך ולהשתמש במסנן חיפוש כדי לשלוט בגישה.",
+ "LDAP_User_Search_Field_Description": "התכונה של LDAP המזהה את המשתמש LDAP שמנסה אימות. שדה זה צריך להיות `sAMAccountName` להתקנות של Active Directory ביותר, אבל זה עשוי להיות` uid` לפתרונות LDAP אחרים, כגון OpenLDAP. אתה יכול להשתמש `mail` לזהות משתמשים בדוא\"ל או כל תכונה שאתה רוצה. תוכל להשתמש בערכים מרובים המופרדים בפסיק כדי לאפשר למשתמשים להתחבר באמצעות מזהים מרובים כמו שם משתמש או דוא\"ל.",
+ "LDAP_User_Search_Filter_Description": "אם צויין, רק משתמשים התואמים מסנן זה יורשו להיכנס. אם אין מסנן מצוין, כל המשתמשים בתחולת בבסיס התחום שצוין יוכלו להיכנס. למשל עבור Active Directory `memberOf = cn = ROCKET_CHAT, ou = כללי Groups`. לדוגמא עבור OpenLDAP (חיפוש בהתאמה להרחבה) `ou: DN: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "משתמש LDAP שמבצע חיפושי משתמש כדי לאמת משתמשים אחרים כאשר הם נכנסים. זה בדרך כלל חשבון שירות שנוצרו במיוחד עבור ואינטגרציות צד שלישי. השתמש בשם מלא, כגון `cn = מנהל, cn = Users, dc = דוגמא, dc = com`.",
"LDAP_Enable": "אפשר",
"LDAP_Enable_Description": "מנסה לאתחל LDAP עבור הזדהות.",
"LDAP_Encryption": "הצף",
@@ -599,12 +585,9 @@
"LDAP_Sync_User_Data_Description": "דאג למידע מסונכרן על המשתמש בהתחברות לשרת (שם, אימייל).",
"LDAP_Sync_User_Data_FieldMap": "מיפוי שדה User Data",
"LDAP_Sync_User_Data_FieldMap_Description": "הגדר כיצד שדות חשבון המשתמש (כגון אימייל) ישלפו מרשומת ה-LDAP (כאשר נמצאה). לדוגמה, `{\"cn\":\"name\", \"mail\":\"email\"}` יבחרו את השם הקריא של המשתמש מהשדה cn והאימייל שלהם מהשדה mail. השדות האפשריים כוללים `name`, ו-`email`.",
- "LDAP_Sync_Users": "משתמשים Sync",
"LDAP_Test_Connection": "בדיקת חיבור",
"LDAP_Unique_Identifier_Field": "ייחודיות מזהים שדה",
"LDAP_Unique_Identifier_Field_Description": "איזה שדה ישמש לקשר משתמש LDAP ומשתמש Rocket.Chat. אתה יכול להודיע ערכים המופרדים באמצעות פסיק כדי לנסות להשיג את הערך מרשום LDAP. ערך ברירת המחדל הוא `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "השתמש חיפוש דומיין מותאם אישית",
- "LDAP_Use_Custom_Domain_Search_Description": "כתוב מסנן משלך לחפש משתמשים בשרת LDAP.",
"LDAP_Username_Field": "שדה שם המשתמש",
"LDAP_Username_Field_Description": "איזה שדה ישמש * שם משתמש * עבור משתמשים חדשים. השאר ריק להשתמש בשם המשתמש הודיע על דף הכניסה. אתה יכול להשתמש בתגי תבנית מדי, כמו `#{givenName}.#{sn}`. ערך ברירת המחדל הוא `sAMAccountName`.",
"Leave_Group_Warning": "האם אתה בטוח שאתה רוצה לעזוב את הקבוצה \" %s\"?",
@@ -754,8 +737,8 @@
"Nothing_found": "אין תוצאות",
"Notification_Duration": "משך התרעה",
"Notifications": "התרעות",
- "Notify_all_in_this_room": "להודיע לכל מי שבחדר",
"Notify_active_in_this_room": "להודיע לכל המחוברים שבחדר",
+ "Notify_all_in_this_room": "להודיע לכל מי שבחדר",
"Num_Agents": "סוכני #",
"Number_of_messages": "מספר הודעות",
"OAuth_Application": "יישום OAuth",
@@ -1048,19 +1031,19 @@
"The_user_wont_be_able_to_type_in_s": "המשתמש לא יוכל להקליד %s",
"Theme": "ערכת עיצוב",
"theme-color-content-background-color": "צבע הרקע של התוכן",
+ "theme-color-custom-scrollbar-color": "צבע מותאם אישית פס גלילה",
+ "theme-color-info-font-color": "צבע של פונט Info",
+ "theme-color-link-font-color": "צבע פונט של לינק",
"theme-color-primary-background-color": "צבע רקע ראשי",
"theme-color-primary-font-color": "צבע פונט ראשי",
"theme-color-secondary-background-color": "צבע רקע משני",
"theme-color-secondary-font-color": "צבע פונט משני",
- "theme-color-tertiary-background-color": "צבע סטטוס ",
- "theme-color-tertiary-font-color": "צבע פונט שלישי",
- "theme-color-link-font-color": "צבע פונט של לינק",
- "theme-color-info-font-color": "צבע של פונט Info",
- "theme-color-custom-scrollbar-color": "צבע מותאם אישית פס גלילה",
"theme-color-status-away": "צבע סטטוס לא נמצא",
"theme-color-status-busy": "צבע סטטוס עסוק",
"theme-color-status-offline": "צבע סטטוס לא מחובר",
"theme-color-status-online": "צבע סטטוס זמין",
+ "theme-color-tertiary-background-color": "צבע סטטוס ",
+ "theme-color-tertiary-font-color": "צבע פונט שלישי",
"theme-color-unread-notification-color": "צבע הודעות שלא נקראו",
"theme-custom-css": "CSS בהתאמה אישית",
"There_are_no_agents_added_to_this_department_yet": "אין סוכנים שנוספו למחלקה זו עדיין.",
@@ -1097,7 +1080,6 @@
"Unmute_user": "בטל השתקת משתמש",
"Unnamed": "ללא שם",
"Unpin_Message": "שחרור הודעה",
- "Unread_Alert": "התרעה על לא נקרא",
"Unread_Rooms": "חדרים שלא נקראו",
"Unread_Rooms_Mode": "מצב חדרים שלא נקראו",
"Unstar_Message": "הסר ממועדפים",
@@ -1234,4 +1216,4 @@
"Your_mail_was_sent_to_s": "הדואר שלך נשלח אל %s",
"Your_password_is_wrong": "הסיסמה שלך היא לא בסדר!",
"Your_push_was_sent_to_s_devices": "הודעת ה-push נשלח בהצלחה ל-%s מכשירים"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/hr.i18n.json b/packages/rocketchat-i18n/i18n/hr.i18n.json
index 36e241e06ed87..2ad403bf80e3b 100644
--- a/packages/rocketchat-i18n/i18n/hr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/hr.i18n.json
@@ -27,8 +27,6 @@
"Accounts_AllowUserProfileChange": "Dopusti Promjenu Profila",
"Accounts_AvatarResize": "Promjeni veličinu Avatara",
"Accounts_AvatarSize": "Veličina Avatara",
- "Accounts_AvatarStorePath": "Putanja do spremišta Avatara ",
- "Accounts_AvatarStoreType": "Tip Spremišta Avatara",
"Accounts_BlockedDomainsList": "Popis blokiranih domena",
"Accounts_BlockedDomainsList_Description": "Popis blokiranih domena odvojenih zarezom",
"Accounts_BlockedUsernameList": "Popis blokiranih korisničkih imena",
@@ -38,7 +36,7 @@
"Accounts_EmailVerification": "E-mail Verifikacija",
"Accounts_EmailVerification_Description": "Provjerite imate li ispravne postavke SMTP kako bi koristili ovu mogućnost",
"Accounts_Enrollment_Email": "Email dobrodošlice",
- "Accounts_Enrollment_Email_Default": " Dobrodošli u [Site_Name] Idite na [Site_URL] i pokušajte najbolje open source chat rješenje danas!
",
+ "Accounts_Enrollment_Email_Default": " Dobrodošli u [Site_Name] Idite na [Site_URL] i pokušajte najbolje open source chat rješenje danas!
",
"Accounts_Enrollment_Email_Description": "Možete koristiti sljedeće oznake: [name], [fname], [lname] za korisničko ime, ime te prezime. [email] za korisnikov email. [Site_Name] i [Site_URL] za naziv aplikacije i URL.\n ",
"Accounts_Enrollment_Email_Subject_Default": "Dobro došli na [Site_Name]",
"Accounts_ForgetUserSessionOnWindowClose": "Zaboravi korisnikovu prijavu pri zatvaranju prozora",
@@ -95,7 +93,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Tajna",
"Accounts_OAuth_Wordpress": "WordPress Prijava",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress povratnog poziva ",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress povratnog poziva ",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Tajna",
"Accounts_PasswordReset": "Resetiraj lozinku",
@@ -106,7 +104,7 @@
"Accounts_RegistrationForm_Public": "Javan",
"Accounts_RegistrationForm_Secret_URL": "Tajni URL",
"Accounts_RegistrationForm_SecretURL": "Tajni URL za registracijski obrazac",
- "Accounts_RegistrationForm_SecretURL_Description": "Morate navesti nasumični niz znakova koji će biti dodan u vašu registracijski URL. Na primjer: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Morate navesti nasumični niz znakova koji će biti dodan u vašu registracijski URL. Na primjer: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Zahtijevaj ime pri prijavi",
"Accounts_RequirePasswordConfirmation": "Zahtjevaj potvrdu lozinke",
"Accounts_SetDefaultAvatar": "Namjesti zadani Avatar",
@@ -114,7 +112,7 @@
"Accounts_ShowFormLogin": "Prikaži obrazac za prijavu",
"Accounts_UseDefaultBlockedDomainsList": "Koristi zadanu listu blokiranih domena",
"Accounts_UseDNSDomainCheck": "Koristi DNS provjeru domena",
- "Accounts_UserAddedEmail_Default": "Dobrodošli na [Site_Name] Idi na [Site_URL] i isprobaj najbolje open source chat rješenje danas!
Možete se prijaviti preko emaila: [email] i lozinke: [password]. Moguće je da će vas tražiti da zamijenite lozinku nakon prijave.
",
+ "Accounts_UserAddedEmail_Default": "Dobrodošli na [Site_Name] Idi na [Site_URL] i isprobaj najbolje open source chat rješenje danas!
Možete se prijaviti preko emaila: [email] i lozinke: [password]. Moguće je da će vas tražiti da zamijenite lozinku nakon prijave.
",
"Accounts_UserAddedEmail_Description": "Možete koristiti sljedeće oznake: [name], [fname], [lname] za korisničko ime, ime, te prezime. [email] za email korisnika. [password] korisnikovu lozinku. [Site_Name] i [Site_URL] za ime i URL stranice. ",
"Accounts_UserAddedEmailSubject_Default": "Dodani ste na [Site_Name]",
"Activate": "Aktiviraj",
@@ -122,6 +120,7 @@
"Add": "Dodaj",
"Add_agent": "Dodaj agenta",
"Add_custom_oauth": "Dodaj prilagođeni OAuth",
+ "Add_Domain": "Dodaj domenu",
"Add_manager": "Dodaj upravitelja",
"Add_user": "Dodaj korisnika",
"Add_User": "Dodaj korisnika",
@@ -164,6 +163,7 @@
"API_EmbedIgnoredHosts_Description": "Odvojenih zarezom popis domaćini ili CIDR adresa, npr. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Sigurni Ulazi",
"API_EmbedSafePorts_Description": "Popis dopuštenih portova, odvojenih zarezom, za pretpregled",
+ "API_Enable_CORS": "Omogući CORS",
"API_GitHub_Enterprise_URL": "GitHub Enterprise URL",
"API_GitHub_Enterprise_URL_Description": "Na primjer: http://domain.com (isključujući kosu crtu na kraju)",
"API_Gitlab_URL": "GitLab link",
@@ -241,6 +241,7 @@
"CAS_enabled": "Omogućeno",
"CDN_PREFIX": "CDN Prefiks",
"Certificates_and_Keys": "Certifikati i ključevi",
+ "Change_Room_Type": "Mijenjam tip sobe",
"Changing_email": "Promjena email",
"channel": "soba",
"Channel": "Soba",
@@ -263,8 +264,9 @@
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Odaberite pseudonim koji će se pojaviti pred korisničko ime u porukama.",
"Choose_the_username_that_this_integration_will_post_as": "Odaberite korisničko ime za koje će ova integracija objavljivati.",
"clear": "Očisti",
- "clear_cache_now": "Očisti sada predmemoriju",
"Clear_all_unreads_question": "Očisti sve nepročitane?",
+ "clear_cache_now": "Očisti sada predmemoriju",
+ "clear_history": "Očisti Povijest",
"Click_here": "Kliknite ovdje",
"Client_ID": "ID klijenta",
"Client_Secret": "Klijent tajna",
@@ -279,6 +281,7 @@
"Commands": "Naredbe",
"Compact": "Kompaktan",
"Confirm_password": "Potvrdi svoju lozinku",
+ "Content": "Sadržaj",
"Conversation": "Razgovor",
"Conversation_closed": "Razgovor je zatvoren: __comment__.",
"Convert_Ascii_Emojis": "Pretvori ASCII u Emoji",
@@ -293,6 +296,7 @@
"Create_new": "Stvori novi",
"Created_at": "Stvoreno u",
"Created_at_s_by_s": "%s je stvorio %s ",
+ "CRM_Integration": "CRM Integracija",
"CROWD_Reject_Unauthorized": "Odbije neautorizirano",
"Current_Chats": "Trenutni Razgovori",
"Custom": "Prilagođeno",
@@ -310,8 +314,9 @@
"Custom_oauth_unique_name": "Prilagođeno OAuth jedinstveno ime",
"Custom_Script_Logged_In": "Prilagođena skripta za prijavljene korisnike",
"Custom_Script_Logged_Out": "Prilagođena skripta za odjavljene korisnike",
+ "Custom_Sound_Error_Invalid_Sound": "Nevaljan zvuk",
"Custom_Translations": "Prilagođeni prijevodi",
- "Custom_Translations_Description": "Treba biti ispravan JSON gdje su ključevi jezici koji zadrže riječnik ključeva i prijevoda. Npr: \n {\n \"en\": {\n \"key\": \"translation\"\n },\n \"pt\": {\n \"key\": \"tradução\"\n }\n}",
+ "Custom_Translations_Description": "Treba biti ispravan JSON gdje su ključevi jezici koji zadrže riječnik ključeva i prijevoda. Npr: \n {\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n}",
"Dashboard": "Kontrolna ploča",
"Date": "Datum",
"Date_From": "Od",
@@ -401,6 +406,7 @@
"error-could-not-change-username": "Nismo uspjeli promijeniti korisničko ime",
"error-delete-protected-role": "Ne možete izbrisati zaštićenu ulogu",
"error-department-not-found": "Odjel nije pronađen",
+ "error-direct-message-file-upload-not-allowed": "Dijeljenje datoteka nije dozvoljeno u direktnim porukama",
"error-duplicate-channel-name": "Soba s nazivom ' __channel_name__' već postoji",
"error-email-domain-blacklisted": "Email domena je na crnoj listi",
"error-email-send-failed": "Greška pri slanju emaila: __message__",
@@ -421,7 +427,6 @@
"error-invalid-email": "Pogrešan __email__ email",
"error-invalid-file-height": "Neispravna visina datoteke",
"error-invalid-file-type": "Pogrešna vrsta datoteke",
- "error-direct-message-file-upload-not-allowed": "Dijeljenje datoteka nije dozvoljeno u direktnim porukama",
"error-invalid-file-width": "Pogrešna širina datoteke",
"error-invalid-from-address": "Unijeta je kriva OD adresa",
"error-invalid-integration": "Pogrešna integracija",
@@ -479,8 +484,8 @@
"File_not_allowed_direct_messages": "Dijeljenje datoteka nije dozvoljeno u direktnim porukama",
"File_type_is_not_accepted": "Tip datoteke nije prihvaćen",
"FileUpload": "Prijenos datoteke",
- "FileUpload_Enabled": "Prijenos Datoteka Omogućeno",
"FileUpload_Disabled": "Prijenosi datoteka su onemogućeni",
+ "FileUpload_Enabled": "Prijenos Datoteka Omogućeno",
"FileUpload_Enabled_Direct": "Prijenos datoteka u direktnim porukama",
"FileUpload_File_Empty": "Prazna datoteka",
"FileUpload_FileSystemPath": "Odredište u sustavu",
@@ -535,7 +540,7 @@
"Hide_Room_Warning": "Jeste li sigurni da želite sakriti sobu \"%s\"?",
"Hide_usernames": "Sakrij korisnička imena",
"Highlights": "Istaknuto",
- "Highlights_How_To": "Kako bi bilo obaviješteni kada netko spomene neku riječ i li frazu, dodajte ju ovdje. Riječi i fraze odvojite zarezima. Ne ovisi kapitalizaciji.",
+ "Highlights_How_To": "Kako bi bili obaviješteni kada netko spomene neku riječ i li frazu, dodajte ju ovdje. Riječi i fraze odvojite zarezima. Ne ovisi kapitalizaciji.",
"Highlights_List": "Označite riječi",
"History": "Povijest",
"Host": "Domaćin",
@@ -590,6 +595,12 @@
"Integration_Outgoing_WebHook": "Odlazna WebHook integracija",
"Integration_updated": "Integracija je ažurirana",
"Integrations": "Integracije",
+ "Integrations_Outgoing_Type_RoomArchived": "Soba je arhivirana",
+ "Integrations_Outgoing_Type_RoomCreated": "Soba je stvorena (javna i privatna)",
+ "Integrations_Outgoing_Type_RoomJoined": "Korisnik se pridružio sobi",
+ "Integrations_Outgoing_Type_RoomLeft": "Korisnik je napustio sobu",
+ "Integrations_Outgoing_Type_SendMessage": "Poruka je poslana",
+ "Integrations_Outgoing_Type_UserCreated": "Korisnik je stvoren",
"InternalHubot": "Vlastiti Hubot",
"InternalHubot_ScriptsToLoad": "Skripte za učitavanje",
"InternalHubot_ScriptsToLoad_Description": "Unesite zarezom odvojen popis skripti za učitavanje s https://github.com/github/hubot-scripts/tree/master/src/scripts",
@@ -656,31 +667,19 @@
"Layout_Terms_of_Service": "Uvjeti pružanja usluge",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Custom Domain Search",
- "LDAP_Custom_Domain_Search_Description": "Komad JSONa koji upravlja vezama je u obliku: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Zadana domena",
"LDAP_Description": "LDAP je hijerarhijska baza podataka koja mnoge tvrtke koriste za pružanje jedinstvene prijave - usluge za dijeljenje jedne lozinke između više web-mjesta i usluga. Za napredne podatke o konfiguraciji i primjere, obratite se našem wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Osnova domene",
- "LDAP_Domain_Base_Description": "Potpuno kvalificirana Distinguished Name (DN) u LDAP podstablo koje želite pretražiti za korisnike i grupe. Možete dodati koliko god želite; Međutim, svaka grupa mora biti definirana u istoj bazi domeni kao korisnici koji pripadaju njemu. Ako navedete ograničene grupe korisnika, samo korisnici koji pripadaju tim skupinama će biti u opsegu. Preporučujemo da odredite gornju razinu svoje LDAP direktorija stablo kao svoju bazu domene i korištenje filtra za pretraživanje za kontrolu pristupa.",
- "LDAP_Domain_Search_Filter": "Domain Search Filter",
- "LDAP_Domain_Search_Filter_Description": "Ako je navedeno, samo korisnicima koji odgovaraju filteru će biti dopušteno da se prijavite. Ako nijedan filtar nije naveden, svi korisnici u okviru zadane osnovne domene moći će se prijaviti. Npr za Active Directory`memberOf=cn=ROCKET_CHAT,ou=General Groups`.. Npr za OpenLDAP `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Kategorija",
- "LDAP_Domain_Search_Object_Category_Description": "*objectCategory* koji identificira svoje korisnike. Ostavite prazno za *OpenLDAP*. Npr. `person` itd",
- "LDAP_Domain_Search_Object_Class": "Domain Search Object Klasa",
- "LDAP_Domain_Search_Object_Class_Description": "*objectclass* koji identificira svoje korisnike. Npr `organizationalPerson`, `user`, `inetOrgPerson`, itd",
- "LDAP_Domain_Search_Password": "Domena Search Lozinka",
- "LDAP_Domain_Search_Password_Description": "Lozinka za korisnika za pretraživanje domene.",
- "LDAP_Domain_Search_User": "Domain Search Korisnik",
- "LDAP_Domain_Search_User_Description": "LDAP korisnik koja obavlja korisničke dohvate za autentifikaciju drugih korisnika prilikom prijave. To je obično račun za uslugu izrađen posebno za treće integracijama. Koristite potpuno kvalificirani naziv, kao što je `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search ID korisnika",
- "LDAP_Domain_Search_User_ID_Description": "LDAP atribut koji identificira LDAP korisnika koji pokušava provjeru autentičnosti. Ovo polje mora biti `sAMAccountName` za većinu Active Directory instalacija, ali to može biti` uid` za druge LDAP rješenjima, kao što su OpenLDAP. Možete koristiti `mail` identificiraju korisnike putem e-maila ili bilo atribut želite. Možete koristiti više vrijednosti odvojene zarezom kako bi se omogućilo korisnicima da se prijavite koristeći višestruke identifikatore kao što su korisničko ime ili e-mail.",
+ "LDAP_BaseDN_Description": "Potpuno kvalificirana Distinguished Name (DN) u LDAP podstablo koje želite pretražiti za korisnike i grupe. Možete dodati koliko god želite; Međutim, svaka grupa mora biti definirana u istoj bazi domeni kao korisnici koji pripadaju njemu. Ako navedete ograničene grupe korisnika, samo korisnici koji pripadaju tim skupinama će biti u opsegu. Preporučujemo da odredite gornju razinu svoje LDAP direktorija stablo kao svoju bazu domene i korištenje filtra za pretraživanje za kontrolu pristupa.",
+ "LDAP_User_Search_Field_Description": "LDAP atribut koji identificira LDAP korisnika koji pokušava provjeru autentičnosti. Ovo polje mora biti `sAMAccountName` za većinu Active Directory instalacija, ali to može biti` uid` za druge LDAP rješenjima, kao što su OpenLDAP. Možete koristiti `mail` identificiraju korisnike putem e-maila ili bilo atribut želite. Možete koristiti više vrijednosti odvojene zarezom kako bi se omogućilo korisnicima da se prijavite koristeći višestruke identifikatore kao što su korisničko ime ili e-mail.",
+ "LDAP_User_Search_Filter_Description": "Ako je navedeno, samo korisnicima koji odgovaraju filteru će biti dopušteno da se prijavite. Ako nijedan filtar nije naveden, svi korisnici u okviru zadane osnovne domene moći će se prijaviti. Npr za Active Directory`memberOf=cn=ROCKET_CHAT,ou=General Groups`.. Npr za OpenLDAP `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "LDAP korisnik koja obavlja korisničke dohvate za autentifikaciju drugih korisnika prilikom prijave. To je obično račun za uslugu izrađen posebno za treće integracijama. Koristite potpuno kvalificirani naziv, kao što je `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "Omogući",
"LDAP_Enable_Description": "Pokušaj koristiti LDAP za provjeru autentičnosti.",
"LDAP_Encryption": "Šifriranje",
"LDAP_Encryption_Description": "Način šifriranja koristi za sigurnu komunikaciju s LDAP poslužiteljem. Primjeri uključuju `plain` (bez enkripcije),` SSL / LDAPS` (šifriranu od početka), i `StartTLS` (nadogradite na šifrirani komunikacije nekad povezano).",
+ "LDAP_Group_Filter_Group_Name": "Ime grupe",
"LDAP_Host": "Domaćin",
"LDAP_Host_Description": "LDAP domaćin, npr `ldap.example.com` ili` 10.0.0.30`.",
- "LDAP_Import_Users": "Uvezi LDAP korisnike",
"LDAP_Merge_Existing_Users": "Spoji postojeće korisnike",
"LDAP_Merge_Existing_Users_Description": "*Oprez!* Pri uvozu korisnika s LDAPa i ako već postoji korisnik s istim korisničkim imenom, LDAP podaci i lozinka će biti postavljeni na postojećeg korisnika.",
"LDAP_Port": "Port",
@@ -691,12 +690,9 @@
"LDAP_Sync_User_Data_Description": "Održavajte korisničke podatke sinkronizirane sa serverom pri prijavi (npr: ime i prezime, e-mail).",
"LDAP_Sync_User_Data_FieldMap": "Mapa korisničkih podataka",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfigurirajte kako će korisnička polja (poput emaila) biti popunje iz zapisa na LDAPu (nakon što ih nađemo). Na primjer, `{\"cn\":\"name\", \"mail\":\"email\"}` će odabrati čitljivo ime iz cn atributa i njihov email i mail atributa. Dostupna polja uključuju `name`i `email`.",
- "LDAP_Sync_Users": "Sinkronizacija korisnika",
"LDAP_Test_Connection": "Testiraj vezu",
"LDAP_Unique_Identifier_Field": "Jedinstveni identifikator polja",
"LDAP_Unique_Identifier_Field_Description": "Koje polje će se koristiti za povezivanje LDAP korisnika i korisnika Rocket.Chat. Možete koristiti višestruke vrijednosti odvojene zarezom kako bi dobili vrijednost iz LDAP zapisa. Zadana vrijednost je `objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Koristite Custom Domain Search",
- "LDAP_Use_Custom_Domain_Search_Description": "Napišite vlastiti filter za pretraživanje korisnika u LDAP poslužitelju.",
"LDAP_Username_Field": "Polje za Korisničko ime",
"LDAP_Username_Field_Description": "Koje polje će se koristiti kao *username* za nove korisnike. Ostavite prazno za korištenje korisničkog imena s prijave. Možete koristiti oznake poput `#{givenName}.#{sn}`. Zadana vrijednost je `sAMAccountName`.",
"Least_Amount": "Najmanja količina",
@@ -789,6 +785,9 @@
"Message_editing": "Uređivanje poruke",
"Message_GroupingPeriod": "Razdoblje grupiranja (u sekundama)",
"Message_GroupingPeriodDescription": "Poruke će biti grupirane s prethodnim poruka ako su oboje od istog korisnika, a proteklo vrijeme je manje od zadanog u sekundama.",
+ "Message_HideType_ru": "Sakrij \"Korisnik je maknuo\" poruke",
+ "Message_HideType_uj": "Sakrij \"Korisnik se pridružio\" poruke",
+ "Message_HideType_ul": "Sakrij \"Korisnik je otišao\" poruke",
"Message_KeepHistory": "Zadrži Povijest Poruka",
"Message_MaxAll": "Maksimalna veličina sobe za SVE poruke",
"Message_MaxAllowedSize": "Maksimalna dopuštena veličina poruke",
@@ -800,6 +799,7 @@
"Message_ShowEditedStatus": "Prikaži uređeni status",
"Message_ShowFormattingTips": "Prikaži Savjete za oblikovanje",
"Message_starring": "Dodavanje zvjezdica na poruka",
+ "Message_TimeAndDateFormat": "Format Vremena i Datuma",
"Message_TimeFormat": "Format vremena",
"Message_TimeFormat_Description": "Vidi: Moment.js ",
"Message_too_long": "Poruka je preduga",
@@ -815,6 +815,7 @@
"Meta_robots": "Roboti",
"Min_length_is": "Minimalna dužina je %s",
"minutes": "minuta",
+ "Mobile": "Mobilno",
"Monday": "Ponedjeljak",
"Monitor_history_for_changes_on": "Prati povijest za promjena na",
"More_channels": "Više kanala",
@@ -844,6 +845,7 @@
"New_password": "Nova lozinka",
"New_role": "Nova uloga",
"New_Room_Notification": "Obavijest o novoj sobi",
+ "New_Trigger": "Novi Okidač",
"No_available_agents_to_transfer": "Nema dostupnih agenata za prijenos",
"No_channel_with_name_%s_was_found": "Soba s imenom \"%s\" nije nađena",
"No_channels_yet": "Još nisi dio nijedne sobe.",
@@ -860,6 +862,7 @@
"No_user_with_username_%s_was_found": "Korisnik sa korisničkim imenom \"%s\" nije nađen!",
"Nobody_available": "Nema nikoga dostupnog",
"Node_version": "Node verzija",
+ "None": "Ništa",
"Normal": "Normalno",
"Not_authorized": "Niste ovlašteni",
"Not_Available": "Nije dostupno",
@@ -868,6 +871,7 @@
"Nothing_found": "Ništa nije nađeno",
"Notification_Duration": "Trajanje obavijesti",
"Notifications": "Obavijesti",
+ "Notify_active_in_this_room": "Obavijesti aktivne korisnike u ovoj sobi",
"Notify_all_in_this_room": "Obavijesti sve u ovoj sobi",
"Num_Agents": "# agenata",
"Number_of_messages": "Broj poruka",
@@ -878,7 +882,7 @@
"Off_the_record_conversation": "Sigurnosno-nezabilježenih razgovora",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Sigurnosno-nezabilježen razgovor nije dostupan za vaš preglednik ili uređaj.",
"Office_Hours": "Uredovni Sati",
- "Office_Hours_Enabled": "Uredovni Sati omogućeno",
+ "Office_hours_enabled": "Uredovni Sati omogućeno",
"Offline": "Offline",
"Offline_DM_Email": "__user__ vas je izravno kontaktirao",
"Offline_form": "Izvanmrežni obrazac",
@@ -896,6 +900,7 @@
"Open_days_of_the_week": "Otvoreni Dani u Tjednu",
"Open_Livechats": "Otvori Livechat",
"Opened": "Otvoreno",
+ "Opened_in_a_new_window": "Otvoren u novom prozoru.",
"Opens_a_channel_group_or_direct_message": "Otvori sobu, grupu ili direktnu poruku",
"optional": "neobavezno",
"or": "ili",
@@ -940,6 +945,7 @@
"Please_fill_a_name": "Molimo ispunite ime",
"Please_fill_a_username": "Molimo Vas da ispunite korisničko ime",
"Please_fill_name_and_email": "Molimo Vas da ispunite ime i e-mail",
+ "Please_select_an_user": "Molimo odaberite korisnika",
"Please_select_enabled_yes_or_no": "Odaberite opciju za Omogućeno",
"Please_wait": "Pričekajte",
"Please_wait_activation": "Molimo pričekajte, ovo bi moglo potrajati neko vrijeme.",
@@ -953,13 +959,13 @@
"Preferences": "Postavke",
"Preferences_saved": "Postavke spremljene",
"Privacy": "Privatnost",
- "Private": "Privatno",
+ "Private": "Privatni",
"Private_Group": "Privatna Grupa",
"Private_Groups": "Privatne Grupe",
"Private_Groups_list": "Popis privatnih grupa",
"Profile": "Profil",
"Profile_saved_successfully": "Profil je uspješno sačuvan",
- "Public": "Javno",
+ "Public": "Javni",
"Push": "Push obavijesti",
"Push_apn_cert": "APN Cert",
"Push_apn_dev_cert": "APN Dev Cert",
@@ -994,7 +1000,9 @@
"Refresh_keys": "Osvježi ključeve",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Osvježi stranicu nakon instalacije kako bi se omogućilo dijeljenje zaslona",
"Register": "Registriraj novi račun",
+ "Registration": "Registracija",
"Registration_Succeeded": "Registracija je uspjela ",
+ "Regular_Expressions": "Regularni Izrazi",
"Release": "Izdanje",
"Remove": "Ukloni",
"Remove_Admin": "Makni Administratora",
@@ -1005,10 +1013,12 @@
"Remove_last_admin": "Ukloni zadnjeg administratora",
"Remove_someone_from_room": "Uklonite nekoga iz sobe",
"Removed": "Uklonjeno",
+ "Reply": "Odgovor",
"Report_Abuse": "Prijavi zlostavljanje",
"Report_exclamation_mark": "Izvješće!",
"Report_sent": "Izvješće je poslano",
"Report_this_message_question_mark": "Prijavi ovu poruku?",
+ "Reporting": "Prijava",
"Require_password_change": "Zahtijevaj promjenu lozinke",
"Resend_verification_email": "Ponovno pošalji e-mail potvrdu",
"Reset": "Resetiraj",
@@ -1027,13 +1037,17 @@
"room_changed_privacy": "__user_by__ je promjenio vrstu sobe u __room_type__ ",
"room_changed_topic": "__user_by__ je promjenip temu sobe u __room_topic__ ",
"Room_description_changed_successfully": "Opis sobe je uspješno promjenjen",
+ "Room_has_been_archived": "Soba je arhivirana",
"Room_has_been_deleted": "Soba je obrisana",
+ "Room_has_been_unarchived": "Soba je vraćena iz arhive",
"Room_Info": "Info Sobe",
+ "room_is_blocked": "Ova soba je blokirana",
"room_is_read_only": "Ova soba je samo za čitanje",
"room_name": "ime sobe",
"Room_name_changed": "__user_by__ je promjenio ime sobe u: __room_name__ ",
"Room_name_changed_successfully": "Ime sobe je uspješno izmijenjeno",
"Room_not_found": "Soba nije nađena",
+ "Room_password_changed_successfully": "Lozinka sobe je uspješno promijenjena",
"Room_topic_changed_successfully": "Tema sobe je uspješno promijenjena",
"Room_type_changed_successfully": "Vrsta sobe je uspješno promijenjena",
"Room_unarchived": "Soba je dearhivirana",
@@ -1136,6 +1150,7 @@
"SMTP_Test_Button": "Testiraj SMTP postavke",
"SMTP_Username": "SMTP korisničko ime",
"Sound": "Zvuk",
+ "Sound_File_mp3": "Zvučni zapis (mp3)",
"SSL": "SSL",
"Star_Message": "Označi Poruku Zvjezdicom",
"Starred_Messages": "Poruke sa zvjezdicom",
@@ -1160,6 +1175,7 @@
"Stats_Total_Channels": "Ukupno kanala",
"Stats_Total_Direct_Messages": "Ukupno Soba s Izravnim Porukama",
"Stats_Total_Messages": "Ukupno poruka",
+ "Stats_Total_Messages_Channel": "Ukupno poruka u Kanalima",
"Stats_Total_Private_Groups": "Ukupno Privatnih Grupa",
"Stats_Total_Rooms": "Ukupno soba",
"Stats_Total_Users": "Ukupno korisnika",
@@ -1194,20 +1210,24 @@
"The_user_will_be_removed_from_s": "Korisnik će biti uklonjen iz %s",
"The_user_wont_be_able_to_type_in_s": "Korisnik neće moći pisati u %s",
"Theme": "Tema",
+ "theme-color-component-color": "Boja komponente",
"theme-color-content-background-color": "Boja pozadine sadržaja",
+ "theme-color-custom-scrollbar-color": "Prilagođena boja klizača",
+ "theme-color-error-color": "Boja greške",
+ "theme-color-info-font-color": "Boja slova informacija",
+ "theme-color-link-font-color": "Boja slova poveznice",
"theme-color-primary-background-color": "Primarna boja pozadine",
"theme-color-primary-font-color": "Primarna boja slova",
"theme-color-secondary-background-color": "Sekundarna boja pozadine",
"theme-color-secondary-font-color": "Sekundarna boja slova",
- "theme-color-tertiary-background-color": "Tercijarna boja pozadine",
- "theme-color-tertiary-font-color": "Tercijarna boja slova",
- "theme-color-link-font-color": "Boja slova poveznice",
- "theme-color-info-font-color": "Boja slova informacija",
- "theme-color-custom-scrollbar-color": "Prilagođena boja klizača",
+ "theme-color-selection-color": "Boja odabranog",
"theme-color-status-away": "Boja odsutnog statusa",
"theme-color-status-busy": "Boja zauzetog statusa",
"theme-color-status-offline": "Boja izvanmrežnog statusa",
"theme-color-status-online": "Boja umreženog statusa",
+ "theme-color-success-color": "Boja uspješnog",
+ "theme-color-tertiary-background-color": "Tercijarna boja pozadine",
+ "theme-color-tertiary-font-color": "Tercijarna boja slova",
"theme-color-unread-notification-color": "Boja Nepročitanih Obavijesti",
"theme-custom-css": "Prilagođeni CSS",
"theme-font-body-font-family": "Font Obitelj Tijela",
@@ -1230,6 +1250,10 @@
"to_see_more_details_on_how_to_integrate": "kako bi vidjeli više detalja o integraciji",
"To_users": "Korisnicima",
"Topic": "Tema",
+ "Transcript_Enabled": "Pitaj posjetitelja bi li htio transkript nakon što je chat zatvoren",
+ "Transcript_message": "Poruka koja će biti prikazana kad korisnik zatraži transkript",
+ "Transcript_of_your_livechat_conversation": "Transkript tvog razgovora",
+ "Translations": "Prijevodi",
"Travel_and_Places": "Putovanja & Mjesta",
"Trigger_removed": "Okidač uklonjen",
"Trigger_Words": "Riječi okidača",
@@ -1243,27 +1267,31 @@
"Type_your_new_password": "Upišite novu lozinku",
"UI_DisplayRoles": "Prikaži uloge",
"UI_Merge_Channels_Groups": "Spoji privatne grupe s kanalima",
+ "UI_Use_Name_Avatar": "Koristi inicijale punog imena kako bi stvorio avatar",
"Unarchive": "Dearhiviraj",
+ "Unblock_User": "Odblokiraj Korisnika",
"Unmute_someone_in_room": "Uključi nekoga u sobi",
"Unmute_user": "Uključi korisnika",
"Unnamed": "Neimenovano",
"Unpin_Message": "Otkvači Poruku",
- "Unread_Alert": "Nepročitane obavijesti",
"Unread_Rooms": "Nepročitane Sobe",
"Unread_Rooms_Mode": "Mod Nepročitanih Soba",
"Unstar_Message": "Ukloni zvjezdicu",
+ "Upload_file_description": "Opis fajla",
+ "Upload_file_name": "Ime fajla",
"Upload_file_question": "Prenesi datoteku?",
"Uploading_file": "Prijenos datoteke ...",
"Uptime": "Raspoloživost",
"URL": "URL",
+ "URL_room_prefix": "URL prefix sobe",
"Use_account_preference": "Koristite postavke računa",
- "Use_Emojis": "Koristite Emotikone",
+ "Use_Emojis": "Koristi Emotikone",
"Use_Global_Settings": "Koristite globalne postavke",
"Use_initials_avatar": "Koristi inicijale svog korisničkog imena",
"Use_service_avatar": "Koristi %s avatar",
"Use_this_username": "Koristi ovo korisničko ime",
"Use_uploaded_avatar": "Koristi prenijeti avatar",
- "Use_url_for_avatar": "Koristite URL za avatar",
+ "Use_url_for_avatar": "Koristi URL za avatar",
"Use_User_Preferences_or_Global_Settings": "Koristite korisnikove postavke ili globalne postavke",
"User__username__is_now_a_moderator_of__room_name_": "Korisnik __username__ je sada moderator sobe __room_name__",
"User__username__is_now_a_owner_of__room_name_": "Korisnik __username__ je sada vlasnik sobe __room_name__",
@@ -1279,8 +1307,11 @@
"User_has_been_muted_in_s": "Korisnik je utišan u %s",
"User_has_been_removed_from_s": "Korisnik je uklonjen iz %s",
"User_Info": "Podaci o korisniku",
+ "User_Interface": "Korisničko sučelje",
+ "User_is_blocked": "Korisnik je blokiran",
"User_is_no_longer_an_admin": "Korisnik više nije admin",
"User_is_now_an_admin": "Korisnik je sada admin",
+ "User_is_unblocked": "Korisnik je odblokiran",
"User_joined_channel": "Ušao u sobu.",
"User_joined_channel_female": "Ušla u sobu.",
"User_joined_channel_male": "Ušao u sobu.",
@@ -1314,14 +1345,20 @@
"Username_title": "Registriraj korisničko ime",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ želi započeti SP. Želite li prihvatiti?",
"Users": "Korisnici",
+ "Users_added": "Korisnici su dodani",
"Users_in_role": "Korisnici u ulozi",
"UTF8_Names_Slugify": "UTF8 Imena Slugify",
"UTF8_Names_Validation": "UTF8 Provjera Imena",
"UTF8_Names_Validation_Description": "RegExp koji će biti korišten za provjeru korisničkih imena i imena soba",
+ "Validate_email_address": "Validiraj email adresu",
+ "Verification": "Verifikacija",
+ "Verification_Email": "Klikni ovdje da bi potvrdio svoj račun.",
"Verification_email_sent": "Provjera e-maila poslana",
+ "Verification_Email_Subject": "[Site_Name] - Potvrdi svoj račun",
"Verified": "Ovjeren",
"Version": "Verzija",
"Video_Chat_Window": "Video razgovor",
+ "Video_Conference": "Video Konferencija",
"Videocall_declined": "Videopoziv odbijen",
"Videocall_enabled": "Videopoziv omogućen",
"View_All": "Prikaži Sve",
@@ -1337,6 +1374,7 @@
"Visitor_page_URL": "URL stranice posjetitelja",
"Visitor_time_on_site": "Vrijeme posjetitelja na stranici",
"Wait_activation_warning": "Prije nego što se prijavite, vaš račun mora ručno aktivirati administrator.",
+ "Warnings": "Upozorenja",
"We_are_offline_Sorry_for_the_inconvenience": "Mi smo izvan mreže. Oprostite na neugodnosti.",
"We_have_sent_password_email": "Poslan ti je e-mail sa uputama za resetiranje lozinke. Provjeri i spam folder! Ako ga ne primiš uskoro, molimo te, vrati se i pokušaj opet.",
"We_have_sent_registration_email": "Poslan ti je e-mail kako bi potvrdio svoju registraciju. Provjeri i spam folder! Ako ga ne primiš uskoro, molimo te vrati se i pokušaj opet.",
@@ -1354,12 +1392,14 @@
"will_be_able_to": "će moći",
"Would_you_like_to_return_the_inquiry": "Želite li vratiti upit?",
"Yes": "Da",
+ "Yes_archive_it": "Da, arhiviraj!",
"Yes_clear_all": "Da, makni sve!",
"Yes_delete_it": "Da, obriši!",
"Yes_hide_it": "Da, sakrij!",
"Yes_leave_it": "Da, napusti!",
"Yes_mute_user": "Da, utišaj korisnika!",
"Yes_remove_user": "Da, ukloni korisnika!",
+ "Yes_unarchive_it": "Da, izvadi iz arhive!",
"You": "Vi",
"you_are_in_preview_mode_of": "Ti si u preglednom načinu sobe # __room_name__ ",
"You_are_logged_in_as": "Prijavljeni ste kao",
@@ -1393,4 +1433,4 @@
"your_message_optional": "tvoja poruka (opcionalno)",
"Your_password_is_wrong": "Vaša lozinka je pogrešna!",
"Your_push_was_sent_to_s_devices": "Push obavijest je poslana %s uređaje"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/hu.i18n.json b/packages/rocketchat-i18n/i18n/hu.i18n.json
index 9a1c4837bac65..c4f26287970b7 100644
--- a/packages/rocketchat-i18n/i18n/hu.i18n.json
+++ b/packages/rocketchat-i18n/i18n/hu.i18n.json
@@ -1,19 +1,24 @@
{
+ "#channel": "#csatorna",
"0_Errors_Only": "0 - Csak hibák",
"1_Errors_and_Information": "1 - Hibák és Információk",
- "2_Erros_Information_and_Debug": "2 - Hibák, Információk és Debug",
+ "2_Erros_Information_and_Debug": "2 - Hibák, információk és hibakeresés",
"403": "Tiltott",
"500": "Belső Szerverhiba",
+ "@username": "@felhasználónév",
+ "@username_message": "@felhasználónév ",
"__username__is_no_longer__role__defined_by__user_by_": "__username__ már nem __role__, által __user_by__",
"__username__was_set__role__by__user_by_": "__username__ állították __role__ által __user_by__",
"Accept": "Ok",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "A bejövő élő chat felkérés elfogadása akkor is, ha nincs elérhető ügynök",
+ "Accept_with_no_online_agents": "Elfogadás online ügynök nélkül",
"Access_not_authorized": "Hozzáférés nem engedélyezett",
"Access_Token_URL": "Access Token URL",
- "Accessing_permissions": "Hozzáférés jogosultságok",
+ "Accessing_permissions": "Hozzáférési jogosultságok",
"Account_SID": "Fiók SID",
"Accounts": "Fiókok",
"Accounts_AllowDeleteOwnAccount": "Felhasználó törölheti saját fiókját",
- "Accounts_AllowedDomainsList": "Engedélyezett domainek listája",
+ "Accounts_AllowedDomainsList": "Engedélyezett domain-ek listája",
"Accounts_AllowedDomainsList_Description": "Engedélyezett domain-ek listája (vesszővel elválasztva)",
"Accounts_AllowEmailChange": "E-mail cím megváltoztatható",
"Accounts_AllowPasswordChange": "Jelszó megváltoztatható",
@@ -22,8 +27,6 @@
"Accounts_AllowUserProfileChange": "Felhasználó módosíthatja profilját",
"Accounts_AvatarResize": "Profilképek átméretezése",
"Accounts_AvatarSize": "Profilkép mérete",
- "Accounts_AvatarStorePath": "Profilkép tárolásának elérési útja",
- "Accounts_AvatarStoreType": "Profilkép tárolásának típusa",
"Accounts_BlockedDomainsList": "Blokkolt domainek listája",
"Accounts_BlockedDomainsList_Description": "Blokkolt domain-ek listája (vesszővel elválasztva)",
"Accounts_BlockedUsernameList": "Blokkolt felhasználónevek listája",
@@ -32,9 +35,10 @@
"Accounts_EmailVerification": "Email megerősítése",
"Accounts_EmailVerification_Description": "Győződjön meg róla, hogy az SMTP megfelelően be van állítva",
"Accounts_Enrollment_Email": "Beiratkozás E-mail",
- "Accounts_Enrollment_Email_Default": " Isten hozott a [Site_Name] Tovább a [Site_URL], és próbálja a legjobb nyílt forráskódú chat megoldást ma elérhető!
",
+ "Accounts_Enrollment_Email_Default": " Isten hozott a [Site_Name] Tovább a [Site_URL] , és próbálja a legjobb nyílt forráskódú chat megoldást ma elérhető!
",
"Accounts_Enrollment_Email_Description": "Lehet használni [name], [fname], [lname] a felhasználó teljes nevét, keresztnevét vagy vezetéknevét, ill. Lehet használni [email] A felhasználó e-mail.",
"Accounts_Enrollment_Email_Subject_Default": "Üdvözöljük a [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "Elfelejtett felhasználói munkamenet bezárása",
"Accounts_Iframe_api_method": "Api módszer",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "Engedélyezett",
@@ -49,9 +53,12 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "identity Path",
"Accounts_OAuth_Custom_Login_Style": "Bejelentkezési stílus",
+ "Accounts_OAuth_Custom_Merge_Users": "Felhasználók összevonása",
+ "Accounts_OAuth_Custom_Scope": "hatáskör",
"Accounts_OAuth_Custom_Secret": "Titok",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token keresztül küldött",
+ "Accounts_OAuth_Custom_Username_Field": "felhasználónév menző",
"Accounts_OAuth_Facebook": "Facebook bejelentkezés",
"Accounts_OAuth_Facebook_callback_url": "Facebook visszahívás URL",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -85,7 +92,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter titkos",
"Accounts_OAuth_Wordpress": "WordPress Bejelentkezés",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress visszahívás URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress visszahívás URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Jelszó visszaállítása",
@@ -96,12 +103,15 @@
"Accounts_RegistrationForm_Public": "Nyilvános",
"Accounts_RegistrationForm_Secret_URL": "titkos URL",
"Accounts_RegistrationForm_SecretURL": "Regisztrációs űrlap titkos URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Meg kell adnia egy véletlenszerű karaktersorozat, amely hozzáadódik a regisztrációs URL-t. Példa: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Meg kell adnia egy véletlenszerű karaktersorozat, amely hozzáadódik a regisztrációs URL-t. Példa: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Igényel elnevezése Regisztráció",
+ "Accounts_RequirePasswordConfirmation": "Igényelt jelszó megerősítése",
+ "Accounts_SetDefaultAvatar": "alapértelmezett Avatar beállítása",
+ "Accounts_SetDefaultAvatar_Description": "alapértelmezett Avatar meghatározása az Oauth vagy a Gravatar alapján",
"Accounts_ShowFormLogin": "Megmutatása űrlap alapú bejelentkezés",
"Accounts_UseDefaultBlockedDomainsList": "Use Default blokkolt domainek listája",
"Accounts_UseDNSDomainCheck": "DNS használata Domain ellenőrzése",
- "Accounts_UserAddedEmail_Default": " Isten hozott a [Site_Name] Tovább a [Site_URL], és próbálja a legjobb nyílt forráskódú chat megoldást ma elérhető!
Beléphet használja az e-mail: [email] és jelszót [password]. Szükség lehet változtatni, miután az első bejelentkezés.",
+ "Accounts_UserAddedEmail_Default": "
Isten hozott a [Site_Name] Tovább a [Site_URL] , és próbálja a legjobb nyílt forráskódú chat megoldást ma elérhető!
Beléphet használja az e-mail: [email] és jelszót [password]. Szükség lehet változtatni, miután az első bejelentkezés.",
"Accounts_UserAddedEmail_Description": "Használhatja a következő szimbólumokat:
[name], [fname], [lname] a felhasználó teljes nevét, keresztnevét vagy vezetéknevét, ill. [email] A felhasználó e-mail. [password] a felhasználó jelszavát. [Site_Name] és [Site_URL] Az Alkalmazás neve és URL ill. ",
"Accounts_UserAddedEmailSubject_Default": "Akkor kerültek fel [Site_Name]",
"Activate": "Aktiválja",
@@ -109,6 +119,7 @@
"Add": "hozzáad",
"Add_agent": "Add ügynök",
"Add_custom_oauth": "Add egyéni OAuth",
+ "Add_Domain": "domain hozzáadása",
"Add_manager": "Add menedzser",
"Add_user": "Add felhasználó",
"Add_User": "Felhasználó hozzáadása",
@@ -120,9 +131,11 @@
"Additional_Feedback": "további Visszajelzés",
"Administration": "Adminisztráció",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Miután OAuth2 hitelesítésre, a felhasználók lesz irányítva erre az URL",
+ "Agent": "ügynök",
"Agent_added": "Agent hozzáadott",
"Agent_removed": "Agent eltávolított",
"Alias": "Álnév",
+ "Alias_Format": "álnév formátum",
"All": "Minden",
"All_channels": "minden csatorna",
"All_logs": "minden rönk",
@@ -145,10 +158,13 @@
"API_EmbedIgnoredHosts_Description": "Vesszővel elválasztott listája hosts vagy CIDR címeket, pl. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "biztonságos portok",
"API_EmbedSafePorts_Description": "Vesszővel elválasztott listája portok engedélyezve előnézetét.",
+ "API_Enable_CORS": "CORS engedélyezése",
+ "API_Enable_Direct_Message_History_EndPoint": "Teljes közvetlen üzenetek történetének engedélyezése",
"API_GitHub_Enterprise_URL": "szerver URL",
"API_GitHub_Enterprise_URL_Description": "Példa: http://domain.com (kivéve záró perjel)",
"API_Gitlab_URL": "GitLab URL",
"API_Token": "API Token",
+ "API_Upper_Count_Limit": "maximális feljegyzés mennyisége",
"API_User_Limit": "Használati Limit hozzátéve, hogy minden felhasználó csatornára",
"API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Key",
@@ -164,6 +180,7 @@
"Are_you_sure": "Biztos vagy benne?",
"Are_you_sure_you_want_to_delete_your_account": "Biztos, hogy törli a fiókot?",
"at": "nál nél",
+ "Attachment_File_Uploaded": "Fájl feltöltve",
"Auth_Token": "Auth Token",
"Author": "Szerző",
"Authorization_URL": "engedélyezési URL",
@@ -178,6 +195,7 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URL",
"AutoLinker_Urls_www": "AutoLinker \"www\" URL",
"AutoLinker_UrlsRegExp": "AutoLinker URL reguláris kifejezés",
+ "AutoTranslate_Enabled": "automatikus fordítás engedélyezése",
"Available": "Elérhető",
"Available_agents": "elérhető szerek",
"Avatar": "Kép megváltoztatása",
@@ -192,9 +210,10 @@
"Away_male": "El",
"Back": "Hát",
"Back_to_applications": "Vissza az alkalmazások",
- "Back_to_integrations": "Vissza az integrációk",
+ "Back_to_integrations": "Vissza az integrációkhoz",
"Back_to_login": "Vissza a bejelentkezéshez",
"Back_to_permissions": "Vissza az engedélyeket",
+ "Block_User": "felhasználó blokkolása",
"Body": "Test",
"bold": "bátor",
"Branch": "Ág",
@@ -205,17 +224,27 @@
"busy_male": "elfoglalt",
"Busy_male": "Elfoglalt",
"by": "által",
+ "cache_cleared": "Cache törölve",
"Cancel": "Mégse",
"Cancel_message_input": "Mégse",
"Cannot_invite_users_to_direct_rooms": "Nem lehet meghívni a felhasználók közvetlen szobák",
+ "CAS_button_color": "Bejelentkezés gomb háttérszíne",
+ "CAS_button_label_color": "Bejelentkezés gomb színe",
+ "CAS_button_label_text": "Bejelentkezés gomb felirata",
+ "CAS_enabled": "Engedélyezett",
+ "CAS_version": "CAS verzió",
"CDN_PREFIX": "CDN előtag",
"Certificates_and_Keys": "Bizonyítványok és kulcsok",
+ "Change_Room_Type": "Szoba típusának változtatása",
"Changing_email": "változó email",
+ "channel": "csatorna",
"Channel": "Csatorna",
"Channel_already_exist": "A csatorna \"#% s 'már létezik.",
"Channel_already_Unarchived": "Csatorna névvel `#% s` már archivált állapotban",
"Channel_Archived": "Csatorna névvel `#% s` archiválva lett sikeres",
+ "Channel_created": "Csatorna `#%s` létre lett hozva.",
"Channel_doesnt_exist": "A csatorna `# %s` nem létezik.",
+ "Channel_to_listen_on": "Csatorna figyelő",
"Channel_Unarchived": "Csatorna névvel `#% s` már archivált sikeresen",
"Channels": "Csatornák",
"Channels_list": "Nyilvános csatornák listája",
@@ -230,13 +259,18 @@
"Choose_messages": "üzenetek kiválasztása",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Válassza Alias előtt jelenik meg a felhasználónevét üzeneteket.",
"Choose_the_username_that_this_integration_will_post_as": "Válassza ki a felhasználónevét, hogy ez az integráció utáni mint.",
+ "clear": "Törlés",
"Clear_all_unreads_question": "Törölje az összes unreads?",
+ "clear_cache_now": "Cache törlése ",
"Click_here": "Kattints ide",
+ "Click_here_for_more_info": "Kattints ide a további információért",
"Client_ID": "ügyfél-azonosító",
"Client_Secret": "Client Secret",
"Clients_will_refresh_in_a_few_seconds": "Az ügyfelek frissíteni néhány másodperc",
"close": "bezár",
+ "Close": "Bezárás",
"Closed": "Zárva",
+ "Closed_by_visitor": "Látogató által bezárva",
"Closing_chat": "záró beszélgetés",
"Collapse_Embedded_Media_By_Default": "Összecsukása beágyazott média alapértelmezés",
"Color": "Szín",
@@ -259,16 +293,32 @@
"Created_at_s_by_s": "Alkotó:% s% s ",
"Current_Chats": "jelenlegi beszélgetés",
"Custom": "Szokás",
+ "Custom_Emoji": "Egyéni hangulatjelek",
+ "Custom_Emoji_Add": "Új Emoji hozzáadása",
+ "Custom_Emoji_Added_Successfully": "Egyéni hangulatjel sikeresen hozzáadva",
+ "Custom_Emoji_Has_Been_Deleted": "Az egyéni emoji törölve lett",
+ "Custom_Emoji_Info": "Info az egyéni Emojiról",
+ "Custom_Emoji_Updated_Successfully": "Az egyéni emoji feltöltése sikeres",
"Custom_Fields": "egyéni mezők",
"Custom_oauth_helper": "Amikor beállítja OAuth Szolgáltató, akkor tájékoztatni visszahívás URL. Használat %s .",
"Custom_oauth_unique_name": "Egyedi OAuth egyedi nevet",
"Custom_Script_Logged_In": "Egyedi szkript bejelentkezett felhasználóknak",
"Custom_Script_Logged_Out": "Egyedi szkript kijelentkezett felhasználó",
+ "Custom_Scripts": "Egyéni Srcipt",
+ "Custom_Sound_Add": "Egyéni hang hozzáadása",
+ "Custom_Sound_Delete_Warning": "A hang törlése nem vonható vissza.",
+ "Custom_Sound_Error_Invalid_Sound": "Érvénytelen hang",
+ "Custom_Sound_Error_Name_Already_In_Use": "Ez az egyéni hang már használatban van.",
+ "Custom_Sound_Has_Been_Deleted": "Az egyéni hang törölve lett.",
+ "Custom_Sound_Info": "Egyéni hang infó",
+ "Custom_Sound_Saved_Successfully": "Az egyéni hang sikeresen mentve",
+ "Custom_Sounds": "Egyéni Hangok",
+ "Custom_Translations": "Egyéni fordítás",
"Dashboard": "Műszerfal",
- "Date": "Dátum",
+ "Date": "Időpont",
"days": "napok",
- "DB_Migration": "adatbázis migráció",
- "DB_Migration_Date": "Adatbázis migráció dátuma",
+ "DB_Migration": "Adatbázis migráció",
+ "DB_Migration_Date": "Adatbázis migráció időpontja",
"Deactivate": "deaktiválása",
"Default": "Alapértelmezett",
"Delete": "Töröl",
@@ -279,7 +329,7 @@
"Deleted": "Törölve!",
"Department_removed": "Department eltávolított",
"Departments": "Osztályok",
- "Deployment_ID": "Telepítés ID",
+ "Deployment_ID": "Telepítés azonosító",
"Description": "Leírás",
"Desktop": "Desktop",
"Desktop_Notification_Test": "Asztali értesítés teszt",
@@ -296,7 +346,7 @@
"Domain": "Domain",
"Domains": "Domains",
"Drop_to_upload_file": "Dobd lehet feltölteni a fájlt",
- "Dry_run": "Szárazon futás",
+ "Dry_run": "Tesztelés",
"Dry_run_description": "Csak akkor küldünk egy e-mailt, hogy ugyanaz a cím, mint a From. Az e-mail kell tartozniuk felhasználó érvényes.",
"Duplicate_archived_channel_name": "Archivált Channel névvel ' %s' létezik",
"Duplicate_archived_private_group_name": "Archivált Private csoport név ' %s' létezik",
@@ -311,16 +361,16 @@
"Email": "Email",
"Email_address_to_send_offline_messages": "E-mail címét, hogy üzenetet küldjön",
"Email_already_exists": "Az e-mail cím már létezik",
- "Email_body": "E-mail test",
+ "Email_body": "E-mail szövege",
"Email_Change_Disabled": "Az Rocket.Chat rendszergazda letiltotta a változó e-mail",
"Email_Footer_Description": "Használhatja a következő szimbólumokat: [Site_Name] és [Site_URL] Az Alkalmazás neve és URL ill. ",
- "Email_from": "Ból ből",
+ "Email_from": "Feladó",
"Email_Header_Description": "Használhatja a következő szimbólumokat: [Site_Name] és [Site_URL] Az Alkalmazás neve és URL ill. ",
"Email_Notification_Mode": "Offline-mail értesítések",
"Email_Notification_Mode_All": "Minden Említés / DM",
"Email_Notification_Mode_Disabled": "Tiltva",
"Email_or_username": "Email or username",
- "Email_subject": "Tantárgy",
+ "Email_subject": "Tárgy",
"Email_verified": "Email hitelesítve",
"Emoji": "Emoji",
"Empty_title": "üres címet",
@@ -412,8 +462,11 @@
"Field": "Mező",
"Field_removed": "Field eltávolított",
"File_exceeds_allowed_size_of_bytes": "Fájl mérete meghaladja a megengedett méretet a __size__ bájt",
+ "File_uploaded": "Fájl feltöltve",
"FileUpload": "Fájlfeltöltés",
+ "FileUpload_Disabled": "Fájl feltöltés nem lehetséges.",
"FileUpload_Enabled": "Fájlfeltöltések Enabled",
+ "FileUpload_Enabled_Direct": "Fájl feltöltés engedélyezése a közvetlen üzeneteknél",
"FileUpload_File_Empty": "Fájl üres",
"FileUpload_FileSystemPath": "rendszer Path",
"FileUpload_MaxFileSize": "Feltölthető legnagyobb fájlméret (bájtban)",
@@ -438,7 +491,14 @@
"Force_SSL": "Force SSL",
"Force_SSL_Description": "* Figyelem! * _Force SSL_ soha nem lehet fordított proxy. Ha van egy fordított proxy, meg kell tennie az átirányítást OTT. Ez a lehetőség fennáll telepítések mint Heroku, amely nem teszi lehetővé az átirányítás konfiguráció a fordított proxy.",
"Forgot_password": "Elfelejtetted a jelszavad?",
+ "Forgot_Password_Email": "Kattints ide a jelszó visszaállításához.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - jelszó visszaállítva",
+ "Forward": "Előre",
+ "Forward_chat": "Chat továbbítása",
+ "Forward_to_department": "Továbbítás a részlegnek",
+ "Forward_to_user": "Továbbítás a felhasználónak",
"Frequently_Used": "gyakran használt",
+ "Friday": "Péntek",
"From": "Ból ből",
"From_Email": "az e-mailben",
"From_email_warning": "Figyelmeztetés: A mező van kitéve az e-mail szerver beállításait.",
@@ -447,10 +507,17 @@
"Give_a_unique_name_for_the_custom_oauth": "Adj egy egyedi nevet az egyéni OAuth",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Adjon az alkalmazás nevét. Ez látható lesz az Ön számára.",
"Global": "Globális",
+ "GoogleCloudStorage": "Google Cloud Storage",
"GoogleTagManager_id": "Google Címkekezelő Id",
+ "Guest_Pool": "Vendég medence",
"Hash": "hash",
"Header": "Fejléc",
+ "Header_and_Footer": "Fejléc és lábléc",
+ "Helpers": "Segítők",
+ "Hex_Color_Preview": "Hex színek elölnézet",
"Hidden": "Rejtett",
+ "Hide_Avatars": "Avatar elrejtése",
+ "Hide_flextab": "Jobb oldali sáv elrejtése kattintással",
"Hide_Group_Warning": "Biztosan el szeretné rejteni a csoport \" %s\"?",
"Hide_Private_Warning": "Biztosan el szeretné rejteni a beszélgetés \" %s\"?",
"Hide_room": "Szoba elrejtése",
@@ -471,7 +538,7 @@
"Importer_Archived": "archivált",
"Importer_done": "Importálása befejeződött!",
"Importer_finishing": "Utolsó simítások az import.",
- "Importer_From_Description": "Behozatal __from __ 's adatok Rocket.Chat.",
+ "Importer_From_Description": "__from __ adatok importálása Rocket.Chat-be.",
"Importer_import_cancelled": "Import törölték.",
"Importer_import_failed": "Hiba történt a futás az import.",
"Importer_importing_channels": "Importálása a csatornákat.",
@@ -492,15 +559,15 @@
"Install_FxOs_error": "Sajnos ez nem működik rendeltetésszerűen! A következő hiba jelent meg:",
"Install_FxOs_follow_instructions": "Kérjük, erősítse meg az alkalmazás telepítése a készülék (nyomja meg a \"telepítés\").",
"Installation": "Telepítés",
- "Installed_at": "telepítve",
+ "Installed_at": "Telepítés időpontja",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Útmutató a látogató töltse ki az űrlapot, hogy küldjön egy üzenetet",
"Integration_added": "Integráció került",
"Integration_Incoming_WebHook": "Bejövő WebHook integráció",
"Integration_New": "új integráció",
"Integration_Outgoing_WebHook": "Kimenő WebHook integráció",
"Integration_updated": "Integration frissült",
- "Integrations": "Integráció",
- "InternalHubot": "Internal Hubot",
+ "Integrations": "Integrációk",
+ "InternalHubot": "Belső Hubot",
"InternalHubot_ScriptsToLoad": "Scripts betölteni",
"InternalHubot_ScriptsToLoad_Description": "Kérjük, vesszővel elválasztott listáját szkriptek betölteni https://github.com/github/hubot-scripts/tree/master/src/scripts",
"InternalHubot_Username_Description": "Ez kell, hogy legyen egy érvényes felhasználónevet egy bot van regisztrálva a szerveren.",
@@ -566,24 +633,12 @@
"Layout_Terms_of_Service": "Szolgáltatás feltételei",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Egyéni Domain Search",
- "LDAP_Custom_Domain_Search_Description": "Egy darab JSON, amely szabályozza kötődnek és a kapcsolat adatainak és a forma: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Default Domain",
"LDAP_Description": "Az LDAP hierarchikus adatbázis sok cég használja, hogy single sign on - a létesítmény megosztása egy jelszót a több oldalak és szolgáltatások. Speciális konfigurációs információkat és példákat, kérjük forduljon a wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Domain Base",
- "LDAP_Domain_Base_Description": "A teljesen minősített elkülönítő neve (DN) LDAP részfa szeretne keresni felhasználókat és csoportokat. Akkor adjunk hozzá annyi, amennyit akar; azonban minden csoport kell meghatározni ugyanabban a tartományban bázis a felhasználók számára, hogy tartozik hozzá. Ha megadod korlátozott felhasználói csoportok, csak azok a felhasználók, hogy tartoznak azok a csoportok lesznek hatálya alá. Javasoljuk, hogy adja meg a felső szint a LDAP fa, mint a domain bázis és használja keresési szűrő a hozzáférés szabályozására.",
- "LDAP_Domain_Search_Filter": "Domain Search Filter",
- "LDAP_Domain_Search_Filter_Description": "Ha meg van adva, csak azok a felhasználók, amelyek megfelelnek a szűrőt tenni, hogy jelentkezzen be. Ha nincs szűrő megadva, az összes felhasználó körén belül a megadott tartomány bázis lesz képes bejelentkezni. Pl Active Directory `MemberOf = cn = ROCKET_CHAT, ou = Általános Groups`. Pl OpenLDAP (bővíthető találat keresés) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Kategória",
- "LDAP_Domain_Search_Object_Category_Description": "A * objectCategory * hogy azonosítsa a felhasználókat. Hagyja üresen * OpenLDAP *. Pl: `Person, stb",
- "LDAP_Domain_Search_Object_Class": "Domain Search Objektumosztály",
- "LDAP_Domain_Search_Object_Class_Description": "A * objectlass * hogy azonosítsa a felhasználókat. Pl: `organizationalPerson`,`-használó, `inetOrgPerson` stb",
- "LDAP_Domain_Search_Password": "Domain Search jelszó",
- "LDAP_Domain_Search_Password_Description": "A jelszó a domain kereső felhasználó.",
- "LDAP_Domain_Search_User": "Domain Felhasználó keresése",
- "LDAP_Domain_Search_User_Description": "Az LDAP felhasználó, amely végrehajtja a felhasználó kereséseket hitelesítésére felhasználók, amikor bejelentkeznek. Ez általában egy szolgáltatási fiókot létre kifejezetten a harmadik fél integrációk. Használjon teljes nevét, például `cn = Administrator, cn = Users, dc = példa, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search felhasználói azonosító",
- "LDAP_Domain_Search_User_ID_Description": "Az LDAP-attribútum, amely azonosítja az LDAP felhasználó, aki megkísérel hitelesítést. Ezt a mezőt kell `sAMAccountName` legtöbb Active Directory telepítés, de lehet, hogy` uid` más LDAP megoldások, mint például az OpenLDAP. A `mail` azonosítani felhasználókat e-mailben, vagy bármi kívánt attribútum. A többszörös értékeket vesszővel elválasztva, hogy a felhasználó bejelentkezési segítségével több azonosítók, mint a felhasználónév vagy e-mailben.",
+ "LDAP_BaseDN_Description": "A teljesen minősített elkülönítő neve (DN) LDAP részfa szeretne keresni felhasználókat és csoportokat. Akkor adjunk hozzá annyi, amennyit akar; azonban minden csoport kell meghatározni ugyanabban a tartományban bázis a felhasználók számára, hogy tartozik hozzá. Ha megadod korlátozott felhasználói csoportok, csak azok a felhasználók, hogy tartoznak azok a csoportok lesznek hatálya alá. Javasoljuk, hogy adja meg a felső szint a LDAP fa, mint a domain bázis és használja keresési szűrő a hozzáférés szabályozására.",
+ "LDAP_User_Search_Field_Description": "Az LDAP-attribútum, amely azonosítja az LDAP felhasználó, aki megkísérel hitelesítést. Ezt a mezőt kell `sAMAccountName` legtöbb Active Directory telepítés, de lehet, hogy` uid` más LDAP megoldások, mint például az OpenLDAP. A `mail` azonosítani felhasználókat e-mailben, vagy bármi kívánt attribútum. A többszörös értékeket vesszővel elválasztva, hogy a felhasználó bejelentkezési segítségével több azonosítók, mint a felhasználónév vagy e-mailben.",
+ "LDAP_User_Search_Filter_Description": "Ha meg van adva, csak azok a felhasználók, amelyek megfelelnek a szűrőt tenni, hogy jelentkezzen be. Ha nincs szűrő megadva, az összes felhasználó körén belül a megadott tartomány bázis lesz képes bejelentkezni. Pl Active Directory `MemberOf = cn = ROCKET_CHAT, ou = Általános Groups`. Pl OpenLDAP (bővíthető találat keresés) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Az LDAP felhasználó, amely végrehajtja a felhasználó kereséseket hitelesítésére felhasználók, amikor bejelentkeznek. Ez általában egy szolgáltatási fiókot létre kifejezetten a harmadik fél integrációk. Használjon teljes nevét, például `cn = Administrator, cn = Users, dc = példa, dc = com`.",
"LDAP_Enable": "Engedélyezze",
"LDAP_Enable_Description": "Kísérlet, hogy kihasználja az LDAP hitelesítés.",
"LDAP_Encryption": "Titkosítás",
@@ -598,12 +653,9 @@
"LDAP_Sync_User_Data_Description": "Tartsa a felhasználói adatok szinkronban szerver login (pl: név, e-mail).",
"LDAP_Sync_User_Data_FieldMap": "Felhasználói adatok Field Térkép",
"LDAP_Sync_User_Data_FieldMap_Description": "Állítsd be, hogyan felhasználói fiók területeken (például e-mail) lakott egy rekordot LDAP (egyszer találtak). Példaként `{\" cn \":\" name \",\" mail \":\" email \"}` fog választani egy személy olvasható név a cn attribútumot, és az e-mail a mail attribútumot. Elérhető mezők közé `name` és` email`.",
- "LDAP_Sync_Users": "Szinkronizálás felhasználók",
"LDAP_Test_Connection": "kapcsolat tesztelése",
"LDAP_Unique_Identifier_Field": "Egyedi azonosító mező",
"LDAP_Unique_Identifier_Field_Description": "Mely területen fogják használni, hogy összekapcsolja a LDAP felhasználó és a felhasználói Rocket.Chat. Közölhetitek több értéket vesszővel elválasztva meg kell kérni az érték LDAP rekordot. Az alapértelmezett érték a `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Használja Egyéni Domain Search",
- "LDAP_Use_Custom_Domain_Search_Description": "Írja meg saját szűrő keresni a felhasználókat az LDAP kiszolgálón.",
"LDAP_Username_Field": "felhasználónév mező",
"LDAP_Username_Field_Description": "Mely területen kerül felhasználásra * felhasználónév * az új felhasználók számára. Hagyja üresen használni a felhasználónevét tájékoztatni bejelentkezési oldalon. Használhatja sablon címkéket is, mint a `#{givenName}.#{sn}`. Az alapértelmezett érték `sAMAccountName`.",
"Leave_Group_Warning": "Biztos benne, hogy szeretné elhagyni a csoportot \" %s\"?",
@@ -653,7 +705,7 @@
"Manager_added": "A menedzser hozzátette",
"Manager_removed": "menedzser eltávolított",
"Managing_assets": "vagyongazdálkodás",
- "Managing_integrations": "kezelése integrációk",
+ "Managing_integrations": "Integrációk kezelése",
"Mark_as_read": "Jelöld olvasottként",
"Markdown_Headers": "árleszállítás fejlécek",
"Markdown_SupportSchemesForLink": "Árleszállítás támogatási rendszereket link",
@@ -744,7 +796,7 @@
"No_results_found": "Nincs találat",
"No_starred_messages": "Nincsenek csillagozott üzenetek",
"No_user_with_username_%s_was_found": "Nincs felhasználó felhasználónév: \" %s\" találtak!",
- "Node_version": "node változat",
+ "Node_version": "Node verzió",
"Not_authorized": "nem engedélyezett",
"Not_Available": "Nem elérhető",
"Not_found_or_not_allowed": "Nem található vagy Nem engedett",
@@ -774,15 +826,15 @@
"Opened": "Nyitott",
"optional": "választható",
"Order": "Rendelés",
- "OS_Arch": "OS Arch",
- "OS_Cpus": "Operációs rendszer CPU Count",
- "OS_Freemem": "OS Free Memory",
- "OS_Loadavg": "OS Load Average",
- "OS_Platform": "OS Platform",
- "OS_Release": "OS Release",
- "OS_Totalmem": "OS Összes memória",
- "OS_Type": "OS Type",
- "OS_Uptime": "OS üzemidő",
+ "OS_Arch": "Operációs rendszer architektúra",
+ "OS_Cpus": "Operációs rendszer CPU",
+ "OS_Freemem": "Operációs rendszer elérhető memória",
+ "OS_Loadavg": "Operációs rendszer terheltség",
+ "OS_Platform": "Operációs rendszer platform",
+ "OS_Release": "Operációs rendszer kernel",
+ "OS_Totalmem": "Operációs rendszer elérhető memória",
+ "OS_Type": "Operációs rendszer típusa",
+ "OS_Uptime": "Operációs rendszer indítása óta eltelt idő",
"others": "mások",
"OTR": "OTR",
"OTR_is_only_available_when_both_users_are_online": "OTR csak ha mindkét online",
@@ -901,8 +953,8 @@
"Room_unarchived": "szoba archivált",
"Room_uploaded_file_list": "fájlok",
"Room_uploaded_file_list_empty": "Nincs fájl is elérhető.",
- "Rooms": "szobák",
- "Running_Instances": "példányainak futtatása",
+ "Rooms": "Szobák",
+ "Running_Instances": "Futó példányok",
"S_new_messages_since_s": " %s új üzenet óta %s",
"SAML": "SAML",
"SAML_Custom_Cert": "Egyedi tanúsítvány",
@@ -1013,7 +1065,7 @@
"Stats_Total_Users": "felhasználók",
"Stop_Recording": "Felvétel leállítása",
"strike": "sztrájk",
- "Subject": "Tantárgy",
+ "Subject": "Tárgy",
"Submit": "Elküldés",
"Success": "Siker",
"Success_message": "A siker üzenet",
@@ -1039,23 +1091,23 @@
"The_user_wont_be_able_to_type_in_s": "A felhasználó nem lesz képes, hogy írja be a %s",
"Theme": "Téma",
"theme-color-content-background-color": "Tartalom háttérszíne",
+ "theme-color-custom-scrollbar-color": "Egyedi Scrollbar Color",
+ "theme-color-info-font-color": "Info Betűszín",
+ "theme-color-link-font-color": "Link Betűszín",
"theme-color-primary-background-color": "Elsődleges háttérszíne",
"theme-color-primary-font-color": "Elsődleges Betűszín",
"theme-color-secondary-background-color": "Másodlagos háttérszíne",
"theme-color-secondary-font-color": "Másodlagos Betűszín",
- "theme-color-tertiary-background-color": "Harmadlagos háttérszíne",
- "theme-color-tertiary-font-color": "Harmadlagos Betűszín",
- "theme-color-link-font-color": "Link Betűszín",
- "theme-color-info-font-color": "Info Betűszín",
- "theme-color-custom-scrollbar-color": "Egyedi Scrollbar Color",
"theme-color-status-away": "Idegenben állapot Szín",
"theme-color-status-busy": "Foglalt állapot Szín",
"theme-color-status-offline": "Offline állapot Szín",
"theme-color-status-online": "Online állapot Szín",
+ "theme-color-tertiary-background-color": "Harmadlagos háttérszíne",
+ "theme-color-tertiary-font-color": "Harmadlagos Betűszín",
"theme-color-unread-notification-color": "Olvasatlan értesítés Color",
"theme-custom-css": "egyéni CSS",
"There_are_no_agents_added_to_this_department_yet": "Nincsenek ügynökök hozzá ezen az osztályon még.",
- "There_are_no_integrations": "Nincsenek integrációk",
+ "There_are_no_integrations": "Nincs használatban lévő integráció",
"There_are_no_users_in_this_role": "Nincsenek felhasználók ebben a szerepben.",
"This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Ez az e-mail már felhasználták, és még nem igazolták. Kérjük, változtassa meg a jelszavát.",
"This_is_a_desktop_notification": "Ez egy asztali értesítés",
@@ -1093,7 +1145,7 @@
"Unstar_Message": "csillag eltávolítása",
"Upload_file_question": "Fájl feltöltés?",
"Uploading_file": "Fájl feltöltése ...",
- "Uptime": "üzemidő",
+ "Uptime": "Indítás óta eltelt idő",
"URL": "URL",
"Use_account_preference": "Használja számla preferencia",
"Use_Emojis": "Felhasználási hangulatjelek",
@@ -1149,7 +1201,7 @@
"Username_is_not_in_this_room": "A felhasználó `# %s` nem ebben a szobában.",
"Username_title": "Felhasználónév regisztrálása",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ akar kezdeni OTR. Szeretné, hogy elfogadja?",
- "Users": "felhasználók",
+ "Users": "Felhasználók",
"Users_in_role": "Felhasználók szerepe",
"UTF8_Names_Slugify": "UTF8 nevek Slugify",
"UTF8_Names_Validation": "UTF8 nevek Validation",
@@ -1222,4 +1274,4 @@
"Your_mail_was_sent_to_s": "A mail-ben küldött %s",
"Your_password_is_wrong": "A jelszó rossz!",
"Your_push_was_sent_to_s_devices": "Push küldték %s eszközök"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/id.i18n.json b/packages/rocketchat-i18n/i18n/id.i18n.json
index c41f59d8ca824..e3dd41f3af252 100644
--- a/packages/rocketchat-i18n/i18n/id.i18n.json
+++ b/packages/rocketchat-i18n/i18n/id.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Memungkinkan Profil Pengguna Ganti",
"Accounts_AvatarResize": "Ubah Ukuran Avatar",
"Accounts_AvatarSize": "Ukuran Avatar",
- "Accounts_AvatarStorePath": "Lokasi Penyimpanan Avatar",
- "Accounts_AvatarStoreType": "Tipe Penyimpanan Avatar",
"Accounts_BlockedDomainsList": "Daftar Domain diblokir",
"Accounts_BlockedDomainsList_Description": "Dipisahkan dengan koma daftar domain diblokir",
"Accounts_BlockedUsernameList": "Diblokir Daftar Nama",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "Verifikasi Email",
"Accounts_EmailVerification_Description": "Pastikan Anda memiliki pengaturan SMTP yang benar untuk menggunakan fitur ini",
"Accounts_Enrollment_Email": "Email Pendaftaran ",
- "Accounts_Enrollment_Email_Default": " Selamat Datang di [Nama situs] Pergi ke [Site_URL] dan mencoba yang terbaik open source solusi chatting yang tersedia saat ini!
",
+ "Accounts_Enrollment_Email_Default": " Selamat Datang di [Nama situs] Pergi ke [Site_URL] dan mencoba yang terbaik open source solusi chatting yang tersedia saat ini!
",
"Accounts_Enrollment_Email_Description": "Anda dapat menggunakan placeholder berikut: [Nama], [fname], [lname] untuk nama pengguna penuh, nama depan atau nama belakang, masing-masing. [email] untuk email pengguna. [Site_Name] dan [Site_URL] untuk Nama Aplikasi dan URL masing-masing. ",
"Accounts_Enrollment_Email_Subject_Default": "Selamat Datang [Site_Name]",
"Accounts_Iframe_api_method": "Metode Api",
@@ -83,8 +81,8 @@
"Accounts_OAuth_Twitter_callback_url": "URL Twitter Callback",
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
- "Accounts_OAuth_Wordpress": "Wordpress Login",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress Callback",
+ "Accounts_OAuth_Wordpress": "WordPress Login",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress Callback",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Password reset",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "Publik",
"Accounts_RegistrationForm_Secret_URL": "URL rahasia",
"Accounts_RegistrationForm_SecretURL": "Formulir Pendaftaran Rahasia URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Anda harus memberikan string acak yang akan ditambahkan ke URL pendaftaran Anda. Contoh: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Anda harus memberikan string acak yang akan ditambahkan ke URL pendaftaran Anda. Contoh: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Membutuhkan Nama Untuk Pendaftaran",
"Accounts_ShowFormLogin": "berbasis bentuk acara Login",
"Accounts_UseDefaultBlockedDomainsList": "Gunakan Default Diblokir Daftar Domain",
"Accounts_UseDNSDomainCheck": "Gunakan DNS Domain Periksa",
- "Accounts_UserAddedEmail_Default": " Selamat Datang di [Nama situs] Pergi ke [Site_URL] dan mencoba yang terbaik open source solusi chatting yang tersedia saat ini!
Anda dapat login menggunakan email Anda: [email] dan password: [password]. Anda mungkin diminta untuk mengubahnya setelah login pertama Anda.",
+ "Accounts_UserAddedEmail_Default": "
Selamat Datang di [Nama situs] Pergi ke [Site_URL] dan mencoba yang terbaik open source solusi chatting yang tersedia saat ini!
Anda dapat login menggunakan email Anda: [email] dan password: [password]. Anda mungkin diminta untuk mengubahnya setelah login pertama Anda.",
"Accounts_UserAddedEmail_Description": "Anda dapat menggunakan placeholder berikut:
[Nama], [fname], [lname] untuk nama pengguna penuh, nama depan atau nama belakang, masing-masing. [email] untuk email pengguna. [password] untuk password pengguna. [Site_Name] dan [Site_URL] untuk Nama Aplikasi dan URL masing-masing. ",
"Accounts_UserAddedEmailSubject_Default": "Anda telah ditambahkan ke [Site_Name]",
"Activate": "Aktifkan",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Kebijakan Layanan",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Cari Domain",
- "LDAP_Custom_Domain_Search_Description": "Sepotong JSON yang mengatur mengikat dan koneksi info dan adalah dalam bentuk: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "default Domain",
"LDAP_Description": "LDAP adalah basis data hirarki yang banyak digunakan perusahaan untuk menyediakan fasilitas single sing on untuk berbagi satu kata sandi diantara beberapa situs dan services. Untuk informasi dan contoh konfigurasi lebih lanjut, silahkan berkonsultasi di wiki kami:\nhttps://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "domain Basis",
- "LDAP_Domain_Base_Description": "Nama yang memenuhi syarat Distinguished (DN) dari subtree LDAP Anda ingin mencari pengguna dan kelompok. Anda dapat menambahkan sebanyak yang Anda inginkan; Namun, masing-masing kelompok harus didefinisikan dalam basis domain sama dengan pengguna milik itu. Jika Anda menentukan kelompok pengguna terbatas, hanya pengguna yang termasuk kelompok-kelompok akan di lingkup. Kami menyarankan Anda menentukan tingkat atas pohon direktori LDAP sebagai basis domain Anda dan gunakan filter pencarian untuk mengontrol akses.",
- "LDAP_Domain_Search_Filter": "Domain Cari Filter",
- "LDAP_Domain_Search_Filter_Description": "Jika ditentukan, hanya pengguna yang cocok dengan filter ini akan diizinkan untuk masuk. Jika tidak ada filter yang ditentukan, semua pengguna dalam lingkup dasar domain yang ditentukan akan dapat masuk. Misalnya untuk Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Misalnya untuk OpenLDAP (extensible penelusuran pencocokan) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Cari Obyek Kategori",
- "LDAP_Domain_Search_Object_Category_Description": "The * objectCategory * yang mengidentifikasi pengguna Anda. Biarkan kosong untuk * OpenLDAP *. Misalnya `person`, dll",
- "LDAP_Domain_Search_Object_Class": "Domain Cari Obyek Kelas",
- "LDAP_Domain_Search_Object_Class_Description": "The * objectclass * yang mengidentifikasi pengguna Anda. Misalnya `organizationalPerson`,` user`, `inetOrgPerson`, dll",
- "LDAP_Domain_Search_Password": "Domain Cari Kata",
- "LDAP_Domain_Search_Password_Description": "Password untuk pengguna pencarian domain.",
- "LDAP_Domain_Search_User": "Domain Cari Pengguna",
- "LDAP_Domain_Search_User_Description": "LDAP pengguna yang melakukan pencarian pengguna untuk otentikasi pengguna lain ketika mereka masuk. Ini biasanya account layanan dibuat khusus untuk integrasi pihak ketiga. Gunakan nama yang memenuhi syarat, seperti `cn = Administrator, cn = Users, dc = Contoh, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Cari ID Pengguna",
- "LDAP_Domain_Search_User_ID_Description": "Atribut LDAP yang mengidentifikasi pengguna LDAP yang mencoba otentikasi. Bidang ini harus `sAMAccountName` untuk instalasi yang paling Active Directory, tapi mungkin` uid` untuk solusi LDAP lain, seperti OpenLDAP. Anda dapat menggunakan `mail` untuk mengidentifikasi pengguna melalui email atau atribut apa pun yang Anda inginkan. Anda dapat menggunakan beberapa nilai dipisahkan dengan koma untuk memungkinkan pengguna untuk login menggunakan beberapa pengenal seperti username atau email.",
+ "LDAP_BaseDN_Description": "Nama yang memenuhi syarat Distinguished (DN) dari subtree LDAP Anda ingin mencari pengguna dan kelompok. Anda dapat menambahkan sebanyak yang Anda inginkan; Namun, masing-masing kelompok harus didefinisikan dalam basis domain sama dengan pengguna milik itu. Jika Anda menentukan kelompok pengguna terbatas, hanya pengguna yang termasuk kelompok-kelompok akan di lingkup. Kami menyarankan Anda menentukan tingkat atas pohon direktori LDAP sebagai basis domain Anda dan gunakan filter pencarian untuk mengontrol akses.",
+ "LDAP_User_Search_Field_Description": "Atribut LDAP yang mengidentifikasi pengguna LDAP yang mencoba otentikasi. Bidang ini harus `sAMAccountName` untuk instalasi yang paling Active Directory, tapi mungkin` uid` untuk solusi LDAP lain, seperti OpenLDAP. Anda dapat menggunakan `mail` untuk mengidentifikasi pengguna melalui email atau atribut apa pun yang Anda inginkan. Anda dapat menggunakan beberapa nilai dipisahkan dengan koma untuk memungkinkan pengguna untuk login menggunakan beberapa pengenal seperti username atau email.",
+ "LDAP_User_Search_Filter_Description": "Jika ditentukan, hanya pengguna yang cocok dengan filter ini akan diizinkan untuk masuk. Jika tidak ada filter yang ditentukan, semua pengguna dalam lingkup dasar domain yang ditentukan akan dapat masuk. Misalnya untuk Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Misalnya untuk OpenLDAP (extensible penelusuran pencocokan) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "LDAP pengguna yang melakukan pencarian pengguna untuk otentikasi pengguna lain ketika mereka masuk. Ini biasanya account layanan dibuat khusus untuk integrasi pihak ketiga. Gunakan nama yang memenuhi syarat, seperti `cn = Administrator, cn = Users, dc = Contoh, dc = com`.",
"LDAP_Enable": "Hidupkan",
"LDAP_Enable_Description": "Mencoba untuk memanfaatkan LDAP sebagai otentikasi.",
"LDAP_Encryption": "enkripsi",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Menjaga data pengguna tetap tersinkronasi dengan server saat login(seperti: nama, email).",
"LDAP_Sync_User_Data_FieldMap": "Peta Kolom Data User",
"LDAP_Sync_User_Data_FieldMap_Description": "Mengkonfigurasi bagaimana kolom akun pengguna(seperti email) yang akan diisi dari record dalam LDAP(sekali ditemukan). Sebagai contoh, `{\"cn\":\"name\", \"mail\":\"email\"}` akan memilih nama yang dapat dibaca oleh manusia dari atribut cn, dan email mereka dari atribut mail. Kolom yang tersedia meliputi `name`, and `email`.",
- "LDAP_Sync_Users": "Pengguna sinkronisasi",
"LDAP_Test_Connection": "Tes koneksi",
"LDAP_Unique_Identifier_Field": "Unique Identifier Bidang",
"LDAP_Unique_Identifier_Field_Description": "bidang yang akan digunakan untuk menghubungkan pengguna LDAP dan pengguna Rocket.Chat. Anda dapat menginformasikan beberapa nilai dipisahkan dengan koma untuk mencoba untuk mendapatkan nilai dari catatan LDAP. Nilai default adalah `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Gunakan Pencarian Domain",
- "LDAP_Use_Custom_Domain_Search_Description": "Menulis filter Anda sendiri untuk mencari pengguna di server LDAP.",
"LDAP_Username_Field": "nama pengguna Lapangan",
"LDAP_Username_Field_Description": "bidang yang akan digunakan sebagai * nama * bagi pengguna baru. Biarkan kosong untuk menggunakan nama pengguna informasi pada halaman login. Anda dapat menggunakan tag template juga, seperti `#{givenName}.#{sn}`. Nilai default adalah `sAMAccountName`.",
"Leave_Group_Warning": "Apakah Anda yakin ingin meninggalkan kelompok \"% s\"?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "Pengguna tidak akan dapat mengetikkan% s",
"Theme": "Tema",
"theme-color-content-background-color": "Konten Warna Background",
+ "theme-color-custom-scrollbar-color": "Kustom Warna Scrollbar",
+ "theme-color-info-font-color": "Info Font Color",
+ "theme-color-link-font-color": "Link Font Color",
"theme-color-primary-background-color": "Primer Warna Background",
"theme-color-primary-font-color": "Primary Color Font",
"theme-color-secondary-background-color": "Sekunder Warna Background",
"theme-color-secondary-font-color": "Sekunder Font Color",
- "theme-color-tertiary-background-color": "Tersier Warna Background",
- "theme-color-tertiary-font-color": "Tersier Font Color",
- "theme-color-link-font-color": "Link Font Color",
- "theme-color-info-font-color": "Info Font Color",
- "theme-color-custom-scrollbar-color": "Kustom Warna Scrollbar",
"theme-color-status-away": "Jauh Warna Status",
"theme-color-status-busy": "Sibuk Warna Status",
"theme-color-status-offline": "Offline Warna Status",
"theme-color-status-online": "Secara online Color Status",
+ "theme-color-tertiary-background-color": "Tersier Warna Background",
+ "theme-color-tertiary-font-color": "Tersier Font Color",
"theme-color-unread-notification-color": "Belum dibaca Pemberitahuan Warna",
"theme-custom-css": "CSS kustom",
"There_are_no_agents_added_to_this_department_yet": "Tidak ada agen ditambahkan ke departemen ini.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "email Anda dikirim ke% s",
"Your_password_is_wrong": "password Anda salah!",
"Your_push_was_sent_to_s_devices": "push dikirim ke% s perangkat"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/it.i18n.json b/packages/rocketchat-i18n/i18n/it.i18n.json
index 9771a6653c974..136325e7451ac 100644
--- a/packages/rocketchat-i18n/i18n/it.i18n.json
+++ b/packages/rocketchat-i18n/i18n/it.i18n.json
@@ -2,129 +2,145 @@
"#channel": "#canale",
"0_Errors_Only": "0 - Solo errori",
"1_Errors_and_Information": "1 - Errori e informazioni",
- "2_Erros_Information_and_Debug": "2 - Errori, informazione e di debug",
+ "2_Erros_Information_and_Debug": "2 - Errori, informazioni e debug",
"403": "Proibito",
"500": "Errore interno del server",
"@username": "@username",
"@username_message": "@username ",
"__username__is_no_longer__role__defined_by__user_by_": "__username__ non è più __role__, da __user_by__",
- "__username__was_set__role__by__user_by_": "__username__ è stato fissato __role__ da __user_by__",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Accetta richieste livechat in arrivo anche se non é c'é nessun operatore online",
- "Accept_with_no_online_agents": "Accetta con nessun agente online",
- "Access_not_authorized": "Accesso autorizzato",
- "Access_Token_URL": "Token di accesso URL",
+ "__username__was_set__role__by__user_by_": "A __username__ è stato assegnato il ruolo di __role__ da __user_by__",
+ "Accept": "Accetta",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Accetta richieste livechat in arrivo anche se non è c'è nessun operatore online",
+ "Accept_with_no_online_agents": "Accetta con nessun operatore online",
+ "Access_not_authorized": "Accesso non autorizzato",
+ "Access_Token_URL": "URL del Token di Accesso",
"Accessing_permissions": "Permessi di Accesso",
"Account_SID": "Account SID",
- "Accounts": "Utenti",
- "Accounts_AllowDeleteOwnAccount": "Consenti agli utenti di eliminare il proprio account",
- "Accounts_AllowedDomainsList": "Lista Domini ammessi",
- "Accounts_AllowedDomainsList_Description": "Elenco separato da virgole per i domini consentiti",
- "Accounts_AllowEmailChange": "Consenti cambio dell'e-mail",
+ "Accounts": "Account",
+ "Accounts_AllowAnonymousRead": "Consenti lettura anonima",
+ "Accounts_AllowAnonymousWrite": "Consenti scrittura anonima",
+ "Accounts_AllowDeleteOwnAccount": "Consenti agli utenti di cancellare il proprio account",
+ "Accounts_AllowedDomainsList": "Elenco domini consentiti",
+ "Accounts_AllowedDomainsList_Description": "Elenco separato da virgole dei domini consentiti",
+ "Accounts_AllowEmailChange": "Consenti cambio dell'email",
"Accounts_AllowPasswordChange": "Consenti cambio password",
- "Accounts_AllowUserAvatarChange": "Consenti cambio avatar",
+ "Accounts_AllowUserAvatarChange": "Consenti cambio Avatar",
"Accounts_AllowUsernameChange": "Consenti cambio nome utente",
"Accounts_AllowUserProfileChange": "Consenti cambio profilo utente",
- "Accounts_AvatarResize": "Ridimensiona Avatar",
- "Accounts_AvatarSize": "Dimensione Avatar",
- "Accounts_AvatarStorePath": "Percorso Avatar",
- "Accounts_AvatarStoreType": "Tipo di archiviazione per gli Avatar",
+ "Accounts_AvatarResize": "Ridimensiona avatar",
+ "Accounts_AvatarSize": "Dimensione avatar",
"Accounts_BlockedDomainsList": "Elenco domini bloccati",
- "Accounts_BlockedDomainsList_Description": "elenco separato da virgole dei domini bloccati",
- "Accounts_BlockedUsernameList": "Lista nomi utente bloccati",
- "Accounts_BlockedUsernameList_Description": "Lista di nomi utente bloccati, separati da virgole (ignora le maiuscole)",
- "Accounts_CustomFields_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono il dizionario delle impostazioni del campo. Esempio:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
- "Accounts_denyUnverifiedEmail": "Blocca email non verificate",
+ "Accounts_BlockedDomainsList_Description": "Elenco separato da virgole dei domini bloccati",
+ "Accounts_BlockedUsernameList": "Elenco nomi utenti bloccati",
+ "Accounts_BlockedUsernameList_Description": "Elenco di nomi utenti bloccati separati da virgole (case-insensitive)",
+ "Accounts_CustomFields_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono un dizionario di impostazioni. Esempio:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Suggerimento predefinito del prefisso del nome utente",
+ "Accounts_denyUnverifiedEmail": "Nega email non verificate",
"Accounts_EmailVerification": "Verifica email",
"Accounts_EmailVerification_Description": "Assicurati di aver impostato SMTP in modo corretto per utilizzare questa funzione",
- "Accounts_Enrollment_Email": "Iscrizione e-mail",
- "Accounts_Enrollment_Email_Default": " Benvenuto a [Site_Name] Vai a [Site_URL] per provare la chat open source migliore disponibile!
",
- "Accounts_Enrollment_Email_Description": "Puoi utilizzare [name], [fname], [lname] per il nome completo dell'utente, nome o cognome, rispettivamente. Utilizzare [email] per la e-mail dell'utente.",
+ "Accounts_Enrollment_Email": "Iscrizione email",
+ "Accounts_Enrollment_Email_Default": "Benvenuto su [Site_Name] Vai su [Site_URL] e prova la miglior chat open source disponibile!
",
+ "Accounts_Enrollment_Email_Description": "Puoi utilizzarei seguenti marcatori: [name], [fname], [lname] rispettivamente per il nome utente completo, nome o cognome. [email] per l'email dell'utente. [Site_Name] e [Site_URL] rispettivamente per il nome dell'applicazione e URL. ",
"Accounts_Enrollment_Email_Subject_Default": "Benvenuti su [Site_Name]",
- "Accounts_Iframe_api_method": "Api Method",
- "Accounts_Iframe_api_url": "Api URL",
+ "Accounts_ForgetUserSessionOnWindowClose": "Dimentica la sessione utente alla chiusura della finestra",
+ "Accounts_Iframe_api_method": "Metodo API",
+ "Accounts_Iframe_api_url": "URL API",
"Accounts_iframe_enabled": "Abilitato",
- "Accounts_iframe_url": "Iframe URL",
- "Accounts_LoginExpiration": "Scadenza per l'Accesso in giorni",
+ "Accounts_iframe_url": "URL dell'Iframe",
+ "Accounts_LoginExpiration": "Giorni per la scadenza d'accesso",
"Accounts_ManuallyApproveNewUsers": "Approva manualmente i nuovi utenti",
- "Accounts_OAuth_Custom_Authorize_Path": "Authorize Path",
+ "Accounts_OAuth_Custom_Authorize_Path": "Percorso di autorizzazione",
"Accounts_OAuth_Custom_Button_Color": "Colore pulsante",
"Accounts_OAuth_Custom_Button_Label_Color": "Colore testo pulsante",
"Accounts_OAuth_Custom_Button_Label_Text": "Testo pulsante",
- "Accounts_OAuth_Custom_Enable": "Attivo",
+ "Accounts_OAuth_Custom_Enable": "Abilita",
"Accounts_OAuth_Custom_id": "Id",
- "Accounts_OAuth_Custom_Identity_Path": "Identity Path",
- "Accounts_OAuth_Custom_Login_Style": "Stile Login",
- "Accounts_OAuth_Custom_Scope": "Scope",
- "Accounts_OAuth_Custom_Secret": "Secret",
- "Accounts_OAuth_Custom_Token_Path": "Token Path",
- "Accounts_OAuth_Custom_Token_Sent_Via": "Token Inviato via",
+ "Accounts_OAuth_Custom_Identity_Path": "Percorso dell'identità",
+ "Accounts_OAuth_Custom_Login_Style": "Stile di accesso",
+ "Accounts_OAuth_Custom_Merge_Users": "Unisci utenti",
+ "Accounts_OAuth_Custom_Scope": "Scopo",
+ "Accounts_OAuth_Custom_Secret": "Chiave segreta",
+ "Accounts_OAuth_Custom_Token_Path": "Percorso del token",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Token inviato tramite",
+ "Accounts_OAuth_Custom_Username_Field": "Campo nome utente",
+ "Accounts_OAuth_Drupal": "Drupal Login abilitato",
+ "Accounts_OAuth_Drupal_callback_url": "URI di re-indirizzamento oAuth2 Drupal ",
+ "Accounts_OAuth_Drupal_id": "ID cliente oAuth2 Drupal",
+ "Accounts_OAuth_Drupal_secret": "Chiave segreta oAuth2 Drupal",
"Accounts_OAuth_Facebook": "Facebook Login",
"Accounts_OAuth_Facebook_callback_url": "URL Callback Facebook",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
- "Accounts_OAuth_Facebook_secret": "Facebook Secret",
- "Accounts_OAuth_Github": "Attiva OAuth ",
+ "Accounts_OAuth_Facebook_secret": "Chiave segreta Facebook",
+ "Accounts_OAuth_Github": "OAuth abilitato",
"Accounts_OAuth_Github_callback_url": "URL Callback Github",
- "Accounts_OAuth_GitHub_Enterprise": "OAuth Abilitato",
+ "Accounts_OAuth_GitHub_Enterprise": "OAuth abilitato",
"Accounts_OAuth_GitHub_Enterprise_callback_url": "URL Callback GitHub Enterprise ",
- "Accounts_OAuth_GitHub_Enterprise_id": "Client Id",
- "Accounts_OAuth_GitHub_Enterprise_secret": "Client Secret",
- "Accounts_OAuth_Github_id": "Client Id",
- "Accounts_OAuth_Github_secret": "Client Secret",
- "Accounts_OAuth_Gitlab": "OAuth Abilitato",
+ "Accounts_OAuth_GitHub_Enterprise_id": "ID cliente",
+ "Accounts_OAuth_GitHub_Enterprise_secret": "Chiave segreta",
+ "Accounts_OAuth_Github_id": "ID cliente",
+ "Accounts_OAuth_Github_secret": "Chiave segreta",
+ "Accounts_OAuth_Gitlab": "OAuth abilitato",
"Accounts_OAuth_Gitlab_callback_url": "URL Callback GitLab",
- "Accounts_OAuth_Gitlab_id": "GitLab Id",
- "Accounts_OAuth_Gitlab_secret": "Client Secret",
+ "Accounts_OAuth_Gitlab_id": "ID GitLab",
+ "Accounts_OAuth_Gitlab_secret": "Chiave segreta",
"Accounts_OAuth_Google": "Google Login",
"Accounts_OAuth_Google_callback_url": "URL Callback Google ",
- "Accounts_OAuth_Google_id": "Google Id",
- "Accounts_OAuth_Google_secret": "Google Secret",
+ "Accounts_OAuth_Google_id": "ID Google",
+ "Accounts_OAuth_Google_secret": "Chiave segreta Google",
"Accounts_OAuth_Linkedin": "LinkedIn Login",
"Accounts_OAuth_Linkedin_callback_url": "URL Callback Linkedin",
- "Accounts_OAuth_Linkedin_id": "LinkedIn Id",
- "Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
+ "Accounts_OAuth_Linkedin_id": "ID LinkedIn",
+ "Accounts_OAuth_Linkedin_secret": "Chiave Segreta LinkedIn",
"Accounts_OAuth_Meteor": "Meteor Login",
"Accounts_OAuth_Meteor_callback_url": "URL Callback Meteor",
- "Accounts_OAuth_Meteor_id": "Meteor Id",
- "Accounts_OAuth_Meteor_secret": "Meteor Secret",
- "Accounts_OAuth_Twitter": "Twitter login",
+ "Accounts_OAuth_Meteor_id": "ID Meteor",
+ "Accounts_OAuth_Meteor_secret": "Chiave segreta Meteor",
+ "Accounts_OAuth_Proxy_host": "Host Proxy",
+ "Accounts_OAuth_Proxy_services": "Servizi Proxy",
+ "Accounts_OAuth_Twitter": "Twitter Login",
"Accounts_OAuth_Twitter_callback_url": "URL Callback Twitter ",
- "Accounts_OAuth_Twitter_id": "Twitter Id",
- "Accounts_OAuth_Twitter_secret": "Twitter Secret",
- "Accounts_OAuth_Wordpress": "Accesso WordPress",
- "Accounts_OAuth_Wordpress_callback_url": "URL Callback Wordpress",
+ "Accounts_OAuth_Twitter_id": "ID Twitter",
+ "Accounts_OAuth_Twitter_secret": "Chiave segreta Twitter",
+ "Accounts_OAuth_Wordpress": "WordPress Login",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress URL Callback",
"Accounts_OAuth_Wordpress_id": "ID WordPress",
- "Accounts_OAuth_Wordpress_secret": "WordPress Secret ",
- "Accounts_PasswordReset": "Reimpostare la password",
+ "Accounts_OAuth_Wordpress_secret": "Chiave segreta WordPress",
+ "Accounts_PasswordReset": "Reimposta password",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Ruoli predefiniti per i Servizi di Autenticazione",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Ruoli predefiniti (separati da virgola) per gli utenti che saranno registrati tramite servizi di autenticazione",
"Accounts_Registration_AuthenticationServices_Enabled": "Registrazione tramite servizi di autenticazione",
- "Accounts_RegistrationForm": "Schermata di registrazione",
+ "Accounts_RegistrationForm": "Modulo di registrazione",
"Accounts_RegistrationForm_Disabled": "Disabilitato",
- "Accounts_RegistrationForm_LinkReplacementText": "Testo Link del Modulo di registrazione",
+ "Accounts_RegistrationForm_LinkReplacementText": "Link di sostituzione al modulo di registrazione",
"Accounts_RegistrationForm_Public": "Pubblico",
- "Accounts_RegistrationForm_Secret_URL": "URL Secret",
- "Accounts_RegistrationForm_SecretURL": "Modulo di registrazione URL segreta",
- "Accounts_RegistrationForm_SecretURL_Description": "È necessario fornire una stringa casuale che verrà aggiunta alla URL di registrazione. Esempio: https://demo.rocket.chat/register/[secret_hash]",
- "Accounts_RequireNameForSignUp": "Richiedi il nome per l'iscrizione",
+ "Accounts_RegistrationForm_Secret_URL": "URL segreto",
+ "Accounts_RegistrationForm_SecretURL": "URL segreto del modulo di registrazione ",
+ "Accounts_RegistrationForm_SecretURL_Description": "È necessario fornire una stringa casuale che verrà aggiunta all'URL di registrazione. Esempio: https://open.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "Richiedi il nome per la registrazione",
"Accounts_RequirePasswordConfirmation": "Richiede conferma della password",
+ "Accounts_SetDefaultAvatar": "Imposta Avatar Predefinito",
+ "Accounts_SetDefaultAvatar_Description": "Prova a determinare l'avatar predefinito basato sull'account OAuth di Gravatar",
"Accounts_ShowFormLogin": "Mostra il modulo d'accesso",
- "Accounts_UseDefaultBlockedDomainsList": "Utilizza la lista dei domini bloccati",
+ "Accounts_UseDefaultBlockedDomainsList": "Utilizza l'elenco dei domini bloccati",
"Accounts_UseDNSDomainCheck": "Utilizza la verifica del dominio DNS",
- "Accounts_UserAddedEmail_Default": " Benvenuto a [Site_Name] Vai a [Site_URL] e prova la chat open source migliore disponibile!
Puoi effettuare il login usando la tua email: [email] e la password: [password]. Ti potrà essere richiesto di cambiarla dopo il primo accesso.
",
- "Accounts_UserAddedEmail_Description": "È possibile utilizzare i seguenti segnaposti: [name], [fname], [lname] per il nome completo dell'utente, nome o cognome, rispettivamente. [email] per l'e-mail dell'utente. [password] per la password dell'utente. [Site_Name] e [Site_URL] per il Nome applicazione e l'URL, rispettivamente. ",
- "Accounts_UserAddedEmailSubject_Default": "Sei stato aggiunto a [Site_Name]",
- "Activate": "Attivare",
+ "Accounts_UserAddedEmail_Default": " Benvenuto a [Site_Name] Vai a [Site_URL] e prova la chat open source migliore disponibile!
Puoi effettuare il login usando la tua email: [email] e la password: [password]. Ti potrà essere richiesto di cambiarla dopo il primo accesso.",
+ "Accounts_UserAddedEmail_Description": "È possibile utilizzare i seguenti marcatori:
[name], [fname], [lname] per il nome completo dell'utente, nome o cognome, rispettivamente. [email] per l'e-mail dell'utente. [password] per la password dell'utente. [Site_Name] e [Site_URL] per il Nome applicazione e l'URL, rispettivamente. ",
+ "Accounts_UserAddedEmailSubject_Default": "Sei stato aggiunto su [Site_Name]",
+ "Activate": "Attiva",
"Activity": "Attività",
"Add": "Aggiungi",
"Add_agent": "Aggiungi operatore",
- "Add_custom_oauth": "Aggiungere OAuth personalizzato",
+ "Add_custom_oauth": "Aggiungi OAuth personalizzato",
+ "Add_Domain": "Aggiungi Dominio",
"Add_manager": "Aggiungi gestore",
"Add_user": "Aggiungi utente",
"Add_User": "Aggiungi utente",
"Add_users": "Aggiungi utenti",
- "Adding_OAuth_Services": "Aggiunta di Servizi OAuh ",
- "Adding_permission": "Aggiungi i permessi",
- "Adding_user": "Aggiunta di utente",
- "Additional_emails": "Altre E-Mail",
- "Additional_Feedback": "Commenti aggiuntivi",
+ "Adding_OAuth_Services": "In fase di aggiunta dei Servizi OAuh ",
+ "Adding_permission": "In fase di aggiunta dei permessi",
+ "Adding_user": "In fase di aggiunta dell'utente",
+ "Additional_emails": "Email aggiuntive",
+ "Additional_Feedback": "Feedback aggiuntivo",
"Administration": "Amministrazione",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Dopo l'autenticazione OAuth2, gli utenti saranno reindirizzati a questo URL",
"Agent": "Operatore",
@@ -138,67 +154,96 @@
"All_channels": "Tutti i canali",
"All_logs": "Tutti i log",
"All_messages": "Tutti i messaggi",
- "Allow_Invalid_SelfSigned_Certs": "Consenti i Certificati SSL Self-Signed",
- "Allow_Invalid_SelfSigned_Certs_Description": "Consenti l'uso di certificati SSL non validi e self-signed per la validazione dei link e anteprime.",
+ "Allow_Invalid_SelfSigned_Certs": "Consenti i certificati SSL auto-firmati",
+ "Allow_Invalid_SelfSigned_Certs_Description": "Consenti l'uso di certificati SSL non validi e auto-firmati per la validazione dei link e le anteprime.",
+ "Allow_switching_departments": "Consenti ai visitatori di cambiare dipartimento",
+ "Always_open_in_new_window": "Apri sempre in una nuova finestra",
"Analytics_features_enabled": "Funzioni abilitate",
"Analytics_features_messages_Description": "Traccia eventi personalizzati relativi alle azioni che un utente fa sui messaggi.",
- "Analytics_features_rooms_Description": "Traccia eventi personalizzati relativi alle azioni su un canale od un canale privato (creazione, abbandono, cancellazione).",
- "Analytics_features_users_Description": "Traccia eventi personalizzati relativi alle azioni relative agli utenti (tempi di reimpostazione della password, il profilo cambiamento dell'immagine, ecc).",
+ "Analytics_features_rooms_Description": "Traccia eventi personalizzati relativi alle azioni su un canale o su un gruppo (creazione, abbandono, cancellazione).",
+ "Analytics_features_users_Description": "Traccia eventi personalizzati relativi alle azioni relative agli utenti (tempi di reimpostazione della password, il cambiamento d'immagine del profilo, ecc).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "ID monitoraggio",
"and": "e",
"And_more": "E altri __length __",
"Animals_and_Nature": "Animali & Natura",
+ "Announcement": "Annuncio",
"API": "API",
+ "API_Allow_Infinite_Count": "Permette di ottenere ogni dato",
+ "API_Allow_Infinite_Count_Description": "Dovrebbe chiamare la API REST per permettere il ritorno di ogni dato da una chiamata?",
"API_Analytics": "Analytics",
- "API_Embed": "Embed",
+ "API_CORS_Origin": "CORS Origin",
+ "API_Default_Count": "Conteggio Predefinito",
+ "API_Default_Count_Description": "Il conteggio predefinito per i risultati della REST API se l'utente non fornisce niente.",
+ "API_Drupal_URL": "URL Server Drupal",
+ "API_Drupal_URL_Description": "Esempio: https://domain.com (escludendo lo slash finale)",
+ "API_Embed": "Incorpora le anteprime dei link",
"API_Embed_Description": "Anteprime link abilitate o meno quando un utente manda un link ad un sito.",
- "API_EmbedDisabledFor": "Disattiva embedding per gli utenti",
- "API_EmbedDisabledFor_Description": "Elenco separato da virgole dei nomi utente",
- "API_EmbedIgnoredHosts": "Host Embed ignorati",
- "API_EmbedIgnoredHosts_Description": "Elenco di host o indirizzi CIDR separati da virgole, ad esempio: localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
+ "API_EmbedCacheExpirationDays": "Giorni per la scadenza della cache degli embed",
+ "API_EmbedDisabledFor": "Disabilita gli incorporamenti (embed) per gli utenti",
+ "API_EmbedDisabledFor_Description": "Elenco separato da virgole dei nomi utenti che hannno le anteprime dei link incorporati (embedded) disabilitati.",
+ "API_EmbedIgnoredHosts": "Host ignorati per gli incorporamenti (embed)",
+ "API_EmbedIgnoredHosts_Description": "Elenco separato da virgole degli host o degli indirizzi CIDR, ad esempio: localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Porte sicure",
- "API_EmbedSafePorts_Description": "elenco delle porte consentite per l'anteprima separate da virgole.",
+ "API_EmbedSafePorts_Description": "Elenco separato da virgole delle porte consentite per l'anteprima.",
+ "API_Enable_CORS": "Abilita CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "Abilita l'endpoint per lo storico dei messaggi diretti",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Questo abilita `/api/v1/im.history.others` che permette di vedere i messaggi diretti inviati dagli altri utenti di cui il chiamante non è parte.",
+ "API_Enable_Shields": "Abilita Shield",
+ "API_Enable_Shields_Description": "Abilita gli shield disponibili a `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "URL del server",
- "API_GitHub_Enterprise_URL_Description": "Esempio: http://domain.com (escluso slash)",
+ "API_GitHub_Enterprise_URL_Description": "Esempio: http://domain.com (escludendo lo slash finale)",
"API_Gitlab_URL": "URL GitLab",
- "API_Token": "API Token",
- "API_User_Limit": "Limite utenti per aggiungerli tutti al canale",
- "API_Wordpress_URL": "WordPress URL",
- "Apiai_Key": "Api.ai Key",
- "Apiai_Language": "Api.ai Lingua",
+ "API_Shield_Types": "Tipi di Shield",
+ "API_Shield_Types_Description": "Tipi di shield da abilitare come elenco separato da virgole, scegli da `online`, `channel` o `*` per tutto\n",
+ "API_Token": "Token API",
+ "API_Upper_Count_Limit": "Numero massimo del registro",
+ "API_Upper_Count_Limit_Description": "Qual è il numero massimo di record della REST API che può ritornare (quando non è illimitata)?",
+ "API_User_Limit": "Limite utente per aggiungere tutti gli utenti al canale",
+ "API_Wordpress_URL": "URL WordPress",
+ "Apiai_Key": "Chiave Api.ai",
+ "Apiai_Language": "Lingua Api.ai",
"Appearance": "Aspetto",
"Application_added": "Applicazione aggiunta",
- "Application_Name": "Nome dell'applicazione",
+ "Application_Name": "Nome applicazione",
"Application_updated": "Applicazione aggiornata",
- "Apply_and_refresh_all_clients": "Applicare e aggiornare tutti i client",
+ "Apply_and_refresh_all_clients": "Applica e aggiorna tutti i clienti",
"Archive": "Archivio",
- "are_also_typing": "sta digitando anche",
- "are_typing": "sta digitando",
+ "are_also_typing": "sta scrivendo anche",
+ "are_typing": "sta scrivendo",
"Are_you_sure": "Sei sicuro?",
- "Are_you_sure_you_want_to_delete_your_account": "Sei sicuro di voler eliminare il tuo account?",
- "Assign_admin": "Assegna Amministratore",
+ "Are_you_sure_you_want_to_delete_your_account": "Sei sicuro di voler cancellare il tuo account?",
+ "Assign_admin": "Assegna amministratore",
"at": "a",
"AtlassianCrowd": "Atlassian Crowd",
- "Attachment_File_Uploaded": "File Caricato",
- "Auth_Token": "Auth Token",
+ "Attachment_File_Uploaded": "File caricato",
+ "Attribute_handling": "Gestione attributi",
+ "Auth_Token": "Token di Autenticazione",
"Author": "Autore",
- "Authorization_URL": "URL Authorization",
+ "Authorization_URL": "URL di autorizzazione",
"Authorize": "Autorizza",
- "Auto_Load_Images": "Autocaricamento immagini",
+ "Auto_Load_Images": "Auto-caricamento immagini",
+ "Auto_Translate": "Auto-traduci",
"AutoLinker_Email": "AutoLinker Email",
"AutoLinker_Phone": "AutoLinker Phone",
- "AutoLinker_Phone_Description": "Linka automaticamente i numeri di telefono. Ad esempio, `(123) 456-7890`",
+ "AutoLinker_Phone_Description": "Trasforma automaticamente i numeri di telefono in collegamenti. Ad esempio, `(123) 456-7890`",
"AutoLinker_StripPrefix": "L'AutoLinker rimuove il prefisso",
"AutoLinker_StripPrefix_Description": "Visualizzazione breve. ad es. https://rocket.chat => rocket.chat",
"AutoLinker_Urls_Scheme": "AutoLinker Schema:// URL",
"AutoLinker_Urls_TLD": "AutoLinker TLD URL ",
"AutoLinker_Urls_www": "AutoLinker 'www' URL ",
- "AutoLinker_UrlsRegExp": "AutoLinker URL Regular Expression",
+ "AutoLinker_UrlsRegExp": "AutoLinker URL Espressione Regolare",
+ "Automatic_Translation": "Traduzione automatica",
+ "AutoTranslate_Change_Language_Description": "Cambiando la lingua della traduzione automatica non traduce i messaggi precedenti.",
+ "AutoTranslate_Enabled": "Abilita traduzione automatica",
+ "AutoTranslate_Enabled_Description": "Abilitando la traduzione automatica consentirà alle persone con il permesso auto-traduci di avere tutti i messaggi automaticamente tradotti nella loro lingua. Potranno essere richieste delle tariffe, leggere la Documentazione di Google ",
+ "AutoTranslate_GoogleAPIKey": "Chiave API Google",
"Available": "Disponibile",
- "Available_agents": "Agenti disponibili",
+ "Available_agents": "Operatori disponibili",
"Avatar": "Avatar",
"Avatar_changed_successfully": "Avatar cambiato con successo",
- "Avatar_URL": "URL Avatar",
- "Avatar_url_invalid_or_error": "L'URL fornito non è valido o non è accessibile. Riprova, ma con un URL diverso.",
+ "Avatar_URL": "URL avatar",
+ "Avatar_url_invalid_or_error": "L'URL fornito non è valido o non è accessibile. Si prega di riprovare, ma con un URL differente.",
"away": "assente",
"Away": "Assente",
"away_female": "assente",
@@ -207,15 +252,20 @@
"Away_male": "Assente",
"Back": "Indietro",
"Back_to_applications": "Torna alle applicazioni",
+ "Back_to_integration_detail": "Torna ai dettagli della integrazione",
"Back_to_integrations": "Torna alle integrazioni",
- "Back_to_login": "Torna al login",
+ "Back_to_login": "Torna all'accesso",
"Back_to_permissions": "Torna ai permessi",
+ "Backup_codes": "Backup codici",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Funzionalità Beta. Dipende se la Video Conferenza è abilitata.",
+ "Block_User": "Blocca Utente",
"Body": "Corpo",
"bold": "grassetto",
- "bot_request": "Richiesta Bot",
- "BotHelpers_userFields": "Campi Utente",
- "BotHelpers_userFields_Description": "File CSV con i campi utente a cui i metodi del bot possono accedere.",
+ "bot_request": "Richiesta bot",
+ "BotHelpers_userFields": "Campi utente",
+ "BotHelpers_userFields_Description": "File CSV con i campi utente a cui il bot può accedere tramite i metodi helper.",
"Branch": "Ramo",
+ "Broadcast_Connected_Instances": "Trasmetti le istanze connesse",
"Bugsnag_api_key": "Bugsnag API Key",
"busy": "occupato",
"Busy": "Occupato",
@@ -224,51 +274,79 @@
"busy_male": "occupato",
"Busy_male": "Occupato",
"by": "di",
- "Cancel": "Cancella",
- "Cancel_message_input": "Cancella",
- "Cannot_invite_users_to_direct_rooms": "Non è possibile invitare gli utenti in canali diretti",
+ "cache_cleared": "Svuota Cache",
+ "Cancel": "Annulla",
+ "Cancel_message_input": "Annulla",
+ "Cannot_invite_users_to_direct_rooms": "Impossibile invitare gli utenti nei canali diretti",
+ "Cannot_open_conversation_with_yourself": "Impossibile aprire una conversazione con se stessi",
+ "CAS_autoclose": "Chiudi automaticamente il popup di login",
+ "CAS_base_url": "SSO Base URL",
+ "CAS_base_url_Description": "La base URL del tuo servizio esterno SSO es: https://sso.example.undef/sso/",
+ "CAS_button_color": "Colore di sfondo del pulsante di login",
+ "CAS_button_label_color": "Colore del testo del pulsante di login",
+ "CAS_button_label_text": "Etichetta del pulsante di login",
+ "CAS_enabled": "Abilitato",
+ "CAS_Login_Layout": "CAS Login Layout",
+ "CAS_login_url": "SSO Login URL",
+ "CAS_login_url_Description": "La URL del login del tuo servizio esterno SSO es: https://sso.example.undef/sso/login",
+ "CAS_popup_height": "Altezza del popup di login",
+ "CAS_popup_width": "Larghezza del popup di login",
+ "CAS_Sync_User_Data_Enabled": "Sincronizza sempre i dati utente",
+ "CAS_Sync_User_Data_Enabled_Description": "Sincronizza sempre i dati utente CAS esterni per degli attributi disponibili dal login. Nota: Gli attributi sono sempre sincronizzati alla creazione dell'account.",
+ "CAS_Sync_User_Data_FieldMap": "Mappa attributi",
+ "CAS_Sync_User_Data_FieldMap_Description": "Usa questo JSON in input per costruire attributi (chiavi) interne da attributi (valori) esterni. Attributi nominativi esterni con '%' saranno interpretato come stringhe di valori. Esempio, `{\"email\":\"%email%\", \"name\":\"%firstname%, %lastname%\"}` La mappa degli attribbuti é sempre interpretata. In case 1.0 solo l'attributo `username` è disponibile. Attributi interni disponibili sono: username, name, email, rooms; rooms é una lista separata di stanze in cui entrare alla creazione utente es: {\"rooms\": \"%team%,%department%\"} permette agli utenti CAS alla creazione di entrare nel loro team canale di dipartimento.",
+ "CAS_version": "Versione CAS",
+ "CAS_version_Description": "Utilizza solo la versione CAS supportata dal tuo servizio CAS SSO.",
"CDN_PREFIX": "Prefisso CDN",
"Certificates_and_Keys": "Certificati e chiavi",
- "Changing_email": "Modifica e-mail",
+ "Change_Room_Type": "Cambia la tipologia di stanza",
+ "Changing_email": "In fase di cambiamento dell'email",
"channel": "canale",
"Channel": "Canale",
- "Channel_already_exist": "Il canale `#%s` esiste già.",
- "Channel_already_Unarchived": "Il canale con nome `#%s` è già in stato Non Archiviato",
+ "Channel_already_exist": "Il canale `#%s` già esiste.",
+ "Channel_already_Unarchived": "Il canale con nome `#%s` è già in stato Disarchiviato",
"Channel_Archived": "Il canale con nome `#%s` è stato archiviato con successo",
+ "Channel_created": "Canale `#%s` creato.",
"Channel_doesnt_exist": "Il canale `# %s` non esiste.",
- "Channel_Unarchived": "Il canale con nome `#%s` è stato estratto dall'archivio con successo",
+ "Channel_to_listen_on": "Canale da seguire su",
+ "Channel_Unarchived": "Il canale con nome `#%s` è stato Disarchiviato con successo",
"Channels": "Canali",
"Channels_list": "Elenco dei canali pubblici",
- "Chat_button": "Pulsante Chat",
+ "Chat_button": "Pulsante chat",
"Chat_closed": "Chat chiusa",
"Chat_closed_successfully": "Chat chiusa con successo",
- "Chat_window": "Finestra di chat",
+ "Chat_window": "Finestra chat",
"Chatops_Enabled": "Abilita Chatops",
"Chatops_Title": "Pannello Chatops",
- "Chatops_Username": "Chatops Nome utente",
+ "Chatops_Username": "Chatops nome utente",
"Choose_a_room": "Scegli un canale",
"Choose_messages": "Scegli i messaggi",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Scegli l'alias che verrà visualizzato prima del nome utente nei messaggi.",
- "Choose_the_username_that_this_integration_will_post_as": "Scegliere il nome utente che verrà usato da integrazione.",
+ "Choose_the_username_that_this_integration_will_post_as": "Scegliere il nome utente che verrà usato per questa integrazione.",
+ "clear": "Pulisci",
"Clear_all_unreads_question": "Marcare come letti tutti i messaggi non letti?",
+ "clear_cache_now": "Svuota la cache ora",
+ "clear_history": "Svuota lo storico",
"Click_here": "Clicca qui",
- "Client_ID": "ID Client",
- "Client_Secret": "Client Secret",
- "Clients_will_refresh_in_a_few_seconds": "I client saranno aggiornati in pochi secondi",
+ "Click_here_for_more_info": "Clicca qui per altre informazioni",
+ "Client_ID": "ID cliente",
+ "Client_Secret": "Chiave segreta",
+ "Clients_will_refresh_in_a_few_seconds": "I clienti saranno aggiornati in pochi secondi",
"close": "chiudi",
"Close": "Chiudi",
"Closed": "Chiuso",
"Closed_by_visitor": "Chiuso dal visitatore",
- "Closing_chat": "Chat chiusa",
- "Collapse_Embedded_Media_By_Default": "Riduci allegato multimediale in modo predefinito",
+ "Closing_chat": "In fase di chiusura della chat",
+ "Collapse_Embedded_Media_By_Default": "Riduci i media incorporati (embedded) di default",
"Color": "Colore",
"Commands": "Comandi",
"Comment_to_leave_on_closing_session": "Commento da lasciare alla chiusura della sessione",
"Compact": "Compatto",
- "Confirm_password": "Conferma la password",
+ "Confirm_password": "Conferma la tua password",
+ "Content": "Contenuto",
"Conversation": "Conversazione",
"Conversation_closed": "Conversazione chiusa: __comment__.",
- "Convert_Ascii_Emojis": "Converti ASCII in Emoji",
+ "Convert_Ascii_Emojis": "Converti gli ASCII in Emoji",
"Copied": "Copiato",
"Copy": "Copia",
"Copy_to_clipboard": "Copia negli appunti",
@@ -279,9 +357,12 @@
"Create_A_New_Channel": "Crea un nuovo canale",
"Create_new": "Crea nuovo",
"Created_at": "Creato a",
- "Created_at_s_by_s": "Creato a %s da %s ",
+ "Created_at_s_by_s": "Creato a %s da %s ",
+ "Created_at_s_by_s_triggered_by_s": "Creato alle %s da %s scatenato da %s ",
+ "CRM_Integration": "Integrazione CRM",
"CROWD_Reject_Unauthorized": "Rifiuta non autorizzati",
"Current_Chats": "Chat attuali",
+ "Current_Status": "Stato attuale",
"Custom": "Personalizzato",
"Custom_Emoji": "Emoji personalizzate",
"Custom_Emoji_Add": "Aggiungi una nuova Emoji",
@@ -293,68 +374,99 @@
"Custom_Emoji_Info": "Informazioni Emoji personalizzata",
"Custom_Emoji_Updated_Successfully": "Emoji personalizzata aggiornata con successo",
"Custom_Fields": "Campi personalizzati",
- "Custom_oauth_helper": "Quando si imposta il provider di OAuth, dovrete impostare un URL Callback. Uso %S .",
- "Custom_oauth_unique_name": "Nome univoco OAuth personalizzato",
- "Custom_Script_Logged_In": "Script personalizzato per gli utenti registrati",
- "Custom_Script_Logged_Out": "Script personalizzato per gli utenti registrati fuori",
+ "Custom_oauth_helper": "Quando si imposta l'OAuth Provider, è necessario impostare un URL Callback. Usa %s .",
+ "Custom_oauth_unique_name": "Nome univoco dell'OAuth personalizzato",
+ "Custom_Script_Logged_In": "Script personalizzato per gli utenti collegati",
+ "Custom_Script_Logged_Out": "Script personalizzato per gli utenti scollegati",
+ "Custom_Scripts": "Script personalizzati",
+ "Custom_Sound_Add": "Aggiungi suono personalizzato",
+ "Custom_Sound_Delete_Warning": "La cancellazione di un suono non può essere annullata.",
+ "Custom_Sound_Error_Invalid_Sound": "Suono non valido",
+ "Custom_Sound_Error_Name_Already_In_Use": "Il nome del suono personalizzato è già in uso.",
+ "Custom_Sound_Has_Been_Deleted": "Il suono personalizzato è stato cancellato.",
+ "Custom_Sound_Info": "Informazioni Suono Personalizzato",
+ "Custom_Sound_Saved_Successfully": "Suono personalizzato salvato con successo",
+ "Custom_Sounds": "Suoni personalizzati",
"Custom_Translations": "Traduzioni personalizzate",
- "Custom_Translations_Description": "Dovrebbe essere un JSON valido dove le chiavi sono i campi che contengono il dizionario delle impostazioni del campo. Esempio:{\n \"en\": {\n \"key\": \"translation\"\n },\n \"pt\": {\n \"key\": \"tradução\"\n }\n} ",
+ "Custom_Translations_Description": "Dovrebbe essere un JSON valido dove le chiavi sono le lingue che contengono un dizionario delle traduzioni. Esempio:{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
+ "CustomSoundsFilesystem": "Filesystem suoni personalizzati",
"Dashboard": "Dashboard",
"Date": "Data",
+ "Date_From": "Da",
+ "Date_to": "A",
"days": "giorni",
- "DB_Migration": "Migrazione Database",
- "DB_Migration_Date": "Ultimo aggiornamento migrazione Database",
+ "DB_Migration": "Migrazione database",
+ "DB_Migration_Date": "Data di migrazione del database",
"Deactivate": "Disattiva",
+ "Decline": "Rifiuta",
"Default": "Predefinito",
"Delete": "Cancella",
- "Delete_message": "Elimina messaggio",
+ "delete-c": "Cancella canali pubblici",
+ "delete-c_description": "Permesso di cancellare canali pubblici",
+ "delete-d": "Cancella messaggi diretti",
+ "delete-d_description": "Permesso di cancellare messaggi diretti",
+ "delete-message": "Cancella messaggio",
+ "delete-message_description": "Permesso di cancellare un messaggio all'interno del canale",
+ "delete-p": "Cancella canali privati",
+ "delete-p_description": "Permesso di cancellare canali privati",
+ "delete-user": "Cancella utente",
+ "delete-user_description": "Permesso di cancellare gli utente",
+ "Delete_message": "Cancella messaggio",
"Delete_my_account": "Cancella il mio account",
- "Delete_Room_Warning": "La cancellazione di una stanza rimuoverà tutti i messaggi inseriti all'interno della stanza. Questa azione non può essere annullata.",
- "Delete_User_Warning": "Eliminando un utente verranno eliminati anche tutti i suoi messaggi. Questa operazione non può essere annullata.",
- "Deleted": "Eliminato!",
+ "Delete_Room_Warning": "Cancellando un canale rimuoverà tutti i messaggi postati all'interno del canale. Questa azione non può essere annullata.",
+ "Delete_User_Warning": "Cancellando un utente verranno eliminati anche tutti i suoi messaggi. Questa operazione non può essere annullata.",
+ "Deleted": "Cancellato!",
"Department": "Dipartimento",
"Department_removed": "Dipartimento rimosso",
"Departments": "Dipartimenti",
"Deployment_ID": "ID Installazione",
"Description": "Descrizione",
"Desktop": "Desktop",
- "Desktop_Notification_Test": "Desktop Test di notifica",
+ "Desktop_Notification_Test": "Esegui test di notifica desktop",
"Desktop_Notifications": "Notifiche desktop",
- "Desktop_Notifications_Disabled": "Le notifiche desktop sono disattivate. Modifica le preferenze del browser se hai bisogno di attivare le notifiche.",
- "Desktop_Notifications_Duration": "Durata notifiche",
- "Desktop_Notifications_Duration_Description": "Durata in secondi della notifica del desktop. Può influenzare il Centro di Notifiche di OS X. Inserisci 0 per utilizzare le impostazioni di default del browser e non influire sul Centro di Notifiche di OS X.",
+ "Desktop_Notifications_Disabled": "Le notifiche desktop sono disattivate. Cambia le preferenze del browser se hai bisogno di attivare le notifiche.",
+ "Desktop_Notifications_Duration": "Durata notifiche desktop",
+ "Desktop_Notifications_Duration_Description": "Durata in secondi della notifica desktop. Può influenzare il Centro di Notifiche di OS X. Inserisci 0 per utilizzare le impostazioni di default del browser e per non influire sul Centro di Notifiche di OS X.",
"Desktop_Notifications_Enabled": "Le notifiche desktop sono abilitate",
"Direct_message_someone": "Invia un messaggio diretto",
- "Direct_Messages": "Messaggi privati",
+ "Direct_Messages": "Messaggi diretti",
+ "Disable_Notifications": "Disabilita notifiche",
+ "Disable_two-factor_authentication": "Disabilita autenticazione a due fattori",
"Display_offline_form": "Mostra il modulo offline",
"Displays_action_text": "Mostra il testo di azione",
- "Do_you_want_to_change_to_s_question": "Vuoi cambiare in %s? ",
+ "Do_you_want_to_change_to_s_question": "Vuoi cambiare in %s ?",
"Domain": "Dominio",
+ "Domain_added": "Dominio aggiunto",
+ "Domain_removed": "Dominio rimosso",
"Domains": "Domini",
+ "Domains_allowed_to_embed_the_livechat_widget": "Lista di domini permessi per l'embed del widget livechat. Lascia vuoto per permettere tutti i domini.",
+ "Download_Snippet": "Scarica",
"Drop_to_upload_file": "Rilascia per caricare il file",
"Dry_run": "Invio di prova",
- "Dry_run_description": "Verrà inviata solo una email, allo stesso indirizzo del Mittente. L'email deve appartenere ad un utente valido.",
- "Duplicate_archived_channel_name": "Un canale archiviato con il nome ' %s' esiste",
- "Duplicate_archived_private_group_name": "Un gruppo privato archiviato con il nome ' %s' esiste",
+ "Dry_run_description": "Verrà inviata solo un'email, allo stesso indirizzo del ,ittente. L'email deve appartenere ad un utente valido.",
+ "Duplicate_archived_channel_name": "Un canale archiviato con il nome ' %s' già esiste",
+ "Duplicate_archived_private_group_name": "Un gruppo privato archiviato con il nome ' %s' già esiste",
"Duplicate_channel_name": "Un canale con il nome '%s' già esiste",
- "Duplicate_private_group_name": "Esiste un gruppo privato con nome ' %s'",
+ "Duplicate_private_group_name": "Un gruppo privato con il nome ' %s' già esiste",
"Duration": "Durata",
"Edit": "Modifica",
+ "edit-other-user-info_description": "Permesso di cambiare gli altri nomi, nomi utente o indirizzi email.",
"Edit_Custom_Field": "Modifica campo personalizzato",
- "Edit_Department": "Modifica Dipartimento",
+ "Edit_Department": "Modifica dipartimento",
+ "Edit_Trigger": "Modifica Trigger",
"edited": "modificato",
- "Editing_room": "Stanza di modifica",
- "Editing_user": "Modifica utente",
- "Email": "E-mail",
- "Email_address_to_send_offline_messages": "Indirizzo e-mail per inviare messaggi non in linea",
+ "Editing_room": "In fase di modifica del canale",
+ "Editing_user": "In fase di modifica dell'utente",
+ "Email": "Email",
+ "Email_address_to_send_offline_messages": "Indirizzo email per inviare messaggi offline",
"Email_already_exists": "Email già esistente",
- "Email_body": "Corpo e-mail",
- "Email_Change_Disabled": "L'amministratore di Rocket.Chat ha disattivato il cambio di e-mail",
- "Email_Footer_Description": "È possibile utilizzare i seguenti segnaposti: [Site_Name] e [Site_URL] rispettivamente per il Nome applicazione e l'URL. ",
- "Email_from": "Da parte di",
- "Email_Header_Description": "È possibile utilizzare i seguenti segnaposti: [Site_Name] e [Site_URL] rispettivamente per il Nome applicazione e l'URL. ",
- "Email_Notification_Mode": "Notifiche email quando disconnesso",
- "Email_Notification_Mode_All": "Ogni Menzione/DM",
+ "Email_body": "Corpo email",
+ "Email_Change_Disabled": "Il tuo amministratore di Rocket.Chat ha disattivato il cambio dell'email",
+ "Email_Footer_Description": "È possibile utilizzare i seguenti marcatori: [Site_Name] e [Site_URL] rispettivamente per il nome dell'applicazione e dell'URL. ",
+ "Email_from": "Mittente",
+ "Email_Header_Description": "È possibile utilizzare i seguenti marcatorii: [Site_Name] e [Site_URL] rispettivamente per il nome dell'applicazione e l'URL. ",
+ "Email_Notification_Mode": "Notifiche email offline",
+ "Email_Notification_Mode_All": "Ogni menzione/DM",
"Email_Notification_Mode_Disabled": "Disabilitato",
"Email_or_username": "Email o nome utente",
"Email_subject": "Oggetto",
@@ -362,63 +474,73 @@
"Emoji": "Emoji",
"EmojiCustomFilesystem": "Filesystem personalizzato per le Emoji",
"Empty_title": "Titolo vuoto",
- "Enable": "Attivo",
- "Enable_Desktop_Notifications": "Attiva notifiche per il desktop",
+ "Enable": "Abilita",
+ "Enable_Desktop_Notifications": "Abilita notifiche desktop",
+ "Enable_Svg_Favicon": "Abilita Favicon SVG",
+ "Enable_two-factor_authentication": "Abilita autenticazione a due fattori",
"Enabled": "Abilitato",
"Encrypted_message": "Messaggio cifrato",
- "End_OTR": "Fine OTR",
+ "End_OTR": "Termina OTR",
"Enter_a_regex": "Inserisci una regex",
- "Enter_a_room_name": "Inserire nome stanza",
+ "Enter_a_room_name": "Inserisci un nome al canale",
"Enter_a_username": "Inserisci un nome utente",
+ "Enter_Alternative": "Modalità alternativa (invio con Invio + Ctrl/Alt/Shift/CMD)",
+ "Enter_authentication_code": "Inserisci codice di autenticazione",
+ "Enter_Behaviour": "Comportamento Pulsante Invio",
+ "Enter_Behaviour_Description": "Questi cambiamenti se il pulsante invio invierà un messaggio o il cursore andrà accapo",
"Enter_name_here": "Inserisci il nome qui",
+ "Enter_Normal": "Modalità normale (inviato con Invio)",
"Enter_to": "Invio per",
"Error": "Errore",
"error-action-not-allowed": "__action__ non è permesso",
"error-application-not-found": "Applicazione non trovata",
"error-archived-duplicate-name": "C'è un canale archiviato con il nome '__room_name__'",
- "error-avatar-invalid-url": "Avatar URL non valida: __url__",
- "error-avatar-url-handling": "Errore durante la manipolazione dell'avatar da un URL (__url__) per __username__",
- "error-cant-invite-for-direct-room": "Non è possibile invitare gli utenti in canali diretti",
- "error-could-not-change-email": "Impossibile cambiare e-mail",
+ "error-avatar-invalid-url": "URL avatar non valido: __url__",
+ "error-avatar-url-handling": "Errore durante la manipolazione dell'impostazione dell'avatar da un URL (__url__) per __username__",
+ "error-cant-invite-for-direct-room": "Impossibile invitare gli utenti in canali diretti",
+ "error-could-not-change-email": "Impossibile cambiare l'email",
"error-could-not-change-name": "Impossibile cambiare il nome",
"error-could-not-change-username": "Impossibile cambiare il nome utente",
- "error-delete-protected-role": "Non è possibile eliminare un ruolo protetto",
- "error-department-not-found": "Sezione non trovata",
- "error-duplicate-channel-name": "Esiste un canale con nome ' %s'",
- "error-email-domain-blacklisted": "Il dominio di posta elettronica è nella lista nera",
+ "error-delete-protected-role": "Impossibile cancellare un ruolo protetto",
+ "error-department-not-found": "Dipartimento non trovato",
+ "error-direct-message-file-upload-not-allowed": "Condivisione dei file non permessa nei messaggi diretti",
+ "error-duplicate-channel-name": "Un canale con il '__channel_name__' già esiste",
+ "error-email-domain-blacklisted": "Il dominio dell'email è nella lista nera",
"error-email-send-failed": "Errore nell'invio della mail: __message__",
"error-field-unavailable": "__field__ è già in uso :(",
"error-file-too-large": "Il file è troppo grande",
- "error-importer-not-defined": "L'importatore non è stato definito in modo corretto, manca la classe di importazione.",
+ "error-importer-not-defined": "L'importatore non è stato definito correttamente, manca la classe di importazione.",
"error-input-is-not-a-valid-field": "__input__ non è una valido __field__",
- "error-invalid-actionlink": "Action link non valido",
+ "error-invalid-actionlink": "Link d'azione non valido",
"error-invalid-arguments": "Argomenti non validi",
"error-invalid-asset": "Risorsa non valida",
"error-invalid-channel": "Canale non valido.",
"error-invalid-channel-start-with-chars": "Canale non valido. Inizia con @ o #",
"error-invalid-custom-field": "Campo personalizzato non valido",
- "error-invalid-custom-field-name": "Nome non valido per il campo personalizzato. Utilizza solo lettere, numeri, trattini e underscore.",
+ "error-invalid-custom-field-name": "Nome non valido per il campo personalizzato. Utilizza solo lettere, numeri, trattini e trattini bassi.",
+ "error-invalid-date": "Dati forniti non validi",
"error-invalid-description": "Descrizione non valida",
"error-invalid-domain": "Dominio non valido",
- "error-invalid-email": "L'email __email__ non é valida",
- "error-invalid-file-height": "Altezza del file non valida",
+ "error-invalid-email": "L'email __email__ non è valida",
+ "error-invalid-email-address": "Indirizzo email non valido",
+ "error-invalid-file-height": "Altezza del file non valido",
"error-invalid-file-type": "Tipo di file non valido",
"error-invalid-file-width": "Larghezza file non valido",
- "error-invalid-from-address": "Hai specificato un indirizzo DA non valido.",
+ "error-invalid-from-address": "Hai specificato un indirizzo mittente non valido.",
"error-invalid-integration": "Integrazione non valida",
"error-invalid-message": "Messaggio non valido",
"error-invalid-method": "Metodo non valido",
"error-invalid-name": "Nome non valido",
"error-invalid-password": "Password non valida",
- "error-invalid-redirectUri": "redirectUri non valido",
+ "error-invalid-redirectUri": "RedirectUri non valido",
"error-invalid-role": "Ruolo non valido",
- "error-invalid-room": "Stanza non valido",
- "error-invalid-room-name": " %s non è un nome valido per una stanza, utilizza solo lettere, numeri, trattini e underscore",
+ "error-invalid-room": "Canale non valido",
+ "error-invalid-room-name": "__room_name__ non è un nome valido per un canale, usa solo lettere, numeri, trattini e trattini bassi",
"error-invalid-room-type": "__type__ non è un tipo di canale valido.",
- "error-invalid-settings": "impostazioni fornite non valide ",
+ "error-invalid-settings": "Impostazioni fornite non valide ",
"error-invalid-subscription": "Sottoscrizione non valida",
"error-invalid-token": "Token non valido",
- "error-invalid-triggerWords": "triggerWords non valide",
+ "error-invalid-triggerWords": "TriggerWords non valide",
"error-invalid-urls": "URL non valide",
"error-invalid-user": "Utente non valido",
"error-invalid-username": "Nome utente non valido",
@@ -428,178 +550,263 @@
"error-message-size-exceeded": "La dimensione del messaggio supera Message_MaxAllowedSize",
"error-missing-unsubscribe-link": "È necessario fornire il link [unsubscribe].",
"error-no-tokens-for-this-user": "Non ci sono token per questo utente",
- "error-not-allowed": "Non autorizzato",
+ "error-not-allowed": "Non permesso",
"error-not-authorized": "Non autorizzato",
- "error-push-disabled": "Push disattivato",
+ "error-push-disabled": "Il push è disattivato",
"error-remove-last-owner": "Questo è l'ultimo proprietario. Imposta un nuovo proprietario prima di rimuoverlo.",
- "error-role-in-use": "Impossibile eliminare il ruolo, perché è in uso",
- "error-role-name-required": "Il nome del ruolo è necessario",
- "error-the-field-is-required": "ll campo __field__ é necessario",
- "error-too-many-requests": "Errore, troppe richieste. Per favore rallenta. Devi aspettare __seconds__ secondi prima di riprovare.",
+ "error-role-in-use": "Impossibile cancellare il ruolo perché è in uso",
+ "error-role-name-required": "Il nome del ruolo è richiesto",
+ "error-the-field-is-required": "ll campo __field__ è richiesto",
+ "error-too-many-requests": "Errore, troppe richieste. Si prega di rallentare. È necessario attendere __seconds__ secondi prima di riprovare.",
"error-user-is-not-activated": "L'utente non è stato attivato",
- "error-user-not-in-room": "L'utente non è in questa stanza",
+ "error-user-limit-exceeded": "Il numero di utenti che stai provando ad invitare a #channel_name eccede il limite impostato dall'amministratore",
+ "error-user-not-in-room": "L'utente non è in questo canale",
"error-user-registration-disabled": "La registrazione utente è disattivata",
- "error-user-registration-secret": "La registrazione Utente è consentita solo tramite URL Segreto",
- "error-you-are-last-owner": "Tu sei l'ultimo proprietario. Imposta il nuovo proprietario prima di lasciare la stanza.",
+ "error-user-registration-secret": "La registrazione utente è consentita solo tramite URL segreto",
+ "error-you-are-last-owner": "Tu sei l'ultimo proprietario. Si prega di impostare il nuovo proprietario prima di lasciare il canale.",
"Error_changing_password": "Errore nel cambio password",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Errore: Rocket.Chat richiede la coda oplog quando in esecuzione su diverse instanze",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Verifica che il tuo MongoDB è in modalità ReplicaSet e la variabile di sistema MONGO_OPLOG_URL è definita correttamente sul server dell'applicativo",
"Esc_to": "Esc per",
+ "Event_Trigger": "Evento scatenante",
+ "Event_Trigger_Description": "Selezione quale tipo di evento verrà scatenato con questa Integrazione WebHook in uscita",
"every_30_minutes": "Una volta ogni 30 minuti",
"every_hour": "Una volta ogni ora",
"every_six_hours": "Una volta ogni 6 ore",
"Example_s": "Esempio: %s",
"Exclude_Botnames": "Escludi bot",
- "Exclude_Botnames_Description": "Non propagare i messaggi dai bot quando il nome é riscontrato dalla espressione regolare qui sopra. Se lasciato vuoto, tutti i messaggi dei bot saranno propagati.",
+ "Exclude_Botnames_Description": "Non propagare i messaggi dai bot quando il nome corrisponde all'espressione regolare qui sopra. Se lasciato vuoto, tutti i messaggi dei bot saranno propagati.",
"False": "Falso",
- "Favorite_Rooms": "Abilita Stanze Preferite",
+ "Favorite_Rooms": "Abilita canali preferiti",
"Favorites": "Preferiti",
- "Features_Enabled": "Funzioni Abilitate",
+ "Features_Enabled": "Funzioni abilitate",
"Field": "Campo",
"Field_removed": "Campo rimosso",
"Field_required": "Campo richiesto",
"File_exceeds_allowed_size_of_bytes": "Il file supera la dimensione consentita di __size__ byte",
+ "File_not_allowed_direct_messages": "Condivisione file non permessa nei messaggi diretti.",
"File_type_is_not_accepted": "Il tipo di file non è accettato.",
+ "File_uploaded": "File caricato",
"FileUpload": "Caricamento file",
+ "FileUpload_Disabled": "Caricamento file non permesso.",
"FileUpload_Enabled": "Caricamento file abilitato",
+ "FileUpload_Enabled_Direct": "Caricamento file abilitato nei messaggi diretti",
"FileUpload_File_Empty": "File vuoto",
"FileUpload_FileSystemPath": "Percorso di sistema",
- "FileUpload_MaxFileSize": "Dimensione massima file (in bytes)",
- "FileUpload_MediaType_NotAccepted": "Tipi di file non accettati",
- "FileUpload_MediaTypeWhiteList": "Tipi di file permessi",
- "FileUpload_MediaTypeWhiteListDescription": "Elenco dei tipi di media separato da virgole. Lasciare vuoto per accettarli tutti.",
- "FileUpload_ProtectFiles": "Proteggere i file caricati",
+ "FileUpload_GoogleStorage_AccessId": "Google Storage Access Id",
+ "FileUpload_GoogleStorage_AccessId_Description": "L'ID di accesso é generalmente in formato email, per esempio: \"example-test@example.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Google Storage Bucket Name",
+ "FileUpload_GoogleStorage_Bucket_Description": "Il nome del bucket dove i file saranno caricati.",
+ "FileUpload_GoogleStorage_Secret": "Google Storage Secret",
+ "FileUpload_GoogleStorage_Secret_Description": "Segui queste istruzioni e incolla qui i risultati.",
+ "FileUpload_MaxFileSize": "Dimensione massima file (in byte)",
+ "FileUpload_MediaType_NotAccepted": "Tipi di media non accettati",
+ "FileUpload_MediaTypeWhiteList": "Tipi di media accettati",
+ "FileUpload_MediaTypeWhiteListDescription": "Elenco separato da virgole dei tipi di media. Lasciare vuoto per accettare tutti i tipi di media.",
+ "FileUpload_ProtectFiles": "Proteggi i file caricati",
"FileUpload_ProtectFilesDescription": "Solo gli utenti autenticati avranno accesso",
- "FileUpload_S3_Acl": "Amazon S3 ACL",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 nome bucket",
- "FileUpload_S3_BucketURL": "Bucket URL",
+ "FileUpload_S3_Acl": "ACL Amazon S3",
+ "FileUpload_S3_AWSAccessKeyId": "AWSAccessKeyId Amazon S3",
+ "FileUpload_S3_AWSSecretAccessKey": "AWSSecretAccessKey Amazon S3",
+ "FileUpload_S3_Bucket": "Bucket Name Amazon S3",
+ "FileUpload_S3_BucketURL": "URL Bucket",
"FileUpload_S3_CDN": "Dominio CDN per i download",
"FileUpload_S3_Region": "Regione",
- "FileUpload_S3_URLExpiryTimeSpan": "Periodo scadenza delle URL",
- "FileUpload_S3_URLExpiryTimeSpan_Description": "Il tempo dopo il quale le URL generate da Amazon S3 non é piú valido (in secondi). Se é impostato in meno di 5 secondi, questo campo sarà ignorato.",
+ "FileUpload_S3_URLExpiryTimeSpan": "Periodo di scadenza degli URL",
+ "FileUpload_S3_URLExpiryTimeSpan_Description": "Il tempo dopo il quale le URL generate da Amazon S3 non sono più valide (in secondi). Se è impostato a meno di 5 secondi, questo campo sarà ignorato.",
"FileUpload_Storage_Type": "Tipo di archiviazione",
"Flags": "Bandiere",
- "Follow_social_profiles": "Segui i nostri profili sociali, fai un fork su github e condividi i tuoi pensieri circa l'app rocket.chat nella nostra bacheca Trello.",
- "Food_and_Drink": "Cibo & Bevanda",
- "Footer": "Footer",
+ "Follow_social_profiles": "Segui i nostri profili sociali, fai un fork su github e condividi i tuoi pensieri su rocket.chat nella nostra bacheca Trello.",
+ "Fonts": "Caratteri",
+ "Food_and_Drink": "Cibo & Bevande",
+ "Footer": "Piè di pagina",
"For_your_security_you_must_enter_your_current_password_to_continue": "Per motivi di sicurezza, è necessario reinserire la password per continuare",
+ "force-delete-message": "Forza la cancellazione del messaggio",
+ "force-delete-message_description": "Permesso di cancellare un messaggio bypassando tutte le restrizioni",
+ "Force_Disable_OpLog_For_Cache": "Forza la disabilitazione di OpLog per la Cache",
+ "Force_Disable_OpLog_For_Cache_Description": "Non usare OpLog per sincronizzare la cache quanto disponibile",
"Force_SSL": "Forza SSL",
- "Force_SSL_Description": "* Attenzione * _Force SSL_ non dovrebbe mai essere usato con reverse proxy. Se si dispone di un reverse proxy, si dovrebbe fare il redirect QUI. Questa opzione esiste per ambienti come Heroku, che non permettono la configurazione per il reindirizzamento al reverse proxy.",
- "Forgot_password": "Ho dimenticato mia password",
- "Forward": "Inoltro",
- "Forward_chat": "Chat di Inoltro",
+ "Force_SSL_Description": "*Attenzione!* _Force SSL_ non dovrebbe mai essere usato con il reverse proxy. Se si dispone di un reverse proxy, si dovrebbe fare il redirect LÌ. Questa opzione esiste per ambienti come Heroku che non consentono la configurazione del re-indirizzamento del reverse proxy.",
+ "Forgot_password": "Password dimenticata",
+ "Forgot_Password_Description": "Puoi usare i seguenti segnaposti: [Forgot_Password_Url] per la URL del recupero password. [name], [fname], [lname] rispettivamente per il nome completo dell'utente, nome or cognome. [email] per la email dell'utente. [Site_Name] e [Site_URL] rispettivamente per il nome della applicazione e la URL. ",
+ "Forgot_Password_Email": "Clicca qui per resettare la tua password.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Recupero Password",
+ "Forgot_password_section": "Password dimenticata",
+ "Forward": "Inoltra",
+ "Forward_chat": "Inoltra Chat",
"Forward_to_department": "Inoltra al dipartimento",
"Forward_to_user": "Inoltra all'utente",
"Frequently_Used": "Usato frequentemente",
"Friday": "Venerdì",
- "From": "Da parte di",
+ "From": "Da",
"From_Email": "Indirizzo mittente",
"From_email_warning": "Attenzione: Il campo Da è soggetto alle impostazioni del server di posta.",
"General": "Generale",
- "github_no_public_email": "Non hai un email publicca sul tuo account GitHub",
- "Give_a_unique_name_for_the_custom_oauth": "Dai un nome univoco per OAuth personalizzato",
+ "github_no_public_email": "Non hai un email publica sul tuo account GitHub",
+ "Give_a_unique_name_for_the_custom_oauth": "Dai un nome univoco per l'OAuth personalizzato",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Dai un nome all'applicazione. Sarà visibile agli utenti.",
"Global": "Globale",
- "GoogleTagManager_id": "Google Tag Manager Id",
+ "GoogleCloudStorage": "Google Cloud Storage",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "File JSON dell'account di servizio. Ulteriori informazioni sono disponibili [qui](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
+ "GoogleTagManager_id": "ID Google Tag Manager",
"Guest_Pool": "Stanza ospiti",
"Hash": "Hash",
- "Header": "Header",
+ "Header": "Testata",
+ "Header_and_Footer": "Testata e Piè di pagina",
+ "Helpers": "Helpers",
+ "Hex_Color_Preview": "Anteprima colore esadecimale",
"Hidden": "Nascosto",
- "Hide_Avatars": "Nascondi gli Avatar",
- "Hide_flextab": "Nascondi la barra di destra con un click",
- "Hide_Group_Warning": "Sicuro di voler nascondere il gruppo \" %s\"?",
- "Hide_Private_Warning": "Sicuro di voler nascondere la discussione con \" %s\"?",
+ "Hide_Avatars": "Nascondi avatar",
+ "Hide_flextab": "Nascondi la barra destra con un click",
+ "Hide_Group_Warning": "Sei sicuro di voler nascondere il gruppo \"%s\"?",
+ "Hide_Private_Warning": "Sei sicuro di voler nascondere la discussione con \"%s\"?",
+ "Hide_roles": "Nascondi ruoli",
"Hide_room": "Nascondi il canale",
- "Hide_Room_Warning": "Sicuro di voler nascondere la stanza \" %s\"?",
+ "Hide_Room_Warning": "Sei sicuro di voler nascondere il canale \"%s\"?",
+ "Hide_Unread_Room_Status": "Nascondi lo stato del canale non letto",
"Hide_usernames": "Nascondi nomi utente",
- "Highlights": "In Evidenza",
- "Highlights_How_To": "Per ricevere una notifica quando qualcuno menziona una parola o frase, inserirla qui. È possibile separare parole o frasi con le virgole. Evidenzia Parole ignora maiuscole o minuscole.",
- "Highlights_List": "Evidenzia le parole",
+ "Highlights": "In evidenza",
+ "Highlights_How_To": "Per essere notificati quando qualcuno menziona una parola o una frase, aggiungilo qua. È possibile separare parole o frasi con le virgole. Le parole evidenziate non sono 'case sensitive'.",
+ "Highlights_List": "Evidenzia parole",
"History": "Storico",
- "Host": "Server",
+ "Host": "Host",
"hours": "ore",
"Hours": "Ore",
- "How_friendly_was_the_chat_agent": "Quanto é stato intuitivo l'operatore chat?",
- "How_knowledgeable_was_the_chat_agent": "Quanto é stato semplice l'operatore chat?",
- "How_long_to_wait_after_agent_goes_offline": "Quanto attendere dopo che l'agente di è disconnesso",
- "How_responsive_was_the_chat_agent": "Quanto é reattivo l'operatore chat?",
+ "How_friendly_was_the_chat_agent": "Quanto è stato intuitivo l'operatore chat?",
+ "How_knowledgeable_was_the_chat_agent": "Quanto è stato semplice l'operatore chat?",
+ "How_long_to_wait_after_agent_goes_offline": "Tempo di attesa dopo che l'operatore si è disconnesso",
+ "How_responsive_was_the_chat_agent": "Quanto è reattivo l'operatore chat?",
"How_satisfied_were_you_with_this_chat": "Quanto sei soddisfatto di questa chat?",
- "How_to_handle_open_sessions_when_agent_goes_offline": "Come gestire le sessioni attive quando l'agente si disconnette",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "Come gestire le sessioni attive quando l'opreatore si disconnette",
+ "If_this_email_is_registered": "Se questa email è registrata, invieremo istruzioni su come reimpostare la propria password. Se non la ricevi in breve tempo, si prega di ritornare e riprovare.",
"If_you_are_sure_type_in_your_password": "Se sei sicuro inserisci la password:",
"If_you_are_sure_type_in_your_username": "Se sei sicuro inserisci il tuo nome utente:",
- "Iframe_Integration_receive_enable": "Abilita Ricezione",
- "Iframe_Integration_receive_enable_Description": "Permetti alla finestra genitore di inviare comandi a Rocket.Chat.",
- "Iframe_Integration_receive_origin": "Ricevi le origini",
- "Iframe_Integration_receive_origin_Description": "Solo pagine con una origine certa potranno inviare comandi o '*' per tutte le origini. Puoi usare valori multipli separati da ','. Esempio `http://localhost,https://localhost`",
- "Iframe_Integration_send_enable": "Abilita Invio",
- "Iframe_Integration_send_enable_Description": "Invia eventi alla finestra genitore",
- "Iframe_Integration_send_target_origin": "Invia il target delle origini",
- "Iframe_Integration_send_target_origin_Description": "Solo pagine con una origine certa potranno ascoltare gli eventi o '*' per tutte le origini. Example `http://localhost`",
+ "Iframe_Integration": "Integrazione Iframe",
+ "Iframe_Integration_receive_enable": "Abilita ricezione",
+ "Iframe_Integration_receive_enable_Description": "Consenti alla finestra padre di inviare comandi a Rocket.Chat.",
+ "Iframe_Integration_receive_origin": "Ricevi origini",
+ "Iframe_Integration_receive_origin_Description": "Solo pagine con un'origine potranno ricevere comandi. Puoi usare valori multipli separati da virgole, esempio 'https://localhost, http://localhost', o * per consentire la ricezione da qualsiasi parte.",
+ "Iframe_Integration_send_enable": "Abilita invio",
+ "Iframe_Integration_send_enable_Description": "Invia eventi alla finestra padre",
+ "Iframe_Integration_send_target_origin": "Invia l'origine del target",
+ "Iframe_Integration_send_target_origin_Description": "Solo pagine con una origine certa potranno ascoltare gli eventi o '*' per tutte le origini. Esempio `http://localhost`",
+ "Impersonate_user": "Impersona utente",
+ "Impersonate_user_description": "Quando abilitato i post integrati come l'utente che ha scatenato l'integrazione",
"Importer_Archived": "Archiviato",
+ "Importer_CSV_Information": "L'importatore CSV richiede un formato specifico, leggi la documentazione per scoprire come organizzare il tuo file zip:",
"Importer_done": "Importazione completata!",
- "Importer_finishing": "Sto finendo l'importazione.",
- "Importer_From_Description": "Importa i dati da __from __ 's in Rocket.Chat.",
+ "Importer_finishing": "In fase di terminazione dell'importazione.",
+ "Importer_From_Description": "Importa i dati da __from __ in Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Nota che questa importazione è in sviluppo, riporta ogni errori che può avvenire su GitHub:",
+ "Importer_HipChatEnterprise_Information": "Il file caricato deve essere un file tar.gz decriptato, leggi la documentazione per altre informazioni:",
"Importer_import_cancelled": "Importazione annullata.",
- "Importer_import_failed": "È avvenuto un errore durante l'esecuzione dell'importazione.",
- "Importer_importing_channels": "Importa i canali.",
- "Importer_importing_messages": "Importazione dei messaggi.",
- "Importer_importing_started": "Avvio importazione.",
- "Importer_importing_users": "Importazione degli utenti.",
- "Importer_not_in_progress": "L'importatore non è in esecuzione.",
- "Importer_Prepare_Restart_Import": "Ravvia Importazione",
- "Importer_Prepare_Start_Import": "Avviare l'importazione",
- "Importer_Prepare_Uncheck_Archived_Channels": "Deseleziona i Canali Archiviati",
- "Importer_Prepare_Uncheck_Deleted_Users": "Deseleziona utenti eliminati",
+ "Importer_import_failed": "Si è verificato un errore durante l'esecuzione dell'importazione.",
+ "Importer_importing_channels": "In fase d'importazione dei canali.",
+ "Importer_importing_messages": "In fase d'importazione dei messaggi.",
+ "Importer_importing_started": "In fase d'avvio dell'importazione.",
+ "Importer_importing_users": "In fase d'importazione degli utenti.",
+ "Importer_not_in_progress": "L'importatore non è al momento in esecuzione.",
+ "Importer_not_setup": "L'importatore non è impostato in modo corretto, non ritorna nessun dato.",
+ "Importer_Prepare_Restart_Import": "Ravvia l'importazione",
+ "Importer_Prepare_Start_Import": "Avvia l'importazione",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Deseleziona i canali archiviati",
+ "Importer_Prepare_Uncheck_Deleted_Users": "Deseleziona utenti cancellati",
"Importer_progress_error": "Impossibile ottenere lo stato di avanzamento per l'importazione.",
- "Importer_setup_error": "È avvenuto un errore durante l'impostazione dell'importatore.",
+ "Importer_setup_error": "Si è verificato un errore durante l'impostazione dell'importatore.",
+ "Importer_Source_File": "Selezione dei file sorgente",
"Incoming_Livechats": "LiveChat in arrivo",
+ "Incoming_WebHook": "WebHook in Entrata",
"inline_code": "inline_code",
"Install_Extension": "Installa estensione",
- "Install_FxOs": "Installare Rocket.Chat sul tuo Firefox",
+ "Install_FxOs": "Installa Rocket.Chat sul tuo Firefox",
"Install_FxOs_done": "Grande! È ora possibile utilizzare Rocket.Chat tramite l'icona sulla tua schermata principale. Buon divertimento con Rocket.Chat!",
- "Install_FxOs_error": "Siamo spiacenti, che non ha funzionato come ti aspettavi! Il seguente errore è avvenuto:",
- "Install_FxOs_follow_instructions": "Conferma l'installazione dell'applicazione sul proprio dispositivo (premere \"Installa\" quando richiesto).",
+ "Install_FxOs_error": "Siamo spiacenti che non ha funzionato come inteso! Si è verificato il seguente errore:",
+ "Install_FxOs_follow_instructions": "Si prega di confermare l'installazione dell'applicazione sul proprio dispositivo (premere \"Installa\" quando richiesto).",
"Installation": "Installazione",
"Installed_at": "Installato il",
+ "Instance_Record": "Record d'istanza",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Istruzioni per il visitatore, compila il modulo per inviare un messaggio",
"Integration_added": "L'integrazione è stata aggiunta",
- "Integration_Incoming_WebHook": "Integrazione WebHook In Arrivo",
+ "Integration_Advanced_Settings": "Impostazioni avanzate",
+ "Integration_History_Cleared": "Integrazione Storico svuotata con successo",
+ "Integration_Incoming_WebHook": "Integrazione WebHook In arrivo",
"Integration_New": "Nuova integrazione",
"Integration_Outgoing_WebHook": "Integrazione WebHook in uscita",
+ "Integration_Outgoing_WebHook_History": "Storico Integrazioni Webhook in uscita",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Dati passati alla integrazione",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Dati passati alla URL",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Stacktrace errore",
+ "Integration_Outgoing_WebHook_History_Http_Response": "Risposta HTTP",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "Risposta errore HTTP",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Messaggi inviato dal punto di preparazione",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Messaggi inviato dal punto di risposta del processo",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Tempo di conclusione o di errore",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Tempo integrazione evento",
+ "Integration_Outgoing_WebHook_History_Trigger_Step": "Ultimo evento",
+ "Integration_Outgoing_WebHook_No_History": "Questa integrazione webhook in uscita non ha ancora nessun elemento.",
+ "Integration_Retry_Count": "Riprova conteggio",
+ "Integration_Retry_Count_Description": "Quante volte l'integrazione dovrebbe provare se la chiamata alla URL fallisce?",
+ "Integration_Retry_Delay": "Riprova ritardo",
+ "Integration_Retry_Delay_Description": "Quale algoritmo di ritardo per i tentativi si deve utilizzare? 10^x or 2^x or x*2",
+ "Integration_Retry_Failed_Url_Calls": "Riprova la chiamata URL fallita",
+ "Integration_Retry_Failed_Url_Calls_Description": "L'integrazione dovrebbe chiedere un tempo ragionale in caso di chiamata URL fallita?",
+ "Integration_Run_When_Message_Is_Edited": "Avvia con modifiche",
+ "Integration_Run_When_Message_Is_Edited_Description": "L'integrazione dovrebbe avviarsi quando il messaggio viene modificato? Impostando questa opzione a false, l'integrazione verrà eseguita solo sui nuovi messaggi.",
"Integration_updated": "L'integrazione è stata aggiornata",
+ "Integration_Word_Trigger_Placement": "Posizione parole ovunque",
+ "Integration_Word_Trigger_Placement_Description": "La parola dovrebbe essere scatenata quando posizionata ovunque nella frase oltre che all'inizio?",
"Integrations": "Integrazioni",
+ "Integrations_for_all_channels": "Inserisci all_public_channels per ascoltare su tutti i canali pubblici, all_private_groups per ascoltare su tutti i gruppi privati e all_direct_messages per ascoltare su tutti i messaggi diretti.",
+ "Integrations_Outgoing_Type_FileUploaded": "File caricato",
+ "Integrations_Outgoing_Type_RoomArchived": "Stanza Archiviata",
+ "Integrations_Outgoing_Type_RoomCreated": "Stanza creata (pubblica e privata)",
+ "Integrations_Outgoing_Type_RoomJoined": "Utente è entrato nella stanza",
+ "Integrations_Outgoing_Type_RoomLeft": "Utente lascia la stanza",
+ "Integrations_Outgoing_Type_SendMessage": "Messaggio inviato",
+ "Integrations_Outgoing_Type_UserCreated": "Utente creato",
"InternalHubot": "Hubot interno",
- "InternalHubot_ScriptsToLoad": "Script per caricare",
- "InternalHubot_ScriptsToLoad_Description": "Inserisci un elenco separato da virgole per gli script da caricare da https://github.com/github/hubot-scripts/tree/master/src/scripts",
- "InternalHubot_Username_Description": "Deve essere un nome utente valido di un bot registrato nel tuo server.",
+ "InternalHubot_PathToLoadCustomScripts": "Cartella per caricare gli script",
+ "InternalHubot_reload": "Ricarica gli script",
+ "InternalHubot_ScriptsToLoad": "Script da caricare",
+ "InternalHubot_ScriptsToLoad_Description": "Si prega di inserire un elenco separato da virgole degli gli script da caricare dalla tua cartella personalizzata",
+ "InternalHubot_Username_Description": "Deve essere un nome utente valido di un bot registrato sul tuo server.",
"Invalid_confirm_pass": "La password di conferma non corrisponde con la password",
"Invalid_email": "L'email inserita non è valida",
- "Invalid_Export_File": "Il file caricato non è un %s file di esportazione valido.",
+ "Invalid_Export_File": "Il file caricato non è un file valido d'esportazione di %s.",
"Invalid_Import_File_Type": "Tipo di file non valido per l'importazione.",
"Invalid_name": "Il nome non può essere vuoto",
- "Invalid_notification_setting_s": "impostazione di notifica non valida: %s",
+ "Invalid_notification_setting_s": "Impostazione di notifica non valida: %s",
"Invalid_pass": "La password non deve essere vuota",
- "Invalid_room_name": "%s il nome del canale non è corretto, usa solo lettere, numeri, trattini ed underscores",
- "Invalid_secret_URL_message": "La URL fornito non è valida.",
+ "Invalid_room_name": "%s il nome del canale non è corretto, usa solo lettere, numeri, trattini e underscore",
+ "Invalid_secret_URL_message": "La URL fornita non è valida.",
+ "Invalid_setting_s": "Impostazione non valida: %s",
+ "Invalid_two_factor_code": "Codice a due fattori non valido",
"invisible": "invisibile",
"Invisible": "Invisibile",
- "Invitation_HTML": "invito HTML",
- "Invitation_HTML_Default": " Sei stato invitato a [Site_Name] Vai a [Site_URL] per provare la migliore soluzione di chat open source oggi disponibile!
",
- "Invitation_HTML_Description": "È possibile utilizzare i seguenti segnaposti: [email] per l'e-mail del destinatario. [Site_Name] e [Site_URL] rispettivamente per il Nome applicazione e l'URL. ",
- "Invitation_Subject": "Oggetto invito",
- "Invitation_Subject_Default": "Sei stato invitato a [Site_Name]",
+ "Invitation": "Inviti",
+ "Invitation_HTML": "Invito HTML",
+ "Invitation_HTML_Default": "Sei stato invitato su [Site_Name] Vai su [Site_URL] e prova la miglior chat open source disponibile!
",
+ "Invitation_HTML_Description": "È possibile utilizzare i seguenti marcatori: [email] per l'email del destinatario. [Site_Name] e [Site_URL] rispettivamente per il nome dell'applicazione e l'URL. ",
+ "Invitation_Subject": "Oggetto dell'invito",
+ "Invitation_Subject_Default": "Sei stato invitato su [Site_Name]",
"Invite_user_to_join_channel": "Invita un utente ad entrare in questo canale",
+ "Invite_user_to_join_channel_all_from": "Invita tutti gli utenti da [#channell] per unirsi a questo canale",
+ "Invite_user_to_join_channel_all_to": "Invita tutti gli utenti di questo canale a unirsi [#channel]",
"Invite_Users": "Invita utenti",
- "is_also_typing": "sta digitando anche",
+ "IRC_Channel_Join": "Output del comando JOIN",
+ "IRC_Channel_Leave": "Output del comando PART",
+ "IRC_Description": "Internet Relay Chat (IRC) è uno strumento di comunicazione di gruppo basato su testo. Gli utenti entrano in canali univocamente denominati o in canali per discussioni aperte. IRC inoltre supporta messaggi privati tra utenti individuali e la possibilità di condividere file. Questo pacchetto integra questi livelli di funzionalità con Rocket.Chat.",
+ "IRC_Quit": "Output alla uscita della sessione IRC.",
+ "is_also_typing": "sta anche scrivendo",
"is_also_typing_female": "sta anche scrivendo",
"is_also_typing_male": "sta anche scrivendo",
- "is_typing": "sta digitando",
+ "is_typing": "sta scrivendo",
"is_typing_female": "sta scrivendo",
"is_typing_male": "sta scrivendo",
"It_works": "Funziona",
"italics": "corsivo",
- "Jitsi_Chrome_Extension": "Chrome Extension Id",
- "Jitsi_Enable_Channels": "Attiva nei Canali",
+ "Jitsi_Chrome_Extension": "ID estensione Chrome",
+ "Jitsi_Enable_Channels": "Abilita nei canali",
"join": "Entra",
"Join_audio_call": "Partecipa alla chiamata audio",
"Join_default_channels": "Partecipa ai canali predefiniti",
@@ -614,7 +821,7 @@
"Katex_Dollar_Syntax": "Consenti la Sintassi Dollaro",
"Katex_Dollar_Syntax_Description": "Consenti l'utilizzo di $$katex block$$ e sintassi $inline katex$",
"Katex_Enabled": "Katex Abilitato",
- "Katex_Enabled_Description": "Consenti l'utilizzodi Katex per la matematica nei messaggi",
+ "Katex_Enabled_Description": "Consenti l'utilizzo di Katex per la matematica nei messaggi",
"Katex_Parenthesis_Syntax": "Consenti Sintassi parentesi",
"Katex_Parenthesis_Syntax_Description": "Consenti l'utilizzo di sintassi \\[katex block\\] e \\(inline katex\\)",
"Knowledge_Base": "Knowledge Base",
@@ -629,36 +836,37 @@
"Layout_Home_Title": "Titolo pagina iniziale",
"Layout_Login_Terms": "Condizioni d'accesso",
"Layout_Privacy_Policy": "Privacy Policy",
- "Layout_Sidenav_Footer": "Pié di Pagina Navigazione Laterale",
- "Layout_Sidenav_Footer_description": "La dimensione del piè di pagina è di 260 x 70 px",
+ "Layout_Sidenav_Footer": "Piè di Pagina Navigazione Laterale",
+ "Layout_Sidenav_Footer_description": "La dimensione del piè di pagina è di 260 x 70px",
"Layout_Terms_of_Service": "Termini di servizio",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Ricerca dominio personalizzato",
- "LDAP_Custom_Domain_Search_Description": "Un pezzo di JSON che lega e collega informazioni di questo tipo: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "Timeout Connessione (ms)",
"LDAP_Default_Domain": "Dominio Predefinito",
"LDAP_Description": "LDAP è un database gerarchico che molte aziende utilizzano per fornire single sign on - per la condivisione di una sola password tra più siti e servizi. Per informazioni sulla configurazione avanzata ed esempi, consulta il nostro wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Dominio Base",
- "LDAP_Domain_Base_Description": "Il nome Distinguished Name (DN) di una sottostruttura LDAP in cui vuoi cercare utenti e gruppi. È possibile aggiungere quanti ne vuoi; Tuttavia, ogni gruppo deve essere definito nella stessa base dominio degli utenti che ne fanno parte. Se specifichi gruppi di utenti con restrizioni, solo gli utenti che appartengono a questi gruppi saranno raggiungibili. Si consiglia di specificare il livello superiore nell'albero della directory LDAP come base di dominio e utilizzare il filtro di ricerca per controllare l'accesso.",
- "LDAP_Domain_Search_Filter": "Filtro di ricerca del dominio ",
- "LDAP_Domain_Search_Filter_Description": "Se specificato, solo gli utenti che corrispondono a questo filtro sarà consentito effettuare il login. Se non viene specificato alcun filtro, tutti gli utenti che rientrano nel campo della base di dominio specificato saranno in grado di accedere. Ad esempio, per Active Directory `memberOf = CN = ROCKET_CHAT, ou = Generale Groups`. Ad esempio per OpenLDAP (extensible ricerca match) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Ricerca nel dominio Categoria Oggetto",
- "LDAP_Domain_Search_Object_Category_Description": "I * * objectCategory che identificano gli utenti. Lascia vuoto per * * OpenLDAP. Ad esempio `Person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Ricerca di Object Class nel dominio",
- "LDAP_Domain_Search_Object_Class_Description": "I * * objectclass che identificano gli utenti. Ad esempio `organizationalPerson`,` user`, `inetOrgPerson`, ecc.",
- "LDAP_Domain_Search_Password": "Ricerca password nel dominio ",
- "LDAP_Domain_Search_Password_Description": "La password per l'utente del dominio di ricerca.",
- "LDAP_Domain_Search_User": "Ricerca utente nel dominio",
- "LDAP_Domain_Search_User_Description": "L'utente che esegue ricerche LDAP per l'autenticazione degli utenti quando accedono. Solitamente é un account di servizio creato appositamente per le integrazioni di terze parti. Utilizzare un nome completo, come `cn = Administrator, CN = Users, dc = example, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Ricerca User ID nel dominio",
- "LDAP_Domain_Search_User_ID_Description": "L'attributo LDAP che identifica l'utente LDAP che tenta l'autenticazione. Questo campo deve essere `sAMAccountName` per la maggior parte di installazioni Active Directory, ma può essere `uid` per altre soluzioni LDAP, come OpenLDAP. È possibile utilizzare `mail` per identificare gli utenti via e-mail o tramite attributo. È possibile utilizzare più valori separati da virgola per consentire agli utenti di accedere con più identificatori, come nome utente o e-mail.",
+ "LDAP_BaseDN_Description": "Il nome Distinguished Name (DN) di una sottostruttura LDAP in cui vuoi cercare utenti e gruppi. È possibile aggiungere quanti ne vuoi; Tuttavia, ogni gruppo deve essere definito nella stessa base dominio degli utenti che ne fanno parte. Se specifichi gruppi di utenti con restrizioni, solo gli utenti che appartengono a questi gruppi saranno raggiungibili. Si consiglia di specificare il livello superiore nell'albero della directory LDAP come base di dominio e utilizzare il filtro di ricerca per controllare l'accesso.",
+ "LDAP_User_Search_Field_Description": "L'attributo LDAP che identifica l'utente LDAP che tenta l'autenticazione. Questo campo deve essere `sAMAccountName` per la maggior parte di installazioni Active Directory, ma può essere `uid` per altre soluzioni LDAP, come OpenLDAP. È possibile utilizzare `mail` per identificare gli utenti via e-mail o tramite attributo. È possibile utilizzare più valori separati da virgola per consentire agli utenti di accedere con più identificatori, come nome utente o e-mail.",
+ "LDAP_User_Search_Filter_Description": "Se specificato, solo gli utenti che corrispondono a questo filtro sarà consentito effettuare il login. Se non viene specificato alcun filtro, tutti gli utenti che rientrano nel campo della base di dominio specificato saranno in grado di accedere. Ad esempio, per Active Directory `memberOf = CN = ROCKET_CHAT, ou = Generale Groups`. Ad esempio per OpenLDAP (extensible ricerca match) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "L'utente che esegue ricerche LDAP per l'autenticazione degli utenti quando accedono. Solitamente é un account di servizio creato appositamente per le integrazioni di terze parti. Utilizzare un nome completo, come `cn=Administrator, CN=Users, dc=example, dc=com`.",
"LDAP_Enable": "Attivo",
"LDAP_Enable_Description": "Tenta di utilizzare LDAP per l'autenticazione.",
"LDAP_Encryption": "Crittografia",
"LDAP_Encryption_Description": "Il metodo di cifratura utilizzato per proteggere le comunicazioni con il server LDAP. Gli esempi includono `plain` (senza crittografia),` SSL / LDAPS` (criptato dall'inizio), e `StartTLS` (passaggio ad una comunicazione criptata una volta connesso).",
+ "LDAP_Group_Filter_Enable": "Abilita il controllo del gruppo",
+ "LDAP_Group_Filter_Enable_Description": "Limita l'accesso agli utenti che appartengono ad uno specifico gruppo LDAP Utile per i server OpenLDAP che *non* hanno il filtro *memberOf*",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Nome del campo che identifica i gruppi",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "Ad esempio *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute": "Nome del campo che identifica i membri di un gruppo",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "Ad esempio *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format": "Formato dei membri di un gruppo",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "Ad esempio *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Nome del gruppo",
+ "LDAP_Group_Filter_Group_Name_Description": "Nome del gruppo al quale appartiene l'utente",
+ "LDAP_Group_Filter_ObjectClass": "ObjectClass dei gruppi",
+ "LDAP_Group_Filter_ObjectClass_Description": "*objectclass* che identifica i gruppi LDAP. E.g. OpenLDAP:groupOfUniqueNames",
"LDAP_Host": "Host",
"LDAP_Host_Description": "Host LDAP, ad esempio `ldap.example.com` o` 10.0.0.30`.",
- "LDAP_Import_Users": "Importa utenti LDAP",
+ "LDAP_Idle_Timeout": "Timeout attesa (ms)",
"LDAP_Import_Users_Description": "Il processo true sync importerà tutti gli utenti LDAP *Attenzione!* Specificare il filtro di ricerca per non importare gli utenti in eccesso.",
"LDAP_Login_Fallback": "Login di Fallback",
"LDAP_Login_Fallback_Description": "Se il login su LDAP non ha successo, prova ad effettuarlo sul sistema di account locale. E' utile quando il server LDAP è down per qualche ragione.",
@@ -669,39 +877,25 @@
"LDAP_Reject_Unauthorized": "Rifiuta i non autorizzati",
"LDAP_Sync_User_Avatar": "Sincronizzazione Avatar Utenti",
"LDAP_Sync_User_Data": "Sincronizzazione Dati",
- "LDAP_Sync_User_Data_Description": "Conserva i dati degli utenti in sincro con il server di login (ad esempio: nome, e-mail).",
+ "LDAP_Sync_User_Data_Description": "Conserva i dati degli utenti in sincro con il server di login (ad esempio: nome, email).",
"LDAP_Sync_User_Data_FieldMap": "Campo Utente Dati Mappa",
- "LDAP_Sync_User_Data_FieldMap_Description": "Configura come i campi dell'account utente (come e-mail) sono popolate da un record LDAP (una volta trovato). A titolo di esempio, `{\" cn \":\" nome \",\" mail \":\" e-mail \"}` sceglierà il nome di una persona umana dall'attributo CN, e la loro e-mail dall'attributo di posta elettronica. I campi disponibili includono `name` e `email`.",
- "LDAP_Sync_Users": "Sincronizza utenti",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configura come i campi dell'account utente (come l'email) sono popolate da un record LDAP (una volta trovato). A titolo di esempio, `{\" cn \":\" nome \",\" mail \":\" email \"}` sceglierà il nome di una persona umana dall'attributo cn, e la loro email dall'attributo mail. In aggiunta è possibile usare le variabili, per esempio: { \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` usa una combinazione di nome e cognome dell'utente per il campo `name` di rocket chat. I campi disponibili in Rocket.Chat includono: `name` e `email`.",
"LDAP_Test_Connection": "Connessione di prova",
"LDAP_Unique_Identifier_Field": "Campo Identificativo Univoco",
"LDAP_Unique_Identifier_Field_Description": "Quale campo verrà utilizzato per collegare l'utente LDAP e l'utente Rocket.Chat. È possibile comunicare più valori separati da virgola per cercare di ottenere il valore dal record di LDAP. Il valore predefinito è `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Utilizza la Ricerca del dominio personalizzato",
- "LDAP_Use_Custom_Domain_Search_Description": "Scrive il tuo filtro per cercare gli utenti nel server LDAP.",
"LDAP_Username_Field": "Nome utente campo",
"LDAP_Username_Field_Description": "Quale campo verrà utilizzato come *username* per i nuovi utenti. Lascia vuoto per usare il nome utente informato sulla pagina di login. È possibile utilizzare i tag modello di troppo, come `#{givenName}.#{sn}`. Il valore predefinito è `sAMAccountName`.",
- "LDAP_Group_Filter_Enable": "Abilita il controllo del gruppo",
- "LDAP_Group_Filter_Enable_Description": "Limita l'accesso agli utenti che appartengono ad uno specifico gruppo LDAP Utile per i server OpenLDAP che *non* hanno il filtro *memberOf*",
- "LDAP_Group_Filter_ObjectClass": "ObjectClass dei gruppi",
- "LDAP_Group_Filter_ObjectClass_Description": "*objectclass* che identifica i gruppi LDAP. E.g. OpenLDAP:groupOfUniqueNames",
- "LDAP_Group_Filter_Group_Id_Attribute": "Nome del campo che identifica i gruppi",
- "LDAP_Group_Filter_Group_Id_Attribute_Description": "Ad esempio *OpenLDAP:*cn",
- "LDAP_Group_Filter_Group_Member_Attribute": "Nome del campo che identifica i membri di un gruppo",
- "LDAP_Group_Filter_Group_Member_Attribute_Description": "Ad esempio *OpenLDAP:*uniqueMember",
- "LDAP_Group_Filter_Group_Member_Format": "Formato dei membri di un gruppo",
- "LDAP_Group_Filter_Group_Member_Format_Description": "Ad esempio *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
- "LDAP_Group_Filter_Group_Name": "Nome del gruppo",
- "LDAP_Group_Filter_Group_Name_Description": "Nome del gruppo al quale appartiene l'utente",
"Least_Amount": "Importo Minimo",
"Leave_Group_Warning": "Sei sicuro di voler lasciare il gruppo \"%s\"?",
"Leave_Private_Warning": "Sei sicuro di volere lasciare la discussione con \"%s\"?",
"Leave_room": "Lasciare il canale",
- "Leave_Room_Warning": "Sei sicuro di voler lasciare la stanza \"%s\"?",
+ "Leave_Room_Warning": "Sei sicuro di voler abbandonare il canale \"%s\"?",
"Leave_the_current_channel": "Abbandona il canale corrente",
"line": "linea",
- "List_of_Channels": "Lista di Canali",
+ "List_of_Channels": "Elenco di Canali",
"List_of_Direct_Messages": "Elenco dei messaggi privati",
- "Livechat_agents": "Agenti livechat",
+ "Livechat_agents": "Operatori livechat",
+ "Livechat_AllowedDomainsList": "Domini permessi per Livechat",
"Livechat_Dashboard": "Dashboard livechat",
"Livechat_enabled": "Livechat abilitato",
"Livechat_forward_open_chats": "Inoltra le chat aperte",
@@ -711,8 +905,9 @@
"Livechat_managers": "Manager livechat",
"Livechat_offline": "Livechat disconnessa",
"Livechat_online": "Livechat connessa",
+ "Livechat_open_inquiery_show_connecting": "Mostra i messaggi di connessione invece dell'input quando gli ospiti non sono connessi all'operatore",
"Livechat_Queue": "Coda Livechat",
- "Livechat_room_count": "Conteggio stanza livechat",
+ "Livechat_room_count": "Conteggio canale livechat",
"Livechat_Routing_Method": "Metodo di routing della Livechat",
"Livechat_Take_Confirm": "Vuoi usare questo client?",
"Livechat_title": "Titolo Livechat",
@@ -724,7 +919,7 @@
"Loading_suggestion": "Caricamento opzioni...",
"Localization": "Localizzazione",
"Log_Exceptions_to_Channel": "Riporta le eccezioni sul canale",
- "Log_Exceptions_to_Channel_Description": "Un canale che riceverà tutte le eccezioni rilevate. Lasciare vuoto per ingnorare le eccezioni.",
+ "Log_Exceptions_to_Channel_Description": "Un canale che riceverà tutte le eccezioni rilevate. Lasciare vuoto per ignorare le eccezioni.",
"Log_File": "Mostra File e Linea",
"Log_Level": "Livello di log",
"Log_Package": "Visualizza Pacchetto",
@@ -734,11 +929,11 @@
"Login_with": "Accedi con %s",
"Logout": "Disconnetti",
"Logout_Others": "Disconnetti Da Altre chat",
- "Mail_Message_Invalid_emails": "Hai fornito una o più e-mail non valide: %s",
+ "Mail_Message_Invalid_emails": "Hai fornito una o più email non valide: %s",
"Mail_Message_Missing_to": "Devi selezionare uno o più utenti o fornire uno o più indirizzi email, separati da virgole.",
"Mail_Message_No_messages_selected_select_all": "Non hai selezionato nessun messaggio. Vuoi selezionare tutti i messaggi visibili?",
"Mail_Messages": "Messaggi di posta",
- "Mail_Messages_Instructions": "Scegli quali messaggi vuoi inviare via e-mail cliccandoci",
+ "Mail_Messages_Instructions": "Scegli quali messaggi vuoi inviare via email cliccandoci",
"Mail_Messages_Subject": "Ecco una porzione di %s messaggi",
"Mailer": "Mailer",
"Mailer_body_tags": "È necessario utilizzare il tag [unsubscribe] per il link di cancellazione. È possibile utilizzare [name], [fname], [lname] rispettivamente per il nome completo dell'utente, nome o cognome. È possibile utilizzare [email] per l'indirizzo email dell'utente.",
@@ -757,8 +952,8 @@
"Markdown_Headers": "Intestazioni Markdow ",
"Markdown_SupportSchemesForLink": "Schemi di supporto Markdown per i link",
"Markdown_SupportSchemesForLink_Description": "Elenco separato da virgole per i programmi consentiti",
- "Max_length_is": "Lunghezza massima é %s",
- "Members_List": "Lista dei membri",
+ "Max_length_is": "Lunghezza massima è %s",
+ "Members_List": "Elenco dei membri",
"Mentions": "Menzioni",
"Mentions_default": "Menzioni (default)",
"Message": "Messaggio",
@@ -771,6 +966,7 @@
"Message_AllowEditing_BlockEditInMinutesDescription": "Inserisci 0 per disattivare il blocco.",
"Message_AllowPinning": "Permette di appuntare i messaggi",
"Message_AllowPinning_Description": "Consenti di appuntare i messaggi su qualsiasi canale.",
+ "Message_AllowSnippeting": "Permetti Messaggi Snippet",
"Message_AllowStarring": "Consenti evidenziazione messaggio",
"Message_AllowUnrecognizedSlashCommand": "Permetti comandi Slash non riconosciuti",
"Message_AlwaysSearchRegExp": "Cerca sempre utilizzando le espressioni regolari",
@@ -778,17 +974,22 @@
"Message_AudioRecorderEnabled": "Registrazione Audio Abilitata",
"Message_AudioRecorderEnabledDescription": "Richiede che il tipo 'wav/audio' debba essere fra i tipi accettati nelle impostazioni di 'Caricamento file'.",
"Message_BadWordsFilterList": "Aggiungi parolacce alla lista nera",
- "Message_BadWordsFilterListDescription": "Aggiungi parolacce all'elenco separato da virgole per filtrarle",
+ "Message_BadWordsFilterListDescription": "Aggiungi parolacce da filtrare all'elenco separato da virgole",
"Message_DateFormat": "Formato data",
"Message_DateFormat_Description": "Vedi anche: Moment.js ",
"Message_deleting_blocked": "Questo messaggio non può più essere eliminato",
"Message_editing": "Modifica del messaggio",
- "Message_GroupingPeriod": "Raggruppaperiodo (in secondi)",
+ "Message_GroupingPeriod": "Raggruppa periodo (in secondi)",
"Message_GroupingPeriodDescription": "I messaggi saranno raggruppati con il messaggio precedente, se entrambi sono dallo stesso utente e il tempo trascorso è inferiore del tempo informato in secondi.",
+ "Message_HideType_au": "Nascondi messaggi \"Utente aggiunti\"",
+ "Message_HideType_mute_unmute": "Nascondi messaggi \"Utente muto/non muto\"",
+ "Message_HideType_ru": "Nascondi messaggi \"Utente rimosso\"",
+ "Message_HideType_uj": "Nascondi messaggi \"Utente entrato\"",
+ "Message_HideType_ul": "Nascondi messaggi \"Utente uscito\"",
"Message_KeepHistory": "Mantieni la Cronologia messaggi",
"Message_MaxAll": "La dimensione massima del canale per TUTTI i messaggi",
"Message_MaxAllowedSize": "Dimensione massima del messaggio ammessa",
- "Message_pinning": "Appunta Messaggio",
+ "Message_pinning": "Evidenzia Messaggio",
"Message_removed": "Messaggio rimosso",
"Message_SetNameToAliasEnabled": "Imposta un nome utente come alias nel messaggio",
"Message_SetNameToAliasEnabled_Description": "Solo se non esiste imposta l'alias. L'alias del vecchio messaggio non sarà cambiato se l'utente ha cambiato il nome.",
@@ -796,32 +997,36 @@
"Message_ShowEditedStatus": "Mostra lo stato modificato",
"Message_ShowFormattingTips": "Mostra suggerimenti di formattazione",
"Message_starring": "Segnalibro Messaggio",
+ "Message_TimeAndDateFormat": "Formato data e ora",
+ "Message_TimeAndDateFormat_Description": "Vedi anche: Moment.js ",
"Message_TimeFormat": "Formato orario",
"Message_TimeFormat_Description": "Vedi anche: Moment.js ",
"Message_too_long": "Messaggio troppo lungo",
"Message_VideoRecorderEnabled": "Registrazione Video Abilitata",
- "Message_VideoRecorderEnabledDescription": "Richiede che i file del tipo 'video/webm' siano fra gli accettati nella sezione 'Upload File'.",
+ "Message_VideoRecorderEnabledDescription": "Richiede che i file del tipo 'video/webm' siano fra gli accettati nella sezione 'Caricamento File'.",
"Messages": "Messaggi",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "I messaggi inviati WebHook In Arrivo verranno pubblicati qui.",
"Meta": "Meta",
+ "Meta_custom": "Meta tag personalizzati",
"Meta_fb_app_id": "Facebook App Id",
"Meta_google-site-verification": "Google Site Verification",
"Meta_language": "Lingua",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Robots",
- "Min_length_is": "nghezza minima é %s",
+ "Min_length_is": "La lunghezza minima è %s",
"minutes": "minuti",
+ "Mobile": "Mobile",
"Monday": "Lunedì",
"Monitor_history_for_changes_on": "Osserva lo storico per le modifiche su",
- "More_channels": "Piu canali",
+ "More_channels": "Più canali",
"More_direct_messages": "Altri messaggi diretti",
"More_groups": "Altri canali privati",
- "More_unreads": "Piú non letti",
+ "More_unreads": "Più non letti",
"Msgs": "Msgs",
"multi": "multi",
"Mute_someone_in_room": "Silenzia qualcuno nel canale",
"Mute_user": "Silenzia utente",
- "Muted": "SIlenzioso",
+ "Muted": "Silenzioso",
"My_Account": "Il mio account",
"n_messages": "% messaggi",
"N_new_messages": " %s nuovi messaggi",
@@ -840,6 +1045,8 @@
"New_password": "Nuova password",
"New_role": "Nuovo ruolo",
"New_Room_Notification": "Notifica nuovo canale",
+ "New_Trigger": "Nuovo trigger",
+ "New_videocall_request": "Nuova richiesta video",
"No_available_agents_to_transfer": "Nessun operatore disponibile da trasferire",
"No_channel_with_name_%s_was_found": "Non è stato trovato nessun canale con nome \" %s\" !",
"No_channels_yet": "Non fai ancora parte di nessun canale.",
@@ -847,10 +1054,12 @@
"No_Encryption": "Senza crittografia",
"No_group_with_name_%s_was_found": "Non è stato trovato nessun gruppo privato con nome \" %s\" !",
"No_groups_yet": "Per ora non hai gruppi privati.",
- "No_livechats": "Non hai livechats.",
+ "No_integration_found": "Nessuna integrazione trovata dal provider ID.",
+ "No_livechats": "Non hai livechat.",
"No_mentions_found": "Nessuna menzione trovata",
"No_pinned_messages": "Nessun messaggio in evidenza",
"No_results_found": "Nessun risultato trovato",
+ "No_snippet_messages": "Nessun snippet",
"No_starred_messages": "Nessun messaggio evidenziato",
"No_such_command": "Nessun comando: `/__command__`",
"No_user_with_username_%s_was_found": "Non è stato trovato nessun utente con nome \" %s\" !",
@@ -865,8 +1074,9 @@
"Nothing_found": "Non abbiamo trovato nulla",
"Notification_Duration": "Durata notifica",
"Notifications": "Notifiche",
- "Notify_all_in_this_room": "Notifica tutti in questa stanza",
- "Num_Agents": "# Agenti",
+ "Notify_active_in_this_room": "Notifica utenti attivi in questa stanza",
+ "Notify_all_in_this_room": "Notifica tutti in questo canale",
+ "Num_Agents": "# Operatori",
"Number_of_messages": "Numero di messaggi",
"OAuth_Application": "Applicazione OAuth",
"OAuth_Applications": "Applicazioni OAuth",
@@ -875,11 +1085,11 @@
"Off_the_record_conversation": "Conversazione Off-the-record",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Conversazione Off-the-record non è disponibile per il browser o dispositivo.",
"Office_Hours": "Ore d'ufficio",
- "Office_Hours_Enabled": "Ore d'ufficio attive",
+ "Office_hours_enabled": "Orario ufficio attivo",
"Offline": "Offline",
"Offline_DM_Email": "Hai ricevuto un messaggio diretto da __user__",
"Offline_form": "Modulo offline",
- "Offline_form_unavailable_message": "Messaggio se il modulo di offline non è disponibile",
+ "Offline_form_unavailable_message": "Messaggio non disponibile se il modulo è offline",
"Offline_Link_Message": "VAI AL MESSAGGIO",
"Offline_Mention_Email": "Sei stato citato da __user__ in #__room__",
"Offline_message": "Messaggio offline",
@@ -887,12 +1097,14 @@
"Offline_unavailable": "Offline non disponibile",
"On": "Accendi",
"Online": "Online",
+ "Only_On_Desktop": "Modalità Desktop (invia solo con invio su desktop)",
"Only_you_can_see_this_message": "Solo tu puoi vedere questo messaggio",
"Oops!": "Spiacenti",
"Open": "Aperto",
"Open_days_of_the_week": "Giorni di apertura",
"Open_Livechats": "Apri Livechat",
"Opened": "Ha aperto",
+ "Opened_in_a_new_window": "Apri in una nuova finestra",
"Opens_a_channel_group_or_direct_message": "Apre un canale, canale privato o messaggi diretto",
"optional": "facoltativo",
"or": "o",
@@ -909,7 +1121,9 @@
"others": "altri",
"OTR": "OTR",
"OTR_is_only_available_when_both_users_are_online": "OTR è disponibile solo se entrambi gli utenti sono on-line",
- "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL sostitutiva in cui vengono caricati i file. Questo URL é utilizzato anche per i download a meno che una CDN sia impostata",
+ "Outgoing_WebHook": "WebHook in uscita",
+ "Outgoing_WebHook_Description": "Ottieni i dati da Rocket.Chat in tempo reale.",
+ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "URL sostitutiva in cui vengono caricati i file. Questo URL è utilizzato anche per i download a meno che una CDN sia impostata",
"Page_title": "Titolo pagina",
"Page_URL": "URL pagina",
"Password": "Password",
@@ -925,18 +1139,20 @@
"Pinned_Messages": "Messaggi appuntati",
"PiwikAnalytics_siteId_Description": "Il sito ID da utilizzare per l'identificazione di questo sito. Esempio: 17",
"PiwikAnalytics_url_Description": "L'URL di Piwik, verifica di includere lo slash. Esempio: //piwik.rocket.chat/",
- "Placeholder_for_email_or_username_login_field": "Segnaposto per e-mail o campo nome utente del login",
- "Placeholder_for_password_login_field": "Segnaposto per il campo password login ",
+ "Placeholder_for_email_or_username_login_field": "Marcatore per il campo d'accesso email o nome utente",
+ "Placeholder_for_password_login_field": "Marcatore per il campo d'accesso password",
"Please_add_a_comment": "Aggiungi un commento",
- "Please_add_a_comment_to_close_the_room": "Aggiungi un commento per chiudere la stanza",
+ "Please_add_a_comment_to_close_the_room": "Si prega di aggiungere un commento per chiudere il canale",
"Please_answer_survey": "Prenditi un momento per rispondere a un rapido sondaggio su questa chat",
+ "please_enter_valid_domain": "Inserisci un dominio valido",
"Please_enter_value_for_url": "Inserisci un valore per la URL del tuo avatar.",
- "Please_enter_your_new_password_below": "Digita la nuova password sotto:",
+ "Please_enter_your_new_password_below": "Si prega di inserire la nuova password sotto:",
"Please_enter_your_password": "Reinserisci la password",
"Please_fill_a_label": "Compila una etichetta",
"Please_fill_a_name": "Compila un nome",
"Please_fill_a_username": "Compila un nome utente",
- "Please_fill_name_and_email": "Compila il nome ed e-mail",
+ "Please_fill_name_and_email": "Compila il nome ed email",
+ "Please_select_an_user": "Seleziona un utente",
"Please_select_enabled_yes_or_no": "Seleziona un'opzione per Abilitato",
"Please_wait": "Attendere prego",
"Please_wait_activation": "Attendere prego, questa operazione può richiedere tempo.",
@@ -945,7 +1161,7 @@
"Please_wait_while_your_profile_is_being_saved": "Attendi che il tuo profilo venga salvato ...",
"Port": "Porta",
"Post_as": "Posta come",
- "Post_to_Channel": "Scrivi nel canale",
+ "Post_to_Channel": "Posta nel canale",
"Post_to_s_as_s": "Pubblica %s in %s ",
"Preferences": "Preferenze",
"Preferences_saved": "Preferenze salvate",
@@ -980,72 +1196,92 @@
"quote": "citazione",
"Quote": "Citazione",
"Random": "Casuale",
+ "React_when_read_only": "Permetti reazioni",
+ "React_when_read_only_changed_successfully": "Permetti reazioni quando la modalità sola lettura è cambiata con successo",
"Reacted_with": "Reagito con",
"Reactions": "Reazioni",
"Read_only": "Sola lettura",
"Read_only_changed_successfully": "Sola lettura cambiato con successo",
"Read_only_channel": "Canale in sola lettura",
"Read_only_group": "Gruppo in sola lettura",
- "Record": "Registrazione",
+ "Record": "Record",
"Redirect_URI": "Redirect URI",
"Refresh_keys": "Aggiorna Chiavi",
+ "Refresh_oauth_services": "Ricarica servizi OAuth",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Aggiornare la pagina dopo l'installazione per consentire la condivisione dello schermo",
"Register": "Registra una nuovo account",
+ "Registration": "Registrazione",
"Registration_Succeeded": "Registrazione avvenuta con successo",
+ "Registration_via_Admin": "Registrazione via amministrazione",
+ "Regular_Expressions": "Espressioni regolari",
"Release": "Release",
"Remove": "Rimuovi",
- "Remove_Admin": "Rimuovi Admin",
+ "remove-user": "Rimuovi utente",
+ "remove-user_description": "Permesso di rimuovere un utente dal canale",
+ "Remove_Admin": "Rimuovi Amministratore",
"Remove_as_moderator": "Rimuovi come moderatore",
"Remove_as_owner": "Rimuovi come proprietario",
- "Remove_custom_oauth": "Rimuovere OAuth personalizzato",
+ "Remove_custom_oauth": "Rimuovi OAuth personalizzato",
"Remove_from_room": "Rimuovi dal canale",
"Remove_last_admin": "Rimuovi ultimo amministratore",
- "Remove_someone_from_room": "Rimuovi qualcuno dalla stanza",
+ "Remove_someone_from_room": "Rimuovi qualcuno dal canale",
"Removed": "Rimosso",
"Reply": "Rispondi",
"Report_Abuse": "Segnala un abuso",
"Report_exclamation_mark": "Rapporto!",
"Report_sent": "Rapporto inviato",
"Report_this_message_question_mark": "Segnalare questo messaggio?",
- "Require_password_change": "Richiede la modifica della password",
+ "Reporting": "Resoconti",
+ "Require_password_change": "Richiedi cambio password",
"Resend_verification_email": "Invia nuovamente email di verifica",
- "Reset": "Reset",
- "Reset_password": "Resetta la tua password",
+ "Reset": "Reimposta",
+ "Reset_password": "Reimposta password",
+ "Reset_section_settings": "Resetta le impostazioni della sezione",
"Restart": "Riavvia",
"Restart_the_server": "Riavvia il server",
"Role": "Ruolo",
"Role_Editing": "Ruolo Editing",
"Role_removed": "Ruolo rimosso",
"Room": "Canale",
+ "Room_announcement_changed_successfully": "Annuncio del canale cambiato con successo",
"Room_archivation_state": "Stato",
"Room_archivation_state_false": "Attivo",
"Room_archivation_state_true": "Archiviati",
"Room_archived": "Canale archiviato",
+ "room_changed_announcement": "Annuncio del canale cambiato in: __room_announcement__ da __user_by__ ",
"room_changed_description": "Descrizione del canale cambiata in: __room_description__ da __user_by__ ",
"room_changed_privacy": "Tipo di canale cambiato in: __room_type__ da __user_by__ ",
"room_changed_topic": "Argomento del canale cambiato in: __room_topic__ da __user_by__ ",
"Room_description_changed_successfully": "Descrizione del canale cambiata con successo",
+ "Room_has_been_archived": "La stanza è stata archiviata",
"Room_has_been_deleted": "Il canale è stato eliminato",
+ "Room_has_been_unarchived": "La stanza è stata tolta dall'archivio",
"Room_Info": "Informazioni canale",
+ "room_is_blocked": "La stanza è sbloccata",
"room_is_read_only": "Questo canale è in sola lettura",
"room_name": "nome canale",
- "Room_name_changed": "Il nome della stanza è stato cambiato in: __room_name__ da __user_by__ ",
+ "Room_name_changed": "Il nome del canale è stato cambiato in: __room_name__ da __user_by__ ",
"Room_name_changed_successfully": "Nome del canale cambiato con successo",
"Room_not_found": "Canale non trovato",
- "Room_topic_changed_successfully": "Argomento stanza cambiato con successo",
- "Room_type_changed_successfully": "Tipo di stanza cambiata con successo",
- "Room_unarchived": "Stanza estratta dall'archivio",
+ "Room_password_changed_successfully": "Password della stanza cambiata con successo",
+ "Room_topic_changed_successfully": "Argomento del canale cambiato con successo",
+ "Room_type_changed_successfully": "Tipo di canale cambiato con successo",
+ "Room_type_of_default_rooms_cant_be_changed": "Questo è un canale predefinito e il tipo non può essere cambiato, si prega di consultarsi con un amministratore.",
+ "Room_unarchived": "Canale disarchiviato",
"Room_uploaded_file_list": "Elenco dei file",
"Room_uploaded_file_list_empty": "Nessun file disponibile.",
- "Rooms": "Stanze",
+ "Rooms": "Canali",
"Running_Instances": "Istanze in esecuzione",
"S_new_messages_since_s": " %s nuovi messaggi dal %s",
"SAML": "SAML",
"SAML_Custom_Cert": "Certificato personalizzato",
"SAML_Custom_Entry_point": "Custom Entry Point",
"SAML_Custom_Generate_Username": "Genera Nome utente",
+ "SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO Redirect URL",
"SAML_Custom_Issuer": "Custom Issuer",
+ "SAML_Custom_Private_Key": "Contenuto chiave privata",
"SAML_Custom_Provider": "Custom Provider",
+ "SAML_Custom_Public_Cert": "Public cert contents",
"Sandstorm_Powerbox_Share": "Condividi un Sandstorm grain",
"Saturday": "Sabato",
"Save": "Salva",
@@ -1054,6 +1290,7 @@
"Save_to_enable_this_action": "Salva per abilitare questa azione",
"Saved": "Salvato",
"Saving": "Salvataggio",
+ "Scan_QR_code": "Usare un'app di autenticazione come Google Authenticator, Authy o Duo, scannerizza il codice QR. Mostrerà un codice di 6 cifre che dovrai inserire qui sotto.",
"Scope": "Scope",
"Screen_Share": "Condividi Schermo",
"Script_Enabled": "Abilita Script ",
@@ -1062,7 +1299,7 @@
"Search_Messages": "Cerca Messaggi",
"Search_Private_Groups": "Ricerca gruppi privati",
"seconds": "secondi",
- "Secret_token": "Secret token",
+ "Secret_token": "Token segreto",
"Select_a_department": "Seleziona un reparto",
"Select_a_user": "Seleziona un utente",
"Select_an_avatar": "Seleziona l'avatar",
@@ -1078,14 +1315,14 @@
"Send_confirmation_email": "Invia email di conferma",
"Send_data_into_RocketChat_in_realtime": "Invia i dati in Rocket.Chat in tempo reale.",
"Send_email": "Invia una email",
- "Send_invitation_email": "Invia e-mail di invito",
+ "Send_invitation_email": "Invia email di invito",
"Send_invitation_email_error": "Non hai fornito un indirizzo email valido.",
- "Send_invitation_email_info": "È possibile inviare più inviti e-mail in una sola volta.",
- "Send_invitation_email_success": "Hai inviato con successo una e-mail di invito ai seguenti indirizzi:",
+ "Send_invitation_email_info": "È possibile inviare più inviti email in una sola volta.",
+ "Send_invitation_email_success": "Hai inviato con successo una email di invito ai seguenti indirizzi:",
"Send_request_on_chat_close": "Manda la richiesta alla chiusura della chat",
"Send_request_on_offline_messages": "Manda la richiesta sull'evento di messaggi offline",
"Send_Test": "Manda test",
- "Send_welcome_email": "Invia e-mail di benvenuto",
+ "Send_welcome_email": "Invia email di benvenuto",
"Send_your_JSON_payloads_to_this_URL": "Invia i tuoi payload JSON a questo URL.",
"Sending": "Invio...",
"Served_By": "Servito da",
@@ -1101,19 +1338,27 @@
"Show_all": "Mostra tutto",
"Show_more": "Mostra di più",
"show_offline_users": "mostra utenti offline",
+ "Show_on_registration_page": "Mostra sulla pagina di registrazione",
"Show_only_online": "Mostra solo on-line",
- "Show_preregistration_form": "Mostra modulo di pre-registrazione",
+ "Show_preregistration_form": "Mostra il modulo di pre-registrazione",
"Show_queue_list_to_all_agents": "Mostra coda a tutti gli operatori",
+ "Show_the_keyboard_shortcut_list": "Mostra l'elenco delle scorciatoie per la tastiera",
"Showing_archived_results": "Mostra %s risultati archiviati
",
"Showing_online_users": "Visualizzati __total_showing__ su __total__users",
- "Showing_results": "Visualizzati %s resultati
",
+ "Showing_results": "Visualizzati %s risultati
",
"since_creation": "da %s",
"Site_Name": "Nome del sito",
- "Site_Url": "indirizzo del sito",
+ "Site_Url": "URL del sito",
"Site_Url_Description": "Esempio: https://chat.domain.com/",
"Skip": "Salta",
"SlackBridge_error": "SlackBridge ha rilevato un errore durante l'importazione dei messaggi alle %s: %s",
"SlackBridge_finish": "SlackBridge ha finito di importare i messaggi alle %s. Ricarica per vedere tutti i messaggi.",
+ "SlackBridge_Out_All": "SlackBridge Out All",
+ "SlackBridge_Out_All_Description": "Invia messaggi da tutti i canali che esistono in Slack e che il bot è entrato",
+ "SlackBridge_Out_Channels": "SlackBridge Out Canali",
+ "SlackBridge_Out_Channels_Description": "Scegli quale canale invierà i messaggi a Slack",
+ "SlackBridge_Out_Enabled": "SlackBridge Out Abilitato",
+ "SlackBridge_Out_Enabled_Description": "Scegli quale Slackbridge deve anche inviate i messaggi a Slack",
"SlackBridge_start": "@%s ha avviato un import SlackBridge alle `#%s`. Ti faremo sapere quando verrà ultimato.",
"Slash_Gimme_Description": "Mostra ༼ つ ◕_◕ ༽つ prima del messaggio",
"Slash_LennyFace_Description": "Mostra ( ͡° ͜ʖ ͡°) dopo il messaggio",
@@ -1138,16 +1383,20 @@
"SMTP_Port": "Porta SMTP",
"SMTP_Test_Button": "Prova le impostazioni SMTP",
"SMTP_Username": "Nome utente SMTP",
+ "Snippet_Added": "Creato su %s",
+ "Snippet_Messages": "Messaggi snippet",
+ "Snippeted_a_message": "Crea uno snippet __snippetLink__",
"Sound": "Suoni",
+ "Sound_File_mp3": "File sonoro (mp3)",
"SSL": "SSL",
"Star_Message": "Evidenzia messaggio",
- "Starred_Messages": "Messaggi speciali",
+ "Starred_Messages": "Messaggi evidenziati",
"Start_audio_call": "Avvia chiamata audio",
"Start_Chat": "Avvia chat",
- "Start_of_conversation": "Inizia una conversazione",
+ "Start_of_conversation": "Inizio della conversazione",
"Start_OTR": "Inizio OTR",
"Start_video_call": "Avvia chiamata video",
- "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Inizia con",
+ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Inizia con %s per gli utenti o %s peri canali. Es: %s o %s",
"Started_At": "Avviato il",
"Statistics": "Statistiche",
"Statistics_reporting": "Invia statistiche a Rocket.Chat",
@@ -1162,12 +1411,20 @@
"Stats_Online_Users": "Utenti in linea",
"Stats_Total_Channels": "Canali Totali",
"Stats_Total_Direct_Messages": "Totale canali diretti",
+ "Stats_Total_Livechat_Rooms": "Totale stanze Livechat",
"Stats_Total_Messages": "Messaggi totali",
+ "Stats_Total_Messages_Channel": "Messaggi totali nei canali",
+ "Stats_Total_Messages_Direct": "Messaggi totali nei messaggi diretti",
+ "Stats_Total_Messages_Livechat": "Messaggi totali nelle livechat",
+ "Stats_Total_Messages_PrivateGroup": "Messaggi totali nei gruppi privati",
"Stats_Total_Private_Groups": "Totale Gruppi Privati",
- "Stats_Total_Rooms": "Stanze Totali",
+ "Stats_Total_Rooms": "Canali Totali",
"Stats_Total_Users": "Utenti Totali",
"Status": "Stato",
"Stop_Recording": "Interrompi registrazione",
+ "Stream_Cast": "Stream Cast",
+ "Stream_Cast_Address": "Stream Cast Address",
+ "Stream_Cast_Address_Description": "IP o Host della tua installazione centrale di Rocket.Chat per lo stream cast. Es: `92.168.1.1:3000` or `localhost:4000`",
"strike": "barrato",
"Subject": "Oggetto",
"Submit": "Invia",
@@ -1181,36 +1438,50 @@
"Sync_Users": "Sincronizza utenti",
"System_messages": "Messaggi di sistema",
"Tag": "Tag",
- "Take_it": "Prendilo",
+ "Take_it": "Prendilo!",
+ "TargetRoom": "Stanza Target",
+ "TargetRoom_Description": "La stanza dove i messaggi saranno inviati quando i risultati di questi eventi saranno scatenati. Solo la stanza target è permessa e deve esistere.",
"Test_Connection": "Verifica Connessione",
"Test_Desktop_Notifications": "Verifica Notifiche Desktop",
"Thank_you_exclamation_mark": "Grazie!",
"Thank_you_for_your_feedback": "Grazie per il tuo feedback",
- "The_application_name_is_required": "Il nome dell'applicazione é richiesta",
- "The_channel_name_is_required": "Il nome del canale é richiesto",
+ "The_application_name_is_required": "Il nome dell'applicazione è richiesta",
+ "The_channel_name_is_required": "Il nome del canale è richiesto",
"The_emails_are_being_sent": "Le email verranno inviate.",
"The_field_is_required": "Il campo %s è richiesto.",
"The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Il ridimensionamento dell'immagine non funzionerà se non rileva ImageMagick or GraphicsMagick installato sul tuo server.",
- "The_redirectUri_is_required": "Il redirectUri é richiesto",
+ "The_redirectUri_is_required": "Il redirectUri è richiesto",
"The_server_will_restart_in_s_seconds": "Il server si riavvierà in %s secondi",
- "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "L'impostazione%s é configurata su %s e stai accedendo da%s !",
+ "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "L'impostazione%s è configurata su %s e stai accedendo da%s !",
"The_user_will_be_removed_from_s": "L'utente sarà rimosso da %s",
"The_user_wont_be_able_to_type_in_s": "L'utente non potrà più scrivere sul canale %s",
"Theme": "Tema",
+ "theme-color-component-color": "Colore componente",
"theme-color-content-background-color": "Colore di Sfondo del contenuto",
+ "theme-color-custom-scrollbar-color": "Colore Personalizzato della Barra Scorrevole",
+ "theme-color-error-color": "Colore Errore",
+ "theme-color-info-font-color": "Colore del Carattere delle Informazioni",
+ "theme-color-link-font-color": "Colore del Carattere dei Link",
+ "theme-color-pending-color": "Colore in attesa",
+ "theme-color-primary-action-color": "Colore azione primario",
"theme-color-primary-background-color": "Colore di Sfondo Primario",
"theme-color-primary-font-color": "Colore del Carattere Primario ",
+ "theme-color-secondary-action-color": "Colore azione secondario",
"theme-color-secondary-background-color": "Colore di Sfondo Secondario",
"theme-color-secondary-font-color": "Colore del Carattere Secondario",
- "theme-color-tertiary-background-color": "Colore di Sfondo Terziario",
- "theme-color-tertiary-font-color": "Colore del CarattereTerzario",
- "theme-color-link-font-color": "Colore del Carattere dei Link",
- "theme-color-info-font-color": "Colore del Carattere delle Informazioni",
- "theme-color-custom-scrollbar-color": "Colore Personalizzato della Barra Scorrevole",
+ "theme-color-selection-color": "Colore selezione",
"theme-color-status-away": "Colore di stato Assente",
"theme-color-status-busy": "Colore dello Stato Occupato",
"theme-color-status-offline": "Colore dello Stato Offline ",
"theme-color-status-online": "Colore dello Stato Online ",
+ "theme-color-success-color": "Colore \"Successo\"",
+ "theme-color-tertiary-background-color": "Colore di Sfondo Terziario",
+ "theme-color-tertiary-font-color": "Colore del Carattere Terzario",
+ "theme-color-transparent-dark": "Trasparente scuro",
+ "theme-color-transparent-darker": "Trasparente molto scuro",
+ "theme-color-transparent-light": "Trasparente chiaro",
+ "theme-color-transparent-lighter": "Trasparente molto chiaro",
+ "theme-color-transparent-lightest": "Trasparente veramente molto chiaro",
"theme-color-unread-notification-color": "Colore notifiche non lette",
"theme-custom-css": "CSS personalizzato",
"theme-font-body-font-family": "Famiglia del Font per il Corpo del Testo",
@@ -1218,11 +1489,11 @@
"There_are_no_integrations": "Non esistono integrazioni",
"There_are_no_users_in_this_role": "Non ci sono utenti in questo ruolo.",
"This_conversation_is_already_closed": "Questa conversazione sarà chiusa.",
- "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Questa email é stata già utilizzata e non é stata verificata. Cambia la tua password.",
- "This_is_a_desktop_notification": "Questa é una notifica desktop",
+ "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Questa email è stata già utilizzata e non é stata verificata. Cambia la tua password.",
+ "This_is_a_desktop_notification": "Questa è una notifica desktop",
"This_is_a_push_test_messsage": "Questa è una prova di notifica push",
"This_room_has_been_archived_by__username_": "Questo canale è stato archiviato da __username__",
- "This_room_has_been_unarchived_by__username_": "Questo canale è stato estratto dall'archivio da __username__",
+ "This_room_has_been_unarchived_by__username_": "Questo canale è stato disarchiviato da __username__",
"Thursday": "Giovedì",
"Time_in_seconds": "Tempo in secondi",
"Title": "Titolo",
@@ -1233,46 +1504,55 @@
"to_see_more_details_on_how_to_integrate": "per vedere altri dettagli su come integrarlo.",
"To_users": "Agli Utenti",
"Topic": "Argomento",
- "Travel_and_Places": "Travel & Places",
+ "Transcript_Enabled": "Chiedi al visitatore se vuole una trascrizione dopo la chiusura della chat",
+ "Transcript_message": "Messaggio da mostrare quando si chiede la transcrizione",
+ "Transcript_of_your_livechat_conversation": "Transcrizione della tua conversazione livechat",
+ "Translations": "Traduzioni",
+ "Travel_and_Places": "Viaggi & Luoghi",
"Trigger_removed": "Trigger rimosso",
"Trigger_Words": "Parole Trigger",
"Triggers": "Trigger",
"True": "Vero",
"Tuesday": "Martedì",
"Type": "Tipo",
- "Type_your_email": "Inserisci la tua e-mail",
+ "Type_your_email": "Inserisci la tua email",
"Type_your_message": "Inserisci la tua messaggio",
- "Type_your_name": "Scrivi il tuo nome",
- "Type_your_new_password": "Digita la nuova password",
+ "Type_your_name": "Inserisci il tuo nome",
+ "Type_your_new_password": "Inserisci la nuova password",
"UI_DisplayRoles": "Mostra Ruoli",
"UI_Merge_Channels_Groups": "Unisci i gruppi privati con i canali",
+ "UI_Use_Name_Avatar": "Usa le iniziali del nome completo per generare l'avatar predefinito",
"Unarchive": "Togli dall'archivio",
- "Unmute_someone_in_room": "Togli il muto a qualcuno nella stanza",
+ "Unblock_User": "Sblocca utente",
+ "Unmute_someone_in_room": "Smuta a qualcuno nel canale",
"Unmute_user": "Togli il muto all'utente",
"Unnamed": "Senza nome",
"Unpin_Message": "Rimuovi il pin dal messaggio",
- "Unread_Alert": "Avviso Non Letto",
- "Unread_Rooms": "Stanze non letti",
- "Unread_Rooms_Mode": "Modalità Stanze Non Letta",
- "Unstar_Message": "Rimuovi segnalibro",
+ "Unread_Rooms": "Canali non letti",
+ "Unread_Rooms_Mode": "Modalità canali non letti",
+ "Unstar_Message": "Non evidenziare messaggio",
+ "Upload_file_description": "Descrizione file",
+ "Upload_file_name": "Nome file",
"Upload_file_question": "Caricare il file?",
"Uploading_file": "Caricamento del file ...",
"Uptime": "Uptime",
"URL": "URL",
+ "URL_room_prefix": "Prefisso URL stanza",
"Use_account_preference": "Utilizzare preferenze account",
"Use_Emojis": "Utilizzare Emojis",
"Use_Global_Settings": "Usa Impostazioni Globali",
"Use_initials_avatar": "Usa le iniziali del tuo nome utente",
+ "Use_minor_colors": "Usa la palette dei colori semplici (predefinito per i colori principali)",
"Use_service_avatar": "Usa l'avatar %s",
"Use_this_username": "Usa questo nome utente",
"Use_uploaded_avatar": "Usa l'avatar caricato",
"Use_url_for_avatar": "Utilizzare una URL per l'avatar",
"Use_User_Preferences_or_Global_Settings": "Usa le Preferenze Utente o Globali",
- "User__username__is_now_a_moderator_of__room_name_": "L'Utente __username__ é ora un moderatore di __room_name__",
- "User__username__is_now_a_owner_of__room_name_": "L'Utente __username__é ora proprietario di __room_name__",
+ "User__username__is_now_a_moderator_of__room_name_": "L'Utente __username__ è ora un moderatore di __room_name__",
+ "User__username__is_now_a_owner_of__room_name_": "L'Utente __username__ è ora proprietario di __room_name__",
"User__username__removed_from__room_name__moderators": "L'Utente __username__rimosso dai moderatori __room_name__",
"User__username__removed_from__room_name__owners": "L'Utente __username__rimosso dai proprietari __room_name__",
- "User_added": "Utente __user_added__ aggiunto.",
+ "User_added": "Utente __user_added__ aggiunto.",
"User_added_by": "Utente __user_added__ aggiunto da __user_by__ .",
"User_added_successfully": "Utente aggiunto correttamente",
"User_doesnt_exist": "Non esiste nessun utente con il nome `@%s`.",
@@ -1282,12 +1562,15 @@
"User_has_been_muted_in_s": "L'utente è stato mutato in %s",
"User_has_been_removed_from_s": "L'utente è stato rimosso da %s",
"User_Info": "Info utente",
+ "User_Interface": "Interfaccia utente",
+ "User_is_blocked": "Utente è bloccato",
"User_is_no_longer_an_admin": "L'utente non è più un amministratore",
"User_is_now_an_admin": "L'utente è ora un amministratore",
+ "User_is_unblocked": "Utente è sbloccato",
"User_joined_channel": "È entrato nel canale.",
"User_joined_channel_female": "È entrata nel canale.",
"User_joined_channel_male": "È entrato nel canale.",
- "User_left": "__user_left__ ha lasciato il canale.",
+ "User_left": "Ha lasciato il canale.",
"User_left_female": "Ha lasciato il canale.",
"User_left_male": "Ha lasciato il canale.",
"User_logged_out": "L'utente è disconnesso ",
@@ -1301,7 +1584,7 @@
"User_removed_by": "Utente __user_removed__ rimosso da __user_by__ . ",
"User_Settings": "Impostazioni utente",
"User_unmuted_by": "Utente __user_unmuted__ non mutato da __user_by__ .",
- "User_unmuted_in_room": "Utente non mutato nella stanza",
+ "User_unmuted_in_room": "Utente smutato nel canale",
"User_updated_successfully": "Utente aggiornato con successo",
"Username": "Nome utente",
"Username_and_message_must_not_be_empty": "Utente e messaggio non devono essere vuoti",
@@ -1311,25 +1594,34 @@
"Username_description": "Il nome utente viene utilizzato per permetter agli altri di inviarti dei messaggi.",
"Username_doesnt_exist": "Il nome utente `%s` non esiste.",
"Username_ended_the_OTR_session": "__username__ chiude la sessione OTR",
- "Username_invalid": "%s non é un nome utente valido, usa solo lettere, numeri, punti, trattini e underscore.",
+ "Username_invalid": "%s non è un nome utente valido, usa solo lettere, numeri, punti, trattini e underscore.",
"Username_is_already_in_here": "`@%s` è già qui.",
- "Username_is_not_in_this_room": "L'utente `#%s` non é in questa stanza.",
+ "Username_is_not_in_this_room": "L'utente `#%s` non è in questo canale",
"Username_title": "Registra nome utente",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ vuole iniziare OTR. Vuoi accettare?",
"Users": "Utenti",
+ "Users_added": "L'utente è stato aggiunto",
"Users_in_role": "Utenti nel ruolo",
"UTF8_Names_Slugify": "UTF8 Names Slugify",
"UTF8_Names_Validation": "Validazione dei Nomi UTF8",
"UTF8_Names_Validation_Description": "Non permettere caratteri speciali e spazi. Puoi usare -_ e . na non alla fine del nome",
+ "Validate_email_address": "Verifica indirizzo email",
+ "Verification": "Verifica",
+ "Verification_Description": "Puoi usare i seguenti segnaposti: [Forgot_Password_Url] per la URL del recupero password. [name], [fname], [lname] rispettivamente per il nome completo dell'utente, nome or cognome. [email] per la email dell'utente. [Site_Name] e [Site_URL] rispettivamente per il nome della applicazione e la URL. ",
+ "Verification_Email": "Clicca qui per verificare il tuo account",
"Verification_email_sent": "Invio Verifica email",
+ "Verification_Email_Subject": "[Site_Name] - Verifica il tuo account",
"Verified": "Verificata",
"Version": "Versione",
"Video_Chat_Window": "Chat Video",
+ "Video_Conference": "Video conferenza",
+ "Videocall_declined": "Chiamata video rifiutata",
+ "Videocall_enabled": "Chiamata video abilitata",
"View_All": "Vedi tutto",
"View_Logs": "Visualizza log",
"View_mode": "Aspetto",
"View_mode_info": "Questo cambia il numero di spazio nei messaggi sullo schermo.",
- "Viewing_room_administration": "Visualizza Stanza amministrazione",
+ "Viewing_room_administration": "In fase di visualizzazione del canale di amministrazione",
"Visibility": "Visibilità",
"Visible": "Visibile",
"Visitor": "Visitatore",
@@ -1338,8 +1630,9 @@
"Visitor_page_URL": "URL Pagina Visitatori",
"Visitor_time_on_site": "Tempo dei visitatori sul sito",
"Wait_activation_warning": "Prima di poter effettuare il login, il tuo account deve essere attivato manualmente da un amministratore.",
+ "Warnings": "Avvisi",
"We_are_offline_Sorry_for_the_inconvenience": "Non siamo in linea. Ci dispiace per l'inconveniente.",
- "We_have_sent_password_email": "Ti abbiamo inviato una email con le istruzioni per reimpostare la password. Se non la ricevi in breve tempo, torna e prova di nuovo.",
+ "We_have_sent_password_email": "Ti abbiamo inviato un'email con le istruzioni per reimpostare la password. Se non la ricevi in breve tempo, si prega di ritornare e riprovare.",
"We_have_sent_registration_email": "Ti abbiamo inviato una email per confermare la registrazione. Se non la ricevi entro pochi minuti, torna e prova di nuovo.",
"Webhook_URL": "URL Webhook",
"Webhooks": "Webhooks",
@@ -1355,12 +1648,14 @@
"will_be_able_to": "potranno",
"Would_you_like_to_return_the_inquiry": "Vuoi tornare alla richiesta",
"Yes": "Sì",
+ "Yes_archive_it": "Si, archivialo!",
"Yes_clear_all": "Sì, svuota tutti!",
- "Yes_delete_it": "Sì, eliminalo!",
+ "Yes_delete_it": "Sì, cancellalo!",
"Yes_hide_it": "Sì, nascondilo!",
"Yes_leave_it": "Sì, lascia!",
"Yes_mute_user": "Sì, silenzia l'utente!",
"Yes_remove_user": "Sì, rimuovi l'utente!",
+ "Yes_unarchive_it": "Si, togli dall'archivio!",
"You": "Tu",
"you_are_in_preview_mode_of": "Sei in modalità di anteprima del canale # __room_name__ ",
"You_are_logged_in_as": "Sei loggato come",
@@ -1369,27 +1664,29 @@
"You_can_search_using_RegExp_eg": "È possibile cercare usando espressioni regolari. Per esempio",
"You_can_use_an_emoji_as_avatar": "È inoltre possibile utilizzare un emoji come avatar.",
"You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Puoi usare i webhooks per integrare facilmente Livechat con il tuo CRM.",
- "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Non puoi lasciare la stanza livechat. Utilizza il pulsante di chiusura.",
- "You_have_been_muted": "Hai silenziato e non puoi parlare in questa stanza",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Non puoi lasciare il canale livechat. Si prega di usare il pulsante di chiusura.",
+ "You_have_been_muted": "Sei stato mutato e non puoi parlare in questo canale",
"You_have_not_verified_your_email": "Non hai verificato la tua email.",
- "You_have_successfully_unsubscribed": "Sei stato disiscritto con successo dalla nostra Mailing List.",
+ "You_have_successfully_unsubscribed": "Hai annullato con successo l'iscrizione alla nostra Mailing List.",
"You_must_join_to_view_messages_in_this_channel": "Devi entrare nel canale per poter vedere i messaggi contenuti",
- "You_need_confirm_email": "Devi confermare la tua email per accedere!",
- "You_need_install_an_extension_to_allow_screen_sharing": "Devi installare una estensione per permettere la condivisione dello schermo",
- "You_need_to_change_your_password": "Devi cambiare la tua password",
- "You_need_to_type_in_your_password_in_order_to_do_this": "Devo scrivere la password per poterlo fare!",
- "You_need_to_type_in_your_username_in_order_to_do_this": "Devo inserire il nome utente per poterlo fare!",
+ "You_need_confirm_email": "È necessario confermare la tua email per accedere!",
+ "You_need_install_an_extension_to_allow_screen_sharing": "È necessario installare un'estensione per permettere la condivisione dello schermo",
+ "You_need_to_change_your_password": "È necessario cambiare la tua password",
+ "You_need_to_type_in_your_password_in_order_to_do_this": "È necessario scrivere la password per poterlo fare!",
+ "You_need_to_type_in_your_username_in_order_to_do_this": "È necessario inserire il nome utente per poterlo fare!",
"You_need_to_verifiy_your_email_address_to_get_notications": "È necessario verificare tuo indirizzo email per ricevere le notifiche",
- "You_need_to_write_something": "Devi scrivere qualcosa!",
+ "You_need_to_write_something": "È necessario scrivere qualcosa!",
"You_should_inform_one_url_at_least": "Devi inserire almeno una URL.",
"You_should_name_it_to_easily_manage_your_integrations": "Devi mettere il nome nella integrazione.",
"You_will_not_be_able_to_recover": "Non sarai in grado di recuperare questo messaggio!",
"You_will_not_be_able_to_recover_file": "Non puoi recuperare questo file!",
"You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Non riceverai notifiche via email, perché non hai verificato l'indirizzo.",
- "Your_email_has_been_queued_for_sending": "La tua email é stata messa in coda per l'invio",
- "Your_entry_has_been_deleted": "La tua immissione é stata cancellata.",
+ "Your_email_has_been_queued_for_sending": "La tua email è stata messa in coda per l'invio",
+ "Your_entry_has_been_deleted": "La tua immissione è stata cancellata.",
"Your_file_has_been_deleted": "Il file è stato eliminato.",
"Your_mail_was_sent_to_s": "La tua mail è stata inviata a %s",
+ "your_message": "il tuo messaggio",
+ "your_message_optional": "il tuo messaggio (opzionale)",
"Your_password_is_wrong": "La password è sbagliata!",
- "Your_push_was_sent_to_s_devices": "La tua richiesta é stata inviata ai %s dispositivi."
-}
\ No newline at end of file
+ "Your_push_was_sent_to_s_devices": "La tua richiesta è stata inviata ai %s dispositivi."
+}
diff --git a/packages/rocketchat-i18n/i18n/ja.i18n.json b/packages/rocketchat-i18n/i18n/ja.i18n.json
index 8cc4b4e22f4ef..9ddc55c8a4a41 100644
--- a/packages/rocketchat-i18n/i18n/ja.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ja.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "プロフィールの変更を許可する",
"Accounts_AvatarResize": "アバターの大きさを変更する",
"Accounts_AvatarSize": "アバターの大きさ",
- "Accounts_AvatarStorePath": "アバターの保存先",
- "Accounts_AvatarStoreType": "アバターの保存先ストレージ種類",
"Accounts_BlockedDomainsList": "ブロックされたドメイン一覧",
"Accounts_BlockedDomainsList_Description": "カンマ区切りのブロックされたドメイン一覧",
"Accounts_BlockedUsernameList": "ブロックされたユーザー名の一覧",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "メール認証をする",
"Accounts_EmailVerification_Description": "この機能を使う前に、SMTP が正しく設定されているか確認してください",
"Accounts_Enrollment_Email": "登録メール",
- "Accounts_Enrollment_Email_Default": "ようこそ [Site_Name] [Site_URL]に移動し、今日利用可能な最高のオープンソースのチャットソリューションを試してみてください!
",
+ "Accounts_Enrollment_Email_Default": "ようこそ [Site_Name] [Site_URL] に移動し、今日利用可能な最高のオープンソースのチャットソリューションを試してみてください!
",
"Accounts_Enrollment_Email_Description": "ユーザーのフルネームに [name], [fname], [lname] を使用できます。姓 または 名 にも対応しています。 メールアドレスには、 [email] を使用できます。",
"Accounts_Enrollment_Email_Subject_Default": "[Site_Name]へようこそ",
"Accounts_Iframe_api_method": "API メソッド",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "公開",
"Accounts_RegistrationForm_Secret_URL": "非公開 URL",
"Accounts_RegistrationForm_SecretURL": "登録フォームの非公開 URL",
- "Accounts_RegistrationForm_SecretURL_Description": "ランダムな文字列を入力してください。この文字列は、登録フォームの URL に使用されます。 例: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "ランダムな文字列を入力してください。この文字列は、登録フォームの URL に使用されます。 例: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "登録時にユーザー名を必須にする",
"Accounts_ShowFormLogin": "ログインフォームを表示する",
"Accounts_UseDefaultBlockedDomainsList": "既定のブロックされたドメイン一覧を利用する",
"Accounts_UseDNSDomainCheck": "DNS ドメイン検証を利用する",
- "Accounts_UserAddedEmail_Default": "ようこそ [Site_Name] [Site_URL]に移動し、今日利用可能な最高のオープンソースのチャットソリューションを試してみてください!
[email]とパスワード:[password]あなたはあなたの電子メールを使用してログインすることができます。あなたはあなたの最初のログイン後に変更する必要があります。",
+ "Accounts_UserAddedEmail_Default": "
ようこそ [Site_Name] [Site_URL] に移動し、今日利用可能な最高のオープンソースのチャットソリューションを試してみてください!
[email]とパスワード:[password]あなたはあなたの電子メールを使用してログインすることができます。あなたはあなたの最初のログイン後に変更する必要があります。",
"Accounts_UserAddedEmail_Description": "あなたは、次のプレースホルダを使用することがあります。
[name]、[fname]、[lname]ユーザのフルネーム、姓または名の、それぞれ。 ユーザーの電子メールのための[email]。 ユーザーのパスワードの[password]。 [Site_Name]と[Site_URL]アプリケーション名とURLのそれぞれ。 ",
"Accounts_UserAddedEmailSubject_Default": "あなたは[Site_Name]に追加されました",
"Activate": "有効化",
@@ -570,24 +568,12 @@
"Layout_Terms_of_Service": "サービス利用規約",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA 証明書",
- "LDAP_Custom_Domain_Search": "カスタムドメイン検索",
- "LDAP_Custom_Domain_Search_Description": "バインドと接続情報を管理し、フォームのあるJSONの作品: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "既定ドメイン",
"LDAP_Description": "LDAP は、多くの企業でシングルサインオンを提供する為に使用している階層構造データベースで、 1 つのパスワードを複数サイトやサービスで共有できる手法です。高度な設定情報や例示は、私達の wiki で相談してください: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "ドメインベース",
- "LDAP_Domain_Base_Description": "検索したいユーザーやグループが LDAP サブツリーとして属す完全修飾の Distinguished Name (DN) 。 それぞれのグループは、そこに属すユーザーと同じドメインベースに定義されていなければなりません。特定のユーザーグループを制限した場合、そのグループに属したユーザーのみ対象になります。LDAP ディレクトリーのトップレベルドメインをドメインベースとし、アクセス制御には検索フィルターを使用することを推奨します。",
- "LDAP_Domain_Search_Filter": "ドメイン検索フィルター",
- "LDAP_Domain_Search_Filter_Description": "指定すると、このフィルターにマッチしたユーザーのみログインできます。何も指定しないと、指定したドメインベースの範囲にいるすべてのユーザーログインできるようになります。 例えば Active Directory では `memberOf=cn=ROCKET_CHAT,ou=General Groups` など。 例えば OpenLDAP ( 拡張可能な検索 ) では `ou:dn:=ROCKET_CHAT` など。",
- "LDAP_Domain_Search_Object_Category": "ドメイン検索の objectCategory",
- "LDAP_Domain_Search_Object_Category_Description": "ユーザーを識別する *objectCategory* 。 空値は *OpenLDAP* のために、除いてください。 例えば、 `person` など。",
- "LDAP_Domain_Search_Object_Class": "ドメイン検索の objectclass",
- "LDAP_Domain_Search_Object_Class_Description": "ユーザーを識別する *objectclass* 。 例えば、 `organizationalPerson` 、 `user` 、 `inetOrgPerson` など。",
- "LDAP_Domain_Search_Password": "ドメイン検索のパスワード",
- "LDAP_Domain_Search_Password_Description": "ドメイン検索ユーザーのパスワード。",
- "LDAP_Domain_Search_User": "ドメイン検索ユーザー",
- "LDAP_Domain_Search_User_Description": "ユーザーがログインするためにユーザーを検索する時に使用する LDAP ユーザー。 これは多くの場合、 3rd パーティー連携の為に特別に作成されたサービスアカウントです。 `cn=Administrator,cn=Users,dc=Example,dc=com` といった完全修飾名を使用してください。",
- "LDAP_Domain_Search_User_ID": "ドメイン検索ユーザー ID",
- "LDAP_Domain_Search_User_ID_Description": "認証を試みるユーザーの LDAP 属性。 このフィールドは、ほとんどの Active Directory インストールで `sAMAccountName` とすることを推奨されていますが、ほかの OpenLDAP などの LDAP システムでは `uid` かもしれません。 `mail` をメールアドレスとしてユーザーを識別であれば使用できますし、この他にも識別できればどんな属性でも構いません。 複数の値をカンマ区切りで指定すれば、メールアドレスとユーザー名といったように複数のIDでログインできるようになります。",
+ "LDAP_BaseDN_Description": "検索したいユーザーやグループが LDAP サブツリーとして属す完全修飾の Distinguished Name (DN) 。 それぞれのグループは、そこに属すユーザーと同じドメインベースに定義されていなければなりません。特定のユーザーグループを制限した場合、そのグループに属したユーザーのみ対象になります。LDAP ディレクトリーのトップレベルドメインをドメインベースとし、アクセス制御には検索フィルターを使用することを推奨します。",
+ "LDAP_User_Search_Field_Description": "認証を試みるユーザーの LDAP 属性。 このフィールドは、ほとんどの Active Directory インストールで `sAMAccountName` とすることを推奨されていますが、ほかの OpenLDAP などの LDAP システムでは `uid` かもしれません。 `mail` をメールアドレスとしてユーザーを識別であれば使用できますし、この他にも識別できればどんな属性でも構いません。 複数の値をカンマ区切りで指定すれば、メールアドレスとユーザー名といったように複数のIDでログインできるようになります。",
+ "LDAP_User_Search_Filter_Description": "指定すると、このフィルターにマッチしたユーザーのみログインできます。何も指定しないと、指定したドメインベースの範囲にいるすべてのユーザーログインできるようになります。 例えば Active Directory では `memberOf=cn=ROCKET_CHAT,ou=General Groups` など。 例えば OpenLDAP ( 拡張可能な検索 ) では `ou:dn:=ROCKET_CHAT` など。",
+ "LDAP_Authentication_UserDN_Description": "ユーザーがログインするためにユーザーを検索する時に使用する LDAP ユーザー。 これは多くの場合、 3rd パーティー連携の為に特別に作成されたサービスアカウントです。 `cn=Administrator,cn=Users,dc=Example,dc=com` といった完全修飾名を使用してください。",
"LDAP_Enable": "有効にする",
"LDAP_Enable_Description": "LDAP による認証を試行するようになります。",
"LDAP_Encryption": "暗号化",
@@ -602,12 +588,9 @@
"LDAP_Sync_User_Data_Description": "ログインする時に、ユーザーデータを同期します (例: 名前, メールアドレス)",
"LDAP_Sync_User_Data_FieldMap": "ユーザーデータのフィールドマップ",
"LDAP_Sync_User_Data_FieldMap_Description": "どのようにユーザーアカウントのフィールド (メールアドレスなど) を LDAP にあるレコードから調整するか。 例えば、 `{\"cn\":\"name\", \"mail\":\"email\"}` では、人間が読める名前を cn 属性とし、メールアドレスを mail 属性から取得します。 使用できるは、 `名前` と `メールアドレス` を含むものです。",
- "LDAP_Sync_Users": "ユーザーを同期する",
"LDAP_Test_Connection": "接続テスト",
"LDAP_Unique_Identifier_Field": "一意性を識別するフィールド",
"LDAP_Unique_Identifier_Field_Description": "どのフィールドで LDAP ユーザーと Rocket.Chat ユーザーをリンクするか。複数の値をカンマ区切りで指定すると LDAP レコードからそれぞれ取得することを試みます。 既定値は、 `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber` です",
- "LDAP_Use_Custom_Domain_Search": "カスタムドメイン検索を使用する",
- "LDAP_Use_Custom_Domain_Search_Description": "LDAP サーバー上で検索する際の独自フィルターを記述する場合に指定します。",
"LDAP_Username_Field": "ユーザー名フィールド",
"LDAP_Username_Field_Description": "どのフィールドを新しいユーザーの *ユーザー名* として使用するのか。ログインページのユーザー名を利用する場合は、空にしてください。 テンプレートタグとして `#{givenName}.#{sn}` といった記述も使用できます。 既定値は、 `sAMAccountName` です",
"Leave_Group_Warning": "本当にグループ \"%s\" から退出しますか?",
@@ -659,8 +642,15 @@
"Managing_assets": "資産を管理します",
"Managing_integrations": "統合管理",
"Mark_as_read": "既読にする",
- "Markdown_Headers": "Markdown ヘッダー",
- "Markdown_SupportSchemesForLink": "Markdown リンクでサポートするスキーマ",
+ "Markdown_Headers": "ヘッダーを有効にする",
+ "Markdown_Marked_Breaks": "Marked Breaks を有効にする",
+ "Markdown_Marked_GFM": "Marked GFM を有効にする",
+ "Markdown_Marked_Pedantic": "Marked Pedantic を有効にする",
+ "Markdown_Marked_SmartLists": "Marked Smart Lists を有効にする",
+ "Markdown_Marked_Smartypants": "Marked Smartypants を有効にする",
+ "Markdown_Marked_Tables": "Marked Tables を有効にする",
+ "Markdown_Parser": "Markdown パーサー",
+ "Markdown_SupportSchemesForLink": "リンクでサポートするスキーマリスト",
"Markdown_SupportSchemesForLink_Description": "許可するスキーマをカンマ区切りで記述してください。",
"Members_List": "メンバーリスト",
"Mentions": "メンション",
@@ -785,6 +775,7 @@
"Opened": "開いた状態",
"optional": "オプション",
"Order": "注文",
+ "Original": "オリジナル",
"OS_Arch": "OS アーキテクチャー",
"OS_Cpus": "OS CPU 数",
"OS_Freemem": "OS 空きメモリー",
@@ -1054,19 +1045,19 @@
"The_user_wont_be_able_to_type_in_s": "そのユーザーは、 %s で入力できなくなります",
"Theme": "テーマ",
"theme-color-content-background-color": "コンテンツ 背景色",
+ "theme-color-custom-scrollbar-color": "カスタム スクロールバー色",
+ "theme-color-info-font-color": "情報 文字色",
+ "theme-color-link-font-color": "リンク 文字色",
"theme-color-primary-background-color": "基本 背景色",
"theme-color-primary-font-color": "基本 文字色",
"theme-color-secondary-background-color": "二次 背景色",
"theme-color-secondary-font-color": "二次 文字色",
- "theme-color-tertiary-background-color": "三次 背景色",
- "theme-color-tertiary-font-color": "三次 文字色",
- "theme-color-link-font-color": "リンク 文字色",
- "theme-color-info-font-color": "情報 文字色",
- "theme-color-custom-scrollbar-color": "カスタム スクロールバー色",
"theme-color-status-away": "離席中 ステータス色",
"theme-color-status-busy": "取り込み中 ステータス色",
"theme-color-status-offline": "状態を隠す ステータス色",
"theme-color-status-online": "オンライン ステータス色",
+ "theme-color-tertiary-background-color": "三次 背景色",
+ "theme-color-tertiary-font-color": "三次 文字色",
"theme-color-unread-notification-color": "未読 通知色",
"theme-custom-css": "カスタム CSS",
"There_are_no_agents_added_to_this_department_yet": "この部門には、まだ担当者がいません。",
@@ -1103,7 +1094,6 @@
"Unmute_user": "ミュートを解除",
"Unnamed": "無名",
"Unpin_Message": "ピン留めを外す",
- "Unread_Alert": "未読アラート",
"Unread_Rooms": "未読のあるルーム",
"Unread_Rooms_Mode": "未読ルーム表示モード",
"Unstar_Message": "スターを外す",
@@ -1240,4 +1230,4 @@
"Your_mail_was_sent_to_s": "メールは %s へを送信されました",
"Your_password_is_wrong": "パスワードが間違っています!",
"Your_push_was_sent_to_s_devices": "プッシュ通知が %s 台のデバイスへ送信されました"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/km.i18n.json b/packages/rocketchat-i18n/i18n/km.i18n.json
index 2374ff4d1139c..6e4dd71321028 100644
--- a/packages/rocketchat-i18n/i18n/km.i18n.json
+++ b/packages/rocketchat-i18n/i18n/km.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "អនុញ្ញាតិអ្នកប្រើប្រាស់ប្តូរព័ត៌មានផ្ទាល់ខ្លួន",
"Accounts_AvatarResize": "ប្តូរទំហំ Avatar",
"Accounts_AvatarSize": "ទំហំ Avatar",
- "Accounts_AvatarStorePath": "ទីតាំងផ្ទុក Avatar",
- "Accounts_AvatarStoreType": "ប្រភេទបន្ទុក Avatar",
"Accounts_BlockedDomainsList": "បញ្ជីដែន",
"Accounts_BlockedDomainsList_Description": "បញ្ជីបំបែកដោយសញ្ញាក្បៀសនៃដែនបានបិទ",
"Accounts_BlockedUsernameList": "បញ្ជីឈ្មោះអ្នកប្រើ",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "ការផ្ទៀងផ្ទាត់តាមអ៊ីម៉ែល",
"Accounts_EmailVerification_Description": "សូមប្រាកដថាអ្នកមានការកំណត់របស់ SMTP ត្រឹមត្រូវដើម្បីប្រើលក្ខណៈពិសេសនេះ",
"Accounts_Enrollment_Email": "ការចូលអ៊ីមែល",
- "Accounts_Enrollment_Email_Default": " ស្វាគមន៍មកកាន់ [Site_Name] ចូរទៅទៅ [Site_URL] និងព្យាយាមដំណោះស្រាយប្រភពបើកចំហជជែកកំសាន្តដែលអាចប្រើបានល្អបំផុតនាពេលបច្ចុប្បន្ននេះ!
",
+ "Accounts_Enrollment_Email_Default": " ស្វាគមន៍មកកាន់ [Site_Name] ចូរទៅទៅ [Site_URL] និងព្យាយាមដំណោះស្រាយប្រភពបើកចំហជជែកកំសាន្តដែលអាចប្រើបានល្អបំផុតនាពេលបច្ចុប្បន្ននេះ!
",
"Accounts_Enrollment_Email_Description": "អ្នកប្រហែលប្រើ [name], [fname], [lname] ពីឈ្មោះពេញរបស់អ្នកប្រើប្រាស់ គោត្តនាម ឬនាមខ្លួន។ អ្នកប្រហែលប្រើប្រាស់ [email] ពីអ៊ីមែលរបស់អញនកប្រើប្រាស់។",
"Accounts_Enrollment_Email_Subject_Default": "សូមស្វាគមន៍មកកាន់ [Site_Name]",
"Accounts_Iframe_api_method": "វិធីសាស្រ្ត API",
@@ -83,7 +81,7 @@
"Accounts_OAuth_Twitter_callback_url": "URL ដែល Twitter បានហៅទៅវិញ",
"Accounts_OAuth_Twitter_id": "លេខសម្គាល់ Twitter",
"Accounts_OAuth_Twitter_secret": "Twitter សម្ងាត់",
- "Accounts_OAuth_Wordpress": "ការឡុកចូល Wordpress",
+ "Accounts_OAuth_Wordpress": "ការឡុកចូល WordPress",
"Accounts_OAuth_Wordpress_callback_url": "URL ដែលប្លកហៅទៅវិញ",
"Accounts_OAuth_Wordpress_id": "លេខសម្គាល់ WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress សម្ងាត់",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "សាធារណៈ",
"Accounts_RegistrationForm_Secret_URL": "URL ដែលជាការសម្ងាត់",
"Accounts_RegistrationForm_SecretURL": "ទម្រង់បែបបទចុះឈ្មោះរបស់ URL សម្ងាត់",
- "Accounts_RegistrationForm_SecretURL_Description": "អ្នកត្រូវតែផ្ដល់ខ្សែអក្សរចៃដន្យដែលនឹងត្រូវបានបន្ថែមទៅ URL ចុះឈ្មោះរបស់អ្នក។ ឧទាហរណ៍: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "អ្នកត្រូវតែផ្ដល់ខ្សែអក្សរចៃដន្យដែលនឹងត្រូវបានបន្ថែមទៅ URL ចុះឈ្មោះរបស់អ្នក។ ឧទាហរណ៍: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "ត្រូវការ Name សម្រាប់ការចុះឈ្មោះ",
"Accounts_ShowFormLogin": "ការចូលជាទម្រង់ដែលមានមូលដ្ឋានបង្ហាញ",
"Accounts_UseDefaultBlockedDomainsList": "បញ្ជីដែនប្រើលំនាំដើម",
"Accounts_UseDNSDomainCheck": "ប្រើដែនឈ្មោះ DNS ពិនិត្យ",
- "Accounts_UserAddedEmail_Default": " ស្វាគមន៍មកកាន់ [Site_Name] ចូរទៅទៅ [Site_URL] និងព្យាយាមដំណោះស្រាយប្រភពបើកចំហជជែកកំសាន្តដែលអាចប្រើបានល្អបំផុតនាពេលបច្ចុប្បន្ននេះ!
អ្នកអាចចូលប្រើអ៊ីម៉ែលរបស់អ្នក: [email] និងពាក្យសម្ងាត់: [password] ។ អ្នកអាចត្រូវបានទាមទារឱ្យផ្លាស់ប្តូរវាបន្ទាប់ពីការចូលលើកដំបូងរបស់អ្នក។",
+ "Accounts_UserAddedEmail_Default": "
ស្វាគមន៍មកកាន់ [Site_Name] ចូរទៅទៅ [Site_URL] និងព្យាយាមដំណោះស្រាយប្រភពបើកចំហជជែកកំសាន្តដែលអាចប្រើបានល្អបំផុតនាពេលបច្ចុប្បន្ននេះ!
អ្នកអាចចូលប្រើអ៊ីម៉ែលរបស់អ្នក: [email] និងពាក្យសម្ងាត់: [password] ។ អ្នកអាចត្រូវបានទាមទារឱ្យផ្លាស់ប្តូរវាបន្ទាប់ពីការចូលលើកដំបូងរបស់អ្នក។",
"Accounts_UserAddedEmail_Description": "អ្នកអាចប្រើកន្លែងដាក់ខាងក្រោម:
[name], [fname] [lname] សម្រាប់ឈ្មោះអ្នកប្រើពេញលេញ, ឈ្មោះជាលើកដំបូងឬឈ្មោះចុងក្រោយ, រៀងគ្នា។ [email] សម្រាប់អ៊ីម៉ែលរបស់អ្នកប្រើ។ [password] ពាក្យសម្ងាត់របស់អ្នកប្រើ។ [Site_Name] និង [Site_URL] សម្រាប់ឈ្មោះកម្មវិធីនិង URL រៀងគ្នា។ ",
"Accounts_UserAddedEmailSubject_Default": "អ្នកត្រូវបានបន្ថែមទៅ [Site_Name]",
"Activate": "ធ្វើឱ្យសកម្ម",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "ល័ក្ខខ័ណ្ឌនៃសេវាកម្ម",
"LDAP": "ប្រើ LDAP",
"LDAP_CA_Cert": "CA បានវិញ្ញាបនបត្រ",
- "LDAP_Custom_Domain_Search": "ស្វែងរកដែនផ្ទាល់ខ្លួន",
- "LDAP_Custom_Domain_Search_Description": "បំណែកមួយនៃ JSON ប៉ុណ្ណោះដែលគ្រប់គ្រង info ចងនិងការតភ្ជាប់និងជានៃសំណុំបែបបទនេះ: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "ដែនលំនាំដើម",
"LDAP_Description": "LDAP គឺជាលំដាប់ក្នុងទូផ្ទុកទិន្នន័យដែលផ្ទុកព័ត៌មានក្រុមហ៊ុនជាច្រើនដែលប្រើប្រាស់ដើម្បីធ្វើការ Authentication ដោយប្រើប្រាស់ Username និង Password រវាង Site ជាច្រើន និងសេវាកម្មផ្សេងៗ។ ព័ត៌មានអំពីការកំណត់កម្រិតខ្ពស់ និងឧទាហរណ៍សូមចូលទៅកាន់វីគី https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "មូលដ្ឋានដែន",
- "LDAP_Domain_Base_Description": "ឈ្មោះដែលមានសមត្ថភាពយ៉ាងពេញលេញកិត្តិយស (DN) នៃមែកធាងរបស់ LDAP មួយដែលអ្នកចង់បានដើម្បីស្វែងរកអ្នកប្រើនិងក្រុម។ អ្នកអាចបន្ថែមជាច្រើនដូចជាអ្នកចង់; ទោះជាយ៉ាងណា, ក្រុមនីមួយត្រូវតែត្រូវបានកំណត់នៅក្នុងមូលដ្ឋានដែនដូចគ្នាជាអ្នកប្រើប្រាស់ដែលជាកម្មសិទ្ធិរបស់វា។ ប្រសិនបើអ្នកបញ្ជាក់ក្រុមអ្នកប្រើបានដាក់មានតែអ្នកប្រើដែលជារបស់ក្រុមទាំងនោះនឹងមាននៅក្នុងវិសាលភាព។ យើងផ្ដល់អនុសាសន៍ថាអ្នកបញ្ជាក់ក្នុងកម្រិតកំពូលរបស់ថត LDAP របស់អ្នកដើមឈើជាមូលដ្ឋានដែនរបស់អ្នកហើយប្រើតម្រងស្វែងរកដើម្បីគ្រប់គ្រងការចូលប្រើ។",
- "LDAP_Domain_Search_Filter": "តម្រងស្វែងរកដែន",
- "LDAP_Domain_Search_Filter_Description": "ប្រសិនបើបានបញ្ជាក់នោះមានតែអ្នកប្រើដែលផ្គូផ្គងនឹងតម្រងនេះនឹងត្រូវបានអនុញ្ញាតឱ្យចូល។ ប្រសិនបើមិនមានតម្រងត្រូវបានបញ្ជាក់, អ្នកប្រើប្រាស់ទាំងអស់នៅក្នុងវិសាលភាពនៃមូលដ្ឋានដែនដែលបានបញ្ជាក់នឹងអាចចូល។ ឧសម្រាប់ថតសកម្ម `memberOf = CN = ROCKET_CHAT, ou = ទូទៅ Groups` ។ ឧសម្រាប់ OpenLDAP (ស្វែងរកការប្រកួតពង្រីក) `OU: DN: = ROCKET_CHAT` ។",
- "LDAP_Domain_Search_Object_Category": "ដែនស្វែងរកវត្ថុ",
- "LDAP_Domain_Search_Object_Category_Description": "នេះ * objectCategory * ដែលសម្គាល់អ្នកប្រើរបស់អ្នក។ ទុកឱ្យនៅទទេចំពោះ * របស់ OpenLDAP * ។ ឧ `person` ល",
- "LDAP_Domain_Search_Object_Class": "ស្វែងរកវត្ថុដែនថ្នាក់",
- "LDAP_Domain_Search_Object_Class_Description": "នេះ * objectClass * ដែលសម្គាល់អ្នកប្រើរបស់អ្នក។ ឧ `organizationalPerson`: user`: inetOrgPerson` ល",
- "LDAP_Domain_Search_Password": "ស្វែងរកពាក្យសម្ងាត់ដែន",
- "LDAP_Domain_Search_Password_Description": "ពាក្យសម្ងាត់សម្រាប់អ្នកប្រើស្វែងរកដែន។",
- "LDAP_Domain_Search_User": "ដែនស្វែងរករបស់អ្នកប្រើ",
- "LDAP_Domain_Search_User_Description": "អ្នកប្រើ LDAP ដែលដំណើរការរកមើលអ្នកប្រើដើម្បីផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវអ្នកប្រើផ្សេងទៀតនៅពេលពួកគេចូល។ នេះគឺជាការជាធម្មតាគណនីសេវាកម្មមួយដែលបានបង្កើតឡើងជាពិសេសសម្រាប់ការធ្វើសមាហរណកម្មភាគីទីបី។ ប្រើឈ្មោះដែលមានសមត្ថភាពយ៉ាងពេញលេញជាមួយដូចជា `CN = គ្រប់គ្រង CN = អ្នកប្រើ, DC = ឧទាហរណ៍ dc = com` ។",
- "LDAP_Domain_Search_User_ID": "លេខសម្គាល់អ្នកដែនស្វែងរក",
- "LDAP_Domain_Search_User_ID_Description": "គុណលក្ខណៈ LDAP ដែលបានកំណត់អ្នកប្រើ LDAP ដែលប៉ុនប៉ងផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ។ វាលនេះគួរតែជា `sAMAccountName` សម្រាប់ការដំឡើងថតសកម្មច្រើនបំផុតប៉ុន្តែវាអាចជាដំណោះស្រាយ` uid` ផ្សេងទៀតរបស់ LDAP ដូចជារបស់ OpenLDAP ។ អ្នកអាចប្រើ `mail` អត្តសញ្ញាណអ្នកប្រើដោយអ៊ីម៉ែលឬគុណលក្ខណៈដែលអ្នកចង់បាន។ អ្នកអាចប្រើតម្លៃជាច្រើនត្រូវបានបំបែកដោយសញ្ញាក្បៀសដើម្បីអនុញ្ញាតឱ្យអ្នកប្រើដើម្បីចូលទៅប្រើប្រាស់ជាច្រើនដូចឈ្មោះអ្នកប្រើអត្តសញ្ញាឬអ៊ីម៉ែល។",
+ "LDAP_BaseDN_Description": "ឈ្មោះដែលមានសមត្ថភាពយ៉ាងពេញលេញកិត្តិយស (DN) នៃមែកធាងរបស់ LDAP មួយដែលអ្នកចង់បានដើម្បីស្វែងរកអ្នកប្រើនិងក្រុម។ អ្នកអាចបន្ថែមជាច្រើនដូចជាអ្នកចង់; ទោះជាយ៉ាងណា, ក្រុមនីមួយត្រូវតែត្រូវបានកំណត់នៅក្នុងមូលដ្ឋានដែនដូចគ្នាជាអ្នកប្រើប្រាស់ដែលជាកម្មសិទ្ធិរបស់វា។ ប្រសិនបើអ្នកបញ្ជាក់ក្រុមអ្នកប្រើបានដាក់មានតែអ្នកប្រើដែលជារបស់ក្រុមទាំងនោះនឹងមាននៅក្នុងវិសាលភាព។ យើងផ្ដល់អនុសាសន៍ថាអ្នកបញ្ជាក់ក្នុងកម្រិតកំពូលរបស់ថត LDAP របស់អ្នកដើមឈើជាមូលដ្ឋានដែនរបស់អ្នកហើយប្រើតម្រងស្វែងរកដើម្បីគ្រប់គ្រងការចូលប្រើ។",
+ "LDAP_User_Search_Field_Description": "គុណលក្ខណៈ LDAP ដែលបានកំណត់អ្នកប្រើ LDAP ដែលប៉ុនប៉ងផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ។ វាលនេះគួរតែជា `sAMAccountName` សម្រាប់ការដំឡើងថតសកម្មច្រើនបំផុតប៉ុន្តែវាអាចជាដំណោះស្រាយ` uid` ផ្សេងទៀតរបស់ LDAP ដូចជារបស់ OpenLDAP ។ អ្នកអាចប្រើ `mail` អត្តសញ្ញាណអ្នកប្រើដោយអ៊ីម៉ែលឬគុណលក្ខណៈដែលអ្នកចង់បាន។ អ្នកអាចប្រើតម្លៃជាច្រើនត្រូវបានបំបែកដោយសញ្ញាក្បៀសដើម្បីអនុញ្ញាតឱ្យអ្នកប្រើដើម្បីចូលទៅប្រើប្រាស់ជាច្រើនដូចឈ្មោះអ្នកប្រើអត្តសញ្ញាឬអ៊ីម៉ែល។",
+ "LDAP_User_Search_Filter_Description": "ប្រសិនបើបានបញ្ជាក់នោះមានតែអ្នកប្រើដែលផ្គូផ្គងនឹងតម្រងនេះនឹងត្រូវបានអនុញ្ញាតឱ្យចូល។ ប្រសិនបើមិនមានតម្រងត្រូវបានបញ្ជាក់, អ្នកប្រើប្រាស់ទាំងអស់នៅក្នុងវិសាលភាពនៃមូលដ្ឋានដែនដែលបានបញ្ជាក់នឹងអាចចូល។ ឧសម្រាប់ថតសកម្ម `memberOf = CN = ROCKET_CHAT, ou = ទូទៅ Groups` ។ ឧសម្រាប់ OpenLDAP (ស្វែងរកការប្រកួតពង្រីក) `OU: DN: = ROCKET_CHAT` ។",
+ "LDAP_Authentication_UserDN_Description": "អ្នកប្រើ LDAP ដែលដំណើរការរកមើលអ្នកប្រើដើម្បីផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវអ្នកប្រើផ្សេងទៀតនៅពេលពួកគេចូល។ នេះគឺជាការជាធម្មតាគណនីសេវាកម្មមួយដែលបានបង្កើតឡើងជាពិសេសសម្រាប់ការធ្វើសមាហរណកម្មភាគីទីបី។ ប្រើឈ្មោះដែលមានសមត្ថភាពយ៉ាងពេញលេញជាមួយដូចជា `CN = គ្រប់គ្រង CN = អ្នកប្រើ, DC = ឧទាហរណ៍ dc = com` ។",
"LDAP_Enable": "អនុញ្ញាតិ LDAP",
"LDAP_Enable_Description": "ព្យាយាមប្រើប្រាស់ LDAP ក្នុងការផ្ទៀងផ្ទាត់គណនី",
"LDAP_Encryption": "ការអ៊ីនគ្រីប",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "រក្សាទិន្នន័យអ្នកប្រើប្រាស់ក្នុងការ Sync ជាមួយម៉ាស៊ីនមេក្នុងការ Login (eg: name, email)។",
"LDAP_Sync_User_Data_FieldMap": "ចំណុចចងភ្ជាប់ទិន្នន័យអ្នកប្រើប្រាស់",
"LDAP_Sync_User_Data_FieldMap_Description": "ការកំណត់ចន្លោះគណនីអ្នកប្រើប្រាស់ (ដូចជាអ៊ីមែល) គឺត្រូវបានទាញទិន្នន័យចេញពី LDAP (ពេលដែលរកឃើញ)។ ឧទាហរណ៍៖ `{\"cn\":\"ឈ្មោះ\", \"mail\":\"អ៊ីមែល\"}` នឹងត្រូវបានជ្រើសយកឈ្មោះមនុស្សពីធាតុ cn ហើយអ៊ីមែលរបស់ពួកគេទាញចេញពីធាតុ email។ ចន្លោះទំនេររាប់បញ្ចូលទាំង `ឈ្មោះ` និង `អ៊ីមែល`។",
- "LDAP_Sync_Users": "អ្នកប្រើសមកាលកម្ម",
"LDAP_Test_Connection": "សាកល្បងការតភ្ជាប់",
"LDAP_Unique_Identifier_Field": "មានតែមួយគត់សម្គាល់វាល",
"LDAP_Unique_Identifier_Field_Description": "វាលនេះដែលនឹងត្រូវបានប្រើដើម្បីភ្ជាប់អ្នកប្រើ LDAP និងអ្នកប្រើ Rocket.Chat នេះ។ អ្នកអាចជូនដំណឹងដល់តម្លៃជាច្រើនត្រូវបានបំបែកដោយសញ្ញាក្បៀសដើម្បីព្យាយាមដើម្បីទទួលបានតម្លៃពីកំណត់ត្រា LDAP ។ តម្លៃលំនាំដើមគឺ `objectGUID, ក្រុមហ៊ុន IBM-entryUUID, ណែនាំ, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "ប្រើ Search ដែនផ្ទាល់ខ្លួន",
- "LDAP_Use_Custom_Domain_Search_Description": "ការសរសេរតម្រងផ្ទាល់ខ្លួនរបស់អ្នកដើម្បីស្វែងរកអ្នកប្រើនៅក្នុងម៉ាស៊ីនបម្រើ LDAP ។",
"LDAP_Username_Field": "ឈ្មោះអ្នកប្រើវាល",
"LDAP_Username_Field_Description": "វាលនេះដែលនឹងត្រូវបានប្រើជា * សម្រាប់អ្នកប្រើឈ្មោះអ្នកប្រើ * ថ្មី។ ទុកឱ្យទទេដើម្បីប្រើឈ្មោះអ្នកប្រើដែលបានជូនដំណឹងនៅលើទំព័រចូល។ អ្នកអាចប្រើស្លាកពុម្ពផងដែរ, ដូចជា `#{givenName}.#{sn}` ។ តម្លៃលំនាំដើមគឺ `sAMAccountName` ។",
"Leave_Group_Warning": "តើអ្នកពិតជាចង់ចាកចេញពីក្រុម \" %s\" ទេ?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "អ្នកប្រើនឹងមិនអាចវាយនៅក្នុង %s",
"Theme": "ស្បែក",
"theme-color-content-background-color": "ពណ៌ផ្ទៃខាងក្រោយអត្ថបទ",
+ "theme-color-custom-scrollbar-color": "របាររមូរផ្ទាល់ខ្លួន Color",
+ "theme-color-info-font-color": "ពណ៌ពុម្ពអក្សររបស់ Info",
+ "theme-color-link-font-color": "ពណ៌ពុម្ពអក្សរតំណភ្ជាប់",
"theme-color-primary-background-color": "ពណ៌អាទិភាពផ្ទៃខាងក្រោយ",
"theme-color-primary-font-color": "ពណ៌អាទិភាពពុម្ពអក្សរ",
"theme-color-secondary-background-color": "ពណ៌បន្ទាប់បន្សំផ្ទៃខាងក្រោយ",
"theme-color-secondary-font-color": "ពណ៌បន្ទាប់បន្សំពុម្ពអក្សរ",
- "theme-color-tertiary-background-color": "ផ្ទៃខាងក្រោយឧត្តមសិក្សា",
- "theme-color-tertiary-font-color": "ឧត្តមសិក្សាល័ពុម្ពអក្សរ",
- "theme-color-link-font-color": "ពណ៌ពុម្ពអក្សរតំណភ្ជាប់",
- "theme-color-info-font-color": "ពណ៌ពុម្ពអក្សររបស់ Info",
- "theme-color-custom-scrollbar-color": "របាររមូរផ្ទាល់ខ្លួន Color",
"theme-color-status-away": "ពណ៌ស្ថានភាពនៅឆ្ងាយ",
"theme-color-status-busy": "ពណ៌ស្ថានភាពរវល់",
"theme-color-status-offline": "ពណ៌ស្ថានភាពក្រៅបណ្តាញ",
"theme-color-status-online": "ពណ៌ស្ថានភាពលើបណ្តាញ",
+ "theme-color-tertiary-background-color": "ផ្ទៃខាងក្រោយឧត្តមសិក្សា",
+ "theme-color-tertiary-font-color": "ឧត្តមសិក្សាល័ពុម្ពអក្សរ",
"theme-color-unread-notification-color": "មិនទាន់អាន Color ជូនដំណឹង",
"theme-custom-css": "CSS ផ្ទាល់ខ្លួន",
"There_are_no_agents_added_to_this_department_yet": "មានភ្នាក់ងារបានបន្ថែមទៅនាយកដ្ឋាននេះនៅឡើយទេ។",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "សំបុត្ររបស់អ្នកត្រូវបានបញ្ជូនទៅកាន់ %s",
"Your_password_is_wrong": "ពាក្យសម្ងាត់របស់អ្នកគឺខុស!",
"Your_push_was_sent_to_s_devices": "ការជំរុញរបស់អ្នកត្រូវបានបញ្ជូនទៅកាន់ឧបករណ៍ %s បាន"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ko.i18n.json b/packages/rocketchat-i18n/i18n/ko.i18n.json
index a8349ea92fd3e..28ff18bf5dc6a 100644
--- a/packages/rocketchat-i18n/i18n/ko.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ko.i18n.json
@@ -5,45 +5,49 @@
"2_Erros_Information_and_Debug": "2 - 오류, 정보 및 디버그",
"403": "금지됨",
"500": "내부 서버 오류",
- "@username": "@username",
- "@username_message": "@username ",
- "__username__is_no_longer__role__defined_by__user_by_": "__ 사용자 이름 __는 __user_by__에 의해, __role__ 더 이상 없다",
- "__username__was_set__role__by__user_by_": "__ 사용자 이름 __은 __user_by__에 의해 __role__ 설정했다",
+ "@username": "@사용자명",
+ "@username_message": "@사용자이름 ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__사용자는 더이상 __가설정한 __역할이 없습니다",
+ "__username__was_set__role__by__user_by_": "__ 사용자에게 __사용자가 __역할을__ 설정하였습니다",
"Accept": "수락",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "온라인 상담원이없는 경우에도 들어오는 실시간 채팅 요청 수락",
- "Access_not_authorized": "액세스 권한이 없습니다",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "상담원이 온라인 상태가 아닌 경우에도 라이브챗을 수락합니다.",
+ "Accept_with_no_online_agents": "온라인 에이전트가 없는 것을 허용",
+ "Access_not_authorized": "엑세스 권한이 없습니다",
"Access_Token_URL": "액세스 토큰 URL",
- "Accessing_permissions": "권한 액세스",
+ "Accessing_permissions": "접속권한",
"Account_SID": "계정 SID",
"Accounts": "계정",
- "Accounts_AllowDeleteOwnAccount": "사용자가 자신의 계정을 삭제할 수있습니다.",
- "Accounts_AllowedDomainsList": "허용 가능한 도메인 목록",
+ "Accounts_AllowAnonymousRead": "익명사용자 읽기 허용",
+ "Accounts_AllowAnonymousWrite": "익명사용자 쓰기 허용",
+ "Accounts_AllowDeleteOwnAccount": "사용자가 자신의 계정을 삭제할 수 있습니다",
+ "Accounts_AllowedDomainsList": "허용된 도메인 목록",
"Accounts_AllowedDomainsList_Description": "허용된 도메인을 쉼표(,)로 구분하기",
"Accounts_AllowEmailChange": "이메일 변경을 허용합니다",
- "Accounts_AllowPasswordChange": "암호 변경 허용",
+ "Accounts_AllowPasswordChange": "암호 변경을 허용합니다.",
"Accounts_AllowUserAvatarChange": "사용자 아바타 변경을 허용",
"Accounts_AllowUsernameChange": "사용자 이름 변경 허용",
"Accounts_AllowUserProfileChange": "사용자 프로필 변경을 허용",
"Accounts_AvatarResize": "아바타 크기 조정",
"Accounts_AvatarSize": "아바타 크기",
- "Accounts_AvatarStorePath": "아바타 저장 경로",
- "Accounts_AvatarStoreType": "아바파 저장 타입",
- "Accounts_BlockedDomainsList": "차단 된 도메인 목록",
- "Accounts_BlockedDomainsList_Description": "차단 된 도메인의 쉼표로 구분 된 목록",
- "Accounts_BlockedUsernameList": "차단 된 사용자 이름 목록",
- "Accounts_BlockedUsernameList_Description": "차단 된 사용자 이름의 쉼표로 구분 된 목록 (대소 문자 구분)",
+ "Accounts_BlockedDomainsList": "차단된 도메인 목록",
+ "Accounts_BlockedDomainsList_Description": "쉼표로 구문된 차단 도메인 리스트",
+ "Accounts_BlockedUsernameList": "차단된 사용자 리스트",
+ "Accounts_BlockedUsernameList_Description": "쉼표로 구문된 차단 사용자 리스트 (대소 문자 구분)",
+ "Accounts_CustomFields_Description": "필드 설정에 포함된 필드명을 사용한 올바른 JSON 이여야 합니다.\n\n예:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_DefaultUsernamePrefixSuggestion": "사용자 기본 접두어 제안",
"Accounts_denyUnverifiedEmail": "확인되지 않은 이메일 거부",
"Accounts_EmailVerification": "이메일 확인",
"Accounts_EmailVerification_Description": "이 기능을 사용하려면 SMTP설정이 올바르게 되어있는지 확인해주십시오.",
"Accounts_Enrollment_Email": "등록된 이메일",
- "Accounts_Enrollment_Email_Default": " 에 오신 것을 환영합니다 [Site_Name] [Site_URL]로 이동하여 오늘날 최고의 오픈 소스 채팅 솔루션을보십시오!
",
- "Accounts_Enrollment_Email_Description": "당신은 각각 사용자의 전체 이름, 이름 또는 성을 위해 [lname], [name], [fname]을 사용할 수 있습니다. 당신은 사용자의 이메일을 [email]을 사용할 수 있습니다.",
- "Accounts_Enrollment_Email_Subject_Default": "에 오신 것을 환영합니다 [Site_Name]",
+ "Accounts_Enrollment_Email_Default": " 에 오신 것을 환영합니다 [Site_Name] [Site_URL] 로 이동하여 오늘날 최고의 오픈 소스 채팅 솔루션을보십시오!
",
+ "Accounts_Enrollment_Email_Description": "다음의 기호를 사용할 수 있습니다: [lname] - 성, [name] - 이름, [fname] - 전체이름(성+이름) [email] - 이메일 [Site_Name] - 응용프로그램의 이름, [Site_URL] - URL ",
+ "Accounts_Enrollment_Email_Subject_Default": "[Site_Name] 에 오신 것을 환영합니다 ",
+ "Accounts_ForgetUserSessionOnWindowClose": "창을 닫을때 사용자 세션을 삭제합니다",
"Accounts_Iframe_api_method": "API 메소드",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "사용",
"Accounts_iframe_url": "iframe URL",
- "Accounts_LoginExpiration": "로그인 만료 일수",
+ "Accounts_LoginExpiration": "로그인 만료날짜",
"Accounts_ManuallyApproveNewUsers": "수동으로 새로운 사용자 승인합니다",
"Accounts_OAuth_Custom_Authorize_Path": "Authorize 경로",
"Accounts_OAuth_Custom_Button_Color": "버튼 색",
@@ -53,46 +57,57 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "Identity 경로",
"Accounts_OAuth_Custom_Login_Style": "로그인 스타일",
+ "Accounts_OAuth_Custom_Merge_Users": "사용자 합치기",
+ "Accounts_OAuth_Custom_Scope": "범위",
"Accounts_OAuth_Custom_Secret": "비밀",
"Accounts_OAuth_Custom_Token_Path": "Token 경로",
- "Accounts_OAuth_Custom_Token_Sent_Via": "토큰 보낸 비아",
- "Accounts_OAuth_Facebook": "Facebook 로그인",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "보내진 토큰",
+ "Accounts_OAuth_Custom_Username_Field": "사용자 이름 필드",
+ "Accounts_OAuth_Drupal": "듀팔 로그인 이 활성화 되었습니다.",
+ "Accounts_OAuth_Drupal_callback_url": "듀팔 oAuth2 리다이렉트 URI",
+ "Accounts_OAuth_Drupal_id": "듀팔 oAuth2 클라이언트 ID",
+ "Accounts_OAuth_Drupal_secret": "듀팔 oAuth2 클라이언트 비밀번호",
+ "Accounts_OAuth_Facebook": "페이스북 로그인",
"Accounts_OAuth_Facebook_callback_url": "페이스 북 콜백 URL",
"Accounts_OAuth_Facebook_id": "Facebook 앱 ID",
"Accounts_OAuth_Facebook_secret": "Facebook 암호",
- "Accounts_OAuth_Github": "Github 로그인",
+ "Accounts_OAuth_Github": "OAuth 활성화",
"Accounts_OAuth_Github_callback_url": "GitHub의 콜백 URL",
"Accounts_OAuth_GitHub_Enterprise": "OAuth 활성화",
- "Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub의 기업 콜백 URL",
- "Accounts_OAuth_GitHub_Enterprise_id": "Client ID",
+ "Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub Enterprise 의 콜백 URL",
+ "Accounts_OAuth_GitHub_Enterprise_id": "Client 아이디",
"Accounts_OAuth_GitHub_Enterprise_secret": "Client 암호",
- "Accounts_OAuth_Github_id": "Github ID",
+ "Accounts_OAuth_Github_id": "Github 아이디",
"Accounts_OAuth_Github_secret": "Github 암호",
"Accounts_OAuth_Gitlab": "OAuth 활성화",
"Accounts_OAuth_Gitlab_callback_url": "GitLab 콜백 URL",
- "Accounts_OAuth_Gitlab_id": "GitLab ID",
+ "Accounts_OAuth_Gitlab_id": "GitLab 아이디",
"Accounts_OAuth_Gitlab_secret": "Client 암호",
"Accounts_OAuth_Google": "구글 로그인",
"Accounts_OAuth_Google_callback_url": "구글 콜백 URL",
- "Accounts_OAuth_Google_id": "구글 ID",
+ "Accounts_OAuth_Google_id": "구글 아이디",
"Accounts_OAuth_Google_secret": "구글 암호",
- "Accounts_OAuth_Linkedin": "LinkedIn 로그인",
+ "Accounts_OAuth_Linkedin": "링크드 인 로그인",
"Accounts_OAuth_Linkedin_callback_url": "링크드 인 콜백 URL",
- "Accounts_OAuth_Linkedin_id": "LinkedIn ID",
- "Accounts_OAuth_Linkedin_secret": "LinkedIn 암호",
+ "Accounts_OAuth_Linkedin_id": "링크드 인 아이디",
+ "Accounts_OAuth_Linkedin_secret": "링크드 인 암호",
"Accounts_OAuth_Meteor": "Meteor 로그인",
- "Accounts_OAuth_Meteor_callback_url": "유성 콜백 URL",
+ "Accounts_OAuth_Meteor_callback_url": "Meteor 콜백 URL",
"Accounts_OAuth_Meteor_id": "Meteor ID",
"Accounts_OAuth_Meteor_secret": "Meteor 암호",
+ "Accounts_OAuth_Proxy_host": "프록시 호스트",
+ "Accounts_OAuth_Proxy_services": "프록시 서비스",
"Accounts_OAuth_Twitter": "트위터 로그인",
"Accounts_OAuth_Twitter_callback_url": "트위터 콜백 URL",
- "Accounts_OAuth_Twitter_id": "트위터 ID",
+ "Accounts_OAuth_Twitter_id": "트위터 아이디",
"Accounts_OAuth_Twitter_secret": "트위터 암호",
- "Accounts_OAuth_Wordpress": "WordPress 로그인",
+ "Accounts_OAuth_Wordpress": "워드 프레스 로그인",
"Accounts_OAuth_Wordpress_callback_url": "워드 프레스 콜백 URL",
- "Accounts_OAuth_Wordpress_id": "WordPress ID",
- "Accounts_OAuth_Wordpress_secret": "WordPress 암호",
+ "Accounts_OAuth_Wordpress_id": "워드 프레스 아이디",
+ "Accounts_OAuth_Wordpress_secret": "워드 프레스 암호",
"Accounts_PasswordReset": "암호 재설정",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "인증서비스용 기본 역할",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "인증 서비스를 통해서 등록된 사용자는 기본 역할이 주어지게 됩니다.",
"Accounts_Registration_AuthenticationServices_Enabled": "인증 서비스에 등록",
"Accounts_RegistrationForm": "등록 양식",
"Accounts_RegistrationForm_Disabled": "비활성화",
@@ -100,61 +115,91 @@
"Accounts_RegistrationForm_Public": "공개",
"Accounts_RegistrationForm_Secret_URL": "비밀 URL",
"Accounts_RegistrationForm_SecretURL": "등록 양식 비밀 URL",
- "Accounts_RegistrationForm_SecretURL_Description": "당신은 당신의 등록 URL에 추가됩니다 임의의 문자열을 제공해야합니다. 예 : https://demo.rocket.chat/register/[secret_hash]",
- "Accounts_RequireNameForSignUp": "회원 가입은 이름 필요",
- "Accounts_ShowFormLogin": "보기 양식 기반 로그인",
- "Accounts_UseDefaultBlockedDomainsList": "기본값 사용 차단 된 도메인 목록",
- "Accounts_UseDNSDomainCheck": "DNS 도메인 확인을 사용하여",
- "Accounts_UserAddedEmail_Default": " 에 오신 것을 환영합니다 [Site_Name] [Site_URL]로 이동하여 오늘날 최고의 오픈 소스 채팅 솔루션을보십시오!
[email]과 비밀번호 : [password] 당신은 당신의 이메일을 사용하여 로그인 할 수 있습니다. 당신은 처음 로그인 후 변경해야 할 수 있습니다.",
- "Accounts_UserAddedEmail_Description": "다음과 같은 자리를 사용할 수 있습니다 :
각각 사용자의 전체 이름, 이름 또는 성을위한 [name], [fname], [lname]. 사용자의 이메일 [email]. 사용자의 비밀번호 [password]. [Site_Name]와 [Site_URL] 각각 응용 프로그램 이름 및 URL합니다. ",
- "Accounts_UserAddedEmailSubject_Default": "당신이 추가되었습니다 [Site_Name]",
+ "Accounts_RegistrationForm_SecretURL_Description": "등록 URL에 추가될 임의의 문자열을 제공해야 합니다. 예 : https://open.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "회원 가입을 위한 이름이 필요합니다.",
+ "Accounts_RequirePasswordConfirmation": "비밀번호 확인이 필요합니다.",
+ "Accounts_SetDefaultAvatar": "기본 아바타 설정",
+ "Accounts_SetDefaultAvatar_Description": "OAuth 계정이나 Gravatar 를 바탕으로 기본 아바타 설정을 시도합니다.",
+ "Accounts_ShowFormLogin": "폼방식 로그인 보기",
+ "Accounts_UseDefaultBlockedDomainsList": "기본 차단 도메인리스트 사용",
+ "Accounts_UseDNSDomainCheck": "DNS 도메인 확인 사용",
+ "Accounts_UserAddedEmail_Default": " [Site_Name] 에 오신 것을 환영합니다 \n [Site_URL] 로 이동하여 오늘날 최고의 오픈 소스 채팅 솔루션을 경험 해 보십시오!
\n 이메일:[email] 과 비밀번호 : [password] 로 로그인 할 수 있습니다. 로그인 후에는 변경하셔야 합니다.",
+ "Accounts_UserAddedEmail_Description": "다음의 기호를 사용할 수 있습니다:
[lname] - 성, [name] - 이름, [fname] - 전체이름(성+이름) [email] - 사용자 이메일 [password] - 사용자 암호 [Site_Name] - 응용프로그램의 이름, [Site_URL] - URL ",
+ "Accounts_UserAddedEmailSubject_Default": "당신이은 [Site_Name] 에 추가되었습니다",
"Activate": "활성화",
"Activity": "활동",
"Add": "추가",
- "Add_agent": "에이전트를 추가",
+ "Add_agent": "상담사 추가",
"Add_custom_oauth": "사용자 정의 OAuth 추가",
+ "Add_Domain": "도메인 추가",
"Add_manager": "관리자 추가",
"Add_user": "사용자 추가",
"Add_User": "사용자 추가",
"Add_users": "사용자 추가",
- "Adding_OAuth_Services": "OAuth는 서비스 추가",
- "Adding_permission": "권한을 추가",
- "Adding_user": "추가 사용자",
- "Additional_emails": "추가 E - 메일",
+ "Adding_OAuth_Services": "OAuth 서비스 추가",
+ "Adding_permission": "권한 추가",
+ "Adding_user": "사용자 추가",
+ "Additional_emails": "추가 이메일",
"Additional_Feedback": "추가 의견",
"Administration": "관리",
- "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "OAuth2를 인증 한 후, 사용자는이 URL로 리디렉션됩니다",
- "Agent_added": "에이전트는 추가",
- "Agent_removed": "에이전트 제거",
+ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Oauth2 인증후 사용자는 이 URL로 이동됩니다",
+ "Agent": "상담사",
+ "Agent_added": "상담사가 추가되었습니다",
+ "Agent_removed": "상담사가 삭제되었습니다",
"Alias": "별명",
+ "Alias_Format": "별명 형식",
+ "Alias_Format_Description": "앨리어스를 가지고 Slack 으로부터 메시지를 임포트 합니다.; %s 는 사용자의 username으로 대치됩니다, 비어있으면 앨리어스를 사용하지 않습니다.",
+ "Alias_Set": "별칭 설정",
"All": "모든",
"All_channels": "모든 채널",
"All_logs": "모든 로그",
"All_messages": "모든 메시지",
- "Allow_Invalid_SelfSigned_Certs": "잘못된 Self-Signed Certs 허용",
- "Allow_Invalid_SelfSigned_Certs_Description": "링크 확인 및 미리보기 무효 및 자체 서명 된 SSL 인증서의 허용.",
- "Analytics_features_enabled": "기능 활성화",
- "Analytics_features_messages_Description": "사용자가 메시지에 대해 수행 행동과 관련된 사용자 정의 이벤트를 추적합니다.",
- "Analytics_features_rooms_Description": "채널 또는 그룹 (삭제두고 작성)에 대한 작업에 관련된 사용자 정의 이벤트를 추적합니다.",
+ "Allow_Invalid_SelfSigned_Certs": "잘못된 자체서명 Certs 를 허용합니다",
+ "Allow_Invalid_SelfSigned_Certs_Description": "링크확인 과 프리뷰에 잘못된 자체서명 Certs 를 허용합니다.",
+ "Allow_switching_departments": "방문자가 부서를 변경할 수 있도록 허용합니다",
+ "Always_open_in_new_window": "항상 새창에서 열기",
+ "Analytics_features_enabled": "기능이 활성화 되었습니다",
+ "Analytics_features_messages_Description": "사용자의 메시지에 대해 수행 행동과 관련된 사용자 정의 이벤트를 추적합니다.",
+ "Analytics_features_rooms_Description": "채널 또는 그룹에 대한 작업에 관련된 사용자 정의 이벤트를 추적합니다. (생성, 채널나감, 삭제)",
"Analytics_features_users_Description": "사용자 (암호 재설정 시간, 프로필 사진 변경 등)에 관련 작업에 관련된 사용자 정의 이벤트를 추적합니다.",
+ "Analytics_Google": "구글 애널리틱스",
+ "Analytics_Google_id": "Tracking ID",
"and": "그리고",
- "And_more": "그리고 더 __length __",
+ "And_more": "그리고 __length __만큼 더",
"Animals_and_Nature": "동물과 자연",
+ "Announcement": "공지",
"API": "API",
- "API_Analytics": "분석",
- "API_Embed": "포함",
- "API_EmbedDisabledFor": "사용자에대한 Embed 비활성화",
+ "API_Allow_Infinite_Count": "모든것 허용",
+ "API_Allow_Infinite_Count_Description": "REST API 호출이 모든 내용을 하나의 호출에 리턴 할 수 있도록 할까요?",
+ "API_Analytics": "분석(에널리틱스)",
+ "API_CORS_Origin": "CORS Origin",
+ "API_Default_Count": "기본 카운트",
+ "API_Default_Count_Description": "아무것도 지정하지 않았을 때의 REST API 결과에 대한 기본 개수",
+ "API_Drupal_URL": "Drupal 서버 URL",
+ "API_Drupal_URL_Description": "예: https://domain.com (마지막의 슬레시 제외)",
+ "API_Embed": "링크 프리뷰 포함",
+ "API_Embed_Description": "사용자가 웹사이트에 대한 링크를 post 했을때에 그 링크 미리보기 기능의 포함 여부",
+ "API_EmbedCacheExpirationDays": "캐시 만료 날짜 Embed",
+ "API_EmbedDisabledFor": "사용자에 대한 Embed 비활성화",
"API_EmbedDisabledFor_Description": "쉼표로 구분된 사용자 이름 목록",
- "API_EmbedIgnoredHosts": "포함 무시 호스트",
- "API_EmbedIgnoredHosts_Description": "예를 들어, 호스트 또는 CIDR 주소의 목록을 쉼표로 구분. 로컬 호스트, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
+ "API_EmbedIgnoredHosts": "무시되어진 호스트 Embed",
+ "API_EmbedIgnoredHosts_Description": "쉼표로 구분된 호스트 또는 CIDR 주소의 목록. 예. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "안전 포트",
- "API_EmbedSafePorts_Description": "미리보기 허용 포트 목록을 쉼표로 구분.",
+ "API_EmbedSafePorts_Description": "쉼표로 구분된 미리보기를 위한 허용 포트 목록.",
+ "API_Enable_CORS": "CORS 활성화",
+ "API_Enable_Direct_Message_History_EndPoint": "Direct Message History Endpoint 활성화",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "소속되지 않은 다른 유저로 부터 보내진 다이렉트메시지를 보기를 허용하는 'api/v1/im.history.others' 를 활성화 합니다.",
+ "API_Enable_Shields": "쉴드 활성화",
+ "API_Enable_Shields_Description": "'/api/v1/shield.svg' 에 있는 쉴드를 활성화",
"API_GitHub_Enterprise_URL": "Server URL",
"API_GitHub_Enterprise_URL_Description": "예: http://domain.com (마지막 슬래시 제외)",
"API_Gitlab_URL": "GitLab URL",
+ "API_Shield_Types": "쉴드 타입",
+ "API_Shield_Types_Description": "쉴드의 종류",
"API_Token": "API 토큰",
+ "API_Upper_Count_Limit": "최대 레코드 수",
"API_User_Limit": "채널에 모든 사용자를 추가하는 사용자 제한",
- "API_Wordpress_URL": "WordPress URL",
+ "API_Wordpress_URL": "워드프레스 URL",
"Apiai_Key": "Api.ai 키",
"Apiai_Language": "Api.ai 언어",
"Appearance": "외관",
@@ -165,7 +210,7 @@
"Archive": "아카이브",
"are_also_typing": "또한 입력중",
"are_typing": "입력 중",
- "Are_you_sure": "괜찮아요?",
+ "Are_you_sure": "확실 합니까?",
"Are_you_sure_you_want_to_delete_your_account": "당신은 당신의 계정을 삭제 하시겠습니까?",
"at": "...에서",
"Auth_Token": "인증 토큰",
@@ -173,6 +218,7 @@
"Authorization_URL": "인증 URL",
"Authorize": "권한 부여",
"Auto_Load_Images": "이미지 자동 로드",
+ "Auto_Translate": "자동 번역",
"AutoLinker_Email": "AutoLinker 이메일",
"AutoLinker_Phone": "AutoLinker 전화",
"AutoLinker_Phone_Description": "자동으로 전화 번호를 연결. 예를 들어`(123) 456-7890`",
@@ -182,6 +228,9 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URL을",
"AutoLinker_Urls_www": "AutoLinker 'WWW'의 URL",
"AutoLinker_UrlsRegExp": "AutoLinker URL 정규 표현식",
+ "Automatic_Translation": "자동 번역",
+ "AutoTranslate_Enabled": "자동 번역 활성화",
+ "AutoTranslate_GoogleAPIKey": "구글 API 키",
"Available": "유효한",
"Available_agents": "사용 가능한 에이전트",
"Avatar": "아바타 변경",
@@ -195,13 +244,22 @@
"away_male": "자리비움",
"Away_male": "자리비움",
"Back": "뒤로",
- "Back_to_applications": "다시 응용 프로그램",
- "Back_to_integrations": "위로 통합에",
+ "Back_to_applications": "응용 프로그램으로 돌아가기",
+ "Back_to_integration_detail": "Integration detail 로 돌아가기",
+ "Back_to_integrations": "Integrations 로 돌아가기",
"Back_to_login": "로그인으로 돌아가기",
- "Back_to_permissions": "돌아 가기 권한",
- "Body": "신체",
+ "Back_to_permissions": "권한 으로 돌아가기",
+ "Backup_codes": "백업 코드",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "베타 기능. 활성화 될 비디오컨퍼런스 에 의존 함.",
+ "Block_User": "사용자 차단",
+ "Body": "본문",
"bold": "굵게",
+ "bot_request": "봇(bot) 요청",
+ "BotHelpers_userFields": "사용자 필드",
+ "BotHelpers_userFields_Description": "bots helper methods 가 접근할 수 있는 사용자 필드에 대한 CSV.",
"Branch": "분기",
+ "Broadcast_Connected_Instances": "연결된 인스턴스 제공(broadcast)",
+ "Bugsnag_api_key": "Bugsnag API 키",
"busy": "바쁨",
"Busy": "바쁨",
"busy_female": "바쁨",
@@ -209,9 +267,24 @@
"busy_male": "바쁨",
"Busy_male": "바쁨",
"by": "으로",
+ "cache_cleared": "캐시가 삭제됨",
"Cancel": "취소",
"Cancel_message_input": "취소",
- "Cannot_invite_users_to_direct_rooms": "객실을 지시하는 사용자를 초대 할 수 없습니다",
+ "Cannot_invite_users_to_direct_rooms": "direct room 으로 사용자를 초대할 수 없습니다.",
+ "CAS_autoclose": "로그인 팝업을 자동으로 닫음",
+ "CAS_base_url": "SSO Base URL",
+ "CAS_base_url_Description": "외부 SSO 서비스에 대한 base URL. 예: https://sso.example.undef/sso/",
+ "CAS_button_color": "로그인 버튼 배경 색상",
+ "CAS_button_label_color": "로그인 버튼 텍스트 색상",
+ "CAS_button_label_text": "로그인 버튼 레이블",
+ "CAS_enabled": "활성화 됨",
+ "CAS_Login_Layout": "CAS 로그인 Layout",
+ "CAS_login_url": "SSO 로그인 URL",
+ "CAS_login_url_Description": "외부 SSO 서비스에 대한 로그인 URL. 예: https://sso.example.undef/sso/login",
+ "CAS_popup_height": "로그인 팝업 높이",
+ "CAS_popup_width": "로그인 팝업 넓이",
+ "CAS_Sync_User_Data_Enabled": "항상 사용자 데이터 동기화",
+ "CAS_Sync_User_Data_Enabled_Description": "로그인 시 마다 외부 CAS 사용자 데이터 중 가능한 속성에 대해 항상 동기화. 주: 속성은 계정생성이 될때 마다 항상 동기화 됩니다.",
"CDN_PREFIX": "CDN Prefix",
"Certificates_and_Keys": "인증서와 키",
"Changing_email": "변경 이메일",
@@ -247,29 +320,57 @@
"Commands": "명령",
"Compact": "콤팩트",
"Confirm_password": "암호를 확인하세요",
+ "Content": "내용",
"Conversation": "대화",
- "Conversation_closed": "대화 폐쇄 : __comment__합니다.",
+ "Conversation_closed": "대화 종료 : __comment__.",
"Convert_Ascii_Emojis": "이모지를 ASCII로 변환",
- "Copied": "복사",
- "Copy": "부",
+ "Copied": "복사된",
+ "Copy": "복사",
"Copy_to_clipboard": "클립 보드에 복사",
"COPY_TO_CLIPBOARD": "클립 보드에 복사",
"Count": "카운트",
"Cozy": "편안한",
- "Create": "몹시 떠들어 대다",
+ "Create": "생성",
"Create_A_New_Channel": "새 채널 만들기",
"Create_new": "새로 만들기",
- "Created_at": "제작",
+ "Created_at": "만든",
"Created_at_s_by_s": " %s에 의해 %s로 만든",
+ "Created_at_s_by_s_triggered_by_s": "%s 에 트리거 된 %s 에 의해 %s 에 생성됨",
+ "CRM_Integration": "CRM Integration",
+ "CROWD_Reject_Unauthorized": "인증되지않은 것 거부",
"Current_Chats": "현재 채팅",
- "Custom": "관습",
+ "Current_Status": "현재 상태",
+ "Custom": "맞춤",
+ "Custom_Emoji": "사용자 정의 이모지",
+ "Custom_Emoji_Add": "새 이모지 추가",
+ "Custom_Emoji_Added_Successfully": "사용자 정의 이모자가 추가 되었습니다.",
+ "Custom_Emoji_Delete_Warning": "이모지 삭제는 복구 할 수 없습니다",
+ "Custom_Emoji_Error_Invalid_Emoji": "유효하지 않은 이모지",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "사용자 정의 이모지나 그 앨리어스가 이미 사용 중입니다.",
+ "Custom_Emoji_Has_Been_Deleted": "사용자 정의 이모지가 삭제 되었습니다.",
+ "Custom_Emoji_Info": "사용자 정의 이모지 정보",
+ "Custom_Emoji_Updated_Successfully": "사용자 정의 이모지가 성공적으로 업데이트 되었습니다",
"Custom_Fields": "사용자 정의 필드",
"Custom_oauth_helper": "OAuth Provider를 설정할때, 콜백 URL을 알려줘야합니다. %s 를 사용.",
- "Custom_oauth_unique_name": "사용자 정의 OAuth 고유한 이름",
- "Custom_Script_Logged_In": "사용자 정의 스크립트 로그인 한 사용자를 위해",
- "Custom_Script_Logged_Out": "사용자 정의 스크립트 로그 아웃 사용자를위한",
- "Dashboard": "계기반",
+ "Custom_oauth_unique_name": "사용자 정의 OAuth 고유 이름",
+ "Custom_Script_Logged_In": "로그인 한 사용자를 위한 사용자 정의 스크립트 ",
+ "Custom_Script_Logged_Out": "로그 아웃 사용자를 위한 사용자 정의 스크립트 ",
+ "Custom_Scripts": "사용자 정의 스크립트",
+ "Custom_Sound_Add": "사용자 정의 사운드 추가",
+ "Custom_Sound_Delete_Warning": "사운드 삭제는 복구 할 수 없습니다.",
+ "Custom_Sound_Error_Invalid_Sound": "잘못된 사운드",
+ "Custom_Sound_Error_Name_Already_In_Use": "사용자 정의 사운드 이름이 이미 사용중입니다.",
+ "Custom_Sound_Has_Been_Deleted": "사용자 정의 사운드가 삭제되었습니다.",
+ "Custom_Sound_Info": "사용자 정의 사운드 정보",
+ "Custom_Sound_Saved_Successfully": "사용자 정의 사운드가 성공적으로 저장 되었습니다",
+ "Custom_Sounds": "사용자 정의 사운드",
+ "Custom_Translations": "사용자 정의 번역(해석)",
+ "Custom_Translations_Description": " Key는 Key와 번역의 딕셔너리가 포함된 언어 인 유효한 JSON 이어야 합니다. 예:{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n}",
+ "CustomSoundsFilesystem": "사용자 정의 사운드 파일시스템",
+ "Dashboard": "대시보드",
"Date": "날짜",
+ "Date_From": "발신",
+ "Date_to": "수신",
"days": "일",
"DB_Migration": "데이터베이스 마이그레이션",
"DB_Migration_Date": "데이터베이스 마이그레이션 날짜",
@@ -341,14 +442,14 @@
"Error": "오류",
"error-action-not-allowed": "__action__ 허용되지 않습니다",
"error-application-not-found": "응용 프로그램을 찾을 수 없습니다",
- "error-archived-duplicate-name": "이름이 '__room_name__'에 보관 된 채널이있다",
+ "error-archived-duplicate-name": "보관된 '__room_name__' 채널이 있습니다.",
"error-avatar-invalid-url": "잘못된 아바타 URL : __url__",
- "error-avatar-url-handling": "오류 __ 사용자 이름 __에 대한 URL (__url__)에서 아바타 설정을 처리하는 동안",
- "error-cant-invite-for-direct-room": "직접 객실에 대한 사용자를 초대 할 수 없습니다",
+ "error-avatar-url-handling": " __ username__에 대한 URL (__url__)에서 아바타 설정을 처리하는 동안 오류발생",
+ "error-cant-invite-for-direct-room": "direct room 으로 사용자를 초대할 수 없습니다.",
"error-could-not-change-email": "이메일을 변경할 수 없습니다",
"error-could-not-change-name": "이름을 변경할 수 없습니다",
"error-could-not-change-username": "사용자 이름을 변경할 수 없습니다",
- "error-delete-protected-role": "보호 역할을 삭제할 수 없습니다",
+ "error-delete-protected-role": "보호된 역할을 삭제할 수 없습니다",
"error-department-not-found": "부서를 찾을 수 없습니다",
"error-duplicate-channel-name": "'%s' 채널 이름은 이미 존재합니다.",
"error-email-domain-blacklisted": "이메일 도메인이 블랙리스트",
@@ -396,7 +497,7 @@
"error-not-allowed": "허용되지 않음",
"error-not-authorized": "권한이 없습니다",
"error-push-disabled": "푸시을 사용할 수 없습니다",
- "error-remove-last-owner": "이 마지막 소유자입니다. 이 중 하나를 제거하기 전에 새 소유자를 설정하십시오.",
+ "error-remove-last-owner": "마지막 소유자입니다. 제거하기 전에 새 소유자를 설정하십시오.",
"error-role-in-use": "그것이 사용 때문에 역할을 삭제할 수 없습니다",
"error-role-name-required": "역할 이름이 필요합니다",
"error-the-field-is-required": "필드 __field__이 필요합니다.",
@@ -544,7 +645,7 @@
"Join_video_call": "화상 통화에 참여",
"Joined": "가입",
"Jump": "도약",
- "Jump_to_first_unread": "첫 번째 읽지로 이동",
+ "Jump_to_first_unread": "읽지않은 첫 메시지로 이동",
"Jump_to_message": "메시지로 이동",
"Jump_to_recent_messages": "최근 메시지에 점프",
"Katex_Dollar_Syntax": "허용 달러 구문",
@@ -570,24 +671,12 @@
"Layout_Terms_of_Service": "이용약관",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA 쿠폰",
- "LDAP_Custom_Domain_Search": "맞춤 도메인 검색",
- "LDAP_Custom_Domain_Search_Description": "바인딩 및 연결 정보를 지배하고 양식입니다 JSON의 조각 : {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "기본 도메인",
"LDAP_Description": "LDAP는 많은 기업들이 통합 인증을 제공하기 위해 사용하는 계층적인 데이터베이스입니다. 여러 사이트와 서비스 간에 하나의 암호를 공유하기 위한 기능으로, 자세한 정보는 위키를 참고하세요: https://github.com/RocketChat/Rocket.Chat/wiki/LDAP",
- "LDAP_Domain_Base": "도메인 자료",
- "LDAP_Domain_Base_Description": "사용자와 그룹을 검색하려는 LDAP 하위 트리의 완전한 고유 이름 (DN). 당신은 당신이 원하는만큼 추가 할 수 있습니다; 그러나, 각각의 그룹은 그것이 속하는 사용자와 동일한 도메인베이스에 정의되어야한다. 당신이 제한된 사용자 그룹을 지정하면 해당 그룹에 속한 사용자 만 범위에있을 것입니다. 우리는 당신이 도메인베이스로 LDAP 디렉토리 트리의 최상위 레벨을 지정하고 액세스를 제어하는 검색 필터를 사용하는 것이 좋습니다.",
- "LDAP_Domain_Search_Filter": "도메인 검색 필터",
- "LDAP_Domain_Search_Filter_Description": "이 필터와 일치하는 지정된 사용자 만이 로그인 할 수 할 경우에는 필터가 지정되지 않은 경우. 지정된 도메인베이스의 범위 내에서 모든 사용자가 로그인 할 수 있습니다. Active Directory에 대한 예`의 memberOf = CN = ROCKET_CHAT, OU = 일반 Groups`. OpenLDAP를위한 예 (확장 일치 검색)`OU : DN = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "도메인 검색 개체 카테고리",
- "LDAP_Domain_Search_Object_Category_Description": "사용자를 식별 *의 수 objectcategory의 *. *의 OpenLDAP를 * 빈 둡니다. 예를 들어`person` 등",
- "LDAP_Domain_Search_Object_Class": "도메인 검색 객체 클래스",
- "LDAP_Domain_Search_Object_Class_Description": "사용자를 식별 * 객체 클래스의 *. 예를 들어`organizationalPerson`,`user`,`inetOrgPerson` 등",
- "LDAP_Domain_Search_Password": "도메인 검색 비밀",
- "LDAP_Domain_Search_Password_Description": "도메인 검색 사용자의 암호입니다.",
- "LDAP_Domain_Search_User": "도메인 검색 사용",
- "LDAP_Domain_Search_User_Description": "가 로그인 할 때 다른 사용자를 인증하는 사용자 조회를 수행하는 LDAP 사용자입니다. 이것은 일반적으로 타사 통합을 위해 특별히 만든 서비스 계정입니다. 정규화 된 이름을 사용, 같은 CN = 관리자 '로, CN 사용자, DC = 예, DC = com`을 =.",
- "LDAP_Domain_Search_User_ID": "도메인 검색 사용자 ID",
- "LDAP_Domain_Search_User_ID_Description": "인증을 시도하는 LDAP 사용자를 식별하는 LDAP 속성입니다. 이 필드는`대부분의 Active Directory 설치를위한 sAMAccountName`해야하지만, 그러한 OpenLDAP를 다른 LDAP 솔루션에 대한`uid` 수있다. 당신은 이메일이나 어떤 속성 당신이 원하는하여 사용자를 식별하기 위해`mail`를 사용할 수 있습니다. 당신은 사용자가 사용자 이름 또는 이메일 등 여러 ID를 사용하여 로그인 할 수 있도록 쉼표로 구분하여 여러 값을 사용할 수 있습니다.",
+ "LDAP_BaseDN_Description": "사용자와 그룹을 검색하려는 LDAP 하위 트리의 완전한 고유 이름 (DN). 당신은 당신이 원하는만큼 추가 할 수 있습니다; 그러나, 각각의 그룹은 그것이 속하는 사용자와 동일한 도메인베이스에 정의되어야한다. 당신이 제한된 사용자 그룹을 지정하면 해당 그룹에 속한 사용자 만 범위에있을 것입니다. 우리는 당신이 도메인베이스로 LDAP 디렉토리 트리의 최상위 레벨을 지정하고 액세스를 제어하는 검색 필터를 사용하는 것이 좋습니다.",
+ "LDAP_User_Search_Field_Description": "인증을 시도하는 LDAP 사용자를 식별하는 LDAP 속성입니다. 이 필드는`대부분의 Active Directory 설치를위한 sAMAccountName`해야하지만, 그러한 OpenLDAP를 다른 LDAP 솔루션에 대한`uid` 수있다. 당신은 이메일이나 어떤 속성 당신이 원하는하여 사용자를 식별하기 위해`mail`를 사용할 수 있습니다. 당신은 사용자가 사용자 이름 또는 이메일 등 여러 ID를 사용하여 로그인 할 수 있도록 쉼표로 구분하여 여러 값을 사용할 수 있습니다.",
+ "LDAP_User_Search_Filter_Description": "이 필터와 일치하는 지정된 사용자 만이 로그인 할 수 할 경우에는 필터가 지정되지 않은 경우. 지정된 도메인베이스의 범위 내에서 모든 사용자가 로그인 할 수 있습니다. Active Directory에 대한 예`의 memberOf = CN = ROCKET_CHAT, OU = 일반 Groups`. OpenLDAP를위한 예 (확장 일치 검색)`OU : DN = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "가 로그인 할 때 다른 사용자를 인증하는 사용자 조회를 수행하는 LDAP 사용자입니다. 이것은 일반적으로 타사 통합을 위해 특별히 만든 서비스 계정입니다. 정규화 된 이름을 사용, 같은 CN = 관리자 '로, CN 사용자, DC = 예, DC = com`을 =.",
"LDAP_Enable": "LDAP 사용",
"LDAP_Enable_Description": "인증을 위해 LDAP를 사용하려고합니다.",
"LDAP_Encryption": "암호화",
@@ -602,12 +691,9 @@
"LDAP_Sync_User_Data_Description": "서버에 로그인할 때 사용자 데이터의 동기화를 유지하세요(예: 이름, 이메일).",
"LDAP_Sync_User_Data_FieldMap": "사용자 데이터 필드 맵",
"LDAP_Sync_User_Data_FieldMap_Description": "사용자 계정 필드 (이메일 등) LDAP의 레코드에서 채워집니다 방법을 구성 (한 번 발견). 예를 들어,`{ \"CN은\": \"이름\", \"메일\": \"이메일\"}`cn 속성에서 사람의 사람이 읽을 수있는 이름, 메일 속성에서 이메일을 선택합니다. 사용 가능한 필드는 name`, 그리고`email``등이 있습니다.",
- "LDAP_Sync_Users": "동기화 사용자",
"LDAP_Test_Connection": "연결 테스트",
"LDAP_Unique_Identifier_Field": "고유 식별자 필드",
"LDAP_Unique_Identifier_Field_Description": "어떤 필드는 LDAP 사용자와 Rocket.Chat 사용자를 연결하는 데 사용됩니다. 당신은 LDAP 레코드에서 값을 얻기 위해 시도하는 쉼표로 구분하여 여러 값을 알릴 수 있습니다. 기본값은 '의 objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueid도, uidNumber`입니다",
- "LDAP_Use_Custom_Domain_Search": "맞춤 도메인 검색을 사용하여",
- "LDAP_Use_Custom_Domain_Search_Description": "LDAP 서버에서 사용자를 검색 할 자신의 필터를 작성합니다.",
"LDAP_Username_Field": "사용자 이름 필드",
"LDAP_Username_Field_Description": "어떤 분야는 새로운 사용자를위한 * 사용자 이름 *으로 사용됩니다. 로그인 페이지에서 정보를 사용자 이름을 사용하는 빈 둡니다. 당신은 # {givenName으로}`처럼, 너무 템플릿 태그를 사용할 수 있습니다. # {SN}`. 기본값은`sAMAccountName`입니다.",
"Leave_Group_Warning": "당신은 당신이 그룹 \" %s을 (를)\"에서 탈퇴 하시겠습니까?",
@@ -1043,19 +1129,19 @@
"The_user_wont_be_able_to_type_in_s": "사용자는 %s에 입력 할 수 없습니다",
"Theme": "테마",
"theme-color-content-background-color": "콘텐츠 배경색",
+ "theme-color-custom-scrollbar-color": "사용자 지정 스크롤 막대 색상",
+ "theme-color-info-font-color": "글자 색상 정보",
+ "theme-color-link-font-color": "링크 글꼴 색상",
"theme-color-primary-background-color": "기본 배경색",
"theme-color-primary-font-color": "기본 글자 색상",
"theme-color-secondary-background-color": "보조 배경색",
"theme-color-secondary-font-color": "보조 글자 색상",
- "theme-color-tertiary-background-color": "차 배경 색상",
- "theme-color-tertiary-font-color": "차 글꼴 색상",
- "theme-color-link-font-color": "링크 글꼴 색상",
- "theme-color-info-font-color": "글자 색상 정보",
- "theme-color-custom-scrollbar-color": "사용자 지정 스크롤 막대 색상",
"theme-color-status-away": "자리비움 상태 색상",
"theme-color-status-busy": "바쁨 상태 색상",
"theme-color-status-offline": "보지않음 상태 색상",
"theme-color-status-online": "온라인 상태 색상",
+ "theme-color-tertiary-background-color": "차 배경 색상",
+ "theme-color-tertiary-font-color": "차 글꼴 색상",
"theme-color-unread-notification-color": "읽지 않은 알림 색상",
"theme-custom-css": "사용자 정의 CSS",
"There_are_no_agents_added_to_this_department_yet": "아직이 부서에 추가에는 에이전트가 없습니다.",
@@ -1226,4 +1312,4 @@
"Your_mail_was_sent_to_s": "메일은 %s의 전송되었습니다",
"Your_password_is_wrong": "암호가 잘못되었습니다!",
"Your_push_was_sent_to_s_devices": "귀하의 푸시는 %의 기기에 전송"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ku.i18n.json b/packages/rocketchat-i18n/i18n/ku.i18n.json
index ac6d31aede773..3ba4638ec8583 100644
--- a/packages/rocketchat-i18n/i18n/ku.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ku.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Destûrê bide User Profile Change",
"Accounts_AvatarResize": "resize Avatars",
"Accounts_AvatarSize": "Avatar Size",
- "Accounts_AvatarStorePath": "Path Avatar Storage",
- "Accounts_AvatarStoreType": "Avatar Type Storage",
"Accounts_BlockedDomainsList": "Astengkirin Lîsteya Domain",
"Accounts_BlockedDomainsList_Description": "lîsteya bêhnok-cuda ji qada astengkirin",
"Accounts_BlockedUsernameList": "Astengkirin Lîsteya Username",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "Verification E-mail",
"Accounts_EmailVerification_Description": "Piştrast tu settings SMTP correct ji bo bikaranîna vê funksîyonê",
"Accounts_Enrollment_Email": "Kînge E-mail",
- "Accounts_Enrollment_Email_Default": " bi xêr bên [Site_Name] Go to [Site_URL] û hewl baştirîn çareserî chat çavkaniya vekirî ya îro tune!
",
+ "Accounts_Enrollment_Email_Default": " bi xêr bên [Site_Name] Go to [Site_URL] û hewl baştirîn çareserî chat çavkaniya vekirî ya îro tune!
",
"Accounts_Enrollment_Email_Description": "Dibe ku tu [name], [fname] ji bo navê bikarhêner, nav an paşnav, bi rêzê ve bi kar tînin, [lname]. Dibe ku tu [email] ji bo email bikarhêner bi kar tînin.",
"Accounts_Enrollment_Email_Subject_Default": "Bi xêr hatî [Site_Name]",
"Accounts_Iframe_api_method": "Method Api",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Login",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress Callback",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress Callback",
"Accounts_OAuth_Wordpress_id": "Id WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Şîfreyê nû bike",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "Alenî",
"Accounts_RegistrationForm_Secret_URL": "URL Secret",
"Accounts_RegistrationForm_SecretURL": "Formê Qeydkirina Secret URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Divê tu string random ku wê bê URL xwe qeyd added ne. Mînak: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Divê tu string random ku wê bê URL xwe qeyd added ne. Mînak: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Hewce Name Ji bo Signup",
"Accounts_ShowFormLogin": "Login-bingeha forma nîşan",
"Accounts_UseDefaultBlockedDomainsList": "Use Default astengkirin Lîsteya Domain",
"Accounts_UseDNSDomainCheck": "Bi kar bîne Check DNS Domain",
- "Accounts_UserAddedEmail_Default": " bi xêr bên [Site_Name] Go to [Site_URL] û hewl baştirîn çareserî chat çavkaniya vekirî ya îro tune!
[email] û şîfreya:: [password] Hûn dikarin bi bikaranîna email te (login). Te pêwîst be ji bo ku ew piştî yekem login xwe biguherînî.",
+ "Accounts_UserAddedEmail_Default": "
bi xêr bên [Site_Name] Go to [Site_URL] û hewl baştirîn çareserî chat çavkaniya vekirî ya îro tune!
[email] û şîfreya:: [password] Hûn dikarin bi bikaranîna email te (login). Te pêwîst be ji bo ku ew piştî yekem login xwe biguherînî.",
"Accounts_UserAddedEmail_Description": "Dibe ku divê tu guhêrbaran li jêr bi kar tînin:
[name], [fname], [lname] ji bo navê bikarhêner full, nav an paşnav, bi rêzê ve. [email] ji bo email bikarhêner. [password] ji bo şîfreya bikarhêner. [Site_Name] û [Site_URL] ji bo Name Application û URL rêzê. ",
"Accounts_UserAddedEmailSubject_Default": "Hûn hatine zêdekirin [Site_Name]",
"Activate": "de çalak bike",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Terms of Service",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Search Custom Domain",
- "LDAP_Custom_Domain_Search_Description": "A perçek ji JSON ku rê bind û girêdana info e û yên ku forma: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Default Domain",
"LDAP_Description": "hesanîyekî ji bo parvekirina yek nasnavê di navbera sites û xizmetên piralî - LDAP a nav HTMLê da heye hiyerarşîk ku gelek kompaniyên bi kar ji bo ne yek nîşanek li ser e. https://rocket.chat/docs/administrator-guides/authentication/ldap/: Ji bo agahiyên Mîhengên pêşketî û wergerandî, ji kerema xwe ve wiki me bişêwirin.",
- "LDAP_Domain_Base": "Base Domain",
- "LDAP_Domain_Base_Description": "The Name bi temamî bi kalîte Hêja (DN) ya subtree LDAP hûn jî dixwazin ku ji bo lêgerîna bikarhênerên û komên. Hûn dikarin wek gelek wek ku hûn dixwazin lê zêde bike; Lê belê, her kom, divê li ser bingeha domain eynî wek ku bikarhênerên ku ji bo ev were terîf kirin. Ger tu komên user dibî diyar bike, tenê bikarhênerên ku endamên wan koman dê di çarçoveya be. Em tewsiye dikin ku tu di asta herî bilind de ji LDAP dara pêristeke xwe diyar bike, wek bingeha Domaina xwe û bi kar tînin Parzûna lêgerîn ji bo kontrolkirina access.",
- "LDAP_Domain_Search_Filter": "Domain Search Filter",
- "LDAP_Domain_Search_Filter_Description": "Ger diyarkirin, tenê bikarhênerên ku lihevhatina bi vî Parzûna bê destûr dê têkevim. Heke tu Parzûna dîyarkirin, hemû bikarhêneran di çarçoveya bingeha domain xwe bişinî dê karibin bi îmza li bin. Mînak: ji bo Active Directory `memberOf = cn = ROCKET_CHAT, ou = Giştî Groups`. Mînak: ji bo OpenLDAP (search match Extensible) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Kategorî",
- "LDAP_Domain_Search_Object_Category_Description": "The * objectCategory * ku bikarhênerên xwe. Vala bihêlin ji bo * OpenLDAP *. Eg `person`, û hwd.",
- "LDAP_Domain_Search_Object_Class": "Domain Class Search Object",
- "LDAP_Domain_Search_Object_Class_Description": "The * objectclass * ku bikarhênerên xwe. Eg `organizationalPerson`,` user`, `inetOrgPerson`, û hwd.",
- "LDAP_Domain_Search_Password": "Domain Search Password",
- "LDAP_Domain_Search_Password_Description": "The şîfreya bikarhêner ji bo search domain.",
- "LDAP_Domain_Search_User": "Domain Search Bikarhêner",
- "LDAP_Domain_Search_User_Description": "The user LDAP ku performs Lookups user piştrastkirin bikarhênerên din, gava ku ew sign in. Ev account xizmeta bi taybetî ji bo integrations third-party tên afirandin e, bêhtirê. Bi kar tînin a name bi temamî bi kalîte, wek `cn = Administrator, cn = Bikarhêner, dc = mînak, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search ID'ya bikarhêner",
- "LDAP_Domain_Search_User_ID_Description": "Çawaniya LDAP ku tê nasîn user LDAP ku hewldanên di naskirinê. Vî warî de divê `be sAMAccountName` ji bo avahîyên herî çalak Directory, lê dibe ku` uid` bo din çareseriyên LDAP, wek OpenLDAP. Tu dikarî `mail` ji bo diyarkirina by email an jî her tiştê ku wesf û tu dixwazî bi kar tînin. Tu dikarî nirxên multiple ji hev veqetîne de bêhnok bête bi rê bikarhênerên têkevim bikaranîna identifiers multiple wek bikarhêner an jî email bi kar tînin.",
+ "LDAP_BaseDN_Description": "The Name bi temamî bi kalîte Hêja (DN) ya subtree LDAP hûn jî dixwazin ku ji bo lêgerîna bikarhênerên û komên. Hûn dikarin wek gelek wek ku hûn dixwazin lê zêde bike; Lê belê, her kom, divê li ser bingeha domain eynî wek ku bikarhênerên ku ji bo ev were terîf kirin. Ger tu komên user dibî diyar bike, tenê bikarhênerên ku endamên wan koman dê di çarçoveya be. Em tewsiye dikin ku tu di asta herî bilind de ji LDAP dara pêristeke xwe diyar bike, wek bingeha Domaina xwe û bi kar tînin Parzûna lêgerîn ji bo kontrolkirina access.",
+ "LDAP_User_Search_Field_Description": "Çawaniya LDAP ku tê nasîn user LDAP ku hewldanên di naskirinê. Vî warî de divê `be sAMAccountName` ji bo avahîyên herî çalak Directory, lê dibe ku` uid` bo din çareseriyên LDAP, wek OpenLDAP. Tu dikarî `mail` ji bo diyarkirina by email an jî her tiştê ku wesf û tu dixwazî bi kar tînin. Tu dikarî nirxên multiple ji hev veqetîne de bêhnok bête bi rê bikarhênerên têkevim bikaranîna identifiers multiple wek bikarhêner an jî email bi kar tînin.",
+ "LDAP_User_Search_Filter_Description": "Ger diyarkirin, tenê bikarhênerên ku lihevhatina bi vî Parzûna bê destûr dê têkevim. Heke tu Parzûna dîyarkirin, hemû bikarhêneran di çarçoveya bingeha domain xwe bişinî dê karibin bi îmza li bin. Mînak: ji bo Active Directory `memberOf = cn = ROCKET_CHAT, ou = Giştî Groups`. Mînak: ji bo OpenLDAP (search match Extensible) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "The user LDAP ku performs Lookups user piştrastkirin bikarhênerên din, gava ku ew sign in. Ev account xizmeta bi taybetî ji bo integrations third-party tên afirandin e, bêhtirê. Bi kar tînin a name bi temamî bi kalîte, wek `cn = Administrator, cn = Bikarhêner, dc = mînak, dc = com`.",
"LDAP_Enable": "Bikêrkirin",
"LDAP_Enable_Description": "Hewldana ji bo dozeke LDAP bo piştrastkirinê.",
"LDAP_Encryption": "Şîfrekirin,",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Keep welat user di synchê bi server li ser login (wek nimûne: name, email).",
"LDAP_Sync_User_Data_FieldMap": "Bikarhêner Data Map Field",
"LDAP_Sync_User_Data_FieldMap_Description": "Mîheng bikî ka zeviyên Hesabê bikarhêner (wek email) bi ji qeyda li LDAP dijîn (cih). Wek nimûne, `{\" cn \":\" name \",\" mail \":\" email \"}` ê bi navê mirovekî mirovan xwendin ji bikarbar cn, û email xwe ji taybetiyê mail hilbijêre. zeviyên Available de `name`, û` email`.",
- "LDAP_Sync_Users": "Bikarhêner li ser Syncê",
"LDAP_Test_Connection": "Connection test",
"LDAP_Unique_Identifier_Field": "Krom Field",
"LDAP_Unique_Identifier_Field_Description": "Ku qada wê were bikaranîn berve bikarhênerê LDAP û user Rocket.Chat de. Tu dikarî nirxên multiple ji hev veqetîne de bêhnok agahdar to try to get nirxa ku ji qeyda LDAP. nirxa standard e `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Bi kar tînin Custom Search Domain",
- "LDAP_Use_Custom_Domain_Search_Description": "Hewe Parzûna xwe bi xwe ji bo bikarhênerên lêgerîn li server LDAP de.",
"LDAP_Username_Field": "Username Field",
"LDAP_Username_Field_Description": "Ku qada wê bên * username * ji bo bikarhênerên nû de tê bikaranîn. Dev ji vala bi kar username agahdar li ser rûpela têketinê. Tu dikarî tags şablonê pêk hatiye jî bi kar tînin, wek `#{givenName}.#{sn}`. nirxa standard e `sAMAccountName`.",
"Leave_Group_Warning": "Ma tu dizanî, tu dixwazî ji koma \" %s\" ku herin?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "The user bi wê bikaribin kes li %s",
"Theme": "Mijad",
"theme-color-content-background-color": "Content Color Background",
+ "theme-color-custom-scrollbar-color": "Custom scrollbar Color",
+ "theme-color-info-font-color": "Info Font Color",
+ "theme-color-link-font-color": "Link Font Color",
"theme-color-primary-background-color": "Primary Color Background",
"theme-color-primary-font-color": "Primary Font Color",
"theme-color-secondary-background-color": "Navîn Color Background",
"theme-color-secondary-font-color": "Navîn Font Color",
- "theme-color-tertiary-background-color": "Kirmashan Color Background",
- "theme-color-tertiary-font-color": "Kirmashan Font Color",
- "theme-color-link-font-color": "Link Font Color",
- "theme-color-info-font-color": "Info Font Color",
- "theme-color-custom-scrollbar-color": "Custom scrollbar Color",
"theme-color-status-away": "Rewş Away Color",
"theme-color-status-busy": "Rewş Mijûl Color",
"theme-color-status-offline": "Rewş is Color",
"theme-color-status-online": "Bike Status Color",
+ "theme-color-tertiary-background-color": "Kirmashan Color Background",
+ "theme-color-tertiary-font-color": "Kirmashan Font Color",
"theme-color-unread-notification-color": "Unread Notifications Color",
"theme-custom-css": "CSS Custom",
"There_are_no_agents_added_to_this_department_yet": "are no ajanên added ji bo vê beşê yet hene.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "nameya te ji bo %s hate şandin",
"Your_password_is_wrong": "Te şîfreya xwe ji xelet e!",
"Your_push_was_sent_to_s_devices": "push xwe ji bo cîhazên %s hate şandin"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/lo.i18n.json b/packages/rocketchat-i18n/i18n/lo.i18n.json
index 6c71bb90512df..51ed887697631 100644
--- a/packages/rocketchat-i18n/i18n/lo.i18n.json
+++ b/packages/rocketchat-i18n/i18n/lo.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "ອະນຸຍາດໃຫ້ການປ່ຽນແປງຂໍ້ມູນຂອງຜູ້ໃຊ້",
"Accounts_AvatarResize": "ປັບຂະຫນາດນົດ",
"Accounts_AvatarSize": "Avatar ຂະຫນາດ",
- "Accounts_AvatarStorePath": "ເສັ້ນທາງກ້າວສູ່ຮູບສ່ວນຕົວການເກັບຮັກສາ",
- "Accounts_AvatarStoreType": "Avatar ປະເພດການເກັບຮັກສາ",
"Accounts_BlockedDomainsList": "ສະກັດຊີ Domains",
"Accounts_BlockedDomainsList_Description": "ບັນຊີລາຍຊື່ຈຸດ, ແຍກຂອງໂດເມນກັດ",
"Accounts_BlockedUsernameList": "ບັນຊີ Username ກັດ",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "ການກວດສອບອີເມລ໌",
"Accounts_EmailVerification_Description": "ເຮັດໃຫ້ແນ່ໃຈວ່າທ່ານມີການຕັ້ງຄ່າ SMTP ທີ່ຖືກຕ້ອງທີ່ຈະນໍາໃຊ້ຄຸນນະສົມບັດນີ້",
"Accounts_Enrollment_Email": "ການລົງທະບຽນ E-mail",
- "Accounts_Enrollment_Email_Default": " ຍິນດີຕ້ອນຮັບສູ່ [Site_Name] ໄປທີ່ [Site_URL] ແລະພະຍາຍາມມາເປີດການແກ້ໄຂທີ່ດີທີ່ສຸດສົນທະຢູ່ໃນມື້ນີ້!
",
+ "Accounts_Enrollment_Email_Default": " ຍິນດີຕ້ອນຮັບສູ່ [Site_Name] ໄປທີ່ [Site_URL] ແລະພະຍາຍາມມາເປີດການແກ້ໄຂທີ່ດີທີ່ສຸດສົນທະຢູ່ໃນມື້ນີ້!
",
"Accounts_Enrollment_Email_Description": "ທ່ານອາດຈະນໍາໃຊ້ [name], [fname], [lname] ສໍາລັບຊື່ເຕັມຂອງຜູ້ໃຊ້ໄດ້, ຊື່ທໍາອິດຫຼືຊື່ສຸດທ້າຍ, ຕາມລໍາດັບ. ທ່ານອາດຈະນໍາໃຊ້ [email] ສໍາລັບອີເມລຂອງຜູ້ໃຊ້ໄດ້.",
"Accounts_Enrollment_Email_Subject_Default": "ຍິນດີຕ້ອນຮັບ [Site_Name]",
"Accounts_Iframe_api_method": "ວິທີການ Api",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Id Twitter",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress ເຂົ້າສູ່ລະບົບ",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress ໂທກັບ",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress ໂທກັບ",
"Accounts_OAuth_Wordpress_id": "Id WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "ຕັ້ງຄ່າລະຫັດຜ່ານ",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "ສາທາລະນະ",
"Accounts_RegistrationForm_Secret_URL": "URL Secret",
"Accounts_RegistrationForm_SecretURL": "ການລົງທະບຽນແບບຟອມ URL Secret",
- "Accounts_RegistrationForm_SecretURL_Description": "ທ່ານຕ້ອງໄດ້ສະຫນອງການຊ່ອຍແນ່ໄປທີ່ຈະໄດ້ຮັບການເພີ່ມ URL ລົງທະບຽນຂອງທ່ານ. ຍົກຕົວຢ່າງ: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "ທ່ານຕ້ອງໄດ້ສະຫນອງການຊ່ອຍແນ່ໄປທີ່ຈະໄດ້ຮັບການເພີ່ມ URL ລົງທະບຽນຂອງທ່ານ. ຍົກຕົວຢ່າງ: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "ຮຽກຮ້ອງໃຫ້ຊື່ສໍາລັບສະຫມັກ",
"Accounts_ShowFormLogin": "ສະແດງໃຫ້ເຫັນຮູບແບບທີ່ເຂົ້າສູ່ລະບົບ",
"Accounts_UseDefaultBlockedDomainsList": "ການນໍາໃຊ້ມາດຕະຖານສະກັດຊີ Domains",
"Accounts_UseDNSDomainCheck": "ການນໍາໃຊ້ Check DNS ໂດເມນ",
- "Accounts_UserAddedEmail_Default": " ຍິນດີຕ້ອນຮັບສູ່ [Site_Name] ໄປທີ່ [Site_URL] ແລະພະຍາຍາມມາເປີດການແກ້ໄຂທີ່ດີທີ່ສຸດສົນທະຢູ່ໃນມື້ນີ້!
ທ່ານອາດຈະເຂົ້າສູ່ລະບົບການນໍາໃຊ້ອີເມວຂອງທ່ານ: [email] ແລະລະຫັດຜ່ານ: [password]. ທ່ານອາດຈະຖືກຮຽກຮ້ອງໃຫ້ມີການປ່ຽນແປງມັນຫຼັງຈາກເຂົ້າສູ່ລະບົບຄັ້ງທໍາອິດຂອງທ່ານ.",
+ "Accounts_UserAddedEmail_Default": "
ຍິນດີຕ້ອນຮັບສູ່ [Site_Name] ໄປທີ່ [Site_URL] ແລະພະຍາຍາມມາເປີດການແກ້ໄຂທີ່ດີທີ່ສຸດສົນທະຢູ່ໃນມື້ນີ້!
ທ່ານອາດຈະເຂົ້າສູ່ລະບົບການນໍາໃຊ້ອີເມວຂອງທ່ານ: [email] ແລະລະຫັດຜ່ານ: [password]. ທ່ານອາດຈະຖືກຮຽກຮ້ອງໃຫ້ມີການປ່ຽນແປງມັນຫຼັງຈາກເຂົ້າສູ່ລະບົບຄັ້ງທໍາອິດຂອງທ່ານ.",
"Accounts_UserAddedEmail_Description": "ທ່ານອາດຈະນໍາໃຊ້ຕົວຍຶດຕໍາແຫນ່ງດັ່ງຕໍ່ໄປນີ້:
[name], [fname], [lname] ສໍາລັບຊື່ຜູ້ໃຊ້ຂອງໄດ້ຢ່າງເຕັມທີ່, ຊື່ທໍາອິດຫຼືຊື່ສຸດທ້າຍ, ຕາມລໍາດັບ. [email] ສໍາລັບອີເມລຂອງຜູ້ໃຊ້ໄດ້. [password] ສໍາລັບການລະຫັດຜ່ານຂອງຜູ້ໃຊ້ໄດ້. [Site_Name] ແລະ [Site_URL] ສໍາລັບຄໍາຮ້ອງສະຫມັກຊື່ແລະ URL ຕາມລໍາດັບ. ",
"Accounts_UserAddedEmailSubject_Default": "ທ່ານໄດ້ຮັບການເພີ່ມ [Site_Name]",
"Activate": "ກະຕຸ້ນ",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "ເງື່ອນໄຂການໃຫ້ບໍລິການ",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "ຄົ້ນຫາ Domain Custom",
- "LDAP_Custom_Domain_Search_Description": "A ສິ້ນຂອງ JSON ທີ່ຄວບຄຸມຂໍ້ມູນຕິດແລະການເຊື່ອມຕໍ່ແລະເປັນຮູບແບບ: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domain ມາດຕະຖານ",
"LDAP_Description": "LDAP ເປັນຖານຂໍ້ມູນລໍາດັບຊັ້ນທີ່ຫຼາຍບໍລິສັດນໍາໃຊ້ເພື່ອສະຫນອງການເຂົ້າສູ່ລະບົບໃນ - ສະຖານທີ່ສໍາລັບການແລກປ່ຽນລະຫັດຜ່ານຫນຶ່ງລະຫວ່າງສະຖານທີ່ແລະບໍລິການທີ່ຫຼາກຫຼາຍ. ສໍາລັບຂໍ້ມູນການຕັ້ງຄ່າຂັ້ນສູງແລະຕົວຢ່າງ, ກະລຸນາປືກສາຫາລື wiki ຂອງພວກເຮົາ: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Base ໂດເມນ",
- "LDAP_Domain_Base_Description": "ຄຸນສົມບັດຢ່າງເຕັມສ່ວນຊື່ເພາະ (DN) ຂອງຍ່ອຍ LDAP ທ່ານຕ້ອງການຄົ້ນຫາສໍາລັບຜູ້ໃຊ້ແລະກຸ່ມ. ທ່ານສາມາດເພີ່ມເປັນຈໍານວນຫຼາຍຕາມທີ່ທ່ານຕ້ອງການ; ຢ່າງໃດກໍຕາມ, ໃນແຕ່ລະກຸ່ມຈະຕ້ອງໄດ້ຮັບການກໍານົດໄວ້ໃນຖານໂດເມນດຽວກັນຜູ້ຊົມໃຊ້ທີ່ເປັນຂອງມັນ. ຖ້າຫາກວ່າທ່ານລະບຸກຸ່ມຜູ້ໃຊ້ຈໍາກັດ, ມີພຽງແຕ່ຜູ້ໃຊ້ທີ່ຂຶ້ນກັບກຸ່ມຄົນເຫຼົ່ານັ້ນຈະຢູ່ໃນຂອບເຂດ. ພວກເຮົາແນະນໍາໃຫ້ທ່ານກໍານົດລະດັບເທິງຂອງຕົ້ນໄມ້ directory LDAP ຂອງທ່ານເປັນພື້ນຖານໂດເມນຂອງທ່ານແລະການນໍາໃຊ້ການກັ່ນຕອງການຊອກຫາທີ່ຈະຄວບຄຸມການເຂົ້າເຖິງ.",
- "LDAP_Domain_Search_Filter": "ໂດເມນຜົນການຄົ້ນຫາ",
- "LDAP_Domain_Search_Filter_Description": "ຖ້າກໍານົດໄວ້, ຜູ້ໃຊ້ພຽງແຕ່ຄໍາວ່າການກັ່ນຕອງນີ້ຈະໄດ້ຮັບການອະນຸຍາດໃຫ້ເຂົ້າສູ່ລະບົບ. ຖ້າຫາກວ່າບໍ່ມີການກັ່ນຕອງແມ່ນກໍານົດໄວ້, ຜູ້ຊົມໃຊ້ທັງຫມົດພາຍໃນຂອບເຂດຂອງພື້ນຖານໂດເມນທີ່ລະບຸຈະສາມາດເຂົ້າສູ່ລະບົບ. ຕົວຢ່າງ: ສໍາລັບການ Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. ຕົວຢ່າງ: ສໍາລັບການ OpenLDAP (ການຊອກຫາຄໍາວ່າຂະຫຍາຍ) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "ໂດເມນຄົ້ນຫາວັດຖຸປະເພດ",
- "LDAP_Domain_Search_Object_Category_Description": "The * * objectCategory ທີ່ລະບຸຜູ້ໃຊ້ຂອງທ່ານ. ອອກຈາກເປົ່າຫວ່າງສໍາລັບ OpenLDAP * *. ຕົວຢ່າງ: `person`, ແລະອື່ນໆ",
- "LDAP_Domain_Search_Object_Class": "ໂດເມນ Class ຄົ້ນຫາວັດຖຸ",
- "LDAP_Domain_Search_Object_Class_Description": "The * * objectClass ທີ່ລະບຸຜູ້ໃຊ້ຂອງທ່ານ. ຕົວຢ່າງ: `organizationalPerson`,` user`, `inetOrgPerson`, ແລະອື່ນໆ",
- "LDAP_Domain_Search_Password": "ຄົ້ນຫາໂດເມນລະຫັດຜ່ານ",
- "LDAP_Domain_Search_Password_Description": "ລະຫັດຜ່ານສໍາລັບຜູ້ໃຊ້ຄົ້ນຫາໂດເມນທີ່.",
- "LDAP_Domain_Search_User": "ໂດເມນຄົ້ນຫາຜູ້ໃຊ້",
- "LDAP_Domain_Search_User_Description": "ຜູ້ໃຊ້ LDAP ທີ່ດໍາເນີນການຄົ້ນຫາຜູ້ໃຊ້ໃນການກວດສອບຜູ້ຊົມໃຊ້ອື່ນໆໃນເວລາທີ່ພວກເຂົາເຈົ້າເຂົ້າສູ່ລະບົບ. ນີ້ແມ່ນປົກກະຕິບັນຊີການບໍລິການສ້າງໂດຍສະເພາະສໍາລັບການເຊື່ອມໂຍງພາກສ່ວນທີສາມ. ການນໍາໃຊ້ຊື່ຄົບຖ້ວນ, ເຊັ່ນດຽວກັນ, cn = Administrator, cn = ຜູ້ໃຊ້ dc = ຕົວຢ່າງ, dc = com`.",
- "LDAP_Domain_Search_User_ID": "ຄົ້ນຫາ Domain User ID",
- "LDAP_Domain_Search_User_ID_Description": "ການໃຫ້ເຫດຜົນ LDAP ທີ່ລະບຸຜູ້ໃຊ້ LDAP ຜູ້ທີ່ພະຍາຍາມກວດສອບ. ພາກສະຫນາມນີ້ຄວນຈະເປັນ `sAMAccountName` ສໍາລັບການຕິດຕັ້ງໃຊ້ວຽກຫຼາຍທີ່ສຸດລະບົບ, ແຕ່ວ່າມັນອາດຈະ` uid` ສໍາລັບການແກ້ໄຂບັນຫາ LDAP ອື່ນໆ, ເຊັ່ນ: OpenLDAP. ທ່ານສາມາດນໍາໃຊ້ `mail` ເພື່ອກໍານົດຜູ້ໃຊ້ອີເມລຫຼືໃດກໍ່ຕາມເຫດຜົນທີ່ທ່ານຕ້ອງການ. ທ່ານສາມາດນໍາໃຊ້ຄຸນຄ່າຫລາຍຂັ້ນດ້ວຍຈໍ້າຈຸດທີ່ຈະອະນຸຍາດໃຫ້ຜູ້ໃຊ້ສາມາດເຂົ້າສູ່ລະບົບໂດຍໃຊ້ຕົວລະບຸຫຼາຍເຊັ່ນຊື່ຜູ້ໃຊ້ຫລືອີເມລ໌.",
+ "LDAP_BaseDN_Description": "ຄຸນສົມບັດຢ່າງເຕັມສ່ວນຊື່ເພາະ (DN) ຂອງຍ່ອຍ LDAP ທ່ານຕ້ອງການຄົ້ນຫາສໍາລັບຜູ້ໃຊ້ແລະກຸ່ມ. ທ່ານສາມາດເພີ່ມເປັນຈໍານວນຫຼາຍຕາມທີ່ທ່ານຕ້ອງການ; ຢ່າງໃດກໍຕາມ, ໃນແຕ່ລະກຸ່ມຈະຕ້ອງໄດ້ຮັບການກໍານົດໄວ້ໃນຖານໂດເມນດຽວກັນຜູ້ຊົມໃຊ້ທີ່ເປັນຂອງມັນ. ຖ້າຫາກວ່າທ່ານລະບຸກຸ່ມຜູ້ໃຊ້ຈໍາກັດ, ມີພຽງແຕ່ຜູ້ໃຊ້ທີ່ຂຶ້ນກັບກຸ່ມຄົນເຫຼົ່ານັ້ນຈະຢູ່ໃນຂອບເຂດ. ພວກເຮົາແນະນໍາໃຫ້ທ່ານກໍານົດລະດັບເທິງຂອງຕົ້ນໄມ້ directory LDAP ຂອງທ່ານເປັນພື້ນຖານໂດເມນຂອງທ່ານແລະການນໍາໃຊ້ການກັ່ນຕອງການຊອກຫາທີ່ຈະຄວບຄຸມການເຂົ້າເຖິງ.",
+ "LDAP_User_Search_Field_Description": "ການໃຫ້ເຫດຜົນ LDAP ທີ່ລະບຸຜູ້ໃຊ້ LDAP ຜູ້ທີ່ພະຍາຍາມກວດສອບ. ພາກສະຫນາມນີ້ຄວນຈະເປັນ `sAMAccountName` ສໍາລັບການຕິດຕັ້ງໃຊ້ວຽກຫຼາຍທີ່ສຸດລະບົບ, ແຕ່ວ່າມັນອາດຈະ` uid` ສໍາລັບການແກ້ໄຂບັນຫາ LDAP ອື່ນໆ, ເຊັ່ນ: OpenLDAP. ທ່ານສາມາດນໍາໃຊ້ `mail` ເພື່ອກໍານົດຜູ້ໃຊ້ອີເມລຫຼືໃດກໍ່ຕາມເຫດຜົນທີ່ທ່ານຕ້ອງການ. ທ່ານສາມາດນໍາໃຊ້ຄຸນຄ່າຫລາຍຂັ້ນດ້ວຍຈໍ້າຈຸດທີ່ຈະອະນຸຍາດໃຫ້ຜູ້ໃຊ້ສາມາດເຂົ້າສູ່ລະບົບໂດຍໃຊ້ຕົວລະບຸຫຼາຍເຊັ່ນຊື່ຜູ້ໃຊ້ຫລືອີເມລ໌.",
+ "LDAP_User_Search_Filter_Description": "ຖ້າກໍານົດໄວ້, ຜູ້ໃຊ້ພຽງແຕ່ຄໍາວ່າການກັ່ນຕອງນີ້ຈະໄດ້ຮັບການອະນຸຍາດໃຫ້ເຂົ້າສູ່ລະບົບ. ຖ້າຫາກວ່າບໍ່ມີການກັ່ນຕອງແມ່ນກໍານົດໄວ້, ຜູ້ຊົມໃຊ້ທັງຫມົດພາຍໃນຂອບເຂດຂອງພື້ນຖານໂດເມນທີ່ລະບຸຈະສາມາດເຂົ້າສູ່ລະບົບ. ຕົວຢ່າງ: ສໍາລັບການ Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. ຕົວຢ່າງ: ສໍາລັບການ OpenLDAP (ການຊອກຫາຄໍາວ່າຂະຫຍາຍ) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "ຜູ້ໃຊ້ LDAP ທີ່ດໍາເນີນການຄົ້ນຫາຜູ້ໃຊ້ໃນການກວດສອບຜູ້ຊົມໃຊ້ອື່ນໆໃນເວລາທີ່ພວກເຂົາເຈົ້າເຂົ້າສູ່ລະບົບ. ນີ້ແມ່ນປົກກະຕິບັນຊີການບໍລິການສ້າງໂດຍສະເພາະສໍາລັບການເຊື່ອມໂຍງພາກສ່ວນທີສາມ. ການນໍາໃຊ້ຊື່ຄົບຖ້ວນ, ເຊັ່ນດຽວກັນ, cn = Administrator, cn = ຜູ້ໃຊ້ dc = ຕົວຢ່າງ, dc = com`.",
"LDAP_Enable": "ເຮັດໃຫ້ສາມາດ",
"LDAP_Enable_Description": "ພະຍາຍາມທີ່ຈະນໍາໃຊ້ LDAP ສໍາລັບການກວດສອບ.",
"LDAP_Encryption": "ການເຂົ້າລະຫັດ",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "ໃຫ້ເກັບຮັກສາຂໍ້ມູນຜູ້ໃຊ້ໃນ sync ກັບເຄື່ອງແມ່ຂ່າຍຂອງກ່ຽວກັບການເຂົ້າສູ່ລະບົບ (ເຊັ່ນ: ຊື່, ອີເມວ).",
"LDAP_Sync_User_Data_FieldMap": "ຜູ້ໃຊ້ຂໍ້ມູນພາກສະຫນາມແຜນທີ່",
"LDAP_Sync_User_Data_FieldMap_Description": "ກໍາຫນົດຄ່າວິທີຂົງເຂດບັນຊີຜູ້ໃຊ້ (ເຊັ່ນ: ອີ) ມີປະຊາກອນຈາກການບັນທຶກໃນ LDAP ເປັນ (ພົບເທື່ອດຽວ). ໃນຖານະເປັນຕົວຢ່າງ, `{\" cn \":\" ຊື່ \",\" ຈົດຫມາຍ \":\" ອີເມລ໌ \"}` ຈະເລືອກເອົາຊື່ຂອງບຸກຄົນມະນຸດສາມາດອ່ານໄດ້ຈາກ cn ເຫດຜົນ, ແລະອີເມລຂອງເຂົາເຈົ້າຈາກເຫດຜົນ mail ໄດ້. ທົ່ງນາທີ່ມີປະກອບມີ `name`, ແລະ` email`.",
- "LDAP_Sync_Users": "ຜູ້ໃຊ້ Sync",
"LDAP_Test_Connection": "ການເຊື່ອມຕໍ່ການທົດສອບ",
"LDAP_Unique_Identifier_Field": "ເປັນເອກະລັກ Identifier ພາກສະຫນາມ",
"LDAP_Unique_Identifier_Field_Description": "ພາກສະຫນາມທີ່ຈະໄດ້ຮັບການນໍາໃຊ້ເພື່ອເຊື່ອມຕໍ່ຜູ້ໃຊ້ LDAP ແລະຜູ້ໃຊ້ Rocket.Chat ໄດ້. ທ່ານສາມາດແຈ້ງຄ່າຫລາຍຂັ້ນດ້ວຍຈໍ້າຈຸດທີ່ຈະພະຍາຍາມເພື່ອໃຫ້ໄດ້ຮັບມູນຄ່າຈາກການບັນທຶກຂອງ LDAP. ຄ່າເລີ່ມຕົ້ນຄື `objectGUID, IBM, entryUUID, ຄູ່ມື, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "ການນໍາໃຊ້ຄົ້ນຫາ Domain Custom",
- "LDAP_Use_Custom_Domain_Search_Description": "ຂຽນກັ່ນຕອງຂອງທ່ານເອງເພື່ອຄົ້ນຫາຜູ້ໃຊ້ໃນເຄື່ອງແມ່ຂ່າຍຂອງ LDAP.",
"LDAP_Username_Field": "ຊື່ຜູ້ໃຊ້ພາກສະຫນາມ",
"LDAP_Username_Field_Description": "ພາກສະຫນາມທີ່ຈະໄດ້ຮັບການນໍາໃຊ້ເປັນຊື່ຜູ້ໃຊ້ * ສໍາລັບຜູ້ໃຊ້ໃຫມ່ *. ປ່ອຍໃຫ້ເປົ່າການນໍາໃຊ້ຊື່ຜູ້ໃຊ້ຂໍ້ມູນໃນຫນ້າເຂົ້າສູ່ລະບົບ. ທ່ານສາມາດນໍາໃຊ້ tags ແມ່ແບບເກີນໄປເຊັ່ນ: `#{givenName}.#{sn}`. ຄ່າເລີ່ມຕົ້ນຄື `sAMAccountName`.",
"Leave_Group_Warning": "ທ່ານແນ່ໃຈວ່າທ່ານຕ້ອງການທີ່ຈະອອກຈາກກຸ່ມ \" %s\"?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "ຜູ້ໃຊ້ຈະບໍ່ສາມາດຢູ່ໃນປະເພດ %s",
"Theme": "Theme",
"theme-color-content-background-color": "ເນື້ອໃນສີຄວາມເປັນມາ",
+ "theme-color-custom-scrollbar-color": "Custom ເລື່ອນສີ",
+ "theme-color-info-font-color": "ຂໍ້ມູນ Font ສີ",
+ "theme-color-link-font-color": "ການເຊື່ອມຕໍ່ສີຕົວອັກສອນ",
"theme-color-primary-background-color": "ປະຖົມສີຄວາມເປັນມາ",
"theme-color-primary-font-color": "ປະຖົມສີຕົວອັກສອນ",
"theme-color-secondary-background-color": "ມັດທະຍົມສີຄວາມເປັນມາ",
"theme-color-secondary-font-color": "ມັດທະຍົມສີຕົວອັກສອນ",
- "theme-color-tertiary-background-color": "ສາມສີຄວາມເປັນມາ",
- "theme-color-tertiary-font-color": "ສາມສີຕົວອັກສອນ",
- "theme-color-link-font-color": "ການເຊື່ອມຕໍ່ສີຕົວອັກສອນ",
- "theme-color-info-font-color": "ຂໍ້ມູນ Font ສີ",
- "theme-color-custom-scrollbar-color": "Custom ເລື່ອນສີ",
"theme-color-status-away": "ໄປສີສະຖານະ",
"theme-color-status-busy": "ທຸລະກິດສີສະຖານະ",
"theme-color-status-offline": "ອອຟໄລສີສະຖານະ",
"theme-color-status-online": "ອອນໄລນ໌ສີສະຖານະ",
+ "theme-color-tertiary-background-color": "ສາມສີຄວາມເປັນມາ",
+ "theme-color-tertiary-font-color": "ສາມສີຕົວອັກສອນ",
"theme-color-unread-notification-color": "ຍັງບໍ່ໄດ້ອ່ານສີການແຈ້ງເຕືອນ",
"theme-custom-css": "CSS Custom",
"There_are_no_agents_added_to_this_department_yet": "ມີຕົວແທນເພີ່ມບໍ່ມີການພະແນກນີ້ຍັງ.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "ອີເມລຂອງທ່ານໄດ້ຖືກສົ່ງໄປ %s",
"Your_password_is_wrong": "ລະຫັດຜ່ານຂອງທ່ານແມ່ນຜິດພາດ!",
"Your_push_was_sent_to_s_devices": "ການຊຸກຍູ້ຂອງທ່ານໄດ້ຖືກສົ່ງໄປອຸປະກອນ %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/lt.i18n.json b/packages/rocketchat-i18n/i18n/lt.i18n.json
index b0a5d5fd7cfad..310bdcac6b300 100644
--- a/packages/rocketchat-i18n/i18n/lt.i18n.json
+++ b/packages/rocketchat-i18n/i18n/lt.i18n.json
@@ -1,3 +1,9 @@
{
- "0_Errors_Only": "0 - Klaidos Tik"
+ "#channel": "#kanalas",
+ "0_Errors_Only": "0 - Tik klaidos",
+ "1_Errors_and_Information": "1 - Klaidos ir informacija",
+ "2_Erros_Information_and_Debug": "2 - Klaidos, informacija ir tvarkymas",
+ "403": "Prieiga negalima",
+ "500": "Vidinė serverio klaida",
+ "@username": "@vartotojovardas"
}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/mn.i18n.json b/packages/rocketchat-i18n/i18n/mn.i18n.json
new file mode 100644
index 0000000000000..c6ac4b2e4a1de
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/mn.i18n.json
@@ -0,0 +1,3 @@
+{
+ "#channel": "#cуваг"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
index dfb52d0a5e786..b14714b0d3880 100644
--- a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Benarkan Profil Pengguna Tukar",
"Accounts_AvatarResize": "Saiz semula Avatars",
"Accounts_AvatarSize": "avatar Saiz",
- "Accounts_AvatarStorePath": "Avatar Storage Path",
- "Accounts_AvatarStoreType": "Avatar Storage Jenis",
"Accounts_BlockedDomainsList": "Senarai Domain Disekat",
"Accounts_BlockedDomainsList_Description": "Senarai diasingkan koma bagi domain disekat",
"Accounts_BlockedUsernameList": "Senarai Nama pengguna Disekat",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "Pengesahan E-mel",
"Accounts_EmailVerification_Description": "Pastikan anda mempunyai tetapan SMTP betul untuk menggunakan ciri-ciri ini",
"Accounts_Enrollment_Email": "Pendaftaran E-mel",
- "Accounts_Enrollment_Email_Default": " Selamat datang ke [Site_Name] Pergi ke [Site_URL] dan cuba yang terbaik penyelesaian chat sumber terbuka yang ada hari ini!
",
+ "Accounts_Enrollment_Email_Default": " Selamat datang ke [Site_Name] Pergi ke [Site_URL] dan cuba yang terbaik penyelesaian chat sumber terbuka yang ada hari ini!
",
"Accounts_Enrollment_Email_Description": "Anda boleh menggunakan [nama], [fname], [lname] bagi nama penuh pengguna, nama pertama atau nama akhir, masing-masing. Anda boleh menggunakan [email] untuk e-mel pengguna.",
"Accounts_Enrollment_Email_Subject_Default": "Selamat datang ke [Site_Name]",
"Accounts_Iframe_api_method": "Kaedah Api",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "Daftar masuk WordPress",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress Callback",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress Callback",
"Accounts_OAuth_Wordpress_id": " ID WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Password Reset",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "awam",
"Accounts_RegistrationForm_Secret_URL": "URL Secret",
"Accounts_RegistrationForm_SecretURL": "Borang Pendaftaran URL Secret",
- "Accounts_RegistrationForm_SecretURL_Description": "Anda mesti menyediakan rentetan rawak yang akan ditambah ke URL pendaftaran anda. Contoh: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Anda mesti menyediakan rentetan rawak yang akan ditambah ke URL pendaftaran anda. Contoh: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Memerlukan Nama Untuk Daftar",
"Accounts_ShowFormLogin": "berasaskan Tunjukkan bentuk Login",
"Accounts_UseDefaultBlockedDomainsList": "Penggunaan Lalai Disekat Senarai Domain",
"Accounts_UseDNSDomainCheck": "Gunakan DNS Domain Daftar",
- "Accounts_UserAddedEmail_Default": " Selamat datang ke [Site_Name] Pergi ke [Site_URL] dan cuba yang terbaik penyelesaian chat sumber terbuka yang ada hari ini!
Anda boleh log masuk menggunakan e-mel anda: [email] dan kata laluan: [password]. Anda mungkin dikehendaki untuk mengubahnya selepas log masuk pertama anda.",
+ "Accounts_UserAddedEmail_Default": "
Selamat datang ke [Site_Name] Pergi ke [Site_URL] dan cuba yang terbaik penyelesaian chat sumber terbuka yang ada hari ini!
Anda boleh log masuk menggunakan e-mel anda: [email] dan kata laluan: [password]. Anda mungkin dikehendaki untuk mengubahnya selepas log masuk pertama anda.",
"Accounts_UserAddedEmail_Description": "Anda boleh menggunakan pemegang tempat berikut:
[name], [fname], [lname] untuk nama pengguna penuh, nama pertama atau nama akhir, masing-masing. [email] untuk e-mel pengguna. [password] bagi kata laluan pengguna. [Site_Name] dan [Site_URL] untuk Nama Permohonan dan URL masing-masing. ",
"Accounts_UserAddedEmailSubject_Default": "Anda telah ditambahkan pada [Site_Name]",
"Activate": "Aktifkan",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Terma Perkhidmatan",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Custom Domain Search",
- "LDAP_Custom_Domain_Search_Description": "Sekeping JSON yang mentadbir maklumat mengikat dan sambungan dan dalam bentuk: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domain lalai",
"LDAP_Description": "LDAP adalah pangkalan data hierarki bahawa banyak syarikat gunakan untuk menyediakan single sign on - kemudahan untuk berkongsi satu kata laluan antara beberapa tapak dan perkhidmatan. Untuk maklumat konfigurasi lanjutan dan contoh, sila rujuk wiki kami: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Base domain",
- "LDAP_Domain_Base_Description": "Nama pertama layak sepenuhnya Cemerlang (DN) seorang anak pohon LDAP anda ingin mencari pengguna-pengguna dan kumpulan. Anda boleh menambah seberapa banyak yang anda suka; Walau bagaimanapun, setiap kumpulan mesti ditakrifkan dalam asas domain yang sama dengan pengguna yang menjadi miliknya. Jika anda menentukan kumpulan pengguna terhad, hanya pengguna yang di dalam kumpulan-kumpulan akan berada dalam skop. Kami mengesyorkan bahawa anda menentukan tahap bahagian atas pokok direktori LDAP anda sebagai asas domain anda dan menggunakan penapis carian untuk mengawal akses.",
- "LDAP_Domain_Search_Filter": "Domain Search Filter",
- "LDAP_Domain_Search_Filter_Description": "Jika dinyatakan, hanya pengguna yang sepadan dengan penapis ini akan dibenarkan untuk log masuk. Jika tiada penapis yang dinyatakan, semua pengguna dalam skop asas domain yang dinyatakan akan dapat untuk mendaftar masuk. Contohnya untuk Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Contohnya untuk OpenLDAP (search Perlawanan extensible) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Cari Objek Kategori",
- "LDAP_Domain_Search_Object_Category_Description": "The * objectCategory * yang mengenal pasti pengguna anda. Tinggalkan kosong untuk * OpenLDAP *. Eg `person`, dan lain-lain",
- "LDAP_Domain_Search_Object_Class": "Domain Kelas Cari Objek",
- "LDAP_Domain_Search_Object_Class_Description": "The * kelas objek * yang mengenal pasti pengguna anda. Eg `organizationalPerson`,` user`, `inetOrgPerson`, dan lain-lain",
- "LDAP_Domain_Search_Password": "Domain Cari Kata laluan",
- "LDAP_Domain_Search_Password_Description": "Kata laluan untuk pengguna carian domain.",
- "LDAP_Domain_Search_User": "Domain Search Pengguna",
- "LDAP_Domain_Search_User_Description": "The LDAP pengguna yang melaksanakan pencarian pengguna untuk mengesahkan pengguna lain apabila mereka log masuk. Ini biasanya satu akaun perkhidmatan dicipta khusus untuk integrasi pihak ketiga. Gunakan nama yang memenuhi syarat, seperti `cn = Administrator, cn = Pengguna, dc = Contoh, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search ID Pengguna",
- "LDAP_Domain_Search_User_ID_Description": "The LDAP atribut yang mengenal pasti pengguna LDAP yang cuba pengesahan. medan ini sepatutnya menjadi `sAMAccountName` untuk pemasangan paling Active Directory, tetapi ia boleh menjadi` uid` penyelesaian LDAP yang lain, seperti OpenLDAP. Anda boleh menggunakan `mail` untuk mengenal pasti pengguna melalui e-mel atau apa sahaja atribut yang anda mahu. Anda boleh menggunakan pelbagai nilai dipisahkan oleh koma untuk membolehkan pengguna untuk log masuk menggunakan berbilang pengecam seperti nama pengguna atau e-mel.",
+ "LDAP_BaseDN_Description": "Nama pertama layak sepenuhnya Cemerlang (DN) seorang anak pohon LDAP anda ingin mencari pengguna-pengguna dan kumpulan. Anda boleh menambah seberapa banyak yang anda suka; Walau bagaimanapun, setiap kumpulan mesti ditakrifkan dalam asas domain yang sama dengan pengguna yang menjadi miliknya. Jika anda menentukan kumpulan pengguna terhad, hanya pengguna yang di dalam kumpulan-kumpulan akan berada dalam skop. Kami mengesyorkan bahawa anda menentukan tahap bahagian atas pokok direktori LDAP anda sebagai asas domain anda dan menggunakan penapis carian untuk mengawal akses.",
+ "LDAP_User_Search_Field_Description": "The LDAP atribut yang mengenal pasti pengguna LDAP yang cuba pengesahan. medan ini sepatutnya menjadi `sAMAccountName` untuk pemasangan paling Active Directory, tetapi ia boleh menjadi` uid` penyelesaian LDAP yang lain, seperti OpenLDAP. Anda boleh menggunakan `mail` untuk mengenal pasti pengguna melalui e-mel atau apa sahaja atribut yang anda mahu. Anda boleh menggunakan pelbagai nilai dipisahkan oleh koma untuk membolehkan pengguna untuk log masuk menggunakan berbilang pengecam seperti nama pengguna atau e-mel.",
+ "LDAP_User_Search_Filter_Description": "Jika dinyatakan, hanya pengguna yang sepadan dengan penapis ini akan dibenarkan untuk log masuk. Jika tiada penapis yang dinyatakan, semua pengguna dalam skop asas domain yang dinyatakan akan dapat untuk mendaftar masuk. Contohnya untuk Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Contohnya untuk OpenLDAP (search Perlawanan extensible) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "The LDAP pengguna yang melaksanakan pencarian pengguna untuk mengesahkan pengguna lain apabila mereka log masuk. Ini biasanya satu akaun perkhidmatan dicipta khusus untuk integrasi pihak ketiga. Gunakan nama yang memenuhi syarat, seperti `cn = Administrator, cn = Pengguna, dc = Contoh, dc = com`.",
"LDAP_Enable": "membolehkan",
"LDAP_Enable_Description": "Cuba untuk menggunakan LDAP untuk pengesahan.",
"LDAP_Encryption": "penyulitan",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Menyimpan data pengguna dalam penyegerakan dengan pelayan pada login (contohnya: nama, e-mel).",
"LDAP_Sync_User_Data_FieldMap": "Pengguna Data Field Peta",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfigur berapa bidang akaun pengguna (seperti e-mel) adalah penduduk dari satu rekod dalam LDAP (sekali dijumpai). Sebagai contoh, `{\" cn \":\" nama \",\" mel \":\" e-mel \"}` akan memilih nama seseorang manusia boleh dibaca dari atribut cn, dan e-mel mereka dari sifat mel. bidang termasuk `name`, dan` email`.",
- "LDAP_Sync_Users": "Pengguna Sync",
"LDAP_Test_Connection": "Test Connection",
"LDAP_Unique_Identifier_Field": "Pengecam Unik Field",
"LDAP_Unique_Identifier_Field_Description": "Yang bidang akan digunakan untuk menghubungkan pengguna LDAP dan pengguna Rocket.Chat itu. Anda boleh memaklumkan pelbagai nilai dipisahkan oleh koma untuk cuba untuk mendapatkan nilai daripada rekod LDAP. Nilai lalai adalah `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Gunakan Custom Domain Search",
- "LDAP_Use_Custom_Domain_Search_Description": "Tulis penapis anda sendiri untuk mencari pengguna dalam pelayan LDAP.",
"LDAP_Username_Field": "Nama pengguna Field",
"LDAP_Username_Field_Description": "Yang bidang akan digunakan sebagai * nama pengguna * bagi pengguna baru. Biarkan kosong untuk menggunakan nama pengguna yang dimaklumkan pada halaman login. Anda boleh menggunakan tag template juga, seperti `#{givenName}.#{sn}`. Nilai lalai adalah `sAMAccountName`.",
"Leave_Group_Warning": "Adakah anda pasti anda mahu meninggalkan kumpulan \" %s\"?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "Pengguna tidak akan dapat untuk menaip dalam %s",
"Theme": "tema",
"theme-color-content-background-color": "Warna Latar Belakang kandungan",
+ "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
+ "theme-color-info-font-color": "Maklumat Font Warna",
+ "theme-color-link-font-color": "Link Font Warna",
"theme-color-primary-background-color": "Warna Latar Belakang Utama",
"theme-color-primary-font-color": "Primary Font Warna",
"theme-color-secondary-background-color": "Warna Latar Belakang Menengah",
"theme-color-secondary-font-color": "Menengah Font Warna",
- "theme-color-tertiary-background-color": "Warna Latar Belakang Tertiary",
- "theme-color-tertiary-font-color": "Tertiary Font Warna",
- "theme-color-link-font-color": "Link Font Warna",
- "theme-color-info-font-color": "Maklumat Font Warna",
- "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
"theme-color-status-away": "Status Away Warna",
"theme-color-status-busy": "Status Busy Warna",
"theme-color-status-offline": "Status Offline Warna",
"theme-color-status-online": "Online Status Warna",
+ "theme-color-tertiary-background-color": "Warna Latar Belakang Tertiary",
+ "theme-color-tertiary-font-color": "Tertiary Font Warna",
"theme-color-unread-notification-color": "Belum Baca Pemberitahuan Warna",
"theme-custom-css": "CSS Custom",
"There_are_no_agents_added_to_this_department_yet": "Tiada ejen ditambah kepada jabatan ini.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "mel anda telah dihantar ke %s",
"Your_password_is_wrong": "Kata laluan anda adalah salah!",
"Your_push_was_sent_to_s_devices": "push anda telah dihantar ke peranti %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/nl.i18n.json b/packages/rocketchat-i18n/i18n/nl.i18n.json
index a175e83d61644..e3baf213e6b05 100644
--- a/packages/rocketchat-i18n/i18n/nl.i18n.json
+++ b/packages/rocketchat-i18n/i18n/nl.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Sta wijzen van gebruikers profiel toe",
"Accounts_AvatarResize": "Wijzig Avatar grootte",
"Accounts_AvatarSize": "Avatar grootte",
- "Accounts_AvatarStorePath": "Avatar opslag pad",
- "Accounts_AvatarStoreType": "Avatar opslag type",
"Accounts_BlockedDomainsList": "Geblokkeerde domeinen List",
"Accounts_BlockedDomainsList_Description": "Door komma's gescheiden lijst van geblokkeerde domeinen",
"Accounts_BlockedUsernameList": "Geblokkeerde Gebruikersnaam List",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "E-mail verificatie",
"Accounts_EmailVerification_Description": "Zorg ervoor dat u de juiste SMTP-instellingen om deze functie te gebruiken",
"Accounts_Enrollment_Email": "Registratie E-mail",
- "Accounts_Enrollment_Email_Default": " Welkom bij [Site naam] Ga naar [Site_URL] en probeer de beste open source chat-oplossing die vandaag beschikbaar zijn!
",
+ "Accounts_Enrollment_Email_Default": " Welkom bij [Site naam] Ga naar [Site_URL] en probeer de beste open source chat-oplossing die vandaag beschikbaar zijn!
",
"Accounts_Enrollment_Email_Description": "You may use [name], [fname], [lname] for the user's full name, first name or last name, respectively. You may use [email] for the user's e-mail.",
"Accounts_Enrollment_Email_Subject_Default": "Welkom bij [Site_Name]",
"Accounts_Iframe_api_method": "API-methode",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Inloggen",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Geheim (secret)",
"Accounts_PasswordReset": "Wachtwoord reset",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "Openbaar",
"Accounts_RegistrationForm_Secret_URL": "Geheime URL",
"Accounts_RegistrationForm_SecretURL": "Registration Form Secret URL",
- "Accounts_RegistrationForm_SecretURL_Description": "You must provide a random string that will be added to your registration URL. Example: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "You must provide a random string that will be added to your registration URL. Example: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Vereis naam tijdens registratie",
"Accounts_ShowFormLogin": "Laat formulier-gebaseerd loginscherm zien",
"Accounts_UseDefaultBlockedDomainsList": "Gebruik Default geblokkeerde domeinen List",
"Accounts_UseDNSDomainCheck": "Gebruik DNS-domein controleren",
- "Accounts_UserAddedEmail_Default": " Welkom bij [Site_Name] Ga naar [Site_URL] en probeer de beste open source chat-oplossing die vandaag beschikbaar zijn!
U kunt inloggen met uw e-mail: [email] en wachtwoord: [password]. U kan nodig zijn om het te veranderen na uw eerste login.",
+ "Accounts_UserAddedEmail_Default": "
Welkom bij [Site_Name] Ga naar [Site_URL] en probeer de beste open source chat-oplossing die vandaag beschikbaar zijn!
U kunt inloggen met uw e-mail: [email] en wachtwoord: [password]. U kan nodig zijn om het te veranderen na uw eerste login.",
"Accounts_UserAddedEmail_Description": "U mag de volgende plaatshouders gebruiken:
[name], [fname], [lname] voor de volledige naam van de gebruiker, voornaam of achternaam, respectievelijk. [email] voor e-mail van de gebruiker. [password] voor het wachtwoord van de gebruiker. [Site_Name] en [Site_URL] voor de toepassing Naam en URL respectievelijk. ",
"Accounts_UserAddedEmailSubject_Default": "Je hebt toegevoegd aan [Site_Name]",
"Activate": "Activeren",
@@ -143,7 +141,7 @@
"API_EmbedIgnoredHosts": "Insluiten Genegeerd Hosts",
"API_EmbedIgnoredHosts_Description": "Komma's gescheiden lijst met hosts of CIDR adressen, bijv. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Safe Ports",
- "API_EmbedSafePorts_Description": "Door komma's gescheiden lijst van havens toegestaan voor het bekijken.",
+ "API_EmbedSafePorts_Description": "Door komma's gescheiden lijst van poorten toegestaan voor het bekijken.",
"API_GitHub_Enterprise_URL": "Server URL",
"API_GitHub_Enterprise_URL_Description": "Voorbeeld: http://domain.com (exclusief slash)",
"API_Gitlab_URL": "GitLab URL",
@@ -182,7 +180,7 @@
"Avatar": "Verander uw foto",
"Avatar_changed_successfully": "Afbeelding is gewijzigd",
"Avatar_URL": "Afbeelding URL",
- "Avatar_url_invalid_or_error": "De gegeven URL us ongeldig of niet bereikbaar. Probeer het opnieuw met een andere URL.",
+ "Avatar_url_invalid_or_error": "De gegeven URL is ongeldig of niet bereikbaar. Probeer het opnieuw met een andere URL.",
"away": "Afwezig",
"Away": "Afwezig",
"away_female": "afwezig",
@@ -237,7 +235,7 @@
"close": "Sluiten",
"Closed": "Gesloten",
"Closing_chat": "closing-chat",
- "Collapse_Embedded_Media_By_Default": "Collapse ingebedde media standaard",
+ "Collapse_Embedded_Media_By_Default": "Klap ingebedde media standaard in",
"Color": "Kleur",
"Commands": "Commando's",
"Compact": "Compact",
@@ -248,11 +246,11 @@
"Copied": "gekopieerde",
"Copy": "Kopiëren",
"Copy_to_clipboard": "Kopieer naar klembord",
- "COPY_TO_CLIPBOARD": "KOPIEER NAAR KLEMBOARD",
+ "COPY_TO_CLIPBOARD": "KOPIEER NAAR KLEMBORD",
"Count": "Aantal",
"Cozy": "Knus",
"Create": "creëren",
- "Create_A_New_Channel": "Een nieuwe zender aanmaken",
+ "Create_A_New_Channel": "Een nieuw kanaal aanmaken",
"Create_new": "Maak nieuw",
"Created_at": "Gemaakt op",
"Created_at_s_by_s": "Gemaakt op %s door %s ",
@@ -297,10 +295,10 @@
"Drop_to_upload_file": "Sleep hierheen om een bestand te uploaden",
"Dry_run": "Testrun",
"Dry_run_description": "Zal slechts één e-mail sturen naar hetzelfde adres als in afzenderveld. De e-mail moet horen bij een geldige gebruiker.",
- "Duplicate_archived_channel_name": "An gearchiveerd kanaal met naam '%s' bestaat al",
- "Duplicate_archived_private_group_name": "An gearchiveerde privé-group met naam '%s' bestaat al",
- "Duplicate_channel_name": "Een kanaal met de naam '% s' bestaat",
- "Duplicate_private_group_name": "Een privé-groep met de naam '%s' bestaat reeds",
+ "Duplicate_archived_channel_name": "Een gearchiveerd kanaal met naam '%s' bestaat al",
+ "Duplicate_archived_private_group_name": "Een gearchiveerde privé-group met naam '%s' bestaat al",
+ "Duplicate_channel_name": "Een kanaal met de naam '% s' bestaat al",
+ "Duplicate_private_group_name": "Een privé-groep met de naam '%s' bestaat al",
"Edit": "Wijzig",
"Edit_Custom_Field": "Bewerken Aangepast veld",
"Edit_Department": "Afdeling bewerken",
@@ -514,6 +512,7 @@
"Invalid_secret_URL_message": "De gegeven URL is ongeldig.",
"invisible": "onzichtbaar",
"Invisible": "Onzichtbaar",
+ "Idle_Time_Limit": "Niet-actieve tijdslimiet",
"Invitation_HTML": "Uitnodiging HTML",
"Invitation_HTML_Default": " Je bent uitgenodigd voor [Site_Name] Ga naar [Site_URL] en probeer de beste open source chat-oplossing die vandaag beschikbaar zijn!
",
"Invitation_HTML_Description": "U mag de volgende plaatshouders gebruiken: [email] voor de ontvanger e-mail. [Site_Name] en [Site_URL] voor de toepassing Naam en URL respectievelijk. ",
@@ -533,9 +532,9 @@
"Jitsi_Enable_Channels": "Schakelen in Channels",
"join": "Toetreden",
"Join_audio_call": "Voeg me toe aan audio gesprek",
- "Join_default_channels": "Join standaardkanalen",
+ "Join_default_channels": "Word lid van standaardkanalen",
"Join_the_Community": "Word lid",
- "Join_the_given_channel": "Word lid van de gegeven kanaal",
+ "Join_the_given_channel": "Word lid van het gegeven kanaal",
"Join_video_call": "Voeg me toe aan video gesprek",
"Joined": "Geregistreerd",
"Jump": "Springen",
@@ -561,28 +560,16 @@
"Layout_Login_Terms": "Login voorwaarden",
"Layout_Privacy_Policy": "Privacybeleid",
"Layout_Sidenav_Footer": "Side Navigation Footer",
- "Layout_Sidenav_Footer_description": "Footer afmetingen is 260 x 70px",
+ "Layout_Sidenav_Footer_description": "Footer afmetingen zijn 260 x 70px",
"Layout_Terms_of_Service": "Algemene Voorwaarden",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Custom Domain Search",
- "LDAP_Custom_Domain_Search_Description": "Een stuk van JSON die regeert binden en de aansluiting info en is van de vorm: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Default Domain",
"LDAP_Description": "LDAP is a hierarchical database that many companies use to provide single sign on - a facility for sharing one password between multiple sites and services. For advanced configuration information and examples, please consult our wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Domain Base",
- "LDAP_Domain_Base_Description": "De volledig gekwalificeerde Distinguished Name (DN) van een LDAP subtree u wilt zoeken voor gebruikers en groepen. U kunt zoveel als je wilt toevoegen; echter, moet elke groep worden gedefinieerd in hetzelfde domein basis als de gebruikers die behoren. Als u beperkte gebruikersgroepen geven, zullen alleen gebruikers die behoren tot die groepen in scope. Wij raden u aan het hoogste niveau van de LDAP-directory tree opgeven als uw domein basis en gebruiken zoekfilter om toegang te controleren.",
- "LDAP_Domain_Search_Filter": "Domain Zoek Filter",
- "LDAP_Domain_Search_Filter_Description": "Indien gespecificeerd, alleen gebruikers die overeenkomen met dit filter zal worden toegestaan om in te loggen. Als er geen filter is aangegeven, zijn alle gebruikers in het kader van het opgegeven domein basis zal in staat zijn om in te loggen. Bijvoorbeeld voor Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Bijvoorbeeld voor OpenLDAP (extensible match zoeken) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Categorie",
- "LDAP_Domain_Search_Object_Category_Description": "De * objectCategory * dat uw gebruikers te identificeren. Laat leeg voor OpenLDAP * *. Bijvoorbeeld `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Domain Search Object Class",
- "LDAP_Domain_Search_Object_Class_Description": "De * objectclass * dat uw gebruikers te identificeren. Bijvoorbeeld `organizationalPerson`,` netgebruiker, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Domain Search Password",
- "LDAP_Domain_Search_Password_Description": "Het wachtwoord voor het domein zoeken gebruiker.",
- "LDAP_Domain_Search_User": "Domain Search Gebruiker",
- "LDAP_Domain_Search_User_Description": "De LDAP-gebruiker die gebruiker lookups uitvoert om andere gebruikers te verifiëren wanneer ze zich aanmelden. Dit is typisch een service-account speciaal gemaakt voor derden integraties. Gebruik een volledig gekwalificeerde naam, zoals `cn = Administrator, cn = Users, dc = voorbeeld, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search User ID",
- "LDAP_Domain_Search_User_ID_Description": "De LDAP-kenmerk dat de LDAP-gebruiker die verificatie probeert identificeert. Dit veld moet `sAMAccountName` voor de meeste Active Directory-installaties, maar het kan` uid` andere LDAP-oplossingen, zoals OpenLDAP zijn. U kunt `mail` gebruiken om gebruikers te identificeren via e-mail of wat kenmerk dat u wilt. U kunt meerdere waarden gescheiden door een komma te gebruiken om gebruikers in staat om in te loggen met behulp van meerdere identifiers zoals gebruikersnaam of e-mail.",
+ "LDAP_BaseDN_Description": "De volledig gekwalificeerde Distinguished Name (DN) van een LDAP subtree u wilt zoeken voor gebruikers en groepen. U kunt zoveel als je wilt toevoegen; echter, moet elke groep worden gedefinieerd in hetzelfde domein basis als de gebruikers die behoren. Als u beperkte gebruikersgroepen geven, zullen alleen gebruikers die behoren tot die groepen in scope. Wij raden u aan het hoogste niveau van de LDAP-directory tree opgeven als uw domein basis en gebruiken zoekfilter om toegang te controleren.",
+ "LDAP_User_Search_Field_Description": "De LDAP-kenmerk dat de LDAP-gebruiker die verificatie probeert identificeert. Dit veld moet `sAMAccountName` voor de meeste Active Directory-installaties, maar het kan` uid` andere LDAP-oplossingen, zoals OpenLDAP zijn. U kunt `mail` gebruiken om gebruikers te identificeren via e-mail of wat kenmerk dat u wilt. U kunt meerdere waarden gescheiden door een komma te gebruiken om gebruikers in staat om in te loggen met behulp van meerdere identifiers zoals gebruikersnaam of e-mail.",
+ "LDAP_User_Search_Filter_Description": "Indien gespecificeerd, alleen gebruikers die overeenkomen met dit filter zal worden toegestaan om in te loggen. Als er geen filter is aangegeven, zijn alle gebruikers in het kader van het opgegeven domein basis zal in staat zijn om in te loggen. Bijvoorbeeld voor Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. Bijvoorbeeld voor OpenLDAP (extensible match zoeken) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "De LDAP-gebruiker die gebruiker lookups uitvoert om andere gebruikers te verifiëren wanneer ze zich aanmelden. Dit is typisch een service-account speciaal gemaakt voor derden integraties. Gebruik een volledig gekwalificeerde naam, zoals `cn = Administrator, cn = Users, dc = voorbeeld, dc = com`.",
"LDAP_Enable": "Aanzetten",
"LDAP_Enable_Description": "Probeer LDAP te gebruiken voor authenticatie.",
"LDAP_Encryption": "encryptie",
@@ -597,12 +584,9 @@
"LDAP_Sync_User_Data_Description": "Houd gebruikersdata synchroon met de server tijdens login (bijv. naam en email).",
"LDAP_Sync_User_Data_FieldMap": "User Data Field Map",
"LDAP_Sync_User_Data_FieldMap_Description": "Configure how user account fields (like email) are populated from a record in LDAP (once found). As an example, {\"cn\":\"name\", \"mail\":\"email\"} will choose a person's human readable name from the cn attribute, and their email from the mail attribute. Available fields include name, and email.",
- "LDAP_Sync_Users": "Sync Gebruikers",
"LDAP_Test_Connection": "Test verbinding",
"LDAP_Unique_Identifier_Field": "Unique Identifier Field",
"LDAP_Unique_Identifier_Field_Description": "Welk veld zal worden gebruikt om de LDAP-gebruiker en de Rocket.Chat gebruiker te koppelen. U kunt meerdere waarden gescheiden door een komma te informeren om te proberen om de waarde van LDAP plaat te krijgen. Standaard waarde is `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Gebruik Custom Domain Search",
- "LDAP_Use_Custom_Domain_Search_Description": "Schrijf uw eigen filter te zoeken gebruikers in de LDAP-server.",
"LDAP_Username_Field": "gebruikersnaam Field",
"LDAP_Username_Field_Description": "Welk veld zal gebruikt worden als gebruikersnaam * * voor nieuwe gebruikers. Laat leeg om de gebruikersnaam op de hoogte inlogpagina te gebruiken. U kunt template-tags te gebruiken, zoals `#{givenName}.#{sn}`. Standaard waarde is `sAMAccountName`.",
"Leave_Group_Warning": "Weet je zeker dat je groep \"%s\" wil verlaten?",
@@ -634,7 +618,7 @@
"Log_Level": "Log level",
"Log_Package": "Laat package zien",
"Log_View_Limit": "Log limiet",
- "Logged_out_of_other_clients_successfully": "Uitgeloggen van andere plekken was succevol",
+ "Logged_out_of_other_clients_successfully": "Uitgeloggen van andere plekken is gelukt",
"Login": "Log In",
"Login_with": "Login met %s",
"Logout": "Uitloggen",
@@ -817,7 +801,7 @@
"Please_wait_while_OTR_is_being_established": "Een moment geduld aub OTR tot stand wordt gebracht",
"Please_wait_while_your_account_is_being_deleted": "Een moment geduld aub uw account wordt verwijderd ...",
"Please_wait_while_your_profile_is_being_saved": "Een ogenblik geduld terwijl uw profiel wordt opgeslagen ...",
- "Port": "Haven",
+ "Port": "Poort",
"Post_as": "Stuur als",
"Post_to_Channel": "Posten in kanaal",
"Post_to_s_as_s": "Posten in %s als %s ",
@@ -1038,19 +1022,19 @@
"The_user_wont_be_able_to_type_in_s": "De gebruiker kan niet typen in %s",
"Theme": "Thema",
"theme-color-content-background-color": "Inhoud Achtergrondkleur",
+ "theme-color-custom-scrollbar-color": "Handmatige Scrollbarkleur",
+ "theme-color-info-font-color": "Info Tekstkleur",
+ "theme-color-link-font-color": "Link Tekstkleur",
"theme-color-primary-background-color": "Primaire Achtergrondkleur",
"theme-color-primary-font-color": "Primaire Tekstkleur",
"theme-color-secondary-background-color": "Secondaire Achtergrondkleur",
"theme-color-secondary-font-color": "Secondaire Tekstkleur",
- "theme-color-tertiary-background-color": "Tertiaire Achtergronkleur",
- "theme-color-tertiary-font-color": "Tertiaire Tekstkleur ",
- "theme-color-link-font-color": "Link Tekstkleur",
- "theme-color-info-font-color": "Info Tekstkleur",
- "theme-color-custom-scrollbar-color": "Handmatige Scrollbarkleur",
"theme-color-status-away": "Afwezig Statuskleur",
"theme-color-status-busy": "Bezet Statuskleur",
"theme-color-status-offline": "Offline Statuskleur",
"theme-color-status-online": "Online Statuskleur",
+ "theme-color-tertiary-background-color": "Tertiaire Achtergronkleur",
+ "theme-color-tertiary-font-color": "Tertiaire Tekstkleur ",
"theme-color-unread-notification-color": "Ongelezen Notificaties Kleur",
"theme-custom-css": "Custom CSS",
"There_are_no_agents_added_to_this_department_yet": "Er zijn nog geen agenten aan deze afdeling toegevoegd.",
@@ -1094,7 +1078,7 @@
"Uploading_file": "Bestand uploaden...",
"Uptime": "Uptime",
"URL": "URL",
- "Use_account_preference": "Gebruik rekening voorkeur",
+ "Use_account_preference": "Gebruik account voorkeur",
"Use_Emojis": "Gebruik Emojis",
"Use_initials_avatar": "Gebruik de initialen van uw gebruikersnaam",
"Use_service_avatar": "Gebruik %s afbeelding",
@@ -1147,6 +1131,7 @@
"Username_is_already_in_here": "`@%s` is al hier.",
"Username_is_not_in_this_room": "De gebruiker `#%s` is niet in deze kamer.",
"Username_title": "Registreer Gebruikersnaam",
+ "User_Presence": "Aanwezigheid van de gebruiker",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ wil OTR starten. Heeft u wilt accepteren?",
"Users": "Gebruikers",
"Users_in_role": "Gebruikers met rol",
@@ -1179,7 +1164,7 @@
"WebRTC_Enable_Direct": "Toestaan directe berichten",
"WebRTC_Enable_Private": "Toestaan voor privé-berichten",
"WebRTC_Servers": "STUN / TURN Servers",
- "WebRTC_Servers_Description": "Een lijst van STUN en TURN servers gescheiden door een komma. Gebruikersnaam, wachtwoord en de haven zijn toegestaan in het formaat `gebruikersnaam: wachtwoord @ stun: host: port` of` gebruikersnaam: wachtwoord @ beurt: host: port`.",
+ "WebRTC_Servers_Description": "Een lijst van STUN en TURN servers gescheiden door een komma. Gebruikersnaam, wachtwoord en de poort zijn toegestaan in het formaat `gebruikersnaam: wachtwoord @ stun: host: port` of` gebruikersnaam: wachtwoord @ beurt: host: port`.",
"Welcome": "Welkom %s .",
"Welcome_to_the": "Welkom bij de",
"Why_do_you_want_to_report_question_mark": "Waarom wil je melden?",
@@ -1221,4 +1206,4 @@
"Your_mail_was_sent_to_s": "Uw e-mail werd verzonden naar %s",
"Your_password_is_wrong": "Je wachtwoord is verkeerd!",
"Your_push_was_sent_to_s_devices": "Je push werd verzonden naar %s apparaten"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/no.i18n.json b/packages/rocketchat-i18n/i18n/no.i18n.json
new file mode 100644
index 0000000000000..9d0ef72b114a7
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/no.i18n.json
@@ -0,0 +1,68 @@
+{
+ "0_Errors_Only": "0 - Kun Feil",
+ "1_Errors_and_Information": "1 - Feil og informasjon",
+ "2_Erros_Information_and_Debug": "2 - Feil, Informasjon og Feilsøking",
+ "403": "Forbudt",
+ "500": "Intern server feil",
+ "Accept": "Aksepter",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Aksepter innkommende livechat selv om det ikke er noen online",
+ "Accept_with_no_online_agents": "Aksepter uten online agenter",
+ "Access_not_authorized": "Aksepter uautoriserte",
+ "Accounts_Enrollment_Email_Subject_Default": "Velkommen til [Site_Name]",
+ "Accounts_PasswordReset": "Reset passord",
+ "Accounts_RegistrationForm_Disabled": "Deaktivert",
+ "Accounts_RegistrationForm_Public": "Offentlig",
+ "Activate": "Aktiver",
+ "Activity": "Aktivitet",
+ "Add": "Legg til",
+ "Add_agent": "Legg til agent",
+ "Add_Domain": "Legg til domene",
+ "Add_manager": "Legg til leder",
+ "Add_user": "Legg til bruker",
+ "Add_User": "Legg til bruker",
+ "Add_users": "Legg til brukere",
+ "Adding_permission": "Legger til rettigheter",
+ "Adding_user": "Legger til bruker",
+ "Additional_emails": "Ekstra e-postadresser",
+ "Additional_Feedback": "Ekstra tilbakemelding",
+ "Administration": "Administrasjon",
+ "Agent": "Agent",
+ "Agent_added": "Lagt til agent",
+ "Agent_removed": "Fjernet agent",
+ "All": "Alle",
+ "All_channels": "Alle kanaler",
+ "All_logs": "Aller logger",
+ "All_messages": "Alle meldinger",
+ "Archive": "Arkiv",
+ "are_also_typing": "skriver også",
+ "are_typing": "skriver",
+ "Are_you_sure": "Er du sikker?",
+ "Author": "Forfatter",
+ "Available": "Tilgjengelig",
+ "Available_agents": "Tilgjengelige agenter",
+ "away": "borte",
+ "Away": "Borte",
+ "away_female": "borte",
+ "Away_female": "Borte",
+ "away_male": "borte",
+ "Away_male": "Borte",
+ "Back": "Tilbake",
+ "Back_to_applications": "Tilbake til programmer",
+ "Back_to_integrations": "Tilbake til integrasjoner",
+ "Back_to_login": "Tilbake til login",
+ "Back_to_permissions": "Tilbake til rettigheter",
+ "Block_User": "Blokker bruker",
+ "bold": "fet",
+ "busy": "opptatt",
+ "Busy": "Opptatt",
+ "busy_female": "opptatt",
+ "Busy_female": "Opptatt",
+ "busy_male": "opptatt",
+ "Busy_male": "Opptatt",
+ "by": "av",
+ "Cancel": "Avbryt",
+ "Cancel_message_input": "Avbryt",
+ "channel": "kanal",
+ "Channel": "Kanal",
+ "Content": "Innhold"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/pl.i18n.json b/packages/rocketchat-i18n/i18n/pl.i18n.json
index 85a9d5cfc4144..0bf33bccf7910 100644
--- a/packages/rocketchat-i18n/i18n/pl.i18n.json
+++ b/packages/rocketchat-i18n/i18n/pl.i18n.json
@@ -1,19 +1,24 @@
{
+ "#channel": "#kanał",
"0_Errors_Only": "0 - Tylko błędy",
"1_Errors_and_Information": "1 - Błędy i informacje",
"2_Erros_Information_and_Debug": "2 - Błędy, Informacja i debugowanie",
"403": "Zabronione",
"500": "Wewnętrzny błąd serwera",
+ "@username": "@nazwa użytkownika",
+ "@username_message": "@nazwa użytkownika ",
"__username__is_no_longer__role__defined_by__user_by_": "__username__ nie jest już __role__ przez __user_by__",
"__username__was_set__role__by__user_by_": "__username__ ustalono __role__ przez __user_by__",
"Accept": "Akceptuj",
"Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Akceptuj przychodzące zaproszenia do livechat nawet gdy brak agentów online",
- "Accept_with_no_online_agents": "Akceptuj nawet bez agentów online",
+ "Accept_with_no_online_agents": "Akceptuj nawet bez dostępnych agentów",
"Access_not_authorized": "Dostęp zabroniony",
"Access_Token_URL": "Access Token URL",
"Accessing_permissions": "Uzyskiwanie dostępu",
- "Account_SID": "Account SID",
+ "Account_SID": "SID konta",
"Accounts": "Konta",
+ "Accounts_AllowAnonymousRead": "Pozwalaj na anonimowe czytanie",
+ "Accounts_AllowAnonymousWrite": "Pozwalaj na anonimowe pisanie",
"Accounts_AllowDeleteOwnAccount": "Zezwalaj użytkownikom na usunięcie własnego konta",
"Accounts_AllowedDomainsList": "Lista dozwolonych domen",
"Accounts_AllowedDomainsList_Description": "Lista dozwolonych domen oddzielona przecinkami",
@@ -24,17 +29,16 @@
"Accounts_AllowUserProfileChange": "Pozwól na zmienianie profilów użytkowników",
"Accounts_AvatarResize": "Zmiana rozmiaru avatarów",
"Accounts_AvatarSize": "Rozmiar avataru",
- "Accounts_AvatarStorePath": "Ścieżka przechowywania avatarów",
- "Accounts_AvatarStoreType": "Rodzaj magazynu avatarów",
"Accounts_BlockedDomainsList": "Lista zablokowanych domen",
"Accounts_BlockedDomainsList_Description": "Oddzielonych przecinkami lista zablokowanych domen",
"Accounts_BlockedUsernameList": "Lista zablokowanych użytkowników",
"Accounts_BlockedUsernameList_Description": "Oddzielona przecinkami lista zablokowanych użytkowników (bez uwzględniania wielkości liter)",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Domyślne powiadomnienia mobilne",
"Accounts_denyUnverifiedEmail": "Odrzucaj niezweryfikowane adresy email",
"Accounts_EmailVerification": "Weryfikacja adresu email",
"Accounts_EmailVerification_Description": "Upewnij się, że masz odpowiednie ustawienia SMTP by korzystać z tej funkcji",
"Accounts_Enrollment_Email": "Adres e-mail do rekrutacji",
- "Accounts_Enrollment_Email_Default": " Witamy w [Site_Name] Przejdź do [Site_URL] i spróbuj najlepszego rozwiązanie czat open source dostępne już dziś!
",
+ "Accounts_Enrollment_Email_Default": " Witamy w [Site_Name] Przejdź do [Site_URL] i spróbuj najlepszego rozwiązanie czat open source dostępne już dziś!
",
"Accounts_Enrollment_Email_Description": "Możesz użyć znaczników [name], [fname], [lname] by wstawić odpowiednio pełną nazwę użytkownika, jego imię, nazwisko. \nMożesz użyć znacznika [email] by wstawić adres email użytkownika.",
"Accounts_Enrollment_Email_Subject_Default": "Witamy w [Site_Name]",
"Accounts_Iframe_api_method": "Metoda Api",
@@ -51,10 +55,12 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "Identity Path",
"Accounts_OAuth_Custom_Login_Style": "Styl logowania",
+ "Accounts_OAuth_Custom_Merge_Users": "Przenieś użytkowników",
"Accounts_OAuth_Custom_Scope": "Zakres",
"Accounts_OAuth_Custom_Secret": "Secret",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token wysyłany przez",
+ "Accounts_OAuth_Custom_Username_Field": "Pole nazwa użytkownika",
"Accounts_OAuth_Facebook": "Facebook Login",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -83,12 +89,13 @@
"Accounts_OAuth_Meteor_callback_url": "Meteor Callback URL",
"Accounts_OAuth_Meteor_id": "Meteor Id",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_services": "Usługi Proxy",
"Accounts_OAuth_Twitter": "Twitter Login",
"Accounts_OAuth_Twitter_callback_url": "Twitter Callback URL",
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Login",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Zresetuj hasło",
@@ -99,13 +106,14 @@
"Accounts_RegistrationForm_Public": "Publiczny",
"Accounts_RegistrationForm_Secret_URL": "Sekretny adres URL",
"Accounts_RegistrationForm_SecretURL": "Sekretny adres URL formularza rejestracyjnego",
- "Accounts_RegistrationForm_SecretURL_Description": "Musisz podać losowy ciąg znaków, który zostanie dodany do adresu URL rejestracji. Przykład: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Musisz podać losowy ciąg znaków, który zostanie dodany do adresu URL rejestracji. Przykład: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Wymagaj podana nazwy podczas rejestracji",
"Accounts_RequirePasswordConfirmation": "Wymagaj potwierdzenia hasła",
+ "Accounts_SetDefaultAvatar": "Ustaw domyślny Avatar",
"Accounts_ShowFormLogin": "Pokaż formularz logowania",
"Accounts_UseDefaultBlockedDomainsList": "Użyj domyślnego Lista zablokowanych domen",
"Accounts_UseDNSDomainCheck": "Użyj DNS domeny Check",
- "Accounts_UserAddedEmail_Default": " Witamy w [Site_Name] Przejdź do [Site_URL] i spróbuj najlepsze rozwiązanie czat open source dostępne już dziś!
Możesz zalogować się przy użyciu adresu e-mail: [email] i hasło: [hasło]. Może być konieczne, aby go zmienić po pierwszym logowaniu.
",
+ "Accounts_UserAddedEmail_Default": " Witamy w [Site_Name] Przejdź do [Site_URL] i spróbuj najlepsze rozwiązanie czat open source dostępne już dziś!
Możesz zalogować się przy użyciu adresu e-mail: [email] i hasło: [hasło]. Może być konieczne, aby go zmienić po pierwszym logowaniu.
",
"Accounts_UserAddedEmail_Description": "Możesz użyć następujących symboli zastępczych: [name], [fname] [lname] dla pełnej nazwy użytkownika, imienia lub nazwiska, odpowiednio. [email] przez e-mail użytkownika. [password] o hasło użytkownika. [Site_Name] i [Site_URL] dla nazwy aplikacji i zawartości odpowiednio. ",
"Accounts_UserAddedEmailSubject_Default": "Zostałeś dodany do [Site_Name]",
"Activate": "Aktywuj",
@@ -113,7 +121,10 @@
"Add": "Dodaj",
"Add_agent": "Dodaj agenta",
"Add_custom_oauth": "Dodaj własne OAuth",
+ "Add_Domain": "Dodaj domenę",
+ "Add_files_from": "Dodaj pliki z",
"Add_manager": "Dodaj menedżera",
+ "Add_Role": "Dodaj rolę",
"Add_user": "Dodaj użytkownika",
"Add_User": "Dodaj użytkownika",
"Add_users": "Dodaj użytkowników",
@@ -123,6 +134,7 @@
"Additional_emails": "Dodatkowe adresy e-mail",
"Additional_Feedback": "Dodatkowy komentarz",
"Administration": "Administracja",
+ "Adult_images_are_not_allowed": "Obrazy dla dorosłych nie są dozwolone",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Po uwierzytelnieniu OAuth2, użytkownik zostanie przekierowany na ten adres URL",
"Agent": "Agent",
"Agent_added": "Agent dodany",
@@ -144,8 +156,10 @@
"and": "i",
"And_more": "I __length__ więcej",
"Animals_and_Nature": "Fauna & Flora",
+ "Announcement": "Ogłoszenie",
"API": "API",
"API_Analytics": "Analytics",
+ "API_Default_Count": "Domyślny licznik",
"API_Embed": "Osadź",
"API_Embed_Description": "Czy podgląd umieszczanych linków do stron przez użytkownika jest aktywny.",
"API_EmbedDisabledFor": "Wyłącz osadzanie dla użytkowników",
@@ -175,6 +189,7 @@
"Assign_admin": "Przypisywanie admina",
"at": "w",
"Attachment_File_Uploaded": "Plik wysłany",
+ "Audio_message": "Wiadomość audio",
"Auth_Token": "Auth Token",
"Author": "Autor",
"Authorization_URL": "URL autoryzacji",
@@ -189,6 +204,7 @@
"AutoLinker_Urls_TLD": "URL AutoLinker TLD",
"AutoLinker_Urls_www": "URL AutoLinker \"www\"",
"AutoLinker_UrlsRegExp": "AutoLinker URL Regular Expression",
+ "Automatic_Translation": "Automatyczne tłumaczenie",
"Available": "Dostępny",
"Available_agents": "Dostępni agenci",
"Avatar": "Avatary",
@@ -203,9 +219,11 @@
"Away_male": "Zaraz wracam",
"Back": "Wstecz",
"Back_to_applications": "Powrót do aplikacji",
+ "Back_to_chat": "Wróć do czatu",
"Back_to_integrations": "Powrót do integracji",
"Back_to_login": "Wróć do strony logowania",
"Back_to_permissions": "Powrót do uprawnień",
+ "Block_User": "Zablokować użytkownika",
"Body": "Zawartość",
"bold": "pogrubienie",
"bot_request": "Żądanie bota",
@@ -219,6 +237,7 @@
"busy_male": "zajęty",
"Busy_male": "Zajęty",
"by": "by",
+ "cache_cleared": "Wyczyszczono cache",
"Cancel": "Anuluj",
"Cancel_message_input": "Anuluj",
"Cannot_invite_users_to_direct_rooms": "Nie możnesz zaprosić użytkowników do bezpośrednich pokoi",
@@ -236,6 +255,7 @@
"CAS_version": "Wersja CAS",
"CDN_PREFIX": "Prefiks CDN",
"Certificates_and_Keys": "Certyfikaty i klucze",
+ "Change_Room_Type": "Zmiana typu pokoju",
"Changing_email": "Zmiana e-mail",
"channel": "kanał",
"Channel": "Kanał",
@@ -273,6 +293,7 @@
"Comment_to_leave_on_closing_session": "Komentarz pozostawiany przy zamknięciu sesji",
"Compact": "Kompaktowy",
"Confirm_password": "Potwierdź hasło",
+ "Content": "Zawartość",
"Conversation": "Rozmowa",
"Conversation_closed": "Rozmowa zamknięty: __comment__.",
"Convert_Ascii_Emojis": "Konwertuj ASCII do Emoji",
@@ -304,8 +325,11 @@
"Custom_Script_Logged_In": "Skrypt dla zalogowanych użytkowników",
"Custom_Script_Logged_Out": "Skrypt dla niezalogowanych użytkowników",
"Custom_Translations": "Własne tłumaczenia",
+ "CustomSoundsFilesystem": "Niestandardowy system plików dźwiękowych",
"Dashboard": "Panel",
"Date": "Data",
+ "Date_From": "Od",
+ "Date_to": "do",
"days": "dni",
"DB_Migration": "Migracja bazy danych",
"DB_Migration_Date": "Data migracji bazy danych",
@@ -331,11 +355,32 @@
"Desktop_Notifications_Enabled": "Powiadomienia na pulpicie są włączone",
"Direct_message_someone": "Wyślij bezpośrednią wiadomość",
"Direct_Messages": "Prywatne wiadomości",
+ "Direct_Reply": "Bezpośrednia odpowiedź",
+ "Direct_Reply_Debug": "Debuguj bezpośrednią odpowiedź",
+ "Direct_Reply_Debug_Description": "[Uwaga] Włączenie trybu debugowania wyświetli 'Zwykłym tekstem' twoje hasło w konsoli administracyjnej.",
+ "Direct_Reply_Delete": "Usuwanie przechwyconych wiadomości e-mail",
+ "Direct_Reply_Enable": "Włącz bezpośrednią odpowiedź",
+ "Direct_Reply_Frequency": "Częstotliwość sprawdzania poczty e-mail",
+ "Direct_Reply_Frequency_Description": "(w minutach, domyślnie/minimum 2)",
+ "Direct_Reply_Host": "Odpowiedź Bezpośrednia Host",
+ "Direct_Reply_IgnoreTLS": "Ignoruj TLS",
+ "Direct_Reply_Password": "Hasło",
+ "Direct_Reply_Port": "Odpowiedź Bezpośrednia Port",
+ "Direct_Reply_Protocol": "Protokół bezpośredniej odpowiedzi",
+ "Direct_Reply_Separator": "Separator",
+ "Direct_Reply_Separator_Description": "[Zmiana tylko wtedy, gdy wiesz dokładnie, co robisz, zapoznaj się z dokumentami] Separator pomiędzy częścią bazową i znacznikiem wiadomości e-mail",
+ "Direct_Reply_Username": "Nazwa użytkownika",
+ "Direct_Reply_Username_Description": "Proszę użyj absolutnego adresu e-mail, tagowanie nie jest dozwolone, bo byłoby nadpisane",
+ "Disable_Notifications": "Wyłącz powiadomienia",
+ "Disable_two-factor_authentication": "Wyłącz uwierzytelnianie dwuskładnikowe",
"Display_offline_form": "Pokaż formularz nieaktywny",
"Displays_action_text": "Wyświetla tekst akcji",
"Do_you_want_to_change_to_s_question": "Czy chcesz zmienić na %s ?",
"Domain": "Domena",
+ "Domain_added": "domena dodana",
+ "Domain_removed": "Usunięto domenę",
"Domains": "domeny",
+ "Download_Snippet": "Pobierz",
"Drop_to_upload_file": "Przeciągnij, aby przesłać plik",
"Dry_run": "Próba",
"Dry_run_description": "Wyśle tylko jedną wiadomość e-mail, na adres podany w polu `Od`. Adres e-mail musi należeć do istniejącego użytkownika.",
@@ -369,13 +414,16 @@
"Empty_title": "Pusty tytuł",
"Enable": "Włącz",
"Enable_Desktop_Notifications": "Włącz powiadomienia na pulpicie",
+ "Enable_two-factor_authentication": "Włącz uwierzytelnianie dwuskładnikowe",
"Enabled": "Włączone",
"Encrypted_message": "Zaszyfrowana wiadomość",
"End_OTR": "Koniec OTR",
"Enter_a_regex": "Wprowadź regex",
"Enter_a_room_name": "Wpisz nazwę pokoju",
"Enter_a_username": "Nazwa użytkownika",
+ "Enter_authentication_code": "Wprowadź kod uwierzytelnienia",
"Enter_name_here": "Wpisz nazwę tutaj",
+ "Enter_Normal": "Tryb normalny (wysyłaj klawiszem Enter)",
"Enter_to": "Naciśnij Enter: ",
"Error": "Błąd",
"error-action-not-allowed": "__action__ jest niedozwolone",
@@ -403,9 +451,11 @@
"error-invalid-channel-start-with-chars": "Nieprawidłowy kanał. Rozpocznij z @ lub #",
"error-invalid-custom-field": "Nieprawidłowe pole",
"error-invalid-custom-field-name": "Nieprawidłowa nazwa pole niestandardowe. Używaj tylko litery, cyfry, łączniki i podkreślenia.",
+ "error-invalid-date": "Nieprawidłowa data.",
"error-invalid-description": "Nieprawidłowy opis",
"error-invalid-domain": "Nieprawidłowa domena",
"error-invalid-email": "Nieprawidłowy email: __email__",
+ "error-invalid-email-address": "Niepoprawny adres email",
"error-invalid-file-height": "Nieprawidłowa wysokość pliku",
"error-invalid-file-type": "Nieprawidłowy typ pliku",
"error-invalid-file-width": "Nieprawidłowa szerokość pliku",
@@ -490,6 +540,8 @@
"Force_SSL": "Wymuś SSL",
"Force_SSL_Description": "* Uwaga! * _Force SSL_ nigdy nie powinno być stosowane z reverse proxy. Jeśli masz reverse proxy, należy zrobić przekierowanie tam. Opcja ta istnieje dla wdrożeń, np. na Heroku, który nie pozwala na konfigurację przekierowania przez reverse proxy.",
"Forgot_password": "Zapomniałeś hasła",
+ "Forgot_Password_Email": "Kliknij tutaj , aby zresetować hasło.\n",
+ "Forgot_password_section": "Zapomniałeś hasła",
"Forward": "Przekaż",
"Forward_chat": "Przekaż czat",
"Forward_to_department": "Przekaż do oddziału",
@@ -505,15 +557,25 @@
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Nadaj aplikacji nazwę. Będzie ona widoczna dla użytkowników.",
"Global": "Światowy",
"GoogleTagManager_id": "Menedżer tagów Google Id",
+ "GoogleVision_Type_Document": "Wykrywanie tekstu dokumentu",
+ "GoogleVision_Type_Faces": "Wykrywanie twarzy",
+ "GoogleVision_Type_Labels": "Wykrywanie etykiet",
+ "GoogleVision_Type_Landmarks": "Wykrywanie cech charakterystycznych",
+ "GoogleVision_Type_Logos": "Wykrywanie logotypu",
+ "GoogleVision_Type_Similar": "Znajdź podobne obrazy",
"Hash": "Hash",
"Header": "Nagłówek",
+ "Header_and_Footer": "Nagłówek i stopka",
"Hidden": "Ukryty",
"Hide_Avatars": "Ukryj avatary",
"Hide_flextab": "Ukryj prawy sidebar po kliknięciu",
"Hide_Group_Warning": "Czy na pewno chcesz ukryć grupę \" %s\"?",
+ "Hide_Livechat_Warning": "Czy na pewno chcesz ukryć livechat z \"%s\"?",
"Hide_Private_Warning": "Czy na pewno chcesz ukryć dyskusję z \"%s\"?",
+ "Hide_roles": "Ukryj role",
"Hide_room": "Ukryj pokój",
"Hide_Room_Warning": "Czy na pewno chcesz ukryć pokój \" %s\"?",
+ "Hide_Unread_Room_Status": "Ukryj nieprzeczytany stan pokoju",
"Hide_usernames": "Ukrywanie nazw użytkowników",
"Highlights": "Podświetlane słowa",
"Highlights_How_To": "Aby otrzymywać powiadomienie, gdy ktoś wspomina słowo lub frazę, dodaj go tutaj. Można oddzielić słowa lub wyrażenia przecinkami. Podświetlane słowa nie są wrażliwe na wielkość liter.",
@@ -530,6 +592,9 @@
"How_to_handle_open_sessions_when_agent_goes_offline": "Co robić z otwartymi sesjami gdy agent offline",
"If_you_are_sure_type_in_your_password": "Jeżeli jesteś pewien, wpisz swoje hasło:",
"If_you_are_sure_type_in_your_username": "Jeżeli jesteś pewien, wpisz swoją nazwę użytkownika:",
+ "Iframe_Integration": "Integracja z ramkami iframe",
+ "Iframe_Integration_receive_enable": "Włącz Odbierz",
+ "Iframe_Integration_send_enable": "Włącz Send",
"Importer_Archived": "Zarchiwizowane",
"Importer_done": "Importowanie zakończone!",
"Importer_finishing": "Kończąc się na import.",
@@ -558,11 +623,21 @@
"Installed_at": "Zainstalowany o",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instrukcje dla odwiedzającego wypełnić formularz, aby wysłać wiadomość",
"Integration_added": "Integracja została dodana",
+ "Integration_Advanced_Settings": "Zaawansowane ustawienia",
"Integration_Incoming_WebHook": "Integracja: Przychodzący WebHook",
"Integration_New": "Nowy Integracja",
"Integration_Outgoing_WebHook": "Integracja: Wychodzący WebHook",
+ "Integration_Retry_Delay": "Ponów próbę opóźnienia",
+ "Integration_Run_When_Message_Is_Edited": "Uruchom Edytory",
"Integration_updated": "Integracja została zaktualizowana",
"Integrations": "Integracje",
+ "Integrations_Outgoing_Type_FileUploaded": "Plik przesłany",
+ "Integrations_Outgoing_Type_RoomArchived": "Pokój zarchiwizowany",
+ "Integrations_Outgoing_Type_RoomCreated": "Pokój utworzony (publiczny i prywatny)",
+ "Integrations_Outgoing_Type_RoomJoined": "Użytkownik dołączył do pokoju",
+ "Integrations_Outgoing_Type_RoomLeft": "Użytkownik opuścił pokoju",
+ "Integrations_Outgoing_Type_SendMessage": "Wiadomość wysłana",
+ "Integrations_Outgoing_Type_UserCreated": "Użytkownik utworzony",
"InternalHubot": "Wewnętrzny Hubot",
"InternalHubot_ScriptsToLoad": "Skrypty do załadowania",
"InternalHubot_ScriptsToLoad_Description": "Wpisz oddzielone przecinkami listę skryptów załadować z https://github.com/github/hubot-scripts/tree/master/src/scripts",
@@ -585,6 +660,7 @@
"Invitation_Subject_Default": "Zostałeś zaproszony do [Site_Name]",
"Invite_user_to_join_channel": "Zaproś użytkownika by dołączył do kanału",
"Invite_Users": "Zaproś użytkowników",
+ "IRC_Hostname": "Serwer hosta IRC, z którym się nawiążesz.",
"is_also_typing": "również pisze",
"is_also_typing_female": "pisze",
"is_also_typing_male": "również pisze",
@@ -606,12 +682,19 @@
"Jump_to_first_unread": "Przejdź do pierwszej nieprzeczytanej",
"Jump_to_message": "Skocz do wiadomości",
"Jump_to_recent_messages": "Przejdź do ostatnich wiadomości",
+ "Just_invited_people_can_access_this_channel": "Zaproszeni ludzie mogą uzyskać dostęp do tego kanału",
"Katex_Dollar_Syntax": "Pozwól Dolar Składnia",
"Katex_Dollar_Syntax_Description": "Pozwól użyciu bloku KATEX $$ $$ $ i $ inline KATEX składnie",
"Katex_Enabled": "KATEX Włączony",
"Katex_Enabled_Description": "Pozwól użyciu KATEX do składu matematyki w wiadomościach",
"Katex_Parenthesis_Syntax": "Pozwól Parenthesis Składnia",
"Katex_Parenthesis_Syntax_Description": "Pozwól używając \\ [blokowe KATEX \\] i \\ (inline KATEX \\) składnie",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Edytuj poprzednią wiadomość",
+ "Keyboard_Shortcuts_Keys_2": "Strzałka w górę ",
+ "Keyboard_Shortcuts_Keys_3": "Polecenie (lub Alt ) + Strzałka w lewo ",
+ "Keyboard_Shortcuts_Keys_4": "Polecenie (lub Alt ) + Strzałka w górę ",
+ "Keyboard_Shortcuts_Keys_5": "Polecenie (lub Alt ) + Strzałka w prawo\n ",
+ "Keyboard_Shortcuts_Keys_6": "Polecenie (lub Alt ) + Strzałka w dół\n ",
"Knowledge_Base": "Baza wiedzy",
"Label": "Etykieta",
"Language": "Język",
@@ -629,31 +712,18 @@
"Layout_Terms_of_Service": "Regulamin",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Szukaj Domena niestandardowa",
- "LDAP_Custom_Domain_Search_Description": "Kawałek JSON, który reguluje powiązania i połączenia informacji i ma postać: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domyślna domena",
"LDAP_Description": "LDAP to hierarchiczna baza danych wykorzystywana przez wiele firm w celu udostępniania pojedynczej usługi autoryzacji użytkowników pomiędzy wieloma serwisami. Aby uzyskać dodatkowe informacje i przykłady konfiguracji, odwiedź nasze wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Baza domeny",
- "LDAP_Domain_Base_Description": "W pełni kwalifikowana nazwa wyróżniająca (DN) w poddrzewie LDAP chcesz wyszukać użytkowników i grup. Możesz dodać tyle, ile zechcesz; Jednakże, każda grupa musi być określona w ten sam bazie domeny jako użytkowników należących do niego. Jeśli podasz niewielkich grup użytkowników, tylko użytkownicy należący do tych grup będzie w zasięgu. Zaleca się, aby określić górny poziom drzewa katalogów LDAP jako baza domeny i użyć filtru wyszukiwania w celu kontroli dostępu.",
- "LDAP_Domain_Search_Filter": "Domeny Filtr wyszukiwania",
- "LDAP_Domain_Search_Filter_Description": "Jeśli określony, tylko użytkownicy pasujących ten filtr będzie mógł zalogować. Jeśli filtr nie jest określony, wszyscy użytkownicy w zakresie określonym bazie domeny będą mogli się zalogować. Np Active Directory `memberOf = cn = ROCKET_CHAT, ou = Ogólne Groups`. Np OpenLDAP (rozszerzalny wyszukiwania match) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Kategoria",
- "LDAP_Domain_Search_Object_Category_Description": "* Przy objectCategory *, które identyfikują użytkowników. Zostaw pusty * OpenLDAP *. Np `osoba prowadząca, etc.",
- "LDAP_Domain_Search_Object_Class": "Domain Search Object Class",
- "LDAP_Domain_Search_Object_Class_Description": "Gwiazdka * * objectclass które identyfikują użytkowników. Np `organizationalPerson`,` użytkownik portu, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Domain Search Hasło",
- "LDAP_Domain_Search_Password_Description": "Hasło dla użytkownika wyszukiwarki domeny.",
- "LDAP_Domain_Search_User": "Domeny Szukaj użytkownika",
- "LDAP_Domain_Search_User_Description": "Użytkownik LDAP, który wykonuje wyszukiwań użytkowników do uwierzytelnienia innych użytkowników podczas logowania się. Jest to zazwyczaj konto usługi stworzony specjalnie dla integracji osób trzecich. Użyj pełnej nazwy, takie jak `cn = Administrator, CN = Users, DC = example, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search ID użytkownika",
- "LDAP_Domain_Search_User_ID_Description": "Atrybut LDAP, która identyfikuje użytkownika LDAP, który próbuje uwierzytelnienia. To pole powinno być `sAMAccountName` dla instalacji najbardziej Active Directory, ale może to być` uid` innych rozwiązań, takich jak LDAP OpenLDAP. Można użyć `mail` celu identyfikacji użytkowników przez e-mail lub cokolwiek atrybut chcesz. Można użyć wielu wartości oddzielonych przecinkiem, aby umożliwić użytkownikom, aby zalogować się za pomocą wielu identyfikatorów, takich jak nazwa użytkownika lub adres e-mail.",
+ "LDAP_BaseDN_Description": "W pełni kwalifikowana nazwa wyróżniająca (DN) w poddrzewie LDAP chcesz wyszukać użytkowników i grup. Możesz dodać tyle, ile zechcesz; Jednakże, każda grupa musi być określona w ten sam bazie domeny jako użytkowników należących do niego. Jeśli podasz niewielkich grup użytkowników, tylko użytkownicy należący do tych grup będzie w zasięgu. Zaleca się, aby określić górny poziom drzewa katalogów LDAP jako baza domeny i użyć filtru wyszukiwania w celu kontroli dostępu.",
+ "LDAP_User_Search_Field_Description": "Atrybut LDAP, która identyfikuje użytkownika LDAP, który próbuje uwierzytelnienia. To pole powinno być `sAMAccountName` dla instalacji najbardziej Active Directory, ale może to być` uid` innych rozwiązań, takich jak LDAP OpenLDAP. Można użyć `mail` celu identyfikacji użytkowników przez e-mail lub cokolwiek atrybut chcesz. Można użyć wielu wartości oddzielonych przecinkiem, aby umożliwić użytkownikom, aby zalogować się za pomocą wielu identyfikatorów, takich jak nazwa użytkownika lub adres e-mail.",
+ "LDAP_User_Search_Filter_Description": "Jeśli określony, tylko użytkownicy pasujących ten filtr będzie mógł zalogować. Jeśli filtr nie jest określony, wszyscy użytkownicy w zakresie określonym bazie domeny będą mogli się zalogować. Np Active Directory `memberOf = cn = ROCKET_CHAT, ou = Ogólne Groups`. Np OpenLDAP (rozszerzalny wyszukiwania match) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Użytkownik LDAP, który wykonuje wyszukiwań użytkowników do uwierzytelnienia innych użytkowników podczas logowania się. Jest to zazwyczaj konto usługi stworzony specjalnie dla integracji osób trzecich. Użyj pełnej nazwy, takie jak `cn = Administrator, CN = Users, DC = example, dc = com`.",
"LDAP_Enable": "Włącz LDAP",
"LDAP_Enable_Description": "Włącza LDAP podczas uwierzytelniania.",
"LDAP_Encryption": "Szyfrowanie",
"LDAP_Encryption_Description": "Metoda szyfrowania wykorzystywany do zabezpieczenia komunikacji z serwerem LDAP. Przykłady obejmują `plain` (bez szyfrowania),` SSL / LDAPS` (zaszyfrowany od początku) i `StartTLS` (upgrade do szyfrowanej komunikacji po podłączeniu).",
"LDAP_Host": "Host",
"LDAP_Host_Description": "Gospodarz LDAP, np `ldap.example.com` lub` 10.0.0.30`.",
- "LDAP_Import_Users": "Importuj użytkowników LDAP",
"LDAP_Login_Fallback_Description": "Jeżeli logowanie LDAP zakończy się niepowodzeniem, spróbuj zalogować lokalnie. Pomocne w przypadku gdy LDAP jest nieosiągalny.",
"LDAP_Merge_Existing_Users": "Połącz istniejących użytkowników",
"LDAP_Port": "Port LDAP",
@@ -664,12 +734,9 @@
"LDAP_Sync_User_Data_Description": "Utrzymuj dane (np: nazwa, email) w synchronizacji z serwerem podczas logowania",
"LDAP_Sync_User_Data_FieldMap": "Mapa pól użytkownika",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfigurowanie sposobu w jaki pola kont (np. email) są uzupełniane z rekordów LDAP (gdy takowe zostaną znalezione). Na przykład podając `{\"cn\":\"name\", \"mail\":\"email\"}` system wybierze wyświetlaną nazwę użytkownika z pola cn i jego adres email z pola email. Dostępne pola to: `name`, `email`.",
- "LDAP_Sync_Users": "Użytkownicy Sync",
"LDAP_Test_Connection": "Testuj połączenie",
"LDAP_Unique_Identifier_Field": "Unikalny Identyfikator Pole",
"LDAP_Unique_Identifier_Field_Description": "To które będą stosowane do łączenia użytkownika LDAP i użytkownika Rocket.Chat. Możesz poinformować wiele wartości oddzielonych przecinkiem, aby postarać się o wartość z rejestru LDAP. Domyślną wartością jest `objectGUID IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Użyj wyszukiwarki Domena niestandardowa",
- "LDAP_Use_Custom_Domain_Search_Description": "Wpisz swój własny filtr do wyszukiwania użytkowników na serwerze LDAP.",
"LDAP_Username_Field": "Nazwa pola",
"LDAP_Username_Field_Description": "Które pole będzie używany jako nazwa użytkownika * * Dla nowych użytkowników. Zostaw puste, aby użyć nazwy użytkownika informować na stronie logowania. Można używać znaczników szablonów też, podobnie jak `#{givenName}.#{sn}`. Domyślną wartością jest `sAMAccountName`.",
"Least_Amount": "Ostatnia ilość",
@@ -781,6 +848,8 @@
"Meta_robots": "Roboty",
"Min_length_is": "Minimalna długość to %s",
"minutes": "minut",
+ "Mobile": "Powiadomnienia mobilne",
+ "Mobile_Notifications_Default_Alert": "Domyślne powiadomnienia mobilne",
"Monday": "Poniedziałek",
"Monitor_history_for_changes_on": "Sprawdź historię zmian na",
"More_channels": "Więcej kanałów",
@@ -793,6 +862,7 @@
"Mute_user": "Wycisz użytkownika",
"Muted": "Wyciszony",
"My_Account": "Moje konto",
+ "My_location": "Moja lokalizacja",
"n_messages": "%s wiadomości",
"N_new_messages": " %s nowych wiadomości",
"Name": "Nazwa",
@@ -831,6 +901,7 @@
"Nothing_found": "Nic nie znaleziono",
"Notification_Duration": "Czas trwania powiadomienia",
"Notifications": "Powiadomienia",
+ "Notifications_Sound_Volume": "Głośność powiadomienia ",
"Notify_all_in_this_room": "Powiadom wszystkich w pokoju",
"Num_Agents": "# agentów",
"Number_of_messages": "Ilość wiadomości",
@@ -857,6 +928,7 @@
"optional": "opcjonalne",
"or": "lub",
"Order": "Kolejność",
+ "Original": "Oryginalny",
"OS_Arch": "Architektura systemu",
"OS_Cpus": "Ilość procesorów",
"OS_Freemem": "Ilość wolnej pamięci",
@@ -915,6 +987,8 @@
"Private_Groups": "Prywatne grupy",
"Private_Groups_list": "Lista prywatnych grup",
"Profile": "Profil",
+ "Profile_details": "Szczegóły profilu",
+ "Profile_picture": "Zdjęcie profilowe",
"Profile_saved_successfully": "Dane zostały zapisane",
"Public": "Publiczny",
"Push": "Powiadomienia",
@@ -1022,6 +1096,7 @@
"Search_Private_Groups": "Wyszukaj prywatne grupy",
"seconds": "sekund",
"Secret_token": "Tajny tokena",
+ "Security": "Bezpieczeństwo",
"Select_a_department": "Wybierz dział",
"Select_a_user": "Wybierz użytkownika",
"Select_an_avatar": "Wybierz awatar",
@@ -1116,6 +1191,7 @@
"Stats_Total_Private_Groups": "Liczba grup prywatnych",
"Stats_Total_Rooms": "Liczba wszystkich pokoi",
"Stats_Total_Users": "Liczba użytkowników",
+ "Status": "Status",
"Stop_Recording": "Zatrzymaj nagrywanie",
"strike": "przekreślenie",
"Subject": "Temat",
@@ -1147,19 +1223,19 @@
"The_user_wont_be_able_to_type_in_s": "Użytkownik nie będzie mógł wpisać w %s",
"Theme": "Motyw",
"theme-color-content-background-color": "Kolor tła zawartości",
+ "theme-color-custom-scrollbar-color": "Niestandardowy kolor Scrollbar`a",
+ "theme-color-info-font-color": "Kolor czcionki informacji",
+ "theme-color-link-font-color": "Kolor czcionki odnośników",
"theme-color-primary-background-color": "Podstawowy kolor tła",
"theme-color-primary-font-color": "Podstawowy kolor czcionki",
"theme-color-secondary-background-color": "Dodatkowy kolor tła",
"theme-color-secondary-font-color": "Dodatkowy kolor czcionki",
- "theme-color-tertiary-background-color": "Trzeciorzędny kolor tła",
- "theme-color-tertiary-font-color": "Trzeciorzędny kolor czcionki",
- "theme-color-link-font-color": "Kolor czcionki odnośników",
- "theme-color-info-font-color": "Kolor czcionki informacji",
- "theme-color-custom-scrollbar-color": "Niestandardowy kolor Scrollbar`a",
"theme-color-status-away": "Kolor statusu Zaraz wracam",
"theme-color-status-busy": "Kolor statusu Zajęty",
"theme-color-status-offline": "Kolor statusu Niedostępny",
"theme-color-status-online": "Kolor statusu Online",
+ "theme-color-tertiary-background-color": "Trzeciorzędny kolor tła",
+ "theme-color-tertiary-font-color": "Trzeciorzędny kolor czcionki",
"theme-color-unread-notification-color": "Kolor nieprzeczytanych powiadomień",
"theme-custom-css": "Niestandardowy CSS",
"There_are_no_agents_added_to_this_department_yet": "Nie ma agentów dodanych do tego oddziału.",
@@ -1181,15 +1257,19 @@
"to_see_more_details_on_how_to_integrate": "aby zobaczyć więcej szczegółów na temat integracji.",
"To_users": "Do użytkowników",
"Topic": "Temat",
- "Travel_and_Places": "Podróże & Miejsca",
"Transcript_Enabled": "Zapytaj odwiedzających czy potrzebują transkryptu rozmowy po jej zakończeniu.",
"Transcript_message": "Wiadomość do wyświetlenia przy zapytaniu o transkrypt.",
"Transcript_of_your_livechat_conversation": "Transkrypt twojej rozmowy.",
+ "Travel_and_Places": "Podróże & Miejsca",
"Trigger_removed": "Wyzwalacz usunięty",
"Trigger_Words": "Słowa wyzwalające",
"Triggers": "Wyzwalacze",
"True": "Tak",
"Tuesday": "Wtorek",
+ "Two-factor_authentication": "Uwierzytelnianie dwuskładnikowe",
+ "Two-factor_authentication_disabled": "Wyłączono uwierzytelnianie dwuskładnikowe",
+ "Two-factor_authentication_enabled": "Włączono uwierzytelnianie dwuskładnikowe",
+ "Two-factor_authentication_is_currently_disabled": "Obecnie uwierzytelnianie dwuskładnikowe jest wyłączone\n",
"Type": "Rodzaj",
"Type_your_email": "Wpisz swój e-mail",
"Type_your_message": "Wpisz wiadomość",
@@ -1198,11 +1278,14 @@
"UI_DisplayRoles": "Pokaż role",
"UI_Merge_Channels_Groups": "Scalanie prywatne grupy z kanałami",
"Unarchive": "Przywróć",
+ "Unblock_User": "Odblokuj użytkownika",
"Unmute_someone_in_room": "Anuluj wyciszenie osoby w pokoju",
"Unmute_user": "Anuluj wyciszenie użytkownika",
"Unnamed": "Anonimowy",
"Unpin_Message": "Odepnij wiadomość",
- "Unread_Alert": "Alarm nieprzeczytany",
+ "Unread_Count": "Liczba nieprzeczytanych",
+ "Unread_Count_DM": "Liczba nieprzeczytanych dla bezpośrednich wiadomości",
+ "Unread_Messages": "Nieprzeczytane wiadomości",
"Unread_Rooms": "Nieprzeczytane pokoje",
"Unread_Rooms_Mode": "Tryb nieprzeczytanych pokoi",
"Unstar_Message": "Usuń oznaczenie",
@@ -1219,6 +1302,7 @@
"Use_uploaded_avatar": "Użyj dodany awatar",
"Use_url_for_avatar": "Użyj adresu URL",
"Use_User_Preferences_or_Global_Settings": "Użyj ustawień użytkownika lub ustawień globalnych",
+ "User": "Użytkownik",
"User__username__is_now_a_moderator_of__room_name_": "Użytkownik __username__ jest teraz moderatorem pokoju __room_name__",
"User__username__is_now_a_owner_of__room_name_": "Użytkownik __username__ jest teraz właścicielem pokoju __room_name__",
"User__username__removed_from__room_name__moderators": "Użytkownik __username__ usunięty z moderatorów pokoju __room_name__",
@@ -1272,10 +1356,13 @@
"UTF8_Names_Slugify": "Nazwy UTF8 Slugify",
"UTF8_Names_Validation": "Walidacja UTF8 nazw",
"UTF8_Names_Validation_Description": "Nie dopuszczaj znaków specjalnych i spacji. Można użyć `-`, `_` i `.`, ale nie na końcu nazwy",
+ "Verification": "Weryfikacja",
"Verification_email_sent": "E-mail weryfikacyjny został wysłany",
"Verified": "Zweryfikowany",
"Version": "Wersja",
"Video_Chat_Window": "Video Chat",
+ "Video_Conference": "Konferencja wideo",
+ "Video_message": "Wiadomość wideo",
"Videocall_declined": "Rozmowa video odrzucona.",
"Videocall_enabled": "Rozmowa video uruchomiona",
"View_All": "Pokaż wszystko",
@@ -1291,6 +1378,7 @@
"Visitor_page_URL": "Adres URL gościa",
"Visitor_time_on_site": "Czas gościa na stronie",
"Wait_activation_warning": "Zanim się zalogujesz, twoje konto musi być aktywowane przez administratora.",
+ "Warnings": "Ostrzeżenia",
"We_are_offline_Sorry_for_the_inconvenience": "Jesteśmy offline. Przepraszamy za niedogodności.",
"We_have_sent_password_email": "Wysłaliśmy Ci e-mail z instrukcjami resetowania hasła. Jeśli nie dostaniesz wiadomości, prosimy spróbować ponownie.",
"We_have_sent_registration_email": "Wysłaliśmy e-mail w celu potwierdzenie Twojej rejestracji. Jeśli nie dostaniesz wiadomości, prosimy spróbować ponownie.",
@@ -1307,6 +1395,7 @@
"Why_do_you_want_to_report_question_mark": "Dlaczego chcesz to zgłosić?",
"will_be_able_to": "będzie zdolny do",
"Yes": "Tak",
+ "Yes_archive_it": "Tak, archiwizuj!",
"Yes_clear_all": "Tak, wyczyść!",
"Yes_delete_it": "Tak, usuń to!",
"Yes_hide_it": "Tak, ukryj!",
@@ -1342,6 +1431,8 @@
"Your_entry_has_been_deleted": "Twój wpis został usunięty.",
"Your_file_has_been_deleted": "Twój plik został usunięty.",
"Your_mail_was_sent_to_s": "Twoja wiadomość została wysłana do użytkownika %s",
+ "your_message": "twoja wiadomość",
+ "your_message_optional": "twoja wiadomość (opcjonalnie)",
"Your_password_is_wrong": "To nie jest poprawne hasło!",
"Your_push_was_sent_to_s_devices": "Twój push została wysłany do urządzeń: %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json
new file mode 100644
index 0000000000000..d869357e085bc
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json
@@ -0,0 +1,1326 @@
+{
+ "#channel": "#canal",
+ "0_Errors_Only": "0 - Apenas erros",
+ "1_Errors_and_Information": "1 - Erros e Informações",
+ "2_Erros_Information_and_Debug": "2 - Erros, Informação e Debug",
+ "403": "Proibido",
+ "500": "Erro Interno do Servidor",
+ "@username": "@username",
+ "@username_message": "@usuario ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ não pertence mais à __role__, por __user_by__",
+ "__username__was_set__role__by__user_by_": "__username__ foi definido como __role__ por __user_by__",
+ "Accept": "Aceitar",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Aceitar requisições de livechat mesmo se não houverem agentes online",
+ "Accept_with_no_online_agents": "Aceitar sem agentes online",
+ "Access_not_authorized": "Acesso não autorizado",
+ "Access_Token_URL": "URL do Token de Acesso",
+ "Accessing_permissions": "Acessando permissões",
+ "Account_SID": "SID da Conta",
+ "Accounts": "Contas",
+ "Accounts_AllowDeleteOwnAccount": "Permitir que usuários apaguem a própria conta",
+ "Accounts_AllowedDomainsList": "Lista de domínios permitidos",
+ "Accounts_AllowedDomainsList_Description": "Lista de domínios permitidos, separados por vírgula",
+ "Accounts_AllowEmailChange": "Permitir alterar e-mail",
+ "Accounts_AllowPasswordChange": "Permitir Alteração de Senha",
+ "Accounts_AllowUserAvatarChange": "Permitir que o usuário troque o avatar",
+ "Accounts_AllowUsernameChange": "Permitir alterar nome de usuário",
+ "Accounts_AllowUserProfileChange": "Permitir que o usuário altere o perfil",
+ "Accounts_AvatarResize": "Redimensionar Avatares",
+ "Accounts_AvatarSize": "Tamanho do Avatar",
+ "Accounts_BlockedDomainsList": "Lista de Domínios Bloqueados",
+ "Accounts_BlockedDomainsList_Description": "Lista de domínios bloqueados, separados por vírgulas ",
+ "Accounts_BlockedUsernameList": "Lista de nomes de usuário bloqueados",
+ "Accounts_BlockedUsernameList_Description": "Lista de nomes de usuários bloqueados, separada por vírgulas (não diferencia maiúsculas)",
+ "Accounts_CustomFields_Description": "Deve ser um JSON válido onde as chaves são os nomes de campos contendo um dicionário de configuração de campos. Exemplo:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"estudante\",\n \"options\": [\"professor\", \"estudante\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Campos personalizados a exibir",
+ "Accounts_Default_User_Preferences": "Preferências Padrões do Usuário",
+ "Accounts_Default_User_Preferences_audioNotifications": "Áudio padrão para alerta de notificação",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Alerta padrão para notificações Desktop",
+ "Accounts_Default_User_Preferences_mobileNotifications": "Alerta padrão para notificações Mobile",
+ "Accounts_denyUnverifiedEmail": "Proibir e-mail não verificado",
+ "Accounts_EmailVerification": "Verificação de E-mail",
+ "Accounts_EmailVerification_Description": "Certifique-se de que as configurações de SMTP estão corretas para usar este recurso",
+ "Accounts_Enrollment_Email": "E-mail de inscrição",
+ "Accounts_Enrollment_Email_Default": "Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
",
+ "Accounts_Enrollment_Email_Description": "Você pode usar [name], [fname], [lname] para o nome completo, primeiro nome ou último nome do usuário, respectivamente. Você pode usar [email] para o email do usuário.",
+ "Accounts_Enrollment_Email_Subject_Default": "Bem-vindo ao [Site_Name]",
+ "Accounts_Iframe_api_method": "Método Api",
+ "Accounts_Iframe_api_url": "URL da API",
+ "Accounts_iframe_enabled": "Habilitado",
+ "Accounts_iframe_url": "Url do Iframe",
+ "Accounts_LoginExpiration": "Validade do Login em Dias",
+ "Accounts_ManuallyApproveNewUsers": "Aprovar manualmente novos usuários",
+ "Accounts_OAuth_Custom_Authorize_Path": "Authorize Path",
+ "Accounts_OAuth_Custom_Button_Color": "Cor do botão",
+ "Accounts_OAuth_Custom_Button_Label_Color": "Cor do texto do botão",
+ "Accounts_OAuth_Custom_Button_Label_Text": "Texto do botão",
+ "Accounts_OAuth_Custom_Enable": "Enable",
+ "Accounts_OAuth_Custom_id": "Id",
+ "Accounts_OAuth_Custom_Identity_Path": "Identity Path",
+ "Accounts_OAuth_Custom_Login_Style": "Estilo de Login",
+ "Accounts_OAuth_Custom_Scope": "Escopo",
+ "Accounts_OAuth_Custom_Secret": "Secret",
+ "Accounts_OAuth_Custom_Token_Path": "Token Path",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Token Enviado Por",
+ "Accounts_OAuth_Facebook": "Login do Facebook",
+ "Accounts_OAuth_Facebook_callback_url": "URL de Callback do Facebook",
+ "Accounts_OAuth_Facebook_id": "Facebook App Id",
+ "Accounts_OAuth_Facebook_secret": "Facebook Secret",
+ "Accounts_OAuth_Github": "Login do GitHub",
+ "Accounts_OAuth_Github_callback_url": "URL de Callback do Github",
+ "Accounts_OAuth_GitHub_Enterprise": "OAuth Ativado",
+ "Accounts_OAuth_GitHub_Enterprise_callback_url": "URL de Callback do GitHub Enterprise",
+ "Accounts_OAuth_GitHub_Enterprise_id": "GitHub Id",
+ "Accounts_OAuth_GitHub_Enterprise_secret": "Segredo",
+ "Accounts_OAuth_Github_id": "GitHub Id",
+ "Accounts_OAuth_Github_secret": "GitHub Secret",
+ "Accounts_OAuth_Gitlab": "OAuth Ativado",
+ "Accounts_OAuth_Gitlab_callback_url": "URL de Callback do GitLab",
+ "Accounts_OAuth_Gitlab_id": "GitLab Id",
+ "Accounts_OAuth_Gitlab_secret": "Segredo",
+ "Accounts_OAuth_Google": "Login do Google",
+ "Accounts_OAuth_Google_callback_url": "URL de Callback do Google",
+ "Accounts_OAuth_Google_id": "Google Id",
+ "Accounts_OAuth_Google_secret": "Google Secret",
+ "Accounts_OAuth_Linkedin": "Login do LinkedIn",
+ "Accounts_OAuth_Linkedin_callback_url": "URL de Callback do Linkedin",
+ "Accounts_OAuth_Linkedin_id": "LinkedIn Id",
+ "Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
+ "Accounts_OAuth_Meteor": "Login do Meteor",
+ "Accounts_OAuth_Meteor_callback_url": "URL de Callback do Meteor",
+ "Accounts_OAuth_Meteor_id": "Meteor Id",
+ "Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Twitter": "Login do Twitter",
+ "Accounts_OAuth_Twitter_callback_url": "URL de Callback do Twitter",
+ "Accounts_OAuth_Twitter_id": "Twitter Id",
+ "Accounts_OAuth_Twitter_secret": "Twitter Secret",
+ "Accounts_OAuth_Wordpress": "Login WordPress",
+ "Accounts_OAuth_Wordpress_callback_url": "URL de Callback do Wordpress",
+ "Accounts_OAuth_Wordpress_id": "WordPress ID",
+ "Accounts_OAuth_Wordpress_secret": "WordPress Secret",
+ "Accounts_PasswordReset": "Resetar senha",
+ "Accounts_Registration_AuthenticationServices_Enabled": "Registro com os Serviços de Autenticação",
+ "Accounts_RegistrationForm": "Formulário de Registro",
+ "Accounts_RegistrationForm_Disabled": "Desativado",
+ "Accounts_RegistrationForm_LinkReplacementText": "Text de Substituição do Link do Formulário de Registro",
+ "Accounts_RegistrationForm_Public": "Público",
+ "Accounts_RegistrationForm_Secret_URL": "URL Secreta",
+ "Accounts_RegistrationForm_SecretURL": "URL Secreta para o Formulário de Registro",
+ "Accounts_RegistrationForm_SecretURL_Description": "Você deve fornecer uma seqüência aleatória que será adicionada à sua URL de registro. Exemplo: https://open.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "Nome é obrigatório para cadastro",
+ "Accounts_RequirePasswordConfirmation": "Requer Confirmação de Senha",
+ "Accounts_SearchFields": "Campos a considerar na busca",
+ "Accounts_ShowFormLogin": "Mostrar formulário de login",
+ "Accounts_UseDefaultBlockedDomainsList": "Use Lista Padrão de Domínios Bloqueados",
+ "Accounts_UseDNSDomainCheck": "Use verificação de Domínio DNS",
+ "Accounts_UserAddedEmail_Default": " Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
Você pode fazer o login usando seu e-mail: [email] e password: [password]. Você pode ser obrigado a mudá-lo após o seu primeiro login.",
+ "Accounts_UserAddedEmail_Description": "Você pode usar os seguintes espaços reservados:
[name], [fname], [lname] para o nome do usuário completo, primeiro nome ou sobrenome, respectivamente. [email] para e-mail do usuário. [Senha] para a senha do usuário. [Site_Name] e [Site_URL] para o nome do aplicativo e URL, respectivamente. ",
+ "Accounts_UserAddedEmailSubject_Default": "Você foi adicionado para [Site_Name]",
+ "Activate": "Ativar",
+ "Activity": "Atividade",
+ "Add": "Adicionar",
+ "Add_agent": "Adicionar agente",
+ "Add_custom_oauth": "Adicionar oauth customizado",
+ "Add_manager": "Adicionar gerente",
+ "Add_user": "Adicionar usuário",
+ "Add_User": "Adicionar Usuário",
+ "Add_users": "Adicionar usuários",
+ "Adding_OAuth_Services": "Adicionando Serviços OAuth",
+ "Adding_permission": "Adicionando permissão",
+ "Adding_user": "Adicionando usuário",
+ "Additional_emails": "E-mails adicionais",
+ "Additional_Feedback": "Comentários Adicionais",
+ "Administration": "Administração",
+ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Após a autenticação OAuth2, os usuários serão redirecionados para esta URL",
+ "Agent": "Agente",
+ "Agent_added": "Agente adicionado",
+ "Agent_removed": "Agente removido",
+ "Alias": "Apelido",
+ "Alias_Format": "Formato do apelido",
+ "Alias_Format_Description": "Importar mensagens do Slack com um apelido; %s será trocado pelo username do usuário. Se vazio, nenhum apelido será usado.",
+ "Alias_Set": "Conjunto de apelidos",
+ "All": "Todos",
+ "All_channels": "Todos os canais",
+ "All_logs": "Todos os logs",
+ "All_messages": "Todas as mensagens",
+ "Allow_Invalid_SelfSigned_Certs": "Permitir certificados inválidos e auto-assinados para validação de links e previews",
+ "Allow_Invalid_SelfSigned_Certs_Description": "Permitir certificado SSL inválidos e auto-assinados para validação de link e previews.",
+ "Analytics_features_enabled": "Funcionalidades habilitadas",
+ "Analytics_features_messages_Description": "Rastreia eventos personalizados relacionados a ações que um usuário faz em mensagens.",
+ "Analytics_features_rooms_Description": "Rastreia eventos personalizados relacionados com ações em um canal ou grupo (criar, sair, apague).",
+ "Analytics_features_users_Description": "Rastreia eventos personalizados relacionados às ações relacionadas aos usuários (tempos de redefinição de senha, mudança imagem de perfil, etc).",
+ "and": "e",
+ "And_more": "E mais __length__",
+ "Animals_and_Nature": "Animais e Natureza",
+ "API": "API",
+ "API_Analytics": "Analytics",
+ "API_Embed": "Embed",
+ "API_EmbedDisabledFor": "Desabilitar incorporação para usuários",
+ "API_EmbedDisabledFor_Description": "Lista de nomes de usuário separados por vírgula para desabilitar a pré-visualização de links embutidos",
+ "API_EmbedIgnoredHosts": "Incorporar Hosts Ignorados ",
+ "API_EmbedIgnoredHosts_Description": "Lista de hosts ou endereços CIDR separados por vírgulas (exemplo: localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)",
+ "API_EmbedSafePorts": "Portas de seguras",
+ "API_EmbedSafePorts_Description": "Lista de portas permitidas para pré-visualização separada por vírgulas.",
+ "API_GitHub_Enterprise_URL": "URL do servidor",
+ "API_GitHub_Enterprise_URL_Description": "Exemplo: http://dominio.com (excluindo barra final)",
+ "API_Gitlab_URL": "URL do GitLab",
+ "API_Token": "API Token",
+ "API_User_Limit": "Limite de usuários para adicionar todos os usuários para o canal",
+ "API_Wordpress_URL": "URL do WordPress",
+ "Apiai_Key": "Api.ai Key",
+ "Apiai_Language": "Idioma Api.ai",
+ "Appearance": "Aparência",
+ "Application_added": "Aplicação adicionada",
+ "Application_Name": "Nome da Aplicação",
+ "Application_updated": "Aplicação atualizada",
+ "Apply_and_refresh_all_clients": "Aplicar e atualizar todos os clientes",
+ "Archive": "Arquivar",
+ "are_also_typing": "também estão digitando",
+ "are_typing": "estão digitando",
+ "Are_you_sure": "Você tem certeza?",
+ "Are_you_sure_you_want_to_delete_your_account": "Tem certeza de que deseja excluir a sua conta?",
+ "Assign_admin": "Atribuindo administrador",
+ "at": "em",
+ "AtlassianCrowd": "Atlassian Crowd",
+ "Attachment_File_Uploaded": "Arquivo Carregado",
+ "Auth_Token": "Auth Token",
+ "Author": "Autor",
+ "Authorization_URL": "URL de Autorização",
+ "Authorize": "Autorizar",
+ "Auto_Load_Images": "Auto Carregar Imagens",
+ "AutoLinker_Email": "Aplicar para Email",
+ "AutoLinker_Phone": "Aplicar para Telefone",
+ "AutoLinker_Phone_Description": "Links automáticos para para números de telefone. Por exemplo, `(123) 456-7890`",
+ "AutoLinker_StripPrefix": "Remover Prefixo",
+ "AutoLinker_StripPrefix_Description": "Exibição curta. Por exemplo https://rocket.chat => rocket.chat",
+ "AutoLinker_Urls_Scheme": "Auto-linkar URLs com esquema://",
+ "AutoLinker_Urls_TLD": "Auto-linkar URLs de TLD",
+ "AutoLinker_Urls_www": "Auto-linkar URLs com 'www'",
+ "AutoLinker_UrlsRegExp": "Expressão Regular para URL",
+ "Available": "Disponível",
+ "Available_agents": "Agentes disponíveis",
+ "Avatar": "Avatar",
+ "Avatar_changed_successfully": "Avatar alterado com sucesso",
+ "Avatar_URL": "URL do Avatar",
+ "Avatar_url_invalid_or_error": "A URL fornecida é inválida ou não acessível. Por favor tente novamente, mas com uma url diferente.",
+ "away": "ausente",
+ "Away": "Ausente",
+ "away_female": "ausente",
+ "Away_female": "Ausente",
+ "away_male": "ausente",
+ "Away_male": "Ausente",
+ "Back": "Voltar",
+ "Back_to_applications": "Voltar para aplicações",
+ "Back_to_integrations": "Voltar para integrações",
+ "Back_to_login": "Voltar para o login",
+ "Back_to_permissions": "Voltar para permissões",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Funcionalidade Beta! Depende que Vídeo Conferência esteja habilitado",
+ "Body": "Corpo",
+ "bold": "negrito",
+ "bot_request": "Requisição de Bot",
+ "BotHelpers_userFields": "Campos de usuário",
+ "Branch": "Ramo",
+ "busy": "ocupado",
+ "Busy": "Ocupado",
+ "busy_female": "ocupado",
+ "Busy_female": "Ocupado",
+ "busy_male": "ocupado",
+ "Busy_male": "Ocupado",
+ "by": "por",
+ "Cancel": "Cancelar",
+ "Cancel_message_input": "Cancelar",
+ "Cannot_invite_users_to_direct_rooms": "Não é possível convidar pessoas para salas diretas",
+ "CAS_button_color": "Cor de fundo do botão de login",
+ "CAS_button_label_color": "Cor de texto do botão de login",
+ "CAS_button_label_text": "Nome do botão de login",
+ "CAS_enabled": "Habilitado",
+ "CAS_login_url": "URL de login SSO",
+ "CAS_login_url_Description": "A URL de login de seu serviço SSO externo (exemplo: https://sso.exemplo.indef/sso/login)",
+ "CAS_popup_height": "Altura da janela instantânea de login",
+ "CAS_popup_width": "Largura da janela instantânea de login",
+ "CAS_Sync_User_Data_Enabled": "Sempre sincronizar dados do usuário",
+ "CAS_Sync_User_Data_FieldMap": "Mapa de atributos",
+ "CDN_PREFIX": "Prefixo CDN",
+ "Certificates_and_Keys": "Certificados e Chaves",
+ "Changing_email": "Alterando e-mail",
+ "channel": "canal",
+ "Channel": "Canal",
+ "Channel_already_exist": "O canal '#%s' já existe.",
+ "Channel_already_Unarchived": "Canal com o nome `#%s` já está não arquivado",
+ "Channel_Archived": "Canal com o nome `#%s` foi arquivado com sucesso",
+ "Channel_doesnt_exist": "O canal `#%s` não existe.",
+ "Channel_Unarchived": "Canal com o nome `#%s` foi desarquivado com sucesso",
+ "Channels": "Canais",
+ "Channels_list": "Lista de canais públicos",
+ "Chat_button": "Botão do chat",
+ "Chat_closed": "Chat encerrado",
+ "Chat_closed_successfully": "Chat encerrado com sucesso",
+ "Chat_window": "Janela de chat",
+ "Chatops_Enabled": "Ativar Chatops",
+ "Chatops_Title": "Painel Chatops",
+ "Chatops_Username": "Ops do chat",
+ "Choose_a_room": "Escolha uma sala",
+ "Choose_messages": "Escolha mensagens",
+ "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Escolha o alias que aparecerá antes do nome de usuário nas mensagens.",
+ "Choose_the_username_that_this_integration_will_post_as": "Escolha o nome do usuário que esta integração utilizará.",
+ "Clear_all_unreads_question": "Limpar todas não lidas?",
+ "Click_here": "Clique aqui",
+ "Client_ID": "ID do Cliente",
+ "Client_Secret": "Segredo do Cliente",
+ "Clients_will_refresh_in_a_few_seconds": "Os clientes irão atualizar em poucos segundos",
+ "close": "fechar",
+ "Close": "Fechar",
+ "Closed": "Fechado",
+ "Closed_by_visitor": "Encerrado pelo visitante",
+ "Closing_chat": "Encerrando chat",
+ "Collapse_Embedded_Media_By_Default": "Esconder mídia por padrão",
+ "Color": "Cor",
+ "Commands": "Comandos",
+ "Comment_to_leave_on_closing_session": "Comentário ao fechar sessão",
+ "Compact": "Compacto",
+ "Confirm_password": "Confirmar a senha",
+ "Conversation": "Conversa",
+ "Conversation_closed": "Chat encerrado: __comment__.",
+ "Convert_Ascii_Emojis": "Converter ASCII para Emoji",
+ "Copied": "Copiado",
+ "Copy": "Cópia",
+ "Copy_to_clipboard": "Copiar para área de transferência",
+ "COPY_TO_CLIPBOARD": "COPIAR PARA ÁREA DE TRANSFERÊNCIA",
+ "Count": "Total",
+ "Cozy": "Menor",
+ "Create": "Criar",
+ "Create_A_New_Channel": "Criar um novo canal",
+ "Create_new": "Criar um novo",
+ "Created_at": "Data criação",
+ "Created_at_s_by_s": "Criado em %s por %s ",
+ "Current_Chats": "Bate-papos atuais",
+ "Custom": "Personalizado",
+ "Custom_Emoji": "Emoji ",
+ "Custom_Emoji_Add": "Adicionar Novo Emoji",
+ "Custom_Emoji_Added_Successfully": "Emoji customizado adicionado com sucesso",
+ "Custom_Emoji_Delete_Warning": "Eliminar um emoji não pode ser desfeito.",
+ "Custom_Emoji_Error_Invalid_Emoji": "Emoji inválido",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "O emoji customizado ou um dos seus apelidos já está em uso.",
+ "Custom_Emoji_Has_Been_Deleted": "O emoji customizado foi ",
+ "Custom_Emoji_Info": "Informações do emoji customizado",
+ "Custom_Emoji_Updated_Successfully": "Emoji customizado atualizado com sucesso",
+ "Custom_Fields": "Campos Personalizados",
+ "Custom_oauth_helper": "Ao configurar o seu Provedor de OAuth, você terá que informar uma URL de retorno de chamada. Use %s .",
+ "Custom_oauth_unique_name": "Nome exclusivo para oauth customizado",
+ "Custom_Script_Logged_In": "Script Personalizado para usuários logados",
+ "Custom_Script_Logged_Out": "Script Personalizado para usuários não logados",
+ "Dashboard": "Dashboard",
+ "Date": "Data",
+ "Date_From": "De",
+ "Date_to": "até",
+ "days": "dias",
+ "DB_Migration": "Migração de banco de dados",
+ "DB_Migration_Date": "Data da migração do banco de dados",
+ "Deactivate": "Desativar",
+ "Decline": "Recusar",
+ "Default": "Padrão",
+ "Delete": "Deletar",
+ "Delete_message": "Apagar mensagem",
+ "Delete_my_account": "Excluir minha conta",
+ "Delete_Room_Warning": "A exclusão de uma sala irá apagar todas as mensagens postadas na sala. Isso não pode ser desfeito.",
+ "Delete_User_Warning": "Excluir um usuário irá apagar todas as mensagens desse usuário também. Isso não poderá ser desfeito.",
+ "Deleted": "Deletado!",
+ "Department": "Departamento",
+ "Department_removed": "Departamento removido",
+ "Departments": "Departamentos",
+ "Deployment_ID": "ID instalação",
+ "Description": "Descrição",
+ "Desktop": "Área de Trabalho",
+ "Desktop_Notification_Test": "Teste de Notificação de Desktop",
+ "Desktop_Notifications": "Notificações Desktop",
+ "Desktop_Notifications_Disabled": "Notificações Desktop estão Desativadas. Mude as preferências do seu navegador se quiser habilitar as notificações.",
+ "Desktop_Notifications_Duration": "Duração das notificações",
+ "Desktop_Notifications_Duration_Description": "Segundos para exibir notificação de desktop. Isso pode afetar Centro de Notificação do OS X. Insira 0 para usar as configurações padrão do navegador e não afetar Centro de Notificação do OS X.",
+ "Desktop_Notifications_Enabled": "Notificações Desktop estão Habilitadas",
+ "Direct_message_someone": "Enviar mensagem direta para alguém",
+ "Direct_Messages": "Mensagens Diretas",
+ "Display_offline_form": "Exibir formulário quando offline",
+ "Displays_action_text": "Exibe texto da ação",
+ "Do_you_want_to_change_to_s_question": "Você quer mudar para %s ?",
+ "Domain": "Domínio",
+ "Domains": "Domínios",
+ "Drop_to_upload_file": "Largue para enviar arquivos",
+ "Dry_run": "Simulação",
+ "Dry_run_description": "Enviará apenas um e-mail, para o mesmo endereço definido em 'De'. O e-mail deve pertencer a um usuário válido.",
+ "Duplicate_archived_channel_name": "Já existe um canal arquivado com o nome '%s'",
+ "Duplicate_archived_private_group_name": "Já existe um Grupo Privado, arquivado, com o nome '%s'",
+ "Duplicate_channel_name": "Um canal com o nome '%s' já existe",
+ "Duplicate_private_group_name": "Já existe um Grupo Privado com nome '%s'",
+ "Duration": "Duração",
+ "Edit": "Editar",
+ "Edit_Custom_Field": "Editar Campo Personalizado",
+ "Edit_Department": "Editar Departamento",
+ "Edit_Trigger": "Editar Gatilho",
+ "edited": "editado",
+ "Editing_room": "Edição de sala",
+ "Editing_user": "Edição de usuário",
+ "Email": "Email",
+ "Email_address_to_send_offline_messages": "Endereço de e-mail para enviar mensagens offline",
+ "Email_already_exists": "Email já cadastrado",
+ "Email_body": "Corpo do e-mail",
+ "Email_Change_Disabled": "O administrador do Rocket.Chat desativou a mudança de e-mail",
+ "Email_Footer_Description": "Você pode usar os seguintes espaços reservados: [Site_Name] e [Site_URL] para o nome do aplicativo e URL, respectivamente. ",
+ "Email_from": "De",
+ "Email_Header_Description": "Você pode usar os seguintes espaços reservados: [Site_Name] e [Site_URL] para o nome do aplicativo e URL, respectivamente. ",
+ "Email_Notification_Mode": "Notificações de E-mail Offline",
+ "Email_Notification_Mode_All": "Cada Menção / Mensagem Direta",
+ "Email_Notification_Mode_Disabled": "Desativado",
+ "Email_or_username": "Email ou nome de usuário",
+ "Email_subject": "Assunto",
+ "Email_verified": "Email verificado",
+ "Emoji": "Emoji",
+ "EmojiCustomFilesystem": "Sistema de arquivos do emoji customizado",
+ "Empty_title": "Título vazio",
+ "Enable": "Habilitar",
+ "Enable_Auto_Away": "Habilitar Auto Ausência",
+ "Enable_Desktop_Notifications": "Habilitar Notificações Desktop",
+ "Enabled": "Ativado",
+ "Encrypted_message": "Mensagem criptografada",
+ "End_OTR": "Finalizar OTR",
+ "Enter_a_regex": "Introduza um regex",
+ "Enter_a_room_name": "Digite um nome de sala",
+ "Enter_a_username": "Nome de usuário",
+ "Enter_name_here": "Insira o nome aqui",
+ "Enter_to": "Enter para",
+ "Error": "Erro",
+ "error-action-not-allowed": "__action__ não é permitido",
+ "error-application-not-found": "Aplicação não encontrada",
+ "error-archived-duplicate-name": "Já há um canal arquivado com o nome '__room_name__'",
+ "error-avatar-invalid-url": "URL inválida de avatar: __url__",
+ "error-avatar-url-handling": "Erro durante o manuseio configuração avatar a partir de uma URL (__url__) para __username__",
+ "error-cant-invite-for-direct-room": "Não é possível convidar usuários para salas diretas",
+ "error-could-not-change-email": "Não foi possível mudar e-mail",
+ "error-could-not-change-name": "Não foi possível mudar o nome",
+ "error-could-not-change-username": "Não foi possível alterar o nome de usuário",
+ "error-delete-protected-role": "Não é possível remover um papel protegido",
+ "error-department-not-found": "Departamento não encontrado",
+ "error-duplicate-channel-name": "Já existe um canal com nome '__channel_name__'",
+ "error-email-domain-blacklisted": "O domínio de e-mail está na lista negra",
+ "error-field-unavailable": "__field__ já está sendo usado :(",
+ "error-file-too-large": "Arquivo é muito grande",
+ "error-importer-not-defined": "O importador não foi definido corretamente; está faltando a classe Import.",
+ "error-input-is-not-a-valid-field": "__input__ não é válido um __field__",
+ "error-invalid-actionlink": "Link de ação inválido",
+ "error-invalid-arguments": "Argumentos inválidos",
+ "error-invalid-asset": "Arquivo Inválido",
+ "error-invalid-channel": "Canal inválido.",
+ "error-invalid-channel-start-with-chars": "Canal inválido. Comece com @ ou #",
+ "error-invalid-custom-field": "Campo personalizado inválido",
+ "error-invalid-custom-field-name": "Nome inválido para o campo personalizado. Use apenas letras, números, hífens e underscores.",
+ "error-invalid-description": "Descrição inválida",
+ "error-invalid-domain": "Domínio inválido",
+ "error-invalid-email": "__email__ não é um e-mail válido",
+ "error-invalid-email-address": "Endereço de e-mail inválido",
+ "error-invalid-file-height": "Altura de arquivo inválida",
+ "error-invalid-file-type": "Tipo de arquivo inválido",
+ "error-invalid-file-width": "Altura de arquivo inválida",
+ "error-invalid-from-address": "Você informou um e-mail DE inválido.",
+ "error-invalid-integration": "Integração inválida",
+ "error-invalid-message": "Mensagem inválida",
+ "error-invalid-method": "Método inválido",
+ "error-invalid-name": "Nome inválido",
+ "error-invalid-password": "Senha inválida",
+ "error-invalid-redirectUri": "redirectUri inválido",
+ "error-invalid-role": "Papel inválido",
+ "error-invalid-room": "Sala inválida",
+ "error-invalid-room-name": "__room_name__ não é um nome de sala válido, utilizar apenas letras, números, hífens e underscores",
+ "error-invalid-room-type": "__type__ não é um tipo de sala válido.",
+ "error-invalid-settings": "Configurações fornecidas inválidas",
+ "error-invalid-subscription": "Assinatura inválida",
+ "error-invalid-token": "Token inválido",
+ "error-invalid-triggerWords": "triggerWords inválidos",
+ "error-invalid-urls": "URLs inválidas",
+ "error-invalid-user": "Usuário inválido",
+ "error-invalid-username": "Nome de usuário Inválido",
+ "error-invalid-webhook-response": "O URL do webhook respondeu com um status diferente de 200",
+ "error-message-deleting-blocked": "Exclusão de mensagens está bloqueada",
+ "error-message-editing-blocked": "Edição de mensagens está bloqueada",
+ "error-message-size-exceeded": "O tamanho da mensagem excede Message_MaxAllowedSize",
+ "error-missing-unsubscribe-link": "Você deve fornecer o link para desinscrever-se: [unsubscribe].",
+ "error-no-tokens-for-this-user": "Não existem tokens para este usuário",
+ "error-not-allowed": "Não permitido",
+ "error-not-authorized": "Não autorizado",
+ "error-push-disabled": "Notificações push desativadas",
+ "error-remove-last-owner": "Este é o último proprietário. Por favor, defina um novo proprietário antes de remover este.",
+ "error-role-in-use": "Não é possível remover o papel pois ele está em uso",
+ "error-role-name-required": "Nome do papel é obrigatório",
+ "error-the-field-is-required": "O campo __field__ é obrigatório.",
+ "error-too-many-requests": "Erro, muitas solicitações. Por favor, diminua a velocidade. Você deve esperar __seconds__ segundos antes de tentar novamente.",
+ "error-user-is-not-activated": "O usuário não está ativo",
+ "error-user-has-no-roles": "O usuário não possui permissões",
+ "error-user-not-in-room": "O usuário não está nesta sala",
+ "error-user-registration-disabled": "O registro do usuário está desativado",
+ "error-user-registration-secret": "O registro de usuário é permitido somente via URL secreta",
+ "error-you-are-last-owner": "Você é o último proprietário da sala. Por favor defina um novo proprietário antes de sair.",
+ "Error_changing_password": "Erro ao alterar senha",
+ "Esc_to": "Esc para",
+ "Example_s": "Exemplo: %s",
+ "Exclude_Botnames": "Excluir bots",
+ "False": "Não",
+ "Favorite_Rooms": "Ativar salas favoritas",
+ "Favorites": "Favoritos",
+ "Features_Enabled": "Funcionalidades habilitadas",
+ "Field": "Campo",
+ "Field_removed": "Campo removido",
+ "File_exceeds_allowed_size_of_bytes": "O arquivo excede o tamanho permitido de __size__ bytes",
+ "FileUpload": "Upload de Arquivos",
+ "FileUpload_Enabled": "Habilitar upload de arquivos",
+ "FileUpload_File_Empty": "Arquivo vazio",
+ "FileUpload_FileSystemPath": "Caminho do Sistema",
+ "FileUpload_MaxFileSize": "Tamanho máximo dos arquivos (em bytes)",
+ "FileUpload_MediaType_NotAccepted": "Tipos de Arquivos Não Aceitos",
+ "FileUpload_MediaTypeWhiteList": "Lista de tipos de mídia",
+ "FileUpload_MediaTypeWhiteListDescription": "Tipos separados por vírgula. Deixe em branco para aceitar todos os tipos de arquivo.",
+ "FileUpload_ProtectFiles": "Proteger arquivos enviados",
+ "FileUpload_ProtectFilesDescription": "Somente usuários autenticados terão acesso",
+ "FileUpload_S3_Acl": "Amazon S3 ACL ",
+ "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
+ "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
+ "FileUpload_S3_Bucket": "Nome do bucket do Amazon S3",
+ "FileUpload_S3_BucketURL": "URL do Bucket",
+ "FileUpload_S3_CDN": "Domínio CDN para downloads",
+ "FileUpload_S3_Region": "Região",
+ "FileUpload_Storage_Type": "Tipo de Armazenamento",
+ "Flags": "Bandeiras",
+ "Follow_social_profiles": "Siga-nos nas redes sociais, faça fork no github e compartilhe suas ideias sobre o app rocket.chat em nosso trello.",
+ "Food_and_Drink": "Comida & Bebida",
+ "Footer": "Rodapé",
+ "For_your_security_you_must_enter_your_current_password_to_continue": "Para sua segurança, você deve digitar sua senha atual para continuar",
+ "Force_SSL": "Forçar SSL",
+ "Force_SSL_Description": "*Cuidado!* _Forçar SSL_ nunca deve ser usado com proxy reverso. Se você tem um proxy reverso, você deve fazer o redirecionamento LÁ. Esta opção existe para implantações como Heroku, que não permite a configuração de redirecionamento de proxy reverso.",
+ "Forgot_password": "Esqueceu sua senha",
+ "Forward": "Encaminhar",
+ "Forward_chat": "Encaminhar chat",
+ "Forward_to_department": "Encaminhar ao departamento",
+ "Forward_to_user": "Encaminhar ao usuário",
+ "Frequently_Used": "Usados frequentemente",
+ "From": "De",
+ "From_Email": "Email De",
+ "From_email_warning": "Aviso : O campo De está sujeito às configurações do seu servidor de emails.",
+ "General": "Geral",
+ "github_no_public_email": "Você não possui um e-mail público em sua conta do GitHub",
+ "Give_a_unique_name_for_the_custom_oauth": "Dê um nome exclusivo para o oauth customizado",
+ "Give_the_application_a_name_This_will_be_seen_by_your_users": "Dê um nome à aplicação. Isso será visto por seus usuários.",
+ "Global": "Global",
+ "GoogleTagManager_id": "Google Tag Manager Id",
+ "Hash": "Hash",
+ "Header": "Cabeçalho",
+ "Hidden": "Escondido",
+ "Hide_Avatars": "Esconder Avatares",
+ "Hide_flextab": "Esconder barra da direita com clique",
+ "Hide_Group_Warning": "Tem certeza de que deseja ocultar o grupo \"%s\"?",
+ "Hide_Private_Warning": "Tem certeza de que deseja ocultar a discussão com \"%s\"?",
+ "Hide_room": "Esconder sala",
+ "Hide_Room_Warning": "Tem certeza de que deseja ocultar a sala \"%s\"?",
+ "Hide_usernames": "Esconder nomes de usuário",
+ "Highlights": "Destaques",
+ "Highlights_How_To": "Para ser notificado quando alguém menciona uma palavra ou frase, adicione-as aqui. Você pode separar palavras ou frases com vírgulas. Não há diferenciação de maiúsculas e minúsculas ao destacar palavras.",
+ "Highlights_List": "Destacar palavras",
+ "History": "Histórico",
+ "Host": "Host",
+ "hours": "horas",
+ "How_friendly_was_the_chat_agent": "Quão amigável foi o agente de bate-papo?",
+ "How_knowledgeable_was_the_chat_agent": "O agente bate-papo possuía conhecimentos suficientes?",
+ "How_long_to_wait_after_agent_goes_offline": "Quanto tempo esperar após agente ficar offline",
+ "How_responsive_was_the_chat_agent": "Quão responsivo foi o agente de bate-papo?",
+ "How_satisfied_were_you_with_this_chat": "Ficou satisfeito com este bate-papo?",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "O que fazer com sessões abertas quando agente ficar offline",
+ "If_you_are_sure_type_in_your_password": "Se você tem certeza, digite sua senha:",
+ "If_you_are_sure_type_in_your_username": "Se você tem certeza, digite seu nome de usuário:",
+ "Importer_Archived": "Arquivado",
+ "Importer_done": "Importação concluída!",
+ "Importer_finishing": "Terminando a importação.",
+ "Importer_From_Description": "Importa dados de __from__ para o Rocket.Chat.",
+ "Importer_import_cancelled": "Importação cancelada.",
+ "Importer_import_failed": "Ocorreu um erro durante a execução da importação.",
+ "Importer_importing_channels": "Importando os canais.",
+ "Importer_importing_messages": "Importando as mensagens.",
+ "Importer_importing_started": "Iniciando a importação.",
+ "Importer_importing_users": "Importando os usuários.",
+ "Importer_not_in_progress": "O importador não está em execução.",
+ "Importer_Prepare_Restart_Import": "Reiniciar Importação",
+ "Importer_Prepare_Start_Import": "Começar a importar",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Desmarque Canais Arquivados",
+ "Importer_Prepare_Uncheck_Deleted_Users": "Desmarque Usuários Excluídos",
+ "Importer_progress_error": "Falha ao obter o progresso da importação.",
+ "Importer_setup_error": "Ocorreu um erro durante a configuração do importador.",
+ "inline_code": "código",
+ "Install_Extension": "Instalar Extensão",
+ "Install_FxOs": "Instale o Rocket.Chat em seu Firefox",
+ "Install_FxOs_done": "Ótimo! Agora você pode usar o Rocket.Chat através do ícone na sua tela inicial. Aproveite o Rocket.Chat!",
+ "Install_FxOs_error": "Desculpe, isso não funcionou conforme planejado! Ocorreu o seguinte erro:",
+ "Install_FxOs_follow_instructions": "Por favor confirme a instalação do app no seu dispositivo (pressione \"instalar\" quando solicitado).",
+ "Installation": "Instalação",
+ "Installed_at": "Instalado em",
+ "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instruções para o visitante preencher o formulário para enviar uma mensagem",
+ "Integration_added": "A integração foi adicionada",
+ "Integration_Incoming_WebHook": "Integração com WebHook de Entrada",
+ "Integration_New": "Nova Integração",
+ "Integration_Outgoing_WebHook": "Integração de WebHook de Saída",
+ "Integration_updated": "A integração foi atualizada",
+ "Integrations": "Integrações",
+ "InternalHubot": "Hubot interno",
+ "InternalHubot_PathToLoadCustomScripts": "Pasta para carregar os scripts",
+ "InternalHubot_ScriptsToLoad": "Scripts para carregar",
+ "InternalHubot_ScriptsToLoad_Description": "Por favor insira uma lista separada por vírgula de scripts para carregar a partir de https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_Username_Description": "Este deve ser um nome de usuário válido de um bot registrado em seu servidor.",
+ "Invalid_confirm_pass": "A confirmação de senha não é igual à senha",
+ "Invalid_email": "O e-mail informado é inválido",
+ "Invalid_Export_File": "O arquivo enviado não é um arquivo de exportação %s válido.",
+ "Invalid_Import_File_Type": "Tipo de Arquivo de Importação Inválido.",
+ "Invalid_name": "O nome não pode ser vazio",
+ "Invalid_notification_setting_s": "Configuração de notificação inválida: %s",
+ "Invalid_pass": "A senha não pode ser vazia",
+ "Invalid_room_name": "%s não é um nome válido, utilizar apenas letras, números e hífens",
+ "Invalid_secret_URL_message": "A URL fornecida é inválida.",
+ "invisible": "invisível",
+ "Invisible": "Invisível",
+ "Invitation_HTML": "HTML do Convite",
+ "Invitation_HTML_Default": " Você foi convidado para [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
",
+ "Invitation_HTML_Description": "Você pode usar os seguintes espaços reservados: [email] para o e-mail do destinatário. [Site_Name] e [Site_URL] para o nome do aplicativo e URL, respectivamente. ",
+ "Invitation_Subject": "Assunto do Convite",
+ "Invitation_Subject_Default": "Você foi convidado para [Site_Name]",
+ "Invite_user_to_join_channel": "Convidar um usuário para este canal",
+ "Invite_Users": "Convidar Usuários",
+ "IRC_Channel_Join": "Saída do comando JOIN.",
+ "IRC_Channel_Leave": "Saída do comando PART.",
+ "IRC_Channel_Users": "Saída do comando NAMES.",
+ "IRC_Channel_Users_End": "Fim da saída do comando NAMES.",
+ "IRC_Description": "Internet Relay Chat (IRC) é uma ferramenta de comunicação em grupo baseada em texto. Usuários entram em canais com nome único, ou salas, para discussões abertas. O IRC também suporta mensagens privadas e compartilhamento de arquivos. Esse pacote integra esses pacotes de funcionalidade com o Rocket.Chat.",
+ "IRC_Enabled": "Tenta integrar suport IRC. Alterar esse valor requer reiniciar o Rocket.Chat.",
+ "IRC_Hostname": "O servidor IRC para se conectar",
+ "IRC_Login_Fail": "Resposta a uma conexão com falha ao servidor IRC.",
+ "IRC_Login_Success": "Resposta a uma conexão bem sucedida ao servidor IRC.",
+ "IRC_Message_Cache_Size": "O limite cache para manipulação de mensagens de saída.",
+ "IRC_Port": "A porta para se conectar ao servidor IRC.",
+ "IRC_Private_Message": "Saída do comando PRIVMSG.",
+ "IRC_Quit": "Saída do encerramento de uma sessão IRC.",
+ "is_also_typing": "também está digitando",
+ "is_also_typing_female": "também está digitando",
+ "is_also_typing_male": "também está digitando",
+ "is_typing": "está digitando",
+ "is_typing_female": "está digitando",
+ "is_typing_male": "está digitando",
+ "It_works": "Funciona",
+ "italics": "itálico",
+ "Jitsi_Chrome_Extension": "Chrome Extension Id",
+ "Jitsi_Enable_Channels": "Habilitar em canais",
+ "join": "Entrar",
+ "Join_audio_call": "Entrar na chamada de áudio",
+ "Join_default_channels": "Entrar em canais predefinidos",
+ "Join_the_Community": "Junte-se à Comunidade",
+ "Join_the_given_channel": "Entrar no canal informado",
+ "Join_video_call": "Entrar na chamada de vídeo",
+ "Joined": "Entrou",
+ "Jump": "Saltar",
+ "Jump_to_first_unread": "Ir para primeira mensagem não lida",
+ "Jump_to_message": "Ir para mensagem",
+ "Jump_to_recent_messages": "Ir para mensagens recentes",
+ "Katex_Dollar_Syntax": "Permitir sintaxe dólar",
+ "Katex_Dollar_Syntax_Description": "Permitir o uso $$bloco Katex $$ e $Katex em linha$ sintaxes",
+ "Katex_Enabled": "Katex Ativado",
+ "Katex_Enabled_Description": "Permitir o uso de Katex para a composição tipográfica matemática em mensagens",
+ "Katex_Parenthesis_Syntax": "Permitir sintaxe com parênteses",
+ "Katex_Parenthesis_Syntax_Description": "Permitir o uso de sintaxes \\[bloco Katex\\] e \\(Katex em linha \\)",
+ "Knowledge_Base": "Base de conhecimento",
+ "Label": "Rótulo",
+ "Language": "Idioma",
+ "Language_Version": "Versão em Português",
+ "Last_login": "Último login",
+ "Last_Message_At": "Última mensagem em",
+ "Last_seen": "Visto por último",
+ "Layout": "Layout",
+ "Layout_Home_Body": "Corpo da Home",
+ "Layout_Home_Title": "Título da Home",
+ "Layout_Login_Terms": "Termos de Login",
+ "Layout_Privacy_Policy": "Política de Privacidade",
+ "Layout_Sidenav_Footer": "Rodapé da Navegação Lateral",
+ "Layout_Sidenav_Footer_description": "Tamanho do rodapé é 260x70",
+ "Layout_Terms_of_Service": "Termos de Serviço",
+ "LDAP": "LDAP",
+ "LDAP_CA_Cert": "Certificado CA",
+ "LDAP_Default_Domain": "Domínio Padrão",
+ "LDAP_Description": "LDAP é um banco de dados hierárquico que muitas empresas usam para fornecer single sign on - uma facilidade para compartilhar uma senha entre múltiplos sites e serviços. Para exemplos e informações de configurações avançadas, por favor consulte nosso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
+ "LDAP_BaseDN_Description": "O nome distinto (DN) de uma sub-árvore LDAP em que você deseja procurar por usuários e grupos. Você pode adicionar tantos quantos quiser; no entanto, cada grupo deve ser definido na mesma base de domínio que os usuários que pertencem a ele. Se você especificar grupos de usuários restritos, somente os usuários que pertencem a esses grupos estarão no escopo. Recomendamos que você especifique o nível mais alto de seu diretório LDAP como a sua base de domínio e use o filtro de pesquisa para controlar o acesso.",
+ "LDAP_User_Search_Field_Description": "O atributo LDAP que identifica o usuário LDAP que tenta autenticar. Este campo deve ser `sAMAccountName` para a maioria das instalações de Active Directory, mas pode ser` uid` para outras soluções LDAP, como o OpenLDAP. Você pode usar `mail` para identificar usuários por e-mail ou qualquer atributo que você desejar. Você pode usar vários valores separados por vírgula para permitir que os usuários façam login usando vários identificadores, como nome de usuário ou e-mail.",
+ "LDAP_User_Search_Filter_Description": "Se especificado, somente os usuários que correspondem a este filtro serão autorizados a entrar. Se nenhum filtro for especificado, todos os usuários dentro do âmbito da base de domínio especificado serão capazes de entrar. Por exemplo, para Active Directory `memberOf = cn = ROCKET_CHAT, ou = Geral Groups`. Por exemplo, para OpenLDAP (extensible match search) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "O usuário LDAP que realiza pesquisas de usuário para autenticar outros usuários quando eles entram. Isto é tipicamente uma conta de serviço criado especificamente para integrações de terceiros. Usar um nome qualificado, como `cn = administrador, cn = usuários, dc = exemplo, dc = com`.",
+ "LDAP_Enable": "Ativar",
+ "LDAP_Enable_Description": "Tente utilizar LDAP para autenticação",
+ "LDAP_Encryption": "Criptografia",
+ "LDAP_Encryption_Description": "O método de criptografia usado para proteger as comunicações com o servidor LDAP. Exemplos incluem `plain` (sem criptografia),` SSL / LDAPS` (criptografados desde o início), e `StartTLS` (upgrade para comunicação criptografada uma vez conectado).",
+ "LDAP_Host": "Host",
+ "LDAP_Host_Description": "O host LDAP, por exemplo, `ldap.example.com` ou `10.0.0.30`.",
+ "LDAP_Merge_Existing_Users": "Mesclar usuários existentes",
+ "LDAP_Port": "Porta",
+ "LDAP_Port_Description": "Porta para acessar o LDAP. Ex.: `389` ou `636` para LDAPS",
+ "LDAP_Reject_Unauthorized": "Rejeitar Não Autorizados",
+ "LDAP_Sync_User_Avatar": "Sincronizar Avatar dos Usuários",
+ "LDAP_Sync_User_Data": "Manter dados dos usuários sincronizados",
+ "LDAP_Sync_User_Data_Description": "Mantenha seus dados de usuário em sincronia logando no servidor (ex.: nome, email).",
+ "LDAP_Sync_User_Data_FieldMap": "Mapeamento de campos do usuário",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configure como os campos da conta de usuário (tipo email) serão populados no LDAP (quando encontrados). Por exemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` irá selecionar o nome do usuário do atributo cn, e o seu e-mail do atributo mail. Os campos disponíveis incluem `name`, `email` e `customFields`.",
+ "LDAP_Test_Connection": "Testar Conexão",
+ "LDAP_Unique_Identifier_Field": "Campo Identificador Único",
+ "LDAP_Unique_Identifier_Field_Description": "O campo que será usado para vincular o usuário LDAP ao usuário Rocket.Chat. Você pode informar vários valores separados por vírgula para tentar obter o valor do registro LDAP. O valor padrão é `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueid, uidNumber`",
+ "LDAP_Username_Field": "Campo do Nome de Usuário",
+ "LDAP_Username_Field_Description": "O campo que será usado como nome de usuário ( *username* ) para novos usuários. Deixe em branco para usar o nome de usuário informado na página de login. Você pode usar tags de template também, como `#{givenName}.#{sn}`. O valor padrão é `sAMAccountName`.",
+ "Leave_Group_Warning": "Tem certeza de que quer sair do grupo \"%s\"?",
+ "Leave_Private_Warning": "Tem certeza de que quer sair da discussão com \"%s\"?",
+ "Leave_room": "Sair da sala",
+ "Leave_Room_Warning": "Tem certeza de que deseja sair da sala \"%s\"?",
+ "Leave_the_current_channel": "Sai deste canal",
+ "line": "linha",
+ "List_of_Channels": "Lista de Canais",
+ "List_of_Direct_Messages": "Lista de Mensagens Diretas",
+ "Livechat_agents": "Agentes do Livechat",
+ "Livechat_Dashboard": "Painel Livechat",
+ "Livechat_enabled": "Livechat habilitado",
+ "Livechat_forward_open_chats": "Encaminhar chats abertos",
+ "Livechat_forward_open_chats_timeout": "Tempo de espera (em segundos) para encaminhas chats",
+ "Livechat_guest_count": "Contador de visitantes",
+ "Livechat_managers": "Gerentes do Livechat",
+ "Livechat_offline": "Livechat offline",
+ "Livechat_online": "Livechat on-line",
+ "Livechat_Queue": "Roleta Livechat",
+ "Livechat_room_count": "Contador de salas de livechat",
+ "Livechat_title": "Título Livechat",
+ "Livechat_title_color": "Cor de fundo do título do Livechat",
+ "Livechat_Users": "Usuários Livechat",
+ "Load_more": "Carregar mais",
+ "Loading...": "Carregando...",
+ "Loading_more_from_history": "Carregando mais a partir do histórico",
+ "Loading_suggestion": "Buscando sugestões...",
+ "Localization": "Localização",
+ "Log_Exceptions_to_Channel": "Log de Exceções no Canal",
+ "Log_Exceptions_to_Channel_Description": "Um canal que irá receber todas as exceções capturadas. Deixe em branco para ignorar exceções.",
+ "Log_File": "Mostrar Arquivo e Linha",
+ "Log_Level": "Nível de Log",
+ "Log_Package": "Mostrar Pacote",
+ "Log_View_Limit": "Limite de Visualização de Log",
+ "Logged_out_of_other_clients_successfully": "Desconectado de outros clientes com sucesso",
+ "Login": "Entrar",
+ "Login_with": "Login com %s",
+ "Logout": "Sair",
+ "Logout_Others": "Sair de outros locais logados",
+ "Mail_Message_Invalid_emails": "Você forneceu um ou mais e-mails inválidos: %s",
+ "Mail_Message_Missing_to": "Você deve selecionar um ou mais usuários ou fornecer um ou mais endereços de e-mail, separados por vírgulas.",
+ "Mail_Message_No_messages_selected_select_all": "Você não selecionou nenhuma mensagem. Gostaria de selecionar todas as mensagens visíveis?",
+ "Mail_Messages": "Mensagens de E-mail",
+ "Mail_Messages_Instructions": "Escolher as mensagens que deseja enviar via e-mail, clicando nas mensagens",
+ "Mail_Messages_Subject": "Aqui está uma parte selecionada de %s mensagens",
+ "Mailer": "Mailer",
+ "Mailer_body_tags": "Você deve usar [unsubscribe] como link para desinscrever-se. Você pode usar [name], [fname], [lname] para utilizar o nome completo, primeiro nome ou último nome, respectivamente. Você pode usar [email] para o email do usuário.",
+ "Mailing": "Mailing",
+ "Make_Admin": "Tornar Administrador",
+ "Manager_added": "Gerente adicionado",
+ "Manager_removed": "Gerente removido",
+ "Managing_assets": "Gerenciando assets",
+ "Managing_integrations": "Gerenciando integrações",
+ "Mark_as_read": "Marcar como lido",
+ "Markdown_Headers": "Cabeçalhos",
+ "Markdown_SupportSchemesForLink": "Protocolos Suportados para Markdown de Links",
+ "Markdown_SupportSchemesForLink_Description": "Lista de protocolos separados por vírgulas",
+ "Members_List": "Lista de Membros",
+ "Mentions": "Menções",
+ "Mentions_default": "Menções (padrão)",
+ "Message": "Mensagem",
+ "Message_AllowBadWordsFilter": "Permitir filtro de palavrões em mensagens",
+ "Message_AllowDeleting": "Permitir Exclusão de Mensagem",
+ "Message_AllowDeleting_BlockDeleteInMinutes": "Bloquear exclusão de mensagens após (n) minutos",
+ "Message_AllowDeleting_BlockDeleteInMinutes_Description": "Digite 0 para desativar o bloqueio.",
+ "Message_AllowDirectMessagesToYourself": "Permitir mensagens diretas do usuário para si mesmo",
+ "Message_AllowEditing": "Permitir Edição de Mensagem",
+ "Message_AllowEditing_BlockEditInMinutes": "Bloquear edição de mensagens após (em minutos - 0 para desabilitar)",
+ "Message_AllowEditing_BlockEditInMinutesDescription": "Insira 0 para desabilitar o bloqueio.",
+ "Message_AllowPinning": "Permitir Fixar Mensagem",
+ "Message_AllowPinning_Description": "Permitir que mensagens sejam fixadas em qualquer canal.",
+ "Message_AllowStarring": "Permitir Mensagens Favoritas",
+ "Message_AlwaysSearchRegExp": "Sempre pesquisar usando expressões regulares",
+ "Message_AlwaysSearchRegExp_Description": "Recomendamos definir `true` se o seu idioma não é suportado em pesquisa de texto MongoDB .",
+ "Message_AudioRecorderEnabled": "Gravação de Áudio Habilitada",
+ "Message_AudioRecorderEnabledDescription": "Requer que 'audio/wav' seja aceito nas configurações de 'Upload de Arquivos'",
+ "Message_BadWordsFilterList": "Adicione palavrões para a lista negra",
+ "Message_BadWordsFilterListDescription": "Adicione palavrões separados por vírgula para filtrar",
+ "Message_DateFormat": "Formato de Data",
+ "Message_DateFormat_Description": "Veja também: Moment.js ",
+ "Message_deleting_blocked": "Esta mensagem não pode ser mais apagada",
+ "Message_editing": "Edição de mensagem",
+ "Message_GroupingPeriod": "Período de Agrupamento (em segundos)",
+ "Message_GroupingPeriodDescription": "As mensagens serão agrupadas com as anteriores se pertencerem ao mesmo usuário e o tempo decorrido for menor do que o tempo em segundos informado.",
+ "Message_KeepHistory": "Manter Histórico de Mensagens",
+ "Message_MaxAll": "Tamanho máximo de canais para a mensagem ALL",
+ "Message_MaxAllowedSize": "Tamanho máximo de mensagem permitido ",
+ "Message_pinning": "Fixação de mensagem",
+ "Message_removed": "Mensagem removida",
+ "Message_ShowDeletedStatus": "Mostrar Status Excluído",
+ "Message_ShowEditedStatus": "Mostrar Status Editado",
+ "Message_ShowFormattingTips": "Exibir dicas de formatação",
+ "Message_starring": "Favoritando mensagem",
+ "Message_TimeFormat": "Formato de Hora",
+ "Message_TimeFormat_Description": "Veja também: Moment.js ",
+ "Message_too_long": "Mensagem muito longa",
+ "Message_VideoRecorderEnabled": "Gravação de vídeo habilitada",
+ "Messages": "Mensagens",
+ "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "As mensagens que são enviadas para o WebHook de Entrada serão publicadas aqui.",
+ "Meta": "Meta",
+ "Meta_custom": "Meta Tags Personalizadas",
+ "Meta_fb_app_id": "Facebook APP ID",
+ "Meta_google-site-verification": "Verificação de Site do Google",
+ "Meta_language": "Idioma",
+ "Meta_msvalidate01": "MSValidate.01",
+ "Meta_robots": "Robots",
+ "minutes": "minutos",
+ "Monitor_history_for_changes_on": "Monitorar mudanças de histórico para",
+ "More_channels": "Mais canais",
+ "More_direct_messages": "Mais mensagens diretas",
+ "More_groups": "Mais grupos privados",
+ "More_unreads": "Mais não lidos",
+ "Msgs": "Msgs",
+ "multi": "multi",
+ "Mute_someone_in_room": "Silenciar alguém na sala",
+ "Mute_user": "Silenciar usuário",
+ "Muted": "Silenciado",
+ "My_Account": "Minha Conta",
+ "n_messages": "%s mensagens",
+ "N_new_messages": "%s novas mensagens",
+ "Name": "Nome",
+ "Name_cant_be_empty": "Nome não pode ser vazio",
+ "Name_of_agent": "Nome do agente",
+ "Name_optional": "Nome (opcional)",
+ "Navigation_History": "Histórico de navegação",
+ "New_Application": "Nova aplicação",
+ "New_Custom_Field": "Novo Campo Personalizado",
+ "New_Department": "Novo Departamento",
+ "New_integration": "Nova integração",
+ "New_logs": "Novos logs",
+ "New_Message_Notification": "Notificação de nova mensagem",
+ "New_messages": "Novas mensagens",
+ "New_password": "Nova senha",
+ "New_role": "Novo papel",
+ "New_Room_Notification": "Notificação de nova sala",
+ "New_Trigger": "Novo Gatilho",
+ "New_videocall_request": "Nova requisição de chamada de vídeo",
+ "No_available_agents_to_transfer": "Nenhum agente disponível para transferir",
+ "No_channel_with_name_%s_was_found": "Nenhum canal com nome \"%s\" foi encontrado!",
+ "No_channels_yet": "Você não faz parte de nenhum canal ainda.",
+ "No_direct_messages_yet": "Você não iniciou nenhuma conversa ainda.",
+ "No_Encryption": "Sem Criptografia",
+ "No_group_with_name_%s_was_found": "Nenhum grupo privado com nome \"%s\" foi encontrado!",
+ "No_groups_yet": "Nenhum grupo privado ainda.",
+ "No_livechats": "Nenhum atendimento.",
+ "No_mentions_found": "Menções não encontradas",
+ "No_pinned_messages": "Não há mensagens fixadas",
+ "No_results_found": "Nenhum resultado encontrado",
+ "No_starred_messages": "Não há mensagens favoritas",
+ "No_user_with_username_%s_was_found": "Nenhum usuário com nome de usuário \"%s\" foi encontrado!",
+ "Nobody_available": "Ninguém disponível",
+ "Node_version": "Versão do Node",
+ "None": "Nada",
+ "Not_authorized": "Não autorizado",
+ "Not_Available": "Não Disponível",
+ "Not_found_or_not_allowed": "Não encontrado ou não permitido",
+ "Nothing": "Nada",
+ "Nothing_found": "Nada encontrado",
+ "Notifications": "Notificações",
+ "Notifications_Sound_Volume": "Volume do som de notificações",
+ "Notify_all_in_this_room": "Notificar todos nesta sala",
+ "Num_Agents": "# Agentes",
+ "Number_of_messages": "Número de mensagens",
+ "OAuth_Application": "Aplicação OAuth",
+ "OAuth_Applications": "Aplicações OAuth",
+ "Objects": "Objetos",
+ "Off_the_record_conversation": "Conversa Off-the-record",
+ "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Conversa Off-the-record não está disponível para o seu navegador ou dispositivo.",
+ "Offline": "Offline",
+ "Offline_DM_Email": "Você recebeu uma mensagem direta de __user__",
+ "Offline_form": "Formulário offline",
+ "Offline_form_unavailable_message": "Mensage quando formulário offline indisponível",
+ "Offline_Mention_Email": "Você foi mencionado por __user__ em #__room__",
+ "Offline_message": "Mensagem quando offline",
+ "Offline_success_message": "Mensagem de sucesso ao enviar formulário offline",
+ "Offline_unavailable": "Form offline indisponível",
+ "Online": "Online",
+ "Only_you_can_see_this_message": "Apenas você pode ver esta mensagem",
+ "Oops!": "Ops",
+ "Open": "Aberto",
+ "Opened": "Aberto",
+ "Opened_in_a_new_window": "Aberto em nova janela.",
+ "Opens_a_channel_group_or_direct_message": "Abre um canal, grupo ou mensagem direta",
+ "optional": "opcional",
+ "or": "ou",
+ "Order": "Ordem",
+ "OS_Arch": "Arquitetura",
+ "OS_Cpus": "Número de CPUs",
+ "OS_Freemem": "Memória Disponível",
+ "OS_Loadavg": "Carga Média",
+ "OS_Platform": "Plataforma",
+ "OS_Release": "Release",
+ "OS_Totalmem": "Memória Total",
+ "OS_Type": "Tipo de Sistema Operacional",
+ "OS_Uptime": "Tempo ligado",
+ "others": "outros",
+ "OTR": "OTR",
+ "OTR_is_only_available_when_both_users_are_online": "OTR só está disponível quando os usuários estão online",
+ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Substituir URL para a qual os arquivos são carregados. Esta url também será usada para downloads, a menos que um CDN seja fornecido",
+ "Page_title": "Título da página",
+ "Page_URL": "URL da página",
+ "Password": "Senha",
+ "Password_Change_Disabled": "O administrador do Rocket.Chat desativou a mudança de senhas",
+ "Password_changed_successfully": "Senha alterada com sucesso",
+ "Past_Chats": "Últimos chats",
+ "Payload": "Payload",
+ "People": "Pessoas",
+ "Permalink": "Link-permanente",
+ "Permissions": "Permissões",
+ "Pin_Message": "Fixar Mensagem",
+ "Pinned_a_message": "Fixou uma mensagem:",
+ "Pinned_Messages": "Mensagens Fixadas",
+ "PiwikAnalytics_siteId_Description": "A ID de site para usar para identificar este site. Exemplo: 17",
+ "PiwikAnalytics_url_Description": "O url onde o Piwik reside, não se esqueça de incluir a barra testando. Exemplo: //piwik.rocket.chat/",
+ "Placeholder_for_email_or_username_login_field": "Espaço reservado para campo de e-mail ou nome de usuário",
+ "Placeholder_for_password_login_field": "Espaço reservado para campo de senha",
+ "Please_add_a_comment": "Por favor, adicione um comentário",
+ "Please_add_a_comment_to_close_the_room": "Por favor, adicione um comentário para encerrar o chat",
+ "Please_answer_survey": "Por favor, dedique um momento para responder a uma pesquisa rápida sobre o bate-papo",
+ "Please_enter_value_for_url": "Por favor insira um valor para a URL do seu avatar.",
+ "Please_enter_your_new_password_below": "Por favor digite sua nova senha abaixo:",
+ "Please_enter_your_password": "Por favor, digite sua senha",
+ "Please_fill_a_label": "Por favor, preencha um rótulo",
+ "Please_fill_a_name": "Por favor, preencha um nome",
+ "Please_fill_a_username": "Por favor preencha um nome de usuário",
+ "Please_fill_name_and_email": "Por favor, preencha nome e e-mail",
+ "Please_select_an_user": "Por favor selecione um usuário",
+ "Please_select_enabled_yes_or_no": "Por favor, selecione uma opção para Ativado",
+ "Please_wait": "Aguarde",
+ "Please_wait_activation": "Por favor aguarde, isso pode levar algum tempo.",
+ "Please_wait_while_OTR_is_being_established": "Por favor aguarde enquanto a conversa OTR está sendo estabelecida",
+ "Please_wait_while_your_account_is_being_deleted": "Por favor aguarde enquanto a sua conta está sendo excluída...",
+ "Please_wait_while_your_profile_is_being_saved": "Aguarde enquanto o seu perfil está sendo salvo...",
+ "Port": "Porta",
+ "Post_as": "Postar como",
+ "Post_to_Channel": "Postar no Canal",
+ "Post_to_s_as_s": "Postar em %s como %s ",
+ "Preferences": "Preferências",
+ "Preferences_saved": "Preferências salvas",
+ "Privacy": "Privacidade",
+ "Private": "Privado",
+ "Private_Group": "Grupo Privado",
+ "Private_Groups": "Grupos Privados",
+ "Private_Groups_list": "Lista de Grupos Privados",
+ "Profile": "Perfil",
+ "Profile_saved_successfully": "Perfil salvo com sucesso",
+ "Public": "Público",
+ "Push": "Push",
+ "Push_apn_cert": "APN Cert",
+ "Push_apn_dev_cert": "APN Dev Cert",
+ "Push_apn_dev_key": "APN Dev Key",
+ "Push_apn_dev_passphrase": "APN Dev Passphrase",
+ "Push_apn_key": "APN Key",
+ "Push_apn_passphrase": "APN Passphrase",
+ "Push_debug": "Debug",
+ "Push_enable": "Habilitar",
+ "Push_enable_gateway": "Ativar Gateway",
+ "Push_gateway": "Gateway",
+ "Push_gcm_api_key": "Chave da API GCM",
+ "Push_gcm_project_number": "Número do Projeto GCM",
+ "Push_production": "Produção",
+ "Push_show_message": "Mostrar mensagem na notificação",
+ "Push_show_username_room": "Mostrar canal / grupo / nome de usuário na notificação",
+ "Push_test_push": "Teste",
+ "Query": "Query",
+ "Query_description": "Condições adicionais para determinar para quais usuários enviar e-mail. Usuários não inscritos são automaticamente removidos a partir da consulta. Deve ser um JSON válido. Exemplo: `{\"createdAt\": {\"$gt\": {\"$date\": \"2015-01-01T00: 00: 00.000Z\"}}}`",
+ "Queue": "Roleta",
+ "quote": "citação",
+ "Quote": "Citar",
+ "Random": "Aleatória",
+ "Reacted_with": "Reagiu com",
+ "Reactions": "Reações",
+ "Record": "Gravar",
+ "Redirect_URI": "URI de redirecionamento",
+ "Refresh_keys": "Atualizar chaves",
+ "Refresh_your_page_after_install_to_enable_screen_sharing": "Atualize sua página após a instalação para permitir o compartilhamento de tela",
+ "Register": "Registrar-se",
+ "Registration_Succeeded": "Registrado com Sucesso",
+ "Release": "Versão",
+ "Remove": "Remover",
+ "Remove_Admin": "Remover Administrador",
+ "Remove_as_moderator": "Remover como moderador",
+ "Remove_as_owner": "Remover de proprietário",
+ "Remove_custom_oauth": "Remover oauth customizado",
+ "Remove_from_room": "Retire da sala",
+ "Remove_someone_from_room": "Retirar alguém da sala",
+ "Removed": "Removido",
+ "Report_Abuse": "Denunciar abuso",
+ "Report_exclamation_mark": "Relatar!",
+ "Report_sent": "Relatório enviado",
+ "Report_this_message_question_mark": "Denunciar esta mensagem?",
+ "Require_password_change": "Exigir alteração de senha",
+ "Resend_verification_email": "Reenviar email de verificação",
+ "Reset": "Resetar",
+ "Reset_password": "Resetar senha",
+ "Reset_section_settings": "Redefinir configurações da seção",
+ "Restart": "Reiniciar",
+ "Restart_the_server": "Reiniciar o servidor",
+ "Role": "Papel",
+ "Role_Editing": "Edição de Papel",
+ "Role_removed": "Papel Removido",
+ "Room": "Sala",
+ "Room_archivation_state": "Estado",
+ "Room_archivation_state_false": "Ativo",
+ "Room_archivation_state_true": "Arquivado",
+ "Room_archived": "Sala arquivada",
+ "room_changed_privacy": "Tipo da sala mudou para: __room_type__ por __user_by__ ",
+ "room_changed_topic": "Tópico da sala mudou para: __room_topic__ por __user_by__ ",
+ "Room_has_been_deleted": "A sala foi excluída",
+ "Room_Info": "Informações da Sala",
+ "room_name": "nome da sala",
+ "Room_name_changed": "Nome da sala alterado para: __room_name__ por __user_by__ ",
+ "Room_name_changed_successfully": "Nome da sala alterado com sucesso",
+ "Room_not_found": "Sala não encontrada",
+ "Room_topic_changed_successfully": "Tópico da sala alterado com sucesso",
+ "Room_type_changed_successfully": "Tipo de sala alterado com sucesso",
+ "Room_unarchived": "Sala desarquivada",
+ "Room_uploaded_file_list": "Lista de arquivos",
+ "Room_uploaded_file_list_empty": "Nenhum arquivo disponível",
+ "Rooms": "Salas",
+ "Running_Instances": "Instâncias em execução",
+ "S_new_messages_since_s": "%s novas mensagens desde %s",
+ "SAML": "SAML",
+ "SAML_Custom_Cert": "Certificado personalizado",
+ "SAML_Custom_Entry_point": "Entry Point personalizado",
+ "SAML_Custom_Generate_Username": "Gerar nome de usuário",
+ "SAML_Custom_Issuer": "Emissor Personalizado",
+ "SAML_Custom_Provider": "Provedor Personalizado",
+ "Save": "Salvar",
+ "Save_changes": "Salvar alterações",
+ "Save_Mobile_Bandwidth": "Economizar Banda Móvel",
+ "Save_to_enable_this_action": "Salvar para habilitar esta ação",
+ "Saved": "Salvo",
+ "Saving": "Salvando",
+ "Scope": "Escopo",
+ "Screen_Share": "Compartilhamento de Tela",
+ "Script_Enabled": "Script Ativado",
+ "Search": "Pesquisar",
+ "Search_by_username": "Busca por nome de usuário",
+ "Search_Messages": "Pesquisar Mensagens",
+ "Search_Private_Groups": "Pesquisar Grupos Privados",
+ "seconds": "segundos",
+ "Secret_token": "Token secreto",
+ "Select_a_department": "Selecione um departamento",
+ "Select_a_user": "Selecione um usuário",
+ "Select_an_avatar": "Selecione um avatar",
+ "Select_file": "Selecione um arquivo",
+ "Select_service_to_login": "Selecione um serviço para iniciar sessão e carregar sua imagem ou faça upload de um arquivo de seu computador",
+ "Select_user": "Escolha um usuário",
+ "Select_users": "Selecione usuários",
+ "Selected_agents": "Agentes selecionados",
+ "Send": "Enviar",
+ "Send_a_message": "Envie uma mensagem",
+ "Send_a_test_mail_to_my_user": "Enviar um e-mail de teste para o meu usuário",
+ "Send_a_test_push_to_my_user": "Enviar um Push de teste para o meu usuário",
+ "Send_confirmation_email": "Enviar email de confirmação",
+ "Send_data_into_RocketChat_in_realtime": "Enviar dados para Rocket.Chat em tempo real.",
+ "Send_email": "Enviar e-mail",
+ "Send_invitation_email": "Enviar convite por e-mail",
+ "Send_invitation_email_error": "Você não forneceu um e-mail válido.",
+ "Send_invitation_email_info": "Você pode enviar vários convites por e-mail de uma vez.",
+ "Send_invitation_email_success": "Você enviou com sucesso um convite por e-mail para os seguintes endereços:",
+ "Send_request_on_chat_close": "Enviar requisição ao fechar conversa",
+ "Send_request_on_offline_messages": "Enviar requisição para mensagens off-line",
+ "Send_Test": "Enviar teste",
+ "Send_welcome_email": "Enviar e-mail de boas-vindas",
+ "Send_your_JSON_payloads_to_this_URL": "Envie seu payload JSON para esta URL.",
+ "Sending": "Enviando ...",
+ "Served_By": "Atendido Por",
+ "Service": "Serviço",
+ "Set_as_moderator": "Definir como moderador",
+ "Set_as_owner": "Definir como proprietário",
+ "Settings": "Configurações",
+ "Settings_updated": "Configurações atualizadas",
+ "Should_be_a_URL_of_an_image": "Deve ser uma URL de uma imagem.",
+ "Should_exists_a_user_with_this_username": "O usuário já deve existir.",
+ "Show_all": "Mostrar tudo",
+ "Show_more": "Mostrar mais",
+ "show_offline_users": "mostrar usuários offline",
+ "Show_only_online": "Mostrar apenas online",
+ "Show_preregistration_form": "Mostrar formulário de pré-registro",
+ "Show_queue_list_to_all_agents": "Mostrar link da roleta à todos agentes",
+ "Showing_archived_results": "Exibindo %s resultados arquivados
",
+ "Showing_online_users": "Mostrando __total_showing__ de __total__ usuários",
+ "Showing_results": "Exibindo %s resultados
",
+ "since_creation": "desde %s",
+ "Site_Name": "Nome do Site",
+ "Site_Url": "URL do Site",
+ "Site_Url_Description": "Exemplo: https://chat.dominio.com.br/",
+ "Skip": "Pular",
+ "Slash_Gimme_Description": "Mostra (つ ◕_◕) つ antes de sua mensagem",
+ "Slash_LennyFace_Description": "Mostra (͡ ° ͜ʖ ͡ °) após a sua mensagem",
+ "Slash_Shrug_Description": "Mostra ¯ \\ _ (ツ) _ / ¯ após a sua mensagem",
+ "Slash_Tableflip_Description": "Mostra (╯°□°)╯︵ ┻━┻",
+ "Slash_TableUnflip_Description": "Mostra ┬─┬ ノ (゜ - ゜ ノ)",
+ "Slash_Topic_Description": "Definir tópico",
+ "Slash_Topic_Params": "Mensagem do tópico",
+ "Smileys_and_People": "Smileys & Pessoas",
+ "SMS_Enabled": "SMS Ativado",
+ "SMTP": "SMTP",
+ "SMTP_Host": "Host SMTP",
+ "SMTP_Password": "Senha SMTP",
+ "SMTP_Port": "Porta SMTP",
+ "SMTP_Test_Button": "Testar Configurações SMTP",
+ "SMTP_Username": "Nome de usuário SMTP",
+ "Sound": "Som",
+ "SSL": "SSL",
+ "Star_Message": "Favoritar Message",
+ "Starred_Messages": "Mensagens Favoritas",
+ "Start_audio_call": "Iniciar chamada de áudio",
+ "Start_Chat": "Iniciar bate-papo",
+ "Start_of_conversation": "Início da conversa",
+ "Start_OTR": "Iniciar OTR",
+ "Start_video_call": "Iniciar chamada de vídeo",
+ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Comece com %s para o usuário ou %s para o canal. Por exemplo: %s ou %s",
+ "Started_At": "Iniciado em",
+ "Statistics": "Estatísticas",
+ "Statistics_reporting": "Enviar estatísticas para Rocket.Chat",
+ "Statistics_reporting_Description": "Ao enviar suas estatísticas, você vai nos ajudar a identificar quantas instâncias de Rocket.Chat são implantadas, bem como o quão bom o sistema está se comportando, para que possamos melhorar ainda mais isso. Não se preocupe, pois nenhuma informação de usuário é enviado e toda a informação que recebemos é mantida em sigilo.",
+ "Stats_Active_Users": "Usuários Ativos",
+ "Stats_Avg_Channel_Users": "Média de Usuários por Canal",
+ "Stats_Avg_Private_Group_Users": "Média de Usuários por Grupo Privado",
+ "Stats_Away_Users": "Usuários ausentes",
+ "Stats_Max_Room_Users": "Número Máximo de Usuários em um Sala",
+ "Stats_Non_Active_Users": "Usuários Inativos",
+ "Stats_Offline_Users": "Usuários Offline",
+ "Stats_Online_Users": "Usuários Online",
+ "Stats_Total_Channels": "Quantidade de Canais",
+ "Stats_Total_Direct_Messages": "Total de Salas de Mensagem Direta",
+ "Stats_Total_Messages": "Quantidade de Mensagens",
+ "Stats_Total_Private_Groups": "Quantidade de Grupos Privados",
+ "Stats_Total_Rooms": "Quantidade de Salas",
+ "Stats_Total_Users": "Quantidade de Usuários",
+ "Status": "Situação",
+ "Stop_Recording": "Parar Gravação",
+ "strike": "tachado",
+ "Subject": "Assunto",
+ "Submit": "Enviar",
+ "Success": "Sucesso",
+ "Success_message": "Mensagem de sucesso",
+ "Survey": "Pesquisa",
+ "Survey_instructions": "Classifique cada questão de acordo com a sua satisfação, 1 significa que você está completamente insatisfeito e 5 significa que você está completamente satisfeito.",
+ "Symbols": "Símbolos",
+ "Sync_success": "Sincronizado com sucesso",
+ "Sync_Users": "Sincronizar Usuários",
+ "Tag": "Tag",
+ "Test_Connection": "Testar Conexão",
+ "Test_Desktop_Notifications": "Testar Notificações de Desktop",
+ "Thank_you_exclamation_mark": "Obrigado!",
+ "Thank_you_for_your_feedback": "Obrigado pelo seu feedback",
+ "The_application_name_is_required": "O nome da aplicação é obrigatório",
+ "The_channel_name_is_required": "O nome do canal é obrigatório",
+ "The_emails_are_being_sent": "Os emails estão sendo enviados.",
+ "The_field_is_required": "O campo %s é obrigatório.",
+ "The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "O redimensionamento da imagem não vai funcionar porque não conseguimos detectar ImageMagick ou GraphicsMagick instalado no seu servidor.",
+ "The_redirectUri_is_required": "O redirectUri é necessário",
+ "The_server_will_restart_in_s_seconds": "O servidor será reiniciado em %s segundos",
+ "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "A configuração %s está definida como %s e você está acessando a partir de %s !",
+ "The_user_will_be_removed_from_s": "O usuário será removido de %s",
+ "The_user_wont_be_able_to_type_in_s": "O usuário não será capaz de escrever em %s",
+ "Theme": "Tema",
+ "theme-color-content-background-color": "Cor de fundo do conteúdo principal",
+ "theme-color-custom-scrollbar-color": "Cor da Barra de Rolagem Customizada",
+ "theme-color-info-font-color": "Cor da fonte de informação",
+ "theme-color-link-font-color": "Cor da fonte de link",
+ "theme-color-primary-background-color": "Cor de fundo primária",
+ "theme-color-primary-font-color": "Cor de fonte primária",
+ "theme-color-secondary-background-color": "Cor de fundo secundária",
+ "theme-color-secondary-font-color": "Cor de fonte secundária",
+ "theme-color-status-away": "Cor da situação ausente",
+ "theme-color-status-busy": "Cor da situação ocupado",
+ "theme-color-status-offline": "Cor da situação offline",
+ "theme-color-status-online": "Cor da situação online",
+ "theme-color-tertiary-background-color": "Cor de fundo terciária",
+ "theme-color-tertiary-font-color": "Cor de fonte terciária",
+ "theme-color-unread-notification-color": "Cor das Notificações Não Lidas",
+ "theme-custom-css": "CSS Customizado",
+ "There_are_no_agents_added_to_this_department_yet": "Não há agentes adicionados a este departamento ainda.",
+ "There_are_no_integrations": "Não há integrações",
+ "There_are_no_users_in_this_role": "Não há usuários neste papel.",
+ "This_conversation_is_already_closed": "Esta conversa já está fechada.",
+ "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Este e-mail já foi utilizado e não foi verificado. Por favor, altere sua senha.",
+ "This_is_a_desktop_notification": "Esta é uma notificação de desktop",
+ "This_is_a_push_test_messsage": "Este é uma mensagem de teste de push notification",
+ "This_room_has_been_archived_by__username_": "Esta sala foi arquivada por __username__",
+ "This_room_has_been_unarchived_by__username_": "Esta sala foi desarquivada por __username__",
+ "Time_in_seconds": "Tempo em segundos",
+ "Title": "Título",
+ "Title_bar_color": "Cor da barra de título",
+ "Title_bar_color_offline": "Cor da barra de título quando offline",
+ "Title_offline": "Título quando offline",
+ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar Rocket.Chat Livechat no seu website, copie e cole este código acima da última tag </ body> em seu site.",
+ "to_see_more_details_on_how_to_integrate": "para ver mais detalhes sobre como integrar.",
+ "To_users": "Para Usuários",
+ "Topic": "Tópico",
+ "Travel_and_Places": "Viagem & Locais",
+ "Trigger_removed": "Gatilho removido",
+ "Trigger_Words": "Palavras Gatilho",
+ "Triggers": "Gatilhos",
+ "True": "Sim",
+ "Type": "Tipo",
+ "Type_your_email": "Digite seu e-mail",
+ "Type_your_message": "Digite sua mensagem",
+ "Type_your_name": "Digite seu nome",
+ "Type_your_new_password": "Digite sua nova senha",
+ "UI_DisplayRoles": "Exibir papéis",
+ "UI_Merge_Channels_Groups": "Mesclar grupos privados com canais",
+ "Unarchive": "Desarquivar",
+ "Unmute_someone_in_room": "Permitir que alguém fale na sala",
+ "Unmute_user": "Permitir que o usuário fale",
+ "Unnamed": "Sem nome",
+ "Unpin_Message": "Desafixar Mensagem ",
+ "Unread_Rooms": "Não Lidas",
+ "Unread_Rooms_Mode": "Agrupar Salas Não Lidas",
+ "Unstar_Message": "Remover Favorito",
+ "Upload_file_question": "Enviar arquivo?",
+ "Uploading_file": "Subindo arquivo...",
+ "Uptime": "Tempo online",
+ "URL": "URL",
+ "URL_room_prefix": "Prefixo da URL da sala",
+ "Use_account_preference": "Use preferências da conta",
+ "Use_Emojis": "Usar Emojis",
+ "Use_initials_avatar": "Usar as iniciais do seu nome de usuário",
+ "Use_service_avatar": "Use o avatar de %s",
+ "Use_this_username": "Usar este nome de usuário",
+ "Use_uploaded_avatar": "Use o avatar de upload",
+ "Use_url_for_avatar": "Use url para o avatar",
+ "User__username__is_now_a_moderator_of__room_name_": "Usuário __username__ agora é um moderador de __room_name__",
+ "User__username__is_now_a_owner_of__room_name_": "Usuário __username__ agora é proprietário de __room_name__",
+ "User__username__removed_from__room_name__moderators": "Usuário __username__ removido dos moderadores de __room_name__",
+ "User__username__removed_from__room_name__owners": "Usuário __username__ removido dos proprietários de __room_name__",
+ "User_added": "Usuário adicionado",
+ "User_added_by": "Usuário __user_added__ adicionado à conversa por __user_by__ .",
+ "User_added_successfully": "Usuário adicionado com sucesso",
+ "User_doesnt_exist": "O usuário `@%s` não existe.",
+ "User_has_been_activated": "Usuário foi ativado",
+ "User_has_been_deactivated": "Usuário foi desativado",
+ "User_has_been_deleted": "O usuário foi excluído",
+ "User_has_been_muted_in_s": "Usuário foi silenciado em %s",
+ "User_has_been_removed_from_s": "Usuário foi removido de %s",
+ "User_Info": "Informações do usuário",
+ "User_is_no_longer_an_admin": "O usuário já não é um administrador",
+ "User_is_now_an_admin": "O usuário tornou-se um administrador",
+ "User_joined_channel": "Entrou no canal.",
+ "User_joined_channel_female": "Entrou no canal.",
+ "User_joined_channel_male": "Entrou no canal.",
+ "User_left": "Saiu da conversa.",
+ "User_left_female": "Saiu da conversa.",
+ "User_left_male": "Saiu da conversa.",
+ "User_logged_out": "Usuário não logado",
+ "User_management": "Gerenciamento de usuários",
+ "User_muted_by": "Usuário __user_muted__ silenciado por __user_by__ .",
+ "User_not_found": "Usuário não encontrado",
+ "User_not_found_or_incorrect_password": "Usuário não encontrado ou senha incorreta",
+ "User_or_channel_name": "Usuário ou nome de canal",
+ "User_removed": "Usuário removido",
+ "User_removed_by": "Usuário __user_removed__ removido da conversa por __user_by__ .",
+ "User_Settings": "Configurações do Usuário",
+ "User_Presence": "Presença do Usuário",
+ "User_unmuted_by": "__user_by__ permitiu que __user_unmuted__ fale na sala.",
+ "User_unmuted_in_room": "Usuário pode falar na sala",
+ "User_updated_successfully": "Usuário atualizado com sucesso",
+ "Username": "Nome de usuário",
+ "Username_and_message_must_not_be_empty": "Usuário e mensagem não devem estar vazios.",
+ "Username_cant_be_empty": "O nome de usuário não pode ser vazio",
+ "Username_Change_Disabled": "O administrador do Rocket.Chat desabilitou a mudança de nome de usuário",
+ "Username_denied_the_OTR_session": "__username__ negou a sessão OTR",
+ "Username_description": "O nome de usuário serve para que outras pessoas possam mencionar você em mensagens",
+ "Username_doesnt_exist": "O nome de usuário `%s` não existe.",
+ "Username_ended_the_OTR_session": "__username__ terminou a sessão OTR",
+ "Username_invalid": "%s não é um nome de usuário válido, usar somente letras, números, pontos, hífens e underscores",
+ "Username_is_already_in_here": "`@%s` já está aqui.",
+ "Username_is_not_in_this_room": "O usuário `%s` não está nesta sala.",
+ "Username_title": "Cadastre um nome de usuário",
+ "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ quer começar OTR. Você aceita?",
+ "Users": "Usuários",
+ "Users_in_role": "Usuários no papel",
+ "UTF8_Names_Slugify": "Slugify Nomes UTF8 ",
+ "UTF8_Names_Validation": "Validação de Nomes UTF8",
+ "UTF8_Names_Validation_Description": "Não permitir caracteres especiais e espaços. Você pode usar - _ e. mas não no final do nome",
+ "Validate_email_address": "Validar endereço de e-mail",
+ "Verification_email_sent": "E-mail de verificação enviado",
+ "Verified": "Verificado",
+ "Version": "Versão",
+ "Video_Chat_Window": "Vídeo Chat",
+ "Video_Conference": "Vídeo Conferência",
+ "Videocall_declined": "Chamada de vídeo negada.",
+ "Videocall_enabled": "Vídeoconferência habilitada",
+ "View_All": "Ver Todos",
+ "View_Logs": "Ver Logs",
+ "View_mode": "Modo de visualização",
+ "View_mode_info": "Isso muda o espaço que as mensagens ocupam na tela.",
+ "Viewing_room_administration": "Administração da sala",
+ "Visibility": "Visibilidade",
+ "Visible": "Visível",
+ "Visitor": "Visitante",
+ "Visitor_Info": "Informações do visitante",
+ "Visitor_Navigation": "Navegação do visitante",
+ "Visitor_page_URL": "URL da página de visitante",
+ "Visitor_time_on_site": "Tempo do visitante no site",
+ "Wait_activation_warning": "Antes que você possa fazer o login, sua conta deve ser manualmente ativada por um administrador.",
+ "We_are_offline_Sorry_for_the_inconvenience": "Estamos offline. Desculpe pela inconveniência.",
+ "We_have_sent_password_email": "Nós lhe enviamos um e-mail com instruções para redefinir sua senha. Se você não receber um e-mail em breve, por favor retorne e tente novamente.",
+ "We_have_sent_registration_email": "Nós lhe enviamos um e-mail para confirmar o seu registro. Se você não receber um e-mail em breve, por favor retorne e tente novamente.",
+ "Webhook_URL": "URL do webhook",
+ "Webhooks": "Webhooks",
+ "WebRTC_Enable_Channel": "Habilitar para canais públicos",
+ "WebRTC_Enable_Direct": "Ativar Mensagens Diretas",
+ "WebRTC_Enable_Private": "Habilitar para canais privados",
+ "WebRTC_Servers": "Servidores STUN/TURN",
+ "WebRTC_Servers_Description": "Uma lista de servidores STUN e TURN separados por vírgula. Nome de usuário, senha e porta são permitidos no formato `username:password @stun:host:port` ou `username:password@turn:host:port`.",
+ "Welcome": "Seja bem-vindo %s .",
+ "Welcome_to_the": "Bem-vindo ao",
+ "Why_do_you_want_to_report_question_mark": "Por que você quer denunciar?",
+ "will_be_able_to": "poderá",
+ "Yes": "Sim",
+ "Yes_clear_all": "Sim, limpar tudo!",
+ "Yes_delete_it": "Sim, exclua!",
+ "Yes_hide_it": "Sim, esconder!",
+ "Yes_leave_it": "Sim, sair!",
+ "Yes_mute_user": "Sim, silenciar o usuário!",
+ "Yes_remove_user": "Sim, remover usuário!",
+ "You": "Você",
+ "you_are_in_preview_mode_of": "Esta é uma prévia do canal #__room_name__ ",
+ "You_are_logged_in_as": "Vocês está logado como",
+ "You_are_not_authorized_to_view_this_page": "Você não possui permissão para visualizar esta página.",
+ "You_can_change_a_different_avatar_too": "Você pode substituir o avatar usado para enviar a partir desta integração.",
+ "You_can_search_using_RegExp_eg": "Você pode pesquisar usando expressões regulares, por exemplo:",
+ "You_can_use_an_emoji_as_avatar": "Você também pode usar um emoji como um avatar.",
+ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Você pode usar webhooks para integrar facilmente o livechat com seu CRM.",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Você não pode sair de uma sala de livechat. Por favor, use o botão de fechar sala.",
+ "You_have_been_muted": "Você foi silenciado e não pode falar nesta sala",
+ "You_have_not_verified_your_email": "Você ainda não verificou o seu e-mail.",
+ "You_have_successfully_unsubscribed": "A partir de agora você não está mais cadastrado em nossa lista de e-mails.",
+ "You_need_confirm_email": "Você precisa confirmar seu email para logar!",
+ "You_need_install_an_extension_to_allow_screen_sharing": "Você precisa instalar uma extensão para permitir o compartilhamento de tela",
+ "You_need_to_change_your_password": "Você precisa alterar sua senha",
+ "You_need_to_type_in_your_password_in_order_to_do_this": "Você precisa digitar sua senha, a fim de fazer isso!",
+ "You_need_to_type_in_your_username_in_order_to_do_this": "Você precisa digitar seu nome de usuário, a fim de fazer isso!",
+ "You_need_to_verifiy_your_email_address_to_get_notications": "Você precisa comprovar o seu endereço de e-mail para obter notificações",
+ "You_need_to_write_something": "Você precisa escrever alguma coisa!",
+ "You_should_inform_one_url_at_least": "Você deve definir pelo menos uma URL.",
+ "You_should_name_it_to_easily_manage_your_integrations": "Você deve nomeá-lo para gerenciar facilmente as suas integrações.",
+ "You_will_not_be_able_to_recover": "Você não será capaz de desfazer!",
+ "You_will_not_be_able_to_recover_file": "Não será possível recuperar esse arquivo!",
+ "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Você não receberá notificações de e-mail, porque você não confirmou seu e-mail.",
+ "Your_email_has_been_queued_for_sending": "Seu e-mail foi enfileirado para envio",
+ "Your_entry_has_been_deleted": "Sua mensagem foi excluída.",
+ "Your_file_has_been_deleted": "Seu arquivo foi apagado.",
+ "Your_mail_was_sent_to_s": "Seu e-mail foi enviado para %s",
+ "your_message": "sua mensagem",
+ "your_message_optional": "sua mensagem (opcional)",
+ "Your_password_is_wrong": "Sua senha está errada!",
+ "Your_push_was_sent_to_s_devices": "Sua natificação foi enviada para %s dispositivos"
+}
diff --git a/packages/rocketchat-i18n/i18n/pt.i18n.json b/packages/rocketchat-i18n/i18n/pt.i18n.json
index 18fd22cd7d24f..7e5d014c8bd1d 100644
--- a/packages/rocketchat-i18n/i18n/pt.i18n.json
+++ b/packages/rocketchat-i18n/i18n/pt.i18n.json
@@ -7,16 +7,18 @@
"500": "Erro Interno do Servidor",
"@username": "@username",
"@username_message": "@usuario ",
- "__username__is_no_longer__role__defined_by__user_by_": "__username__ não pertence mais à __role__, por __user_by__",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ já não pertence a __role__, por __user_by__",
"__username__was_set__role__by__user_by_": "__username__ foi definido como __role__ por __user_by__",
"Accept": "Aceitar",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Aceitar requisições de livechat mesmo se não houverem agentes online",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Aceitar pedidos de livechat mesmo se não houverem agentes online",
"Accept_with_no_online_agents": "Aceitar sem agentes online",
"Access_not_authorized": "Acesso não autorizado",
"Access_Token_URL": "URL do Token de Acesso",
"Accessing_permissions": "Acessando permissões",
"Account_SID": "Account SID",
"Accounts": "Contas",
+ "Accounts_AllowAnonymousRead": "Permitir leitura anónima",
+ "Accounts_AllowAnonymousWrite": "Permitir escrita anónima",
"Accounts_AllowDeleteOwnAccount": "Permitir que usuários apaguem a própria conta",
"Accounts_AllowedDomainsList": "Lista de domínios permitidos",
"Accounts_AllowedDomainsList_Description": "Lista de domínios permitidos, separados por vírgula",
@@ -27,20 +29,21 @@
"Accounts_AllowUserProfileChange": "Permitir que o usuário altere o perfil",
"Accounts_AvatarResize": "Redimensionar Avatares",
"Accounts_AvatarSize": "Tamanho do Avatar",
- "Accounts_AvatarStorePath": "Caminho para armazenar Avatares",
- "Accounts_AvatarStoreType": "Tipo de armazenamento de Avatares",
"Accounts_BlockedDomainsList": "Lista de Domínios Bloqueados",
"Accounts_BlockedDomainsList_Description": "Lista de domínios bloqueados, separados por vírgulas ",
"Accounts_BlockedUsernameList": "Lista de nomes de usuário bloqueados",
"Accounts_BlockedUsernameList_Description": "Lista de nomes de usuários bloqueados, separada por vírgulas (não diferencia maiúsculas)",
- "Accounts_CustomFields_Description": "Deve ser um JSON válido onde as chaves são os nomes de campos contendo um dicionário de configuração de campos. Exemplo:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"estudante\",\n \"options\": [\"professor\", \"estudante\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFields_Description": "Deve ser um JSON válido onde as chaves são os nomes de campos contendo um dicionário de configuração de campos. Exemplo:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"estudante\",\n \"options\": [\"professor\", \"estudante\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Campos personalizados a exibir",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Sugestão de prefixo de utilizador por defeito",
"Accounts_denyUnverifiedEmail": "Proibir e-mail não verificado",
"Accounts_EmailVerification": "Verificação de E-mail",
"Accounts_EmailVerification_Description": "Certifique-se de que as configurações de SMTP estão corretas para usar este recurso",
"Accounts_Enrollment_Email": "E-mail de inscrição",
- "Accounts_Enrollment_Email_Default": "Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
",
+ "Accounts_Enrollment_Email_Default": "Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
",
"Accounts_Enrollment_Email_Description": "Você pode usar [name], [fname], [lname] para o nome completo, primeiro nome ou último nome do usuário, respectivamente. Você pode usar [email] para o email do usuário.",
"Accounts_Enrollment_Email_Subject_Default": "Bem-vindo ao [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "Esquecer sessão de utilizador ao fechar a janela",
"Accounts_Iframe_api_method": "Método Api",
"Accounts_Iframe_api_url": "URL da API",
"Accounts_iframe_enabled": "Habilitado",
@@ -55,10 +58,12 @@
"Accounts_OAuth_Custom_id": "Id",
"Accounts_OAuth_Custom_Identity_Path": "Identity Path",
"Accounts_OAuth_Custom_Login_Style": "Estilo de Login",
+ "Accounts_OAuth_Custom_Merge_Users": "Migrar utilizadores",
"Accounts_OAuth_Custom_Scope": "Escopo",
"Accounts_OAuth_Custom_Secret": "Secret",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token Enviado Por",
+ "Accounts_OAuth_Custom_Username_Field": "Campo de Utilizador",
"Accounts_OAuth_Facebook": "Login do Facebook",
"Accounts_OAuth_Facebook_callback_url": "URL de Callback do Facebook",
"Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -87,6 +92,8 @@
"Accounts_OAuth_Meteor_callback_url": "URL de Callback do Meteor",
"Accounts_OAuth_Meteor_id": "Meteor Id",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_host": "Host de Proxy",
+ "Accounts_OAuth_Proxy_services": "Serviços de Proxy",
"Accounts_OAuth_Twitter": "Login do Twitter",
"Accounts_OAuth_Twitter_callback_url": "URL de Callback do Twitter",
"Accounts_OAuth_Twitter_id": "Twitter Id",
@@ -103,13 +110,14 @@
"Accounts_RegistrationForm_Public": "Público",
"Accounts_RegistrationForm_Secret_URL": "URL Secreta",
"Accounts_RegistrationForm_SecretURL": "URL Secreta para o Formulário de Registro",
- "Accounts_RegistrationForm_SecretURL_Description": "Você deve fornecer uma seqüência aleatória que será adicionada à sua URL de registro. Exemplo: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Você deve fornecer uma seqüência aleatória que será adicionada à sua URL de registro. Exemplo: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Nome é obrigatório para cadastro",
"Accounts_RequirePasswordConfirmation": "Requer Confirmação de Senha",
+ "Accounts_SearchFields": "Campos a considerar na busca",
"Accounts_ShowFormLogin": "Mostrar formulário de login",
"Accounts_UseDefaultBlockedDomainsList": "Use Lista Padrão de Domínios Bloqueados",
"Accounts_UseDNSDomainCheck": "Use verificação de Domínio DNS",
- "Accounts_UserAddedEmail_Default": " Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
Você pode fazer o login usando seu e-mail: [email] e password: [password]. Você pode ser obrigado a mudá-lo após o seu primeiro login.",
+ "Accounts_UserAddedEmail_Default": "
Bem-vindo ao [Site_Name] Vá para [Site_URL] e tente a melhor solução de bate-papo aberta fonte disponível hoje!
Você pode fazer o login usando seu e-mail: [email] e password: [password]. Você pode ser obrigado a mudá-lo após o seu primeiro login.",
"Accounts_UserAddedEmail_Description": "Você pode usar os seguintes espaços reservados:
[name], [fname], [lname] para o nome do usuário completo, primeiro nome ou sobrenome, respectivamente. [email] para e-mail do usuário. [Senha] para a senha do usuário. [Site_Name] e [Site_URL] para o nome do aplicativo e URL, respectivamente. ",
"Accounts_UserAddedEmailSubject_Default": "Você foi adicionado para [Site_Name]",
"Activate": "Ativar",
@@ -117,6 +125,7 @@
"Add": "Adicionar",
"Add_agent": "Adicionar agente",
"Add_custom_oauth": "Adicionar oauth customizado",
+ "Add_Domain": "Adicionar Domínio\n",
"Add_manager": "Adicionar gerente",
"Add_user": "Adicionar usuário",
"Add_User": "Adicionar Usuário",
@@ -141,15 +150,22 @@
"All_messages": "Todas as mensagens",
"Allow_Invalid_SelfSigned_Certs": "Permitir certificados inválidos e auto-assinados para validação de links e previews",
"Allow_Invalid_SelfSigned_Certs_Description": "Permitir certificado SSL inválidos e auto-assinados para validação de link e previews.",
+ "Allow_switching_departments": "Permitir visitante para mudar de departamentos",
+ "Always_open_in_new_window": "Abrir sempre em nova janela",
"Analytics_features_enabled": "Funcionalidades habilitadas",
"Analytics_features_messages_Description": "Rastreia eventos personalizados relacionados a ações que um usuário faz em mensagens.",
"Analytics_features_rooms_Description": "Rastreia eventos personalizados relacionados com ações em um canal ou grupo (criar, sair, apague).",
"Analytics_features_users_Description": "Rastreia eventos personalizados relacionados às ações relacionadas aos usuários (tempos de redefinição de senha, mudança imagem de perfil, etc).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "ID de Tracking",
"and": "e",
"And_more": "E mais __length__",
"Animals_and_Nature": "Animais e Natureza",
+ "Announcement": "Anúncios",
"API": "API",
"API_Analytics": "Analytics",
+ "API_Drupal_URL": "URL de Servidor Drupal",
+ "API_Drupal_URL_Description": "Exemplo: https://dominio.com (sem parêntesis)",
"API_Embed": "Embed",
"API_EmbedDisabledFor": "Desabilitar incorporação para usuários",
"API_EmbedDisabledFor_Description": "Lista de nomes de usuário separados por vírgula para desabilitar a pré-visualização de links embutidos",
@@ -177,13 +193,14 @@
"Are_you_sure_you_want_to_delete_your_account": "Tem certeza de que deseja excluir a sua conta?",
"Assign_admin": "Atribuindo administrador",
"at": "em",
- "AtlassianCrowd": "Multidão Atlassian",
+ "AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Arquivo Carregado",
"Auth_Token": "Auth Token",
"Author": "Autor",
"Authorization_URL": "URL de Autorização",
"Authorize": "Autorizar",
"Auto_Load_Images": "Auto Carregar Imagens",
+ "Auto_Translate": "Tradução-Automática",
"AutoLinker_Email": "Aplicar para Email",
"AutoLinker_Phone": "Aplicar para Telefone",
"AutoLinker_Phone_Description": "Links automáticos para para números de telefone. Por exemplo, `(123) 456-7890`",
@@ -193,6 +210,8 @@
"AutoLinker_Urls_TLD": "Auto-linkar URLs de TLD",
"AutoLinker_Urls_www": "Auto-linkar URLs com 'www'",
"AutoLinker_UrlsRegExp": "Expressão Regular para URL",
+ "AutoTranslate_Enabled": "Activar Tradução-Automática",
+ "AutoTranslate_GoogleAPIKey": "Google API Key",
"Available": "Disponível",
"Available_agents": "Agentes disponíveis",
"Avatar": "Avatar",
@@ -204,13 +223,14 @@
"away_female": "ausente",
"Away_female": "Ausente",
"away_male": "ausente",
- "Away_male": "ausente",
+ "Away_male": "Ausente",
"Back": "Voltar",
"Back_to_applications": "Voltar para aplicações",
"Back_to_integrations": "Voltar para integrações",
"Back_to_login": "Voltar para o login",
"Back_to_permissions": "Voltar para permissões",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Funcionalidade Beta! Depende que Vídeo Conferência esteja habilitado",
+ "Block_User": "Bloquear Utilizador",
"Body": "Corpo",
"bold": "negrito",
"bot_request": "Requisição de Bot",
@@ -223,6 +243,7 @@
"busy_male": "ocupado",
"Busy_male": "Ocupado",
"by": "por",
+ "cache_cleared": "Cache limpa",
"Cancel": "Cancelar",
"Cancel_message_input": "Cancelar",
"Cannot_invite_users_to_direct_rooms": "Não é possível convidar pessoas para salas diretas",
@@ -275,6 +296,7 @@
"Comment_to_leave_on_closing_session": "Comentário ao fechar sessão",
"Compact": "Compacto",
"Confirm_password": "Confirmar a senha",
+ "Content": "Conteúdo",
"Conversation": "Conversa",
"Conversation_closed": "Chat encerrado: __comment__.",
"Convert_Ascii_Emojis": "Converter ASCII para Emoji",
@@ -289,7 +311,9 @@
"Create_new": "Criar um novo",
"Created_at": "Data criação",
"Created_at_s_by_s": "Criado em %s por %s ",
+ "CRM_Integration": "Integração de CRM",
"Current_Chats": "Bate-papos atuais",
+ "Current_Status": "Estado Actual",
"Custom": "Personalizado",
"Custom_Emoji": "Emoji ",
"Custom_Emoji_Add": "Adicionar Novo Emoji",
@@ -305,6 +329,11 @@
"Custom_oauth_unique_name": "Nome exclusivo para oauth customizado",
"Custom_Script_Logged_In": "Script Personalizado para usuários logados",
"Custom_Script_Logged_Out": "Script Personalizado para usuários não logados",
+ "Custom_Scripts": "Scripts Customizados",
+ "Custom_Sound_Add": "Adicionar Som Customizado",
+ "Custom_Sound_Error_Invalid_Sound": "Som inválido",
+ "Custom_Sounds": "Sons Customizados",
+ "Custom_Translations": "Traduções Customizadas",
"Dashboard": "Dashboard",
"Date": "Data",
"Date_From": "De",
@@ -335,11 +364,16 @@
"Desktop_Notifications_Enabled": "Notificações Desktop estão Habilitadas",
"Direct_message_someone": "Enviar mensagem direta para alguém",
"Direct_Messages": "Mensagens Diretas",
+ "Disable_Notifications": "Desactivar Notificações",
+ "Disable_two-factor_authentication": "Desactivar autenticação de dois passos",
"Display_offline_form": "Exibir formulário quando offline",
"Displays_action_text": "Exibe texto da ação",
"Do_you_want_to_change_to_s_question": "Você quer mudar para %s ?",
"Domain": "Domínio",
+ "Domain_added": "Domínio Adicionado",
+ "Domain_removed": "Domínio Removido",
"Domains": "Domínios",
+ "Download_Snippet": "Download",
"Drop_to_upload_file": "Largue para enviar arquivos",
"Dry_run": "Simulação",
"Dry_run_description": "Enviará apenas um e-mail, para o mesmo endereço definido em 'De'. O e-mail deve pertencer a um usuário válido.",
@@ -351,6 +385,7 @@
"Edit": "Editar",
"Edit_Custom_Field": "Editar Campo Personalizado",
"Edit_Department": "Editar Departamento",
+ "Edit_previous_message": "`%s` - Editar mensagem anterior",
"Edit_Trigger": "Editar Gatilho",
"edited": "editado",
"Editing_room": "Edição de sala",
@@ -374,13 +409,17 @@
"Empty_title": "Título vazio",
"Enable": "Habilitar",
"Enable_Desktop_Notifications": "Habilitar Notificações Desktop",
+ "Enable_Svg_Favicon": "Activar favicon SVG",
+ "Enable_two-factor_authentication": "Activar autenticação de dois passos",
"Enabled": "Ativado",
"Encrypted_message": "Mensagem criptografada",
"End_OTR": "Finalizar OTR",
"Enter_a_regex": "Introduza um regex",
"Enter_a_room_name": "Digite um nome de sala",
"Enter_a_username": "Nome de usuário",
+ "Enter_authentication_code": "Introduzir código de autenticação",
"Enter_name_here": "Insira o nome aqui",
+ "Enter_Normal": "Modo normal (enviar com Enter)",
"Enter_to": "Enter para",
"Error": "Erro",
"error-action-not-allowed": "__action__ não é permitido",
@@ -524,6 +563,8 @@
"How_responsive_was_the_chat_agent": "Quão responsivo foi o agente de bate-papo?",
"How_satisfied_were_you_with_this_chat": "Ficou satisfeito com este bate-papo?",
"How_to_handle_open_sessions_when_agent_goes_offline": "O que fazer com sessões abertas quando agente ficar offline",
+ "Idle_Time_Limit": "Tempo limite de ausência",
+ "Enable_Auto_Away": "Habilitar auto ausência",
"If_you_are_sure_type_in_your_password": "Se você tem certeza, digite sua senha:",
"If_you_are_sure_type_in_your_username": "Se você tem certeza, digite seu nome de usuário:",
"Importer_Archived": "Arquivado",
@@ -624,24 +665,12 @@
"Layout_Terms_of_Service": "Termos de Serviço",
"LDAP": "LDAP",
"LDAP_CA_Cert": "Certificado CA",
- "LDAP_Custom_Domain_Search": "Pesquisa de Domínio Personalizado",
- "LDAP_Custom_Domain_Search_Description": "Um pedaço de JSON que governa informações de conexão e ligação e é da forma: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domínio Padrão",
"LDAP_Description": "LDAP é um banco de dados hierárquico que muitas empresas usam para fornecer single sign on - uma facilidade para compartilhar uma senha entre múltiplos sites e serviços. Para exemplos e informações de configurações avançadas, por favor consulte nosso wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "Base de Domínio",
- "LDAP_Domain_Base_Description": "O nome distinto (DN) de uma sub-árvore LDAP em que você deseja procurar por usuários e grupos. Você pode adicionar tantos quantos quiser; no entanto, cada grupo deve ser definido na mesma base de domínio que os usuários que pertencem a ele. Se você especificar grupos de usuários restritos, somente os usuários que pertencem a esses grupos estarão no escopo. Recomendamos que você especifique o nível mais alto de seu diretório LDAP como a sua base de domínio e use o filtro de pesquisa para controlar o acesso.",
- "LDAP_Domain_Search_Filter": "Filtro da Pesquisa de Domínio",
- "LDAP_Domain_Search_Filter_Description": "Se especificado, somente os usuários que correspondem a este filtro serão autorizados a entrar. Se nenhum filtro for especificado, todos os usuários dentro do âmbito da base de domínio especificado serão capazes de entrar. Por exemplo, para Active Directory `memberOf = cn = ROCKET_CHAT, ou = Geral Groups`. Por exemplo, para OpenLDAP (extensible match search) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Categoria de Objeto de Pesquisa de Domínio",
- "LDAP_Domain_Search_Object_Category_Description": "O *objectCategory* que identifica seus usuários. Deixe em branco para *OpenLDAP*. Por exemplo, `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Classe de Objeto de Pesquisa de Domínio",
- "LDAP_Domain_Search_Object_Class_Description": "O *objectclass* que identifica seus usuários. Por exemplo, `organizationalPerson`, `user`, `inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Senha da Pesquisa de Domínio",
- "LDAP_Domain_Search_Password_Description": "A senha para o usuário de pesquisa de domínio.",
- "LDAP_Domain_Search_User": "Usuário da Pesquisa de Domínio",
- "LDAP_Domain_Search_User_Description": "O usuário LDAP que realiza pesquisas de usuário para autenticar outros usuários quando eles entram. Isto é tipicamente uma conta de serviço criado especificamente para integrações de terceiros. Usar um nome qualificado, como `cn = administrador, cn = usuários, dc = exemplo, dc = com`.",
- "LDAP_Domain_Search_User_ID": "ID de Usuário de Pesquisa de Domínio",
- "LDAP_Domain_Search_User_ID_Description": "O atributo LDAP que identifica o usuário LDAP que tenta autenticar. Este campo deve ser `sAMAccountName` para a maioria das instalações de Active Directory, mas pode ser` uid` para outras soluções LDAP, como o OpenLDAP. Você pode usar `mail` para identificar usuários por e-mail ou qualquer atributo que você desejar. Você pode usar vários valores separados por vírgula para permitir que os usuários façam login usando vários identificadores, como nome de usuário ou e-mail.",
+ "LDAP_BaseDN_Description": "O nome distinto (DN) de uma sub-árvore LDAP em que você deseja procurar por usuários e grupos. Você pode adicionar tantos quantos quiser; no entanto, cada grupo deve ser definido na mesma base de domínio que os usuários que pertencem a ele. Se você especificar grupos de usuários restritos, somente os usuários que pertencem a esses grupos estarão no escopo. Recomendamos que você especifique o nível mais alto de seu diretório LDAP como a sua base de domínio e use o filtro de pesquisa para controlar o acesso.",
+ "LDAP_User_Search_Field_Description": "O atributo LDAP que identifica o usuário LDAP que tenta autenticar. Este campo deve ser `sAMAccountName` para a maioria das instalações de Active Directory, mas pode ser` uid` para outras soluções LDAP, como o OpenLDAP. Você pode usar `mail` para identificar usuários por e-mail ou qualquer atributo que você desejar. Você pode usar vários valores separados por vírgula para permitir que os usuários façam login usando vários identificadores, como nome de usuário ou e-mail.",
+ "LDAP_User_Search_Filter_Description": "Se especificado, somente os usuários que correspondem a este filtro serão autorizados a entrar. Se nenhum filtro for especificado, todos os usuários dentro do âmbito da base de domínio especificado serão capazes de entrar. Por exemplo, para Active Directory `memberOf = cn = ROCKET_CHAT, ou = Geral Groups`. Por exemplo, para OpenLDAP (extensible match search) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "O usuário LDAP que realiza pesquisas de usuário para autenticar outros usuários quando eles entram. Isto é tipicamente uma conta de serviço criado especificamente para integrações de terceiros. Usar um nome qualificado, como `cn = administrador, cn = usuários, dc = exemplo, dc = com`.",
"LDAP_Enable": "Ativar",
"LDAP_Enable_Description": "Tente utilizar LDAP para autenticação",
"LDAP_Encryption": "Criptografia",
@@ -656,13 +685,10 @@
"LDAP_Sync_User_Data": "Manter dados dos usuários sincronizados",
"LDAP_Sync_User_Data_Description": "Mantenha seus dados de usuário em sincronia logando no servidor (ex.: nome, email).",
"LDAP_Sync_User_Data_FieldMap": "Mapeamento de campos do usuário",
- "LDAP_Sync_User_Data_FieldMap_Description": "Configure como os campos da conta de usuário (tipo email) serão populados no LDAP (quando encontrados). Por exemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` irá selecionar o nome do usuário do atributo cn, e o seu e-mail do atributo mail. Os campos disponíveis incluem `name` e `email`.",
- "LDAP_Sync_Users": "Sincronizar Usuários",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Configure como os campos da conta de usuário (tipo email) serão populados no LDAP (quando encontrados). Por exemplo, `{\"cn\":\"name\", \"mail\":\"email\"}` irá selecionar o nome do usuário do atributo cn, e o seu e-mail do atributo mail. Os campos disponíveis incluem `name`, `email` e `customFields`.",
"LDAP_Test_Connection": "Testar Conexão",
"LDAP_Unique_Identifier_Field": "Campo Identificador Único",
"LDAP_Unique_Identifier_Field_Description": "O campo que será usado para vincular o usuário LDAP ao usuário Rocket.Chat. Você pode informar vários valores separados por vírgula para tentar obter o valor do registro LDAP. O valor padrão é `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueid, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Use Pesquisa de Domínio Personalizado",
- "LDAP_Use_Custom_Domain_Search_Description": "Escreva seu próprio filtro para procurar usuários no servidor LDAP.",
"LDAP_Username_Field": "Campo do Nome de Usuário",
"LDAP_Username_Field_Description": "O campo que será usado como nome de usuário ( *username* ) para novos usuários. Deixe em branco para usar o nome de usuário informado na página de login. Você pode usar tags de template também, como `#{givenName}.#{sn}`. O valor padrão é `sAMAccountName`.",
"Leave_Group_Warning": "Tem certeza de que quer sair do grupo \"%s\"?",
@@ -727,6 +753,7 @@
"Message_AllowDeleting": "Permitir Exclusão de Mensagem",
"Message_AllowDeleting_BlockDeleteInMinutes": "Bloquear exclusão de mensagens após (n) minutos",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Digite 0 para desativar o bloqueio.",
+ "Message_AllowDirectMessagesToYourself": "Permitir mensagens diretas do usuário para si mesmo",
"Message_AllowEditing": "Permitir Edição de Mensagem",
"Message_AllowEditing_BlockEditInMinutes": "Bloquear edição de mensagens após (em minutos - 0 para desabilitar)",
"Message_AllowEditing_BlockEditInMinutesDescription": "Insira 0 para desabilitar o bloqueio.",
@@ -772,6 +799,8 @@
"More_direct_messages": "Mais mensagens diretas",
"More_groups": "Mais grupos privados",
"More_unreads": "Mais não lidos",
+ "Move_beginning_message": "`%s` - Ir para o início da mensagem",
+ "Move_end_message": "`%s` - Ir para o fim da mensagem",
"Msgs": "Msgs",
"multi": "multi",
"Mute_someone_in_room": "Silenciar alguém na sala",
@@ -789,14 +818,15 @@
"New_Custom_Field": "Novo Campo Personalizado",
"New_Department": "Novo Departamento",
"New_integration": "Nova integração",
+ "New_line_message_compose_input": "`%s` - Adicionar nova linha a mensagem",
"New_logs": "Novos logs",
"New_Message_Notification": "Notificação de nova mensagem",
"New_messages": "Novas mensagens",
"New_password": "Nova senha",
"New_role": "Novo papel",
"New_Room_Notification": "Notificação de nova sala",
- "New_videocall_request": "Nova requisição de chamada de vídeo",
"New_Trigger": "Novo Gatilho",
+ "New_videocall_request": "Nova requisição de chamada de vídeo",
"No_available_agents_to_transfer": "Nenhum agente disponível para transferir",
"No_channel_with_name_%s_was_found": "Nenhum canal com nome \"%s\" foi encontrado!",
"No_channels_yet": "Você não faz parte de nenhum canal ainda.",
@@ -839,6 +869,7 @@
"Only_you_can_see_this_message": "Apenas você pode ver esta mensagem",
"Oops!": "Ops",
"Open": "Aberto",
+ "Open_channel_user_search": "`%s` - Abrir Canal / Busca de Usuário",
"Opened": "Aberto",
"Opened_in_a_new_window": "Aberto em nova janela.",
"Opens_a_channel_group_or_direct_message": "Abre um canal, grupo ou mensagem direta",
@@ -1040,6 +1071,7 @@
"Show_only_online": "Mostrar apenas online",
"Show_preregistration_form": "Mostrar formulário de pré-registro",
"Show_queue_list_to_all_agents": "Mostrar link da roleta à todos agentes",
+ "Show_the_keyboard_shortcut_list": "Exibe a lisgta de atalhos do teclado",
"Showing_archived_results": "Exibindo %s resultados arquivados
",
"Showing_online_users": "Mostrando __total_showing__ de __total__ usuários",
"Showing_results": "Exibindo %s resultados
",
@@ -1120,19 +1152,19 @@
"The_user_wont_be_able_to_type_in_s": "O usuário não será capaz de escrever em %s",
"Theme": "Tema",
"theme-color-content-background-color": "Cor de fundo do conteúdo principal",
+ "theme-color-custom-scrollbar-color": "Cor da Barra de Rolagem Customizada",
+ "theme-color-info-font-color": "Cor da fonte de informação",
+ "theme-color-link-font-color": "Cor da fonte de link",
"theme-color-primary-background-color": "Cor de fundo primária",
"theme-color-primary-font-color": "Cor de fonte primária",
"theme-color-secondary-background-color": "Cor de fundo secundária",
"theme-color-secondary-font-color": "Cor de fonte secundária",
- "theme-color-tertiary-background-color": "Cor de fundo terciária",
- "theme-color-tertiary-font-color": "Cor de fonte terciária",
- "theme-color-link-font-color": "Cor da fonte de link",
- "theme-color-info-font-color": "Cor da fonte de informação",
- "theme-color-custom-scrollbar-color": "Cor da Barra de Rolagem Customizada",
"theme-color-status-away": "Cor da situação ausente",
"theme-color-status-busy": "Cor da situação ocupado",
"theme-color-status-offline": "Cor da situação offline",
"theme-color-status-online": "Cor da situação online",
+ "theme-color-tertiary-background-color": "Cor de fundo terciária",
+ "theme-color-tertiary-font-color": "Cor de fonte terciária",
"theme-color-unread-notification-color": "Cor das Notificações Não Lidas",
"theme-custom-css": "CSS Customizado",
"There_are_no_agents_added_to_this_department_yet": "Não há agentes adicionados a este departamento ainda.",
@@ -1185,6 +1217,7 @@
"Use_this_username": "Usar este nome de usuário",
"Use_uploaded_avatar": "Use o avatar de upload",
"Use_url_for_avatar": "Use url para o avatar",
+ "User_Presence": "Presença do Utilizador",
"User__username__is_now_a_moderator_of__room_name_": "Usuário __username__ agora é um moderador de __room_name__",
"User__username__is_now_a_owner_of__room_name_": "Usuário __username__ agora é proprietário de __room_name__",
"User__username__removed_from__room_name__moderators": "Usuário __username__ removido dos moderadores de __room_name__",
@@ -1216,6 +1249,10 @@
"User_removed": "Usuário removido",
"User_removed_by": "Usuário __user_removed__ removido da conversa por __user_by__ .",
"User_Settings": "Configurações do Usuário",
+ "User_sent_a_message_on_channel": "__username__ enviou uma mensagem em __channel__ :",
+ "User_uploaded_a_file_on_channel": "__username__ enviou um arquivo em __channel__ :",
+ "User_sent_a_message_to_you": "__username__ enviou uma mensagem para você:",
+ "User_uploaded_a_file_to_you": "__username__ enviou um arquivo para você:",
"User_unmuted_by": "__user_by__ permitiu que __user_unmuted__ fale na sala.",
"User_unmuted_in_room": "Usuário pode falar na sala",
"User_updated_successfully": "Usuário atualizado com sucesso",
@@ -1311,4 +1348,4 @@
"your_message_optional": "sua mensagem (opcional)",
"Your_password_is_wrong": "Sua senha está errada!",
"Your_push_was_sent_to_s_devices": "Sua natificação foi enviada para %s dispositivos"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ro.i18n.json b/packages/rocketchat-i18n/i18n/ro.i18n.json
index 94f08574b0e6f..6ea3bb57a3d83 100644
--- a/packages/rocketchat-i18n/i18n/ro.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ro.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Permite schimbarea profilului utilzatorilor",
"Accounts_AvatarResize": "Redimensionarea Avatare",
"Accounts_AvatarSize": "Dimensiune Avatar",
- "Accounts_AvatarStorePath": "Calea de stocare Avatar",
- "Accounts_AvatarStoreType": "Tip stocare Avatar",
"Accounts_BlockedDomainsList": "Blocate List Domenii",
"Accounts_BlockedDomainsList_Description": "Lista de elemente separate prin virgulă de domenii blocate",
"Accounts_BlockedUsernameList": "Utilizator blocat Lista",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "Verificarea email-ului",
"Accounts_EmailVerification_Description": "Asigurați-vă că aveți setările SMT corecte pentru a utiliza această funcționalitate",
"Accounts_Enrollment_Email": "E-mail de înscriere ",
- "Accounts_Enrollment_Email_Default": " Bun venit la [Site_Name] Du-te la [Site_URL] și să încercați cea mai bună soluție de chat open source disponibile astăzi!
",
+ "Accounts_Enrollment_Email_Default": " Bun venit la [Site_Name] Du-te la [Site_URL] și să încercați cea mai bună soluție de chat open source disponibile astăzi!
",
"Accounts_Enrollment_Email_Description": "Puteți utiliza [name], [fname], [lname] pentru numele complet al utilizatorului, prenumele respectiv numele de familie. Puteți folosi [email] pentru e-mailul utilizatorului.",
"Accounts_Enrollment_Email_Subject_Default": "Bine ati venit la [Site_Name]",
"Accounts_Iframe_api_method": "Metodă API",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "Autentificare WordPress",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress URL de apelare inversă",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress URL de apelare inversă",
"Accounts_OAuth_Wordpress_id": " Id WordPress",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Resetează parola",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "Public",
"Accounts_RegistrationForm_Secret_URL": "URL secret",
"Accounts_RegistrationForm_SecretURL": "URL secret din formularul de înregistrare",
- "Accounts_RegistrationForm_SecretURL_Description": "Trebuie să furnizați un șir aleatoriu care va fi adăugat la URL-ul dvs. de înregistrare. Exemplu: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Trebuie să furnizați un șir aleatoriu care va fi adăugat la URL-ul dvs. de înregistrare. Exemplu: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Cere nume pentru înregistrare",
"Accounts_ShowFormLogin": "Arată formularul pentru autentificare",
"Accounts_UseDefaultBlockedDomainsList": "Implicit utilizare blocate Listă Domenii",
"Accounts_UseDNSDomainCheck": "DNS Verificați domeniu utilizați",
- "Accounts_UserAddedEmail_Default": " Bun venit la [Site_Name] Du-te la [Site_URL] și să încercați cea mai bună soluție de chat open source disponibile astăzi!
Te poți loga utilizând un e-mail: [email] și parola: [password]. Vi se poate cere să-l schimbe după prima conectare.",
+ "Accounts_UserAddedEmail_Default": "
Bun venit la [Site_Name] Du-te la [Site_URL] și să încercați cea mai bună soluție de chat open source disponibile astăzi!
Te poți loga utilizând un e-mail: [email] și parola: [password]. Vi se poate cere să-l schimbe după prima conectare.",
"Accounts_UserAddedEmail_Description": "Aveți dreptul să utilizați următoarele Placeholder:
[name], [fname], [lname] pentru numele utilizatorului completă, prenumele sau numele de familie, respectiv. [email] pentru e-mail a utilizatorului. [password] pentru parola utilizatorului. [Site_Name] și [Site_URL] pentru Nume aplicație și, respectiv, URL-ul. ",
"Accounts_UserAddedEmailSubject_Default": "Ați fost adăugat la [Site_Name]",
"Activate": "Activează",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Condții de utilizare",
"LDAP": "LDAP",
"LDAP_CA_Cert": "Certificat CA",
- "LDAP_Custom_Domain_Search": "Căutare în domeniu personalizat",
- "LDAP_Custom_Domain_Search_Description": "O bucată de JSON care guvernează leagă și conexiunea info și este de forma: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domeniu implicit",
"LDAP_Description": "LDAP este o bază de date ierarhică pe care multe companii o folosesc pentru a oferi osingură parolă pe mai multe site-uri și servicii. Pentru informații și exemple de configurare avansate, vă rugăm să consultați wiki nostru: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Baza domeniului",
- "LDAP_Domain_Base_Description": "Numele complet calificat distinctiv (DN) al unui subramificație LDAP pe care doriți să căutați utilizatori și grupuri. Puteți adăuga oricât de multe doriți; cu toate acestea, fiecare grup trebuie să fie definite în același domeniu de bază ca și utilizatorii care îi aparțin. Dacă precizați grupurile de utilizatori sunt restricționate, numai utilizatorii care fac parte din aceste grupuri vor fi în domeniul de aplicare. Vă recomandăm să specificați nivelul superior al arborelui dvs. de director LDAP ca baza domeniului dvs. și utilizați filtrul de căutare pentru a controla accesul.",
- "LDAP_Domain_Search_Filter": "Filtru Căutare Domeniu",
- "LDAP_Domain_Search_Filter_Description": "Dacă se specifică, numai utilizatorii care se potrivesc cu acest filtru va fi permis să te loghezi. Dacă nu este specificat nici un filtru, toți utilizatorii din domeniul de aplicare al bazei domeniului specificat va fi capabil să se conecteze. De exemplu, pentru Active Directory `memberOf = cn = ROCKET_CHAT, ou = generalul Groups`. De exemplu, pentru OpenLDAP (căutare meci extensibil) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domeniul Cautare Obiect Categorie",
- "LDAP_Domain_Search_Object_Category_Description": "* De * objectCategory care identifica utilizatorii. Lasă un gol pentru * OpenLDAP *. De exemplu, `person` etc.",
- "LDAP_Domain_Search_Object_Class": "Domeniul de clasă căutare Obiect",
- "LDAP_Domain_Search_Object_Class_Description": "* De * objectclass care identifica utilizatorii. De exemplu, `organizationalPerson`,` utilizator al, `inetOrgPerson` etc.",
- "LDAP_Domain_Search_Password": "Parolă căutare domeniu",
- "LDAP_Domain_Search_Password_Description": "Parola pentru utilizatorul căutării domeniu",
- "LDAP_Domain_Search_User": "Utilizator căutare domeniu",
- "LDAP_Domain_Search_User_Description": "Utilizatorul LDAP care efectuează căutări de utilizator pentru autentificarea altor utilizatori atunci când se conectează. Aceasta este de obicei un cont de serviciu special creat pentru integrările terțe părți. Utilizați un nume complet calificat, cum ar fi `cn = Administrator, cn = Users, dc = Exemplu, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domeniul de căutare ID utilizator",
- "LDAP_Domain_Search_User_ID_Description": "Acest atribut LDAP care identifică utilizatorul LDAP care încearcă autentificarea. Acest câmp ar trebui să fie `sAMAccountName` pentru instalații de cele mai multe Active Directory, dar poate fi` uid` pentru alte soluții LDAP, cum ar fi OpenLDAP. Aveți posibilitatea să utilizați `mail` pentru a identifica utilizatorii prin e-mail sau orice atribut pe care doriți. Puteți utiliza valori multiple, separate prin virgula pentru a permite utilizatorilor să te autentifici folosind mai mulți identificatori, cum ar fi numele de utilizator sau e-mail.",
+ "LDAP_BaseDN_Description": "Numele complet calificat distinctiv (DN) al unui subramificație LDAP pe care doriți să căutați utilizatori și grupuri. Puteți adăuga oricât de multe doriți; cu toate acestea, fiecare grup trebuie să fie definite în același domeniu de bază ca și utilizatorii care îi aparțin. Dacă precizați grupurile de utilizatori sunt restricționate, numai utilizatorii care fac parte din aceste grupuri vor fi în domeniul de aplicare. Vă recomandăm să specificați nivelul superior al arborelui dvs. de director LDAP ca baza domeniului dvs. și utilizați filtrul de căutare pentru a controla accesul.",
+ "LDAP_User_Search_Field_Description": "Acest atribut LDAP care identifică utilizatorul LDAP care încearcă autentificarea. Acest câmp ar trebui să fie `sAMAccountName` pentru instalații de cele mai multe Active Directory, dar poate fi` uid` pentru alte soluții LDAP, cum ar fi OpenLDAP. Aveți posibilitatea să utilizați `mail` pentru a identifica utilizatorii prin e-mail sau orice atribut pe care doriți. Puteți utiliza valori multiple, separate prin virgula pentru a permite utilizatorilor să te autentifici folosind mai mulți identificatori, cum ar fi numele de utilizator sau e-mail.",
+ "LDAP_User_Search_Filter_Description": "Dacă se specifică, numai utilizatorii care se potrivesc cu acest filtru va fi permis să te loghezi. Dacă nu este specificat nici un filtru, toți utilizatorii din domeniul de aplicare al bazei domeniului specificat va fi capabil să se conecteze. De exemplu, pentru Active Directory `memberOf = cn = ROCKET_CHAT, ou = generalul Groups`. De exemplu, pentru OpenLDAP (căutare meci extensibil) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Utilizatorul LDAP care efectuează căutări de utilizator pentru autentificarea altor utilizatori atunci când se conectează. Aceasta este de obicei un cont de serviciu special creat pentru integrările terțe părți. Utilizați un nume complet calificat, cum ar fi `cn = Administrator, cn = Users, dc = Exemplu, dc = com`.",
"LDAP_Enable": "Activați",
"LDAP_Enable_Description": "Încearcă să utilizezi LDAP pentru autentificare.",
"LDAP_Encryption": "Encriptare",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Păstrați datele utilizatorului în sincron cu serverul de autentificare (de exemplu: nume, e-mail).",
"LDAP_Sync_User_Data_FieldMap": "User Data Field Map",
"LDAP_Sync_User_Data_FieldMap_Description": "Configurați modul în care detalii ale contului de utilizator (cum ar fi e-mail-ul) sunt populate de o înregistrare LDAP (odată găsită). De exemplu, {\"cn\": \"Numele\", \"e-mail\": \"e-mail\"} va alege numele unei persoane ce poate fi citit de la atributul cn, și e-mail lor de atributul e-mail. Detaliile disponibile includ numele și e-mail.",
- "LDAP_Sync_Users": "Sincronizează utilizatori",
"LDAP_Test_Connection": "Test conexiune",
"LDAP_Unique_Identifier_Field": "Identificator unic câmp",
"LDAP_Unique_Identifier_Field_Description": "Care câmp va fi folosit pentru a lega utilizatorul LDAP și utilizatorul Rocket.Chat. Vă poate informa cu valori multiple, separate prin virgula pentru a încerca pentru a obține valoarea de înregistrare LDAP. Valoarea implicită este `objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Folosește Căutare Domeniu Specific",
- "LDAP_Use_Custom_Domain_Search_Description": "Scrie propriul filtru pentru utilizatorii caută în serverul LDAP.",
"LDAP_Username_Field": "Câmp utilizator",
"LDAP_Username_Field_Description": "Care câmp va fi folosit ca nume de utilizator * * pentru noii utilizatori. Lasă un gol pentru a utiliza numele de utilizator informat pe pagina de conectare. Aveți posibilitatea să utilizați etichete șablon prea, cum ar fi `#{givenName}.#{sn}`. Valoarea implicită este `sAMAccountName`.",
"Leave_Group_Warning": "Sunteți sigur că vreți să părăsiți grupul?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "Utilizatorul nu va putea să introducă text în %s",
"Theme": "Temă",
"theme-color-content-background-color": "Culoare de fundal conținut",
+ "theme-color-custom-scrollbar-color": "Culoare Scrollbar personalizat",
+ "theme-color-info-font-color": "Culoare text info",
+ "theme-color-link-font-color": "Culoare text link",
"theme-color-primary-background-color": "Culoare de fundal primară",
"theme-color-primary-font-color": "Culoare text primară",
"theme-color-secondary-background-color": "Culoare de fundal secundară",
"theme-color-secondary-font-color": "Culoare text secundară",
- "theme-color-tertiary-background-color": "Culoare de fundal terțiară",
- "theme-color-tertiary-font-color": "Culoare text terțiară",
- "theme-color-link-font-color": "Culoare text link",
- "theme-color-info-font-color": "Culoare text info",
- "theme-color-custom-scrollbar-color": "Culoare Scrollbar personalizat",
"theme-color-status-away": "Culoare status 'Away'",
"theme-color-status-busy": "Culoare status 'Ocupat'",
"theme-color-status-offline": "Culoare status 'Offline'",
"theme-color-status-online": "Culoare status 'Activ'",
+ "theme-color-tertiary-background-color": "Culoare de fundal terțiară",
+ "theme-color-tertiary-font-color": "Culoare text terțiară",
"theme-color-unread-notification-color": "Culoare notificări mesaje necitite",
"theme-custom-css": "CSS personalizat",
"There_are_no_agents_added_to_this_department_yet": "Încă există agenți adăugați la acest departament.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "E-mail-ul a fost trimis la %s",
"Your_password_is_wrong": "Parola dvs. este greșită!",
"Your_push_was_sent_to_s_devices": "Mesajul Push a fost trimis la %s dispozitive"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ru.i18n.json b/packages/rocketchat-i18n/i18n/ru.i18n.json
index d2bd983890313..4a2838d475119 100644
--- a/packages/rocketchat-i18n/i18n/ru.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ru.i18n.json
@@ -1,39 +1,54 @@
{
+ "#channel": "#канал",
"0_Errors_Only": "0 - Только ошибки",
"1_Errors_and_Information": "1 - Ошибки и информация",
"2_Erros_Information_and_Debug": "2 - Ошибки, информация и отладка",
- "403": "Запрещенно",
+ "403": "Запрещено",
"500": "Внутренняя ошибка сервера",
- "__username__is_no_longer__role__defined_by__user_by_": "__username__ больше не __role__, по решению __user_by__",
+ "@username": "@логин",
+ "@username_message": "@логин ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ больше не __role__ по решению __user_by__",
"__username__was_set__role__by__user_by_": "__username__ был установлен __role__ по решению __user_by__",
- "Access_not_authorized": "Доступ запрещён",
- "Access_Token_URL": "Маркер доступа URL-адреса",
+ "Accept": "Принять",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Принимать входящие запросы с livechat, даже если нет подключенных сотрудников",
+ "Accept_with_no_online_agents": "Принимать с неподключенными сотрудниками",
+ "access-mailer": "Доступ к странице мейлера",
+ "access-mailer_description": "Разрешить рассылку электронного сообщения всем пользователям",
+ "access-permissions": "Доступ к странице разрешений",
+ "access-permissions_description": "Изменяйте разрешения для разных ролей",
+ "Access_not_authorized": "Неавторизованный доступ",
+ "Access_Token_URL": "Токен доступа URL-адреса",
"Accessing_permissions": "Права доступа",
- "Account_SID": "Аккаунт SID",
- "Accounts": "Аккаунты",
- "Accounts_AllowDeleteOwnAccount": "Разрешить пользователям удалять собственный аккаунт",
+ "Account_SID": "SID учетной записи",
+ "Accounts": "Учётные записи",
+ "Accounts_AllowAnonymousRead": "Разрешить чтение анонимным пользователям",
+ "Accounts_AllowAnonymousWrite": "Разрешить писать анонимным пользователям",
+ "Accounts_AllowDeleteOwnAccount": "Разрешить пользователям удалять собственную учетную запись",
"Accounts_AllowedDomainsList": "Список разрешенных доменов",
- "Accounts_AllowedDomainsList_Description": "Разделенный запятыми список разрешенных доменов",
- "Accounts_AllowEmailChange": "Разрешить изменение email адреса",
+ "Accounts_AllowedDomainsList_Description": "Список разрешенных доменов, разделенный запятыми ",
+ "Accounts_AllowEmailChange": "Разрешить изменять адрес электронной почты",
"Accounts_AllowPasswordChange": "Разрешить смену пароля",
"Accounts_AllowUserAvatarChange": "Разрешить пользователю изменять аватар",
- "Accounts_AllowUsernameChange": "Разрешить изменять имя пользователя",
+ "Accounts_AllowUsernameChange": "Разрешить изменять логин",
"Accounts_AllowUserProfileChange": "Разрешить пользователю изменять настройки профиля",
"Accounts_AvatarResize": "Изменение размера аватара",
"Accounts_AvatarSize": "Размер аватара",
- "Accounts_AvatarStorePath": "Путь к аватарам",
- "Accounts_AvatarStoreType": "Тип хранилища аватаров",
"Accounts_BlockedDomainsList": "Список запрещённых доменов",
- "Accounts_BlockedDomainsList_Description": "Запрещённые домены через запятую",
- "Accounts_BlockedUsernameList": "Заблокированные Список Имя пользователя",
- "Accounts_BlockedUsernameList_Description": "Разделенных запятыми список заблокированных имен пользователей (без учета регистра)",
- "Accounts_denyUnverifiedEmail": "Запретить неподтверждённые email",
- "Accounts_EmailVerification": "Подтверждение email",
+ "Accounts_BlockedDomainsList_Description": "Список запрещённых доменов, разделенных запятой",
+ "Accounts_BlockedUsernameList": "Список заблокированных пользователей",
+ "Accounts_BlockedUsernameList_Description": "Список заблокированных имен пользователей (без учета регистра), разделенных запятой",
+ "Accounts_CustomFields_Description": "Ожидается валидный JSON-объект, в котором каждый ключ - это имя поля, а содержимое - словарь настроек поля. Пример:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n}\n",
+ "Accounts_CustomFieldsToShowInUserInfo": "Кастомные поля для отображения в информации пользователя",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Предлагаемая подсказка префикса логина",
+ "Accounts_Default_User_Preferences_desktopNotifications": "Стандартные оповещения на рабочем столе",
+ "Accounts_denyUnverifiedEmail": "Запретить неподтверждённые адреса электронной почты",
+ "Accounts_EmailVerification": "Подтверждение адреса электронной почты",
"Accounts_EmailVerification_Description": "Убедитесь, что у вас верные настройки SMTP для использования этой функции",
- "Accounts_Enrollment_Email": "Запись электронной почты",
- "Accounts_Enrollment_Email_Default": "Добро пожаловать в [Site_Name] Зайдите в [Site_URL] и попробуйте лучшее решение для чата с открытым исходным кодом на сегодняшний день!
",
- "Accounts_Enrollment_Email_Description": "Вы можете использовать следующие динамические значения:\n \n[name], [fname] и [lname] (полное имя, только имя, только фамилия). \n[email] - email пользователя \n[Site_Name] и [Site_URL] - название вашего Rocket.Chat и его адрес \n ",
+ "Accounts_Enrollment_Email": "Электронное сообщение при регистрации",
+ "Accounts_Enrollment_Email_Default": "Добро пожаловать на [Site_Name] Посетите [Site_URL] и попробуйте лучшее решение с открытым исходным кодом для общения на сегодняшний день!
",
+ "Accounts_Enrollment_Email_Description": "Вы можете использовать следующие подстановки: [name], [fname] и [lname] (полное имя пользователя, только имя, только фамилия). \n[email] - адрес электронной почты пользователя \n[Site_Name] и [Site_URL] - название вашего приложения и его URL \n ",
"Accounts_Enrollment_Email_Subject_Default": "Добро пожаловать на [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "Забыть сессию пользователя при закрытии окна",
"Accounts_Iframe_api_method": "Метод API",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "Включено",
@@ -46,130 +61,202 @@
"Accounts_OAuth_Custom_Button_Label_Text": "Текст кнопки",
"Accounts_OAuth_Custom_Enable": "Включить",
"Accounts_OAuth_Custom_id": "Идентификатор",
- "Accounts_OAuth_Custom_Identity_Path": "Единичный путь",
+ "Accounts_OAuth_Custom_Identity_Path": "Identity Path",
"Accounts_OAuth_Custom_Login_Style": "Вид логина",
+ "Accounts_OAuth_Custom_Merge_Users": "Объединить пользователей",
+ "Accounts_OAuth_Custom_Scope": "Область",
"Accounts_OAuth_Custom_Secret": "Ключ",
"Accounts_OAuth_Custom_Token_Path": "Token Path",
- "Accounts_OAuth_Custom_Token_Sent_Via": "Токен посланными через",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Токен отправлен через",
+ "Accounts_OAuth_Custom_Username_Field": "Поле \"логин\"",
+ "Accounts_OAuth_Drupal": "Включить вход через Drupal",
+ "Accounts_OAuth_Drupal_callback_url": "URI перенаправления Drupal oAuth2",
+ "Accounts_OAuth_Drupal_id": "ID клиента Drupal oAuth2",
+ "Accounts_OAuth_Drupal_secret": "Секретный ключ клиента Drupal oAuth2",
"Accounts_OAuth_Facebook": "Facebook логин",
- "Accounts_OAuth_Facebook_callback_url": "Обратный URL-адрес Facebook",
- "Accounts_OAuth_Facebook_id": "Facebook App Id",
+ "Accounts_OAuth_Facebook_callback_url": "Обратный URL-адрес Facebook",
+ "Accounts_OAuth_Facebook_id": "Идентификатор Facebook App",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
- "Accounts_OAuth_Github": "OAuth разрешён",
+ "Accounts_OAuth_Github": "OAuth включен",
"Accounts_OAuth_Github_callback_url": "Обратный URL-адрес Github",
"Accounts_OAuth_GitHub_Enterprise": "OAuth включен",
"Accounts_OAuth_GitHub_Enterprise_callback_url": "Обратный URL-адрес GitHub Enterprise",
- "Accounts_OAuth_GitHub_Enterprise_id": "Client Id",
+ "Accounts_OAuth_GitHub_Enterprise_id": "Идентификатор клиента",
"Accounts_OAuth_GitHub_Enterprise_secret": "Client Secret",
- "Accounts_OAuth_Github_id": "Client Id",
+ "Accounts_OAuth_Github_id": "Идентификатор клиента",
"Accounts_OAuth_Github_secret": "Client Secret",
"Accounts_OAuth_Gitlab": "OAuth включен",
"Accounts_OAuth_Gitlab_callback_url": "Обратный URL-адрес GitLab",
- "Accounts_OAuth_Gitlab_id": "GitLab Id",
+ "Accounts_OAuth_Gitlab_id": "Идентификатор GitLab",
"Accounts_OAuth_Gitlab_secret": "Client Secret",
"Accounts_OAuth_Google": "Google логин",
"Accounts_OAuth_Google_callback_url": "Обратный URL-адрес Google",
- "Accounts_OAuth_Google_id": "Google ID",
+ "Accounts_OAuth_Google_id": "Идентификатор Google",
"Accounts_OAuth_Google_secret": "Google пароль",
- "Accounts_OAuth_Linkedin": "Логин LinkedIn",
+ "Accounts_OAuth_Linkedin": "LinkedIn логин",
"Accounts_OAuth_Linkedin_callback_url": "Обратный URL-адрес Linkedin",
- "Accounts_OAuth_Linkedin_id": "LinkedIn Id",
+ "Accounts_OAuth_Linkedin_id": "Идентификатор LinkedIn",
"Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
- "Accounts_OAuth_Meteor": "Логин Meteor",
+ "Accounts_OAuth_Meteor": "Meteor логин",
"Accounts_OAuth_Meteor_callback_url": "Обратный URL-адрес Meteor",
- "Accounts_OAuth_Meteor_id": "Meteor Id",
+ "Accounts_OAuth_Meteor_id": "Идентификатор Meteor",
"Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_host": "Прокси хост",
+ "Accounts_OAuth_Proxy_services": "Прокси сервисы",
"Accounts_OAuth_Twitter": "Логин Twitter",
- "Accounts_OAuth_Twitter_callback_url": "Обратный URL-адрес Twitter",
- "Accounts_OAuth_Twitter_id": "Twitter ID",
+ "Accounts_OAuth_Twitter_callback_url": "Callback URL-адрес Twitter",
+ "Accounts_OAuth_Twitter_id": "Идентификатор Twitter",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress логин",
"Accounts_OAuth_Wordpress_callback_url": "Обратный URL-адрес Wordpress",
- "Accounts_OAuth_Wordpress_id": "WordPress ID",
- "Accounts_OAuth_Wordpress_secret": "Пароль WordPress",
+ "Accounts_OAuth_Wordpress_id": "Идентификатор WordPress",
+ "Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Восстановление пароля",
- "Accounts_Registration_AuthenticationServices_Enabled": "Регистрация со службами проверки подлинности",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Роли по-умолчанию для сервисов аутентификации",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Роли по-умолчанию (разделенные запятой), назначаемые пользователям при регистрации через сервисы аутентификации",
+ "Accounts_Registration_AuthenticationServices_Enabled": "Регистрация сервисами проверки подлинности",
"Accounts_RegistrationForm": "Регистрационная форма",
"Accounts_RegistrationForm_Disabled": "Отключена",
"Accounts_RegistrationForm_LinkReplacementText": "Текст замены ссылки регистрационной формы",
- "Accounts_RegistrationForm_Public": "Доступна публично",
- "Accounts_RegistrationForm_Secret_URL": "Тайный URL-адрес",
- "Accounts_RegistrationForm_SecretURL": "Тайный URL-адрес регистрационной формы",
- "Accounts_RegistrationForm_SecretURL_Description": "Вы должны предоставить случайную строку, которая будет добавлена к вашему регистрационному URL-адресу. Например: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_Public": "Открытая",
+ "Accounts_RegistrationForm_Secret_URL": "Секретный URL-адрес",
+ "Accounts_RegistrationForm_SecretURL": "Секретный URL-адрес регистрационной формы",
+ "Accounts_RegistrationForm_SecretURL_Description": "Вы должны предоставить случайную строку, которая будет добавлена к вашему регистрационному URL-адресу. Например: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Требуется имя для регистрации",
+ "Accounts_RequirePasswordConfirmation": "Запрашивать подтверждение пароля",
+ "Accounts_SearchFields": "Поля, которые следует учитывать при поиске",
+ "Accounts_SetDefaultAvatar": "Установить аватар по-умолчанию",
+ "Accounts_SetDefaultAvatar_Description": "Пытаться найти аватар по-умолчанию через аккаунт OAuth или Gravatar",
"Accounts_ShowFormLogin": "Показать логин на основе формы",
"Accounts_UseDefaultBlockedDomainsList": "Использовать список запрещённых доменов по умолчанию",
"Accounts_UseDNSDomainCheck": "Использовать DNS проверку доменов",
- "Accounts_UserAddedEmail_Default": "Добро пожаловать в [Site_Name] Посетите [Site_URL] и опробйте лучшее решение для чатов с открытым исходным кодом на сегодняшний день!
Вы можете войти в систему, используя адрес электронной почты: [email] и пароль: [password]. Возможно, вам потребуется изменить его после первого входа в систему.",
- "Accounts_UserAddedEmail_Description": "Вы можете использовать следующие замены:
[name], [fname], [lname] полное имя пользователя, имя или фамилию, соответственно. [email] для электронной почты пользователя. [password] для пароля пользователя. [Site_Name] и [Site_URL] для названия сайта и URL соответственно. ",
+ "Accounts_UserAddedEmail_Default": "Добро пожаловать в [Site_Name] Посетите [Site_URL] и попробуйте лучшее решение для чатов с открытым исходным кодом на сегодняшний день!
Вы можете войти в систему, используя адрес электронной почты: [email] и пароль: [password]. Возможно, вам потребуется изменить его после первого входа в систему.",
+ "Accounts_UserAddedEmail_Description": "Вы можете использовать следующие подстановки:
[name], [fname], [lname] (полное имя пользователя, только имя или только фамилию, соответственно). [email] - адрес электронной почты пользователя. [password] - пароля пользователя. [Site_Name] и [Site_URL] - название вашего приложения и его URL. ",
"Accounts_UserAddedEmailSubject_Default": "Вы были добавлены в [Site_Name]",
"Activate": "Активировать",
"Activity": "Активность",
"Add": "Добавить",
- "Add_agent": "Добавить сотрудника",
- "Add_custom_oauth": "Добавить пользовательский OAuth",
+ "add-oauth-service": "Добавлять сервисы Oauth",
+ "add-oauth-service_description": "Разрешение на добавление новых сервисов Oauth",
+ "add-user": "Добавлять пользователей",
+ "add-user-to-any-c-room": "Добавить пользователя к любому публичному каналу",
+ "add-user-to-any-c-room_description": "Разрешение на добавление пользователя к любому публичному каналу",
+ "add-user-to-any-p-room": "Добавить пользователя к любому приватному каналу",
+ "add-user-to-any-p-room_description": "Разрешение на добавление пользователя к любому приватному каналу",
+ "add-user-to-joined-room": "Добавить пользователя к любому каналу, к которому присоединён",
+ "add-user-to-joined-room_description": "Разрешение на добавление пользователя к тому публичному каналу, к которому сейчас присоединён",
+ "add-user_description": "Разрешение на добавление новых пользователей на сервер на странице пользователей",
+ "Add_agent": "Добавить представителя",
+ "Add_custom_oauth": "Добавить кастомный OAuth",
+ "Add_Domain": "Добавить домен",
+ "Add_files_from": "Добавить файлы",
"Add_manager": "Добавить менеджера",
+ "Add_Role": "Добавить роль",
"Add_user": "Добавить пользователя",
- "Add_User": "Добавить пользователя",
+ "Add_User": "Добавить Пользователя",
"Add_users": "Добавить пользователей",
- "Adding_OAuth_Services": "Добавление OAuth услуги",
+ "Adding_OAuth_Services": "Добавление сервисы OAuth ",
"Adding_permission": "Добавление разрешения",
"Adding_user": "Добавление пользователя",
- "Additional_emails": "Дополнительные email",
+ "Additional_emails": "Дополнительные адреса электронной почты",
"Additional_Feedback": "Дополнительная обратная связь",
"Administration": "Администрирование",
+ "Adult_images_are_not_allowed": "Изображения для взрослых запрещены",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "После аутентификации OAuth2, пользователи будут перенаправляться на этот URL-адрес",
- "Agent": "Агент",
- "Agent_added": "Сотрудник добавлен",
- "Agent_removed": "Сотрудник удален",
- "Alias": "Алиас",
+ "Agent": "Представитель",
+ "Agent_added": "Представитель добавлен",
+ "Agent_removed": "Представитель удален",
+ "Alias": "Псевдоним",
+ "Alias_Format": "Формат псевдонима",
+ "Alias_Format_Description": "Импортировать сообщения из Slack с псевдонимом; %s заменяется на логин пользователя. Если не указано, псевдоним не будет использоваться.",
+ "Alias_Set": "Настройки псевдонима",
"All": "Все",
- "All_channels": "Все Чаты",
+ "All_channels": "Все каналы",
"All_logs": "Все записи",
"All_messages": "Все сообщения",
+ "All_users_in_the_channel_can_write_new_messages": "Все пользователи на канале могут писать новые сообщения",
"Allow_Invalid_SelfSigned_Certs": "Разрешить недействительные самоподписанные сертификаты",
- "Allow_Invalid_SelfSigned_Certs_Description": "Разрешить некорректные и самоподписанные SSL сертификаты.",
- "Analytics_features_enabled": "Особенности Включено",
- "Analytics_features_messages_Description": "Треки пользовательские события, связанные с действиями пользователя делает на сообщениях.",
- "Analytics_features_rooms_Description": "Треки пользовательские события, связанные с действиями по каналу или группе (создание, оставить, удалить).",
- "Analytics_features_users_Description": "Треки пользовательские события, связанные с действиями, связанных с пользователями (время сброса пароля, изменение профиля фото и т.д.).",
+ "Allow_Invalid_SelfSigned_Certs_Description": "Разрешить недействительные и самоподписанные SSL сертификаты для проверки ссылок и предосмотра.",
+ "Allow_switching_departments": "Разрешить посетителю сменить отдел",
+ "Always_open_in_new_window": "Всегда открывать в новом окне",
+ "Analytics_features_enabled": "Включенные функции",
+ "Analytics_features_messages_Description": "Отслеживать пользовательские события, связанные с сообщениями.",
+ "Analytics_features_rooms_Description": "Отслеживать пользовательские события, связанные с действиями в чатах (создать, покинуть, удалить).",
+ "Analytics_features_users_Description": "Отслеживать пользовательские события, связанные с пользователями (время сброса пароля, изменение аватара и т. д.).",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "Идентификатор отслеживания",
"and": "и",
"And_more": "И еще __length__",
"Animals_and_Nature": "Животные и природа",
- "API": "Интерфейс приложения",
+ "Announcement": "Объявление",
+ "API": "API",
+ "API_Allow_Infinite_Count": "Разрешить получить всё",
+ "API_Allow_Infinite_Count_Description": "Могут ли вызовы к REST API возвращать всё за один вызов?",
"API_Analytics": "Аналитика",
- "API_Embed": "Embed вставки",
- "API_EmbedDisabledFor": "Запретить Embed для пользователей",
- "API_EmbedDisabledFor_Description": "Разделенный запятыми список имен пользователей",
+ "API_CORS_Origin": "Заголовок CORS Origin",
+ "API_Default_Count": "Количество по-умолчанию",
+ "API_Default_Count_Description": "Количество результатов REST API для использования по-умолчанию, если потребитель не указал его.",
+ "API_Drupal_URL": "URL сервера Drupal",
+ "API_Drupal_URL_Description": "Пример: https://domain.com (без слэша в конце)",
+ "API_Embed": "Встроенный просмотр ссылок",
+ "API_Embed_Description": "Включить ли предварительный просмотр ссылок, когда пользователь выкладывает ссылку на веб-сайт.",
+ "API_Embed_UserAgent": "Встроенный user agent",
+ "API_EmbedCacheExpirationDays": "Время хранения кэша предварительного просмотра в днях",
+ "API_EmbedDisabledFor": "Запретить встраивание для пользователей",
+ "API_EmbedDisabledFor_Description": "Список логинов, разделенных запятыми, для отключения предварительного просмотра ссылок.",
"API_EmbedIgnoredHosts": "Игнорировать хосты для Embed",
- "API_EmbedIgnoredHosts_Description": "Разделенных запятыми список хостов или CIDR адресов, например. локальный, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
+ "API_EmbedIgnoredHosts_Description": "Список хостов или адресов CIDR, разделенных запятыми, например. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Безопасные порты",
- "API_EmbedSafePorts_Description": "Разделенных запятыми список портов, разрешенных для просмотра.",
+ "API_EmbedSafePorts_Description": "Список портов, разделенных запятыми, разрешенный для предварительного просмотра.",
+ "API_Enable_CORS": "Включить CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "Включить конечную точку истории сообщений",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "Эта настройка включает `/api/v1/im.history.others`. Это разрешает просмотр сообщений из личных диалогов, в которых не участвует вызывающий.",
+ "API_Enable_Shields": "Включить щиты",
+ "API_Enable_Shields_Description": "Включить щиты, доступные в `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "URL-адрес сервера",
- "API_GitHub_Enterprise_URL_Description": "Пример: http://domain.com (без завершающего слеша)",
+ "API_GitHub_Enterprise_URL_Description": "Пример: http://domain.com (без завершающего слеша)",
"API_Gitlab_URL": "GitLab URL",
+ "API_Shield_Types": "Типы щитов",
+ "API_Shield_Types_Description": "Типы щитов в виде списка с разделением запятой, выбирайте из `online`, `channel` либо используйте `*` для всех",
"API_Token": "API Токен",
- "API_User_Limit": "Лимит пользователя для добавления всех пользователей к каналу",
+ "API_Upper_Count_Limit": "Максимальное число записей",
+ "API_Upper_Count_Limit_Description": "Какое максимальное число записей REST API должен возвращать (если не снято ограничение)?",
+ "API_User_Limit": "Лимит пользователя для добавления всех пользователей к чату",
"API_Wordpress_URL": "WordPress URL",
- "Apiai_Key": "Api.ai Key",
+ "Apiai_Key": "Ключ Api.ai",
"Apiai_Language": "Api.ai Язык",
"Appearance": "Внешний вид",
"Application_added": "Приложение добавлено",
"Application_Name": "Наименование приложения",
"Application_updated": "Приложение обновлено",
- "Apply_and_refresh_all_clients": "Применить и обновить все клиенты",
- "Archive": "Удалить",
+ "Apply_and_refresh_all_clients": "Применить",
+ "Archive": "Отправить канал в архив",
+ "archive-room": "Архивировать комнату",
+ "archive-room_description": "Разрешение на архивирование канала",
"are_also_typing": "тоже печатает...",
"are_typing": "печатает...",
"Are_you_sure": "Вы уверены?",
- "Are_you_sure_you_want_to_delete_your_account": "Вы уверены, что хотите удалить свой аккаунт?",
+ "Are_you_sure_you_want_to_delete_your_account": "Вы уверены, что хотите удалить свою учетную запись?",
+ "assign-admin-role": "Назначить на роль Администратора",
+ "assign-admin-role_description": "Разрешение назначить на роль Администратора другим пользователям",
+ "Assign_admin": "Назначенный администратор",
"at": "в",
- "Auth_Token": "Auth Токен",
- "Author": "автор",
+ "AtlassianCrowd": "Atlassian Crowd",
+ "Attachment_File_Uploaded": "Файл загружен",
+ "Attribute_handling": "Обработка атрибутов",
+ "Audio_message": "Звуковое сообщение",
+ "Audio_Notification_Value_Description": "Может быть любой выборочный звук или один из звуков по умолчанию: beep, chelle, ding, droplet, highbell, seasons",
+ "Audio_Notifications_Default_Alert": "Звуковые уведомления",
+ "Audio_Notifications_Value": "Сообщение по умолчанию для аудио уведомления",
+ "Auth_Token": "Токен авторизации",
+ "Author": "Автор",
"Authorization_URL": "Авторизация URL-адреса",
- "Authorize": "Разрешить",
+ "Authorize": "Авторизовать",
+ "auto-translate": "Автоматический перевод",
+ "auto-translate_description": "Разрешение пользоваться автоматическим переводом",
"Auto_Load_Images": "Автозагрузка изображений",
- "AutoLinker_Email": "Подсвечивать Email",
+ "Auto_Translate": "Авто-перевод",
+ "AutoLinker_Email": "Подсвечивать адрес электронной почты",
"AutoLinker_Phone": "Подсвечивать телефоны",
"AutoLinker_Phone_Description": "Автоматически выделять телефонные номера, например `(123)456-7890`",
"AutoLinker_StripPrefix": "Удалять префиксы",
@@ -178,12 +265,17 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URL-адреса",
"AutoLinker_Urls_www": "URL-адреса AutoLinker 'WWW'",
"AutoLinker_UrlsRegExp": "Сокращать URL через регулярное выражение",
+ "Automatic_Translation": "Автоматический перевод",
+ "AutoTranslate_Change_Language_Description": "Изменение языка автоматического перевода не переводит предыдущие сообщения",
+ "AutoTranslate_Enabled": "включить авто-перевод",
+ "AutoTranslate_Enabled_Description": "Автоматический перевод дает пользователю возможность переводить все сообщения на его язык. За перевод может взыматься оплата, обратитесь к документации Google ",
+ "AutoTranslate_GoogleAPIKey": "Google API ключ",
"Available": "Доступен",
- "Available_agents": "Свободные сотрудники",
+ "Available_agents": "Свободные представители",
"Avatar": "Аватар",
"Avatar_changed_successfully": "Аватар успешно изменен",
"Avatar_URL": "URL-адрес Аватара",
- "Avatar_url_invalid_or_error": "Предоставленный URL-адрес недействителен или недоступен. Повторите попытку с другим URL-адресом.",
+ "Avatar_url_invalid_or_error": "Предоставленный URL-адрес недействителен или недоступен. Пожалуйста, повторите попытку с другим URL-адресом.",
"away": "отошёл",
"Away": "Отошёл",
"away_female": "отошла",
@@ -192,61 +284,120 @@
"Away_male": "Отошёл",
"Back": "Назад",
"Back_to_applications": "Вернуться к приложениям",
- "Back_to_integrations": "Назад к интеграциям",
+ "Back_to_chat": "Назад в чат",
+ "Back_to_integration_detail": "Назад к инеграции",
+ "Back_to_integrations": "Назад",
"Back_to_login": "На страницу авторизации",
"Back_to_permissions": "Назад к настройкам прав",
- "Body": "Основная часть",
+ "Backup_codes": "Коды резервного копирования",
+ "ban-user": "Забанить пользователя",
+ "ban-user_description": "Разрешение на бан пользователей на канале",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Функция в бета тестировании. Зависит от Video Conference.",
+ "Block_User": "Заблокировать пользователя",
+ "Body": "Тело",
"bold": "жирный",
+ "bot_request": "Запрос бота",
+ "BotHelpers_userFields": "Пользовательские поля",
+ "BotHelpers_userFields_Description": "CSV полей пользователя, к которым можно получить доступ с помощью методов ботов помощников.",
"Branch": "Ветка",
+ "Broadcast_Connected_Instances": "Широковещательные подключенные виртуальные машины",
+ "Bugsnag_api_key": "Ключ Bugsnag API",
+ "bulk-create-c": "Массовое создание каналов",
+ "bulk-create-c_description": "Разрешение на массовое создание каналов",
+ "bulk-register-user": "Массовое создание каналов",
+ "bulk-register-user_description": "Разрешение на массовое создание каналов",
"busy": "занят",
"Busy": "Занят",
"busy_female": "занята",
- "Busy_female": "Занята",
+ "Busy_female": "Занят",
"busy_male": "занят",
- "Busy_male": "Занят",
+ "Busy_male": "Занята",
"by": "от",
+ "cache_cleared": "Кэш очищен",
"Cancel": "Отмена",
"Cancel_message_input": "Отменить",
- "Cannot_invite_users_to_direct_rooms": "Нельзя приглашать пользователей в приватные чаты",
+ "Cannot_invite_users_to_direct_rooms": "Нельзя приглашать пользователей в личную переписку",
+ "Cannot_open_conversation_with_yourself": "Нельзя создавать чат с самим собой",
+ "CAS_autoclose": "Автозакрытие всплывающего окна авторизации",
+ "CAS_base_url": "SSO базовый URL",
+ "CAS_base_url_Description": "Базовый URL вашего внешнего сервиса SSO. Например: https://sso.example.undef/sso/",
+ "CAS_button_color": "Цвет фона кнопки входа",
+ "CAS_button_label_color": "Цвет текста кнопки входа",
+ "CAS_button_label_text": "Текст кнопки входа",
+ "CAS_enabled": "Включено",
+ "CAS_Login_Layout": "Стиль окна CAS авторизации",
+ "CAS_login_url": "SSO логин URL",
+ "CAS_login_url_Description": "Логин URL вашего внешнего сервиса SSO. Например: https://sso.example.undef/sso/login",
+ "CAS_popup_height": "Высота всплывающего окна входа",
+ "CAS_popup_width": "Ширина всплывающего окна входа",
+ "CAS_Sync_User_Data_Enabled": "Всегда синхронизировать пользовательские данные",
+ "CAS_Sync_User_Data_Enabled_Description": "Всегда синхронизировать внешние пользовательские данные CAS с доступными атрибутами при входе в систему. Примечание: атрибуты всегда синхронизируются при создании учетной записи.",
+ "CAS_Sync_User_Data_FieldMap": "Атрибуты карты",
+ "CAS_Sync_User_Data_FieldMap_Description": "Используйте этот JSON для создания внутренних атрибутов (ключ) из внешних атрибутов (значение). Имена внешних атрибутов, обрамленные '%', будут интерполированы в строки значений. Например, `{\"email\":\"%email%\", \"name\":\"%firstname%, %lastname%\"}` Map атрибутов всегда интерполируется. В CAS 1.0 доступен только атрибут `username`. Из внутренних атрибутов доступны: логин (username), имя (name), адрес электронной почты (email), комнаты (rooms); комнаты - это список комнат, к которым присоединить пользователя после создания, разделенный запятой, например: {\"rooms\": \"%team%,%department%\"} присоединит пользователей CAS при создании к каналам их команды и отдела.",
+ "CAS_version": "Версия CAS",
+ "CAS_version_Description": "Используйте только поддерживаемую версию CAS, поддерживаемую вашим сервисом CAS SSO.",
"CDN_PREFIX": "CDN префикс",
"Certificates_and_Keys": "Ключи и сертификаты",
- "Changing_email": "Изменение электронной почты",
- "Channel": "Публичный чат",
- "Channel_already_exist": "Канал '#% s' уже существует.",
- "Channel_already_Unarchived": "Канал с именем `#% s` уже находится в состоянии разархивирована",
- "Channel_Archived": "Канал с именем `#% s` находится в архиве успешно",
- "Channel_doesnt_exist": "Чат `#%s` не существует.",
- "Channel_Unarchived": "Канал с именем `#% s` был успешно Разархивирован",
- "Channels": "Чаты",
- "Channels_list": "Список общих чатов",
+ "Change_Room_Type": "Изменить тип канала",
+ "Changing_email": "Изменение адреса электронной почты",
+ "channel": "канал",
+ "Channel": "Канал",
+ "Channel_already_exist": "Канал \"#%s\" уже существует.",
+ "Channel_already_exist_static": "Такой канал уже существует",
+ "Channel_already_Unarchived": "Канал с именем \"#%s\" уже находится в состоянии \"разархивирован\"",
+ "Channel_Archived": "Канал с именем \"#%s\" успешно архивирован ",
+ "Channel_created": "Канал \"#%s\" создан.",
+ "Channel_doesnt_exist": "Канала \"#%s\" не существует.",
+ "Channel_name": "Имя канала",
+ "Channel_Name_Placeholder": "Пожалуйста, введите название канала...",
+ "Channel_to_listen_on": "Канал для прослушивания",
+ "Channel_Unarchived": "Канал с именем \"#%s\" успешно разархивирован ",
+ "Channels": "Каналы",
+ "Channels_are_where_your_team_communicate": "Каналы для общения вашей команды",
+ "Channels_list": "Список каналов",
"Chat_button": "кнопка чат",
- "Chat_closed": "чат закрыт",
+ "Chat_closed": "Чат закрыт",
"Chat_closed_successfully": "Чат успешно закрыт",
- "Chat_window": "окно чата",
+ "Chat_Now": "Общатся сейчас",
+ "Chat_window": "Окно чата",
"Chatops_Enabled": "Включить Chatops",
- "Chatops_Title": "Панель Chatops",
- "Chatops_Username": "Имя пользователя Chatops",
- "Choose_a_room": "Выберите чат",
+ "Chatops_Title": "Панель Chatops",
+ "Chatops_Username": "Логин Chatops",
+ "Choose_a_room": "Выберите комнату",
"Choose_messages": "Выбрать сообщения",
- "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Выберите псевдоним, который появится перед именем пользователя в сообщениях.",
- "Choose_the_username_that_this_integration_will_post_as": "Выберите имя пользователя, которое опубликует эта интеграция.",
- "Clear_all_unreads_question": "Удалить все \"непрочитанные\"?",
+ "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Выберите псевдоним, который появится перед логином в сообщениях.",
+ "Choose_the_username_that_this_integration_will_post_as": "Выберите логин, под которым эта интеграция будет постить.",
+ "clean-channel-history": "Очистить историю канала",
+ "clean-channel-history_description": "Разрешение удалять историю на каналах",
+ "clear": "Очистить",
+ "Clear_all_unreads_question": "Удалить все непрочитанные?",
+ "clear_cache_now": "Очистить кэш сейчас",
+ "clear_history": "Очистить историю",
"Click_here": "кликните сюда",
- "Client_ID": "Client ID",
- "Client_Secret": "Client Secret",
+ "Click_here_for_more_info": "Больше информации здесь",
+ "Click_to_join": "Нажмите, чтобы присоединиться!",
+ "Client_ID": "Идентификатор клиента",
+ "Client_Secret": "Клиент Secret",
"Clients_will_refresh_in_a_few_seconds": "Клиенты обновятся через пару секунд",
"close": "закрыть",
"Close": "Закрыть",
+ "close-livechat-room": "Закрыть комнату Livechat ",
+ "close-livechat-room_description": "Разрешение на закрытие текущего чата LiveChat",
+ "close-others-livechat-room": "Закрыть комнату Livechat ",
+ "close-others-livechat-room_description": "Разрешение закрывать другие каналы LiveChat",
"Closed": "Закрыто",
+ "Closed_by_visitor": "Закрыто посетителем",
"Closing_chat": "Закрыть чат",
"Collapse_Embedded_Media_By_Default": "Сворачивать вложенные медиа по умолчанию",
"Color": "Цвет",
"Commands": "Команды",
+ "Comment_to_leave_on_closing_session": "Комментарий для выхода при закрытии сессии",
"Compact": "Компактный",
"Confirm_password": "Подтвердить пароль",
- "Conversation": "Диалог",
- "Conversation_closed": "Разговор закрыт: __comment__.",
- "Convert_Ascii_Emojis": "Конвертировать ASCII в Emoji",
+ "Content": "Содержимое",
+ "Conversation": "Беседа",
+ "Conversation_closed": "Беседа закрыта: __comment__.",
+ "Convert_Ascii_Emojis": "Конвертировать ASCII в эмодзи",
"Copied": "Скопировано",
"Copy": "Копировать",
"Copy_to_clipboard": "Копировать в буфер обмена",
@@ -254,978 +405,1618 @@
"Count": "Количество",
"Cozy": "Удобный",
"Create": "Создать",
- "Create_A_New_Channel": "Создать новый канал",
- "Create_new": "Создать чат",
- "Created_at": "Создано в",
- "Created_at_s_by_s": "Создано в %s при помощи %s ",
+ "create-c": "Создать публичные каналы",
+ "create-c_description": "Разрешение на создание публичных каналов",
+ "create-d": "Создавать чаты личных сообщений",
+ "create-d_description": "Разрешение на создание чатов личных сообщений",
+ "create-p": "Создавать закрытые чаты",
+ "create-p_description": "Разрешение создавать закрытые чаты",
+ "create-user": "Создавать пользователей",
+ "create-user_description": "Разрешение на создание пользователей",
+ "Create_A_New_Channel": "Создать новый канал ",
+ "Create_new": "Создать новый",
+ "Created_at": "Создан",
+ "Created_at_s_by_s": "Создано в %s при помощи %s ",
+ "Created_at_s_by_s_triggered_by_s": "Создано в %s пользователем %s сработало на %s ",
+ "CRM_Integration": "Интеграция с CRM",
+ "CROWD_Reject_Unauthorized": "Отклонить неавторизованных",
"Current_Chats": "Текущие чаты",
- "Custom": "Индивидуальное",
+ "Current_Status": "Текущий статус",
+ "Custom": "Пользовательские ",
+ "Custom_Emoji": "Пользовательские смайлы",
+ "Custom_Emoji_Add": "Добавить новый смайл",
+ "Custom_Emoji_Added_Successfully": "Пользовательский смайл успешно добавлен",
+ "Custom_Emoji_Delete_Warning": "Удаление смайла нельзя отменить.",
+ "Custom_Emoji_Error_Invalid_Emoji": "Некорректный смайл",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "Этот смайл или один из его псевдонимов уже используются",
+ "Custom_Emoji_Has_Been_Deleted": "Пользовательский смайл успешно удален",
+ "Custom_Emoji_Info": "Информация о пользовательском смайле",
+ "Custom_Emoji_Updated_Successfully": "Пользовательский смайл успешно обновлен",
"Custom_Fields": "Пользовательские поля",
- "Custom_oauth_helper": "Настраивая вашего поставщика OAuth, вам необходимо сообщить обратный URL-адрес. Используйте %s .",
- "Custom_oauth_unique_name": "Уникальное имя пользовательского OAuth",
- "Custom_Script_Logged_In": "Пользовательский сценарий для зарегистрированных пользователей",
- "Custom_Script_Logged_Out": "Пользовательский сценарий для незарегистрированных пользователей",
+ "Custom_oauth_helper": "Настраивая вашего поставщика OAuth, вам необходимо сообщить обратный URL-адрес. Используйте %s .",
+ "Custom_oauth_unique_name": "Кастомный uniquie name OAuth",
+ "Custom_Script_Logged_In": "Пользовательский скрипт для зарегистрированных пользователей",
+ "Custom_Script_Logged_Out": "Пользовательский скрипт для незарегистрированных пользователей",
+ "Custom_Scripts": "Пользовательские скрипты",
+ "Custom_Sound_Add": "Добавить свой звук",
+ "Custom_Sound_Delete_Warning": "Удаление звука нельзя отменить",
+ "Custom_Sound_Error_Invalid_Sound": "Некорректный звук",
+ "Custom_Sound_Error_Name_Already_In_Use": "Имя этого звука уже используется",
+ "Custom_Sound_Has_Been_Deleted": "Звук успешно удален",
+ "Custom_Sound_Info": "Информация о пользовательском звуке",
+ "Custom_Sound_Saved_Successfully": "Пользовательский звук успешно сохранен",
+ "Custom_Sounds": "Пользовательские звуки",
+ "Custom_Translations": "Пользовательские переводы",
+ "Custom_Translations_Description": "Должен быть валидным JSON, где ключи - языки, значения - словари ключей и их переводов. Пример:\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n}",
+ "CustomSoundsFilesystem": "Файловая система пользовательских звуков",
"Dashboard": "Панель",
"Date": "Дата",
+ "Date_From": "От",
+ "Date_to": "До",
"days": "дней",
"DB_Migration": "Миграция базы данных",
- "DB_Migration_Date": "База данных Дата миграции",
+ "DB_Migration_Date": "Дата миграции базы данных",
"Deactivate": "Деактивировать",
+ "Decline": "Отклнонить",
"Default": "По умолчанию",
"Delete": "Удалить",
- "Delete_message": "Удаленное сообщение",
- "Delete_my_account": "Удалить мой аккаунт",
- "Delete_Room_Warning": "Удаление чата так же удалит все сообщения в нем. Это действие невозможно отменить.",
- "Delete_User_Warning": "Удаление пользователя удалит все сообщения от этого пользователя. Это действие невозможно отменить.",
+ "delete-c": "Удалить публичные каналы",
+ "delete-c_description": "Разрешение на удаление публичных каналов",
+ "delete-d": "Удалять личные сообщения",
+ "delete-d_description": "Разрешение на удаление личных сообщений",
+ "delete-message": "Удалять сообщения",
+ "delete-message_description": "Разрешение на удаление сообщений из чатов",
+ "delete-p": "Удалять закрытые чаты",
+ "delete-p_description": "Разрешение на удаление закрытых чатов",
+ "delete-user": "Удалять пользователей",
+ "delete-user_description": "Разрешение на удаление пользователей",
+ "Delete_message": "Удалить сообщение",
+ "Delete_my_account": "Удалить мою учетную запись",
+ "Delete_Room_Warning": "Удаление комнаты удалит все сообщения в ней. Это действие невозможно отменить.",
+ "Delete_User_Warning": "Удаление пользователя удалит все сообщения этого пользователя. Это действие невозможно отменить.",
"Deleted": "Удалено!",
- "Department_removed": "Раздел удален",
- "Departments": "Разделы",
- "Deployment_ID": "ID Инсталяции",
+ "Department": "Отдел",
+ "Department_removed": "Отдел удален",
+ "Departments": "Отделы",
+ "Deployment_ID": "Идентификатор развертывания",
"Description": "Описание",
- "Desktop": "Рабочий стол",
- "Desktop_Notification_Test": "Проверка уведомлений рабочего стола",
- "Desktop_Notifications": "Уведомления на рабочем столе",
- "Desktop_Notifications_Disabled": "Уведомления на рабочем столе отключены. Измените настройки браузера, если вам нужно включить уведомления.",
- "Desktop_Notifications_Duration": "Длительность отображения уведомлений",
- "Desktop_Notifications_Duration_Description": "Секунды для отображения уведомлений на рабочем столе. Это может повлиять на OS X Центр уведомлений. Введите 0, чтобы использовать настройки браузера по умолчанию и не влиять на OS X Центр уведомлений.",
- "Desktop_Notifications_Enabled": "Уведомления для рабочего стола включены",
- "Direct_message_someone": "Личное сообщение кому-либо",
- "Direct_Messages": "Личные сообщения",
+ "Desktop": "Компьютер",
+ "Desktop_Notification_Test": "Проверка уведомлений на компьютере",
+ "Desktop_Notifications": "Оповещения на рабочем столе",
+ "Desktop_Notifications_Default_Alert": "Стандартные оповещения на рабочем столе",
+ "Desktop_Notifications_Disabled": "Оповещения отключены. Измените настройки браузера, чтобы включить уведомления.",
+ "Desktop_Notifications_Duration": "Длительность",
+ "Desktop_Notifications_Duration_Description": "Количество секунд в течение которых отображаются уведомления на компьютере. Это может повлиять на центр уведомлений OS X. Введите 0, чтобы использовать настройки браузера по умолчанию и не влиять на центр уведомлений OS X.",
+ "Desktop_Notifications_Enabled": "Уведомления на компьютере включены",
+ "Different_Style_For_User_Mentions": "Другой стиль для упоминаний пользователей",
+ "Direct_message_someone": "Личная переписка с кем-нибудь",
+ "Direct_Messages": "Личная переписка",
+ "Direct_Reply": "Прямой ответ",
+ "Direct_Reply_Debug": "Отладка прямого ответа",
+ "Direct_Reply_Debug_Description": "[ВНИМАНИЕ] Режим отлатки будет отображать ваш пароль в открытом виде в консоли администратора",
+ "Direct_Reply_Delete": "Удалить перехваченную электронную почту",
+ "Direct_Reply_Enable": "Разрешить прямой ответ",
+ "Direct_Reply_Frequency": "Частота проверки почты",
+ "Direct_Reply_Frequency_Description": "(в минутах, по умолчанию/минимальное значение - 2)",
+ "Direct_Reply_Host": "Хост прямого ответа",
+ "Direct_Reply_IgnoreTLS": "Игнорировать TLS",
+ "Direct_Reply_Password": "Пароль",
+ "Direct_Reply_Port": "Порт прямого ответа",
+ "Direct_Reply_Protocol": "Протокол прямого ответа",
+ "Direct_Reply_Separator": "Разделитель",
+ "Direct_Reply_Separator_Description": "[Меняйте только, если вы точно знаете, что делаете, смотрите документацию] разделитель между базой и тегом в электронной почте",
+ "Direct_Reply_Username": "Имя пользователя",
+ "Direct_Reply_Username_Description": "Пожалуйста, используйте абсолютную электронную почту, tagging не разрешено, оно будет переписана.",
+ "Disable_Notifications": "Отключить уведомления",
+ "Disable_two-factor_authentication": "Выключить двухфакторную аутентификацию",
"Display_offline_form": "Показать оффлайн сообщение",
- "Displays_action_text": "Вывести текст действия",
- "Do_you_want_to_change_to_s_question": "Хотите изменить на %s ?",
+ "Displays_action_text": "Показать текст действия",
+ "Do_you_want_to_change_to_s_question": "Хотите изменить на %s ?",
"Domain": "Домен",
+ "Domain_added": "домен добален",
+ "Domain_removed": "Домен удален",
"Domains": "Домены",
+ "Domains_allowed_to_embed_the_livechat_widget": "Список доменов, разделенный запятой, куда можно встроить виджет Livechat. Оставьте пустым, чтобы разрешить любые домены.",
+ "Download_Snippet": "Скачать",
"Drop_to_upload_file": "Переместите сюда для загрузки файла",
"Dry_run": "Пробный запуск",
- "Dry_run_description": "Мы отправим только один email на адрес, указанный в поле \"От\". Адрес должен принадлежать реальному пользователю.",
- "Duplicate_archived_channel_name": "Удалённый канал с именем '%s' существует",
- "Duplicate_archived_private_group_name": "Удалённый приватный чат с именем '%s' существует",
- "Duplicate_channel_name": "Канал с именем '% s' существует",
- "Duplicate_private_group_name": "Приватный чат с именем '%s' уже существует",
+ "Dry_run_description": "Мы отправим только одно электронное сообщение на адрес, указанный в поле \"От\". Адрес электронной почты должен принадлежать реальному пользователю.",
+ "Duplicate_archived_channel_name": "Архивный канал с именем \"#%s\" уже существует",
+ "Duplicate_archived_private_group_name": "Архивная приватная группа с именем \"%s\" уже существует",
+ "Duplicate_channel_name": "Канал с именем \"%s\" уже существует",
+ "Duplicate_private_group_name": "Приватная группа с именем \"%s\" уже существует",
+ "Duration": "Длительность",
"Edit": "Редактировать",
+ "edit-message": "Редактировать сообщения",
+ "edit-message_description": "Разрешение на редактирование сообщений в чатах",
+ "edit-other-user-active-status": "Редактировать статус активности другого пользователя",
+ "edit-other-user-active-status_description": "Разрешение на блокировку и разблокировку аккаунтов",
+ "edit-other-user-info": "Редактировать информацию другого пользователя",
+ "edit-other-user-info_description": "Разрешить изменять имя, логин или адрес электронной почты другого пользователя.",
+ "edit-other-user-password": "Редактировать пароль другого пользователя",
+ "edit-other-user-password_description": "Разрешение на редактирование пароля другого пользователя. Требует разрешения на редактирование информации другого пользователя",
+ "edit-privileged-setting": "Изменить привилегированные параметры",
+ "edit-privileged-setting_description": "Возможность редактирование настроек",
+ "edit-room": "Редактировать комнату",
+ "edit-room_description": "Разрешение на редактирование имени, темы, типа (приватный или публичный) и статуса (активный или архивный) комнаты.",
"Edit_Custom_Field": "Редактировать поле",
- "Edit_Department": "Редактировать раздел",
+ "Edit_Department": "Редактировать отдел",
+ "Edit_previous_message": "'%s' - редактировать предыдущее сообщение",
+ "Edit_Trigger": "Изменить триггер",
"edited": "отредактировано",
- "Editing_room": "Редактирование номера",
+ "Editing_room": "Редактирование комнаты",
"Editing_user": "Редактирование пользователя",
- "Email": "Email",
+ "Email": "Электронная почта",
"Email_address_to_send_offline_messages": "Адрес электронной почты для отправки сообщения в оффлайн режиме",
- "Email_already_exists": "Email уже зарегистрирован",
- "Email_body": "Тело сообщения",
- "Email_Change_Disabled": "Администратор вашего Rocket.Chat запретил изменение email",
- "Email_Footer_Description": "Вы можете использовать следующие замены: [Site_Name] и [Site_URL] для имени приложения и URL соответственно. ",
+ "Email_already_exists": "Такой адрес электронной почты уже используется",
+ "Email_body": "Тело письма",
+ "Email_Change_Disabled": "Администратор вашего Rocket.Chat запретил изменение адреса электронной почты",
+ "Email_Footer_Description": "Вы можете использовать следующие подстановки: [Site_Name] и [Site_URL] для имени приложения и его URL соответственно. ",
"Email_from": "От",
- "Email_Header_Description": "Вы можете использовать следующие замены: [Site_Name] и [Site_URL] для имени приложения и URL соответственно. ",
- "Email_Notification_Mode": "Офлайн уведомления по электронной почте",
+ "Email_Header_Description": "Вы можете использовать следующие подстановки: [Site_Name] и [Site_URL] для имени приложения и его URL соответственно. ",
+ "Email_Notification_Mode": "Уведомления на Email",
"Email_Notification_Mode_All": "Каждое упоминание",
"Email_Notification_Mode_Disabled": "Отключено",
- "Email_or_username": "Почтовый ящик или логин",
+ "Email_or_username": "Адрес электронной почты или логин",
+ "Email_Placeholder": "Пожалуйста, введите ваше почтовый адрес...",
"Email_subject": "Тема",
- "Email_verified": "Email подтверждён",
- "Emoji": "Emoji",
+ "Email_verified": "Адрес электронной почты подтверждён",
+ "Emoji": "Эмодзи ",
+ "EmojiCustomFilesystem": "Файловая система пользовательских смайлов",
"Empty_title": "Пустой заголовок",
"Enable": "Включить",
- "Enable_Desktop_Notifications": "Включить уведомления для рабочего стола",
+ "Enable_Desktop_Notifications": "Включить уведомления на компьютере",
+ "Enable_Svg_Favicon": "Включить SVG favicon",
+ "Enable_two-factor_authentication": "Включить двухфакторную авторизацию",
"Enabled": "Включено",
"Encrypted_message": "Зашифрованное сообщение",
"End_OTR": "Завершить конфиденциальную беседу",
- "Enter_a_regex": "Введите regex",
- "Enter_a_room_name": "Введите название чата",
- "Enter_a_username": "Введите имя пользователя",
+ "Enter_a_regex": "Введите регулярное выражение",
+ "Enter_a_room_name": "Введите название комнаты",
+ "Enter_a_username": "Введите логин",
+ "Enter_Alternative": "Альтернативный режим (отправка по Ctrl/Alt/Shift/CMD + Enter)",
+ "Enter_authentication_code": "Введите код аутантификации",
+ "Enter_Behaviour": "Поведение клавиши Enter",
+ "Enter_Behaviour_Description": "Эта настройка определяет, будет Enter отправлять сообщение или добавлять новую строку",
"Enter_name_here": "Введите название",
+ "Enter_Normal": "Обычный режим (отправка по Enter)",
"Enter_to": "Выйти и ",
"Error": "Ошибка",
- "error-action-not-allowed": "__action__ не допускается",
+ "error-action-not-allowed": "__action__ не разрешено",
"error-application-not-found": "Приложение не найдено",
- "error-archived-duplicate-name": "Там в архивный канал с именем '__room_name__'",
- "error-avatar-invalid-url": "Неверный аватар URL: __url__",
+ "error-archived-duplicate-name": "Существует архивный канал с именем '__room_name__'",
+ "error-avatar-invalid-url": "Неверный URL аватара: __url__",
"error-avatar-url-handling": "Ошибка при работе установки аватара из URL (__url__) для __username__",
"error-cant-invite-for-direct-room": "Нельзя приглашать пользователей в личные сообщения",
- "error-could-not-change-email": "Невозможно изменить электронную почту",
+ "error-could-not-change-email": "Невозможно изменить адрес электронной почты",
"error-could-not-change-name": "Невозможно изменить имя",
- "error-could-not-change-username": "Невозможно изменить имя пользователя",
- "error-delete-protected-role": "Нельзя удалить защищённую позицию",
- "error-department-not-found": "Раздел не найден",
- "error-duplicate-channel-name": "Канал '%s' уже существует",
- "error-email-domain-blacklisted": " Email домен находится в черном списке",
+ "error-could-not-change-username": "Не удалось изменить логин",
+ "error-delete-protected-role": "Нельзя удалить защищённую роль",
+ "error-department-not-found": "Отдел не найден",
+ "error-direct-message-file-upload-not-allowed": "Передача файлов не разрешена в личных сообщениях",
+ "error-duplicate-channel-name": "Канал с именем '__channel_name__' уже существует",
+ "error-email-domain-blacklisted": "Домен адреса электронной почты находится в черном списке",
+ "error-email-send-failed": "Ошибка отправки электронного сообщения: __message__",
"error-field-unavailable": "__field__ уже используется :(",
- "error-file-too-large": "Файл слишком велик",
+ "error-file-too-large": "Размер файл слишком большой",
"error-importer-not-defined": "Импортер не был определен правильно, не хватает классификации импорта.",
- "error-input-is-not-a-valid-field": "__input__ не является допустимым __field__",
- "error-invalid-actionlink": "ссылка Неверное действие",
+ "error-input-is-not-a-valid-field": "__input__ недопустимое __field__",
+ "error-invalid-actionlink": "Недействительная ссылка",
"error-invalid-arguments": "Недопустимые аргументы",
"error-invalid-asset": "Недействительный актив",
"error-invalid-channel": "Недопустимый канал.",
"error-invalid-channel-start-with-chars": "Недопустимый канал. Начните с @ или #",
- "error-invalid-custom-field": "Неверное поле",
- "error-invalid-custom-field-name": "Неверное имя для поля. Используйте тельно буквы, цифры, дефисы и подчеркивания.",
- "error-invalid-description": "Неверное описание",
+ "error-invalid-custom-field": "Неверное пользовательское поле",
+ "error-invalid-custom-field-name": "Некорректное имя для поля. Используйте только буквы, цифры, дефисы и подчеркивания.",
+ "error-invalid-date": "Указана неверная дата",
+ "error-invalid-description": "Недопустимое описание",
"error-invalid-domain": "Ошибочный домен",
- "error-invalid-email": "Invalid __email__ электронной почты",
+ "error-invalid-email": "Некорректный адрес электронной почты __email__",
+ "error-invalid-email-address": "Некорректный адрес электронной почты",
"error-invalid-file-height": "Недопустимая высота файла",
"error-invalid-file-type": "Неверный тип файла",
"error-invalid-file-width": "Недопустимая ширина файла",
"error-invalid-from-address": "Вы сообщили неверный адрес отправителя.",
- "error-invalid-integration": "Invalid интеграция",
+ "error-invalid-integration": "Неверная интеграция",
"error-invalid-message": "Неверное сообщение",
"error-invalid-method": "Недопустимый метод",
- "error-invalid-name": "Ошибочное имя",
+ "error-invalid-name": "Неверное имя",
"error-invalid-password": "Неверный пароль",
"error-invalid-redirectUri": "Ошибочный redirectUri",
- "error-invalid-role": "недопустимая роль",
- "error-invalid-room": "Несуществующий чат",
- "error-invalid-room-name": "%s is not a valid room name, use only letters, numbers, hyphens and underscores",
- "error-invalid-room-type": "__type__ недопустимый тип чата.",
- "error-invalid-settings": "Неверные настройки, предоставляемые",
- "error-invalid-subscription": "Invalid подписка",
- "error-invalid-token": "Недопустимый маркер",
+ "error-invalid-role": "Недопустимая роль",
+ "error-invalid-room": "Такой комнаты не существует",
+ "error-invalid-room-name": "__room_name__ недопустимое имя комнаты",
+ "error-invalid-room-type": "__type__ недопустимый тип комнаты.",
+ "error-invalid-settings": "Недействительные настройки",
+ "error-invalid-subscription": "Неверная подписка",
+ "error-invalid-token": "Недопустимый токен",
"error-invalid-triggerWords": "Недействительные triggerWords",
- "error-invalid-urls": "Недействительные URL",
+ "error-invalid-urls": "Недействительные URLы",
"error-invalid-user": "Неверный пользователь",
- "error-invalid-username": "Неверное имя пользователя",
- "error-invalid-webhook-response": "Webhook URL ответил со статусом, чем 200",
+ "error-invalid-username": "Неверный логин",
+ "error-invalid-webhook-response": "Webhook URL ответил статусом, отличным от 200",
"error-message-deleting-blocked": "Удаление сообщений запрещено",
"error-message-editing-blocked": "Редактирование сообщений запрещено",
"error-message-size-exceeded": "Размер сообщения превышает Message_MaxAllowedSize",
"error-missing-unsubscribe-link": "Для того, чтобы [unsubscribe], вы должны предоставить эту ссылку.",
"error-no-tokens-for-this-user": "Нет токенов для этого пользователя",
"error-not-allowed": "Не разрешено",
- "error-not-authorized": "Не допускается",
- "error-push-disabled": "Push уведомления отключены",
- "error-remove-last-owner": "Это последний владелец. Пожалуйста, назначьте нового владельца до удаления этого.",
- "error-role-in-use": "Нельзя удалить позицию, потому что она используется",
- "error-role-name-required": "Необходимо название роли",
+ "error-not-authorized": "Не авторизован",
+ "error-push-disabled": "Push оповещения отключены",
+ "error-remove-last-owner": "Это последний владелец. Пожалуйста, назначьте нового владельца перед удалением этого.",
+ "error-role-in-use": "Нельзя удалить роль, потому что она используется",
+ "error-role-name-required": "Требуется название роли",
"error-the-field-is-required": "Поле __field__ требуется.",
- "error-too-many-requests": "Слишком много запросов. вы должны подождать __seconds__ секунд перед тем, как попробовать снова.",
+ "error-too-many-requests": "Ошибка, слишком много запросов. вы должны подождать __seconds__ секунд перед тем, как попробовать снова.",
"error-user-is-not-activated": "Пользователь не активирован",
- "error-user-not-in-room": "Пользователь не в этом чате",
+ "error-user-limit-exceeded": "Число пользователей, которых вы пытаетесь пригласить в #channel_name превышает лимит, установленный администратором",
+ "error-user-not-in-room": "Пользователь не в этой комнате",
"error-user-registration-disabled": "Регистрация пользователей отключена",
- "error-user-registration-secret": "Регистрация пользователя допускается только с помощью секретной URL",
- "error-you-are-last-owner": "Вы последний владелец чата. Пожалуйста, назначьте нового владельца до выхода из этого чата.",
+ "error-user-registration-secret": "Регистрация пользователя допускается только с помощью секретной ссылки",
+ "error-you-are-last-owner": "Вы последний владелец комнаты. Пожалуйста, назначьте нового владельца до выхода из этой комнаты.",
"Error_changing_password": "Ошибка при изменении пароля",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances": "Ошибка: требуется слежение за Oplog при запуске Rocket.Chat на виртуальных машинах",
+ "Error_RocketChat_requires_oplog_tailing_when_running_in_multiple_instances_details": "Пожалуйста, убедитесь, что ваш MongoDB находится в режиме ReplicaSet, а переменная среды MONGO_OPLOG_URL правильно определена на сервере приложений.",
"Esc_to": "Выйти и",
- "Example_s": "Пример: %s",
- "False": "Нет",
+ "Event_Trigger": "Событие",
+ "Event_Trigger_Description": "Выберите тим события который будет запускать этот webhook",
+ "every_30_minutes": "Раз в 30 минут",
+ "every_hour": "Раз в час",
+ "every_six_hours": "Раз в 6 часов",
+ "Everyone_can_access_this_channel": "У всех есть доступ в этот канал",
+ "Example_s": "Пример: %s",
+ "Exclude_Botnames": "Исключить ботов",
+ "Exclude_Botnames_Description": "Не обрабатывать сообщения от ботов, имена которых совпадают с регулярным выражением выше. Если незаполнено все сообщения будут обработаны.",
+ "False": "Ложный",
"Favorite_Rooms": "Включить избранные каналы",
- "Favorites": "Избранные чаты",
- "Features_Enabled": "Особенности Включено",
+ "Favorites": "Избранное",
+ "Features_Enabled": "Доступные функции",
"Field": "Поле",
- "Field_removed": "Полу удалено",
- "File_exceeds_allowed_size_of_bytes": "Превышен допустимый размер файла на __size__ байт",
- "FileUpload": "Загрузка файлов",
- "FileUpload_Enabled": "Загрузка файлов включена",
+ "Field_removed": "Поле удалено",
+ "Field_required": "Обязательное поле",
+ "File_exceeds_allowed_size_of_bytes": "Файл превышает допустимый размер __size__.",
+ "File_not_allowed_direct_messages": "Передача файлов не разрешена в личных сообщениях",
+ "File_type_is_not_accepted": "Недопустимый тип файла",
+ "File_uploaded": "Файл загружен",
+ "FileUpload": "Загрузка файла",
+ "FileUpload_Disabled": "Загрузка файлов выключена.",
+ "FileUpload_Enabled": "Загрузка файла включена",
+ "FileUpload_Enabled_Direct": "Включить загрузку файлов в личных сообщениях",
"FileUpload_File_Empty": "Пустой файл",
"FileUpload_FileSystemPath": "Системный путь",
+ "FileUpload_GoogleStorage_AccessId": "Идентификатор доступа Google Storage",
+ "FileUpload_GoogleStorage_AccessId_Description": "Идентификатор доступа обычно представлен в формате адреса электронной почты. Например, \"example-test@example.iam.gserviceaccount.com\"",
+ "FileUpload_GoogleStorage_Bucket": "Название Google Storage Bucket",
+ "FileUpload_GoogleStorage_Bucket_Description": "Название Bucket куда будут загружаться файлы",
+ "FileUpload_GoogleStorage_Secret": "Секретный ключ Google Storage",
+ "FileUpload_GoogleStorage_Secret_Description": "Пожалуйста, следуйте этим инструкциям и вставьте результат здесь.",
"FileUpload_MaxFileSize": "Максимальный размер загружаемых файлов (в байтах)",
"FileUpload_MediaType_NotAccepted": "Медиа-файлы не приняты",
- "FileUpload_MediaTypeWhiteList": "Разрешённые медиа файлы",
- "FileUpload_MediaTypeWhiteListDescription": "Список медиа файлов, разделённый запятой. Оставьте его пустым, чтобы разрешить все типы медиа файлов.",
+ "FileUpload_MediaTypeWhiteList": "Разрешённые медиа-файлы",
+ "FileUpload_MediaTypeWhiteListDescription": "Список медиа-файлов, разделённый запятой. Оставьте его пустым, чтобы разрешить все типы медиа файлов.",
"FileUpload_ProtectFiles": "Защитить загруженные файлы",
"FileUpload_ProtectFilesDescription": "Только авторизованные пользователи будут иметь доступ",
"FileUpload_S3_Acl": "Amazon S3 acl",
- "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
- "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
- "FileUpload_S3_Bucket": "Amazon S3 bucket",
+ "FileUpload_S3_AWSAccessKeyId": "Access Key",
+ "FileUpload_S3_AWSSecretAccessKey": "Secret Key",
+ "FileUpload_S3_Bucket": "Название Bucket",
"FileUpload_S3_BucketURL": "Bucket URL",
"FileUpload_S3_CDN": "Домен CDN для загрузок",
+ "FileUpload_S3_ForcePathStyle": "Форсировать Path Style",
"FileUpload_S3_Region": "Регион",
+ "FileUpload_S3_SignatureVersion": "Версия подписи",
+ "FileUpload_S3_URLExpiryTimeSpan": "Время истечения срока действия URL-адресов",
+ "FileUpload_S3_URLExpiryTimeSpan_Description": "Время, после которого созданные URL-адреса Amazon S3 перестают быть действительными (в секундах). Если установлено менее 5 секунд, это поле будет проигнорировано.",
"FileUpload_Storage_Type": "Тип хранения",
+ "First_Channel_After_Login": "Открыть канал после авторизации",
"Flags": "Флаги",
"Follow_social_profiles": "Добавляйте нас в друзья в социальных сетях, форкайте на github и пишите свои отзывы о нашем приложении у нас в trello.",
+ "Fonts": "Шрифты",
"Food_and_Drink": "Еда и питьё",
"Footer": "Нижний колонтитул",
- "For_your_security_you_must_enter_your_current_password_to_continue": "Чтобы продолжить, вы должны повторно ввести свой пароль для вашей безопасности",
- "Force_SSL": "Принудительный SSL",
- "Force_SSL_Description": "*ВНИМАНИЕ!* Ни в коем случае не используйте _Принудительный SSL_ в установках с обратным прокси (например, nginx). В таком случае вы должны делать переадресацию на нем, а не в Rocket.Chat.",
+ "Footer_Direct_Reply": "Подвал, когда прямой ответ включен",
+ "For_your_security_you_must_enter_your_current_password_to_continue": "Для вашей же безопасности, вы должны повторно ввести свой пароль, чтобы продолжить",
+ "force-delete-message": "Принудительное удаление сообщений",
+ "force-delete-message_description": "Разрешение на удаление сообщений в обход всех ограничений",
+ "Force_Disable_OpLog_For_Cache": "Форсировать отключение OpLog для кэша",
+ "Force_Disable_OpLog_For_Cache_Description": "Не использовать OpLog для синхронизации кеша, даже, если он доступен",
+ "Force_SSL": "Форсировать SSL",
+ "Force_SSL_Description": "* Внимание! * _Force SSL_ никогда не должен использоваться с обратным прокси (например, nginx). Если у вас есть обратный прокси-сервер, вы должны сделать перенаправление ТАМ. _Force SSL_ существует для таких платформ, как Heroku, которая не позволяет перенаправить конфигурацию в обратном прокси.",
"Forgot_password": "Забыли пароль?",
+ "Forgot_Password_Description": "Вы можете использовать следующие подстановки: [Forgot_Password_Url] для URL восстановления пароля. [name], [fname], [lname] для полного имени, имени или фамилии пользователя. [email] для адреса электронной почты пользователя. [Site_Name] и [Site_URL] для имени приложения и его URL. ",
+ "Forgot_Password_Email": "Нажмите сюда для сброса вашего пароля.",
+ "Forgot_Password_Email_Subject": "[Site_Name] - восстановление пароля",
+ "Forgot_password_section": "Забыл пароль",
+ "Forward": "Отправить",
+ "Forward_chat": "Отправить чат",
+ "Forward_to_department": "Перейти к отделу",
+ "Forward_to_user": "Отправить пользователю",
"Frequently_Used": "Часто используемые",
+ "Friday": "Пятницу",
"From": "От",
- "From_Email": "Email отправителя",
- "From_email_warning": "Внимание : Поле От зависит от настроек вашего почтового сервера.",
+ "From_Email": "Адрес электронной почты отправителя",
+ "From_email_warning": "Внимание : Поле От зависит от настроек вашего почтового сервера.",
"General": "Общие настройки",
- "github_no_public_email": "В настройках GitHub отсутствует публично доступный email",
- "Give_a_unique_name_for_the_custom_oauth": "Задайте уникальное имя для пользовательского OAuth",
+ "github_no_public_email": "В вашей учетной записи GitHub отсутствует публично доступный адрес электронной почты",
+ "Give_a_unique_name_for_the_custom_oauth": "Задайте uniquie name OAuth",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Задайте приложению имя. Оно будет видно всем пользователям.",
"Global": "Общие",
- "GoogleTagManager_id": "Google Tag Manager Id",
+ "Google_Vision_usage_limit_exceeded": "Превышен лимит использования Google Vision",
+ "GoogleCloudStorage": "Google Cloud Storage",
+ "GoogleNaturalLanguage_ServiceAccount_Description": "Учетная запись ключа JSON файла. Больше информации можно найти здесь [here](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)",
+ "GoogleTagManager_id": "Идентификатор Google Tag Manager ",
+ "GoogleVision_Block_Adult_Images": "Блокировать изображения для взрослых",
+ "GoogleVision_Block_Adult_Images_Description": "Блокирование изображений для взрослых не будет работать, как только будет достигнут месячный лимит",
+ "GoogleVision_Current_Month_Calls": "Вызовов в текущем месяце",
+ "GoogleVision_Enable": "Включить Google Vision",
+ "GoogleVision_Max_Monthly_Calls": "Максимальное количество вызов в месяц",
+ "GoogleVision_Max_Monthly_Calls_Description": "Используйте 0 для безлимита",
+ "GoogleVision_ServiceAccount": "Учетная запись сервиса Google Vision",
+ "GoogleVision_ServiceAccount_Description": "Создайте серверный ключ (JSON формат) и вставьте данные JSON здесь",
+ "GoogleVision_Type_Document": "Определение и распознание текста",
+ "GoogleVision_Type_Faces": "Определение лиц",
+ "GoogleVision_Type_Labels": "Определение, что есть на изображении",
+ "GoogleVision_Type_Landmarks": "Определение достопримечательностей",
+ "GoogleVision_Type_Logos": "Определение логотипов",
+ "GoogleVision_Type_Properties": "Определение свойств (цвет)",
+ "GoogleVision_Type_SafeSearch": "Определение контента для взрослых",
+ "GoogleVision_Type_Similar": "Искать похожие изображения",
+ "Group_mentions_only": "Только при упоминаниях в общих чатах",
+ "Guest_Pool": "Очередь посетителей",
"Hash": "Хэш",
- "Header": "Заголовок",
+ "Header": "Шапка",
+ "Header_and_Footer": "Шапка и подвал",
+ "Helpers": "Хелперы",
+ "Hex_Color_Preview": "Превью для Hex-цветов",
"Hidden": "Скрытый",
"Hide_Avatars": "Спрятать аватары",
- "Hide_Group_Warning": "Вы уверены, что хотите спрятать групповой чат \"%s\"?",
+ "Hide_flextab": "Скрывать правую боковую панель по клику",
+ "Hide_Group_Warning": "Вы уверены, что хотите спрятать группу \"%s\"?",
+ "Hide_Livechat_Warning": "Вы уверены, что хотите спрятать Livechat с \"%s\"?",
"Hide_Private_Warning": "Вы уверены, что хотите спрятать беседу с \"%s\"?",
- "Hide_room": "Скрыть чат",
- "Hide_Room_Warning": "Вы уверены, что хотите спрятать чат \"%s\"?",
- "Hide_usernames": "Скрыть имена пользователей",
- "Highlights": "Отметка сообщений",
- "Highlights_How_To": "Чтобы получать уведомления, когда кто-то упоминает слово или фразу, добавьте её здесь. Вы можете разделять слова или фразы запятыми. Выбранные слова не чувствительны к регистру.",
+ "Hide_roles": "Скрывать роли пользователей",
+ "Hide_room": "Скрыть комнату",
+ "Hide_Room_Warning": "Вы уверены, что хотите спрятать комнату \"%s\"?",
+ "Hide_Unread_Room_Status": "Скрыть статус \"непрочитанно\" у комнаты",
+ "Hide_usernames": "Скрыть логины",
+ "Highlights": "Подсветка сообщений",
+ "Highlights_How_To": "Чтобы получать уведомления, когда кто-то упоминает слово или фразу, добавьте её здесь. Вы можете разделять слова или фразы запятыми. Слова не чувствительны к регистру.",
"Highlights_List": "Подсвечивать слова",
"History": "История",
"Host": "Хост",
- "hours": "час(ы)",
- "How_friendly_was_the_chat_agent": "Насколько дружелюбен был сотрудник чата?",
- "How_knowledgeable_was_the_chat_agent": "Насколько информирован был сотрудник чата?",
- "How_responsive_was_the_chat_agent": "Насколько отзывчив был сотрудник чата?",
+ "hours": "часы",
+ "Hours": "Часы",
+ "How_friendly_was_the_chat_agent": "Насколько дружелюбен был представитель?",
+ "How_knowledgeable_was_the_chat_agent": "Насколько информирован был представитель?",
+ "How_long_to_wait_after_agent_goes_offline": "Как долго ждать после того как отключился представитель",
+ "How_responsive_was_the_chat_agent": "Насколько отзывчив был представитель ?",
"How_satisfied_were_you_with_this_chat": "Насколько вы удовлетворены использованием этого чата?",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "Как долго держать сессию открытой после того как представитель отключился ",
+ "If_this_email_is_registered": "Если этот адрес электронной почты зарегистрирован, мы отправим на него инструкцию по сбросу пароля. Если вы не получили электронное сообщение, попробуйте снова позже.",
"If_you_are_sure_type_in_your_password": "Если вы уверены, введите пароль:",
- "If_you_are_sure_type_in_your_username": "Если вы уверены, введите имя:",
- "Importer_Archived": "Удаленные",
+ "If_you_are_sure_type_in_your_username": "Если вы уверены, введите ваш логин:",
+ "Iframe_Integration": "Интеграция Iframe ",
+ "Iframe_Integration_receive_enable": "Разрешить получение",
+ "Iframe_Integration_receive_enable_Description": "Разрешить основному окну отправлять команды в Rocket.Chat.",
+ "Iframe_Integration_send_enable": "Разрешить отправку",
+ "Iframe_Integration_send_enable_Description": "Отправлять события основному окну ",
+ "IMAP_intercepter_already_running": "Перехватчик IMAP уже запущен",
+ "IMAP_intercepter_Not_running": "Перехватчик IMAP не запущен",
+ "Impersonate_user": "Представляться пользователем",
+ "Impersonate_user_description": "Когда включено, инеграция отправляет сообщения от имени пользователя, который заставил интеграцию сработать",
+ "Import": "Импортировать",
+ "Importer_Archived": "Архивные",
+ "Importer_CSV_Information": "При импорте CSV требуется соблюдать определенный формат, пожалуйста, прочитайте документацию о том, каким должен быть zip архив:",
"Importer_done": "Импорт данных завершен!",
"Importer_finishing": "Завершить импорт данных.",
"Importer_From_Description": "Импортировать данные из __from__ в Rocket.Chat.",
+ "Importer_HipChatEnterprise_BetaWarning": "Имейте в виду, что импорт всё ещё продолжается. Пожалуйста, сообщите о любых возникающих ошибках на GitHub:",
+ "Importer_HipChatEnterprise_Information": "Загруженный файл должен быть расшифрованным tar.gz, пожалуйста, прочитайте документацию для получения дополнительной информации:",
"Importer_import_cancelled": "Импорт данных отменен.",
"Importer_import_failed": "Во время импорта данных возникла ошибка.",
"Importer_importing_channels": "Импортировать каналы.",
"Importer_importing_messages": "Импортировать сообщения.",
"Importer_importing_started": "Начать импорт данных.",
"Importer_importing_users": "Импортировать пользователей.",
- "Importer_not_in_progress": "Импортер на данный момент не в сети.",
+ "Importer_not_in_progress": "Импортер на данный момент не запущен.",
+ "Importer_not_setup": "Импортер настроен неправильно, так как он не возвращает никаких данных.",
"Importer_Prepare_Restart_Import": "Перезапустить импорт данных.",
"Importer_Prepare_Start_Import": "Начать импорт данных.",
- "Importer_Prepare_Uncheck_Archived_Channels": "Снимите флажок с удаленных каналов",
+ "Importer_Prepare_Uncheck_Archived_Channels": "Снимите флажок с архивных каналов",
"Importer_Prepare_Uncheck_Deleted_Users": "Снимите флажок с удаленных пользователей",
"Importer_progress_error": "Произошла ошибка при выполнении импорта данных.",
"Importer_setup_error": "При настройке импортера возникла ошибка.",
- "inline_code": "внутренний код",
+ "Importer_Source_File": "Выбор исходного файла",
+ "Incoming_Livechats": "Входящие Livechat",
+ "Incoming_WebHook": "Входящий webhook",
+ "initials_avatar": "Инициалы аватара",
+ "inline_code": "код",
"Install_Extension": "Установить расширение",
"Install_FxOs": "Установить Rocket.Chat на Firefox",
- "Install_FxOs_done": "Отлично! Теперь вы можете использовать Rocket.Chat через иконку на вашем рабочем столе. Развлекайтесь вместе с Rocket.Chat!",
+ "Install_FxOs_done": "Отлично! Теперь вы можете использовать Rocket.Chat через иконку на вашем рабочем столе. Развлекайтесь вместе с Rocket.Chat!",
"Install_FxOs_error": "Извините, что-то пошло не так! Появилась следующая ошибка:",
"Install_FxOs_follow_instructions": "Подтвердите установку приложения на ваше устройство (при запросе нажмите \"Установить\").",
"Installation": "Установка",
"Installed_at": "Установленно",
+ "Instance_Record": "Быстрая запись",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Инструкции для вашего посетителя заполнить форму, чтобы отправить сообщение",
"Integration_added": "Интеграция была добавлена",
+ "Integration_Advanced_Settings": "Дополнительные настройки",
+ "Integration_History_Cleared": "История интеграций успешно очищена",
"Integration_Incoming_WebHook": "Входящая интеграция WebHook",
"Integration_New": "Новая интеграция",
"Integration_Outgoing_WebHook": "Исходящая интеграция WebHook",
- "Integration_updated": "Интеграция была загружена",
+ "Integration_Outgoing_WebHook_History": "История исходящих webhook-интеграций",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_Trigger": "Данные, переданные в интеграцию",
+ "Integration_Outgoing_WebHook_History_Data_Passed_To_URL": "Данные, переданные по URL",
+ "Integration_Outgoing_WebHook_History_Error_Stacktrace": "Стек ошибки",
+ "Integration_Outgoing_WebHook_History_Http_Response": "HTTP ответ",
+ "Integration_Outgoing_WebHook_History_Http_Response_Error": "Ошибка ответа HTTP",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Prepare_Script": "Сообщения, отправленные с этапа подготовки",
+ "Integration_Outgoing_WebHook_History_Messages_Sent_From_Process_Script": "Сообщения, отправленные с этапа предоставления ответов",
+ "Integration_Outgoing_WebHook_History_Time_Ended_Or_Error": "Время завершения выполнения интеграции",
+ "Integration_Outgoing_WebHook_History_Time_Triggered": "Время срабатывания интеграции",
+ "Integration_Outgoing_WebHook_No_History": "Эта исходящая webhook-интеграция ещё не имеет записанной истории.",
+ "Integration_Retry_Count": "Число повторных попыток",
+ "Integration_Retry_Count_Description": "Сколько попыток вызова интеграции предпринять, если запрос к URL не удается?",
+ "Integration_Retry_Delay": "Задержка перед повторной попыткой",
+ "Integration_Retry_Delay_Description": "Какой алгоритм задержки перед повторной попыткой использовать? 10^x, 2^x или x*2",
+ "Integration_Retry_Failed_Url_Calls": "Повторный запрос по неудавшемуся URL",
+ "Integration_Retry_Failed_Url_Calls_Description": "Должна ли инеграция пытаться снова в течение небольшого промежутка времени, если вызов по URL неудачен?",
+ "Integration_Run_When_Message_Is_Edited": "Запускать после изменения",
+ "Integration_Run_When_Message_Is_Edited_Description": "Запускать ли интеграцию после редактирования сообщения? Если нет, то интеграция будет запущена только для новых сообщений.",
+ "Integration_updated": "Интеграция была обновлена",
+ "Integration_Word_Trigger_Placement": "Слово может быть где угодно",
+ "Integration_Word_Trigger_Placement_Description": "Может ли быть слово быть расположено где угодно в сообщении, а не только в начале?",
"Integrations": "Интеграции",
+ "Integrations_for_all_channels": "Введите all_public_channels для прослушивания всех публичных каналов, all_private_groups для прослушивания всех приватных групп, all_direct_messages для прослушивания всех личных сообщений.",
+ "Integrations_Outgoing_Type_FileUploaded": "Файл загружен",
+ "Integrations_Outgoing_Type_RoomArchived": "Комната архивирована",
+ "Integrations_Outgoing_Type_RoomCreated": "Создана комната (канал или приватный канал)",
+ "Integrations_Outgoing_Type_RoomJoined": "Пользователь присоединился к комнате",
+ "Integrations_Outgoing_Type_RoomLeft": "Пользователь покинул комнату",
+ "Integrations_Outgoing_Type_SendMessage": "Сообщение отправлено",
+ "Integrations_Outgoing_Type_UserCreated": "Пользователь создан",
"InternalHubot": "Внутренний Hubot",
- "InternalHubot_ScriptsToLoad": "Сценарии для загрузки",
- "InternalHubot_ScriptsToLoad_Description": "Пожалуйста, введите разделенный запятыми список скриптов для загрузки из https://github.com/github/hubot-scripts/tree/master/src/scripts",
- "InternalHubot_Username_Description": "Это должно быть действительным именем пользователя бота, зарегистрированный на сервере.",
+ "InternalHubot_PathToLoadCustomScripts": "Папка для загрузки скриптов",
+ "InternalHubot_reload": "Перезагрузить скрипты",
+ "InternalHubot_ScriptsToLoad": "Скрипты для загрузки",
+ "InternalHubot_ScriptsToLoad_Description": "Пожалуйста, введите разделенный запятыми список скриптов для загрузки из вашей папки. Скрипты можно скачать здесь: https://github.com/github/hubot-scripts/tree/master/src/scripts",
+ "InternalHubot_Username_Description": "Должно быть действительным логином бота, зарегистрированным на сервере.",
"Invalid_confirm_pass": "Пароли не совпадают",
- "Invalid_email": "Неверный email",
- "Invalid_Export_File": "Загруженный файл не является действительным экспортным файлом %s.",
+ "Invalid_email": "Введен некорректный адрес электронной почты",
+ "Invalid_Export_File": "Загруженный файл не является верным экспортным файлом %s.",
"Invalid_Import_File_Type": "Недействительный тип импортируемого файла.",
"Invalid_name": "Имя не может быть пустым",
"Invalid_notification_setting_s": "Неверная настройка уведомлений: %s",
"Invalid_pass": "Пароль не может быть пустым",
- "Invalid_room_name": "%s - недопустимое имя для чата, допустимые символы: цифры, подчеркивание и латинские буквы.",
+ "Invalid_room_name": "%s недопустимое имя комнаты",
"Invalid_secret_URL_message": "Предоставленный URL-адрес недействителен.",
+ "Invalid_setting_s": "Неправильная настройка: %s",
+ "Invalid_two_factor_code": "Неверный двухфакторный код",
"invisible": "невидимый",
"Invisible": "Невидимый",
+ "Invitation": "Приглашение",
"Invitation_HTML": "Приглашение в формате HTML",
- "Invitation_HTML_Default": "Вы были приглашены [Site_Name] Посетите [Site_URL] и опробуйте лучшее решение для чатов с открытым исходным кодом на сегодняшний день!
",
- "Invitation_HTML_Description": "Вы можете использовать следующие замены: [email] для электронной почты получателя. [Site_Name] и [Site_URL] для названия сайта и URL соответственно. ",
- "Invitation_Subject": "Предмет приглашения",
- "Invitation_Subject_Default": "Вы были приглашены [Site_Name]",
- "Invite_user_to_join_channel": "Пригласить пользователя присоединиться к этому публичному чату",
+ "Invitation_HTML_Default": "Вы были приглашены на [Site_Name] Посетите [Site_URL] и попробуйте лучшее решение с открытым исходным кодом для общения на сегодняшний день!
",
+ "Invitation_HTML_Description": "Вы можете использовать следующие подстановки: [email] для электронной почты получателя. [Site_Name] и [Site_URL] для названия приложения и его URL. ",
+ "Invitation_Subject": "Тема приглашения",
+ "Invitation_Subject_Default": "Вы были приглашены на [Site_Name]",
+ "Invite_user_to_join_channel": "Пригласить пользователя в канал",
+ "Invite_user_to_join_channel_all_from": "Пригласить всех пользователей из [#channel] присоединиться к этому каналу",
+ "Invite_user_to_join_channel_all_to": "Пригласить всех пользователей этого канала присоединиться к [#channel]",
"Invite_Users": "Пригласить пользователей",
+ "IRC_Channel_Join": "Вывод команды JOIN",
+ "IRC_Channel_Leave": "Вывод команды PART",
+ "IRC_Channel_Users": "Вывод команды NAMES",
+ "IRC_Channel_Users_End": "Конец вывода команды NAMES",
+ "IRC_Description": "Internet Relay Chat (IRC) - протокол прикладного уровня для обмена сообщениями в режиме реального времени. Пользователи присоединяются к уникальным каналам или комнатам для открытого обсуждения чего или кого угодно. IRC также позволяет обмениваться личными сообщениями и файлами. Данный пакет интегрирует эти возможности с Rocket.Chat.",
+ "IRC_Enabled": "Попытка интегрировать поддержку IRC. После изменения этого параметра потребуется перезапустить Rocket.Chat.",
+ "IRC_Hostname": "Сервер IRC для подключения.",
+ "IRC_Login_Fail": "Вывод при неудачном соединении с IRC-сервером.",
+ "IRC_Login_Success": "Вывод при успешном соединении с IRC-сервером.",
+ "IRC_Message_Cache_Size": "Ограничение кэша для обработки исходящих сообщений.",
+ "IRC_Port": "Порт для привязки к серверу IRC.",
+ "IRC_Private_Message": "Вывод команды PRIVMSG",
+ "IRC_Quit": "Вывод после закрытия сеанса IRC.",
"is_also_typing": "все ещё печатает",
"is_also_typing_female": "все ещё печатает",
"is_also_typing_male": "все ещё печатает",
"is_typing": "печатает",
"is_typing_female": "печатает",
"is_typing_male": "печатает",
+ "IssueLinks_Incompatible": "Внимание: не включайте это и \"Предварительный просмотр Hex цвета\" одновременно",
+ "IssueLinks_LinkTemplate_Description": "Шаблон для проблемных ссылок; %s будет заменена на номер проблемы.",
"It_works": "Оно работает",
"italics": "курсив",
- "Jitsi_Chrome_Extension": "Chrome Id Extension",
- "Jitsi_Enable_Channels": "Включение в каналах",
+ "Jitsi_Chrome_Extension": "Идентификатор расширения для Chrome ",
+ "Jitsi_Enable_Channels": "Включить на канале",
"join": "Присоединиться",
- "Join_audio_call": "Присоединиться к разговору",
- "Join_default_channels": "Отправить в канал по умолчанию",
+ "join-without-join-code": "Присоединяться к публичным чатам без кода входа",
+ "join-without-join-code_description": "Разрешение на обход кода входа для публичных чатов с включенным кодом входа",
+ "Join_audio_call": "Присоединиться к аудиозвонку",
+ "Join_Chat": "Присоединиться к чату",
+ "Join_default_channels": "Присоединить к публичным чатам по-умолчанию",
"Join_the_Community": "Присоединиться к сообществу",
- "Join_the_given_channel": "Присоединиться к этому публичному чату",
+ "Join_the_given_channel": "Присоединиться к этому каналу",
"Join_video_call": "Присоединиться к видеозвонку",
"Joined": "Участвую",
"Jump": "Перейти",
"Jump_to_first_unread": "Перейти к первому непрочитанному",
"Jump_to_message": "Перейти к сообщению",
"Jump_to_recent_messages": "Перейти к последнему сообщению",
+ "Just_invited_people_can_access_this_channel": "Только приглашенные люди имеют доступ к этому каналу",
"Katex_Dollar_Syntax": "Разрешить доллар Синтаксис",
- "Katex_Dollar_Syntax_Description": "Разрешить используя $$ Katex блок $$ и $ рядный Katex $ синтаксисом",
+ "Katex_Dollar_Syntax_Description": "Разрешить использование синтаксисов $$katex block$$ и $inline katex$ ",
"Katex_Enabled": "Katex включен",
- "Katex_Enabled_Description": "Разрешить используя Katex для верстки математики в сообщениях",
+ "Katex_Enabled_Description": "Разрешить использование Katex для отображения математических символов в сообщениях",
"Katex_Parenthesis_Syntax": "Разрешить Скобки Синтаксис",
- "Katex_Parenthesis_Syntax_Description": "Разрешить использование \\ [Katex блок \\] и \\ (встроенный Katex \\) синтаксисом",
+ "Katex_Parenthesis_Syntax_Description": "Разрешить использование синтаксисов \\[katex block\\] и \\(inline katex\\)",
+ "Keyboard_Shortcuts_Edit_Previous_Message": "Редактировать предыдущее сообщение",
+ "Keyboard_Shortcuts_Keys_1": "Ctrl >+p ",
+ "Keyboard_Shortcuts_Keys_2": "Клавиша ↑ ",
+ "Keyboard_Shortcuts_Keys_3": "Command (или Alt ) + клавиша ← ",
+ "Keyboard_Shortcuts_Keys_4": "Command (или Alt ) + клавиша ↑ ",
+ "Keyboard_Shortcuts_Keys_5": "Command (или Alt ) + клавиша → ",
+ "Keyboard_Shortcuts_Keys_6": "Command (или Alt ) + клавиша ↓ ",
+ "Keyboard_Shortcuts_Keys_7": "Shift + Enter ",
+ "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "Перейти в начало сообщения",
+ "Keyboard_Shortcuts_Move_To_End_Of_Message": "Перейти в конец сообщения",
+ "Keyboard_Shortcuts_New_Line_In_Message": "Ввод новой строки в сообщении",
+ "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Открыть канал / поиск пользователей",
+ "Keyboard_Shortcuts_Title": "Горячие клавиши",
"Knowledge_Base": "База знаний",
"Label": "Подпись",
"Language": "Язык",
- "Language_Version": "Русская версия",
- "Last_login": "Последний визит",
+ "Language_Version": "Английская версия",
+ "Last_login": "Последний раз заходил",
"Last_Message_At": "Последнее сообщение",
- "Last_seen": "Последняя активность",
- "Layout": "Макет",
+ "Last_seen": "Последний раз видели",
+ "Layout": "Внешний вид",
"Layout_Home_Body": "Контент на главной",
"Layout_Home_Title": "Название главной",
"Layout_Login_Terms": "Правила составления логина",
"Layout_Privacy_Policy": "Политика конфиденциальности",
- "Layout_Sidenav_Footer": "Футер навигационной панели",
- "Layout_Sidenav_Footer_description": "Размер футера 260 на 70 пикселей",
+ "Layout_Sidenav_Footer": "Колонтитул навигационной панели",
+ "Layout_Sidenav_Footer_description": "Размер колонтитула 260 на 70 пикселей",
"Layout_Terms_of_Service": "Условия использования",
"LDAP": "Протокол LDAP",
"LDAP_CA_Cert": "Сертификат CA",
- "LDAP_Custom_Domain_Search": "Пользовательский домен поиска",
- "LDAP_Custom_Domain_Search_Description": "Часть протокола JSON, которая регулирует привязку и подключение информации, имеет форму: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "Таймаут соединения (мсек)",
"LDAP_Default_Domain": "Домен по умолчанию",
- "LDAP_Description": "Протокол LDAP - это иерархическая база данных, которую используют многие компании для обеспечения единой регистрации - средство для совместного использования одного пароля для разных сайтов и сервисов. Для подробной информации по конфигурации читайте нашу wiki-страницу: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "Доменная база",
- "LDAP_Domain_Base_Description": "Полностью соответствующее Отличительное Имя (ОМ) поддерева протокола LDAP, которое вы хотите найти для пользователей и групп. Вы можете добавлять столько, сколько желаете; однако, каждая группа должна быть определена в одной и той же доменной базе, как и пользователи, относящиеся к ней. Если вы укажете ограниченные группы пользователей, в пределах этих групп будут лишь те пользователи, относящиеся к ним. Вы рекомендуем вам указать верхний уровень дерева каталогов LDAP в качестве доменной базы и использовать фильтр поиска для контроля доступа.",
- "LDAP_Domain_Search_Filter": "Фильтр доменного поиска",
- "LDAP_Domain_Search_Filter_Description": "Если определено, только пользователям, которые соответствуют этому фильтру, разрешат авторизоваться. Если никакой фильтр не будет определен, то все пользователи в рамках указанной доменной базы будут в состоянии регистрироваться. Например для Активной Директории `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Например для OpenLDAP (расширяемый соответствующий поиск) `ou:dn:=ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Категория объекта доменного поиска",
- "LDAP_Domain_Search_Object_Category_Description": "*objectCategory* определяет ваших пользователей. Оставить пустым для *OpenLDAP*. Например `person`, и так далее.",
- "LDAP_Domain_Search_Object_Class": "Класс объекта доменного поиска",
- "LDAP_Domain_Search_Object_Class_Description": "*objectclass* определяет ваших пользователей. Например `organizationalPerson`, `user`, `inetOrgPerson`, и так далее.",
- "LDAP_Domain_Search_Password": "Пароль к доменному поиску",
- "LDAP_Domain_Search_Password_Description": "Пароль для пользователя доменного поиска",
- "LDAP_Domain_Search_User": "Пользователь доменного поиска",
- "LDAP_Domain_Search_User_Description": "Пользователь LDAP, который выполняет пользовательские поиски, чтобы подтвердить подлинность других пользователей, когда они регистрируются. Это, как правило - сервисный аккаунт, созданный определенно для сторонней интеграции. Используйте полностью составное имя, например `cn=Administrator,cn=Users,dc=Example,dc=com`.",
- "LDAP_Domain_Search_User_ID": "Идентификатор пользователя доменного поиска",
- "LDAP_Domain_Search_User_ID_Description": "Признак LDAP, который опознает пользователя LDAP, делающего попытку идентификации. Эта область должна быть `sAMAccountName` для большинства Активных Директивных установок, но она может быть `uid` для других LDAP решений, таких как OpenLDAP. Вы можете использовать `mail` для указания пользователей по электронной почте или любой признак, какой пожелаете. Вы можете использовать несколько значений, разделенных запятой, чтобы разрешить пользователям войти, используя множественные идентификаторы, такие как имя пользователя или электронная почта.",
+ "LDAP_Description": "Протокол LDAP - это иерархическая база данных, которую используют многие компании для обеспечения единой регистрации - средство для совместного использования одного пароля для разных сайтов и сервисов. Для подробной информации по конфигурации читайте нашу wiki-страницу: https://rocket.chat/docs/administrator-guides/authentication/ldap/ ",
+ "LDAP_BaseDN": "Base DN",
+ "LDAP_BaseDN_Description": "Полностью соответствующее Отличительное Имя (ОМ) поддерева протокола LDAP, которое вы хотите найти для пользователей и групп. Вы можете добавлять столько, сколько желаете; однако, каждая группа должна быть определена в одной и той же доменной базе, как и пользователи, относящиеся к ней. Если вы укажете ограниченные группы пользователей, в пределах этих групп будут лишь те пользователи, относящиеся к ним. Вы рекомендуем вам указать верхний уровень дерева каталогов LDAP в качестве доменной базы и использовать фильтр поиска для контроля доступа.",
+ "LDAP_User_Search_Field": "Поле поиска",
+ "LDAP_User_Search_Field_Description": "Атрибут LDAP, который идентифицирует пользователя LDAP, делающего попытку аутентификации. Это поле должно иметь значение `sAMAccountName` для большинства установок Active Directory, но она может иметь значение `uid` для других LDAP решений, таких как OpenLDAP. Вы можете использовать `mail` для указания пользователей по электронной почте или любой атрибут, какой пожелаете. Вы можете использовать несколько значений, разделенных запятой, чтобы разрешить пользователям войти, используя множественные идентификаторы, такие как имя пользователя или электронная почта.",
+ "LDAP_User_Search_Filter": "Фильтр",
+ "LDAP_User_Search_Filter_Description": "Если определено, только пользователям, которые соответствуют этому фильтру, разрешено авторизовываться. Если никакой фильтр не будет определен, то все пользователи в рамках указанной доменной базы будут в состоянии регистрироваться. Например для Активной Директории `memberOf=cn=ROCKET_CHAT,ou=General Groups`. Например: для OpenLDAP (расширяемый соответствующий поиск) `ou:dn:=ROCKET_CHAT`.",
+ "LDAP_User_Search_Scope": "Область",
+ "LDAP_Authentication": "Включить",
+ "LDAP_Authentication_Password": "Пароль",
+ "LDAP_Authentication_UserDN": "User DN",
+ "LDAP_Authentication_UserDN_Description": "Пользователь LDAP, который выполняет пользовательские поиски, чтобы подтвердить подлинность других пользователей, когда они регистрируются. Это, как правило - сервисный аккаунт, созданный определенно для сторонней интеграции. Используйте полностью составное имя, например `cn=Administrator,cn=Users,dc=Example,dc=com`.",
"LDAP_Enable": "Включить LDAP",
"LDAP_Enable_Description": "Попытка использовать LDAP для аутентификации.",
"LDAP_Encryption": "Шифрование",
- "LDAP_Encryption_Description": "Метод шифрования раньше обеспечивал безопасность коммуникаций с сервером LDAP. Примеры содержат `plain` (без шифрования), `SSL/LDAPS`(зашифрованный с начала), а также `StartTLS`(модернизируйте до зашифрованной коммуникации после подключения).",
+ "LDAP_Encryption_Description": "Метод шифрования раньше обеспечивал безопасность коммуникаций с сервером LDAP. Примеры содержат `plain` (без шифрования), `SSL/LDAPS`(зашифрованный с начала), а также `StartTLS`(модернизируйте до зашифрованной коммуникации после подключения).",
+ "LDAP_Internal_Log_Level": "Уровень внутреннего логирования",
+ "LDAP_Group_Filter_Enable": "Включить фильтр групп пользователей LDAP",
+ "LDAP_Group_Filter_Group_Id_Attribute": "Атрибуты Group ID",
+ "LDAP_Group_Filter_Group_Id_Attribute_Description": "Например: *OpenLDAP:*cn",
+ "LDAP_Group_Filter_Group_Member_Attribute_Description": "Например: *OpenLDAP:*uniqueMember",
+ "LDAP_Group_Filter_Group_Member_Format_Description": "Например, *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+ "LDAP_Group_Filter_Group_Name": "Имя группы",
+ "LDAP_Group_Filter_Group_Name_Description": "Имя группы, к которой принадлежит пользователь",
+ "LDAP_Group_Filter_ObjectClass_Description": "*Objectclass*, идентифицирует группы. Например: OpenLDAP: groupOfUniqueNames",
"LDAP_Host": "Хост",
- "LDAP_Host_Description": "Хост LDAP, например `ldap.example.com` или `10.0.0.30`.",
+ "LDAP_Host_Description": "Хост LDAP, например `ldap.example.com` или `10.0.0.30`.",
+ "LDAP_Idle_Timeout": "Таймаут бездействия (мсек)",
+ "LDAP_Idle_Timeout_Description": "Сколько миллисекунд ждать после последней операции LDAP до закрытия соединения (каждая операция открывает новое соединение)",
+ "LDAP_Import_Users_Description": "Если включно, то процесс синхронизации будет импортировать всех пользователей LDAP *Внимание!* Укажите фильтр поиска, чтобы не импортировать лишних пользователей.",
+ "LDAP_Login_Fallback": "Резервная авторизация",
+ "LDAP_Login_Fallback_Description": "Если подключение к сервису LDAP не удалось, то попробовать войти в локальную/по умолчанию систему локальных учетных записей. Может помочь, когда сервис LDAP по каким-то причинам не работает.",
+ "LDAP_Merge_Existing_Users": "Объединить существующих пользователей",
+ "LDAP_Merge_Existing_Users_Description": "*Внимание!* При импорте пользователя из LDAP, если пользователь с таким логином уже существует, данные из LDAP и пароль будут установлены уже существующему пользователю.",
"LDAP_Port": "LDAP порт",
- "LDAP_Port_Description": "Порт для доступа LDAP. Пример: `389` или `636` для LDAPS",
- "LDAP_Reject_Unauthorized": "Отклонить запрещённых",
+ "LDAP_Port_Description": "Порт для доступа LDAP. Пример: `389` или `636` для LDAPS",
+ "LDAP_Reconnect": "Переподключение",
+ "LDAP_Reconnect_Description": "Пробовать переподключаться автоматически, когда соединение прервано по каким-то причинам во время выполнения операций",
+ "LDAP_Reject_Unauthorized": "Отклонить неавторизованных",
+ "LDAP_Reject_Unauthorized_Description": "Отключите эту опцию, чтобы разрешить сертификаты, которые не могут быть проверены. Обычно для работы с самоподписанными сертификатами требуется отключение это опции",
"LDAP_Sync_User_Avatar": "Синхронизация пользовательских аватаров",
- "LDAP_Sync_User_Data": "Синхронизация данных",
- "LDAP_Sync_User_Data_Description": "Хранить пользовательские данные в синхронизации с сервером на логине (например: имя, электронная почта).",
+ "LDAP_Sync_Now": "Запуск фоновой синхронизации",
+ "LDAP_Sync_Now_Description": "Выполнить **Фоновую синхронизацию** сейчас, не дожидаясь **Интервала синхронизации**, даже если **Фоновая синхронизация** отключена. Действие выполняется асинхронно, см. журналы для получения дополнительной информации о процессе",
+ "LDAP_Background_Sync": "Фоновая синхронизация",
+ "LDAP_Background_Sync_Interval": "Интервал фоновой синхронизации",
+ "LDAP_Background_Sync_Interval_Description": "Интервал между синхронизациями. Пример: `каждые 24 часа` или `в первый день недели`, больше примеров в [Cron Text Parser] (http://bunkat.github.io/later/parsers.html#text)",
+ "LDAP_Background_Sync_Import_New_Users": "Фоновая синхронизация импортирует новых пользователей",
+ "LDAP_Background_Sync_Import_New_Users_Description": "Импортирует всех пользователей (на основе критериев вашего фильтра), которые существуют в LDAP, и не существует в Rocket.Chat",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated": "Фоновая синхронизация обновляет сущестующих пользователей",
+ "LDAP_Background_Sync_Keep_Existant_Users_Updated_Description": "Будут синхронизироваться аватар, поля, логин итд (на основе вашей конфигурации) всех пользователей уже импортированных из LDAP каждый **Интервал синхронизации**",
+ "LDAP_Sync_User_Data": "Синхронизация пользовательских данных",
+ "LDAP_Sync_User_Data_Description": "Синхронизировать пользовательские данные с сервером при входе (например: имя, адрес электронной почты).",
"LDAP_Sync_User_Data_FieldMap": "Карта пользовательских данных",
- "LDAP_Sync_User_Data_FieldMap_Description": "Настраивайте то, как будут заполняться поля аккаунта пользователя (email) из записи в LDAP (как только будет найден). Например, при настройке `{\"cn\":\"name\", \"mail\":\"email\"}` имя человека будет выбираться из параметра \"cn\", а email – из параметра \"mail\". Доступны поля `name` и `email`.",
- "LDAP_Sync_Users": "Синхронизация пользователей",
+ "LDAP_Sync_User_Data_FieldMap_Description": "Настраивайте то, как будут заполняться поля аккаунта пользователя (такие как адрес электронной почты) из записи в LDAP (как только будет найден). Например `{\"cn\":\"name\", \"mail\":\"email\"}` выберет человекочитаемое имя человека из атрибута \"cn\", и его адрес электронной почты – из атрибута \"mail\". Дополнительно возможно использовать переменные, например: `{ \"#{givenName} #{sn}\": \"name\", \"mail\": \"email\" }` использует комбинацию имени и фамилии пользователя для поля `name` в Rocket.Chat. В Rocket.Chat доступны поля `name` и `email`.",
+ "LDAP_Search_Page_Size": "Размер страницы поиска",
+ "LDAP_Search_Page_Size_Description": "Максимальное количество записей, которое отображается на странице",
+ "LDAP_Search_Size_Limit": "Ограничение размера поиска",
+ "LDAP_Search_Size_Limit_Description": "Максимальное количество записей, которое отображается на странице **Внимание**! Число должно быть больше, чем число, указанное в **Размер страницы поиска**",
"LDAP_Test_Connection": "Протестировать соединение",
+ "LDAP_Timeout": "Тайм-аут (мс)",
+ "LDAP_Timeout_Description": "Сколько миллисекунд ждать результата поиска, прежде чем вернуть ошибку",
"LDAP_Unique_Identifier_Field": "Поле уникального идентификатора",
- "LDAP_Unique_Identifier_Field_Description": "Какая область будет использоваться, чтобы связать пользователя LDAP и Rocket.Chat. Вы можете сообщать многократные значения, отделенные запятой, чтобы попытаться получить значение из отчета LDAP. Значение по умолчанию `objectGUID, ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Использовать пользовательский домен поиска",
- "LDAP_Use_Custom_Domain_Search_Description": "Напишите свой собственный фильтр, чтобы искать пользователей в сервере LDAP.",
- "LDAP_Username_Field": "Поле \"Имя пользователя\"",
- "LDAP_Username_Field_Description": "Какая область будет использоваться в качестве *username* для новых пользователей. Оставьте поле пустым, чтобы использовать имя пользователя, имеющееся на странице входа. Вы также можете использовать теги шаблонов, как `#{givenName}.#{sn}`. Значение по умолчанию `sAMAccountName`.",
- "Leave_Group_Warning": "Вы уверены, что хотите покинуть групповой чат \"%s\"?",
+ "LDAP_Unique_Identifier_Field_Description": "Какая поле будет использоваться, чтобы связать пользователя LDAP и Rocket.Chat. Вы можете указать несколько значений, отделенные запятой, чтобы попытаться получить значение из записей LDAP. Значение по умолчанию `objectGUID, ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
+ "LDAP_Username_Field": "Поле \"Логин\"",
+ "LDAP_Username_Field_Description": "Какое поле будет устанавливаться в качестве логина для новых пользователей. Оставьте поле пустым, чтобы использовать логин, введенный на странице входа. Вы также можете использовать теги шаблонов, например `#{givenName}.#{sn}`. Значение по умолчанию - `sAMAccountName`.",
+ "Execute_Synchronization_Now": "Выполнить синхронизацию сейчас",
+ "Least_Amount": "Наименьшее количество",
+ "Leave_Group_Warning": "Вы уверены, что хотите покинуть группу \"%s\"?",
+ "Leave_Livechat_Warning": "Вы уверены, что хотите покинуть Livechat с \"%s\"?",
"Leave_Private_Warning": "Вы уверены, что хотите покинуть беседу с \"%s\"?",
- "Leave_room": "Покинуть чат",
- "Leave_Room_Warning": "Вы уверены, что хотите покинуть чат \"%s\"?",
- "line": "линия",
- "List_of_Channels": "Список каналов",
- "List_of_Direct_Messages": "Список личных сообщений",
- "Livechat_agents": "Сотрудники Livechat",
- "Livechat_Dashboard": "Информационная панель Livechat",
+ "Leave_room": "Покинуть комнату",
+ "Leave_Room_Warning": "Вы уверены, что хотите покинуть комнату \"%s\"?",
+ "Leave_the_current_channel": "Покинуть текущий канал",
+ "line": "строк",
+ "List_of_Channels": "Список чатов",
+ "List_of_Direct_Messages": "Список личных переписок",
+ "Livechat_agents": "Представители Livechat",
+ "Livechat_AllowedDomainsList": "Разрешенные домены Livechat",
+ "Livechat_Dashboard": "Информационная панель Livechat",
"Livechat_enabled": "Livechat включен",
- "Livechat_forward_open_chats": "Форвард открытых чатов",
+ "Livechat_forward_open_chats": "Форвард открытых каналов",
"Livechat_forward_open_chats_timeout": "Тайм-аут (в секундах) для пересылки чатов",
- "Livechat_guest_count": "Гостевой счетчик",
+ "Livechat_guest_count": "Счетчик гостей",
"Livechat_managers": "Менеджеры Livechat",
- "Livechat_offline": "Livechat форума",
- "Livechat_online": "Livechat онлайн",
+ "Livechat_offline": "Livechat выключен",
+ "Livechat_online": "Livechat работает",
+ "Livechat_open_inquiery_show_connecting": "Показывать сообщение вместо окна ввода, когда к чату посетителя еще не подключился представитель.",
+ "Livechat_Queue": "Очередь Livechat",
"Livechat_room_count": "Количество комнат Livechat",
- "Livechat_title": "Название чата",
+ "Livechat_Routing_Method": "Livechat Routing Method",
+ "Livechat_Take_Confirm": "Вы хотите взять этого клиента?",
+ "Livechat_title": "Название Livechat",
"Livechat_title_color": "Цвет фона заголовка Livechat",
- "Livechat_Users": "Пользователи Livechat",
+ "Livechat_Users": "Пользователи Livechat",
"Load_more": "Загрузить еще",
"Loading...": "Загрузка...",
"Loading_more_from_history": "Идёт загрузка из истории",
- "Loading_suggestion": "Загрузка предпочтений...",
+ "Loading_suggestion": "Загрузка предпочтений",
"Localization": "Язык",
- "Log_File": "Показать файл и строки",
+ "Log_Exceptions_to_Channel": "Логировать исключения на канале",
+ "Log_Exceptions_to_Channel_Description": "Канал, который получит все захваченные исключения. Оставьте пустым, чтобы игнорировать исключения.",
+ "Log_File": "Отображать файл и строки",
"Log_Level": "Уровень логирования ",
- "Log_Package": "Показать комплект",
- "Log_View_Limit": "Максимум строк в логе",
+ "Log_Package": "Отображать сборку",
+ "Log_View_Limit": "Лимит строк",
"Logged_out_of_other_clients_successfully": "Сеансы в других клиентах успешно завершены",
- "Login": "Войти",
+ "Login": "Авторизация",
"Login_with": "Авторизация через %s",
"Logout": "Выйти",
"Logout_Others": "Выйти со всех устройств",
- "Mail_Message_Invalid_emails": "Вы предоставили один или более недействительных адресов электронной почты: %s",
+ "mail-messages": "Посылать электронные сообщения",
+ "mail-messages_description": "Разрешение на использование функции отправки электронных сообщений",
+ "Mail_Message_Invalid_emails": "Вы предоставили один или более недействительных адресов электронной почты: %s",
"Mail_Message_Missing_to": "Вы должны выбрать одного или нескольких пользователей или указать один или несколько адресов электронной почты, разделенных запятыми.",
- "Mail_Message_No_messages_selected_select_all": "Вы не выбрали ни одного сообщения. Хотели бы вы сделать select all сообщения видимыми?",
- "Mail_Messages": "Отправить сообщения на email",
+ "Mail_Message_No_messages_selected_select_all": "Вы не выбрали ни одного сообщения. Хотели бы вы выбрать все видимые сообщения?",
+ "Mail_Messages": "Почтовые сообщения",
"Mail_Messages_Instructions": "Нажимая на сообщения, выберите, какие из них вы хотите отправить по электронной почте",
- "Mail_Messages_Subject": "Это выделенная часть из %s сообщений.",
- "Mailer": "Отправка Email",
- "Mailer_body_tags": "Для того, чтобы отписаться, вам необходимо перейти [unsubscribe]. Вы можете использовать [name], [fname] и [lname] в качестве полного имени пользователя. Вы можете использовать [email] в качестве электронной почты пользователя.",
- "Mailing": "Почтовое отправление",
+ "Mail_Messages_Subject": "Это выделенная часть из %s сообщений",
+ "Mailer": "Mailer",
+ "Mailer_body_tags": "Вам необходимо использовать [unsubscribe] как ссылку для отписки. Вы можете использовать [name], [fname] и [lname] в качестве полного имени пользователя, имени или фамилии. Вы можете использовать [email] для адреса электронной почты пользователя.",
+ "Mailing": "Рассылка",
"Make_Admin": "Сделать администратором",
+ "manage-assets": "Управлять ресурсами",
+ "manage-assets_description": "Разрешение на управление ресурсами сервера",
+ "manage-emoji": "Управлять смайлами",
+ "manage-emoji_description": "Разрешение на управление смайлами сервера",
+ "manage-integrations": "Управлять интеграциями",
+ "manage-integrations_description": "Разрешение на управление интеграциями сервера",
+ "manage-oauth-apps": "Управлять приложениями OAuth",
+ "manage-oauth-apps_description": "Разрешение на управление приложениями OAuth",
+ "manage-own-integrations": "Создавать свои интеграции",
+ "manage-own-integrations_description": "Возможность разрешения создавать и редактировать свои интеграции и webhook'и",
+ "manage-sounds": "Управлять звуками",
+ "manage-sounds_description": "Разрешение на управление звуками сервера",
"Manager_added": "Менеджер добавлен",
"Manager_removed": "Менеджер удален",
"Managing_assets": "Управление активами",
"Managing_integrations": "Управление интеграций",
- "Mark_as_read": "Пометить как \"прочитанное\"",
- "Markdown_Headers": "Пометить заголовки",
+ "MapView_Enabled": "Включить просмотр карты",
+ "MapView_Enabled_Description": "Включение просмотра карта будет отображать кнопку поделиться местоположением в левой части поля ввода чата.",
+ "MapView_GMapsAPIKey": "Ключ Google Static Map API",
+ "Mark_as_read": "Пометить как прочитанное",
+ "Mark_as_unread": "Пометить как непрочитанное",
+ "Markdown_Headers": "Разрешить заголовки Markdown в сообщениях",
+ "Markdown_Parser": "Парсер Markdown",
"Markdown_SupportSchemesForLink": "Поддерживать Markdown систему ссылок",
"Markdown_SupportSchemesForLink_Description": "Разрешённые Markdown системы через запятую",
+ "Max_length_is": "Максимальная длина %s",
"Members_List": "Пользователи",
+ "mention-all": "Упоминать всех",
+ "mention-all_description": "Разрешение на использование упоминания @all",
"Mentions": "Упоминания",
"Mentions_default": "Упоминания (по умолчанию)",
+ "Mentions_only": "Только упоминания",
"Message": "Сообщение",
- "Message_AllowBadWordsFilter": "Разрешить Сообщение плохих слов фильтрации",
+ "Message_AllowBadWordsFilter": "Разрешить фильтрацию плохих слов в сообщениях",
"Message_AllowDeleting": "Разрешить удаление сообщений",
"Message_AllowDeleting_BlockDeleteInMinutes": "Запретить удаление сообщений через (n) минут",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Введите 0, чтобы отключить запрет.",
+ "Message_AllowDirectMessagesToYourself": "Разрешить пользователю вести переписку с самим собой",
"Message_AllowEditing": "Разрешить редактирование сообщений",
"Message_AllowEditing_BlockEditInMinutes": "Запретить редактирование сообщений через (n) минут",
"Message_AllowEditing_BlockEditInMinutesDescription": "Введите 0, чтобы отключить блокировку.",
"Message_AllowPinning": "Разрешить прикреплять сообщения",
"Message_AllowPinning_Description": "Разрешить прикреплять сообщения к любому из каналов",
+ "Message_AllowSnippeting": "Разрешить сниппеты в сообщениях",
"Message_AllowStarring": "Разрешить отмечать сообщения",
- "Message_AlwaysSearchRegExp": "Всегда искать с помощью RegExp",
- "Message_AlwaysSearchRegExp_Description": "Мы рекомендуем установить `true` если ваш язык не поддерживается в текстовом поиске MongoDB .",
+ "Message_AllowUnrecognizedSlashCommand": "Разрешить нераспознанные слэш команды",
+ "Message_AlwaysSearchRegExp": "Всегда искать с помощью регулярного выражения",
+ "Message_AlwaysSearchRegExp_Description": "Мы рекомендуем установить `Включено`, если текстовый поиск в MongoDB не поддерживает ваш язык.",
"Message_AudioRecorderEnabled": "Активировать запись аудио",
"Message_AudioRecorderEnabledDescription": "Необходимо подтвердить принятие 'audio/wav' файлов в настройках \"Загрузка файла\".",
"Message_BadWordsFilterList": "Добавить плохие слова в черный список",
- "Message_BadWordsFilterListDescription": "Добавить список разделенных запятыми список плохих слов, чтобы фильтровать",
+ "Message_BadWordsFilterListDescription": "Добавить список плохих слов, разделенный запятыми, для фильтрации",
"Message_DateFormat": "Формат даты",
"Message_DateFormat_Description": "Смотрите также: Moment.js ",
- "Message_deleting_blocked": "Это сообщение больше не может быть удалено",
- "Message_editing": "редактирование сообщений",
+ "Message_deleting_blocked": "Это сообщение уже не может быть удалено",
+ "Message_editing": "Редактирование сообщений",
"Message_GroupingPeriod": "Период объединения (в секундах)",
- "Message_GroupingPeriodDescription": "Сообщения будут сгруппированы вместе с предыдущим сообщением, если они оба от одного пользователя и затраченное время было меньше, чем установленное в секундах.",
- "Message_KeepHistory": "Хранить историю сообщений",
- "Message_MaxAll": "Максимальный размер канала для сообщения ALL",
+ "Message_GroupingPeriodDescription": "Сообщения будут сгруппированы вместе с предыдущим сообщением, если они оба от одного пользователя и прошедшее время было меньше, чем установленное.",
+ "Message_HideType_au": "Не показывать сообщение \"Пользователь присоединился\"",
+ "Message_HideType_mute_unmute": "Не показывать сообщение \"Пользователь заглушен / не заглушен\"",
+ "Message_HideType_ru": "Не показывать сообщение \"Пользователь удалён\"",
+ "Message_HideType_uj": "Не показывать сообщение \"Пользователь присоединился к чату\"",
+ "Message_HideType_ul": "Не показывать сообщение \"Пользователь покинул чат\"",
+ "Message_KeepHistory": "Сохранять историю редактирования сообщений",
+ "Message_MaxAll": "Максимальный размер чата для сообщения с упоминанием всех.",
"Message_MaxAllowedSize": "Максимально допустимый размер сообщения",
"Message_pinning": "Закрепление сообщений",
+ "Message_QuoteChainLimit": "Максимальная вложенность цитат",
"Message_removed": "Сообщение удалено",
+ "Message_sent_by_email": "Сообщение отправлено по электронной почте",
+ "Message_SetNameToAliasEnabled": "Установить имя пользователя в качестве псевдонима в сообщении",
+ "Message_SetNameToAliasEnabled_Description": "Только если не установлен псевдоним. Псевдоним в старых сообщениях не изменится, если пользователь изменит имя.",
"Message_ShowDeletedStatus": "Отображать статус \"Удалено\"",
"Message_ShowEditedStatus": "Отображать статус \"Отредактировано\"",
"Message_ShowFormattingTips": "Показывать советы по форматированию",
- "Message_starring": "Сообщение в главной роли",
+ "Message_starring": "Помеченное сообщение",
+ "Message_TimeAndDateFormat": "Формат даты и времени",
+ "Message_TimeAndDateFormat_Description": "Подробнее в: Moment.js ",
"Message_TimeFormat": "Формат времени",
"Message_TimeFormat_Description": "Смотрите также: Moment.js ",
"Message_too_long": "Сообщение слишком длинное",
"Message_VideoRecorderEnabled": "Запись видео включена",
+ "Message_VideoRecorderEnabledDescription": "Тип файлов 'video/webm' должен быть в списке разрешенных к передаче файлов в разделе настроек \"загрузка файлов\"",
"Messages": "Сообщения",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Сообщения, отосланные на Входящие WebHook, будут публиковаться здесь.",
"Meta": "Мета",
- "Meta_fb_app_id": "Facebook App Id",
- "Meta_google-site-verification": "Google Site Verification",
+ "Meta_custom": "Пользовательские мета-теги",
+ "Meta_fb_app_id": "Идентификатор Facebook App",
+ "Meta_google-site-verification": "Проверка Google Site",
"Meta_language": "Язык",
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Боты",
- "minutes": "минут(ы)",
- "More_channels": "Другие чаты",
+ "Min_length_is": "Минимальная длина составляет %s",
+ "minutes": "минуты",
+ "Mobile": "Мобильные устройства",
+ "Mobile_Notifications_Default_Alert": "Уведомления на мобильных устройствах",
+ "Monday": "Понедельник",
+ "Monitor_history_for_changes_on": "Отслеживать историю на изменение в",
+ "More_channels": "Другие каналы",
"More_direct_messages": "Больше личных сообщений",
- "More_groups": "Больше приватных чатов",
+ "More_groups": "Больше приватных групп",
"More_unreads": "Еще \"непрочитанные\"",
+ "Move_beginning_message": "'%s' - перейти к началу сообщения",
+ "Move_end_message": "'%s' - перейти в конец сообщения",
"Msgs": "Сообщения",
- "multi": "много",
- "Mute_someone_in_room": "Заблокировать кого-нибудь в чате",
- "Mute_user": "Заблокировать пользователя",
- "Muted": "Заблокировано",
- "My_Account": "Мой аккаунт",
+ "multi": "несколько",
+ "multi_line": "несколько строк",
+ "mute-user": "Заглушить пользователя",
+ "mute-user_description": "Разрешение на заглушение других пользователей в этом же канале",
+ "Mute_someone_in_room": "Заглушить кого-нибудь в комнате",
+ "Mute_user": "Заглушить",
+ "Muted": "Заглушен",
+ "My_Account": "Моя учетная запись",
+ "My_location": "Моё местонахождение",
"n_messages": "%s сообщений",
"N_new_messages": "%s новых сообщений",
"Name": "Имя",
"Name_cant_be_empty": "Имя не может быть пустым",
- "Name_of_agent": "Имя сотрудника",
- "Name_optional": "Имя (необязательно)",
+ "Name_of_agent": "Имя представителя",
+ "Name_optional": "Имя (опционально)",
+ "Name_Placeholder": "Пожалуйста, введите ваше имя...",
"Navigation_History": "История навигации",
- "New_Application": "Новое приложение",
+ "New_Application": "Новое приложение",
"New_Custom_Field": "Новое пользовательское поле",
- "New_Department": "Новый раздел",
+ "New_Department": "Новый отдел",
"New_integration": "Новая интеграция",
- "New_logs": "Новые регистрации",
+ "New_line_message_compose_input": "\"%s\" - добавить новую строку в сообщение",
+ "New_logs": "Новые логи",
"New_Message_Notification": "Уведомление о новом сообщении",
"New_messages": "Новые сообщения",
"New_password": "Новый пароль",
+ "New_Password_Placeholder": "Пожалуйста, введите новый пароль...",
"New_role": "Новая роль",
- "New_Room_Notification": "Уведомление о новом канале",
- "No_channel_with_name_%s_was_found": "Чат с названием \"%s\" не найден!",
- "No_channels_yet": "Вы не состоите в публичных чатах.",
- "No_direct_messages_yet": "Можно писать пользователям приватные сообщения.",
+ "New_Room_Notification": "Уведомление о новой публичной комнате",
+ "New_Trigger": "Новый триггер",
+ "New_videocall_request": "Новый запрос на видео-звонок",
+ "No_available_agents_to_transfer": "Нет доступных сотрудников для передачи",
+ "No_channel_with_name_%s_was_found": "Канал с названием \"%s\" не найден!",
+ "No_channels_yet": "Вы пока не участвуете ни в одном канале.",
+ "No_direct_messages_yet": "Нет личных переписок.",
"No_Encryption": "Без шифрования",
- "No_group_with_name_%s_was_found": "Приватный чат с названием \"%s\" не найден!",
- "No_groups_yet": "Вы не состоите ни в одном приватном чате.",
- "No_livechats": "У вас нет livechats.",
+ "No_group_with_name_%s_was_found": "Приватный канал с названием \"%s\" не найден!",
+ "No_groups_yet": "Вы не состоите ни в одной приватной группе.",
+ "No_integration_found": "Не найдена интеграция, соответствующая идентификатору",
+ "No_livechats": "У вас нет livechats",
"No_mentions_found": "Упоминания не найдены",
"No_pinned_messages": "Нет прикрепленных сообщений",
- "No_results_found": "Результатов не найдено",
+ "No_results_found": "Ничего не найдено",
+ "No_snippet_messages": "Нет сниппетов",
"No_starred_messages": "Нет отмеченных сообщений",
- "No_user_with_username_%s_was_found": "Пользователь с логином \"%s\" не найден!",
- "Node_version": "Node версия",
- "Not_authorized": "Запрещено",
+ "No_such_command": "Несуществующая команда: \"__command__\"",
+ "No_user_with_username_%s_was_found": "Пользователь с логином \"%s\" не найден!",
+ "Nobody_available": "Никто не доступен",
+ "Node_version": "Версия Node",
+ "None": "Отсутствует",
+ "Normal": "Обычный",
+ "Not_authorized": "Не авторизован",
"Not_Available": "Не доступен",
- "Not_found_or_not_allowed": "Чат не существует или владелец ограничил доступ",
- "Nothing": "Пусто",
+ "Not_found_or_not_allowed": "Не найден или владелец ограничил доступ",
+ "Nothing": "Ничего",
"Nothing_found": "Ничего не найдено",
+ "Notification_Desktop_Default_For": "Отображать уведомления для",
+ "Notification_Duration": "Длительность показа уведомления",
+ "Notification_Mobile_Default_For": "Включить push для",
"Notifications": "Уведомления",
- "Notify_all_in_this_room": "Уведомить всех в данном чате",
- "Num_Agents": "# Сотрудники",
+ "Notifications_Max_Room_Members": "Максимальное количество участников комнаты до отключения всех текстовых уведомлений",
+ "Notifications_Max_Room_Members_Description": "Максимальное количество участников в комнате, превышение которого отключает все уведомления. Участники в индивидуальном порядке по-прежнему могут изменять настройки комнаты, чтобы получать все уведомления. 0 для отключения.",
+ "Notifications_Muted_Description": "Если вы выберете заглушить всех, комната не будет подсвечиваться в списке при появлении новых сообщений за исключением упоминания о вас. Заглушение уведомлений переопределяет настройки уведомлений.",
+ "Notifications_Sound_Volume": "Громкость уведомления",
+ "Notify_active_in_this_room": "Уведомить всех активных в этом чате",
+ "Notify_all_in_this_room": "Уведомить всех в этом чате",
+ "Num_Agents": "# Представители",
"Number_of_messages": "Количество сообщений",
- "OAuth_Application": "Приложение OAuth",
+ "OAuth_Application": "Приложение OAuth",
"OAuth_Applications": "Приложения OAuth",
"Objects": "Объекты",
+ "Off": "Выключено",
"Off_the_record_conversation": "Конфиденциальная беседа",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Конфиденциальная беседа недоступна в вашем браузере или на вашем устройстве.",
+ "Office_Hours": "Рабочие часы",
+ "Office_hours_enabled": "Рабочие часы включены",
+ "Office_hours_updated": "Рабочие часы обновлены",
"Offline": "Не в сети",
- "Offline_DM_Email": " вам было отправлено сообщение пользователем __user__",
+ "Offline_DM_Email": "Тема письма Email для личных сообщений",
"Offline_form": "Офлайн форма",
"Offline_form_unavailable_message": "Офлайн сообщение",
- "Offline_Mention_Email": " вас упомянул(а) __user__ в #__room__",
+ "Offline_Link_Message": "ПЕРЕЙТИ К СООБЩЕНИЮ",
+ "Offline_Mention_Email": "Тема сообщения электронной почты",
"Offline_message": "Офлайн сообщение",
"Offline_success_message": "Офлайн сообщение об отправке",
"Offline_unavailable": "Offline недоступен",
+ "On": "Включено",
"Online": "В сети",
+ "Only_authorized_users_can_write_new_messages": "Только авторизованные пользователи могут писать новые сообщения",
+ "Only_On_Desktop": "Режим рабочего стола (отправлять по Enter только с компьютера)",
"Only_you_can_see_this_message": "Только вы можете видеть это сообщение",
- "Oops!": "Ой",
+ "Oops!": "Упс",
"Open": "Открыть",
+ "Open_channel_user_search": "\"%s\" - открыть канал / поиск пользователей",
+ "Open_days_of_the_week": "Рабочие дни",
+ "Open_Livechats": "Открыть Livechat",
+ "Open_your_authentication_app_and_enter_the_code": "Откройте ваше приложение аутентификации и введите код. Вы также можете использовать один из кодов восстановления (backup codes).",
"Opened": "Открыто",
- "optional": "дополнительно",
- "Order": "Последовательность",
+ "Opened_in_a_new_window": "Открыть в новом окне",
+ "Opens_a_channel_group_or_direct_message": "Открывает канал, группу или личную переписку",
+ "optional": "Опционально",
+ "or": "или",
+ "Or_talk_as_anonymous": "Или говорить как аноним",
+ "Order": "Порядок",
+ "Original": "Оригинальный",
"OS_Arch": "Архитектура ОС",
"OS_Cpus": "Количество процессоров в ОС",
- "OS_Freemem": "Свободное кол-во памяти",
- "OS_Loadavg": "Загрузка ОС",
+ "OS_Freemem": "Свободное количество памяти",
+ "OS_Loadavg": "Среднее загрузка ОС",
"OS_Platform": "Платформа ОС",
"OS_Release": "Версия ОС",
"OS_Totalmem": "Общее кол-во памяти в ОС",
"OS_Type": "Тип ОС",
- "OS_Uptime": "Uptime системы",
+ "OS_Uptime": "Аптайм ОС",
"others": "другие",
"OTR": "OTR",
- "OTR_is_only_available_when_both_users_are_online": "Конфиденциальная беседа доступна, когда оба пользователя online.",
- "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Отклонить URL-адрес, на который загружены файлы. Этот URL-адрес также используется для загрузок в том случае, если указан CDN.",
+ "OTR_is_only_available_when_both_users_are_online": "Конфиденциальная беседа доступна, когда оба пользователя в сети.",
+ "Outgoing_WebHook": "Исходящий webhook",
+ "Outgoing_WebHook_Description": "Отправьте данные из Rocket.Chat в реальном времени",
+ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Отклонить URL-адрес, на который загружены файлы. Этот URL-адрес также используется для загрузок в том случае, если указан CDN.",
"Page_title": "Заголовок страницы",
"Page_URL": "URL страницы",
"Password": "Пароль",
"Password_Change_Disabled": "Администратор отключил возможность изменения паролей",
"Password_changed_successfully": "Пароль успешно изменен",
- "Past_Chats": "Прошлые Чаты",
+ "Past_Chats": "Прошлые чаты",
"Payload": "Тело запроса",
"People": "Люди",
"Permalink": "Постоянная ссылка",
"Permissions": "Настройка прав",
+ "pin-message": "Прикрепить сообщение",
+ "pin-message_description": "Разрешение прикреплять сообщение на канале",
"Pin_Message": "Прикрепить сообщение",
"Pinned_a_message": "Прикрепленное сообщение:",
"Pinned_Messages": "Прикрепленные сообщения",
- "PiwikAnalytics_siteId_Description": "Идентификатор сайта будет использовать для идентификации этого сайта. Пример: 17",
- "PiwikAnalytics_url_Description": "URL, где проживает Piwik, обязательно включают в себя испытания той косой черты. Пример: //piwik.rocket.chat/",
- "Placeholder_for_email_or_username_login_field": "Поля для заполнения электронного адреса или имени пользователя",
- "Placeholder_for_password_login_field": "Поле для заполнения пароля",
+ "PiwikAdditionalTrackers": "Дополнительные сайты Piwik",
+ "PiwikAdditionalTrackers_Description": "Вы можете отправлять статистику на несколько серверов Piwik добавив URL и siteId. Пример: \n[ { \"trackerURL\" : \"https://my.piwik.domain2/\", \"siteId\" : 42 }, { \"trackerURL\" : \"https://my.piwik.domain3/\", \"siteId\" : 15 } ]",
+ "PiwikAnalytics_cookieDomain": "Все субдомены",
+ "PiwikAnalytics_cookieDomain_Description": "Отслеживать посетителей всех субдоменов",
+ "PiwikAnalytics_domains": "Скрыть исходящие ссылки",
+ "PiwikAnalytics_prependDomain": "Добавить имя домена",
+ "PiwikAnalytics_siteId_Description": "Идентификатор. Используетя для идентификации этого сайта. Пример: 17",
+ "PiwikAnalytics_url_Description": "URL, где находится Piwik, обязательно должен содержать слэш в конце. Пример: //piwik.rocket.chat/",
+ "Placeholder_for_email_or_username_login_field": "Подсказка адреса электронной почты или логина пользователя для поля при входе",
+ "Placeholder_for_password_login_field": "Подсказка для поля пароля при входе",
"Please_add_a_comment": "Пожалуйста, добавьте комментарий",
"Please_add_a_comment_to_close_the_room": "Пожалуйста, добавьте комментарий, чтобы закрыть комнату",
"Please_answer_survey": "Пожалуйста, уделите минуту для того, чтобы ответить на несколько вопросов об этом чате",
- "Please_enter_value_for_url": "Пожалуйста, введите значение для URL-адреса вашего аватара.",
+ "please_enter_valid_domain": "Пожалуйста, введите валидный домен",
+ "Please_enter_value_for_url": "Пожалуйста, введите ссылку на ваш аватар.",
"Please_enter_your_new_password_below": "Введите ваш новый пароль ниже:",
"Please_enter_your_password": "Повторно введите свой пароль",
"Please_fill_a_label": "Заполните подпись",
- "Please_fill_a_name": "Введите имя",
- "Please_fill_a_username": "Заполните имя пользователя",
- "Please_fill_name_and_email": "Введите имя и электронный адрес",
+ "Please_fill_a_name": "Пожалуйста, введите имя",
+ "Please_fill_a_username": "Заполните логин",
+ "Please_fill_all_the_information": "Пожалуйста, заполните информацию",
+ "Please_fill_name_and_email": "Заполните имя и адрес электронной почты",
+ "Please_select_an_user": "Пожалуйста, выберите пользователя",
"Please_select_enabled_yes_or_no": "Выберите вариант \"Разрешено\"",
- "Please_wait": "Минуточку",
+ "Please_wait": "Пожалуйста, подождите",
"Please_wait_activation": "Пожалуйста, подождите, это может занять некоторое время.",
"Please_wait_while_OTR_is_being_established": "Подождите, ваша конфиденциальная беседа устанавливается",
- "Please_wait_while_your_account_is_being_deleted": "Подождите, ваш аккаунт удаляется...",
- "Please_wait_while_your_profile_is_being_saved": "Подождите, пока ваш профиль сохраняется...",
+ "Please_wait_while_your_account_is_being_deleted": "Пожалуйста, подождите, ваша учетная запись удаляется...",
+ "Please_wait_while_your_profile_is_being_saved": "Пожалуйста, подождите, пока ваш профиль сохраняется...",
"Port": "Порт",
- "Post_as": "Опубликовать как",
- "Post_to_Channel": "Опубликовать в канал",
- "Post_to_s_as_s": "Опубликовать в %s как %s ",
+ "post-readonly": "Сообщение только для чтения",
+ "post-readonly_description": "Разрешение на отправление сообщений на канале только для чтения",
+ "Post_as": "Отправить от имени",
+ "Post_to_Channel": "Опубликовать на канале",
+ "Post_to_s_as_s": "Отправить в %s от %s ",
"Preferences": "Настройки",
"Preferences_saved": "Настройки сохранены",
+ "preview-c-room": "Предварительный просмотр публичного канала",
+ "preview-c-room_description": "Разрешение на просмотр содержимого публичного канала перед присоединением",
"Privacy": "Приватность",
- "Private": "Частный",
- "Private_Group": "Приватный чат",
- "Private_Groups": "Приватные чаты",
- "Private_Groups_list": "Список приватных чатов",
+ "Private": "Приватный канал",
+ "Private_Channel": "Приватный канал",
+ "Private_Group": "Приватная группа",
+ "Private_Groups": "Приватные группы",
+ "Private_Groups_list": "Список приватных групп",
"Profile": "Профиль",
+ "Profile_details": "Детали профиля",
+ "Profile_picture": "Изображение профиля",
"Profile_saved_successfully": "Профиль успешно сохранен",
- "Public": "общественного",
- "Push": "Push-уведомления",
+ "Public": "Открытый",
+ "Public_Channel": "Канал",
+ "Push": "Push уведомления",
"Push_apn_cert": "APN сертификат",
"Push_apn_dev_cert": "APN Dev сертификат",
- "Push_apn_dev_key": "APN Dev ключ",
- "Push_apn_dev_passphrase": "APN Dev пароль",
- "Push_apn_key": "APN ключ",
- "Push_apn_passphrase": "APN Пароль",
+ "Push_apn_dev_key": "Ключ APN Dev",
+ "Push_apn_dev_passphrase": "APN Dev Passphrase",
+ "Push_apn_key": "Ключ APN",
+ "Push_apn_passphrase": "APN Passphrase",
"Push_debug": "Отладка",
"Push_enable": "Включить",
"Push_enable_gateway": "Включить шлюз",
"Push_gateway": "Шлюз",
- "Push_gcm_api_key": "GCM API-ключ",
+ "Push_gcm_api_key": "Ключ GCM API",
"Push_gcm_project_number": "GCM номер проекта",
- "Push_production": "Продакшн\n",
+ "Push_production": "Продакшн",
"Push_show_message": "Показать сообщение в уведомлении",
- "Push_show_username_room": "Показать канал/группу/имя пользователя в уведомлении",
+ "Push_show_username_room": "Показать имя чата/логин пользователя в уведомлении",
"Push_test_push": "Тест",
"Query": "Запрос",
- "Query_description": "Дополнительные условия для определения того, каким пользователям отправлять электронную почту. Пользователи, не получающие рассылку, автоматически удалены из запроса. Формат JSON должен быть действителен. Например: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
+ "Query_description": "Дополнительные условия для определения того, каким пользователям отправлять электронную почту. Отписавшиеся пользователи, автоматически удаляются из запроса. Должен быть валидным JSON. Например: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
+ "Queue": "Очередь",
"quote": "цитата",
- "Quote": "Цитировать",
- "Random": "случайный",
- "Reacted_with": "реагирующего с",
+ "Quote": "цитата",
+ "Random": "Случайный",
+ "React_when_read_only": "Разрешить реакции",
+ "React_when_read_only_changed_successfully": "Разрешение на реакции при включенном режиме только для чтения изменено",
+ "Reacted_with": "Реагирует с",
"Reactions": "Реакции",
+ "Read_only": "Только для чтения",
+ "Read_only_changed_successfully": "Режим \"только для чтения\" успешно изменен",
+ "Read_only_channel": "Канал только для чтения",
+ "Read_only_group": "Группа только для чтения",
"Record": "Запись",
- "Redirect_URI": "Перенаправить URL-адрес",
+ "Redirect_URI": "Перенаправить URI",
"Refresh_keys": "Обновить клавиши",
+ "Refresh_oauth_services": "Обновить сервисы OAuth",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Чтобы включить демонстрацию экрана, обновите страницу после установки",
- "Register": "Зарегистрироваться",
+ "Regenerate_codes": "Восстановить коды",
+ "Register": "Зарегистрировать новую учетную запись",
+ "Registration": "Регистрация",
"Registration_Succeeded": "Успешная регистрация",
+ "Registration_via_Admin": "Регистрация через администратора",
+ "Regular_Expressions": "Регулярные выражения",
"Release": "Выпуск",
+ "Reload": "Перезагрузить",
"Remove": "Удалить",
- "Remove_Admin": "Разжаловать администратора",
+ "remove-user": "Удалить пользователя",
+ "remove-user_description": "Разрешение на удаление пользователя из чата",
+ "Remove_Admin": "Удалить администратора",
+ "Remove_as_leader": "Удалить из лидеров",
"Remove_as_moderator": "Удалить из модераторов",
"Remove_as_owner": "Удалить из владельцев",
"Remove_custom_oauth": "Удалить пользовательский OAuth",
- "Remove_from_room": "Удалить из чата",
- "Remove_someone_from_room": "Удалить кого-то из чата",
+ "Remove_from_room": "Удалить из канала",
+ "Remove_last_admin": "Удаление последнего администратора",
+ "Remove_someone_from_room": "Удалить кого-то из канала",
"Removed": "Удаленные",
+ "Reply": "Ответить",
"Report_Abuse": "Сообщить о нарушениях",
- "Report_exclamation_mark": "Отчет!",
- "Report_sent": "отчет отправлен",
+ "Report_exclamation_mark": "Соощить!",
+ "Report_sent": "Сообщение отправлено",
"Report_this_message_question_mark": "Сообщить об этом сообщении?",
+ "Reporting": "Сообщаю",
"Require_password_change": "Требуется смена пароля",
- "Resend_verification_email": "Отправить проверочный email ещё раз",
- "Reset": "Сбросить",
- "Reset_password": "Сбросить пароль",
+ "Resend_verification_email": "Отправить проверочное электронное письмо ещё раз",
+ "Reset": "Восстановить",
+ "Reset_password": "Восстановить пароль",
+ "Reset_section_settings": "Восстановить значения по умолчанию",
"Restart": "Перезапустить",
"Restart_the_server": "Перезапустить сервер",
+ "Retry_Count": "Число повторных попыток",
"Role": "Роль",
"Role_Editing": "Редактировать роль",
"Role_removed": "Роль удалена",
- "Room": "Чат",
+ "Room": "Комната",
+ "Room_announcement_changed_successfully": "Объявление комнаты успешно изменено",
"Room_archivation_state": "Статус",
"Room_archivation_state_false": "В сети",
- "Room_archivation_state_true": "Удалено",
- "Room_archived": "Чат удалён",
- "room_changed_privacy": "__user_by__ изменил тип чата на __room_type__ ",
- "room_changed_topic": "__user_by__ изменил тему чата на __room_topic__ ",
- "Room_description_changed_successfully": "Описание комнаты изменено",
- "Room_has_been_deleted": "Чат был удалён",
- "Room_Info": "Информация о чате",
- "Room_name_changed": "Название чата изменено: __room_name__ пользователем __user_by__ ",
- "Room_name_changed_successfully": "Название чата успешно изменено",
- "Room_not_found": "Чат не найден",
- "Room_topic_changed_successfully": "Тема чата успешно изменена",
- "Room_type_changed_successfully": "Тип чата успешно изменен",
- "Room_unarchived": "Чат в архиве",
- "Room_uploaded_file_list": "Список файлов",
+ "Room_archivation_state_true": "Архивировать",
+ "Room_archived": "Комната в архиве",
+ "room_changed_announcement": "Пользователь __user_by__ изменил объявление комнаты на __room_announcement__ ",
+ "room_changed_description": "Пользователь __user_by__ изменил описание комнаты на __room_description__ ",
+ "room_changed_privacy": "Пользователь __user_by__ изменил тип комнаты на __room_type__ ",
+ "room_changed_topic": "Пользователь __user_by__ изменил тему комнаты на __room_topic__ ",
+ "Room_default_change_to_private_will_be_default_no_more": "Этот канал является каналом по умолчанию, если сделать его приватной группой, он перестанет быть каналом по-умолчанию. Вы хотите продолжить?",
+ "Room_description_changed_successfully": "Описание обновлено",
+ "Room_has_been_archived": "Комната была архивирована",
+ "Room_has_been_deleted": "Комната была удалена",
+ "Room_has_been_unarchived": "Чат был разархивирован",
+ "Room_Info": "Информация канала",
+ "room_is_blocked": "Комната была заблокирована",
+ "room_is_read_only": "Эта группа доступна только для чтения",
+ "room_name": "Имя комнаты",
+ "Room_name_changed": "Пользователь __user_by__ поменял название комнаты на __room_name__ ",
+ "Room_name_changed_successfully": "Название комнаты успешно изменено",
+ "Room_not_found": "Комната не найдена",
+ "Room_password_changed_successfully": "Пароль комнаты успешно изменён",
+ "Room_topic_changed_successfully": "Тема комнаты успешно изменена",
+ "Room_type_changed_successfully": "Тип комнаты успешно изменён",
+ "Room_type_of_default_rooms_cant_be_changed": "Эта комната является комнатой по умолчанию и её тип не может быть изменён. Пожалуйста, обратитесь к вашему администратору.",
+ "Room_unarchived": "Комната разархивирована",
+ "Room_uploaded_file_list": "Список файлов канала",
"Room_uploaded_file_list_empty": "Нет доступных файлов",
- "Rooms": "Чаты",
- "Running_Instances": "Запущенные инстансы",
- "S_new_messages_since_s": "%s новых сообщений с %s",
+ "Rooms": "Комнаты",
+ "run-import": "Запускать импорт",
+ "run-import_description": "Разрешение на запуск импортеров",
+ "run-migration": "Запустить миграцию",
+ "run-migration_description": "Разрешение на запуск миграций",
+ "Running_Instances": "Запущенные виртуальные машины",
+ "S_new_messages_since_s": "%s новых сообщений с %s",
+ "Same_Style_For_Mentions": "Такой же стиль для упоминаний",
"SAML": "SAML разметка",
"SAML_Custom_Cert": "Пользовательский сертификат",
"SAML_Custom_Entry_point": "Пользовательская точка входа",
- "SAML_Custom_Generate_Username": "Сгенерировать имя пользователя",
+ "SAML_Custom_Generate_Username": "Сгенерировать логин",
"SAML_Custom_Issuer": "Пользовательская организация",
"SAML_Custom_Provider": "Пользовательский поставщик",
+ "Saturday": "Суббота",
"Save": "Сохранить",
- "Save_changes": "Сохранить изменения",
- "Save_Mobile_Bandwidth": "Включить режим экономии трафика",
- "Save_to_enable_this_action": "Сохранить, чтобы активировать это действие",
+ "save-others-livechat-room-info": "Сохранить информацию о других комнатах livechat",
+ "save-others-livechat-room-info_description": "Разрешение сохранять информацию от других комнатах livechat",
+ "Save_changes": "Применить",
+ "Save_Mobile_Bandwidth": "Включить режим экономии трафика для мобильных устройств",
+ "Save_to_enable_this_action": "Сохраните, чтобы активировать это действие",
"Saved": "Сохранено",
"Saving": "Сохранение",
+ "Scan_QR_code": "Используйте приложения авторизаторы, такие как Google Authenticator, Authy или Duo, для того, чтобы отсканировать QR-код. Вам будет показан 6-значный код, который вы должны ввести ниже.",
+ "Scan_QR_code_alternative_s": "Если вы не можете отсканировать QR код, вы можете ввести код вручную: __code__",
"Scope": "Область",
"Screen_Share": "Демонстрация экрана",
- "Script_Enabled": "Сценарий включен",
+ "Script_Enabled": "Использовать скрипт",
"Search": "Поиск",
- "Search_by_username": "Поиск по имени пользователя",
+ "Search_by_username": "Поиск по логину",
"Search_Messages": "Поиск сообщений",
- "Search_Private_Groups": "Поиск приватных чатов",
- "seconds": "секунд(ы)",
- "Secret_token": "Секретный маркер",
- "Select_a_department": "Выберите раздел",
+ "Search_Private_Groups": "Поиск приватных групп",
+ "seconds": "секунды",
+ "Secret_token": "Секретный токен",
+ "Security": "Безопасность",
+ "Select_a_department": "Выберите отдел",
+ "Select_a_user": "Выберите пользователя",
"Select_an_avatar": "Выберите аватар",
"Select_file": "Выберите файл",
- "Select_service_to_login": "Выберите сервис для аватара или загрузите изображение с компьютера",
+ "Select_role": "Выберите роль",
+ "Select_service_to_login": "Выберите сервис для загрузки вашего изображения или загрузите изображение с компьютера напрямую",
"Select_user": "Выберите пользователя",
"Select_users": "Выберите пользователей",
- "Selected_agents": "Выбранные сотрудники",
+ "Selected_agents": "Выбранные представители",
"Send": "Отправить",
"Send_a_message": "Отправить сообщение",
- "Send_a_test_mail_to_my_user": "Отправить тестовое сообщение моему пользователю",
- "Send_a_test_push_to_my_user": "Отправить тестовое push-уведомление моему пользователю",
- "Send_confirmation_email": "Отправить письмо с подтверждением",
- "Send_data_into_RocketChat_in_realtime": "Отправка данных в Rocket.Chat в режиме реального времени.",
- "Send_email": "Отправить письмо",
+ "Send_a_test_mail_to_my_user": "Проверка",
+ "Send_a_test_push_to_my_user": "Протестировать push-уведомления",
+ "Send_confirmation_email": "Отправить электронное письмо с подтверждением",
+ "Send_data_into_RocketChat_in_realtime": "Отправьте данные в Rocket.Chat в режиме реального времени.",
+ "Send_email": "Отправить электронное письмо",
"Send_invitation_email": "Отправить приглашение по электронной почте",
- "Send_invitation_email_error": "Вы не предоставили корректный email адрес.",
- "Send_invitation_email_info": "Вы можете отправить несколько email приглашений за раз.",
- "Send_invitation_email_success": "Вы успешно отправили приглашения на следующие адреса:",
- "Send_request_on_chat_close": "Отправить запрос на чат закрытия",
+ "Send_invitation_email_error": "Вы не предоставили корректный адрес электронной почты.",
+ "Send_invitation_email_info": "Вы можете отправить несколько электронных писем с приглашением за раз.",
+ "Send_invitation_email_success": "Вы успешно отправили приглашения на следующие адреса электронной почты:",
+ "Send_request_on_chat_close": "Отправить запрос на закрытие чата",
"Send_request_on_offline_messages": "Отправить запрос на сообщения в автономном режиме",
"Send_Test": "Отправить тест",
- "Send_welcome_email": "Отправить письмо с приветствием",
- "Send_your_JSON_payloads_to_this_URL": "Отправить ваши полезные данные формата JSON на этот URL-адрес.",
+ "Send_welcome_email": "Отправить электронное письмо с приветствием",
+ "Send_your_JSON_payloads_to_this_URL": "Отправить ваши полезные данные формата JSON на этот URL-адрес.",
"Sending": "Отправка...",
+ "Served_By": "Обслуживается",
"Service": "Обработчик",
+ "Service_account_key": "Ключ Service account",
+ "set-moderator": "Назначить модератора",
+ "set-moderator_description": "Разрешение на назначение других пользователей модераторами канала",
+ "set-owner": "Назначить владельца",
+ "set-owner_description": "Разрешение на назначение других пользователей владельцами канала",
+ "set-react-when-readonly": "Установить реакцию когда только для чтения",
+ "set-react-when-readonly_description": "Разрешение на изменение возможности реакций на сообщения на канале только для чтения",
+ "set-readonly": "Установить только для чтения",
+ "set-readonly_description": "Разрешение переводить канал в режим только для чтения",
+ "Set_as_leader": "Назначит лидером",
"Set_as_moderator": "Назначить модератором",
"Set_as_owner": "Назначить владельцом",
"Settings": "Настройки",
"Settings_updated": "Настройки обновлены",
- "Should_be_a_URL_of_an_image": "Это должен быть URL-адрес или изображение.",
+ "Share_Location_Title": "Поделиться местоположением?",
+ "Shared_Location": "Предоставленное местоположение",
+ "Should_be_a_URL_of_an_image": "Введите URL изображения.",
"Should_exists_a_user_with_this_username": "Пользователь уже должен существовать.",
"Show_all": "Показать всех",
"Show_more": "Показать больше",
- "Show_only_online": "Показать только online",
+ "show_offline_users": "показывать оффлайн пользователей",
+ "Show_on_registration_page": "Показывать на странице регистрации",
+ "Show_only_online": "Показать только подключенных",
"Show_preregistration_form": "Показать предварительную регистрационную форму",
- "Showing_archived_results": "Демонстрация %s архивных результатов
",
- "Showing_online_users": "Показано __total_showing__ из __total__ пользователей",
- "Showing_results": "Отображено %s результатов
",
+ "Show_queue_list_to_all_agents": "Показывать список очередей всем представителям",
+ "Show_the_keyboard_shortcut_list": "Показывать список горячих клавиш",
+ "Showing_archived_results": "Показано %s архивных результатов
",
+ "Showing_online_users": "Показано: __total_showing__ . Подключенных: __online__. Всего: __total__ пользователей",
+ "Showing_results": "Показано %s результатов
",
+ "Sidebar_list_mode": "Режим отображения списка каналов",
+ "Sign_in_to_start_talking": "Войдите, чтобы начать разговор",
"since_creation": "с %s",
"Site_Name": "Название сайта",
"Site_Url": "URL-адрес сайта",
- "Site_Url_Description": "Пример: https://chat.domain.com/",
+ "Site_Url_Description": "Пример: https://chat.domain.com/",
"Skip": "Пропустить",
- "Slash_Gimme_Description": "Отображение (つ ◕_◕) つ перед тем ваше сообщение",
- "Slash_LennyFace_Description": "Отображение (͡ ° ͜ʖ ͡ °) после того, как ваше сообщение",
- "Slash_Shrug_Description": "Отображает ¯ \\ _ (ツ) _ / ¯ после вашего сообщения",
- "Slash_Tableflip_Description": "Отображение (╯ ° □ °) ╯( ┻━┻",
- "Slash_TableUnflip_Description": "Дисплеи ┬─┬ ノ (゜ - ゜ ノ)",
+ "SlackBridge_error": "В SlackBridge произошла ошибка во время импорта ваших сообщений в %s:%s",
+ "SlackBridge_finish": "SlackBridge закончил импорт сообщений в %s. Пожалуйста, перезагрузите приложение, чтобы увидеть все сообщения.",
+ "SlackBridge_Out_All_Description": "Отправлять сообщения из всех каналов, которые есть в Slack и в которых есть бот",
+ "SlackBridge_Out_Channels": "Общие чаты для SlackBridge Out",
+ "SlackBridge_Out_Channels_Description": "Выберите с каких каналов отправлять сообщения обратно в Slack",
+ "SlackBridge_Out_Enabled": "Включить SlackBridge Out",
+ "SlackBridge_Out_Enabled_Description": "Должен ли SlackBridge также отправлять ваши сообщения обратно в Slack",
+ "SlackBridge_start": "@%s начал импорт через SlackBridge в \"#%s\". Вы получите уведомление после завершения.",
+ "Slash_Gimme_Description": "Показать (つ ◕_◕) つ перед сообщением",
+ "Slash_LennyFace_Description": "Показать (͡ ° ͜ʖ ͡ °) после сообщения",
+ "Slash_Shrug_Description": "Показать ¯ \\ _ (ツ) _ / ¯ после сообщения",
+ "Slash_Tableflip_Description": "Показать (╯ ° □ °) ╯( ┻━┻",
+ "Slash_TableUnflip_Description": "Показать ┬─┬ ノ (゜ - ゜ ノ)",
"Slash_Topic_Description": "Установить тему",
- "Slash_Topic_Params": "тема сообщения",
+ "Slash_Topic_Params": "Тема сообщения",
+ "Smarsh_Email": "Адрес электронной почты Smarsh",
+ "Smarsh_Email_Description": "Адрес электронной почты Smarsh, на который отправлять .eml файл.",
+ "Smarsh_Enabled": "Включить Smarsh",
+ "Smarsh_Enabled_Description": "Включен ли Smarsh eml коннектор (требует заполнения поля \"Адрес электронной почты отправителя\" в \"Электронная почта\" -> \"SMTP\").",
+ "Smarsh_Interval": "Период Smarsh",
+ "Smarsh_Interval_Description": "Период времени ожидания перед отправкой чатов (требует заполнения поля \"Адрес электронной почты отправителя\" в \"Электронная почта\"->\"SMTP\").",
+ "Smarsh_MissingEmail_Email": "Отсутствует электронная почта",
+ "Smarsh_MissingEmail_Email_Description": "Почтовый адрес для учетной записи с пустым почтовым адресом (обычно такие бывает у учетных записей ботов)",
"Smileys_and_People": "Смайлики и люди",
"SMS_Enabled": "SMS включены",
"SMTP": "Протокол SMTP",
"SMTP_Host": "SMTP хост",
- "SMTP_Password": "SMTP Пароль",
- "SMTP_Port": "SMTP Порт",
- "SMTP_Test_Button": "Настройка тестового протокола SMTP",
- "SMTP_Username": "SMTP пользователь",
- "Sound": "Звук",
+ "SMTP_Password": "SMTP пароль",
+ "SMTP_Port": "SMTP порт",
+ "SMTP_Test_Button": "Настройка тестового протокола SMTP",
+ "SMTP_Username": "SMTP логин",
+ "snippet-message": "Сообщение со сниппетом",
+ "snippet-message_description": "Разрешение на создание сообщений со сниппетом",
+ "Snippet_Added": "Создано %s",
+ "Snippet_Messages": "Сообщения со сниппетами",
+ "Snippeted_a_message": "Создан сниппет __snippetLink__",
+ "Sort_by_activity": "Сортировать по активности",
+ "Sound": "Звуковые оповещения",
+ "Sound_File_mp3": "Звуковой файл (mp3)",
+ "Split_by_categories": "Отдельно по категориям",
"SSL": "SSL",
"Star_Message": "Отметить сообщение",
"Starred_Messages": "Отмеченные сообщения",
+ "Start": "Начать",
"Start_audio_call": "Начать голосовой вызов",
"Start_Chat": "Начать чат",
- "Start_of_conversation": "Начало диалога",
+ "Start_of_conversation": "Начало беседы",
"Start_OTR": "Начать конфиденциальную беседу",
"Start_video_call": "Начать видеозвонок",
- "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Начните с %s для пользователя или %s для канала. Например: %s или %s",
+ "Start_video_conference": "Начать видео конференцию?",
+ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Начните с %s для пользователя или %s для канала. Например: %s или %s",
"Started_At": "Начато",
+ "Started_a_video_call": "Начать видеозвонок",
"Statistics": "Статистика",
- "Statistics_reporting": "Отправить статистику в Rocket.Chat",
- "Statistics_reporting_Description": "Отправляя свою статистику, вы поможете нам определить, сколько Rocket.Chat развернуты, а также насколько хорошо ведет себя система, таким образом, мы можем дополнительно улучшить его. Не беспокойтесь, поскольку никакой информации о пользователе не передается, а вся информация, что мы получаем, конфиденциальна.",
+ "Statistics_reporting": "Отправлять статистику в Rocket.Chat",
+ "Statistics_reporting_Description": "Отправляя свою статистику, вы поможете нам определить, сколько Rocket.Chat развернуты, а также насколько хорошо ведет себя система, таким образом, мы можем дополнительно улучшить его. Не беспокойтесь, поскольку никакой информации о пользователях не передается, а вся информация, что мы получаем, конфиденциальна.",
"Stats_Active_Users": "Активные пользователи",
- "Stats_Avg_Channel_Users": "Количество пользователей в публичных чатах",
- "Stats_Avg_Private_Group_Users": "Количество пользователей в приватных чатах",
- "Stats_Away_Users": "Отошедших пользователей",
- "Stats_Max_Room_Users": "Максимальное количество пользователей в чате",
+ "Stats_Avg_Channel_Users": "Среднее число пользователей на каналах",
+ "Stats_Avg_Private_Group_Users": "Среднее число пользователей в приватных группах",
+ "Stats_Away_Users": "Отошедшие пользователи",
+ "Stats_Max_Room_Users": "Максимальное количество пользователей в комнате",
"Stats_Non_Active_Users": "Неактивные пользователи",
"Stats_Offline_Users": "Пользователи не в сети",
"Stats_Online_Users": "Пользователи в сети",
- "Stats_Total_Channels": "Всего публичных чатов",
- "Stats_Total_Direct_Messages": "Общее количество сообщений в личных чатах",
+ "Stats_Total_Channels": "Всего каналов",
+ "Stats_Total_Direct_Messages": "Общее количество личных переписок",
+ "Stats_Total_Livechat_Rooms": "Всего чатов Livechat",
"Stats_Total_Messages": "Всего сообщений",
- "Stats_Total_Private_Groups": "Всего приватных чатов",
- "Stats_Total_Rooms": "Всего чатов",
+ "Stats_Total_Messages_Channel": "Всего сообщений в публичных чатах",
+ "Stats_Total_Messages_Direct": "Всего личных сообщений",
+ "Stats_Total_Messages_Livechat": "Всего сообщений в Livechat чатах",
+ "Stats_Total_Messages_PrivateGroup": "Всего сообщений в приватных чатах",
+ "Stats_Total_Private_Groups": "Всего приватных групп",
+ "Stats_Total_Rooms": "Всего комнат",
"Stats_Total_Users": "Всего пользователей",
+ "Status": "Статус",
"Stop_Recording": "Остановить запись",
"strike": "зачеркнутый",
"Subject": "Тема",
"Submit": "Отправить",
- "Success": "Выполнено",
- "Success_message": "сообщение об успешном выполнении",
+ "Success": "Успех",
+ "Success_message": "Сообщение об успешном выполнении",
+ "Sunday": "Воскресенье",
"Survey": "Опрос",
"Survey_instructions": "Оценивайте каждый вопрос по 5-балльной шкале, где 1 означает, что вы совсем недовольны, и 5 - полностью довольны.",
"Symbols": "Символы",
"Sync_success": "Синхронизация прошла успешно",
+ "Sync_in_progress": "Выполняется синхронизация",
"Sync_Users": "Синхронизация пользователей",
+ "System_messages": "Системные сообщения",
"Tag": "Тег",
+ "Take_it": "Возьми это!",
+ "TargetRoom": "Целевая комната",
+ "TargetRoom_Description": "Комната, куда будут отправляться сообщения, которые являются результатом этого события. Разрешена только одна целевая комната, и она должна существовать.",
+ "Team": "Команда",
"Test_Connection": "Проверка соединения",
- "Test_Desktop_Notifications": "Проверить уведомления рабочего стола",
+ "Test_Desktop_Notifications": "Протестировать работу уведомлений компьютера",
"Thank_you_exclamation_mark": "Спасибо!",
"Thank_you_for_your_feedback": "Спасибо за ваш отзыв",
- "The_application_name_is_required": "Требуется наименование приложения",
- "The_channel_name_is_required": "Имя канала обязательно",
+ "The_application_name_is_required": "Требуется название приложения",
+ "The_channel_name_is_required": "Требуется название канала",
"The_emails_are_being_sent": "Письма отправляются.",
"The_field_is_required": "Поле %s обязательно.",
- "The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Изменить размер изображения не получится, потому что мы не можем обнаружить установленные на вашем сервере ImageMagick или GraphicsMagick.",
- "The_redirectUri_is_required": "Требуется перенаправление URL-адреса",
- "The_server_will_restart_in_s_seconds": "Сервер перезапустится через % секунд",
- "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Параметр %s настраивается на %s и вы получаете доступ из %s !",
- "The_user_will_be_removed_from_s": "Пользователь будет удален из %s",
- "The_user_wont_be_able_to_type_in_s": "Пользователь не сможет ввести в %s",
+ "The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "Изменить размер изображения не получится, потому что мы не можем обнаружить установленные на вашем сервере ImageMagick или GraphicsMagick.",
+ "The_redirectUri_is_required": "Требуется redirectUri ",
+ "The_server_will_restart_in_s_seconds": "Сервер перезапустится через %s секунд",
+ "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Параметр %s настраивается на %s и вы получаете доступ из %s !",
+ "The_user_will_be_removed_from_s": "Пользователь будет удален из %s",
+ "The_user_wont_be_able_to_type_in_s": "Пользователь не сможет отправлять сообщения в %s",
"Theme": "Тема",
+ "theme-color-component-color": "Цвет компонента",
"theme-color-content-background-color": "Цвет фона содержимого",
+ "theme-color-custom-scrollbar-color": "Пользовательский цвет полосы прокрутки",
+ "theme-color-error-color": "Цвет ошибки",
+ "theme-color-info-font-color": "Цвет шрифта информации",
+ "theme-color-link-font-color": "Цвет шрифта ссылки",
+ "theme-color-pending-color": "Цвет ожидания",
+ "theme-color-primary-action-color": "Цвет основного действия",
"theme-color-primary-background-color": "Основной цвет фона",
"theme-color-primary-font-color": "Основной цвет шрифта",
+ "theme-color-secondary-action-color": "Цвет вторичного действия",
"theme-color-secondary-background-color": "Второй цвет фона",
"theme-color-secondary-font-color": "Второй цвет шрифта",
- "theme-color-tertiary-background-color": "Третий цвет фона",
- "theme-color-tertiary-font-color": "Третий цвет шрифта",
- "theme-color-link-font-color": "Цвет шрифта ссылки",
- "theme-color-info-font-color": "Цвет шрифта информации",
- "theme-color-custom-scrollbar-color": "Пользовательский цвет полосы прокрутки",
- "theme-color-status-away": "Цвет статуса \"Нет на месте\"",
+ "theme-color-selection-color": "Цвет выделения",
+ "theme-color-status-away": "Цвет статуса \"Отошёл\"",
"theme-color-status-busy": "Цвет статуса \"Занят\"",
"theme-color-status-offline": "Цвет статуса \"Не в сети\"",
"theme-color-status-online": "Цвет статуса \"В сети\"",
+ "theme-color-success-color": "Цвет успеха",
+ "theme-color-tertiary-background-color": "Третий цвет фона",
+ "theme-color-tertiary-font-color": "Третий цвет шрифта",
+ "theme-color-transparent-dark": "Прозрачный темный",
+ "theme-color-transparent-darker": "Прозрачный темнее",
+ "theme-color-transparent-light": "Прозрачный светлый",
+ "theme-color-transparent-lighter": "Прозрачный светлее",
+ "theme-color-transparent-lightest": "Прозрачный самый светлый",
"theme-color-unread-notification-color": "Цвет непрочитанных уведомлений",
+ "theme-color-rc-color-error": "Ошибка",
+ "theme-color-rc-color-error-light": "Ошибка светлая",
+ "theme-color-rc-color-alert": "Тревога",
+ "theme-color-rc-color-alert-light": "Тревога светлая",
+ "theme-color-rc-color-success": "Успех",
+ "theme-color-rc-color-success-light": "Успех светлый",
+ "theme-color-rc-color-button-primary": "Кнопка основная",
+ "theme-color-rc-color-button-primary-light": "Кнопка основная светлая",
+ "theme-color-rc-color-primary": "Основной",
+ "theme-color-rc-color-primary-darkest": "Основной самый темный",
+ "theme-color-rc-color-primary-dark": "Основной темный",
+ "theme-color-rc-color-primary-light": "Основной светлый",
+ "theme-color-rc-color-primary-light-medium": "Основной умеренно светлый",
+ "theme-color-rc-color-primary-lightest": "Основной самый светлый",
+ "theme-color-rc-color-content": "Содержимое",
"theme-custom-css": "Пользовательский CSS",
- "There_are_no_agents_added_to_this_department_yet": "Сотрудников, добавленных в этот раздел, не найдено.",
+ "theme-font-body-font-family": "Шрифт для тега body",
+ "There_are_no_agents_added_to_this_department_yet": "В этот отдел еще не добавлены сотрудники.",
"There_are_no_integrations": "Интеграций нет",
- "There_are_no_users_in_this_role": "Пользователей в этой должности не найдено.",
- "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Такой email уже использовался и не был подтверждён. Измените ваш пароль.",
- "This_is_a_desktop_notification": "Это уведомление рабочего стола",
+ "There_are_no_users_in_this_role": "Пользователей этой роле не найдено.",
+ "This_conversation_is_already_closed": "Беседа уже закрыта.",
+ "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "Такой адрес электронной почты уже использовался и не был подтверждён. Измените ваш пароль.",
+ "This_is_a_desktop_notification": "Это уведомление компьютера",
"This_is_a_push_test_messsage": "Это тестовое push-уведомление",
- "This_room_has_been_archived_by__username_": "Этот номер был архивируются __username__",
- "This_room_has_been_unarchived_by__username_": "Этот номер был разархивирована по __username__",
+ "This_room_has_been_archived_by__username_": "Комната была архивирована __username__",
+ "This_room_has_been_unarchived_by__username_": "__username__ вернул этот чат из архива",
+ "Thursday": "Четверг",
"Time_in_seconds": "Время в секундах",
"Title": "Заголовок",
"Title_bar_color": "Цвет строки заголовка",
- "Title_bar_color_offline": "Цвет заголовка",
- "Title_offline": "Заголовок оффлайн формы",
- "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Для того, чтобы установить Rocket.Chat Livechat на вашем сайте, скопируйте & и вставьте этот код выше последнего </body> тега на вашем сайте.",
+ "Title_bar_color_offline": "Цвет строки заголовка при отсутствии подключения",
+ "Title_offline": "Заголовок при отсутствии подключения",
+ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Для того, чтобы установить Rocket.Chat Livechat на вашем сайте, скопируйте и вставьте этот код выше последнего </body> тега на вашем сайте.",
"to_see_more_details_on_how_to_integrate": "чтобы увидеть более подробную информацию о том, как интегрировать.",
"To_users": "Пользователям",
+ "Toggle_original_translated": "Переключить оригинал/перевод",
"Topic": "Тема",
+ "Transcript_Enabled": "Спросить у посетителя хочет ли он получить переписку после окончания чата",
+ "Transcript_message": "Показать это сообщение, когда спрашиваем про получение переписке",
+ "Transcript_of_your_livechat_conversation": "Ваши переписки в Livechat.",
+ "Translated": "Переведено",
+ "Translations": "Переводы",
"Travel_and_Places": "Путешествия и места",
"Trigger_removed": "Триггер удален",
"Trigger_Words": "Слова запуска",
- "Triggers": "Триггер",
- "True": "Да",
+ "Triggers": "Триггеры",
+ "True": "Истина",
+ "Tuesday": "Вторник",
+ "Two-factor_authentication": "Двухфакторная аутентификация",
+ "Two-factor_authentication_disabled": "Двухфакторная аутентификация выключена",
+ "Two-factor_authentication_enabled": "Двухфакторная аутентификация включена",
+ "Two-factor_authentication_is_currently_disabled": "Двухфакторная аутентификация сейчас выключена",
+ "Two-factor_authentication_native_mobile_app_warning": "Внимание: Если вы активируете эту функцию вы не сможете работать с мобильных приложений на данный момент.",
"Type": "Тип",
"Type_your_email": "Введите адрес электронной почты",
- "Type_your_message": "Текст сообщения",
- "Type_your_name": "Введите свое имя",
- "Type_your_new_password": "Введите новый пароль",
- "UI_DisplayRoles": "Показывать роли пользователей в сообщениях",
- "UI_Merge_Channels_Groups": "Объединение частных групп с каналами",
- "Unarchive": "Восстановить",
- "Unmute_someone_in_room": "Разблокировать кого-нибудь в чате",
- "Unmute_user": "Разблокировать пользователя",
+ "Type_your_message": "Текст вашего сообщения",
+ "Type_your_name": "Введите ваше имя",
+ "Type_your_new_password": "Введите ваш новый пароль",
+ "UI_Allow_room_names_with_special_chars": "Разрешить специальные символы в названии комнаты",
+ "UI_Click_Direct_Message": "Нажмите, чтобы создать личное сообщение",
+ "UI_Click_Direct_Message_Description": "Не открывать профиль, перейти к беседе",
+ "UI_DisplayRoles": "Показывать роли пользователей",
+ "UI_Merge_Channels_Groups": "Отображать каналы и приватные каналы в одном списке",
+ "UI_Unread_Counter_Style": "Стиль счетчика непрочитанных сообщений",
+ "UI_Use_Name_Avatar": "Использовать инициалы полного имени для создания аватара",
+ "UI_Use_Real_Name": "Использовать настоящее имя",
+ "Unarchive": "Разархивировать",
+ "unarchive-room": "Разархивировать чат",
+ "unarchive-room_description": "Разрешение на разархивирование чатов",
+ "Unblock_User": "Разблокировать пользователя",
+ "Unmute_someone_in_room": "Сделать незаглушенным кого-нибудь в комнате",
+ "Unmute_user": "Сделать незаглушенным пользователя",
"Unnamed": "Без названия",
"Unpin_Message": "Открепить сообщение",
- "Unread_Rooms": "Непрочитанные чаты",
- "Unread_Rooms_Mode": "Режим \"непрочитанные чаты\"",
+ "Unread_Count": "Количество непрочитанных",
+ "Unread_Count_DM": "Количество непрочитанных сообщений для личных переписки",
+ "Unread_Messages": "Непрочитанные сообщения",
+ "Unread_Rooms": "Непрочитанные комнаты",
+ "Unread_Rooms_Mode": "Режим непрочитанные комнаты",
+ "Unread_Tray_Icon_Alert": "Иконка уведомлений о непрочитанных сообщениях в трее",
"Unstar_Message": "Убрать отметку",
+ "Updated_at": "Обновлено в",
+ "Upload_user_avatar": "Загруженный аватар",
+ "Upload_file_description": "Описание файла",
+ "Upload_file_name": "Имя файла",
"Upload_file_question": "Загрузить файл?",
"Uploading_file": "Загрузка файла...",
- "Uptime": "Uptime",
+ "Uptime": "Аптайм",
"URL": "URL",
- "Use_account_preference": "Использовать параметры аккаунта",
- "Use_Emojis": "Использовать Emojis",
- "Use_initials_avatar": "Использовать стандартный аватар",
+ "URL_room_prefix": "Префикс URL комнаты",
+ "Use_account_preference": "Параметры профиля",
+ "Use_Emojis": "Использовать эмодзи ",
+ "Use_Global_Settings": "Использовать глобальные настройки",
+ "Use_initials_avatar": "Использовать инициалы имени пользователя",
"Use_service_avatar": "Использовать %s аватар",
- "Use_this_username": "Использовать это имя пользователя",
- "Use_uploaded_avatar": "Использовать загруженную аватарку",
- "Use_url_for_avatar": "Использовать аватар по URL",
- "User__username__is_now_a_moderator_of__room_name_": "Пользователь __username__ сейчас является модератором __room_name__",
- "User__username__is_now_a_owner_of__room_name_": "Пользователь __username__ является владельцем __room_name__",
- "User__username__removed_from__room_name__moderators": "Пользователь __username__ удален из __room_name__ модераторов",
- "User__username__removed_from__room_name__owners": "Пользователь __username__ удален из __room_name__ владельцев",
+ "Use_this_username": "Использовать этот логин",
+ "Use_uploaded_avatar": "Использовать загруженный аватар",
+ "Use_url_for_avatar": "Использовать аватар по ссылке",
+ "Use_User_Preferences_or_Global_Settings": "Использовать пользовательские или глобальные настройки",
+ "User": "Пользователь",
+ "user-generate-access-token_description": "Разрешение создания токенов",
+ "User__username__is_now_a_leader_of__room_name_": "Пользователь __username__ теперь лидер канала __room_name__",
+ "User__username__is_now_a_moderator_of__room_name_": "Пользователь __username__ теперь является модератором __room_name__",
+ "User__username__is_now_a_owner_of__room_name_": "Пользователь __username__ теперь является владельцем __room_name__",
+ "User__username__removed_from__room_name__leaders": "Пользователь __username__ исключен из лидеров канала __room_name__",
+ "User__username__removed_from__room_name__moderators": "Пользователь __username__ удален из модераторов __room_name__",
+ "User__username__removed_from__room_name__owners": "Пользователь __username__ удален из владельцев __room_name__",
"User_added": "Пользователь __user_added__ добавлен.",
"User_added_by": "Пользователь __user_added__ добавлен __user_by__ .",
"User_added_successfully": "Пользователь успешно добавлен",
- "User_doesnt_exist": "Пользователя с логином `@%s` не существует.",
- "User_has_been_activated": "Пользователь активирован",
- "User_has_been_deactivated": "Пользователь деактивирован",
+ "User_and_group_mentions_only": "Только уведомления пользователя и группы",
+ "User_doesnt_exist": "Пользователя с логином \"@%s\" не существует.",
+ "User_has_been_activated": "Пользователь был активирован",
+ "User_has_been_deactivated": "Пользователь был деактивирован",
"User_has_been_deleted": "Пользователь был удален",
- "User_has_been_muted_in_s": "Пользователь заблокирован в %s",
- "User_has_been_removed_from_s": "Пользователь удален из %s",
+ "User_has_been_muted_in_s": "Пользователь был заглушен в %s",
+ "User_has_been_removed_from_s": "Пользователь был удален из %s",
"User_Info": "Информация о пользователе",
- "User_is_no_longer_an_admin": "Пользователь больше не администратор",
+ "User_Interface": "Пользовательский интерфейс",
+ "User_is_blocked": "Пользователь заблокирован",
+ "User_is_no_longer_an_admin": "Пользователь теперь не администратор",
"User_is_now_an_admin": "Пользователь теперь администратор",
- "User_joined_channel": "Присоединился к чату.",
- "User_joined_channel_female": "Присоединился к чату.",
- "User_joined_channel_male": "Присоединился к чату.",
- "User_left": "__user_left__ покинул чат.",
- "User_left_female": "__user_left__ покинула чат.",
- "User_left_male": "__user_left__ покинул чат.",
+ "User_is_unblocked": "Пользователь разблокирован",
+ "User_joined_channel": "Присоединился к каналу",
+ "User_joined_channel_female": "Присоединился к каналу",
+ "User_joined_channel_male": "Присоединился к каналу",
+ "User_left": "__user_left__ покинул канал.",
+ "User_left_female": "__user_left__ покинула канал.",
+ "User_left_male": "__user_left__ покинул канал.",
"User_logged_out": "Пользователь не в сети",
"User_management": "Управление пользователями",
- "User_muted_by": "Пользователь __user_muted__ заблокирован пользователем __user_by__ .",
+ "User_mentions_only": "Только уведомления",
+ "User_muted": "Пользователь заглушен",
+ "User_muted_by": "Пользователь __user_muted__ заглушен пользователем __user_by__ .",
"User_not_found": "Пользователь не найден",
- "User_not_found_or_incorrect_password": "Пользователь не найден, или введен неправильный пароль",
+ "User_not_found_or_incorrect_password": "Пользователь не найде, или введен неправильный пароль",
"User_or_channel_name": "Имя пользователя или канала",
"User_removed": "Пользователь удален",
"User_removed_by": "Пользователь __user_removed__ удален __user_by__ .",
"User_Settings": "Пользовательские настройки",
- "User_unmuted_by": "Пользователь __user_unmuted__ разблокирован пользователем __user_by__ .",
- "User_unmuted_in_room": "Пользователь разблокирован в чате",
+ "User_unmuted_by": "Пользователь __user_unmuted__ перестал быть заглушенным благодаря пользователю __user_by__ .",
+ "User_unmuted_in_room": "Пользователь перестал быть заглушенным в комнате",
"User_updated_successfully": "Пользователь успешно обновлен",
- "Username": "Имя пользователя",
- "Username_and_message_must_not_be_empty": "Имя пользователя или сообщение не должны быть пустыми",
- "Username_cant_be_empty": "Имя пользователя не может быть пустым",
- "Username_Change_Disabled": "Администратор отключил возможность изменения имен пользователей",
+ "User_uploaded_file": "Загрузил файл",
+ "User_uploaded_image": "Загрузил изображение",
+ "Username": "Логин",
+ "Username_and_message_must_not_be_empty": "Логин и сообщение не должны быть пустыми",
+ "Username_cant_be_empty": "Логин не может быть пустым",
+ "Username_Change_Disabled": "Администратор отключил возможность изменения логина",
"Username_denied_the_OTR_session": "__username__ отклонил конфиденциальную беседу",
- "Username_description": "Имя пользователя используется для обращения других участников к вам.",
- "Username_doesnt_exist": "Имя пользователя `%s` не существует.",
+ "Username_description": "Логин используется для упоминания вас в сообщениях",
+ "Username_doesnt_exist": "Логин `%s` не существует.",
"Username_ended_the_OTR_session": "__username__ завершил конфиденциальную беседу",
- "Username_invalid": "%s — некорректное имя пользователя, можно использовать только цифры, точки, подчеркивания и латинские буквы",
- "Username_is_already_in_here": "`@%s` уже здесь.",
- "Username_is_not_in_this_room": "Пользователь `#%s` не в этом чате.",
+ "Username_invalid": "%s недопустимое имя пользователя, > используйте только буквы, цифры, точки, дефисы и подчеркивания",
+ "Username_is_already_in_here": "\"@%s\" уже здесь.",
+ "Username_is_not_in_this_room": "Пользователь \"#%s\" не в этой комнате.",
+ "Username_Placeholder": "Пожалуйста, введите логин...",
"Username_title": "Зарегистрировать логин",
- "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ хочет начать конфиденциальную беседу. Принять?",
+ "Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ хочет начать конфиденциальную беседу. Принять?",
"Users": "Пользователи",
+ "Users_added": "Пользователь добавлен",
"Users_in_role": "Пользователи с ролью",
- "UTF8_Names_Slugify": "UTF-8 имена",
- "UTF8_Names_Validation": "Проверка имён в UTF8",
- "UTF8_Names_Validation_Description": "Специальные символы запрещены. Можно использовать - _ и . но только не в конце имени",
- "Verification_email_sent": "Проверочный email отправлен",
+ "UTF8_Names_Slugify": "UTF-8 имена Slugify",
+ "UTF8_Names_Validation": "Проверка имён UTF8",
+ "UTF8_Names_Validation_Description": "Регулярное выражение, которое будет использоваться для проверки логина или канала",
+ "Validate_email_address": "Подтвердите адрес электронной почты",
+ "Verification": "Подвтерждение",
+ "Verification_Description": "Вы можете использовать следующие подстановки: [Verification_Url] для URL верификации. [name], [fname], [lname] для полного имени, имени или фамилии пользователя. [email] для адреса электронной почты пользователя. [Site_Name] и [Site_URL] для имени приложения и его URL. ",
+ "Verification_Email": "Нажмите сюда чтобы подтвердить ваш аккаунт.",
+ "Verification_email_sent": "Проверочное электронное письмо отправлено",
+ "Verification_Email_Subject": "[Site_Name] - Подтвердите ваш аккаунт",
"Verified": "Подтверждён",
+ "Verify": "Подтверждение",
"Version": "Версия",
- "Video_Chat_Window": "Видео-чат",
- "View_All": "Посмотреть всех",
+ "Video_Chat_Window": "Видеочат",
+ "Video_Conference": "Видеоконференция",
+ "Video_message": "Видеосообщение",
+ "Videocall_declined": "Видео-звонок отклонён.",
+ "Videocall_enabled": "Включить видео-звонки",
+ "view-c-room": "Смотреть публичные каналы",
+ "view-c-room_description": "Разрешение на просмотр публичных каналов",
+ "view-d-room": "Просматривать личные сообщения",
+ "view-d-room_description": "Разрешение на просмотр личных сообщений",
+ "view-full-other-user-info": "Просмотр полной информации о других пользователях",
+ "view-full-other-user-info_description": "Разрешение на просмотр полных профилей других пользователей, включая дату создания аккаунта, последнего входа и т. д.",
+ "view-history": "Просматривать историю",
+ "view-history_description": "Разрешение на просмотр истории канала",
+ "view-join-code_description": "Разрешение на просмотр кода присоединения канала",
+ "view-joined-room": "Просматривать чаты, к которым присоединился",
+ "view-joined-room_description": "Разрешение на просмотр чатов, к которым сейчас присоединён",
+ "view-l-room": "Просматривать LiveChat чаты",
+ "view-l-room_description": "Разрешение на просмотр LiveChat чатов",
+ "view-livechat-manager": "Просматривать LiveChat Manager",
+ "view-livechat-manager_description": "Разрешение на просмотр других LiveChat Manager",
+ "view-livechat-rooms": "Просматривать LiveChat чаты",
+ "view-livechat-rooms_description": "Разрешение на просмотр других LiveChat чатов",
+ "view-logs": "Просматривать логи",
+ "view-logs_description": "Разрешение на просмотр логов сервера",
+ "view-other-user-channels": "Просматривать публичные чаты, принадлежащие другим пользователям",
+ "view-other-user-channels_description": "Разрешение на просмотр каналов, владельцами которых являются другие пользователи",
+ "view-outside-room": "Посмотреть внешнюю комнату",
+ "view-p-room": "Просматривать закрытые чаты",
+ "view-p-room_description": "Разрешение на просмотр закрытых чатов",
+ "view-privileged-setting": "Просмотр привилегированных настроек",
+ "view-privileged-setting_description": "Разрешение просмотра настроек",
+ "view-room-administration": "Просматривать административную информацию чатов",
+ "view-room-administration_description": "Разрешение на просмотр статистики общих, приватных и личных каналов. Не включает возможность просматривать сообщения в переписке или архивах",
+ "view-statistics": "Просматривать статистику",
+ "view-statistics_description": "Разрешение на просмотр системной статистики, например число пользователей онлайн, ",
+ "view-user-administration": "Просмотр администрирования пользователей",
+ "view-user-administration_description": "Разрешение на частичный просмотр списка других пользователей, которые сейчас в системе. Это разрешение не дает доступа к пользовательской информации из аккаунтов",
+ "View_All": "Смотреть всех участников",
"View_Logs": "Показать лог",
- "View_mode": "Режим просмотра",
- "View_mode_info": "Сколько места сообщений занимают на экране.",
- "Viewing_room_administration": "Администрация Просмотр номера",
+ "View_mode": "Внешний вид сообщений",
+ "View_mode_info": "Сколько места сообщения занимают на экране.",
+ "Viewing_room_administration": "Просмотр администрирования комнаты",
"Visibility": "Видимость",
- "Visible": "Показывать",
+ "Visible": "Видимый",
"Visitor": "Посетитель",
- "Visitor_Info": "Информация для посетителей",
+ "Visitor_Info": "Информация о посетителе",
"Visitor_Navigation": "Посетитель навигации",
"Visitor_page_URL": "URL-адрес страницы посетителя",
- "Visitor_time_on_site": "Время посетителя, проведённое на сайте",
- "Wait_activation_warning": "Прежде чем вы сможете войти в ваш аккаунт, он должен быть активирован администратором.",
+ "Visitor_time_on_site": "Время, проведённое на сайте, посетителем",
+ "Wait_activation_warning": "Прежде чем вы сможете использовать вашу учетную запись, она должна быть активирована администратором.",
+ "Warnings": "Предупреждения",
"We_are_offline_Sorry_for_the_inconvenience": "Мы не в сети. Извините за доставленные неудобства.",
- "We_have_sent_password_email": "На вашу почту было отправлено письмо с инструкциями. Если по каким-то причинам письмо не пришло, попробуйте еще раз и/или напишите нам.",
- "We_have_sent_registration_email": "Все отлично. Осталось только подтвердить регистрацию - письмо выслано на почту. Если что-то пошло не так, попробуйте еще раз и/или напишите нам.",
+ "We_have_sent_password_email": "На вашу электронную почту было отправлено письмо с инструкциями. Если по каким-то причинам письмо не пришло, попробуйте еще раз и/или напишите нам.",
+ "We_have_sent_registration_email": "Чтобы подтвердить вашу регистрацию, мы отправили вам электронное сообщение. Пожалуйста, следуйте инструкциям в этом сообщении. Если вы не получили электронное сообщение, попробуйте ещё раз позже.",
"Webhook_URL": "URL Webhook",
"Webhooks": "Webhooks",
- "WebRTC_Enable_Channel": "Включить для публичных чатов",
+ "WebRTC_Enable_Channel": "Включить для каналов",
"WebRTC_Enable_Direct": "Включить для личных сообщений",
- "WebRTC_Enable_Private": "Включить для приватных чатов",
- "WebRTC_Servers": "Серверы STUN/TURN",
- "WebRTC_Servers_Description": "Список STUN/TURN серверов разделен запятой. Имя пользователя, пароль и порт разрешены в формате `username:password@stun:host:port` или `username:password@turn:host:port`.",
+ "WebRTC_Enable_Private": "Включить для приватных каналов",
+ "WebRTC_Servers": "Серверы STUN/TURN",
+ "WebRTC_Servers_Description": "Список STUN/TURN серверов, разделенных запятой. Имя пользователя, пароль и порт разрешены в формате `username:password@stun:host:port` или `username:password@turn:host:port`.",
+ "Wednesday": "Среда",
"Welcome": "Добро пожаловать, %s .",
"Welcome_to_the": "Добро пожаловать в",
"Why_do_you_want_to_report_question_mark": "Почему вы хотите сообщить?",
"will_be_able_to": "в состоянии",
+ "Would_you_like_to_return_the_inquiry": "Вы хотите вернуть запрос?",
"Yes": "Да",
+ "Yes_archive_it": "Да, архивировать!",
"Yes_clear_all": "Да, удалить все!",
- "Yes_delete_it": "Да, удалить его!",
+ "Yes_delete_it": "Да, удалить!",
"Yes_hide_it": "Да, спрятать!",
"Yes_leave_it": "Да, покинуть!",
- "Yes_mute_user": "Да, заблокировать пользователя!",
+ "Yes_mute_user": "Да, заглушить пользователя!",
"Yes_remove_user": "Да, удалить пользователя!",
+ "Yes_unarchive_it": "Да, разархивировать.",
"You": "Вы",
- "you_are_in_preview_mode_of": "Вы находитесь в режиме предварительного просмотра #__room_name__ ",
+ "you_are_in_preview_mode_of": "Вы находитесь в режиме предварительного просмотра канала #__room_name__ ",
"You_are_logged_in_as": "Вы вошли как",
"You_are_not_authorized_to_view_this_page": "Недостаточно прав для просмотра страницы.",
- "You_can_change_a_different_avatar_too": "Вы можете не принимать аватар, используемый для публикации из интеграции.",
+ "You_can_change_a_different_avatar_too": "Вы можете заменить аватар, используемый в интеграции.",
"You_can_search_using_RegExp_eg": "Искать можно используя RegExp, например:",
- "You_can_use_an_emoji_as_avatar": "Вы также можете использовать emoji в качестве аватара.",
- "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Вы можете использовать webhooks легко интегрировать с LiveChat CRM.",
- "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Вы не можете оставить Livechat комнату. Пожалуйста, используйте кнопку закрытия.",
- "You_have_been_muted": "Вы были заблокированы и не можете говорить в этом чате",
- "You_have_not_verified_your_email": "Вы не подтвердили email.",
+ "You_can_use_an_emoji_as_avatar": "Вы также можете использовать эмодзи в качестве аватара.",
+ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Вы можете использовать webhooks для легкой интеграции Livechat с вашей CRM.",
+ "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Вы не можете покинуть Livechat комнату. Пожалуйста, используйте кнопку закрыть.",
+ "You_have_been_muted": "Вы были заглушены и не можете говорить в этой комнате",
+ "You_have_n_codes_remaining": "У вас__number__ кодов осталось.",
+ "You_have_not_verified_your_email": "Вы не подтвердили ваш адрес электронной почты.",
"You_have_successfully_unsubscribed": "Вы успешно отписаны от нашей почтовой рассылки.",
- "You_need_confirm_email": "Необходимо подтвердить email для входа!",
+ "You_must_join_to_view_messages_in_this_channel": "Вы должны присоединиться, чтобы просматривать сообщения на этом канале",
+ "You_need_confirm_email": "Необходимо подтвердить ваш адрес электронной почты для входа!",
"You_need_install_an_extension_to_allow_screen_sharing": "Для демонстрации экрана вам необходимо установить расширение",
"You_need_to_change_your_password": "Вам необходимо сменить пароль",
"You_need_to_type_in_your_password_in_order_to_do_this": "Для этого действия необходимо ввести пароль!",
- "You_need_to_type_in_your_username_in_order_to_do_this": "Для этого действия необходимо ввести имя пользователя!",
- "You_need_to_verifiy_your_email_address_to_get_notications": "Вам необходимо подтвердить свой email для получения уведомлений",
- "You_need_to_write_something": "Вам нужно написать что-нибудь!",
+ "You_need_to_type_in_your_username_in_order_to_do_this": "Для этого действия необходимо ввести логин!",
+ "You_need_to_verifiy_your_email_address_to_get_notications": "Вам необходимо подтвердить ваш адрес электронной почты для получения уведомлений",
+ "You_need_to_write_something": "Вы должны написать что-нибудь!",
"You_should_inform_one_url_at_least": "Вы должны определить по крайней мере один URL.",
- "You_should_name_it_to_easily_manage_your_integrations": "Стоит указать для простоты управления интеграциями",
+ "You_should_name_it_to_easily_manage_your_integrations": "Стоит указать название для простоты управления вашими интеграциями",
"You_will_not_be_able_to_recover": "Вы не сможете восстановить это сообщение!",
"You_will_not_be_able_to_recover_file": "Восстановить этот файл будет невозможно!",
- "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Вы не можете получать уведомления по email, потому что не подтвердили его.",
- "Your_email_has_been_queued_for_sending": "Ваш email был поставлен в очередь на отправку",
+ "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Вы не можете получать уведомления по электронной почте, потому что не подтвердили ваш адрес электронной почты.",
+ "Your_email_has_been_queued_for_sending": "Ваше электронное сообщение поставлено в очередь на отправку",
"Your_entry_has_been_deleted": "Ваша запись была удалена.",
"Your_file_has_been_deleted": "Ваш файл был удалён.",
- "Your_mail_was_sent_to_s": "Ваше сообщение было отправлено на %s",
- "Your_password_is_wrong": "Неверный пароль!",
- "Your_push_was_sent_to_s_devices": "Ваше push-уведомление было отправлено на % устройств."
-}
\ No newline at end of file
+ "Your_mail_was_sent_to_s": "Ваше сообщение было отправлено на %s",
+ "your_message": "Ваше сообщение",
+ "your_message_optional": "Сообщение (опционально)",
+ "Your_password_is_wrong": "Ваш пароль неверен!",
+ "Your_push_was_sent_to_s_devices": "Оповещение было отправлено на %s устройств."
+}
diff --git a/packages/rocketchat-i18n/i18n/sl-SI.i18n.json b/packages/rocketchat-i18n/i18n/sl-SI.i18n.json
new file mode 100644
index 0000000000000..a8e784cc3e6f4
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/sl-SI.i18n.json
@@ -0,0 +1,7 @@
+{
+ "#channel": "#kanal",
+ "0_Errors_Only": "0 - Samo napake",
+ "1_Errors_and_Information": "1 - Napake in informacije",
+ "@username_message": "@uporabnik ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ ni več __role__ by __user_by__"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-i18n/i18n/sq.i18n.json b/packages/rocketchat-i18n/i18n/sq.i18n.json
index 2789b1173d7f2..cfe1972721e4d 100644
--- a/packages/rocketchat-i18n/i18n/sq.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sq.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Lejo përdoruesit Profilin Change",
"Accounts_AvatarResize": "Ndrysho madhësin e Avatarit",
"Accounts_AvatarSize": "Madhësia e Avatarit",
- "Accounts_AvatarStorePath": "Avatari Storage Path",
- "Accounts_AvatarStoreType": "Avatari Storage Lloji",
"Accounts_BlockedDomainsList": "Blocked Lista Domains",
"Accounts_BlockedDomainsList_Description": "lista të ndara me presje të fushave të bllokuara",
"Accounts_BlockedUsernameList": "Blocked List Emri i përdoruesit",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "E-mail Verifikimi",
"Accounts_EmailVerification_Description": "Sigurohuni që keni cilësimet e duhura SMTP për të përdorur këtë funksion",
"Accounts_Enrollment_Email": "Regjistrimi E-mail",
- "Accounts_Enrollment_Email_Default": " Mire se erdhet ne [Site_Name] Shko tek [Site_URL] dhe të përpiqet të mirë të burimit të hapur chat zgjidhje në dispozicion sot!
",
+ "Accounts_Enrollment_Email_Default": " Mire se erdhet ne [Site_Name] Shko tek [Site_URL] dhe të përpiqet të mirë të burimit të hapur chat zgjidhje në dispozicion sot!
",
"Accounts_Enrollment_Email_Description": "Ju mund të përdorni [name], [fname], [lname] për emrin e plotë të përdoruesit, emrin e parë ose emrin e fundit, respektivisht. Ju mund të përdorni [email] për email të përdoruesit.",
"Accounts_Enrollment_Email_Subject_Default": "Mirë se vini në [Site_Name]",
"Accounts_Iframe_api_method": "Metoda api",
@@ -84,7 +82,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "WordPress Login",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "Password Reset",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "publik",
"Accounts_RegistrationForm_Secret_URL": "URL Secret",
"Accounts_RegistrationForm_SecretURL": "Regjistrimi Form Secret URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Ju duhet të sigurojë një varg të rastit që do të shtohet në URL tuaj e regjistrimit. Shembull: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Ju duhet të sigurojë një varg të rastit që do të shtohet në URL tuaj e regjistrimit. Shembull: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Nevojitet emri për regjistrim",
"Accounts_ShowFormLogin": "Tregojnë formë të bazuar Login",
"Accounts_UseDefaultBlockedDomainsList": "Përdorimi Default Blocked Lista Domains",
"Accounts_UseDNSDomainCheck": "Përdorni DNS Domain Kontrollo",
- "Accounts_UserAddedEmail_Default": " Mire se erdhet ne [Site_Name] Shko tek [Site_URL] dhe të përpiqet të mirë të burimit të hapur chat zgjidhje në dispozicion sot!
Ju mund të identifikoheni duke përdorur email: [email] dhe fjalëkalimin: [password]. Ju mund të kërkohet për të ndryshuar atë pas hyrjes tuaj të parë.",
+ "Accounts_UserAddedEmail_Default": "
Mire se erdhet ne [Site_Name] Shko tek [Site_URL] dhe të përpiqet të mirë të burimit të hapur chat zgjidhje në dispozicion sot!
Ju mund të identifikoheni duke përdorur email: [email] dhe fjalëkalimin: [password]. Ju mund të kërkohet për të ndryshuar atë pas hyrjes tuaj të parë.",
"Accounts_UserAddedEmail_Description": "Ju mund të përdorni placeholders e mëposhtme:
[name], [fname], [lname] për emrin e përdoruesit të plotë, emrin e parë ose emrin e fundit, respektivisht. [email] për email të përdoruesit. [password] për fjalëkalimin e përdoruesit. [Site_Name] dhe [Site_URL] në emër Aplikimit dhe URL respektivisht. ",
"Accounts_UserAddedEmailSubject_Default": "Ju janë shtuar në [Site_Name]",
"Activate": "Aktivizoj",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Kushtet e Shërbimit",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Custom Domain Kërko",
- "LDAP_Custom_Domain_Search_Description": "Një pjesë e JSON që rregullon lidh dhe lidhje info dhe është i formës: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Domain Default",
"LDAP_Description": "LDAP është një bazë të dhënash hierarkike se shumë kompani përdorin për të dhënë shenjë të vetme në - një strukturë për të ndarë një fjalëkalim në mes të vendeve të shumta dhe të shërbimeve. Për informacion të avancuara konfigurimi dhe shembuj, ju lutem konsultoni wiki tonë: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "domain Base",
- "LDAP_Domain_Base_Description": "Plotësisht të kualifikuar nderuar Emri (DN) e një subtree LDAP që ju doni të kërkoni për përdoruesit dhe grupet. Ju mund të shtoni sa më shumë që ju pëlqen; Megjithatë, secili grup duhet të përcaktohen në të njëjtën bazë domain si përdoruesit që i përket. Nëse ju specifikoni grupet e kufizuara të përdoruesve, vetëm përdoruesit që i përkasin këtyre grupeve do të jetë në fushë. Ne ju rekomandojmë që të përcaktojë nivelin e lartë të LDAP pemë tuaj directory si bazë domain dhe përdorimin e kërkimit filtër për të kontrolluar hyrje.",
- "LDAP_Domain_Search_Filter": "Domain Kërko Filter",
- "LDAP_Domain_Search_Filter_Description": "Nëse specifikuara, vetëm përdoruesit që përputhen me këtë filtër do të lejohet të hyni. Nëse nuk është specifikuar filter, të gjithë përdoruesit brenda objektit të bazës së të caktuar domain do të jetë në gjendje të nënshkruajë në. P.sh. për Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. P.sh. për t'OpenLdap (zgjeruar Kërkimi ndeshje) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search Object Category",
- "LDAP_Domain_Search_Object_Category_Description": "* I * objectCategory që identifikojnë përdoruesit tuaj. Lini bosh për * t'OpenLdap *. P.sh. `person`, etj",
- "LDAP_Domain_Search_Object_Class": "Domain Class kerko objekti",
- "LDAP_Domain_Search_Object_Class_Description": "* I * objectclass që identifikojnë përdoruesit tuaj. P.sh. `organizationalPerson`,` user`, `inetOrgPerson`, etj",
- "LDAP_Domain_Search_Password": "Domain Kërko Password",
- "LDAP_Domain_Search_Password_Description": "Fjalëkalimi për përdoruesin e kërkimit domain.",
- "LDAP_Domain_Search_User": "Domain Kërko User",
- "LDAP_Domain_Search_User_Description": "Përdoruesi LDAP që kryen Lookups përdoruesit për të vërtetuar përdoruesit e tjerë, kur ata nënshkruajnë në. Kjo është zakonisht një llogari të shërbimit krijuar posaçërisht për integrime palë të treta. Përdorni një emër plotësisht të kualifikuar, të tilla si 'cn = Administrator, cn = Përdoruesit, dc = Shembull, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Kërko ID User",
- "LDAP_Domain_Search_User_ID_Description": "LDAP atribut që identifikon përdoruesit LDAP që tenton të legalizuara. Kjo fushë duhet të jetë `sAMAccountName` për instalime më të Active Directory, por ajo mund të jetë` uid` për zgjidhje të tjera LDAP, të tilla si t'OpenLdap. Ju mund të përdorni `mail` për të identifikuar përdoruesit me email ose çfarëdo atribut që ju dëshironi. Ju mund të përdorni vlerat e shumta të ndara me presje për të lejuar përdoruesit të identifikoheni duke përdorur identifikuesit të shumta si emrin e përdoruesit ose e-mail.",
+ "LDAP_BaseDN_Description": "Plotësisht të kualifikuar nderuar Emri (DN) e një subtree LDAP që ju doni të kërkoni për përdoruesit dhe grupet. Ju mund të shtoni sa më shumë që ju pëlqen; Megjithatë, secili grup duhet të përcaktohen në të njëjtën bazë domain si përdoruesit që i përket. Nëse ju specifikoni grupet e kufizuara të përdoruesve, vetëm përdoruesit që i përkasin këtyre grupeve do të jetë në fushë. Ne ju rekomandojmë që të përcaktojë nivelin e lartë të LDAP pemë tuaj directory si bazë domain dhe përdorimin e kërkimit filtër për të kontrolluar hyrje.",
+ "LDAP_User_Search_Field_Description": "LDAP atribut që identifikon përdoruesit LDAP që tenton të legalizuara. Kjo fushë duhet të jetë `sAMAccountName` për instalime më të Active Directory, por ajo mund të jetë` uid` për zgjidhje të tjera LDAP, të tilla si t'OpenLdap. Ju mund të përdorni `mail` për të identifikuar përdoruesit me email ose çfarëdo atribut që ju dëshironi. Ju mund të përdorni vlerat e shumta të ndara me presje për të lejuar përdoruesit të identifikoheni duke përdorur identifikuesit të shumta si emrin e përdoruesit ose e-mail.",
+ "LDAP_User_Search_Filter_Description": "Nëse specifikuara, vetëm përdoruesit që përputhen me këtë filtër do të lejohet të hyni. Nëse nuk është specifikuar filter, të gjithë përdoruesit brenda objektit të bazës së të caktuar domain do të jetë në gjendje të nënshkruajë në. P.sh. për Active Directory `memberOf = cn = ROCKET_CHAT, ou = General Groups`. P.sh. për t'OpenLdap (zgjeruar Kërkimi ndeshje) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Përdoruesi LDAP që kryen Lookups përdoruesit për të vërtetuar përdoruesit e tjerë, kur ata nënshkruajnë në. Kjo është zakonisht një llogari të shërbimit krijuar posaçërisht për integrime palë të treta. Përdorni një emër plotësisht të kualifikuar, të tilla si 'cn = Administrator, cn = Përdoruesit, dc = Shembull, dc = com`.",
"LDAP_Enable": "mundësoj",
"LDAP_Enable_Description": "Përpjekje për të shfrytëzuar LDAP për autentikim.",
"LDAP_Encryption": "encryption",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Të mbajtur të dhënat e përdoruesit në sync me server në hyrje (p.sh: emri, email).",
"LDAP_Sync_User_Data_FieldMap": "User Data Map Field",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfiguro si fusha e llogarisë përdoruesit (si email) janë të populluar nga një rekord në LDAP (sapo gjetur). Si një shembull, `{\" cn \":\" Emri \",\" postë \":\" email \"} 'do të zgjedhë emrin e një personi njerëzor lexueshëm nga atribut cn dhe adresën e tyre nga postës atribut. Fushat e vlefshme përfshijnë `name`, dhe` email`.",
- "LDAP_Sync_Users": "Përdoruesit Sync",
"LDAP_Test_Connection": "Test Connection",
"LDAP_Unique_Identifier_Field": "Unique Identifier Field",
"LDAP_Unique_Identifier_Field_Description": "Cilën fushë do të përdoret për të lidhur përdoruesit LDAP dhe përdoruesit Rocket.Chat. Ju mund të informojë vlerat e shumta të ndara me presje për të përpiqen për të marrë vlerën prej rekord LDAP. Vlera e parazgjedhur është 'objectGUID, ibm-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Përdorni Custom Domain Kërko",
- "LDAP_Use_Custom_Domain_Search_Description": "Shkruar vetë filtrin tuaj për të kërkuar përdoruesit në server LDAP.",
"LDAP_Username_Field": "Username Field",
"LDAP_Username_Field_Description": "Cilën fushë do të përdoret si * emrin e përdoruesit * për përdoruesit e rinj. Lini bosh për të përdorur emrin e përdoruesit të informuar në faqen e identifikimit. Ju mund të përdorni tags template shumë, si `#{givenName}.#{sn}`. Vlera e parazgjedhur është `sAMAccountName`.",
"Leave_Group_Warning": "Jeni te sigurte qe doni te largohet nga grupi \" %s\"?",
@@ -750,6 +733,7 @@
"Nothing": "asgjë",
"Nothing_found": "Asgjë për të gjetur",
"Notifications": "Njoftime",
+ "Notifications_Sound_Volume": "Vëllimi i tingullit të njoftimeve",
"Notify_all_in_this_room": "Njoftojë të gjithë në këtë dhomë",
"Num_Agents": "# Agents",
"Number_of_messages": "Numri i mesazheve",
@@ -1038,19 +1022,19 @@
"The_user_wont_be_able_to_type_in_s": "Ky përdorues nuk do të jetë në gjendje të shkruani në %s",
"Theme": "temë",
"theme-color-content-background-color": "Përmbajtja Background Color",
+ "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
+ "theme-color-info-font-color": "Info Font Color",
+ "theme-color-link-font-color": "Link Font Color",
"theme-color-primary-background-color": "Primar Background Color",
"theme-color-primary-font-color": "Primar Font Color",
"theme-color-secondary-background-color": "Mesme Background Color",
"theme-color-secondary-font-color": "Mesme Font Color",
- "theme-color-tertiary-background-color": "Terciar Background Color",
- "theme-color-tertiary-font-color": "Terciar Font Color",
- "theme-color-link-font-color": "Link Font Color",
- "theme-color-info-font-color": "Info Font Color",
- "theme-color-custom-scrollbar-color": "Custom Scrollbar Color",
"theme-color-status-away": "Away Status Color",
"theme-color-status-busy": "Busy Status Color",
"theme-color-status-offline": "Offline Status Color",
"theme-color-status-online": "Online Status Color",
+ "theme-color-tertiary-background-color": "Terciar Background Color",
+ "theme-color-tertiary-font-color": "Terciar Font Color",
"theme-color-unread-notification-color": "Palexuar Njoftimet Color",
"theme-custom-css": "Custom CSS",
"There_are_no_agents_added_to_this_department_yet": "Nuk ka agjentë të shtuar në këtë departament ende.",
@@ -1221,4 +1205,4 @@
"Your_mail_was_sent_to_s": "maili juaj u dërgua në %s",
"Your_password_is_wrong": "Fjalëkalimi juaj është e gabuar!",
"Your_push_was_sent_to_s_devices": "shtytje juaj u dërgua në pajisjet %s"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/sr.i18n.json b/packages/rocketchat-i18n/i18n/sr.i18n.json
index 86b6a9570fcb4..967a110e385d5 100644
--- a/packages/rocketchat-i18n/i18n/sr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sr.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "Дозволите Усер Профиле Цханге",
"Accounts_AvatarResize": "ресизе Аватари",
"Accounts_AvatarSize": "аватар величина",
- "Accounts_AvatarStorePath": "Аватар складиштења Пут",
- "Accounts_AvatarStoreType": "Аватар Стораге Типе:",
"Accounts_BlockedDomainsList": "Блокиран доменов",
"Accounts_BlockedDomainsList_Description": "Зарезом одвојена листа блокираних домена",
"Accounts_BlockedUsernameList": "Блокиран име Списак",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "Е-маил Верификација",
"Accounts_EmailVerification_Description": "Направи сте сигурни имали исправне поставке СМТП да користе ову функцију",
"Accounts_Enrollment_Email": "Упис е-маил",
- "Accounts_Enrollment_Email_Default": " Добродошли у [Site_Name] Иди на [Site_URL] и покушати решење најбољи опен соурце цхат доступан данас!
",
+ "Accounts_Enrollment_Email_Default": " Добродошли у [Site_Name] Иди на [Site_URL] и покушати решење најбољи опен соурце цхат доступан данас!
",
"Accounts_Enrollment_Email_Description": "Можете користити [name], [fname], [lname] за пуно име корисника, имену или презимену, респективно. Можете користити [email] е-поште корисника.",
"Accounts_Enrollment_Email_Subject_Default": "Велцоме то [Site_Name]",
"Accounts_Iframe_api_method": "апи Метод",
@@ -100,7 +98,7 @@
"Accounts_ShowFormLogin": "Схов образац заснован Пријава",
"Accounts_UseDefaultBlockedDomainsList": "Употреба Уобичајено блокираних домена Листа",
"Accounts_UseDNSDomainCheck": "Користи ДНС Домаин Цхецк",
- "Accounts_UserAddedEmail_Default": " Добродошли у [Site_Name] Иди на [Site_URL] и покушати решење најбољи опен соурце цхат доступан данас!
Можете да се пријавите користећи свој емаил: [email] и лозинку: [password]. Можда ће бити потребно да га променимо после прве пријаве.",
+ "Accounts_UserAddedEmail_Default": "
Добродошли у [Site_Name] Иди на [Site_URL] и покушати решење најбољи опен соурце цхат доступан данас!
Можете да се пријавите користећи свој емаил: [email] и лозинку: [password]. Можда ће бити потребно да га променимо после прве пријаве.",
"Accounts_UserAddedEmail_Description": "Можете користити следеће симболе:
[name], [fname], [lname] за пуно име корисника, имену или презимену, респективно. [email] е-поште корисника. [password] за лозинку корисника. [Site_Name] и [Site_URL] за апликације Име и УРЛ респективно. ",
"Accounts_UserAddedEmailSubject_Default": "Додати сте у [Site_Name]",
"Activate": "Активирати",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "Услови коришћења",
"LDAP": "ЛДАП",
"LDAP_CA_Cert": "ЦА Церт",
- "LDAP_Custom_Domain_Search": "Цустом Претрага домена",
- "LDAP_Custom_Domain_Search_Description": "Парче ЈСОН који управља везују и повезивање информација и има облик: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Уобичајено Домен",
"LDAP_Description": "ЛДАП је хијерархијска база података која многе компаније користе да би обезбедили јединствени знак на - објекат за размену једну лозинку између више локација и услуга. За напредне информације о конфигурацији и примере, погледајте наш вики: хттпс://гитхуб.цом/РоцкетЦхат/Роцкет.Цхат/вики/ЛДАП-Аутхентицатион.",
- "LDAP_Domain_Base": "domen База",
- "LDAP_Domain_Base_Description": "Потпуно квалификовани препознатљивог имена (ДН) ЛДАП подстабла желите да тражите кориснике и групе. Можете додати колико год желите; Међутим, свака група мора бити дефинисана у истој бази домена као и корисницима који јој припадају. Ако наведете ограничене групе корисника, само корисници који припадају тим групама ће бити у обиму. Препоручујемо да наведете највиши ниво вашег ЛДАП стабла именика као домена базу и користите филтер за претрагу за контролу приступа.",
- "LDAP_Domain_Search_Filter": "Домен Тражи филтер",
- "LDAP_Domain_Search_Filter_Description": "Ако наведено, само корисници који одговарају овог филтера ће бити дозвољено да се пријавите. Ако није наведен филтера, сви корисници у оквиру наведеног домена базе ће моћи да се пријавите. Нпр за Ацтиве Дирецтори `мемберОф = ЦН = РОЦКЕТ_ЦХАТ, или = генерал Гроупс`. Нпр за ОпенЛДАП (прошириви меч претрага) 'или: ДН: = РОЦКЕТ_ЦХАТ`.",
- "LDAP_Domain_Search_Object_Category": "Домен Претрага Предмет Категорија",
- "LDAP_Domain_Search_Object_Category_Description": "Тхе * објецтЦатегори * да идентификују своје кориснике. Оставите празно за * ОпенЛДАП *. Нпр `персон`, итд",
- "LDAP_Domain_Search_Object_Class": "Домен Класа Претрага Предмет",
- "LDAP_Domain_Search_Object_Class_Description": "Тхе * објецтЦласс * да идентификују своје кориснике. Нпр `организатионалПерсон`,` усер`, `инетОргПерсон`, итд",
- "LDAP_Domain_Search_Password": "Домен Тражи Лозинка",
- "LDAP_Domain_Search_Password_Description": "Лозинка за корисника претраживање домена.",
- "LDAP_Domain_Search_User": "Домен Тражи Корисник",
- "LDAP_Domain_Search_User_Description": "ЛДАП корисник који обавља корисника лоокупс за проверу идентитета друге кориснике када се пријавите. Ово је типично рачун сервис специјално направљена за треће стране интеграције. Користите пуно име, као што су `цн = Администратор, ЦН = Усерс, ДЦ = пример, ДЦ = цом`.",
- "LDAP_Domain_Search_User_ID": "Домен Тражи кориснику ИД",
- "LDAP_Domain_Search_User_ID_Description": "ЛДАП атрибут који идентификује корисника ЛДАП који покушавају проверу идентитета. Ово поље треба да буде `сАМАццоунтНаме` за већину Ацтиве Дирецтори инсталацијама, али може бити` уид` за друге ЛДАП решења, као што је ОпенЛДАП. Можете користити `маил` идентификују кориснике путем е-маила или како атрибут хоћеш. Можете користити више вредности одвојене зарезом да омогући корисницима да се пријавите користећи више идентификаторе као што су корисничко име или е-маилом.",
+ "LDAP_BaseDN_Description": "Потпуно квалификовани препознатљивог имена (ДН) ЛДАП подстабла желите да тражите кориснике и групе. Можете додати колико год желите; Међутим, свака група мора бити дефинисана у истој бази домена као и корисницима који јој припадају. Ако наведете ограничене групе корисника, само корисници који припадају тим групама ће бити у обиму. Препоручујемо да наведете највиши ниво вашег ЛДАП стабла именика као домена базу и користите филтер за претрагу за контролу приступа.",
+ "LDAP_User_Search_Field_Description": "ЛДАП атрибут који идентификује корисника ЛДАП који покушавају проверу идентитета. Ово поље треба да буде `сАМАццоунтНаме` за већину Ацтиве Дирецтори инсталацијама, али може бити` уид` за друге ЛДАП решења, као што је ОпенЛДАП. Можете користити `маил` идентификују кориснике путем е-маила или како атрибут хоћеш. Можете користити више вредности одвојене зарезом да омогући корисницима да се пријавите користећи више идентификаторе као што су корисничко име или е-маилом.",
+ "LDAP_User_Search_Filter_Description": "Ако наведено, само корисници који одговарају овог филтера ће бити дозвољено да се пријавите. Ако није наведен филтера, сви корисници у оквиру наведеног домена базе ће моћи да се пријавите. Нпр за Ацтиве Дирецтори `мемберОф = ЦН = РОЦКЕТ_ЦХАТ, или = генерал Гроупс`. Нпр за ОпенЛДАП (прошириви меч претрага) 'или: ДН: = РОЦКЕТ_ЦХАТ`.",
+ "LDAP_Authentication_UserDN_Description": "ЛДАП корисник који обавља корисника лоокупс за проверу идентитета друге кориснике када се пријавите. Ово је типично рачун сервис специјално направљена за треће стране интеграције. Користите пуно име, као што су `цн = Администратор, ЦН = Усерс, ДЦ = пример, ДЦ = цом`.",
"LDAP_Enable": "омогућити",
"LDAP_Enable_Description": "Покушај да се користе ЛДАП за потврду идентитета.",
"LDAP_Encryption": "шифровање",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "Имајте корисничких података у синхронизацију са сервером на логин (нпр: име, емаил).",
"LDAP_Sync_User_Data_FieldMap": "Корисник поља података Карта",
"LDAP_Sync_User_Data_FieldMap_Description": "Конфигуришете како се поља кориснички налог (као поште) насељено од рекордних у ЛДАП (једном фоунд). Као пример, `{\" ЦН \":\" Име \",\" пошта \":\" е \"}` ће изабрати човеку читљиву име особе из цн атрибута, и њихово емаил од атрибута поште. Поља која укључују `наме`, и` емаил`.",
- "LDAP_Sync_Users": "Синц корисника",
"LDAP_Test_Connection": "тест везе",
"LDAP_Unique_Identifier_Field": "Јединствени идентификатор Поље",
"LDAP_Unique_Identifier_Field_Description": "Који поље ће се користити за повезивање корисника ЛДАП и корисника Роцкет.Цхат. Можете обавестити више вредности одвојене зарезом у покушају да добије вредност од ЛДАП записа. Дефаулт вредност је `објецтГУИД, ИБМ-ентриУУИД, ГУИД, доминоУНИД, нсуникуеИд, уидНумбер`",
- "LDAP_Use_Custom_Domain_Search": "Користити прилагођени домен Сеарцх",
- "LDAP_Use_Custom_Domain_Search_Description": "Напиши свој филтер за претрагу корисника у ЛДАП серверу.",
"LDAP_Username_Field": "корисничко име polje",
"LDAP_Username_Field_Description": "Који поље ће се користити као * корисничко име * за нове кориснике. Оставите празно да користи име информисани на пријаву. Можете користити темплате ознаке такође, као `#{givenName}.#{sn}`. Дефаулт вредност је `сАМАццоунтНаме`.",
"Leave_Group_Warning": "Да ли сте сигурни да желите да напустите групу \"% с\"?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "Корисник неће бити у могућности да уносите у% с",
"Theme": "тема",
"theme-color-content-background-color": "Садржај Боја позадине",
+ "theme-color-custom-scrollbar-color": "Цустом Сцроллбар Боја",
+ "theme-color-info-font-color": "Инфо Боја фонта",
+ "theme-color-link-font-color": "Линк Боја фонта",
"theme-color-primary-background-color": "Примарна Боја позадине",
"theme-color-primary-font-color": "Примарна Боја фонта",
"theme-color-secondary-background-color": "Секундарна Боја позадине",
"theme-color-secondary-font-color": "Секундарна Боја фонта",
- "theme-color-tertiary-background-color": "Терцијарни Боја позадине",
- "theme-color-tertiary-font-color": "Терцијарни Боја фонта",
- "theme-color-link-font-color": "Линк Боја фонта",
- "theme-color-info-font-color": "Инфо Боја фонта",
- "theme-color-custom-scrollbar-color": "Цустом Сцроллбар Боја",
"theme-color-status-away": "Гост статус Боја",
"theme-color-status-busy": "Буси статус Боја",
"theme-color-status-offline": "Оффлине статус Боја",
"theme-color-status-online": "Онлине статус Боја",
+ "theme-color-tertiary-background-color": "Терцијарни Боја позадине",
+ "theme-color-tertiary-font-color": "Терцијарни Боја фонта",
"theme-color-unread-notification-color": "Непрочитану Обавештења Боја",
"theme-custom-css": "цустом ЦСС",
"There_are_no_agents_added_to_this_department_yet": "Нема додају у овом одељењу још агенти.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "Ваш маил је послат на% с",
"Your_password_is_wrong": "Ваша лозинка није у реду!",
"Your_push_was_sent_to_s_devices": "Ваш притиском је послат на% с уређајима"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/sv.i18n.json b/packages/rocketchat-i18n/i18n/sv.i18n.json
index 0415821218655..4d7dccb0ef01a 100644
--- a/packages/rocketchat-i18n/i18n/sv.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sv.i18n.json
@@ -1,65 +1,71 @@
{
- "0_Errors_Only": "Endast fel - 0",
+ "#channel": "#kanal",
+ "0_Errors_Only": "0 - Endast fel",
"1_Errors_and_Information": "1 - Fel och information",
- "2_Erros_Information_and_Debug": "2 - erros, information och felsöknings",
+ "2_Erros_Information_and_Debug": "2 - Fel, information och felsökning",
"403": "Förbjuden",
- "500": "internt serverfel",
- "__username__is_no_longer__role__defined_by__user_by_": "__username__ är inte längre __role__, genom __user_by__",
- "__username__was_set__role__by__user_by_": "__username__ sattes __role__ genom __user_by__",
+ "500": "Internt serverfel",
+ "@username": "@användarnamn",
+ "@username_message": "@användarnamn ",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ är inte längre __role__, av __user_by__",
+ "__username__was_set__role__by__user_by_": "__username__ sattes __role__ av __user_by__",
"Accept": "Acceptera",
- "Access_not_authorized": "Tillgång som inte godkänts",
- "Access_Token_URL": "Tillgång Token URL",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Acceptera förfrågan om inkommande livechatt även om ingen agent är online",
+ "Accept_with_no_online_agents": "Acceptera utan agenter online",
+ "Access_not_authorized": "Tillträde är ej tillåtet",
+ "Access_Token_URL": "Tillgång till Token URL",
"Accessing_permissions": "Åtkomstbehörigheter",
- "Account_SID": "konto SID",
+ "Account_SID": "Konto SID",
"Accounts": "Konton",
"Accounts_AllowDeleteOwnAccount": "Tillåt användare att radera egna konton",
- "Accounts_AllowedDomainsList": "Tillåtet Domäner Lista",
- "Accounts_AllowedDomainsList_Description": "Kommaseparerad list över tillåtna domäner",
+ "Accounts_AllowedDomainsList": "Tillåten Domänlista",
+ "Accounts_AllowedDomainsList_Description": "Kommaseparerad lista över tillåtna domäner",
"Accounts_AllowEmailChange": "Tillåt byte av e-postadress",
"Accounts_AllowPasswordChange": "Tillåt byte av lösenord",
- "Accounts_AllowUserAvatarChange": "Tillåt byte av användaravatar",
- "Accounts_AllowUsernameChange": "Tillåt användarnamn byte",
+ "Accounts_AllowUserAvatarChange": "Tillåt byte av användarens avatar",
+ "Accounts_AllowUsernameChange": "Tillåt byte av användarnamn",
"Accounts_AllowUserProfileChange": "Tillåt byte av användarprofil",
"Accounts_AvatarResize": "Ändra storlek på avatarer",
"Accounts_AvatarSize": "Storlek på avatar",
- "Accounts_AvatarStorePath": "Avatar Storage Path",
- "Accounts_AvatarStoreType": "Avatar Storage Type",
- "Accounts_BlockedDomainsList": "Blockerade domäner Lista",
+ "Accounts_BlockedDomainsList": "Lista över blockerade domäner",
"Accounts_BlockedDomainsList_Description": "Kommaseparerad lista över blockerade domäner",
- "Accounts_BlockedUsernameList": "Blockerad Användarnamn Lista",
+ "Accounts_BlockedUsernameList": "Användarlista över blockerade",
"Accounts_BlockedUsernameList_Description": "Kommaseparerad lista över blockerade användarnamn (skiftlägeskänsligt)",
"Accounts_denyUnverifiedEmail": "Neka okontrollerade e-postadresser",
"Accounts_EmailVerification": "E-postverifiering",
"Accounts_EmailVerification_Description": "Se till att du har korrekta SMTP-inställningar för att använda denna funktion",
- "Accounts_Enrollment_Email": "Inskrivning E-post",
- "Accounts_Enrollment_Email_Default": " Välkommen till [Site_Name] Gå till [Site_URL] och prova bäst öppen källkod chatt lösning som finns idag!
",
- "Accounts_Enrollment_Email_Description": "Du kan använda [namn], [fname], [lname] för användarens fullständiga namn, förnamn eller efternamn, respektive. Du kan använda [email] för användarens e-post.",
+ "Accounts_Enrollment_Email": "Skriv i e-post",
+ "Accounts_Enrollment_Email_Default": " Välkommen till [Site_Name] Gå till [Site_URL] och prova bästa chatt lösning på öppen källkod som finns idag!
",
+ "Accounts_Enrollment_Email_Description": "Du kan använda [namn], [fname], [lname] för användarens fullständiga namn, förnamn eller efternamn, respektive. Du kan använda [email] för användarens e-post.",
"Accounts_Enrollment_Email_Subject_Default": "Välkommen till [Site_Name]",
- "Accounts_Iframe_api_method": "api Metod",
- "Accounts_Iframe_api_url": "api webbadress",
+ "Accounts_ForgetUserSessionOnWindowClose": "Glöm bort användarsession när fönstret stängs ner",
+ "Accounts_Iframe_api_method": "Api Metod",
+ "Accounts_Iframe_api_url": "API webbadress",
"Accounts_iframe_enabled": "Aktiverad",
"Accounts_iframe_url": "iframe Url",
- "Accounts_LoginExpiration": "Logga Utgångs i dagar",
+ "Accounts_LoginExpiration": "Utgångsdagar för inloggning",
"Accounts_ManuallyApproveNewUsers": "Godkänn nya användare manuellt",
- "Accounts_OAuth_Custom_Authorize_Path": "tillåta Path",
- "Accounts_OAuth_Custom_Button_Color": "knappfärg",
- "Accounts_OAuth_Custom_Button_Label_Color": "Knapp Textfärg",
- "Accounts_OAuth_Custom_Button_Label_Text": "Button Text",
+ "Accounts_OAuth_Custom_Authorize_Path": "Tillåt sökväg",
+ "Accounts_OAuth_Custom_Button_Color": "Knappfärg",
+ "Accounts_OAuth_Custom_Button_Label_Color": "Textfärg på knapp",
+ "Accounts_OAuth_Custom_Button_Label_Text": "Knapptext",
"Accounts_OAuth_Custom_Enable": "Aktivera",
"Accounts_OAuth_Custom_id": "ID",
- "Accounts_OAuth_Custom_Identity_Path": "identitet Path",
- "Accounts_OAuth_Custom_Login_Style": "Logga in Style",
- "Accounts_OAuth_Custom_Secret": "Hemlighet",
- "Accounts_OAuth_Custom_Token_Path": "token Path",
- "Accounts_OAuth_Custom_Token_Sent_Via": "Token Sent Via",
+ "Accounts_OAuth_Custom_Identity_Path": "Sökväg för identitet",
+ "Accounts_OAuth_Custom_Login_Style": "Stil på inloggning",
+ "Accounts_OAuth_Custom_Merge_Users": "Slå samman användare",
+ "Accounts_OAuth_Custom_Secret": "Hemlig",
+ "Accounts_OAuth_Custom_Token_Path": "Sökväg Token",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Token sänd via",
+ "Accounts_OAuth_Custom_Username_Field": "Fält för användarnamn",
"Accounts_OAuth_Facebook": "Facebook-inloggning",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook App-ID",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
"Accounts_OAuth_Github": "OAuth Aktiverad",
- "Accounts_OAuth_Github_callback_url": "Github återuppringning URL",
- "Accounts_OAuth_GitHub_Enterprise": "OAuth Enabled",
- "Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub Enterprise återuppringning URL",
+ "Accounts_OAuth_Github_callback_url": "Github Callback URL",
+ "Accounts_OAuth_GitHub_Enterprise": "OAuth Aktiverad",
+ "Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub Enterprise Callback URL",
"Accounts_OAuth_GitHub_Enterprise_id": "klient-ID",
"Accounts_OAuth_GitHub_Enterprise_secret": "klienthemligheten",
"Accounts_OAuth_Github_id": "Klient-ID",
@@ -85,7 +91,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Secret",
"Accounts_OAuth_Wordpress": "Word Login",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress återuppringning URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress återuppringning URL",
"Accounts_OAuth_Wordpress_id": "Word Id",
"Accounts_OAuth_Wordpress_secret": "Word Secret",
"Accounts_PasswordReset": "Nollställ lösenord",
@@ -96,80 +102,92 @@
"Accounts_RegistrationForm_Public": "Offentlig",
"Accounts_RegistrationForm_Secret_URL": "hemliga URL",
"Accounts_RegistrationForm_SecretURL": "Anmälningsblankett Secret URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Du måste ange en slumpmässig sträng som kommer att läggas till din registrering URL. Exempel: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Du måste ange en slumpmässig sträng som kommer att läggas till din registrerings URL. Exempel: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Kräv namn för registrering",
- "Accounts_ShowFormLogin": "Visa form baserade logga",
- "Accounts_UseDefaultBlockedDomainsList": "Använd standard Blockerad domäner Lista",
+ "Accounts_ShowFormLogin": "Visa formbaserad inloggning",
+ "Accounts_UseDefaultBlockedDomainsList": "Använd standardlista för blockerade domäner",
"Accounts_UseDNSDomainCheck": "Använd DNS Domain Check",
- "Accounts_UserAddedEmail_Default": " Välkommen till [Site_Name] Gå till [Site_URL] och prova bäst öppen källkod chatt lösning som finns idag!
Du kan logga in med din e-post: [email] och lösenord: [password]. Du kan bli tvungen att ändra den efter första inloggning.",
+ "Accounts_UserAddedEmail_Default": "
Välkommen till [Site_Name] Gå till [Site_URL] och prova den bästa öppen källkod chattlösningen som finns idag!
Du kan logga in med din e-post: [email] och lösenord: [password]. Du kan bli tvungen att ändra den efter första inloggning.",
"Accounts_UserAddedEmail_Description": "Du kan använda följande platsmarkörer:
[name], [fname], [lname] för användarens fullständiga namn, förnamn eller efternamn, respektive. [email] för användarens e-post. [password] för användarens lösenord. [Site_Name] och [Site_URL] för Programnamn och webbadress respektive. ",
"Accounts_UserAddedEmailSubject_Default": "Du har lagts till [Site_Name]",
"Activate": "Aktivera",
"Activity": "Aktivitet",
- "Add": "Lägg till",
- "Add_agent": "lägga agent",
+ "Add": "Skapa",
+ "add-user": "Lägg till användare",
+ "Add_agent": "Skapa agent",
"Add_custom_oauth": "Lägg till anpassad oauth",
- "Add_manager": "Lägg manager",
- "Add_user": "Lägg till användare",
- "Add_User": "Lägg till användare",
- "Add_users": "Lägg till användare",
+ "Add_Domain": "Lägg till domän",
+ "Add_files_from": "Lägg till filer från",
+ "Add_manager": "Skapa manager",
+ "Add_Role": "Lägg till roll",
+ "Add_user": "Skapa användare",
+ "Add_User": "Skapa Användare",
+ "Add_users": "Skapa användare",
"Adding_OAuth_Services": "Sätta OAuth Tjänster",
"Adding_permission": "Lägga till tillstånd",
- "Adding_user": "Lägga användare",
+ "Adding_user": "Lägga till användare",
"Additional_emails": "Ytterligare e-post",
"Additional_Feedback": "Ytterligare feedback",
"Administration": "Administrering",
- "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Efter OAuth2 autentisering, kommer användarna att omdirigeras till den här webbadressen",
- "Agent_added": "medel som tillsätts",
- "Agent_removed": "medlet avlägsnades",
+ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "Efter OAuth2 autentisering kommer användarna att omdirigeras till den här webbadressen",
+ "Agent": "Agent",
+ "Agent_added": "Agent tillagd",
+ "Agent_removed": "Agent borttagen",
"Alias": "Alias",
+ "Alias_Format": "Alias format",
"All": "Alla",
"All_channels": "Alla kanaler",
- "All_logs": "alla loggar",
+ "All_logs": "Alla loggar",
"All_messages": "Alla meddelanden",
- "Allow_Invalid_SelfSigned_Certs": "Tillåt Ogiltig självsignerat Cert",
- "Allow_Invalid_SelfSigned_Certs_Description": "Tillåt ogiltiga och självsignerade SSL-certifikat är för länk validering och förhandsvisningar.",
- "Analytics_features_enabled": "funktioner aktiverade",
+ "Allow_Invalid_SelfSigned_Certs": "Tillåt ogiltiga självsignerade certifikat",
+ "Allow_Invalid_SelfSigned_Certs_Description": "Tillåt ogiltiga och självsignerade SSL-certifikat är för länkvalidering och förhandsvisningar.",
+ "Always_open_in_new_window": "Öppna alltid i nytt fönster",
+ "Analytics_features_enabled": "Aktiverade funktioner",
"Analytics_features_messages_Description": "Spår anpassade händelser i samband med åtgärder en användare gör på meddelanden.",
"Analytics_features_rooms_Description": "Spår anpassade händelser i samband med åtgärder på en kanal eller grupp (skapa, lämna, ta bort).",
"Analytics_features_users_Description": "Spår anpassade händelser i samband med åtgärder som rör användare (lösenordsåterställning gånger, profilbild förändring, etc).",
+ "Analytics_Google": "Google Analytics",
"and": "och",
"And_more": "Och mer __length __",
"Animals_and_Nature": "Djur & Natur",
"API": "API",
"API_Analytics": "Analytics",
- "API_Embed": "Inbäddad",
+ "API_Embed": "Förhandsgranskning av inbäddade länkar",
"API_EmbedDisabledFor": "Inaktivera Bädda för användare",
"API_EmbedDisabledFor_Description": "Kommaseparerad lista över användarnamn",
"API_EmbedIgnoredHosts": "Bädda Ignorerade Värdar",
"API_EmbedIgnoredHosts_Description": "Kommaseparerad lista av värdar eller CIDR-adresser, t.ex.. localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
- "API_EmbedSafePorts": "säkra portar",
- "API_EmbedSafePorts_Description": "Kommaseparerad lista över hamnar tillåts för förhandsgranskning.",
- "API_GitHub_Enterprise_URL": "serveradress",
+ "API_EmbedSafePorts": "Säkra portar",
+ "API_EmbedSafePorts_Description": "Kommaseparerad lista över tillåtna portar för förhandsgranskning.",
+ "API_GitHub_Enterprise_URL": "Serveradress",
"API_GitHub_Enterprise_URL_Description": "Exempel: http://domain.com (exklusive snedstreck)",
"API_Gitlab_URL": "GitLab URL",
"API_Token": "API Token",
- "API_User_Limit": "Användar Gräns för att lägga alla Användare till kanal",
- "API_Wordpress_URL": "Wordpress URL",
+ "API_User_Limit": "Användar Gräns för att lägga alla Användare till kanal",
+ "API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Key",
- "Apiai_Language": "Api.ai Language",
+ "Apiai_Language": "Api.ai Språk",
"Appearance": "Utseende",
"Application_added": "Applikation tillagd",
"Application_Name": "Applikationsnamn",
- "Application_updated": "Application uppdaterad",
+ "Application_updated": "Applikation uppdaterad",
"Apply_and_refresh_all_clients": "Tillämpa och uppdatera alla klienter",
- "Archive": "arkiv",
+ "Archive": "Arkiv",
+ "archive-room": "Arkivera Rum",
"are_also_typing": "skriver också",
"are_typing": "skriver",
"Are_you_sure": "Är du säker?",
- "Are_you_sure_you_want_to_delete_your_account": "Är du säker att du vill radera ditt konto?",
+ "Are_you_sure_you_want_to_delete_your_account": "Är du säker på att du vill radera ditt konto?",
+ "Assign_admin": "Tilldela administratör",
"at": "på",
"Attachment_File_Uploaded": "Uppladdad fil",
+ "Audio_message": "Ljudmeddelande",
"Auth_Token": "Auth Token",
"Author": "Författare",
"Authorization_URL": "URL-auktorisering",
"Authorize": "Godkänn",
- "Auto_Load_Images": "Ladda bilder automatiskt",
+ "Auto_Load_Images": "Hämta bilder automatiskt",
+ "Auto_Translate": "Automatisk översättning",
"AutoLinker_Email": "AutoLinker E",
"AutoLinker_Phone": "AutoLinker Phone",
"AutoLinker_Phone_Description": "Automatiskt kopplade till telefonnummer. t.ex. `(123) 456-7890`",
@@ -179,12 +197,13 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD adresser",
"AutoLinker_Urls_www": "AutoLinker \"www\" webbadresser",
"AutoLinker_UrlsRegExp": "AutoLinker URL reguljärt uttryck",
+ "Automatic_Translation": "Automatisk översättning",
"Available": "Tillgängliga",
- "Available_agents": "tillgängliga medel",
+ "Available_agents": "Tillgängliga agenter",
"Avatar": "Avatar",
"Avatar_changed_successfully": "Avataren har ändrats",
"Avatar_URL": "Webbadress för avatar",
- "Avatar_url_invalid_or_error": "Denna webbadress är ogiltig eller inte tillgänglig. Försök igen, men med en annan webbadress.",
+ "Avatar_url_invalid_or_error": "Denna webbadress är ogiltig eller inte tillgänglig. Försök igen med en annan webbadress.",
"away": "borta",
"Away": "Borta",
"away_female": "borta",
@@ -193,11 +212,16 @@
"Away_male": "Borta",
"Back": "Tillbaka",
"Back_to_applications": "Tillbaka till applikationer",
+ "Back_to_chat": "Tillbaka till chatten",
"Back_to_integrations": "Tillbaka till integrationer",
"Back_to_login": "Tillbaka till inloggningen",
"Back_to_permissions": "Tillbaka till tillstånd",
+ "Backup_codes": "Backupkoder",
+ "ban-user": "Banna Användare",
+ "Block_User": "Blockera användare",
"Body": "Kropp",
"bold": "fetstil",
+ "BotHelpers_userFields": "Användarfält",
"Branch": "Gren",
"busy": "upptagen",
"Busy": "Upptagen",
@@ -209,107 +233,150 @@
"Cancel": "Avbryt",
"Cancel_message_input": "Avbryta",
"Cannot_invite_users_to_direct_rooms": "Det går inte att bjuda in användare att styra rum",
+ "CAS_enabled": "Aktiverad",
+ "CAS_Sync_User_Data_Enabled": "Synkronisera alltid användardata",
+ "CAS_version": "CAS Version",
"CDN_PREFIX": "CDN Prefix",
"Certificates_and_Keys": "Certifikat och nycklar",
- "Changing_email": "ändra e",
+ "Change_Room_Type": "Ändra rumstyp",
+ "Changing_email": "Ändra e-post",
+ "channel": "kanal",
"Channel": "Kanal",
"Channel_already_exist": "Kanalens #% s \"finns redan.",
+ "Channel_already_exist_static": "Kanalen finns redan.",
"Channel_already_Unarchived": "Kanal med namnet '#% s` är redan i Hämtad från arkiv tillstånd",
"Channel_Archived": "Kanal med namnet '#% s` har arkiverats framgångsrikt",
"Channel_doesnt_exist": "Kanalen `#%s`existerar inte.",
+ "Channel_name": "Kanalnamn",
"Channel_Unarchived": "Kanal med namnet '#% s` har avarkiverats framgångsrikt",
"Channels": "Kanaler",
- "Channels_list": "Lista över offentliga kanaler",
- "Chat_button": "chatt knapp",
- "Chat_closed": "chat stängd",
- "Chat_closed_successfully": "Chat stängd framgångsrikt",
- "Chat_window": "chattfönster",
+ "Channels_list": "Lista över publika kanaler",
+ "Chat_button": "Chattknapp",
+ "Chat_closed": "Chatt stängd",
+ "Chat_closed_successfully": "Chatten stängdes framgångsrikt",
+ "Chat_Now": "Chatta nu",
+ "Chat_window": "Chattfönster",
"Chatops_Enabled": "aktivera Chatops",
"Chatops_Title": "Chatops Panel",
"Chatops_Username": "Chatops Användarnamn",
"Choose_a_room": "Välj ett rum",
- "Choose_messages": "Välj meddelanden ",
+ "Choose_messages": "Välj meddelanden ",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Välj alias som ska visas före användarnamnet i meddelanden.",
"Choose_the_username_that_this_integration_will_post_as": "Välj det användarnamn som denna integration kommer att lägga upp som.",
+ "clear": "Rensa",
"Clear_all_unreads_question": "Rensa alla olästa?",
+ "clear_history": "Rensa historiken",
"Click_here": "Klicka här",
- "Client_ID": "kund-ID",
+ "Click_here_for_more_info": "Klicka här för mer information",
+ "Client_ID": "Klient-ID",
"Client_Secret": "klienthemligheten",
"Clients_will_refresh_in_a_few_seconds": "Kunderna kommer uppdateras inom några sekunder",
"close": "stäng",
+ "Close": "Stäng",
"Closed": "Stängd",
- "Closing_chat": "stängnings chat",
- "Collapse_Embedded_Media_By_Default": "Kollapsa inbäddade medier som standard",
+ "Closed_by_visitor": "Stängd av besökare",
+ "Closing_chat": "Stänger chat",
+ "Collapse_Embedded_Media_By_Default": "Kollapsa inbäddad media som standard",
"Color": "Färg",
"Commands": "Kommandon",
"Compact": "Kompakt",
"Confirm_password": "Bekräfta ditt lösenord",
- "Conversation": "Meddelande",
- "Conversation_closed": "Konversation stängt: __comment__.",
+ "Content": "Innehåll",
+ "Conversation": "Konversation",
+ "Conversation_closed": "Konversation stängd: __comment__.",
"Convert_Ascii_Emojis": "Konvertera ASCII till Emoji",
"Copied": "Kopierad",
"Copy": "Kopiera",
"Copy_to_clipboard": "Kopiera till urklipp",
- "COPY_TO_CLIPBOARD": "Kopiera till Urklipp",
+ "COPY_TO_CLIPBOARD": "KOPIERA TILL URKLIPP",
"Count": "Räkna",
"Cozy": "Mysig",
"Create": "Skapa",
+ "create-d": "Skapa Direktmeddelanden",
+ "create-p": "Skapa Privata Kanaler",
+ "create-user": "Skapa Användare",
"Create_A_New_Channel": "Skapa en ny kanal",
"Create_new": "Skapa ny",
- "Created_at": "Skapad ",
- "Created_at_s_by_s": "Skapad vid %s av %s ",
- "Current_Chats": "nuvarande Chatt",
- "Custom": "Beställnings",
- "Custom_Emoji_Add": "Lägg till ny emoji",
+ "Created_at": "Skapad ",
+ "Created_at_s_by_s": "Skapad den %s av %s ",
+ "Created_at_s_by_s_triggered_by_s": "Skapad den %s av %s triggad av %s ",
+ "CRM_Integration": "CRM integrering",
+ "Current_Chats": "Nuvarande Chattar",
+ "Current_Status": "Nuvarande Status",
+ "Custom": "Anpassad",
+ "Custom_Emoji": "Anpassad Emoji",
+ "Custom_Emoji_Add": "Lägg till ny Emoji",
+ "Custom_Emoji_Added_Successfully": "Anpassad emoji har lagts till",
+ "Custom_Emoji_Delete_Warning": "Det går inte ångra borttagningen av emojis.",
+ "Custom_Emoji_Error_Invalid_Emoji": "Ogiltig emoji",
+ "Custom_Emoji_Info": "Anpassad Emoji information",
"Custom_Fields": "Anpassade fält",
"Custom_oauth_helper": "När du ställer in din OAuth leverantör, måste du informera en återuppringning webbadress. Användning %s .",
"Custom_oauth_unique_name": "Anpassad oauth unikt namn",
"Custom_Script_Logged_In": "Custom Script för inloggade användare",
"Custom_Script_Logged_Out": "Custom Script för utloggade användare",
+ "Custom_Scripts": "Anpassade Skript",
+ "Custom_Sound_Add": "Lägg till anpassat ljud",
+ "Custom_Sounds": "Anpassade Ljud",
"Dashboard": "instrumentbräda",
"Date": "Datum",
+ "Date_From": "Från",
+ "Date_to": "till",
"days": "dagar",
- "DB_Migration": "databas Migration",
+ "DB_Migration": "Migration av databas",
"DB_Migration_Date": "Databas Migration Datum",
"Deactivate": "Inaktivera",
+ "Decline": "Tacka nej",
"Default": "Standard",
"Delete": "Radera",
+ "delete-message": "Ta bort meddelande",
+ "delete-p": "Ta Bort Privata Kanaler",
+ "delete-user": "Ta bort användare",
"Delete_message": "Radera meddelande",
"Delete_my_account": "Radera mitt konto",
"Delete_Room_Warning": "Om man raderar ett rum, raderas alla postade meddelanden i det rummet. Denna åtgärd kan inte ångras.",
- "Delete_User_Warning": "Radering av en användare kommer att radera alla meddelanden från den användaren. Detta kan inte göras ogjort.",
+ "Delete_User_Warning": "Radering av en användare kommer att radera alla meddelanden från den användaren. Detta kan inte ångras.",
"Deleted": "Borttaget!",
+ "Department": "Avdelning",
"Department_removed": "Avdelning borttagen",
"Departments": "Avdelningar",
"Deployment_ID": "utplacering ID",
"Description": "Beskrivning",
"Desktop": "Skrivbord",
- "Desktop_Notification_Test": "Desktop notifierings test",
+ "Desktop_Notification_Test": "Test av skrivbordsnotifiering",
"Desktop_Notifications": "Skrivbordsnotifieringar",
- "Desktop_Notifications_Disabled": "Skrivbordsnotifieringar är inaktiverade. Ändra dina webbläsarinställningar om du vill aktivera notifieringar",
+ "Desktop_Notifications_Disabled": "Skrivbordsnotifieringar är inaktiverade. Ändra dina webbläsarinställningar om du vill aktivera notifieringar.",
"Desktop_Notifications_Duration": "aviseringar Varaktighet",
"Desktop_Notifications_Duration_Description": "Sekunder för att visa skrivbordet. Detta kan påverka OS X Notiscenter. Ange 0 för att använda webbläsarens standardinställningar och inte påverka OS X Notiscenter.",
"Desktop_Notifications_Enabled": "Skrivbordsnotifieringar är aktiverade.",
- "Direct_message_someone": "Direktmeddelande någon",
+ "Direct_message_someone": "Skicka direktmeddelande till någon",
"Direct_Messages": "Direktmeddelanden",
- "Display_offline_form": "Display offline formulär",
- "Displays_action_text": "Displayer Texten",
+ "Disable_Notifications": "Inaktivera notifieringar",
+ "Display_offline_form": "Visa offline formulär",
+ "Displays_action_text": "Visar action text",
"Do_you_want_to_change_to_s_question": "Vill du ändra till %s ?",
"Domain": "Domän",
- "Domains": "domäner",
+ "Domain_added": "Domän tillagd",
+ "Domain_removed": "Domän borttagen",
+ "Domains": "Domäner",
+ "Download_Snippet": "Ladda ned",
"Drop_to_upload_file": "Släpp för att ladda upp filen",
"Dry_run": "Torrkörning",
"Dry_run_description": "Kommer endast att skicka ett e-postmeddelande, till samma adress som i Från. E-postadressen måste höra till en giltig användare.",
- "Duplicate_archived_channel_name": "En arkiverad kanal med namnet '%s' existerar",
- "Duplicate_archived_private_group_name": "En arkiverad privat grupp med namnet '%s' existerar.",
- "Duplicate_channel_name": "En kanal med namnet \"% s\" existerar",
- "Duplicate_private_group_name": "En privat grupp med namnet \\\"%s\\\" existerar redan",
+ "Duplicate_archived_channel_name": "En arkiverad kanal med namnet '%s' finns redan",
+ "Duplicate_archived_private_group_name": "En arkiverad privat grupp med namnet '%s' finns redan",
+ "Duplicate_channel_name": "En kanal med namnet \"% s\" finns redan",
+ "Duplicate_private_group_name": "En privat grupp med namnet \\\"%s\\\" finns redan",
+ "Duration": "Varaktighet",
"Edit": "Redigera",
+ "edit-message": "Ändra meddelande",
+ "edit-room": "Ändra rum",
"Edit_Custom_Field": "Redigera anpassat fält",
"Edit_Department": "Redigera avdelning",
+ "Edit_previous_message": "`%s` - Modifiera föregående meddelande",
"edited": "redigerad",
"Editing_room": "klipprummet",
- "Editing_user": "redigering användaren",
+ "Editing_user": "redigera användare",
"Email": "E-post",
"Email_address_to_send_offline_messages": "E-postadress att skicka offline-meddelanden",
"Email_already_exists": "E-postadressen finns redan",
@@ -330,10 +397,10 @@
"Enable_Desktop_Notifications": "Aktivera skrivbordsnotifieringar",
"Enabled": "Aktiverad",
"Encrypted_message": "Krypterat meddelande",
- "End_OTR": "änden OTR",
+ "End_OTR": "Avsluta OTR",
"Enter_a_regex": "Ange en regex",
- "Enter_a_room_name": "In i ett rum namn",
- "Enter_a_username": "Skriv ett användarnamn",
+ "Enter_a_room_name": "Ange ett namn för rummet",
+ "Enter_a_username": "Ange ett användarnamn",
"Enter_name_here": "Ange namn här",
"Enter_to": "Enter för att",
"Error": "Fel",
@@ -355,26 +422,26 @@
"error-importer-not-defined": "Importören var inte korrekt definierade, det saknas Importera klassen.",
"error-input-is-not-a-valid-field": "__input__ är inte ett giltigt __field__",
"error-invalid-actionlink": "Ogiltig åtgärd länk",
- "error-invalid-arguments": "ogiltiga argument",
+ "error-invalid-arguments": "Ogiltiga argument",
"error-invalid-asset": "ogiltig tillgång",
"error-invalid-channel": "Ogiltig kanal.",
"error-invalid-channel-start-with-chars": "Ogiltig kanal. Börja med @ eller #",
"error-invalid-custom-field": "Ogiltigt anpassat fält",
"error-invalid-custom-field-name": "Ogiltig anpassad fältnamn. Använd endast bokstäver, siffror, bindestreck och understreck.",
- "error-invalid-description": "ogiltig beskrivning",
+ "error-invalid-description": "Ogiltig beskrivning",
"error-invalid-domain": "Ogiltig domän",
- "error-invalid-email": "Ogiltig e __email__",
+ "error-invalid-email": "Ogiltig e-post __email__",
"error-invalid-file-height": "Felaktig filhöjd",
"error-invalid-file-type": "Felaktig filtyp",
"error-invalid-file-width": "Felaktig filbredd",
"error-invalid-from-address": "Dig informerad en ogiltig FRÅN adress.",
- "error-invalid-integration": "ogiltig integration",
- "error-invalid-message": "ogiltigt meddelande",
- "error-invalid-method": "ogiltigt metod",
+ "error-invalid-integration": "Ogiltig integration",
+ "error-invalid-message": "Ogiltigt meddelande",
+ "error-invalid-method": "Ogiltigt metod",
"error-invalid-name": "Ogiltigt namn",
"error-invalid-password": "Felaktigt lösenord",
- "error-invalid-redirectUri": "ogiltig redirectUri",
- "error-invalid-role": "ogiltig roll",
+ "error-invalid-redirectUri": "Ogiltig redirectUri",
+ "error-invalid-role": "Ogiltig roll",
"error-invalid-room": "ogiltig room",
"error-invalid-room-name": " %s är inte ett giltigt rumsnamn, Använd endast bokstäver, siffror, bindestreck och understreck",
"error-invalid-room-type": "__type__ är inte en giltig rumstyp.",
@@ -392,7 +459,7 @@
"error-missing-unsubscribe-link": "Du måste ge [unsubscribe] länk.",
"error-no-tokens-for-this-user": "Det finns inga polletter för användare",
"error-not-allowed": "Inte tillåtet",
- "error-not-authorized": "ej tillåtet",
+ "error-not-authorized": "Ej tillåtet",
"error-push-disabled": "Push är inaktiverat",
"error-remove-last-owner": "Detta är den sista ägaren. Ställ in en ny ägare innan du tar bort detta.",
"error-role-in-use": "Det går inte att radera rollen eftersom den används",
@@ -402,18 +469,19 @@
"error-user-is-not-activated": "Användaren är inte aktiverad",
"error-user-not-in-room": "Användaren är inte i det här rummet",
"error-user-registration-disabled": "Användarregistrering är inaktiverad",
- "error-user-registration-secret": "Användarregistrering är endast tillåtet via Secret URL",
+ "error-user-registration-secret": "Användarregistrering är endast tillåtet via Hemlig URL",
"error-you-are-last-owner": "Du är den sista ägaren. Ställ ny ägare innan de lämnar rummet.",
"Error_changing_password": "Fel vid byte av lösenord",
"Esc_to": "Esc för att",
- "Example_s": "Exempel: %s",
+ "Example_s": "Exempel: %s",
"False": "Falskt",
- "Favorite_Rooms": "Aktivera favorit rum",
+ "Favorite_Rooms": "Aktivera favoritrum",
"Favorites": "Favoriter",
"Features_Enabled": "funktioner aktiverade",
"Field": "Fält",
"Field_removed": "fältet avlägsnas",
"File_exceeds_allowed_size_of_bytes": "Filen överskrider tillåten storlek __size__ bytes",
+ "File_uploaded": "Uppladdad fil",
"FileUpload": "Uppladdad fil",
"FileUpload_Enabled": "Filuppladdningar aktiverade",
"FileUpload_File_Empty": "Tom fil",
@@ -436,11 +504,18 @@
"Follow_social_profiles": "Följ våra sociala mediakonton, forka oss på github och dela med dig av dina tankar om rocket.chatt på vår trello.",
"Food_and_Drink": "Mat & Dryck",
"Footer": "footer",
- "For_your_security_you_must_enter_your_current_password_to_continue": "För din egen säkerhet måste du ange ditt nuvarande lösenord igen för att fortsätta",
- "Force_SSL": "force SSL",
+ "For_your_security_you_must_enter_your_current_password_to_continue": "För din egen säkerhet måste du ange ditt nuvarande lösenord för att fortsätta",
+ "Force_SSL": "Tvinga SSL",
"Force_SSL_Description": "* OBS! * _Force SSL_ ska aldrig användas med reverse proxy. Om du har en omvänd proxy, bör du göra omdirigeringen DET. Det här alternativet finns för installationer som Heroku, som inte tillåter konfiguration omdirigeringen på den omvända proxyservern.",
"Forgot_password": "Glömt ditt lösenord?",
+ "Forgot_Password_Email_Subject": "[Site_Name] - Återställning av lösenord",
+ "Forgot_password_section": "Glömt lösenord",
+ "Forward": "Vidarebefodra",
+ "Forward_chat": "Vidarebefodra chatt",
+ "Forward_to_department": "Vidarebefodra till avdelning",
+ "Forward_to_user": "Vidarebefodra till användare",
"Frequently_Used": "Ofta använd",
+ "Friday": "Fredag",
"From": "Från",
"From_Email": "Från e-postadress",
"From_email_warning": "Varning: Fältet Från är föremål för e-postserverinställningar.",
@@ -453,8 +528,10 @@
"Hash": "Hash",
"Header": "Rubrik",
"Hidden": "Dolda",
+ "Hide_Avatars": "Göm Avatarer",
"Hide_Group_Warning": "Är du säker att du vill dölja gruppen \"%s\"?",
"Hide_Private_Warning": "Är du säker att du vill dölja diskussionen med \"%s\"?",
+ "Hide_roles": "Göm roller",
"Hide_room": "Dölj rum",
"Hide_Room_Warning": "Är du säker att du vill dölja rummet \"%s\"?",
"Hide_usernames": "Göm användarnamn",
@@ -497,12 +574,18 @@
"Installed_at": "installerad vid",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Instruktioner till besökaren fylla i formuläret för att skicka ett meddelande",
"Integration_added": "Integrationen har lagts",
+ "Integration_Advanced_Settings": "Avancerade inställningar",
"Integration_Incoming_WebHook": "Inkommande WebHook Integration",
"Integration_New": "Ny integrering",
"Integration_Outgoing_WebHook": "Utgående WebHook Integration",
"Integration_updated": "Integrationen har uppdaterats",
"Integrations": "Integreringar",
+ "Integrations_Outgoing_Type_FileUploaded": "Uppladdad fil",
+ "Integrations_Outgoing_Type_RoomArchived": "Rum arkiverat",
+ "Integrations_Outgoing_Type_RoomLeft": "Användare lämnade rummet",
+ "Integrations_Outgoing_Type_UserCreated": "Användare skapad",
"InternalHubot": "intern Hubot",
+ "InternalHubot_reload": "Ladda om skript",
"InternalHubot_ScriptsToLoad": "Skript för att ladda",
"InternalHubot_ScriptsToLoad_Description": "Ange en kommaseparerad lista med skript för att ladda från https://github.com/github/hubot-scripts/tree/master/src/scripts",
"InternalHubot_Username_Description": "Detta måste vara ett giltigt användarnamn av en bot är registrerad på din server.",
@@ -517,6 +600,7 @@
"Invalid_secret_URL_message": "Den angivna webbadressen är felaktig.",
"invisible": "osynlig",
"Invisible": "Osynlig",
+ "Invitation": "Inbjudan",
"Invitation_HTML": "inbjudan HTML",
"Invitation_HTML_Default": " Du har blivit inbjuden till [Site_Name] Gå till [Site_URL] och prova bäst öppen källkod chatt lösning som finns idag!
",
"Invitation_HTML_Description": "Du kan använda följande platsmarkörer: [email] för mottagarens e. [Site_Name] och [Site_URL] för Programnamn och webbadress respektive. ",
@@ -536,6 +620,7 @@
"Jitsi_Enable_Channels": "Aktivera i kanaler",
"join": "Gå med",
"Join_audio_call": "Gå med i ljudsamtal",
+ "Join_Chat": "Gå med i chatt",
"Join_default_channels": "Gå med standardkanaler",
"Join_the_Community": "Gå med i communityt",
"Join_the_given_channel": "Gå med i den givna kanalen",
@@ -568,30 +653,21 @@
"Layout_Terms_of_Service": "Användarvillkor",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Anpassad Domain Search",
- "LDAP_Custom_Domain_Search_Description": "En bit av JSON som styr binder och anslutningsinfo och har formen: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Standarddomän",
"LDAP_Description": "LDAP är en hierarkisk databas som många företag använder för att tillhandahålla enkel inloggning - en anläggning för att dela ett lösenord mellan flera webbplatser och tjänster. För avancerad konfiguration. information och exempel, kontakta vår wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "domän Base",
- "LDAP_Domain_Base_Description": "Den fullständiga unika namn (DN) på en LDAP träd som du vill söka efter användare och grupper. Du kan lägga till så många som du vill, emellertid måste definieras varje grupp i samma domän basen som de användare som hör till den. Om du anger begränsade användargrupper, kommer endast användare som tillhör dessa grupper vara i omfattning. Vi rekommenderar att du anger den översta nivån i LDAP-katalogträd som domänen bas och använda sökfunktionen filter för att kontrollera åtkomsten.",
- "LDAP_Domain_Search_Filter": "Domän Filter",
- "LDAP_Domain_Search_Filter_Description": "Om angivna endast användare som matchar detta filter kommer att tillåtas att logga in. Om inget filter anges kommer alla användare inom ramen för den angivna domänen bas kunna logga in. T.ex. för Active Directory `MEMBEROF = cn = ROCKET_CHAT, ou = General Groups`. T.ex. för OpenLDAP (extensible match ökning) `ou: DN: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Search kvalitetsklass",
- "LDAP_Domain_Search_Object_Category_Description": "Den * objectcategory * som identifierar användarna. Lämna tomt för * OpenLDAP *. T.ex. `person`, etc.",
- "LDAP_Domain_Search_Object_Class": "Domain Search Objektklass",
- "LDAP_Domain_Search_Object_Class_Description": "Den * object * som identifierar användarna. T.ex. `organizationalPerson`, 'användare:,' inetOrgPerson`, etc.",
- "LDAP_Domain_Search_Password": "Domän Sök Lösenord",
- "LDAP_Domain_Search_Password_Description": "Lösenordet för domänen sökanvänd.",
- "LDAP_Domain_Search_User": "Domän Sök användare",
- "LDAP_Domain_Search_User_Description": "LDAP användare som utför användaruppslag att autentisera andra användare när de loggar in. Detta är typiskt ett servicekonto som skapats speciellt för tredjeparts integrationer. Använd ett fullständigt namn, såsom `cn = Administratör, cn = användare, dc = example, dc = com`.",
- "LDAP_Domain_Search_User_ID": "Domain Search användar-ID",
- "LDAP_Domain_Search_User_ID_Description": "LDAP-attribut som identifierar LDAP användare som försöker autentisering. Detta område bör vara `sAMAccountName` för de flesta Active Directory installationer, men det kan vara` uid` för andra LDAP lösningar, såsom OpenLDAP. Du kan använda `mail` att identifiera användare via e-post eller vad attribut du vill. Du kan använda flera värden separerade med kommatecken för att tillåta användare att logga in med flera identifierare som användarnamn eller e-postadress.",
+ "LDAP_BaseDN_Description": "Den fullständiga unika namn (DN) på en LDAP träd som du vill söka efter användare och grupper. Du kan lägga till så många som du vill, emellertid måste definieras varje grupp i samma domän basen som de användare som hör till den. Om du anger begränsade användargrupper, kommer endast användare som tillhör dessa grupper vara i omfattning. Vi rekommenderar att du anger den översta nivån i LDAP-katalogträd som domänen bas och använda sökfunktionen filter för att kontrollera åtkomsten.",
+ "LDAP_User_Search_Field_Description": "LDAP-attribut som identifierar LDAP användare som försöker autentisering. Detta område bör vara `sAMAccountName` för de flesta Active Directory installationer, men det kan vara` uid` för andra LDAP lösningar, såsom OpenLDAP. Du kan använda `mail` att identifiera användare via e-post eller vad attribut du vill. Du kan använda flera värden separerade med kommatecken för att tillåta användare att logga in med flera identifierare som användarnamn eller e-postadress.",
+ "LDAP_User_Search_Filter_Description": "Om angivna endast användare som matchar detta filter kommer att tillåtas att logga in. Om inget filter anges kommer alla användare inom ramen för den angivna domänen bas kunna logga in. T.ex. för Active Directory `MEMBEROF = cn = ROCKET_CHAT, ou = General Groups`. T.ex. för OpenLDAP (extensible match ökning) `ou: DN: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "LDAP användare som utför användaruppslag att autentisera andra användare när de loggar in. Detta är typiskt ett servicekonto som skapats speciellt för tredjeparts integrationer. Använd ett fullständigt namn, såsom `cn = Administratör, cn = användare, dc = example, dc = com`.",
"LDAP_Enable": "Aktivera",
"LDAP_Enable_Description": "Försök att använda LDAP för autentisering.",
"LDAP_Encryption": "kryptering",
"LDAP_Encryption_Description": "Krypteringsmetod som används för att säkra kommunikationen till LDAP-servern. Som exempel kan nämnas `plain` (ingen kryptering),` SSL / LDAPS` (krypterad från början), och `StartTLS` (uppgradera till krypterad kommunikation när ansluten).",
+ "LDAP_Group_Filter_Group_Name": "Gruppnamn",
"LDAP_Host": "Värd",
"LDAP_Host_Description": "LDAP värd, t.ex. `ldap.example.com` eller` 10.0.0.30`.",
+ "LDAP_Idle_Timeout": "Timeout för inaktivitet (ms)",
+ "LDAP_Merge_Existing_Users": "Slå samman existerande användare",
"LDAP_Port": "Port",
"LDAP_Port_Description": "Port för att få tillgång till LDAP. t.ex. `389` eller` 636` för LDAPS",
"LDAP_Reject_Unauthorized": "Avvisa obehöriga",
@@ -600,12 +676,9 @@
"LDAP_Sync_User_Data_Description": "Håll användardata i synk med servern vid inloggning ( t.ex. namn, e-post ).",
"LDAP_Sync_User_Data_FieldMap": "Användardatafält Karta",
"LDAP_Sync_User_Data_FieldMap_Description": "Konfigurera hur användarkonto fält (som e-post) fylls från en post i LDAP (en gång hittade). Som ett exempel, `{\" cn \":\" namn \",\" post \":\" email \"} 'kommer att välja en persons mänskligt läsbar namn från cn attribut och deras e-post från e-postattribut. Tillgängliga fält inkluderar `name` och` email`.",
- "LDAP_Sync_Users": "Synkronisera Användare",
"LDAP_Test_Connection": "Testa anslutning",
"LDAP_Unique_Identifier_Field": "Unique Identifier Field",
"LDAP_Unique_Identifier_Field_Description": "Vilket fält kommer att användas för att länka LDAP användare och Rocket.Chat användaren. Du kan informera flera värden separerade med kommatecken för att försöka få värdet från LDAP register. Standardvärdet är 'objectGUID, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Använd egen domän Sök",
- "LDAP_Use_Custom_Domain_Search_Description": "Skriv ditt eget filter för att söka användare i LDAP-servern.",
"LDAP_Username_Field": "Användarnamn Field",
"LDAP_Username_Field_Description": "Vilket fält kommer att användas som * användarnamn * för nya användare. Lämna tomt för att använda användarnamn informerad om inloggningssidan. Du kan använda malltaggar också, som `#{givenName}.#{sn}`. Standardvärdet är 'sAMAccountName`.",
"Leave_Group_Warning": "Är du säker att du vill lämna gruppen \"%s\"?",
@@ -634,7 +707,7 @@
"Loading_suggestion": "Laddar förslag...",
"Localization": "Lokalisering",
"Log_File": "Visa Arkiv och Linje",
- "Log_Level": "Log Level",
+ "Log_Level": "Loggnivå",
"Log_Package": "Visa Package",
"Log_View_Limit": "Loggen Limit",
"Logged_out_of_other_clients_successfully": "Loggades framgångsrikt ut ur andra klienter",
@@ -652,10 +725,13 @@
"Mailer_body_tags": "Du måste använda [unsubscribe] för prenumeration länken. Du kan använda [name], [fname], [lname] för användarens fullständiga namn, förnamn eller efternamn, respektive. Du kan använda [email] för användarens e-post.",
"Mailing": "Mailing",
"Make_Admin": "Gör till administratör",
+ "manage-emoji": "Hantera Emojis",
+ "manage-integrations": "Hantera integreringar",
+ "manage-sounds": "Hantera Ljud",
"Manager_added": "manager sattes",
"Manager_removed": "manager avlägsnades",
"Managing_assets": "hantera tillgångar",
- "Managing_integrations": "hantera integrationer",
+ "Managing_integrations": "Hantera integrationer",
"Mark_as_read": "Markera som läst",
"Mark_as_unread": "Markera som oläst",
"Markdown_Headers": "Wiki rubriker",
@@ -665,7 +741,7 @@
"Mentions": "Omnämningar ",
"Mentions_default": "Omnämningar (standard)",
"Message": "Meddelande",
- "Message_AllowBadWordsFilter": "Tillåt meddelande fula ord filtrering",
+ "Message_AllowBadWordsFilter": "Tillåt filtrering av fula ord i meddelanden",
"Message_AllowDeleting": "Tillåt radering av meddelanden",
"Message_AllowDeleting_BlockDeleteInMinutes": "Block Message Radera Efter (n) Minuter",
"Message_AllowDeleting_BlockDeleteInMinutes_Description": "Ange 0 för att inaktivera blockering.",
@@ -673,13 +749,13 @@
"Message_AllowEditing_BlockEditInMinutes": "Blockera redigering av meddelanden efter (n) minuter",
"Message_AllowEditing_BlockEditInMinutesDescription": "Skriv 0 för att inaktivera blockering.",
"Message_AllowPinning": "Tillåt pinnande av meddelanden",
- "Message_AllowPinning_Description": "Tillåt meddelanden att bli pinnade i alla olika kanaler",
+ "Message_AllowPinning_Description": "Tillåt meddelanden att bli pinnade i alla kanaler",
"Message_AllowStarring": "Tillåt stjärnmarkering av meddelanden.",
"Message_AlwaysSearchRegExp": "sök alltid använder RegExp",
"Message_AlwaysSearchRegExp_Description": "Vi rekommenderar att ställa in TRUE om ditt språk inte stöds på MongoDB textsökning .",
"Message_AudioRecorderEnabled": "Audio Recorder Enabled",
"Message_AudioRecorderEnabledDescription": "Kräver \"audio / wav\" filer att vara en accepterad mediatyp inom \"File Ladda upp\" inställningar.",
- "Message_BadWordsFilterList": "Lägg fula ord till den svarta listan",
+ "Message_BadWordsFilterList": "Lägg till dåliga ord i svartlistan",
"Message_BadWordsFilterListDescription": "Lägg till lista med kommaseparerade lista över dåliga ord för att filtrera",
"Message_DateFormat": "Datumformat",
"Message_DateFormat_Description": "Se även: Moment.js ",
@@ -696,9 +772,10 @@
"Message_ShowEditedStatus": "Visa Redigerad status",
"Message_ShowFormattingTips": "Visa Formatera Tips",
"Message_starring": "meddelande starring",
+ "Message_TimeAndDateFormat": "Tid och datumformat",
"Message_TimeFormat": "Tidsformat",
"Message_TimeFormat_Description": "Se även: Moment.js ",
- "Message_too_long": "Meddelande för långt",
+ "Message_too_long": "Meddelandet är för långt",
"Messages": "Meddelanden",
"Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Meddelanden som skickas till den inkommande WebHook kommer att publiceras här.",
"Meta": "Meta",
@@ -708,16 +785,21 @@
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Robots",
"minutes": "minuter",
+ "Mobile": "Mobil",
+ "Monday": "Måndag",
"More_channels": "Fler kanaler",
"More_direct_messages": "Fler direktmeddelanden",
"More_groups": "Fler privata grupper",
"More_unreads": "Fler olästa",
+ "Move_beginning_message": "`%s` - Gå till början av meddelande",
+ "Move_end_message": "`%s` - Gå till slutet av meddelande",
"Msgs": "Meddelanden ",
"multi": "mång",
"Mute_someone_in_room": "Tysta någon i rummet",
"Mute_user": "mute användaren",
"Muted": "dämpad",
"My_Account": "Mitt Konto",
+ "My_location": "Min position",
"n_messages": "%s meddelanden",
"N_new_messages": "%s nya meddelanden",
"Name": "Namn",
@@ -729,7 +811,7 @@
"New_Custom_Field": "New anpassat fält",
"New_Department": "Ny avdelning",
"New_integration": "Ny integrering",
- "New_logs": "nya loggar",
+ "New_logs": "Nya loggar",
"New_Message_Notification": "Nytt Meddelande Notifikation",
"New_messages": "Nya meddelanden",
"New_password": "Nytt lösenord",
@@ -737,7 +819,7 @@
"New_Room_Notification": "Nytt Rum Notifikation",
"No_channel_with_name_%s_was_found": "Ingen kanal med namnet \"%s\" kunde hittas!",
"No_channels_yet": "Du är inte med i någon kanal ännu.",
- "No_direct_messages_yet": "Du har inte startat några samtal än.",
+ "No_direct_messages_yet": "Du har inte startat några konversationer än.",
"No_Encryption": "ingen kryptering",
"No_group_with_name_%s_was_found": "Ingen privat grupp med namnet \"%s\" kunde hittas!\n",
"No_groups_yet": "Du har inga privata grupper än.",
@@ -747,7 +829,10 @@
"No_results_found": "Inga resultat funna",
"No_starred_messages": "Inga stjärnmarkerade meddelanden",
"No_user_with_username_%s_was_found": "Ingen användare med användarnamnet \"%s\" kunde hittas!",
+ "Nobody_available": "Ingen tillgänglig",
"Node_version": "nod version",
+ "None": "Ingen",
+ "Normal": "Normal",
"Not_authorized": "Inte auktoriserad",
"Not_Available": "Inte tillgänglig",
"Not_found_or_not_allowed": "Inte hittad eller inte tillåten",
@@ -755,27 +840,33 @@
"Nothing_found": "Inget hittat",
"Notifications": "Notifikationer",
"Notify_all_in_this_room": "Meddela alla i det här rummet",
- "Num_Agents": "# Agents",
+ "Num_Agents": "# Agenter",
"Number_of_messages": "Antal meddelanden",
"OAuth_Application": "OAuth Application",
"OAuth_Applications": "OAuth Tillämpningar",
"Objects": "Föremål",
+ "Off": "Av",
"Off_the_record_conversation": "Off-the-record konversation",
- "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record konversationen finns inte tillgängligt för din webbläsare eller enhet.",
- "Offline": "Off-line",
+ "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-record konversationen finns inte tillgänglig för din webbläsare eller enhet.",
+ "Office_Hours": "Kontorstider",
+ "Offline": "Offline",
"Offline_DM_Email": "Du har fått ett meddelande av __user__",
"Offline_form": "offline formen",
"Offline_form_unavailable_message": "Offline formen tillgänglig meddelande",
+ "Offline_Link_Message": "GÅ TILL MEDDELANDE",
"Offline_Mention_Email": "Du har nämnts av __user__ i #__room__",
- "Offline_message": "offline meddelande",
+ "Offline_message": "Offlinemeddelande",
"Offline_success_message": "Offline framgång meddelande",
- "Offline_unavailable": "offline tillgänglig",
+ "Offline_unavailable": "Offline ej tillgänglig",
+ "On": "På",
"Online": "Online",
"Only_you_can_see_this_message": "Bara du kan se detta meddelande",
"Oops!": "Oj",
- "Open": "Öppen",
+ "Open": "Öppna",
+ "Open_channel_user_search": "`%s` - Öppna kanal / Sök Användare",
"Opened": "Öppnad",
"optional": "valfritt",
+ "or": "eller",
"Order": "Beställa",
"OS_Arch": "OS Arch",
"OS_Cpus": "OS CPU Count",
@@ -788,19 +879,24 @@
"OS_Uptime": "OS Uptime",
"others": "andra",
"OTR": "OTR",
- "OTR_is_only_available_when_both_users_are_online": "OTR är endast tillgänglig när båda användarna är online",
+ "OTR_is_only_available_when_both_users_are_online": "OTR är endast tillgängligt när båda användarna är online",
"Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Åsido URL till vilka filer som laddas upp. Denna url används också för nedladdning såvida inte en CDN ges",
+ "Page_title": "Sidtitel",
"Password": "Lösenord",
- "Password_Change_Disabled": "Din Rocket.Chatadministratör har inaktiverat lösenordsbyten",
+ "Password_Change_Disabled": "Din Rocket.Chat-administratör har inaktiverat lösenordsbyten",
"Password_changed_successfully": "Lösenordet ändrat",
- "Past_Chats": "tidigare Chatt",
+ "Past_Chats": "Tidigare Chattar",
"Payload": "nyttolast",
"People": "Folk",
"Permalink": "Länka meddelande",
"Permissions": "Tillstånd",
+ "pin-message": "Pinna Meddelande",
+ "pin-message_description": "Tillstång att pinna ett meddelande i en kanal",
"Pin_Message": "Pinna Meddelande",
"Pinned_a_message": "Pinnade ett meddelande",
"Pinned_Messages": "Pinnade Meddelanden",
+ "PiwikAnalytics_cookieDomain": "Alla subdomäner",
+ "PiwikAnalytics_domains": "Göm utgående länkar",
"PiwikAnalytics_siteId_Description": "Webbplatsen id som ska användas för att identifiera denna webbplats. Exempel: 17",
"PiwikAnalytics_url_Description": "Url där Piwik bor, se till att inkludera den trialing snedstreck. Exempel: //piwik.rocket.chat/",
"Placeholder_for_email_or_username_login_field": "Platshållare för e-post- eller användarnamnsinloggningsfältet",
@@ -817,11 +913,11 @@
"Please_fill_name_and_email": "Vänligen fyll i namn och e-postadress",
"Please_select_enabled_yes_or_no": "Välj ett alternativ för Enabled",
"Please_wait": "Vänligen vänta",
- "Please_wait_activation": "Var vänlig och vänta, detta kan ta lite tid.",
+ "Please_wait_activation": "Vänligen vänta, detta kan ta lite tid.",
"Please_wait_while_OTR_is_being_established": "Vänta medan OTR upprättas",
"Please_wait_while_your_account_is_being_deleted": "Vänligen vänta medan ditt konto raderas...",
"Please_wait_while_your_profile_is_being_saved": "Vänligen vänta medan din profil sparas...",
- "Port": "Hamn",
+ "Port": "Port",
"Post_as": "Posta som",
"Post_to_Channel": "Posta till kanal",
"Post_to_s_as_s": "Posta till %s som %s ",
@@ -829,12 +925,16 @@
"Preferences_saved": "Inställningar sparade",
"Privacy": "Integritet",
"Private": "Privat",
- "Private_Group": "Privat grupp",
+ "Private_Channel": "Privat kanal",
+ "Private_Group": "Privat Grupp",
"Private_Groups": "Privata Grupper",
"Private_Groups_list": "Lista över privata grupper",
"Profile": "Profil",
+ "Profile_details": "Profildetaljer",
+ "Profile_picture": "Profilbild",
"Profile_saved_successfully": "Profilen sparad",
"Public": "Offentlig",
+ "Public_Channel": "Publik kanal",
"Push": "Push",
"Push_apn_cert": "APN Cert",
"Push_apn_dev_cert": "APN Dev Cert",
@@ -853,7 +953,8 @@
"Push_show_username_room": "Visa kanal/grupp/användarnamn i notifieringar",
"Push_test_push": "Test",
"Query": "Fråga",
- "Query_description": "Ytterligare villkor för att avgöra vilken användare att skicka e-post till. Användare som inte prenumererar tas automatiskt bort från frågan. Det måste vara ett giltigt JSON. Exempel: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
+ "Query_description": "Ytterligare villkor för att avgöra vilken användare att skicka e-post till. Användare som inte prenumererar tas automatiskt bort från frågan. Det måste vara ett giltigt JSON. Exempel: \"{\"createdAt\":{\"$gt\":{\"$date\": \"2015-01-01T00:00:00.000Z\"}}}\"",
+ "Queue": "Kö",
"quote": "citat",
"Quote": "Citera inlägg",
"Random": "Slumpmässig",
@@ -864,20 +965,26 @@
"Refresh_keys": "refresh nycklar",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Uppdatera sidan efter installationen för att aktivera skärmdelning",
"Register": "Registrera ett nytt konto",
+ "Registration": "Registrering",
"Registration_Succeeded": "Registreringen lyckades",
+ "Registration_via_Admin": "Registrering via en administratör",
"Release": "Släpp",
+ "Reload": "Ladda om",
"Remove": "Ta bort",
"Remove_Admin": "Ta bort administratör",
"Remove_as_moderator": "Ta bort som moderator",
"Remove_as_owner": "Ta bort som ägare",
"Remove_custom_oauth": "Ta bort anpassade oauth",
"Remove_from_room": "Ta bort från rum",
+ "Remove_last_admin": "Tar bort senaste administratör",
"Remove_someone_from_room": "Ta bort någon från detta rum",
"Removed": "Borttagen",
+ "Reply": "Svara",
"Report_Abuse": "Anmäl inlägg",
"Report_exclamation_mark": "Anmäl!",
"Report_sent": "rapport skickas",
"Report_this_message_question_mark": "Rapportera det här meddelandet?",
+ "Reporting": "Rapportering",
"Require_password_change": "Kräv byte av lösenord",
"Resend_verification_email": "Skicka verifieringsemail igen",
"Reset": "Nollställ",
@@ -885,7 +992,7 @@
"Restart": "Starta om",
"Restart_the_server": "Starta om servern",
"Role": "Roll",
- "Role_Editing": "roll Redigering",
+ "Role_Editing": "Redigering av roll",
"Role_removed": "Roll borttagen",
"Room": "Rum",
"Room_archivation_state": "Status",
@@ -895,22 +1002,26 @@
"room_changed_privacy": "Typ rum ändras till: __room_type__ av __user_by__ ",
"room_changed_topic": "Rummets ämne ändrat till: __room_topic__ by __user_by__ __room_name__ av __user_by__ ",
+ "Room_Info": "Rumsinformation",
+ "room_is_blocked": "Rummet är blockerat",
+ "room_name": "Rumsnamn",
+ "Room_name_changed": "Rummets namn ändrat till : __room_name__ av __user_by__ ",
"Room_name_changed_successfully": "Rummets namn har ändrats ",
"Room_not_found": "Rummet kunde inte hittas",
"Room_topic_changed_successfully": "Rummets ämne har ändrats",
"Room_type_changed_successfully": "Rummets typ har ändrats",
- "Room_unarchived": "rummet avarkiverats",
+ "Room_unarchived": "Rummet har avarkiverats",
"Room_uploaded_file_list": "Fillista",
"Room_uploaded_file_list_empty": "Inga filer tillgängliga.",
"Rooms": "Rum",
+ "run-import": "Kör Import",
+ "run-migration": "Kör Migrering",
"Running_Instances": "kör instanser",
"S_new_messages_since_s": "%s nya meddelanden sedan %s",
"SAML": "SAML",
"SAML_Custom_Cert": "beställnings Certificate",
"SAML_Custom_Entry_point": "Custom Entry Point",
- "SAML_Custom_Generate_Username": "Skapa användarnamn",
+ "SAML_Custom_Generate_Username": "Generera Användarnamn",
"SAML_Custom_Issuer": "Custom Emittent",
"SAML_Custom_Provider": "anpassade Provider",
"Save": "Spara",
@@ -921,7 +1032,7 @@
"Saving": "Sparar",
"Scope": "Omfattning",
"Screen_Share": "Skärmdelning",
- "Script_Enabled": "script Enabled",
+ "Script_Enabled": "Skript Aktiverat",
"Search": "Sök",
"Search_by_username": "Sök på användarnamn",
"Search_Messages": "Sök meddelanden",
@@ -953,14 +1064,19 @@
"Send_your_JSON_payloads_to_this_URL": "Skicka dina JSON nyttolaster till denna URL.",
"Sending": "Skickar...",
"Service": "Service",
+ "set-moderator": "Välj Moderator",
+ "set-owner": "Välj Ägare",
"Set_as_moderator": "Ange som moderator",
"Set_as_owner": "Ange som ägare",
"Settings": "Inställningar",
"Settings_updated": "Inställningar uppdaterade",
+ "Share_Location_Title": "Dela position?",
+ "Shared_Location": "Delad position",
"Should_be_a_URL_of_an_image": "Ska vara en webbadress till en bild.",
"Should_exists_a_user_with_this_username": "Användaren måste existera redan.",
"Show_all": "Visa alla",
"Show_more": "Visa mer",
+ "Show_on_registration_page": "Visa på registeringssidan",
"Show_only_online": "Visa enbart online",
"Show_preregistration_form": "Visa förhandsregistreringsformulär",
"Showing_archived_results": "Visar %s arkiverade resultat
",
@@ -971,13 +1087,13 @@
"Site_Url": "webbadress",
"Site_Url_Description": "Example: https://chat.domain.com/",
"Skip": "Hoppa över",
- "Slash_Gimme_Description": "Displayer (つ ◕_◕) つ innan ditt meddelande",
- "Slash_LennyFace_Description": "Displayer (͡ ° ͜ʖ ͡ °) efter ditt meddelande",
- "Slash_Shrug_Description": "Displayer ¯ \\ _ (ツ) _ / ¯ efter ditt meddelande",
+ "Slash_Gimme_Description": "Visar (つ ◕_◕) つ innan ditt meddelande",
+ "Slash_LennyFace_Description": "Visar (͡ ° ͜ʖ ͡ °) efter ditt meddelande",
+ "Slash_Shrug_Description": "Visar ¯ \\ _ (ツ) _ / ¯ efter ditt meddelande",
"Slash_Tableflip_Description": "Displayer ° (╯ ° □ °) ╯( ┻━┻",
"Slash_TableUnflip_Description": "Displayer ┬─┬ ノ (゜ - ゜ ノ)",
"Slash_Topic_Description": "Ställ ämne",
- "Slash_Topic_Params": "ämne meddelande",
+ "Slash_Topic_Params": "Ämne för meddelande",
"Smileys_and_People": "Smileys & Personer",
"SMS_Enabled": "SMS Enabled",
"SMTP": "SMTP",
@@ -986,14 +1102,16 @@
"SMTP_Port": "SMTP Port",
"SMTP_Test_Button": "Testa SMTP-inställningar",
"SMTP_Username": "SMTP Användarnamn",
+ "Snippet_Added": "Skapad den %s",
"Sound": "Ljud",
+ "Sound_File_mp3": "Ljudfil (mp3)",
"SSL": "SSL",
"Star_Message": "Stjärnmarkera meddelande",
"Starred_Messages": "Stjärnmarkerade meddelanden",
"Start_audio_call": "Starta ljudsamtal",
"Start_Chat": "Starta chatt",
"Start_of_conversation": "Början av samtalet",
- "Start_OTR": "start OTR",
+ "Start_OTR": "Starta OTR",
"Start_video_call": "Starta videosamtal",
"Start_with_s_for_user_or_s_for_channel_Eg_s_or_s": "Starta med %s för användare eller %s för kanal. Ex: %s eller %s",
"Started_At": "började på",
@@ -1014,17 +1132,20 @@
"Stats_Total_Private_Groups": "Totala Privata Grupper",
"Stats_Total_Rooms": "Totala Rum",
"Stats_Total_Users": "Totala användare",
+ "Status": "Status",
"Stop_Recording": "Sluta spela in",
"strike": "strejk",
"Subject": "Ämne",
"Submit": "Skicka",
"Success": "Framgång",
"Success_message": "framgång meddelande",
+ "Sunday": "Söndag",
"Survey": "Enkät",
"Survey_instructions": "Betygsätt varje fråga efter hur nöjd du är, 1 betyder att du inte alls är nöjd och 5 betyder att du är helt nöjd.\n",
"Symbols": "Symboler",
"Sync_success": "synk framgång",
"Sync_Users": "Synkronisera Användare",
+ "System_messages": "Systemmeddelanden",
"Tag": "Märka",
"Test_Connection": "Testa anslutningen",
"Test_Desktop_Notifications": "Testa Desktop notifiering",
@@ -1042,19 +1163,19 @@
"The_user_wont_be_able_to_type_in_s": "Användaren kommer inte att kunna skriva i %s",
"Theme": "Tema",
"theme-color-content-background-color": "Innehåll bakgrundsfärg",
+ "theme-color-custom-scrollbar-color": "Beställnings Scrollbar Färg",
+ "theme-color-info-font-color": "Info Font Color",
+ "theme-color-link-font-color": "Länk Font Color",
"theme-color-primary-background-color": "Primära bakgrundsfärg",
"theme-color-primary-font-color": "Primär Font Color",
"theme-color-secondary-background-color": "Sekundär bakgrundsfärg",
"theme-color-secondary-font-color": "Sekundär Teckenfärg",
- "theme-color-tertiary-background-color": "Tertiary bakgrundsfärg",
- "theme-color-tertiary-font-color": "Tertiary Teckenfärg",
- "theme-color-link-font-color": "Länk Font Color",
- "theme-color-info-font-color": "Info Font Color",
- "theme-color-custom-scrollbar-color": "Beställnings Scrollbar Färg",
"theme-color-status-away": "Statusfärg för Borta",
"theme-color-status-busy": "Statusfärg för Upptagen",
"theme-color-status-offline": "Statusfärg för Offline",
"theme-color-status-online": "Statusfärg för Online",
+ "theme-color-tertiary-background-color": "Tertiary bakgrundsfärg",
+ "theme-color-tertiary-font-color": "Tertiary Teckenfärg",
"theme-color-unread-notification-color": "Olästa meddelanden Färg",
"theme-custom-css": "anpassade CSS",
"There_are_no_agents_added_to_this_department_yet": "Det finns inga medel har lagts till i avdelning ännu.",
@@ -1065,6 +1186,7 @@
"This_is_a_push_test_messsage": "Detta är ett testpushmeddelande",
"This_room_has_been_archived_by__username_": "Detta rum har arkiverats av __username__",
"This_room_has_been_unarchived_by__username_": "Detta rum har avarkiverats av __username__",
+ "Thursday": "Torsdag",
"Time_in_seconds": "Tid i sekunder",
"Title": "Titel",
"Title_bar_color": "Titel bar färg",
@@ -1074,11 +1196,14 @@
"to_see_more_details_on_how_to_integrate": "att se mer information om hur man kan integrera.",
"To_users": "Till användare",
"Topic": "Ämne",
+ "Translated": "Översatt",
+ "Translations": "Översättningar",
"Travel_and_Places": "Fordon & Platser",
"Trigger_removed": "trigger avlägsnades",
"Trigger_Words": "trigger ord",
"Triggers": "triggers",
"True": "Sant",
+ "Tuesday": "Tisdag",
"Type": "Typ",
"Type_your_email": "Skriv din e-post",
"Type_your_message": "Skriv in ditt meddelande",
@@ -1086,14 +1211,20 @@
"Type_your_new_password": "Skriv in ditt nya lösenord",
"UI_DisplayRoles": "visnings Roller",
"UI_Merge_Channels_Groups": "Merge privata grupper med kanaler",
+ "UI_Use_Real_Name": "Använd riktigt namn",
"Unarchive": "unarchive",
+ "Unblock_User": "Avblockera användare",
"Unmute_someone_in_room": "Mikrofon på någon i rummet",
"Unmute_user": "Mikrofon på användaren",
"Unnamed": "Namnlös",
"Unpin_Message": "Ta bort pinnat meddelande",
+ "Unread_Messages": "Olästa meddelanden",
"Unread_Rooms": "Olästa rum",
"Unread_Rooms_Mode": "Olästa Rum Läge",
"Unstar_Message": "Ta bort stjärnmarkering",
+ "Updated_at": "Uppdaterad den",
+ "Upload_file_description": "Filbeskrivning",
+ "Upload_file_name": "Filnamn",
"Upload_file_question": "Ladda upp fil?",
"Uploading_file": "Laddar upp fil...",
"Uptime": "drifttid",
@@ -1105,6 +1236,7 @@
"Use_this_username": "Använd det här användarnamnet",
"Use_uploaded_avatar": "Använd uppladdad avatar",
"Use_url_for_avatar": "Använd webbadress för avatar",
+ "User": "Användare",
"User__username__is_now_a_moderator_of__room_name_": "Användar __username__ är nu en moderator för __room_name__",
"User__username__is_now_a_owner_of__room_name_": "Användar __username__ är nu en ägare av __room_name__",
"User__username__removed_from__room_name__moderators": "Användar __username__ avlägsnas från __room_name__ moderatorer",
@@ -1119,7 +1251,9 @@
"User_has_been_muted_in_s": "Användaren har stängts av i %s",
"User_has_been_removed_from_s": "Användaren har blivit borttagen från %s",
"User_Info": "Användarinfo",
- "User_is_no_longer_an_admin": "Användaren är inte längre administratör",
+ "User_Interface": "Användargränssnitt",
+ "User_is_blocked": "Användare är blockerad",
+ "User_is_no_longer_an_admin": "Användaren är inte längre en administratör",
"User_is_now_an_admin": "Användaren är nu administratör",
"User_joined_channel": "Har anslutit sig till kanalen.",
"User_joined_channel_female": "Har anslutit sig till kanalen.",
@@ -1139,11 +1273,13 @@
"User_unmuted_by": "Användar __user_unmuted__ tystade av __user_by__. ",
"User_unmuted_in_room": "Användar tystade i rummet",
"User_updated_successfully": "Användare framgångsrikt uppdaterad",
+ "User_uploaded_file": "Laddade upp en fil",
+ "User_uploaded_image": "Laddade upp en bild",
"Username": "Användarnamn",
"Username_and_message_must_not_be_empty": "Användarnamn och meddelande får inte vara tomma",
"Username_cant_be_empty": "Användarnamnet kan inte vara tomt",
"Username_Change_Disabled": "Byte av användarnamn är avaktiverat",
- "Username_denied_the_OTR_session": "__username__ förnekade OTR-session",
+ "Username_denied_the_OTR_session": "__username__ nekade OTR-session",
"Username_description": "Användarnamnet används för att låta andra nämna dig i meddelanden.",
"Username_doesnt_exist": "Användarnamnet `%s` finns inte.",
"Username_ended_the_OTR_session": "__username__ avslutade OTR-session",
@@ -1153,27 +1289,38 @@
"Username_title": "Registrera användarnamn",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ vill starta OTR. Vill du acceptera?",
"Users": "Användare",
+ "Users_added": "Användarna har blivit tillagda",
"Users_in_role": "Användare i rollen",
"UTF8_Names_Slugify": "UTF8 Names Slugify",
"UTF8_Names_Validation": "UTF8 Names Validering",
"UTF8_Names_Validation_Description": "Tillåt inte specialtecken och mellanslag. Du kan använda - _ och . men inte i slutet av namnet",
+ "Validate_email_address": "Validera e-postadress",
+ "Verification": "Verifikation",
"Verification_email_sent": "Verifieringsmeddelande har skickats",
"Verified": "verifierade",
+ "Verify": "Verifiera",
"Version": "Version",
- "Video_Chat_Window": "video~~POS=TRUNC",
- "View_All": "Visa alla",
+ "Video_Chat_Window": "Videochatt",
+ "Video_Conference": "Videokonferens",
+ "Video_message": "Videomeddelande",
+ "view-d-room": "Visa direktmeddelanden",
+ "view-history": "Se historik",
+ "view-logs": "Visa loggar",
+ "view-statistics": "Visa Statistik",
+ "View_All": "Visa Alla",
"View_Logs": "Visa Loggar",
- "View_mode": "visningsläge",
+ "View_mode": "Visningsläge",
"View_mode_info": "Detta ändrar mängden rymd meddelanden tar upp på skärmen.",
"Viewing_room_administration": "Visning rum administration",
"Visibility": "Synlighet",
"Visible": "Synlig",
"Visitor": "Besökare",
- "Visitor_Info": "För besökare",
+ "Visitor_Info": "Besökarinformation",
"Visitor_Navigation": "Visitor Navigation",
"Visitor_page_URL": "Visitor Sidans URL",
"Visitor_time_on_site": "Besökare tid på plats",
"Wait_activation_warning": "Innan du kan logga in måste ditt konto aktiveras manuellt av en administratör.",
+ "Warnings": "Varningar",
"We_are_offline_Sorry_for_the_inconvenience": "Vi är offline. Vi beklagar olägenheten. ",
"We_have_sent_password_email": "Vi har skickat ett mail med instruktioner för återställande av lösenord. Om du inte får ett mail inom kort, kom tillbaka och försök igen.",
"We_have_sent_registration_email": "Vi har skickat ett mail för att bekräfta din registrering. Om du inte får ett mail inom kort, kom tillbaka och försök igen.",
@@ -1184,11 +1331,13 @@
"WebRTC_Enable_Private": "Aktivera för privata kanaler",
"WebRTC_Servers": "STUN / TURN-servrar",
"WebRTC_Servers_Description": "En lista över STUN och vrid servrar separerade med kommatecken. Användarnamn, lösenord och hamn är tillåtna i formatet `användarnamn: lösenord @ bedövar: värd: hamn: eller 'användarnamn: lösenord @ tur: värd: hamn:.",
+ "Wednesday": "Onsdag",
"Welcome": "Välkommen %s .",
"Welcome_to_the": "Välkommen till",
"Why_do_you_want_to_report_question_mark": "Varför vill du anmäla?",
"will_be_able_to": "kommer att kunna",
"Yes": "Ja",
+ "Yes_archive_it": "Ja, arkivera!",
"Yes_clear_all": "Ja, rensa alla!",
"Yes_delete_it": "Ja, ta bort det!",
"Yes_hide_it": "Ja, dölj den!",
@@ -1216,13 +1365,15 @@
"You_need_to_write_something": "Du måste skriva något!",
"You_should_inform_one_url_at_least": "Du bör definiera minst en webbadress.",
"You_should_name_it_to_easily_manage_your_integrations": "Du bör namnge den för att enkelt kunna hantera dina integrationer .\n",
- "You_will_not_be_able_to_recover": "Du kommer inte att kunna återskapa detta meddelande!",
+ "You_will_not_be_able_to_recover": "Du kommer inte kunna återskapa detta meddelande!",
"You_will_not_be_able_to_recover_file": "Du kommer inte att kunna återskapa den här filen!",
"You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Du kommer inte att få e-postmeddelanden eftersom du inte har verifierat din e-post.",
"Your_email_has_been_queued_for_sending": "Ditt e-postmeddelande har köats för att skickas",
"Your_entry_has_been_deleted": "Ditt meddelande har tagits bort.",
"Your_file_has_been_deleted": "Din fil har blivit raderad.",
"Your_mail_was_sent_to_s": "Ditt e-postmeddelande skickades till %s",
+ "your_message": "ditt meddelande",
+ "your_message_optional": "ditt meddelande (valfri)",
"Your_password_is_wrong": "Ditt lösenord är fel!",
"Your_push_was_sent_to_s_devices": "Din push skickades till %s enheter"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
index 58ea59cd2b62a..eaebb11a2b953 100644
--- a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "பயனர் விவரம் மாற்றம் அனுமதி",
"Accounts_AvatarResize": "அவதாரங்களை அளவை",
"Accounts_AvatarSize": "avatar அளவு",
- "Accounts_AvatarStorePath": "அவதார் சேமிப்பு பாதை",
- "Accounts_AvatarStoreType": "அவதார் சேமிப்பு வகை",
"Accounts_BlockedDomainsList": "தடுக்கப்பட்ட களங்கள் பட்டியல்",
"Accounts_BlockedDomainsList_Description": "தடுக்கப்பட்டது களங்களின் கமாவால் பிரிக்கப்பட்ட பட்டியல்",
"Accounts_BlockedUsernameList": "தடுக்கப்பட்ட பயனர் பெயர் பட்டியல்",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "மின்னஞ்சல் சரிபார்ப்பு",
"Accounts_EmailVerification_Description": "நிச்சயமாக நீங்கள் இந்த வசதியை பயன்படுத்த சரியான SMTP அமைப்புகளை வைத்து கொள்ளுங்கள்",
"Accounts_Enrollment_Email": "பதிவு மின்னஞ்சல்",
- "Accounts_Enrollment_Email_Default": " வரவேற்கிறோம் [Site_Name] [Site_URL] போய், இன்றைக்கும் கிடைக்க சிறந்த திறந்த மூல அரட்டை தீர்வு முயற்சி!
",
+ "Accounts_Enrollment_Email_Default": " வரவேற்கிறோம் [Site_Name] [Site_URL] போய், இன்றைக்கும் கிடைக்க சிறந்த திறந்த மூல அரட்டை தீர்வு முயற்சி!
",
"Accounts_Enrollment_Email_Description": "முறையே பயனர் முழு பெயர், முதல் பெயர் அல்லது கடைசி பெயரை நீங்கள் [name], [fname], பயன்படுத்தலாம் [lname]. நீங்கள் பயனர் மின்னஞ்சல் ஐந்து [email] பயன்படுத்தலாம்.",
"Accounts_Enrollment_Email_Subject_Default": "வரவேற்கிறோம் [Site_Name]",
"Accounts_Iframe_api_method": "API முறை",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "பொது",
"Accounts_RegistrationForm_Secret_URL": "இரகசிய URL ஐ",
"Accounts_RegistrationForm_SecretURL": "பதிவு படிவம் இரகசிய URL ஐ",
- "Accounts_RegistrationForm_SecretURL_Description": "நீங்கள் உங்கள் பதிவு URL ஐ சேர்க்க வேண்டும் என்று ஒரு சீரற்ற சரமாக வழங்க வேண்டும். உதாரணம்: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "நீங்கள் உங்கள் பதிவு URL ஐ சேர்க்க வேண்டும் என்று ஒரு சீரற்ற சரமாக வழங்க வேண்டும். உதாரணம்: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "இணைந்ததற்கு பெயர் தேவை",
"Accounts_ShowFormLogin": "காட்டு-சார்ந்த தேதி",
"Accounts_UseDefaultBlockedDomainsList": "பயன்பாட்டு இயல்புநிலை தடுக்கப்பட்ட களங்கள் பட்டியல்",
"Accounts_UseDNSDomainCheck": "டிஎன்எஸ் இணைய சோதனை பயன்படுத்தவும்",
- "Accounts_UserAddedEmail_Default": " வரவேற்கிறோம் [Site_Name] [Site_URL] போய், இன்றைக்கும் கிடைக்க சிறந்த திறந்த மூல அரட்டை தீர்வு முயற்சி!
[email] மற்றும் கடவுச்சொல்லை: [password] நீங்கள் உங்கள் மின்னஞ்சல் பயன்படுத்தி உள்நுழையலாம் இருக்கலாம். நீங்கள் உங்கள் முதல் உள்நுழைவு பின்னர் அதை மாற்ற தேவைப்படலாம்.",
+ "Accounts_UserAddedEmail_Default": "
வரவேற்கிறோம் [Site_Name] [Site_URL] போய், இன்றைக்கும் கிடைக்க சிறந்த திறந்த மூல அரட்டை தீர்வு முயற்சி!
[email] மற்றும் கடவுச்சொல்லை: [password] நீங்கள் உங்கள் மின்னஞ்சல் பயன்படுத்தி உள்நுழையலாம் இருக்கலாம். நீங்கள் உங்கள் முதல் உள்நுழைவு பின்னர் அதை மாற்ற தேவைப்படலாம்.",
"Accounts_UserAddedEmail_Description": "நீங்கள் கீழ்கண்ட இடப்பயனர்கள் பயன்படுத்தலாம்:
[name], [fname], [lname] முறையே பயனர் முழு பெயர், முதல் பெயர் அல்லது கடைசி பெயர், ஐந்து. பயனர் மின்னஞ்சல் ஐந்து [email]. பயனரின் கடவுச்சொல்லை [password]. [Site_Name] மற்றும் [Site_URL] முறையே விண்ணப்ப பெயர் மற்றும் URL க்கான. ",
"Accounts_UserAddedEmailSubject_Default": "நீங்கள் சேர்க்கப் பட்டுள்ளது [Site_Name]",
"Activate": "செயல்படுத்த",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "சேவை விதிமுறைகள்",
"LDAP": "LDAP,",
"LDAP_CA_Cert": "கலிபோர்னியா சான்றிதழ்",
- "LDAP_Custom_Domain_Search": "விருப்ப இணைய தேடல்",
- "LDAP_Custom_Domain_Search_Description": "ஜெர்மானிய மற்றும் இணைப்பு தகவல் நிர்வகிக்கிறது மற்றும் அந்த வடிவம் JSON ஒரு துண்டு: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "இயல்புநிலை களப்",
"LDAP_Description": "பல தளங்கள் மற்றும் சேவைகள் இடையே ஒரு கடவுச்சொல்லை பகிர்ந்து ஒரு வசதி - LDAP, பல நிறுவனங்கள் ஒற்றை அடையாளம் வழங்க பயன்படுத்த என்று ஒரு படிநிலை தரவுத்தள உள்ளது. https://rocket.chat/docs/administrator-guides/authentication/ldap/: மேம்பட்ட கட்டமைப்பு தகவல் மற்றும் உதாரணங்கள், எங்கள் விக்கி கலந்தாலோசிக்கவும்.",
- "LDAP_Domain_Base": "இணைய தளம்",
- "LDAP_Domain_Base_Description": "பயனர்கள் மற்றும் குழுக்களுக்கு தேட வேண்டும் ஒரு LDAP உபபடிநிலை முழுவதும் தகுதியான டிஸ்டிங்கஷ்ட் நேம் (DN). நீங்கள் போன்ற பல சேர்க்க முடியும்; எனினும், ஒவ்வொரு குழு சேர்ந்தவை என்று பயனர்கள் அதே டொமைன் அடிப்படை வரையறுக்கப்பட்டிருக்க வேண்டும். நீங்கள் கட்டுப்படுத்தப்பட்ட பயனர் குழுக்கள் குறிப்பிட்டால், அந்த குழுக்கள் சேர்ந்தவை என்று பயனர்கள் மட்டுமே நோக்கம் இருக்கும். நாங்கள் உங்கள் டொமைன் தளமாக LDAP அடைவு கிளையின் மேல் நிலை குறிப்பிட மற்றும் அணுகல் கட்டுப்படுத்த தேடல் வடிகட்டி பயன்படுத்த பரிந்துரைக்கிறோம்.",
- "LDAP_Domain_Search_Filter": "இணைய தேடல் வடிகட்டி",
- "LDAP_Domain_Search_Filter_Description": "குறிப்பிட்ட, இந்த வடிகட்டி பொருந்தும் என்று பயனர்கள் மட்டுமே நுழைய அனுமதி வேண்டும் என்றால். எந்த வடிகட்டி குறிப்பிடப்பட்டால், குறிப்பிட்ட களப் அடிப்படை எல்லைக்குள் அனைத்து பயனர்கள் உள்நுழைய முடியும். ஆக்டிவ் டைரக்டரி எ.கா.: memberOf = CN = ROCKET_CHAT, OU = பொது Groups`. OpenLDAP ஆனது எ.கா (நீடிக்கவும் போட்டியில் தேடல்): OU: DN: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "இணைய தேடல் பொருள் வகை",
- "LDAP_Domain_Search_Object_Category_Description": "உங்கள் பயனர் அடையாளம் என்று * objectCategory *. * OpenLDAP ஆனது * காலியாக விடவும். எ.கா: person`, முதலியன",
- "LDAP_Domain_Search_Object_Class": "இணைய தேடல் பொருள் வகுப்பு",
- "LDAP_Domain_Search_Object_Class_Description": "உங்கள் பயனர் அடையாளம் என்று * objectClass *. எ.கா: organizationalPerson`, `user`,` inetOrgPerson`, முதலியன",
- "LDAP_Domain_Search_Password": "இணைய தேடல் கடவுச்சொல்",
- "LDAP_Domain_Search_Password_Description": "டொமைன் தேடல் பயனர் கடவுச்சொல்லை.",
- "LDAP_Domain_Search_User": "இணைய தேடல் பயனர்",
- "LDAP_Domain_Search_User_Description": "அவர்கள் உள்நுழையும் போது மற்ற பயனாளிகள் அங்கீகரிக்க பயனர் தேடுதல்களும் செய்கிறது என்று, LDAP பயனர். இது பொதுவாக மூன்றாம் தரப்பு ஒருங்கிணைவு குறிப்பாக உருவாக்கப்பட்ட ஒரு சேவை கணக்கு உள்ளது. ஒரு முழு தகுதி பெயரை பயன்படுத்த, அத்தகைய CN = நிர்வாகி `என, cn = பயனர்கள், DC = example, dc = com`.",
- "LDAP_Domain_Search_User_ID": "இணைய தேடல் பயனர் ஐடி",
- "LDAP_Domain_Search_User_ID_Description": "அங்கீகார முயலும், LDAP பயனர் அடையாளம் என்று ஒரு LDAP பண்பு. இந்த துறையில் `மிக ஆக்டிவ் டைரக்டரி நிறுவலுக்கு sAMAccountName` இருக்க வேண்டும், ஆனால் இது போன்ற OpenLDAP ஆனது போல் மற்ற LDAP, தீர்வுகள், ரூபாய் uid` இருக்கலாம். நீங்கள் மின்னஞ்சல் அல்லது என்ன பண்பு நீங்கள் விரும்பும் மூலம் பயனர் அடையாளம்: mail` பயன்படுத்த முடியும். நீங்கள் செய்த பயனர் பெயர் அல்லது மின்னஞ்சல் போன்ற பல அடையாளங்காட்டிகளானது பயன்படுத்தி உள்நுழைய அனுமதிக்க கமா பிரிக்கப்பட்ட பல மதிப்புகள் பயன்படுத்த முடியும்.",
+ "LDAP_BaseDN_Description": "பயனர்கள் மற்றும் குழுக்களுக்கு தேட வேண்டும் ஒரு LDAP உபபடிநிலை முழுவதும் தகுதியான டிஸ்டிங்கஷ்ட் நேம் (DN). நீங்கள் போன்ற பல சேர்க்க முடியும்; எனினும், ஒவ்வொரு குழு சேர்ந்தவை என்று பயனர்கள் அதே டொமைன் அடிப்படை வரையறுக்கப்பட்டிருக்க வேண்டும். நீங்கள் கட்டுப்படுத்தப்பட்ட பயனர் குழுக்கள் குறிப்பிட்டால், அந்த குழுக்கள் சேர்ந்தவை என்று பயனர்கள் மட்டுமே நோக்கம் இருக்கும். நாங்கள் உங்கள் டொமைன் தளமாக LDAP அடைவு கிளையின் மேல் நிலை குறிப்பிட மற்றும் அணுகல் கட்டுப்படுத்த தேடல் வடிகட்டி பயன்படுத்த பரிந்துரைக்கிறோம்.",
+ "LDAP_User_Search_Field_Description": "அங்கீகார முயலும், LDAP பயனர் அடையாளம் என்று ஒரு LDAP பண்பு. இந்த துறையில் `மிக ஆக்டிவ் டைரக்டரி நிறுவலுக்கு sAMAccountName` இருக்க வேண்டும், ஆனால் இது போன்ற OpenLDAP ஆனது போல் மற்ற LDAP, தீர்வுகள், ரூபாய் uid` இருக்கலாம். நீங்கள் மின்னஞ்சல் அல்லது என்ன பண்பு நீங்கள் விரும்பும் மூலம் பயனர் அடையாளம்: mail` பயன்படுத்த முடியும். நீங்கள் செய்த பயனர் பெயர் அல்லது மின்னஞ்சல் போன்ற பல அடையாளங்காட்டிகளானது பயன்படுத்தி உள்நுழைய அனுமதிக்க கமா பிரிக்கப்பட்ட பல மதிப்புகள் பயன்படுத்த முடியும்.",
+ "LDAP_User_Search_Filter_Description": "குறிப்பிட்ட, இந்த வடிகட்டி பொருந்தும் என்று பயனர்கள் மட்டுமே நுழைய அனுமதி வேண்டும் என்றால். எந்த வடிகட்டி குறிப்பிடப்பட்டால், குறிப்பிட்ட களப் அடிப்படை எல்லைக்குள் அனைத்து பயனர்கள் உள்நுழைய முடியும். ஆக்டிவ் டைரக்டரி எ.கா.: memberOf = CN = ROCKET_CHAT, OU = பொது Groups`. OpenLDAP ஆனது எ.கா (நீடிக்கவும் போட்டியில் தேடல்): OU: DN: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "அவர்கள் உள்நுழையும் போது மற்ற பயனாளிகள் அங்கீகரிக்க பயனர் தேடுதல்களும் செய்கிறது என்று, LDAP பயனர். இது பொதுவாக மூன்றாம் தரப்பு ஒருங்கிணைவு குறிப்பாக உருவாக்கப்பட்ட ஒரு சேவை கணக்கு உள்ளது. ஒரு முழு தகுதி பெயரை பயன்படுத்த, அத்தகைய CN = நிர்வாகி `என, cn = பயனர்கள், DC = example, dc = com`.",
"LDAP_Enable": "இயக்கு",
"LDAP_Enable_Description": "அங்கீகார க்கான LDAP பயன்படுத்த முயற்சிக்கும்.",
"LDAP_Encryption": "குறியாக்க",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "உள்நுழைவு சர்வர் ஒத்திசைந்து பயனர் தரவை வைத்திருக்கவும் (எ.கா.: பெயர், மின்னஞ்சல்).",
"LDAP_Sync_User_Data_FieldMap": "பயனர் தகவல்கள் களம் வரைபடம்",
"LDAP_Sync_User_Data_FieldMap_Description": "பயனர் கணக்கு துறைகள் (மின்னஞ்சல் போன்ற) LDAP இல் ஒரு சாதனை இருந்து மக்கள் எப்படி கட்டமைக்க (ஒரு முறை காணப்படுகிறது). உதாரணமாக, `{\" cn \"என்பது:\" பெயர் \",\" மெயில் \":\" மின்னஞ்சல் \"}: CN பண்பு இருந்து ஒரு நபரின் மனித வாசிக்கக்கூடிய பெயர், மற்றும் மெயில் பண்பு தங்கள் மின்னஞ்சல் தேர்வு செய்யும். கிடைக்க துறைகள் name`, மற்றும் `email` அடங்கும்:.",
- "LDAP_Sync_Users": "ஒத்திசைவு பயனர்கள்",
"LDAP_Test_Connection": "சோதனை இணைப்பு",
"LDAP_Unique_Identifier_Field": "தனித்துவ அடையாளங்காட்டி களம்",
"LDAP_Unique_Identifier_Field_Description": "எந்த துறையில், LDAP பயனர் மற்றும் Rocket.Chat பயனர் இணைக்க பயன்படுத்தப்படும். நீங்கள் ஒரு LDAP சாதனை இருந்து மதிப்பு பெற முயற்சி செய்ய கமா பிரிக்கப்பட்ட பல மதிப்புகள் தெரிவிக்க முடியும். இயல்புநிலை மதிப்பு `objectGUID, IBM-என்ட்ரி UUID, GUID அகம், dominoUNID, nsuniqueId, uidNumber` ஆகும்",
- "LDAP_Use_Custom_Domain_Search": "விருப்ப இணைய தேடல் பயன்படுத்தவும்",
- "LDAP_Use_Custom_Domain_Search_Description": "LDAP சர்வர் உள்ள பயனர்கள் தேட உங்கள் சொந்த வடிகட்டி எழுது.",
"LDAP_Username_Field": "பயனர்பெயர் துறையில்",
"LDAP_Username_Field_Description": "எந்த துறையில் * பயனர் பெயர் * புதிய பயனர்கள் பயன்படுத்தப்படும். உள்நுழைவு பக்கத்தில் தகவல் பயனர் பெயர் பயன்படுத்த காலியாக விடவும். நீங்கள் `# {givenName} போல், மிக டெம்ப்ளேட் குறிச்சொற்களை பயன்படுத்த முடியும். # {SN}:. இயல்புநிலை மதிப்பு `sAMAccountName` உள்ளது.",
"Leave_Group_Warning": "குழு \" %s\" பதில் விட்டு வெளியேற வேண்டும் என்பதில் உறுதியாக இருக்கிறீர்களா?",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "பயனர் தட்டச்சு %s முடியாது",
"Theme": "தீம்",
"theme-color-content-background-color": "உள்ளடக்க பின்புல வண்ணம்",
+ "theme-color-custom-scrollbar-color": "விருப்ப சுருள் கலர்",
+ "theme-color-info-font-color": "தகவல் எழுத்துரு வண்ணம்",
+ "theme-color-link-font-color": "இணைப்பு எழுத்துரு வண்ணம்",
"theme-color-primary-background-color": "முதன்மை பின்னணி வண்ணம்",
"theme-color-primary-font-color": "முதன்மை எழுத்துரு வண்ணம்",
"theme-color-secondary-background-color": "பின்னணி வண்ணமாக",
"theme-color-secondary-font-color": "இரண்டாம் எழுத்துரு வண்ணம்",
- "theme-color-tertiary-background-color": "மூன்றாம் நிலை பின்னணி வண்ணம்",
- "theme-color-tertiary-font-color": "மூன்றாம் நிலை எழுத்துரு வண்ணம்",
- "theme-color-link-font-color": "இணைப்பு எழுத்துரு வண்ணம்",
- "theme-color-info-font-color": "தகவல் எழுத்துரு வண்ணம்",
- "theme-color-custom-scrollbar-color": "விருப்ப சுருள் கலர்",
"theme-color-status-away": "அவே நிலைமை கலர்",
"theme-color-status-busy": "பிஸி நிலை கலர்",
"theme-color-status-offline": "அந்தஸ்து கலர்",
"theme-color-status-online": "ஆன்லைன் அந்தஸ்து கலர்",
+ "theme-color-tertiary-background-color": "மூன்றாம் நிலை பின்னணி வண்ணம்",
+ "theme-color-tertiary-font-color": "மூன்றாம் நிலை எழுத்துரு வண்ணம்",
"theme-color-unread-notification-color": "படிக்காத அறிவிப்புகள் கலர்",
"theme-custom-css": "தனிப்பயன் CSS",
"There_are_no_agents_added_to_this_department_yet": "இன்னும் இந்த துறை சேர்க்கப்பட்டது எந்த முகவர் உள்ளன.",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "உங்கள் மெயில்% கள் அனுப்பப்பட்டது",
"Your_password_is_wrong": "உங்கள் கடவுச்சொல் தவறு!",
"Your_push_was_sent_to_s_devices": "உங்கள் மிகுதி% கள் சாதனங்கள் அனுப்பப்பட்டது"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/th-TH.i18n.json b/packages/rocketchat-i18n/i18n/th-TH.i18n.json
new file mode 100644
index 0000000000000..d5aa81b5427b9
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/th-TH.i18n.json
@@ -0,0 +1,57 @@
+{
+ "#channel": "ช่องทาง",
+ "0_Errors_Only": "0 - แสดงข้อผิดพลาดเท่านั้น",
+ "1_Errors_and_Information": "1 - แสดงข้อผิดพลาดและข้อมูล",
+ "2_Erros_Information_and_Debug": "2 - แสดงข้อผิดพลาด, ข้อมูลและการแก้ปัญหา",
+ "403": "ไม่อนุญาต",
+ "500": "เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์",
+ "@username": "@ชื่อผู้ใช้",
+ "@username_message": "@ชื่อผู้ใช้ <ข้อความ0>",
+ "__username__is_no_longer__role__defined_by__user_by_": "_username_ ไม่ไช่ _role_by_user_by_",
+ "__username__was_set__role__by__user_by_": "_username_ was set _role_by_user_by",
+ "Accept": "ยอมรับ",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "ยอมรับการร้องขอ Livechat ถึงแม้จะไม่มี Agents ออนไลน์",
+ "Accept_with_no_online_agents": "ยอมรับโดยไม่มี Agents ออนไลน์",
+ "Access_not_authorized": "การเข้าถึงไม่ได้รับอนุมัติ",
+ "Access_Token_URL": "Access Token URL",
+ "Accessing_permissions": "กฏระเบียบการเข้าถึง",
+ "Account_SID": "บัญชี SID",
+ "Accounts": "บัญชี",
+ "Accounts_AllowAnonymousRead": "ยอมให้อ่านแบบไม่ระบุตัวตน",
+ "Accounts_AllowAnonymousWrite": "ยอมให้เขียนแบบไม่ระบุตัวตน",
+ "Accounts_AllowDeleteOwnAccount": "ยอมให้ผู้ใช้ลบบัญชีของตนเอง",
+ "Accounts_AllowedDomainsList": "รายชื่อ Domain ที่ยอมรับ",
+ "Accounts_AllowedDomainsList_Description": "รายชื่อ Domain ที่ยอมรับคั่นด้วยคอมม่า",
+ "Accounts_AllowEmailChange": "ยอมให้เปลี่ยนอีเมล์",
+ "Accounts_AllowPasswordChange": "ยอมให้เปลี่ยนพาสเวิร์ด",
+ "Accounts_AllowUserAvatarChange": "ยอมให้ผู้ใช้เปลี่ยนรูปประจำตัว",
+ "Accounts_AllowUsernameChange": "ยอมให้ผู้ใช้เปลี่ยนชื่อผู้ใช้",
+ "Accounts_AllowUserProfileChange": "ยอมให้แก้ไขข้อมูลผู้ใช้",
+ "Accounts_AvatarResize": "แก้ไขขนาดรูปประจำตัว",
+ "Accounts_AvatarSize": "ขนาดของรูปประจำตัว",
+ "Accounts_BlockedDomainsList": "รายชื่อ Domain ที่ไม่ยอมรับ",
+ "Accounts_BlockedDomainsList_Description": "รายชื่อ Domain ที่ไม่ยอมรับคั่นด้วยคอมม่า",
+ "Accounts_BlockedUsernameList": "รายชื่อผู้ใช้ที่ไม่ยอมรับ",
+ "Accounts_BlockedUsernameList_Description": "รายชื่อผู้ใช้ที่ไม่ยอมรับคั่นด้วยคอมม่า (ไม่สนใจตัวอักษร)",
+ "Accounts_CustomFields_Description": "คุณจะเป็น JSON ที่ถูกต้องโดยมี Keys เป็นชื่อประกอบไปด้วย Doctionary ของรายละเอียดของ Keys. ตัวอย่างเช่น:{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_DefaultUsernamePrefixSuggestion": "คำแนะนำสำหรับค่าเริ่มต้นของคำนำหน้าชื่อผู้ใช้",
+ "Accounts_denyUnverifiedEmail": "ปฏิเสธอีเมล์ที่ไม่ได้รับการตรวจสอบ",
+ "Accounts_EmailVerification": "การตรวจสอบอีเมล์",
+ "Accounts_EmailVerification_Description": "ต้องตั้งค่า SMTP เพื่อใช้งานฟีเจอร์นี้",
+ "Accounts_Enrollment_Email": "การลงทะเบียนอีเมล์",
+ "Accounts_Enrollment_Email_Default": "ยินดีต้อนรับสูง [Site_Name] ไปที่ [Site_URL] และทดลองใช้งานโปรแกรมแชทที่ดีที่สุดที่มี ณ ปัจจุบัน
",
+ "Accounts_Enrollment_Email_Subject_Default": "ยินดีต้อนรับสูง [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "ลืม session เมื่อปิดหน้าต่าง",
+ "Accounts_Iframe_api_method": "Api Method",
+ "Accounts_Iframe_api_url": "API URL",
+ "Accounts_iframe_enabled": "เปิดใช้งานแล้ว",
+ "Accounts_iframe_url": "Iframe Url",
+ "Accounts_LoginExpiration": "การเข้าระบบมีอายุเป็นจำนวนวัน",
+ "Accounts_ManuallyApproveNewUsers": "ตรวจสอบผู้ใช้ใหม่ด้วยมือ",
+ "Accounts_OAuth_Custom_Authorize_Path": "Authorize Path",
+ "Accounts_OAuth_Custom_Button_Color": "สีของปุ่ม",
+ "Accounts_OAuth_Custom_Button_Label_Color": "สีของตัวหนังสือบนปุ่ม",
+ "Accounts_OAuth_Custom_Button_Label_Text": "ตัวหนังสือบนปุ่ม",
+ "Accounts_OAuth_Custom_Enable": "เปิดใช้งาน",
+ "Accounts_OAuth_Custom_id": "Id"
+}
diff --git a/packages/rocketchat-i18n/i18n/tr.i18n.json b/packages/rocketchat-i18n/i18n/tr.i18n.json
index 210bb755effaa..ea6faebde1b9f 100644
--- a/packages/rocketchat-i18n/i18n/tr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/tr.i18n.json
@@ -10,13 +10,19 @@
"__username__is_no_longer__role__defined_by__user_by_": "__username__ adlı kullanıcı __user_by__ tarafından __role__ rolünden çıkarıldı.",
"__username__was_set__role__by__user_by_": "__username__ adlı kullanıcı __user_by__ tarafından __role__ rolüne atandı.",
"Accept": "Kabul Et",
- "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Canlı sohbet isteklerini çevrimiçi 'Firma Temsilcisi' yoksa da kabul et",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Canlı sohbet isteklerini çevrimiçi 'Müşteri Temsilcisi' yoksa da kabul et",
"Accept_with_no_online_agents": "Çevrimiçi 'Firma Temsilcisi' Olmadan da Kabul Et",
- "Access_not_authorized": "Erişim yetkisi yok",
- "Access_Token_URL": "Erişim Jetonu URL",
+ "access-mailer": "Posta Göndericisine Erişim",
+ "access-mailer_description": "Kullanıcılara toplu e-posta gönderme izni",
+ "access-permissions": "İzinler Ekranına Giriş",
+ "access-permissions_description": "Belirli roller için izinleri değiştir",
+ "Access_not_authorized": "Yetkisiz erişim",
+ "Access_Token_URL": "Erişim anahtarı URL",
"Accessing_permissions": "Erişim izinleri",
"Account_SID": "Hesap SID",
"Accounts": "Hesaplar",
+ "Accounts_AllowAnonymousRead": "Anonim okumaya izin ver",
+ "Accounts_AllowAnonymousWrite": "Anonim yazmaya izin ver",
"Accounts_AllowDeleteOwnAccount": "Kullanıcıların kendi hesaplarını silmelerine izin ver",
"Accounts_AllowedDomainsList": "İzinli Alan Adları Listesi",
"Accounts_AllowedDomainsList_Description": "Virgülle ayrılmış izin verilen alan adları listesi",
@@ -27,18 +33,19 @@
"Accounts_AllowUserProfileChange": "Kullanıcının Profilini Değiştirmesine izin ver",
"Accounts_AvatarResize": "Profil Resimlerini yeniden boyutlandır",
"Accounts_AvatarSize": "Profil Resmi Boyutu",
- "Accounts_AvatarStorePath": "Profil Resmi Depo Yolu",
- "Accounts_AvatarStoreType": "Profil Resmi Depolama Türü",
"Accounts_BlockedDomainsList": "Engellenen Alanlar Listesi",
"Accounts_BlockedDomainsList_Description": "Engellenen alanların virgülle ayrılmış listesi",
"Accounts_BlockedUsernameList": "Engellenen Kullanıcı Adı Listesi",
"Accounts_BlockedUsernameList_Description": "Engellenen kullanıcı adlarının virgülle ayrılmış listesi (harf büyüklüğüne duyarsız)",
- "Accounts_CustomFields_Description": "Anahtarların, alan ayarları sözlüğü bulunduran alan isimleri olduğu geçerli bir JSON olmalı. Örnek:{\n\n \"role\": {\n\n \"type\": \"select\",\n\n \"defaultValue\": \"student\",\n\n \"options\": [\"teacher\", \"student\"],\n\n \"required\": true,\n\n \"modifyRecordField\": {\n\n \"array\": true,\n\n \"field\": \"roles\"\n\n }\n\n },\n\n \"twitter\": {\n\n \"type\": \"text\",\n\n \"required\": true,\n\n \"minLength\": 2,\n\n \"maxLength\": 10\n\n }\n\n} ",
+ "Accounts_CustomFields_Description": "Anahtarların, alan ayarları sözlüğü bulunduran alan isimleri olduğu geçerli bir JSON olmalı. Örnek:{\n\n \"role\": {\n\n \"type\": \"select\",\n\n \"defaultValue\": \"student\",\n\n \"options\": [\"teacher\", \"student\"],\n\n \"required\": true,\n\n \"modifyRecordField\": {\n\n \"array\": true,\n\n \"field\": \"roles\"\n\n }\n\n },\n\n \"twitter\": {\n\n \"type\": \"text\",\n\n \"required\": true,\n\n \"minLength\": 2,\n\n \"maxLength\": 10\n\n }\n\n} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Kullanıcı Bilgilerini Göstermek için Özel alanlar",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Varsayılan kullanıcı adı ön eki tavsiyesi",
+ "Accounts_Default_User_Preferences_audioNotifications": "Sesli Mesaj için Varsayılan Uyarı",
"Accounts_denyUnverifiedEmail": "Doğrulanmamış e-posta'yı reddet",
"Accounts_EmailVerification": "E-Posta Doğrulama",
"Accounts_EmailVerification_Description": "Bu özelliği kullanmak için doğru SMTP ayarlarına sahip olduğunuza emin olun",
"Accounts_Enrollment_Email": "Kayıt E-Postası",
- "Accounts_Enrollment_Email_Default": " [Site_Name] sitesine hoşgeldiniz! [Site_URL] 'a gidin ve şu an mevcut en iyi açık kaynak sohbet çözümünü deneyin!
",
+ "Accounts_Enrollment_Email_Default": " [Site_Name] sitesine hoşgeldiniz! [Site_URL] 'a gidin ve şu an mevcut en iyi açık kaynak sohbet çözümünü deneyin!
",
"Accounts_Enrollment_Email_Description": "Kullanıcının tam adı, ad veya soyadı için sırayla, [lname], [name], [fname] kullanabilirsiniz. Kullanıcının e-postası için [email] kullanabilirsiniz.",
"Accounts_Enrollment_Email_Subject_Default": "[Site_Name] sitesine hoşgeldiniz!",
"Accounts_ForgetUserSessionOnWindowClose": "Pencere kapandığında kullanıcı oturumunu unut",
@@ -56,10 +63,16 @@
"Accounts_OAuth_Custom_id": "Kimlik",
"Accounts_OAuth_Custom_Identity_Path": "Kimlik Yolu",
"Accounts_OAuth_Custom_Login_Style": "Giriş Stili",
+ "Accounts_OAuth_Custom_Merge_Users": "Kullanıcıları birleştir",
"Accounts_OAuth_Custom_Scope": "Yetki Alanı",
"Accounts_OAuth_Custom_Secret": "Gizli Kod",
"Accounts_OAuth_Custom_Token_Path": "Token Yolu",
"Accounts_OAuth_Custom_Token_Sent_Via": "Token'ı Gönder",
+ "Accounts_OAuth_Custom_Username_Field": "Kullanıcı adı alanı",
+ "Accounts_OAuth_Drupal": "Drupal ile giriş yapma aktifleştirildi",
+ "Accounts_OAuth_Drupal_callback_url": "Drupal oAuth2 Yönlendirme URI",
+ "Accounts_OAuth_Drupal_id": "Drupal oAuth2 Müşteri Kimliği",
+ "Accounts_OAuth_Drupal_secret": "Drupal oAuth2 Müşteri Gizli Kodu",
"Accounts_OAuth_Facebook": "Facebook ile giriş",
"Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
"Accounts_OAuth_Facebook_id": "Facebook Uygulama Kimliği",
@@ -88,15 +101,19 @@
"Accounts_OAuth_Meteor_callback_url": "Meteor Callback URL",
"Accounts_OAuth_Meteor_id": "Meteor Kimliği",
"Accounts_OAuth_Meteor_secret": "Meteor Gizli Kodu",
+ "Accounts_OAuth_Proxy_host": "Vekil Sunucu",
+ "Accounts_OAuth_Proxy_services": "Proxy Hizmetleri",
"Accounts_OAuth_Twitter": "Twitter ile giriş",
"Accounts_OAuth_Twitter_callback_url": "Twitter Callback URL",
"Accounts_OAuth_Twitter_id": "Twitter Kimliği",
"Accounts_OAuth_Twitter_secret": "Twitter Gizli Kodu",
"Accounts_OAuth_Wordpress": "WordPress ile Giriş",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress Callback URL",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress Callback URL",
"Accounts_OAuth_Wordpress_id": "WordPress Kimliği",
"Accounts_OAuth_Wordpress_secret": "WordPress Gizli Kodu",
"Accounts_PasswordReset": "Parola Sıfırlama",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Doğrulama Servisi için Varsayılan İşlem",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Kimlik doğrulama servislerini kullanarak kayıt olan kullanıcılara verilecek varsayılan roller (virgülle ayrılmış olmalıdır)",
"Accounts_Registration_AuthenticationServices_Enabled": "Kimlik Doğrulama Hizmetleri ile Kayıt Olma",
"Accounts_RegistrationForm": "Kayıt formu",
"Accounts_RegistrationForm_Disabled": "Devre Dışı",
@@ -104,22 +121,33 @@
"Accounts_RegistrationForm_Public": "Genel",
"Accounts_RegistrationForm_Secret_URL": "Gizli URL",
"Accounts_RegistrationForm_SecretURL": "Kayıt Formu Gizli URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Kayıt URL'sine eklenmesi için rastgele bir harf dizisi sağlamalısınız. Örnek: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Kayıt URL'sine eklenmesi için rastgele bir harf dizisi sağlamalısınız. Örnek: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Üye Olmak İçin Ad İste",
"Accounts_RequirePasswordConfirmation": "Şifre Doğrulaması Gerektir",
+ "Accounts_SearchFields": "Arama sırasında kullanılacak alanlar",
+ "Accounts_SetDefaultAvatar": "Varsayılanı Avatar Seç",
"Accounts_ShowFormLogin": "Form-tabanlı Girişi Göster",
"Accounts_UseDefaultBlockedDomainsList": "Standart Engelli Domain Listesini Kullan",
"Accounts_UseDNSDomainCheck": "DNS Alan Adı Kontrolü'nü Kullan",
- "Accounts_UserAddedEmail_Default": " [Site_Name] sitesine hoşgeldiniz! [Site_URL] 'a gidin ve şu an mevcut en iyi açık kaynak sohbet çözümünü deneyin!
E-mail [email] ve Şifre: [password] 'nizi kullanarak giriş yapabilirsiniz. İlk girişinizden sonra bunları değiştirmeniz gerekebilir.",
+ "Accounts_UserAddedEmail_Default": "
[Site_Name] sitesine hoşgeldiniz! [Site_URL] 'a gidin ve şu an mevcut en iyi açık kaynak sohbet çözümünü deneyin!
E-mail [email] ve Şifre: [password] 'nizi kullanarak giriş yapabilirsiniz. İlk girişinizden sonra bunları değiştirmeniz gerekebilir.",
"Accounts_UserAddedEmail_Description": "
Kullanıcının tam adı, ad veya soyadı için sırasıyla [name], [fname], [lname] kullanabilirsiniz. Kullanıcının e-posta'sı için [email]. Kullanıcının parolası için [password]. Site adı ve Site URL'si için de [Site_Name] ve [Site_URL] kullanabilirsiniz. ",
"Accounts_UserAddedEmailSubject_Default": "[Site_Name] Sitesine Eklendiniz",
"Activate": "Etkinleştir",
"Activity": "Etkinlik",
"Add": "Ekle",
+ "add-oauth-service": "Oauth Hizmeti Ekle",
+ "add-oauth-service_description": "Yeni bir Oauth hizmeti ekleme izni",
+ "add-user": "Kullanıcı Ekle",
+ "add-user-to-any-c-room": "Herhangi bir Açık Kanal'a Kullanıcı Ekle",
+ "add-user-to-any-c-room_description": "Herhangi bir Açık Kanal'a Kullanıcı Ekleme İzni",
+ "add-user-to-any-p-room_description": "Kullanıcıyı herhangi bir özel kanala ekleme yetkisi",
"Add_agent": "Firma Temsilcisi Ekle",
"Add_custom_oauth": "Özel oauth ekle",
+ "Add_Domain": "Alan Adı Ekle",
+ "Add_files_from": "-den dosyalar ekle",
"Add_manager": "Yönetici ekle",
- "Add_user": "Kullanıcı Ekle",
+ "Add_Role": "Rol EKle",
+ "Add_user": "Kullanıcı ekle",
"Add_User": "Kullanıcı Ekle",
"Add_users": "Kullanıcı ekle",
"Adding_OAuth_Services": "OAuth Hizmetleri Ekleme",
@@ -128,6 +156,7 @@
"Additional_emails": "Ek E-postalar",
"Additional_Feedback": "Ek Geri Bildirim",
"Administration": "Yönetim",
+ "Adult_images_are_not_allowed": "Erişkin görüntülere izin verilmez",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "OAuth2 kimlik doğrulamadan sonra, kullanıcılar bu URL'ye yönlendirilecektir",
"Agent": "Firma Temsilcisi",
"Agent_added": "Firma Temsilcisi Eklendi",
@@ -136,21 +165,29 @@
"Alias_Format": "Takma Ad Formatı",
"Alias_Format_Description": "Slack'tan mesajları bir takma ad ile içe aktar. %s kullanıcının kullanıcı adı ile değiştirilecek. Eğer boşsa, herhangi bir takma ad kullanılmayacak.",
"Alias_Set": "Takma Ad Seti",
- "All": "Tüm",
+ "All": "Tümü",
"All_channels": "Daha fazla",
"All_logs": "Tüm Kayıtlar",
"All_messages": "Tüm mesajlar",
+ "All_users_in_the_channel_can_write_new_messages": "Kanaldaki tüm kullanıcılar yeni mesaj yazabilir.",
"Allow_Invalid_SelfSigned_Certs": "Kendinden İmzalı Sertifikalara İzin Ver",
"Allow_Invalid_SelfSigned_Certs_Description": "Bağlantı doğrulama ve önizlemeleri için geçersiz ve kendinden imzalı SSL sertifikalarına izin verin.",
+ "Allow_switching_departments": "Ziyaretçilerin bölüm değiştirmesine izin ver ",
+ "Always_open_in_new_window": "Her zaman yeni sekmede aç",
"Analytics_features_enabled": "Özellikler Etkin",
"Analytics_features_messages_Description": "Bir kullanıcının iletilerde yaptığı eylemlerle bağlantılı özel olayları izler.",
"Analytics_features_rooms_Description": "Bir kanal veya grup (silme, ayrılma, oluşturma) üzerindeki eylemlerle bağlantılı özel olayları izler.",
"Analytics_features_users_Description": "Kullanıcılar (Parola sıfırlama süreleri, profil resmi değiştirme, vb) ile ilgili eylemlerle bağlantılı özel olayları izler.",
+ "Analytics_Google": "Google Analytics",
+ "Analytics_Google_id": "İzleme Kimliği",
"and": "ve",
"And_more": "Ve __length __ kadar daha fazla",
"Animals_and_Nature": "Hayvanlar ve Doğa",
+ "Announcement": "Duyuru",
"API": "API",
"API_Analytics": "Mantıksal Analiz",
+ "API_Drupal_URL": "Drupal Sunucu URL ",
+ "API_Drupal_URL_Description": "Örnek: https://domain.com ( Sonunda slash (eğik çizgi) olmayacak şekilde )",
"API_Embed": "Gömülü ",
"API_Embed_Description": "Bir kullanıcı web sitesi linki paylaştığında, bu linkin önizlemesinin gösterilip gösterilemeyeceği",
"API_EmbedDisabledFor": "Kullanıcılar için Gömülü Özelliğini Devre Dışı Bırak",
@@ -159,10 +196,12 @@
"API_EmbedIgnoredHosts_Description": "Sunucuların veya CIDR adreslerinin virgülle ayrılmış listesi. Örnek : localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "Güvenli Portlar",
"API_EmbedSafePorts_Description": "Önizleme için izin verilen portların virgülle ayrılmış listesi.",
+ "API_Enable_CORS": "CORS'u etkinleştir",
"API_GitHub_Enterprise_URL": "Sunucu URL'si",
"API_GitHub_Enterprise_URL_Description": "Örnek: http://domain.com (sondaki eğik çizgiyi dahil etmeyin)",
"API_Gitlab_URL": "GitLab URL",
"API_Token": "API Jetonu",
+ "API_Upper_Count_Limit": "Azami Kayıt Süresi",
"API_User_Limit": "Kanala Eklenebilecek Tüm Kullanıcıların Sınırı",
"API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Anahtar",
@@ -173,19 +212,29 @@
"Application_updated": "uygulama güncellendi",
"Apply_and_refresh_all_clients": "Uygulayın ve tüm istemcilerin yenilemek",
"Archive": "Arşiv",
+ "archive-room": "Arşiv",
+ "archive-room_description": "Kanal Arşivleme İzni",
"are_also_typing": "yazıyor",
"are_typing": "yazıyor",
"Are_you_sure": "Emin misiniz?",
"Are_you_sure_you_want_to_delete_your_account": "Hesabınızı silmek istediğinizden emin misiniz?",
+ "assign-admin-role": "Admin Rolü Ata",
+ "assign-admin-role_description": "Diğer kullanıcılara admin rolü atama izmi",
"Assign_admin": "Yönetici Görevlendiriliyor",
"at": "at",
"AtlassianCrowd": "Atlassian Crowd",
"Attachment_File_Uploaded": "Dosya Yüklendi",
+ "Audio_message": "Sesli Mesaj",
+ "Audio_Notifications_Default_Alert": "Sesli Mesaj için Varsayılan Uyarı",
+ "Audio_Notifications_Value": "Varsayılan mesaj bildirim sesi",
"Auth_Token": "Kimlik Doğrulama Jetonu",
"Author": "Yazar",
"Authorization_URL": "yetkilendirme URL'si",
"Authorize": "Yetki vermek",
+ "auto-translate": "Otomatik Çeviri",
+ "auto-translate_description": "Otomatik tercüme aracı kullanım izni",
"Auto_Load_Images": "Fotoğrafları Otomatik Yükle",
+ "Auto_Translate": "Otomatik Çeviri",
"AutoLinker_Email": "AutoLinker E-posta",
"AutoLinker_Phone": "AutoLinker Telefon",
"AutoLinker_Phone_Description": "Otomatik olarak Telefon numaraları için bağlantılı. örneğin '(123) 456-7890`",
@@ -195,6 +244,9 @@
"AutoLinker_Urls_TLD": "AutoLinker TLD URL'ler",
"AutoLinker_Urls_www": "AutoLinker 'www' URL'ler",
"AutoLinker_UrlsRegExp": "AutoLinker URL Düzenli İfade",
+ "Automatic_Translation": "Otomatik Çeviri",
+ "AutoTranslate_Enabled": "Otomatik Çeviriyi etkinleştir",
+ "AutoTranslate_GoogleAPIKey": "Google API Anahtarı",
"Available": "Mevcut",
"Available_agents": "mevcut maddeler",
"Avatar": "Avatarı değiştir",
@@ -209,10 +261,14 @@
"Away_male": "Uzakta",
"Back": "Geri",
"Back_to_applications": "Geri uygulamalara",
+ "Back_to_chat": "Sohbete Dön ",
"Back_to_integrations": "Geri entegrasyonlar için",
"Back_to_login": "Giriş sayfasına geri dön",
"Back_to_permissions": "Geri izinleri",
+ "ban-user": "Kullanıcıyı Engelle",
+ "ban-user_description": "Kanaldan bir kullanıcıyı engelleme izni",
"Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta özellik. Görüntülü konferans görüşmesinin aktif olmasını gerektirir.",
+ "Block_User": "Kullanıcıyı engelle",
"Body": "vücut",
"bold": "kalın",
"bot_request": "Bot İsteği",
@@ -227,6 +283,7 @@
"busy_male": "meşgul",
"Busy_male": "Meşgul",
"by": "tarafından",
+ "cache_cleared": "Önbellek temizlendi",
"Cancel": "Vazgeç",
"Cancel_message_input": "Vazgeç",
"Cannot_invite_users_to_direct_rooms": "Odalar doğrudan kullanıcıları davet edemezsiniz",
@@ -237,14 +294,17 @@
"CAS_button_label_color": "Giriş butonu yazı rengi",
"CAS_button_label_text": "Giriş butonu etiketi",
"CAS_enabled": "Etkin",
+ "CAS_login_url": "SSO Giriş URL",
"CDN_PREFIX": "CDN Ön Ek",
"Certificates_and_Keys": "Sertifikalar ve Anahtarlar",
"Changing_email": "değişen e-posta",
+ "channel": "kanal",
"Channel": "Kanal",
"Channel_already_exist": "Kanal '#% s' zaten var.",
"Channel_already_Unarchived": "adı `#% s` ile Kanal arşivlenmemiş durumda zaten",
"Channel_Archived": "adı `#% s` ile Kanal başarıyla arşivlenen olmuştur",
"Channel_doesnt_exist": "`# %s` isminde bir kanal bulunmamaktadır.",
+ "Channel_Name_Placeholder": "Lütfen kanal ismini giriniz...",
"Channel_Unarchived": "adı `#% s` ile Kanal başarıyla Arşivlenmedi olmuştur",
"Channels": "Kanallar",
"Channels_list": "Kanallar",
@@ -259,8 +319,13 @@
"Choose_messages": "mesajları seçin",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "Mesajlarda kullanıcı adı önce görünecektir takma seçin.",
"Choose_the_username_that_this_integration_will_post_as": "Bu bütünleşme olarak yayınlayacağız adını seçin.",
+ "clear": "Temizle",
"Clear_all_unreads_question": "Tüm okunmayanlar temizlensin mi?",
+ "clear_cache_now": "Önbelleği şimdi temizle",
+ "clear_history": "Geçmişi temizle",
"Click_here": "Buraya Tıkla",
+ "Click_here_for_more_info": "Daha fazla bilgi için buraya tıklayınız",
+ "Click_to_join": "Katılmak için tıklayınız!",
"Client_ID": "Müşteri Kimliği",
"Client_Secret": "Müşteri Sırrı",
"Clients_will_refresh_in_a_few_seconds": "Müşteriler birkaç saniye içinde yenilenir",
@@ -274,6 +339,7 @@
"Commands": "Komutlar",
"Compact": "Kompakt",
"Confirm_password": "Parolanızı onaylayın",
+ "Content": "İçerik",
"Conversation": "Direkt Mesaj",
"Conversation_closed": "Konuşma kapalı: __comment__.",
"Convert_Ascii_Emojis": "ASCII kodu emojiye dönüştür",
@@ -284,18 +350,26 @@
"Count": "saymak",
"Cozy": "Rahat",
"Create": "oluşturmak",
+ "create-c_description": "Herkese açık kanalları oluşturma yetkisi",
+ "create-user": "Kullanıcı oluşturma",
+ "create-user_description": "Kullanıcı oluşturma yetkisi",
"Create_A_New_Channel": "Yeni Kanal Oluştur",
"Create_new": "Yeni oluştur",
"Created_at": "Oluşturulma saati",
"Created_at_s_by_s": " %s tarafından %s konumundaki düzenlendi",
+ "CRM_Integration": "CRM Entegrasyonu",
+ "CROWD_Reject_Unauthorized": "Doğrulanmamışları reddet",
"Current_Chats": "Güncel Sohbetler",
"Custom": "görenek",
"Custom_Emoji_Add": "Yeni",
+ "Custom_Emoji_Delete_Warning": "Emoji silme işlemi geri alınamaz",
+ "Custom_Emoji_Error_Invalid_Emoji": "Geçersiz emoji",
"Custom_Fields": "Özel Alanlar",
"Custom_oauth_helper": "OAuth sağlayıcısı kurarken, bir geri bildirim URL bildirmek gerekir. %s kullan.",
"Custom_oauth_unique_name": "Özel oauth benzersiz ad",
"Custom_Script_Logged_In": "Özel Senaryo kullanıcılar giriş için",
"Custom_Script_Logged_Out": "Özel Senaryo çıkış yapmış kullanıcılar için",
+ "Custom_Sound_Error_Invalid_Sound": "Geçersiz ses",
"Custom_Translations": "Özel Çeviriler",
"Dashboard": "gösterge paneli",
"Date": "tarih",
@@ -305,6 +379,7 @@
"Deactivate": "Devre dışı bırak",
"Default": "Varsayılan",
"Delete": "Sil",
+ "delete-message": "Mesaj Silme",
"Delete_message": "mesajı sil",
"Delete_my_account": "Hesabımı sil",
"Delete_Room_Warning": "Bir odayı silmek, oda içinde gönderilen tüm mesajları silecektir. Bu işlem geri alınamaz.",
@@ -324,11 +399,18 @@
"Desktop_Notifications_Enabled": "Masaüstü Bildirimleri Etkin",
"Direct_message_someone": "Doğrudan mesaj birisi",
"Direct_Messages": "Direkt Mesajlar",
+ "Direct_Reply_Password": "Şifre",
+ "Direct_Reply_Separator": "Ayraç",
+ "Direct_Reply_Username": "Kullanıcı Adı",
+ "Disable_Notifications": "Bildirimleri kapat",
"Display_offline_form": "Ekran çevrimdışı formu",
"Displays_action_text": "Görüntüler aksiyon metni",
"Do_you_want_to_change_to_s_question": " %s değiştirmek istiyor musunuz?",
"Domain": "domain",
+ "Domain_added": "alan adı eklendi",
+ "Domain_removed": "Alan adı kaldırıldı",
"Domains": "Etki",
+ "Download_Snippet": "İndir",
"Drop_to_upload_file": "Dosya yüklemek için sürükle",
"Dry_run": "kuru çalışma",
"Dry_run_description": "Sadece itibaren aynı adrese bir e-posta göndereceğiz. E-posta geçerli bir kullanıcı ait olmalıdır.",
@@ -338,6 +420,8 @@
"Duplicate_private_group_name": "' %s' isminde bir Özel Grup mevcut",
"Duration": "Süre",
"Edit": "Düzenle",
+ "edit-message": "Mesajı Düzenle",
+ "edit-message_description": "Bir odada bulunan mesajı düzenleme yetkisi",
"Edit_Custom_Field": "Düzenleme Özel Alan",
"Edit_Department": "Düzenleme Bölümü",
"edited": "düzenlendi",
@@ -381,6 +465,7 @@
"error-could-not-change-username": "adını değiştirmek olamazdı",
"error-delete-protected-role": "Korunan rol silinemiyor",
"error-department-not-found": "Bölümü bulunamadı",
+ "error-direct-message-file-upload-not-allowed": "Doğrudan mesajlarda dosya paylaşımına izin verilmiyor",
"error-duplicate-channel-name": "'__channel_name__' isminde bir kanal var",
"error-email-domain-blacklisted": "E-posta alanı kara listede",
"error-field-unavailable": "__field__ başka biri tarafından kullanılıyor :(",
@@ -397,6 +482,7 @@
"error-invalid-description": "geçersiz açıklama",
"error-invalid-domain": "geçersiz alan",
"error-invalid-email": "Geçersiz e-posta __email__",
+ "error-invalid-email-address": "Geçersiz eposta adresi",
"error-invalid-file-height": "Geçersiz dosya yüksekliği",
"error-invalid-file-type": "Geçersiz dosya türü",
"error-invalid-file-width": "Geçersiz dosya genişliği",
@@ -439,6 +525,10 @@
"error-you-are-last-owner": "Sen son sahibi. oda ayrılmadan önce yeni sahibini ayarlayın.",
"Error_changing_password": "Şifre değiştirmede hata",
"Esc_to": "Esc için",
+ "every_30_minutes": "30 dakikada bir",
+ "every_hour": "Saatte bir",
+ "every_six_hours": "6 saatte bir",
+ "Everyone_can_access_this_channel": "Bu kanala herkes erişebilir",
"Example_s": "Örnek: %s",
"Exclude_Botnames": "Botları Dışarıda Bırak",
"False": "Yanlış",
@@ -476,11 +566,13 @@
"Force_SSL": "kuvvet SSL",
"Force_SSL_Description": "* Dikkat! * _Force SSL_ ters proxy ile asla kullanılmamalıdır. Eğer ters proxy varsa, ORADA yönlendirme yapmak gerekir. Bu seçenek, ters vekil de yönlendirme yapılandırması izin vermez Heroku gibi dağıtımlar için var.",
"Forgot_password": "Şifrenizi mi unuttunuz",
+ "Forgot_password_section": "Şifremi unuttum",
"Forward": "İlet",
"Forward_chat": "Sohbeti İlet",
"Forward_to_department": "Bölüme İlet",
"Forward_to_user": "Kullanıcıya İlet",
"Frequently_Used": "Sıklıkla kullanılan",
+ "Friday": "Cuma",
"From": "itibaren",
"From_Email": "E-posta Gönderen",
"From_email_warning": "Uyarı: Nereden alanı, posta sunucusu ayarlarını tabidir.",
@@ -490,6 +582,7 @@
"Give_the_application_a_name_This_will_be_seen_by_your_users": "Uygulamayı bir ad verin. Bu kullanıcılar tarafından görülecektir.",
"Global": "global",
"GoogleTagManager_id": "Google Etiket Yöneticisi Kimliği",
+ "GoogleVision_Type_Faces": "Yüz Tanıma",
"Guest_Pool": "Misafir Havuzu",
"Hash": "esrar",
"Header": "üstbilgi",
@@ -517,6 +610,7 @@
"Iframe_Integration_receive_enable_Description": "Ata Pencere'nin Rocket Chat'e Komutlar Göndermesine İzin Ver",
"Iframe_Integration_send_enable": "Göndermeyi Etkinleştir",
"Iframe_Integration_send_enable_Description": "Olayları Ata Pencere'ye Gönder",
+ "Import": "İçeri Aktar",
"Importer_Archived": "arşivlenen",
"Importer_done": "Alma tamamlandığı!",
"Importer_finishing": "ithalat kadar bitirme.",
@@ -545,11 +639,14 @@
"Installed_at": "kurulu",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "senin ziyaretçiye talimatlar bir mesaj göndermek için formu doldurunuz",
"Integration_added": "Entegrasyon eklendi",
+ "Integration_Advanced_Settings": "Gelişmiş Ayarlar",
"Integration_Incoming_WebHook": "Gelen WebHook Entegrasyonu",
"Integration_New": "yeni Entegrasyon",
"Integration_Outgoing_WebHook": "Giden WebHook Entegrasyonu",
"Integration_updated": "Entegrasyon güncellendi",
"Integrations": "Entegrasyonlar",
+ "Integrations_Outgoing_Type_SendMessage": "Mesaj gönderildi",
+ "Integrations_Outgoing_Type_UserCreated": "Kullanıcı Oluşturuldu",
"InternalHubot": "İç Hubot",
"InternalHubot_ScriptsToLoad": "Scripts yüklemek için",
"InternalHubot_ScriptsToLoad_Description": "https://github.com/github/hubot-scripts/tree/master/src/scripts yüklemek için komut bir virgülle ayrılmış listesini girin",
@@ -565,6 +662,7 @@
"Invalid_secret_URL_message": "sağlanan URL geçersiz.",
"invisible": "görünmez",
"Invisible": "Görünmez",
+ "Invitation": "Davet",
"Invitation_HTML": "Davet HTML",
"Invitation_HTML_Default": " Sen davet edildi [Site_Name] [Site_URL] gidin ve bugün mevcut en iyi açık kaynak sohbet çözümü deneyin!
",
"Invitation_HTML_Description": "Aşağıdaki yer tutucuları kullanabilirsiniz: Alıcı e-posta için [email]. [Site_Name] ve [Site_URL] sırasıyla Uygulama Adı ve URL. ",
@@ -599,6 +697,7 @@
"Katex_Enabled_Description": "Kullanımına izin Katex mesajlarında matematik dizgi için",
"Katex_Parenthesis_Syntax": "İzin Parantez Sözdizimi",
"Katex_Parenthesis_Syntax_Description": "\\ [Katex blok \\] ve \\ (inline Katex \\) sözdizimi kullanımına izin",
+ "Keyboard_Shortcuts_Title": "Klavye Kısayolları",
"Knowledge_Base": "Bilgi tabanı",
"Label": "Etiket",
"Language": "Dil",
@@ -616,31 +715,20 @@
"Layout_Terms_of_Service": "Kullanım Koşulları",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Sertifika",
- "LDAP_Custom_Domain_Search": "Özel Alan Arama",
- "LDAP_Custom_Domain_Search_Description": "bağlama ve bağlantı bilgileri yönetir ve form olan JSON bir parça: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "varsayılan Etki Alanı",
"LDAP_Description": "Birden çok site ve hizmetler arasında bir parola paylaşımı için bir tesis - LDAP birçok şirket üzerinde tek oturum sağlamak için kullanmak hiyerarşik veritabanı. https://rocket.chat/docs/administrator-guides/authentication/ldap/: gelişmiş yapılandırma bilgi ve örnekler için, bizim wiki danışın.",
- "LDAP_Domain_Base": "Alan Bankası",
- "LDAP_Domain_Base_Description": "Eğer kullanıcılar ve gruplar için aramak istediğiniz bir LDAP alt ağacının tam ayırt edici ad (DN). İstediğiniz kadar ekleyebilirsiniz; Ancak, her grup kendisine ait kullanıcılarıyla aynı etki tabanı tanımlanmış olmalıdır. Eğer kısıtlı kullanıcı grupları belirtirseniz, bu gruplara ait sadece kullanıcıların kapsamında olacak. Size etki temel olarak LDAP dizin ağacının üst düzeyini belirlemek ve erişim kontrolü için arama filtresi kullanmanızı öneririz.",
- "LDAP_Domain_Search_Filter": "Domain Arama Filtresi",
- "LDAP_Domain_Search_Filter_Description": "Bu filtreyle eşleşen belirtilen, sadece kullanıcıların oturum izin verilecek olursa filtre belirtilirse., belirtilen etki alanı tabanının kapsamındaki tüm kullanıcılar oturum mümkün olacak. Active Directory örneğin `memberOf = cn = ROCKET_CHAT, ou = Genel gruplarının iş. OpenLDAP için (örn genişletilebilir maç arama) `ou: dn: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Domain Arama Nesne Kategori",
- "LDAP_Domain_Search_Object_Category_Description": "senin kullanıcıları tanımlamak * objectCategory *. * OpenLDAP * için boş bırakın. Örneğin, 'person` vs.",
- "LDAP_Domain_Search_Object_Class": "Domain Arama nesne sınıfı",
- "LDAP_Domain_Search_Object_Class_Description": "senin kullanıcıları tanımlamak * objectclass *. Örneğin, 'organizationalPerson`,' user`, 'inetOrgPerson` vs.",
- "LDAP_Domain_Search_Password": "Domain Arama Şifre",
- "LDAP_Domain_Search_Password_Description": "etki alanı arama kullanıcının parolası.",
- "LDAP_Domain_Search_User": "Domain Arama Kullanıcı",
- "LDAP_Domain_Search_User_Description": "oturum açtıklarında diğer kullanıcıların kimliğini doğrulamak için kullanıcı aramaları gerçekleştiren LDAP kullanıcı. Bu genellikle üçüncü parti entegrasyonları için özel olarak oluşturulan bir hizmet hesabıdır. Bir tam adını kullanın, örneğin cn = Yönetici 'olarak, cn Kullanıcıları, dc = Örnek, dc = com` =.",
- "LDAP_Domain_Search_User_ID": "Domain Arama Kullanıcı Kimliği",
- "LDAP_Domain_Search_User_ID_Description": "kimlik girişimleri LDAP kullanıcı tanımlayan LDAP özelliği. Bu alan `en Active Directory yüklemeleri için sAMAccountName` olmalı, ama böyle OpenLDAP gibi diğer LDAP çözümleri için` uid` olabilir. E-posta ya da her türlü özellik istediğiniz kullanıcıları tanımlamak için `mail` kullanabilirsiniz. Kullanıcıların kullanıcı adı veya e-posta gibi çoklu tanımlayıcıları kullanarak giriş için izin virgülle ayrılmış birden fazla değer kullanabilirsiniz.",
+ "LDAP_BaseDN_Description": "Eğer kullanıcılar ve gruplar için aramak istediğiniz bir LDAP alt ağacının tam ayırt edici ad (DN). İstediğiniz kadar ekleyebilirsiniz; Ancak, her grup kendisine ait kullanıcılarıyla aynı etki tabanı tanımlanmış olmalıdır. Eğer kısıtlı kullanıcı grupları belirtirseniz, bu gruplara ait sadece kullanıcıların kapsamında olacak. Size etki temel olarak LDAP dizin ağacının üst düzeyini belirlemek ve erişim kontrolü için arama filtresi kullanmanızı öneririz.",
+ "LDAP_User_Search_Field_Description": "kimlik girişimleri LDAP kullanıcı tanımlayan LDAP özelliği. Bu alan `en Active Directory yüklemeleri için sAMAccountName` olmalı, ama böyle OpenLDAP gibi diğer LDAP çözümleri için` uid` olabilir. E-posta ya da her türlü özellik istediğiniz kullanıcıları tanımlamak için `mail` kullanabilirsiniz. Kullanıcıların kullanıcı adı veya e-posta gibi çoklu tanımlayıcıları kullanarak giriş için izin virgülle ayrılmış birden fazla değer kullanabilirsiniz.",
+ "LDAP_User_Search_Filter_Description": "Bu filtreyle eşleşen belirtilen, sadece kullanıcıların oturum izin verilecek olursa filtre belirtilirse., belirtilen etki alanı tabanının kapsamındaki tüm kullanıcılar oturum mümkün olacak. Active Directory örneğin `memberOf = cn = ROCKET_CHAT, ou = Genel gruplarının iş. OpenLDAP için (örn genişletilebilir maç arama) `ou: dn: = ROCKET_CHAT`.",
+ "LDAP_Authentication": "Etkinleştir",
+ "LDAP_Authentication_Password": "Şifre",
+ "LDAP_Authentication_UserDN_Description": "oturum açtıklarında diğer kullanıcıların kimliğini doğrulamak için kullanıcı aramaları gerçekleştiren LDAP kullanıcı. Bu genellikle üçüncü parti entegrasyonları için özel olarak oluşturulan bir hizmet hesabıdır. Bir tam adını kullanın, örneğin cn = Yönetici 'olarak, cn Kullanıcıları, dc = Örnek, dc = com` =.",
"LDAP_Enable": "Etkinleştir",
"LDAP_Enable_Description": "Kimlik doğrulama için LDAP kullanmak için deneyin.",
"LDAP_Encryption": "Şifreleme",
"LDAP_Encryption_Description": "LDAP sunucusuna iletişim güvenliğini sağlamak için kullanılan şifreleme yöntemi. Örnekler `plain` (hiçbir şifreleme), (baştan şifreli)` SSL / LDAPS` ve `StartTLS` (şifreli iletişim için bir kez bağlı yükseltme) içerir.",
"LDAP_Host": "evsahibi",
"LDAP_Host_Description": "LDAP ana örneğin 'ldap.example.com` ya da' 10.0.0.30`.",
- "LDAP_Import_Users": "LDAP Kullanıcılarını İçe Aktar",
"LDAP_Merge_Existing_Users": "Varolan Kullanıcıları Birleştir",
"LDAP_Port": "LDAP Port",
"LDAP_Port_Description": "Liman LDAP erişmek için. LDAPS için `389` ya da '636`: örneğin",
@@ -650,12 +738,9 @@
"LDAP_Sync_User_Data_Description": "girişte sunucu ile senkronize kullanıcı verilerini tutmak (örneğin: isim, e-posta).",
"LDAP_Sync_User_Data_FieldMap": "Kullanıcı Veri Alanı Haritası",
"LDAP_Sync_User_Data_FieldMap_Description": "Kullanıcı hesabı alanları (e-posta gibi) LDAP rekor doldurulur nasıl yapılandırma (bir kez bulundu). Bir örnek olarak, `{\" cn \":\" ad \",\" posta \":\" e-posta \"}` cn özniteliği bir kişinin insan okunabilir adı ve posta özniteliği kendi e-posta seçecektir. Mevcut alanları name` ve 'email`' içerir.",
- "LDAP_Sync_Users": "Senkronizasyon Kullanıcılar",
"LDAP_Test_Connection": "Test bağlantısı",
"LDAP_Unique_Identifier_Field": "Benzersiz Tanımlayıcı Alan",
"LDAP_Unique_Identifier_Field_Description": "Hangi alan LDAP kullanıcı ve Rocket.Chat kullanıcıyı bağlamak için kullanılacaktır. LDAP kaydından değerini almak için denemek için virgülle ayrılmış birden fazla değer bilgilendirebilir. Varsayılan değer `Objectguıd, IBM-entryUUID, GUID, dominoUNID, nsuniqueId, uidNumber` olduğunu",
- "LDAP_Use_Custom_Domain_Search": "Özel Alan Arama kullanın",
- "LDAP_Use_Custom_Domain_Search_Description": "LDAP sunucusunda kullanıcıları aramak için kendi filtresini yazın.",
"LDAP_Username_Field": "Adı Alan",
"LDAP_Username_Field_Description": "Hangi alan yeni kullanıcılar için * kullanıcı adı * olarak kullanılacaktır. giriş sayfasında haberdar adını kullanmak için boş bırakın. Sen # {givenName} `gibi, çok şablon etiketlerini kullanabilirsiniz. # {Sn}`. Varsayılan değer `sAMAccountName` olduğunu.",
"Leave_Group_Warning": "Eğer grup \" %s\" ayrılmak istediğinize emin misiniz?",
@@ -707,6 +792,7 @@
"Managing_assets": "varlıkları yönetmek",
"Managing_integrations": "entegrasyonları yönetme",
"Mark_as_read": "Okundu olarak işaretle",
+ "Mark_as_unread": "Okunmamış olarak işaretle",
"Markdown_Headers": "Markdown Başlıkları",
"Markdown_SupportSchemesForLink": "Bağlantı için Markdown Destek Programları",
"Markdown_SupportSchemesForLink_Description": "izin verilen programların virgülle ayrılmış listesi",
@@ -745,6 +831,7 @@
"Message_ShowEditedStatus": "Düzenlenen Durumu Göster",
"Message_ShowFormattingTips": "Biçimlendirme İpuçlarını göster",
"Message_starring": "oynadığı Mesaj",
+ "Message_TimeAndDateFormat": "Saat ve tarih biçimi",
"Message_TimeFormat": "Zaman formatı",
"Message_TimeFormat_Description": "Ayrıca bkz: Moment.js ",
"Message_too_long": "çok uzun İleti",
@@ -757,6 +844,8 @@
"Meta_msvalidate01": "MSValidate.01",
"Meta_robots": "Robotlar",
"minutes": "dakika",
+ "Mobile": "Mobil",
+ "Monday": "Pazartesi",
"More_channels": "Daha fazla",
"More_direct_messages": "Daha direkt mesajlar",
"More_groups": "Daha fazla özel grup",
@@ -797,11 +886,13 @@
"No_starred_messages": "Favori iletin yok",
"No_user_with_username_%s_was_found": "\" %s\" adında hiçbir kullanıcı bulunamadı!",
"Node_version": "düğüm versiyonu",
+ "Normal": "Normal",
"Not_authorized": "Yetkili değil",
"Not_Available": "Müsait değil",
"Not_found_or_not_allowed": "Bulunamadı veya izin verilmiyor",
"Nothing": "Hiçbir şey",
"Nothing_found": "Bulunamadı",
+ "Notification_Duration": "Bildirim süresi",
"Notifications": "Bildirimler",
"Notify_all_in_this_room": "Bu odadaki tüm bildirimleri göster",
"Num_Agents": "# Ajanlar",
@@ -809,6 +900,7 @@
"OAuth_Application": "OAuth Uygulaması",
"OAuth_Applications": "OAuth Uygulamaları",
"Objects": "nesneler",
+ "Off": "Kapalı",
"Off_the_record_conversation": "Off-the-record Konuşma",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-kayıt konuşma tarayıcınız veya aygıt için geçerli değildir.",
"Offline": "Çevrimdışı",
@@ -819,6 +911,7 @@
"Offline_message": "Çevrimdışı mesaj",
"Offline_success_message": "Çevrimdışı başarı mesajı",
"Offline_unavailable": "Çevrimdışı kullanılamıyor",
+ "On": "Açık",
"Online": "Çevrimiçi",
"Only_you_can_see_this_message": "Sadece siz bu mesajı görebilirsiniz",
"Oops!": "Hata",
@@ -903,6 +996,7 @@
"Push_test_push": "Test",
"Query": "Sorgu",
"Query_description": "e-posta göndermek için hangi kullanıcıların belirlemek için ek şartlar. Abone olmayan kullanıcılar otomatik sorgudan kaldırılır. Bu geçerli bir JSON olmalıdır. Örnek: \"{\" createdAt \": {\" $ gt \": {\" $ tarihi \":\" 2015-01-01T00: 00: 00.000Z \"}}}\"",
+ "Queue": "Kuyruk",
"quote": "alıntı",
"Quote": "Alıntı",
"Random": "rasgele",
@@ -913,8 +1007,10 @@
"Refresh_keys": "Yenile tuşları",
"Refresh_your_page_after_install_to_enable_screen_sharing": "Ekran paylaşımını etkinleştirmek için yükledikten sonra sayfayı yenileyin",
"Register": "Yeni hesap ",
+ "Registration": "Kayıt",
"Registration_Succeeded": "Kayıt Başarılı",
"Release": "serbest bırakma",
+ "Reload": "Yeniden yükle",
"Remove": "Kaldır",
"Remove_Admin": "Yöneticiliğini kaldır",
"Remove_as_moderator": "moderatör olarak kaldır",
@@ -923,6 +1019,7 @@
"Remove_from_room": "odadan kaldır",
"Remove_someone_from_room": "odadan birini çıkarın",
"Removed": "Kaldırılan",
+ "Reply": "Yanıtla",
"Report_Abuse": "Uygunsuz",
"Report_exclamation_mark": "Rapor!",
"Report_sent": "rapor gönderildi",
@@ -962,6 +1059,7 @@
"SAML_Custom_Generate_Username": "Kullanıcı Adı Üret",
"SAML_Custom_Issuer": "Özel Yayıncı",
"SAML_Custom_Provider": "Özel Sağlayıcı",
+ "Saturday": "Cumartesi",
"Save": "Kaydet",
"Save_changes": "Değişiklikleri kaydet",
"Save_Mobile_Bandwidth": "Mobil Kotanı Koru",
@@ -978,8 +1076,10 @@
"seconds": "saniye",
"Secret_token": "gizli belirteç",
"Select_a_department": "Bir bölümü seçmek",
+ "Select_a_user": "Kullanıcı seç",
"Select_an_avatar": "Bir avatar seç",
"Select_file": "Dosya seç",
+ "Select_role": "Rol seç",
"Select_service_to_login": "Bilgisayarınızdan veya aşağıda ki servislerden birini kullanarak resim yükleyebilirsiniz",
"Select_user": "seç kullanıcı",
"Select_users": "seç kullanıcılar",
@@ -1010,8 +1110,11 @@
"Should_exists_a_user_with_this_username": "Kullanıcı zaten mevcut olması gerekir.",
"Show_all": "Tümünü göster",
"Show_more": "Daha fazla göster",
+ "show_offline_users": "çevrimdışı kullanıcıları göster",
+ "Show_on_registration_page": "Kayıt sayfasında göster",
"Show_only_online": "yalnızca çevrimiçi göster",
"Show_preregistration_form": "ön kayıt formunu göster",
+ "Show_queue_list_to_all_agents": "Kuyruk listesini tüm temsilcilere göster",
"Showing_archived_results": " %s arşivlenmiş sonuçlar gösteriliyor
",
"Showing_online_users": "__total__ kullanıcıdan __total_showing__ gösteriliyor",
"Showing_results": " %s kayıt bulundu
",
@@ -1039,6 +1142,7 @@
"SSL": "SSL",
"Star_Message": "Favorilere ekle",
"Starred_Messages": "Favori İletilerim",
+ "Start": "Başlat",
"Start_audio_call": "Ses aramayı başlatmak",
"Start_Chat": "Sohbete Başla",
"Start_of_conversation": "Konuşma Başladı",
@@ -1092,20 +1196,24 @@
"The_user_wont_be_able_to_type_in_s": " %s kullanıcısı yazmaya mümkün olmayacaktır",
"Theme": "Tema",
"theme-color-content-background-color": "İçerik Arka Plan Rengi",
+ "theme-color-custom-scrollbar-color": "Özel Scrollbar Renk",
+ "theme-color-info-font-color": "Bilgi Yazı Rengi",
+ "theme-color-link-font-color": "Bağlantı Yazı Rengi",
"theme-color-primary-background-color": "Birincil Arka Plan Rengi",
"theme-color-primary-font-color": "Birincil Yazı Rengi",
"theme-color-secondary-background-color": "İkincil Arka Plan Rengi",
"theme-color-secondary-font-color": "İkincil Yazı Rengi",
- "theme-color-tertiary-background-color": "Tersiyer Arka Plan Rengi",
- "theme-color-tertiary-font-color": "Tersiyer Yazı Rengi",
- "theme-color-link-font-color": "Bağlantı Yazı Rengi",
- "theme-color-info-font-color": "Bilgi Yazı Rengi",
- "theme-color-custom-scrollbar-color": "Özel Scrollbar Renk",
"theme-color-status-away": "Uzakta Durumu Rengi",
"theme-color-status-busy": "Meşgul Durumu Rengi",
"theme-color-status-offline": "Çevrimdışı Durumu Rengi",
"theme-color-status-online": "Çevrimiçi Durumu Rengi",
+ "theme-color-tertiary-background-color": "Tersiyer Arka Plan Rengi",
+ "theme-color-tertiary-font-color": "Tersiyer Yazı Rengi",
"theme-color-unread-notification-color": "Okunmamış Bildirim Rengi",
+ "theme-color-rc-color-error": "Hata",
+ "theme-color-rc-color-alert": "Uyarı",
+ "theme-color-rc-color-success": "Başarı",
+ "theme-color-rc-color-content": "İçerik",
"theme-custom-css": "özel CSS",
"There_are_no_agents_added_to_this_department_yet": "Bu bölüme eklenen herhangi bir müşteri temsilcisi henüz yoktur.",
"There_are_no_integrations": "Entegrasyon yok.",
@@ -1115,6 +1223,7 @@
"This_is_a_push_test_messsage": "Bu itme testi messsage olduğunu",
"This_room_has_been_archived_by__username_": "Bu oda __username__ tarafından arşivlenmiştir.",
"This_room_has_been_unarchived_by__username_": "Bu oda __username__ tarafından arşivden kaldırıldılmıştır.",
+ "Thursday": "Perşembe",
"Time_in_seconds": "Zaman, saniye olarak",
"Title": "Başlık",
"Title_bar_color": "Başlık çubuğu rengi",
@@ -1129,6 +1238,7 @@
"Trigger_Words": "tetikleyici Kelimeler",
"Triggers": "tetikleyiciler",
"True": "Doğru",
+ "Tuesday": "Salı",
"Type": "tip",
"Type_your_email": "E-postanızı yazın",
"Type_your_message": "Mesajınızı yazın",
@@ -1144,6 +1254,9 @@
"Unread_Rooms": "Okunmamış Odalar",
"Unread_Rooms_Mode": "Okunmamış Odalar Modu",
"Unstar_Message": "Yıldızı kaldır",
+ "Updated_at": "Güncelleme zamanı",
+ "Upload_file_description": "Dosya açıklaması",
+ "Upload_file_name": "Dosya adı",
"Upload_file_question": "Dosya yükle",
"Uploading_file": "Dosya yükleniyor ...",
"Uptime": "uptime",
@@ -1155,6 +1268,7 @@
"Use_this_username": "Bu kullanıcı adını kullan",
"Use_uploaded_avatar": "Yüklenen avatarı kullanın",
"Use_url_for_avatar": "avatar için url kullanın",
+ "User": "Kullanıcı",
"User__username__is_now_a_moderator_of__room_name_": "Kullanıcı __username__ adlı şimdi __room_name__ bir moderatör olduğunu",
"User__username__is_now_a_owner_of__room_name_": "Kullanıcı __username__ adlı şimdi __room_name__ bir sahibidir",
"User__username__removed_from__room_name__moderators": "Kullanıcı __username__ adlı __room_name__ moderatörler kaldırıldı",
@@ -1169,6 +1283,7 @@
"User_has_been_muted_in_s": "Kullanıcı %s sesi kapatıldı",
"User_has_been_removed_from_s": "Kullanıcı %s kaldırıldı",
"User_Info": "Kullanıcı bilgisi",
+ "User_Interface": "Kullanıcı Arayüzü",
"User_is_no_longer_an_admin": "Kullanıcı artık bir yönetici değil",
"User_is_now_an_admin": "Kullanıcı şimdi bir yönetici",
"User_joined_channel": "Kanala katıldı.",
@@ -1200,17 +1315,24 @@
"Username_invalid": "%s geçerli bir kullanıcı adı değil, Kullanıcı adınızı seçerken sadece harfler, sayılar, noktalar, tireler ve alt çizgiler kullanın",
"Username_is_already_in_here": "`@ %s` zaten burada.",
"Username_is_not_in_this_room": "Kullanıcı `# %s` bu odada değil.",
+ "Username_Placeholder": "Lütfen kullanıcı adlarını giriniz...",
"Username_title": "Bir kullanıcı adı belirle",
"Username_wants_to_start_otr_Do_you_want_to_accept": "__username__ adlı OTR başlamak istiyor. kabul etmek istiyor musunuz?",
"Users": "Kullanıcılar",
+ "Users_added": "Kullanıcılar eklendi",
"Users_in_role": "rolü Kullanıcılar",
"UTF8_Names_Slugify": "UTF8 İsimler Slugify",
"UTF8_Names_Validation": "UTF8 İsimler Doğrulama",
"UTF8_Names_Validation_Description": "özel karakterler ve boşluklar izin vermeyin. _ Ve - kullanabilirsiniz. ancak adının sonunda",
+ "Validate_email_address": "Eposta adresini doğrula",
+ "Verification_Email": "Hesabınızı doğrulamak için buraya tıklayın",
"Verification_email_sent": "Doğrulama e-postası gönderildi",
"Verified": "Doğrulanmış",
+ "Verify": "Doğrula",
"Version": "versiyon",
"Video_Chat_Window": "Görüntülü Sohbet",
+ "Video_Conference": "Video Konferans",
+ "view-statistics": "İstatistikleri Görüntüle",
"View_All": "Hepsini Gör",
"View_Logs": "Görünüm Günlükleri",
"View_mode": "Görünüm modu",
@@ -1234,6 +1356,7 @@
"WebRTC_Enable_Private": "Özel Kanallar için etkinleştir",
"WebRTC_Servers": "STUN / DÖNÜŞ Sunucular",
"WebRTC_Servers_Description": "virgülle ayrılmış STUN ve TURN sunucularının listesi. şifre @ sersemletici: Kullanıcı adı, şifre ve port biçiminde `adı izin verilen konak: port` veya` kullanıcı adı: şifre @ dönüş: host: port`.",
+ "Wednesday": "Çarşamba",
"Welcome": "Hoşgeldin %s .",
"Welcome_to_the": "Hoşgeldiniz",
"Why_do_you_want_to_report_question_mark": "Neden rapor istiyorsun?",
@@ -1257,6 +1380,7 @@
"You_have_been_muted": "Sen yok sayıldı ve bu odada konuşamıyor",
"You_have_not_verified_your_email": "E-postanızı kontrol etmediniz.",
"You_have_successfully_unsubscribed": "Mail listemizin aboneliğinden başarıyla çıktınız.",
+ "You_must_join_to_view_messages_in_this_channel": "Bu kanaldaki mesajları görmek için giriş yapmalısınız",
"You_need_confirm_email": "Giriş yapabilmek için öncelikle e-posta adresinizi onaylamanız gerekmektedir!",
"You_need_install_an_extension_to_allow_screen_sharing": "Ekran paylaşımını sağlamak için bir uzantı yüklemeye gerek",
"You_need_to_change_your_password": "Şifrenizi değiştirmek gerekir",
@@ -1275,4 +1399,4 @@
"Your_mail_was_sent_to_s": "Posta %s gönderildi",
"Your_password_is_wrong": "Parolanız yanlış!",
"Your_push_was_sent_to_s_devices": "Sizin itme %s cihazlara gönderildi"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/ug.i18n.json b/packages/rocketchat-i18n/i18n/ug.i18n.json
index d3a1dc7c7cfad..876231c3ddef6 100644
--- a/packages/rocketchat-i18n/i18n/ug.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ug.i18n.json
@@ -21,8 +21,6 @@
"Accounts_AllowUserProfileChange": "ئاكونت ئەزانىڭ ماتېرىيالىنى ئۆزگەرتىشكە رۇخسەت قىلدى",
"Accounts_AvatarResize": "ئاكونت باش سۈرئەتنىڭ چوڭ كىچىكلىكىنى تەڭشەش",
"Accounts_AvatarSize": "ئاكونت باش سۈرئەتنىڭ چوڭ كىچىكلىكى",
- "Accounts_AvatarStorePath": "ئاكونت باش سۈرئەت ساقلاش ئادرېسى",
- "Accounts_AvatarStoreType": "ئاكونت باش سۈرئەت ساقلاش تىپى",
"Accounts_BlockedDomainsList": "ئاكونت تور بەت نامى تىزىملىكىنى توسۇۋېتىلدى",
"Accounts_BlockedDomainsList_Description": "چىكىتلىك پەش ئارقىلىق توسۇۋېتىلگەن توربەت نامى تىزىملىكى",
"Accounts_BlockedUsernameList": "ئاكونت مەنئىي قىلغان ئەزا تىزىملىكى",
@@ -31,7 +29,7 @@
"Accounts_EmailVerification": "ئاكونت ئىلخەت تەكشۈرۈپ ئىسپاتلاش",
"Accounts_EmailVerification_Description": "نىڭ توغرا تەڭشەكلىرىنى جەزىملەشتۈرۈڭSTP،بۇ ئىقتىدارنى ئىشلىتىش ئۈچۈن",
"Accounts_Enrollment_Email": "ئىلخەتكە تىزىملىتىش",
- "Accounts_Enrollment_Email_Default": "كەلگىنىڭىزنى قارشى ئالىمىز [Site_Name] بۇنىڭغا ئۆتۈش[Site_URL] ، ھەمدە ھازىرقى ئەڭ ئىلغار بولغان ئورۇق كود پاراڭلىشىشنى ھەل قىلىش پىلانىنى سىناپ بېقىڭ !
",
+ "Accounts_Enrollment_Email_Default": "كەلگىنىڭىزنى قارشى ئالىمىز [Site_Name] بۇنىڭغا ئۆتۈش[Site_URL] ، ھەمدە ھازىرقى ئەڭ ئىلغار بولغان ئورۇق كود پاراڭلىشىشنى ھەل قىلىش پىلانىنى سىناپ بېقىڭ !
",
"Accounts_Enrollment_Email_Description": "سىز تۆۋەندىكى ئورۇن ئىگىلەش بەلگىلەرنى ئىشلىتەلەيسىز :ئىسىم_فامىلىسى [name]、ئىسمى [fname] ياكى فامىلىسى[lname]。 ئىلخەت[email]。 تور بېكەت ئىسمى[Site_Name] ۋە توربېكەت ئادرېسى [Site_URL]。 ",
"Accounts_Enrollment_Email_Subject_Default": "زىيارەت قىلغىنىڭىزنى قارشى ئالىمىز [Site_Name]",
"Accounts_Iframe_api_method": "API ئۇسۇلى",
@@ -95,12 +93,12 @@
"Accounts_RegistrationForm_Public": "ئاشكارا",
"Accounts_RegistrationForm_Secret_URL": "شەخسىي ئادرېسى",
"Accounts_RegistrationForm_SecretURL": "شەخسىي تىزىملىتىش جەدۋىلى ",
- "Accounts_RegistrationForm_SecretURL_Description": "https://demo.rocket.chat/register/[secret_hash] سىز چوقۇم خالىغان ھەرپ-بەلگە تىزىقى بىلەن تەمىنلىشىڭىز كېرەك ، ئۇ ھەرپ-بەلگە تىزىقى سىزنىڭ تىزىملىتىش ئادرېسىڭىزغا قېتىلىدۇ. مەسىلەن: مۇنداق",
+ "Accounts_RegistrationForm_SecretURL_Description": "https://open.rocket.chat/register/[secret_hash] سىز چوقۇم خالىغان ھەرپ-بەلگە تىزىقى بىلەن تەمىنلىشىڭىز كېرەك ، ئۇ ھەرپ-بەلگە تىزىقى سىزنىڭ تىزىملىتىش ئادرېسىڭىزغا قېتىلىدۇ. مەسىلەن: مۇنداق",
"Accounts_RequireNameForSignUp": "ئىسىم_فامىلە يازغاندىن كېيىن ئاندىن تىزىملىتىلىدۇ",
"Accounts_ShowFormLogin": "جەدۋەلنى ئاساس قىلغاندىكى كىرىش يۈزىنى كۆرسىتىدۇ",
"Accounts_UseDefaultBlockedDomainsList": "بەلگىلەنگەن دائىرە نامى توسۇش تىزىملىكىنى ئىشلىتىش",
"Accounts_UseDNSDomainCheck": "دائىرە نامىنى دەلىللەشنى ئىشلىتىشDNS",
- "Accounts_UserAddedEmail_Default": "زىيارەت قىلغىنىڭىزنى قارشى ئالىمىز [Site_Name] يۆتكىلىپ[Site_URL] ، ھەمدە ھازىرقى ئەڭ ئىلغار بولغان ئوچۇق كود پاراڭلىشىشنى ھەل قىلىش پىلانىنى سىناپ كۆرۈڭ !
سىز ئۆزىڭىزنىڭ ئىلخەت ئادرېسنى ئىشلەتسىڭىز بولىدۇ:[email] ۋە مەخپىي نومۇر:[password] سىز تۇنجى قېتىم كىرگەندە مەخپىي نومۇرنى ئالماشتۇرۇشقا موھتاج بولىسىز .",
+ "Accounts_UserAddedEmail_Default": "
زىيارەت قىلغىنىڭىزنى قارشى ئالىمىز [Site_Name] يۆتكىلىپ[Site_URL] ، ھەمدە ھازىرقى ئەڭ ئىلغار بولغان ئوچۇق كود پاراڭلىشىشنى ھەل قىلىش پىلانىنى سىناپ كۆرۈڭ !
سىز ئۆزىڭىزنىڭ ئىلخەت ئادرېسنى ئىشلەتسىڭىز بولىدۇ:[email] ۋە مەخپىي نومۇر:[password] سىز تۇنجى قېتىم كىرگەندە مەخپىي نومۇرنى ئالماشتۇرۇشقا موھتاج بولىسىز .",
"Accounts_UserAddedEmail_Description": "سىز تۆۋەنكى ئورۇن ئىگىلەش بەلگىسى ئىشلىتەلەيسىز:
[name], [fname], [lname] ئايرىم ھالدا ئابونتنىڭ تولۇق ئىسمى ، ئىسمى ياكى فامىلىسى بولىدۇ. [email] ئابونتنىڭ ئىلخىتى بولىدۇ [password] ئابونتنىڭ مەخپىي نومۇرى بولىدۇ [Site_Name] ۋە [Site_URL] ئايرىم ھالدا توربەت ئىسمى ۋە تور بەر ئادرېسى بولىدۇ ",
"Accounts_UserAddedEmailSubject_Default": "گە قاچىلاندىڭىز [Site_Name] سىز",
"Activate": "قوزغىتىش",
@@ -565,24 +563,12 @@
"Layout_Terms_of_Service": "مۇلازىمەت تارمىقى",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA گۇۋاھنامىسى",
- "LDAP_Custom_Domain_Search": "ئۆزى بېكىتكەن تورنامى ئىزدەش شەرتى",
- "LDAP_Custom_Domain_Search_Description": " {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}:سانلىق مەلۇماتنى مۇنداق باشقۇرىمىزJSONئۇچۇر باغلانغان ۋە ئۇلانغان",
"LDAP_Default_Domain": "بەلگىلەنگەن تور نامى",
"LDAP_Description": "ئادەتتە شىركەتلەر تەرىپىدىن ئاددىي نۇقتا كىرىش مېخانىزىمى قىلىپ قوللىنىدۇ .بۇ خىلمېخانىزىم بىر ئەزانى ئوخشاش بىر يۈرۈش ھېسابات نومۇرى ۋە مەخپىي نومۇر ئارقىلىق كۆپلىگەن تور بەت ۋەمۇلازىمەتكە كىرگىلى بولىدۇ.كۆپلىگەن LDAPگۇۋاھنامىسىنى تەڭشەش ۋە مىساللىرىنى ئىچكىرى چۈشەنمەكچى بولسىڭىز بىزنىڭ wikiتور بېتىمىزدىن پايدىلانسىڭىز بولىدۇ https://rocket.chat/docs/administrator-guides/authentication/ldap/ (ېنىك مۇندەرىجىنى زىيارەت قىلىش كېلىشىمى)LDAP",
- "LDAP_Domain_Base": "ئاساس تور بەت نامى",
- "LDAP_Domain_Base_Description": ".تىكى يۇقىرى دەرىجىلىك مۇندەرىجىنى ئاساسىي تورنامى قىلىپ ئىشلىتىشنى تەكلىپ قىلىمىز .تۆۋەنكى 'بەلگىلەنگەن تورنامى ئىزدەش'تاللاش شەرتىگە ئاساسەن ئەزا چەكلەش ئېلىپ بېرىڭ. .LDAP .ئاستىدىكى ئەزانىلا ئىزدىيەلەيدۇ.DNنىڭ ئاساسىي تور نامى بولىشىنى ئەگەر سىز چەكلىگەن بولسىڭىز بۇ ۋاقىتتا پەقەت بۇ DN.نى سىز كۆپرەپ قاتسىڭىز بولىدۇ لېكىن گۇرۇپپا ۋە گۇرۇپپا ئىچىدە ئەزا نامى چوقۇم بىر تورنامى ئاستىدا بولىشى كېرەك DN .نىڭ تارماق دەرىخى ئىچىدىن ئەزا ۋە گۇرۇپ ئىزدىشىگە قولايلىق بولىدۇ .LDAP نىڭ DNبۇنداق بولغاندا (Domain Base)نى تولدۇرۇپ ئۇنى ئاساسى توربەت نامىد قىددلىڭ ،DNئىناۋەتلىك",
- "LDAP_Domain_Search_Filter": "تاللاش شەرتى",
- "LDAP_Domain_Search_Filter_Description": "`memberOf=cn=ROCKET_CHAT,ou=General Groups`。 OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`تورنامىWindows AD مەسلەن تىكى ھەممە ئەزا كىرەلەيدۇ domain base ئەگەر بۇ يەردە تاللاش شەرتىنى بېكىتسىڭىز ،پەقەت شەرتكە توشقان ئەزالا كىرەلەيدۇ. ئەگەر بەلگىلەنگەن تاللاش شەرتى بولسا",
- "LDAP_Domain_Search_Object_Category": "نى ئىزدەشobjectCategoryئەزا ئىشلەتكەن",
- "LDAP_Domain_Search_Object_Category_Description": "دەپ ئايرىيمىز.`person`غا كۆپ ۋاقىتتا Windows AD مەسلەن: ئىشلىتىلسە بۇ ئورۇن قۇرۇق قالىدۇ. *OpenLDAP*ئەگەر نى كىرگۈزۈڭ *objectCategory*ئىچىدە ئەزا تونۇشقا ئىشلىتىلىدىغان LDAP",
- "LDAP_Domain_Search_Object_Class": "نى ئىزدەشobjectCategory",
- "LDAP_Domain_Search_Object_Class_Description": "لاردەك.`user`،`organizationalPerson`,`inetOrgPerson`مەسىلەن: نى كىرگۈزۈڭ .*objectclass* دە ئەزا تونۇشقا ئىشلىتىلىدىغان LDAP",
- "LDAP_Domain_Search_Password": "تورنامى باشقۇرغۇچىنىڭ مەخپىي نومۇرى",
- "LDAP_Domain_Search_Password_Description": "نىڭ مەخپىي نومۇرىLDAPتورنامى باشقۇرغۇچى",
- "LDAP_Domain_Search_User": "تورنامى باشقۇرغۇچى",
- "LDAP_Domain_Search_User_Description": "`cn=Administrator,cn=Users,dc=Example,dc=com`دە ئۈچىنچى تەرەپنىڭ توپلىشىشى ئۈچۈن قۇرۇلغان ھېسابات نومۇرى. ئىناۋەتلىك بولغان پۈتۈن ئىسىم ئىشلىتىڭ مەسىلەن: . LDAP كۆپ ئەھۋالدا ، ئۇ ئەزا نىڭ ئىچىدە ئىزدەش ۋە دەلىللەش رولىنى ئۆتەيدۇ.LDAP ئەزا باشقا ئەزالار كىرگەن چاغدا LDAP بۇ",
- "LDAP_Domain_Search_User_ID": "ھېسابات نومۇرى دەلىللەش خەت بۆلىكى",
- "LDAP_Domain_Search_User_ID_Description": "نى ئىشلەتسە بولىدۇ .`sAMAccountName,mail` مەسلەن بىر ۋاقىتتا ئوخشاش ئەزا نامى ۋە ئىلخەت ئادرېسىنى دەللىلەش ھېسابات نومۇرى قىلسا، ئەگەر بىر ۋاقىتتا كۆپ خىل دەلىللەش ئىشلىتىلسە ، پەش ئارقىلىق خەت بۆلەك ئىسمىنى ئايرىپ تۇرسا بولىدۇ . خەت بۆلىكىنى ئىشلىتىشى مۇمكىن .`uid` بولسا OpenLDAP ھەل قىلىش پىلانلىرى مەسلەن LDAPخەت بۆلىكى ئىشلىتىدۇ .لېكىن باشقا `sAMAccountName` نى ئېلىپ ئېيتقاندا ، كۆپ ئەھۋالدا Windows AD خۇسۇسىيتى كىرگۈچىنىڭ خەت بۆلىكىنى تونۇشقا ئىشلىتىلىدۇ.LDAPبۇ",
+ "LDAP_BaseDN_Description": ".تىكى يۇقىرى دەرىجىلىك مۇندەرىجىنى ئاساسىي تورنامى قىلىپ ئىشلىتىشنى تەكلىپ قىلىمىز .تۆۋەنكى 'بەلگىلەنگەن تورنامى ئىزدەش'تاللاش شەرتىگە ئاساسەن ئەزا چەكلەش ئېلىپ بېرىڭ. .LDAP .ئاستىدىكى ئەزانىلا ئىزدىيەلەيدۇ.DNنىڭ ئاساسىي تور نامى بولىشىنى ئەگەر سىز چەكلىگەن بولسىڭىز بۇ ۋاقىتتا پەقەت بۇ DN.نى سىز كۆپرەپ قاتسىڭىز بولىدۇ لېكىن گۇرۇپپا ۋە گۇرۇپپا ئىچىدە ئەزا نامى چوقۇم بىر تورنامى ئاستىدا بولىشى كېرەك DN .نىڭ تارماق دەرىخى ئىچىدىن ئەزا ۋە گۇرۇپ ئىزدىشىگە قولايلىق بولىدۇ .LDAP نىڭ DNبۇنداق بولغاندا (Domain Base)نى تولدۇرۇپ ئۇنى ئاساسى توربەت نامىد قىددلىڭ ،DNئىناۋەتلىك",
+ "LDAP_User_Search_Field_Description": "نى ئىشلەتسە بولىدۇ .`sAMAccountName,mail` مەسلەن بىر ۋاقىتتا ئوخشاش ئەزا نامى ۋە ئىلخەت ئادرېسىنى دەللىلەش ھېسابات نومۇرى قىلسا، ئەگەر بىر ۋاقىتتا كۆپ خىل دەلىللەش ئىشلىتىلسە ، پەش ئارقىلىق خەت بۆلەك ئىسمىنى ئايرىپ تۇرسا بولىدۇ . خەت بۆلىكىنى ئىشلىتىشى مۇمكىن .`uid` بولسا OpenLDAP ھەل قىلىش پىلانلىرى مەسلەن LDAPخەت بۆلىكى ئىشلىتىدۇ .لېكىن باشقا `sAMAccountName` نى ئېلىپ ئېيتقاندا ، كۆپ ئەھۋالدا Windows AD خۇسۇسىيتى كىرگۈچىنىڭ خەت بۆلىكىنى تونۇشقا ئىشلىتىلىدۇ.LDAPبۇ",
+ "LDAP_User_Search_Filter_Description": "`memberOf=cn=ROCKET_CHAT,ou=General Groups`。 OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`تورنامىWindows AD مەسلەن تىكى ھەممە ئەزا كىرەلەيدۇ domain base ئەگەر بۇ يەردە تاللاش شەرتىنى بېكىتسىڭىز ،پەقەت شەرتكە توشقان ئەزالا كىرەلەيدۇ. ئەگەر بەلگىلەنگەن تاللاش شەرتى بولسا",
+ "LDAP_Authentication_UserDN_Description": "`cn=Administrator,cn=Users,dc=Example,dc=com`دە ئۈچىنچى تەرەپنىڭ توپلىشىشى ئۈچۈن قۇرۇلغان ھېسابات نومۇرى. ئىناۋەتلىك بولغان پۈتۈن ئىسىم ئىشلىتىڭ مەسىلەن: . LDAP كۆپ ئەھۋالدا ، ئۇ ئەزا نىڭ ئىچىدە ئىزدەش ۋە دەلىللەش رولىنى ئۆتەيدۇ.LDAP ئەزا باشقا ئەزالار كىرگەن چاغدا LDAP بۇ",
"LDAP_Enable": "قوزغىتىش",
"LDAP_Enable_Description": "ئارقىلىق سالاھىيەتنى تەكشۈرۈشنى سىناش.LDAP",
"LDAP_Encryption": "مەخپىيلەشتۈرۈش ئۇسۇلى",
@@ -597,12 +583,9 @@
"LDAP_Sync_User_Data_Description": "(مەسىلەن ، ئىسىم فامىلە ، ئىلخەت ئادرېس.) كىرگەندە ئەزانىڭ سانلىق مەلۇماتى بىلەن مۇلازىمىتېرنى قەدەملەشتۈرۈش",
"LDAP_Sync_User_Data_FieldMap": "ئەزانىڭ سانلىق مەلۇمات بۆلىكىنى قايتۇرما ئەكس ئېتىش",
"LDAP_Sync_User_Data_FieldMap_Description": "设置用户数据字段(比如 E-mail)来自 LDAP 何处(如果能找到)。 ;例如:`{\"cn\":\"name\", \"mail\":\"email\"}` 会从属性 cn 中取出名字字段,从 mail 属性中取出 email 字段。 有效字段包括 `name` 和 `email`。",
- "LDAP_Sync_Users": "同步用户",
"LDAP_Test_Connection": "ئۇلاشنى سىناش",
"LDAP_Unique_Identifier_Field": "بىردىنبىر تونۇيدىغان خەت بۆلىكى",
"LDAP_Unique_Identifier_Field_Description": "`objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber` بەلگىلەنگەن قىممتى بولسا : تىكى ئەزا ئۇچۇرىنى ئۇلاش Rocket.Chat ۋە LDAPقايسى خەت بۆلىكىنى ئىشلىتىپ",
- "LDAP_Use_Custom_Domain_Search": "ئۆزى بەلگىلىگەن تور نامى ئىزدەشنى ئىشلىتىش",
- "LDAP_Use_Custom_Domain_Search_Description": "مۇلازىمىتېردە ئەزا ئىزدەشتىكى تاللاش شەرتلىرىنى كىرگۈزۈڭ .LDAP",
"LDAP_Username_Field": "ئەزا ئىسمى خەت بۆلىكى",
"LDAP_Username_Field_Description": "`sAMAccountName`بەلگىلەنگەن خەت بۆلىكى بولسا `#{givenName}.#{sn}`خەتكۈچ ئۈلگىسى ئىشلەتسىڭىز بولىدۇ ، مەسلەن *ئەزا ئىسمى* قايسى خەت بۆلەك قىممىتىنى قىلىپ ئىشلىتىش ئەگەر كىرىش بېتىدىكى ئەزا نامىنى ئىشلەتكەن بولسا بوش ئورۇن قويۇڭ .LDAP يېڭى ئەزانىڭ كىرىشىنى بېكىتكەندە",
"Leave_Group_Warning": "ئەزا گۇرۇپپىسىدىن ئايرىلىشنى جەزملەشتۈردىڭىزمۇ ؟ “%s”سىز",
@@ -1038,19 +1021,19 @@
"The_user_wont_be_able_to_type_in_s": "ئۆيدە گەپ قىلىشتىن چەكلىنىدۇ%sبۇ ئەزا",
"Theme": "تېما",
"theme-color-content-background-color": "مەزمۇنىنىڭ تەگلىك رەڭگى",
+ "theme-color-custom-scrollbar-color": "سيرىلما بەلگە رەڭگى ياسىتىش",
+ "theme-color-info-font-color": "ئۇچۇرخېتىنىڭ رەڭگى",
+ "theme-color-link-font-color": "خەتنىڭ ئۇلانما رەڭگى",
"theme-color-primary-background-color": "ئاساسىي تەگلىك رەڭگى",
"theme-color-primary-font-color": "ئاساسىي گىرافىكنىڭ رەڭگى",
"theme-color-secondary-background-color": "ئىككىنچى تەگلىك رەڭگى",
"theme-color-secondary-font-color": "ئىككىنچى گىرافىكا رەڭگى",
- "theme-color-tertiary-background-color": "ئۈچىنچى تەگلىك رەڭگى",
- "theme-color-tertiary-font-color": "ئۈچىنچى گرافىكا رەڭگى",
- "theme-color-link-font-color": "خەتنىڭ ئۇلانما رەڭگى",
- "theme-color-info-font-color": "ئۇچۇرخېتىنىڭ رەڭگى",
- "theme-color-custom-scrollbar-color": "سيرىلما بەلگە رەڭگى ياسىتىش",
"theme-color-status-away": "ئايرىلغان ھالەتتىكى رەڭگى",
"theme-color-status-busy": "ئالدىراش ھالەتتىكى رەڭگى",
"theme-color-status-offline": "تورسىز ھالەتتىكى رەڭگى",
"theme-color-status-online": "تور ھالىتىدىكى رەڭگى",
+ "theme-color-tertiary-background-color": "ئۈچىنچى تەگلىك رەڭگى",
+ "theme-color-tertiary-font-color": "ئۈچىنچى گرافىكا رەڭگى",
"theme-color-unread-notification-color": "ئوقۇلمىغان ئۇچۇرنىڭ رەڭگى",
"theme-custom-css": "CSSئۆزى بېكىتكەن",
"There_are_no_agents_added_to_this_department_yet": "بۇ بۆلۈم ھېچقانداق مۇلازىم بۆلمىدى",
@@ -1221,4 +1204,4 @@
"Your_mail_was_sent_to_s": "يوللاندى %s سىزنىڭ ئىلخىتىڭىز ئاللىبۇرۇن",
"Your_password_is_wrong": "پارول خاتا !",
"Your_push_was_sent_to_s_devices": "ئۈسكىنىگە يوللاندى %s سىزنىڭ ئىتتىرگىنىڭىز"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/uk.i18n.json b/packages/rocketchat-i18n/i18n/uk.i18n.json
index 51d83c1911d66..3da72b75a825c 100644
--- a/packages/rocketchat-i18n/i18n/uk.i18n.json
+++ b/packages/rocketchat-i18n/i18n/uk.i18n.json
@@ -1,37 +1,39 @@
{
+ "#channel": "#канал",
"0_Errors_Only": "0 - Тільки помилки",
- "1_Errors_and_Information": "1 - Помилки та інформації",
- "2_Erros_Information_and_Debug": "2 - Erros, інформація та налагодження",
- "403": "заборонений",
+ "1_Errors_and_Information": "1 - Помилки та інформація",
+ "2_Erros_Information_and_Debug": "2 - Помилки, інформація та налагодження",
+ "403": "Заборонено",
"500": "Внутрішня помилка сервера",
- "__username__is_no_longer__role__defined_by__user_by_": "__username__ більше не __role__, по __user_by__",
- "__username__was_set__role__by__user_by_": "__username__ був встановлений __role__ по __user_by__",
- "Access_not_authorized": "Доступ не дозволяється",
+ "__username__is_no_longer__role__defined_by__user_by_": "__username__ більше не __role__, за рішенням __user_by__",
+ "__username__was_set__role__by__user_by_": "__username__ був встановлений __role__ за рішенням __user_by__",
+ "Accept": "Погоджуюсь",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Приймати запити із livechat, навіть коли немає підключених співробітників",
+ "Accept_with_no_online_agents": "Приймати із не підключенними співробітниками",
+ "Access_not_authorized": "Не авторизований доступ",
"Access_Token_URL": "URL Токен доступу",
"Accessing_permissions": "доступ дозволів",
- "Account_SID": "рахунок SID",
- "Accounts": "рахунки",
+ "Account_SID": "SID облікового запису",
+ "Accounts": "Облікові записи",
"Accounts_AllowDeleteOwnAccount": "Дозволити користувачам видаляти власний обліковий запис",
"Accounts_AllowedDomainsList": "Список дозволених доменів",
- "Accounts_AllowedDomainsList_Description": "Розділених комами список дозволених доменів",
- "Accounts_AllowEmailChange": "Дозволити E-mail Змінити",
+ "Accounts_AllowedDomainsList_Description": "Перелік дозволених доменів, розділених комами ",
+ "Accounts_AllowEmailChange": "Дозволити зміну email адреси",
"Accounts_AllowPasswordChange": "Дозволити зміну пароля",
- "Accounts_AllowUserAvatarChange": "Дозволити Аватар користувача Зміна",
- "Accounts_AllowUsernameChange": "Дозволити Ім'я користувача Зміна",
- "Accounts_AllowUserProfileChange": "Дозволити Профіль користувача Зміна",
- "Accounts_AvatarResize": "Зміна розміру аватари",
- "Accounts_AvatarSize": "Аватар Розмір",
- "Accounts_AvatarStorePath": "Шлях до аватарам",
- "Accounts_AvatarStoreType": "Аватар для зберігання Тип",
- "Accounts_BlockedDomainsList": "Заблоковані Список доменів",
- "Accounts_BlockedDomainsList_Description": "Розділених комами список заблокованих доменів",
- "Accounts_BlockedUsernameList": "Заблоковані Список Ім'я користувача",
- "Accounts_BlockedUsernameList_Description": "Розділених комами список заблокованих імен користувачів (без урахування регістру)",
+ "Accounts_AllowUserAvatarChange": "Дозволити користувачеві змінювати аватар",
+ "Accounts_AllowUsernameChange": "Дозволити зміну імені користувача",
+ "Accounts_AllowUserProfileChange": "Дозволити користувачеві змінювати налаштування профілю",
+ "Accounts_AvatarResize": "Змінити розмір аватару",
+ "Accounts_AvatarSize": "Розмір аватару",
+ "Accounts_BlockedDomainsList": "Перелік заблокованих доменів",
+ "Accounts_BlockedDomainsList_Description": "Перелік заблокованих доменів, розділених комою",
+ "Accounts_BlockedUsernameList": "Перелік заблокованих користувачів",
+ "Accounts_BlockedUsernameList_Description": "Перелік заблокованих імен користувачів (без урахування регістру), розділених комами ",
"Accounts_denyUnverifiedEmail": "Заборонити неперевірену електронну пошту",
- "Accounts_EmailVerification": "Електронна пошта Перевірка",
- "Accounts_EmailVerification_Description": "Переконайтеся, що у вас є правильні настройки SMTP, щоб використовувати цю функцію",
+ "Accounts_EmailVerification": "Підтвердження електронної пошти",
+ "Accounts_EmailVerification_Description": "Переконайтеся, що у вас є правильні налаштування SMTP, щоб використовувати цю функцію",
"Accounts_Enrollment_Email": "Зарахування Електронна пошта",
- "Accounts_Enrollment_Email_Default": " Ласкаво просимо до [Site_Name] Перейти до [Site_URL] і спробувати краще рішення чат з відкритим вихідним кодом на сьогоднішній день!
",
+ "Accounts_Enrollment_Email_Default": " Ласкаво просимо до [Site_Name] Перейти до [Site_URL] і спробувати краще рішення чат з відкритим вихідним кодом на сьогоднішній день!
",
"Accounts_Enrollment_Email_Description": "Ви можете використовувати [name], [fname], [lname] повне ім'я користувача, ім'я або прізвище, відповідно. Ви можете використовувати [email] для електронної пошти користувача.",
"Accounts_Enrollment_Email_Subject_Default": "Ласкаво просимо на [Site_Name]",
"Accounts_Iframe_api_method": "метод Апі",
@@ -84,7 +86,7 @@
"Accounts_OAuth_Twitter_id": "Twitter Id",
"Accounts_OAuth_Twitter_secret": "Twitter Секретний",
"Accounts_OAuth_Wordpress": "WordPress Увійти",
- "Accounts_OAuth_Wordpress_callback_url": "URL Wordpress Зворотній дзвінок",
+ "Accounts_OAuth_Wordpress_callback_url": "URL WordPress Зворотній дзвінок",
"Accounts_OAuth_Wordpress_id": "WordPress Id",
"Accounts_OAuth_Wordpress_secret": "WordPress Секретний",
"Accounts_PasswordReset": "Скидання пароля",
@@ -95,12 +97,12 @@
"Accounts_RegistrationForm_Public": "суспільного",
"Accounts_RegistrationForm_Secret_URL": "секретний URL",
"Accounts_RegistrationForm_SecretURL": "Форма реєстрації Секретний URL",
- "Accounts_RegistrationForm_SecretURL_Description": "Ви повинні забезпечити випадкову рядок, яка буде додана до вашої реєстрації URL. Приклад: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "Ви повинні забезпечити випадкову рядок, яка буде додана до вашої реєстрації URL. Приклад: https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "Вимагати ім'я для Signup",
"Accounts_ShowFormLogin": "Показати на основі форм Ввійти",
"Accounts_UseDefaultBlockedDomainsList": "Використовувати за замовчуванням Заблоковані Список доменів",
"Accounts_UseDNSDomainCheck": "Використання домену DNS Перевірка",
- "Accounts_UserAddedEmail_Default": " Ласкаво просимо до [Site_Name] Перейти до [Site_URL] і спробувати краще рішення чат з відкритим вихідним кодом на сьогоднішній день!
Ви можете увійти в систему, використовуючи адресу електронної пошти: [email] і пароль: [password]. Можливо, вам буде потрібно змінити його після першого входу в систему.",
+ "Accounts_UserAddedEmail_Default": "
Ласкаво просимо до [Site_Name] Перейти до [Site_URL] і спробувати краще рішення чат з відкритим вихідним кодом на сьогоднішній день!
Ви можете увійти в систему, використовуючи адресу електронної пошти: [email] і пароль: [password]. Можливо, вам буде потрібно змінити його після першого входу в систему.",
"Accounts_UserAddedEmail_Description": "Ви можете використовувати наступні наповнювачі:
[name], [fname], [lname] повне ім'я користувача, ім'я або прізвище, відповідно. [email] для електронної пошти користувача. [password] для пароля користувача. [Site_Name] і [Site_URL] для імені додатки і URL відповідно. ",
"Accounts_UserAddedEmailSubject_Default": "Ви були додані [Site_Name]",
"Activate": "активувати",
@@ -307,9 +309,9 @@
"edited": "відредаговано",
"Editing_room": "редагування номера",
"Editing_user": "редагування користувача",
- "Email": "E-mail",
+ "Email": "Email",
"Email_address_to_send_offline_messages": "Адреса електронної пошти для відправки повідомлення в автономному режимі",
- "Email_already_exists": "E-mail вже існує",
+ "Email_already_exists": "Email вже існує",
"Email_body": "Електронна пошта тіла",
"Email_Change_Disabled": "Ваш Rocket.Chat адміністратор відключив зміна електронної пошти",
"Email_Footer_Description": "Ви можете використовувати наступні наповнювачі: [Site_Name] і [Site_URL] для імені додатки і URL відповідно. ",
@@ -439,7 +441,7 @@
"Forgot_password": "Забули пароль",
"Frequently_Used": "часто використовувані",
"From": "з",
- "From_Email": "З адреси електронної пошти",
+ "From_Email": "Email відправника",
"From_email_warning": "Попередження: Поле Від підлягає налаштувань поштового сервера.",
"General": "загальний",
"github_no_public_email": "В налаштуваннях GitHubвідсутній публічний e-mail",
@@ -504,7 +506,7 @@
"InternalHubot_ScriptsToLoad_Description": "Будь ласка, введіть розділений комами список скриптів для завантаження з https://github.com/github/hubot-scripts/tree/master/src/scripts",
"InternalHubot_Username_Description": "Це повинно бути дійсним ім'ям користувача бота, зареєстрований на сервері.",
"Invalid_confirm_pass": "Підтвердження пароля не збігаються пароль",
- "Invalid_email": "Невірний e-mail",
+ "Invalid_email": "Невірний email",
"Invalid_Export_File": "Файл завантажений не є коректним %s файл експорту.",
"Invalid_Import_File_Type": "Невірний тип файлу імпорту.",
"Invalid_name": "Ім’я має бути заповненим",
@@ -565,24 +567,12 @@
"Layout_Terms_of_Service": "Умови обслуговування",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA Cert",
- "LDAP_Custom_Domain_Search": "Пошук Персональний домен",
- "LDAP_Custom_Domain_Search_Description": "Шматок JSON, який регулює прив'язку і підключення до інформації і має вигляд: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "Домен за замовчуванням",
"LDAP_Description": "LDAP є ієрархічною базу даних, що багато компаній використовують для забезпечення єдиного входу - об'єкта для спільного використання одного пароля між декількома сайтами і послугами. Для отримання попередньої інформації про конфігурацію і приклади, будь ласка, зверніться до нашої вікі: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "базовий домен",
- "LDAP_Domain_Base_Description": "Повний відмітна ім'я (DN) з поддерева LDAP, який потрібно для пошуку користувачів і груп. Ви можете додати стільки, скільки вам подобається; Проте, кожна група повинна бути визначена в тому ж домені, що і базою користувачів, які належать до нього. Якщо вказати обмежені групи користувачів, тільки користувачі, що належать до цих груп буде знаходитися в області видимості. Ми рекомендуємо вам вказати верхній рівень вашого LDAP дерева каталогів в якості домену бази і використовувати фільтр пошуку для управління доступом.",
- "LDAP_Domain_Search_Filter": "Фільтр пошуку домену",
- "LDAP_Domain_Search_Filter_Description": "Якщо вказано, тільки ті користувачі, які відповідають цьому фільтру буде дозволено увійти в систему. Якщо не вказано ні один фільтр, всі користувачі в межах обсягу зазначеного домену бази матиме можливість увійти в систему. Наприклад, для Active Directory `memberOf = сп = ROCKET_CHAT, НУ = Загальні Groups`. Наприклад, для OpenLDAP (розширюваний пошук матчу) `НУ: дп: = ROCKET_CHAT`.",
- "LDAP_Domain_Search_Object_Category": "Домен Об'єкт пошуку Категорія",
- "LDAP_Domain_Search_Object_Category_Description": "* ObjectCategory *, які ідентифікують користувачів. Залиште порожнім * * OpenLDAP. Наприклад, `person` і т.д.",
- "LDAP_Domain_Search_Object_Class": "Домен Клас Об'єкт пошуку",
- "LDAP_Domain_Search_Object_Class_Description": "* ObjectClass *, які ідентифікують користувачів. Наприклад, `organizationalPerson`,` user`, `inetOrgPerson` і т.д.",
- "LDAP_Domain_Search_Password": "Домен пошуку пароля",
- "LDAP_Domain_Search_Password_Description": "Пароль для користувача пошуку домену.",
- "LDAP_Domain_Search_User": "Домен Пошук користувача",
- "LDAP_Domain_Search_User_Description": "Користувач LDAP, який виконує операцій пошуку користувачів для аутентифікації інших користувачів, коли вони підписують в. Як правило, це обліковий запис служби, створена спеціально для сторонніх інтеграції. Використовуйте повне ім'я, наприклад `CN = Administrator, CN = Users, DC = Example, DC = com`.",
- "LDAP_Domain_Search_User_ID": "Пошук домена Ідентифікатор користувача",
- "LDAP_Domain_Search_User_ID_Description": "Атрибут LDAP, який ідентифікує користувача LDAP, який намагається аутентифікацію. Це поле повинно бути `sAMAccountName` для установки найбільш Active Directory, але це може бить` uid` для інших рішень LDAP, таких як OpenLDAP. Ви можете використовувати `mail` для ідентифікації користувачів по електронній пошті або будь-який інший атрибут ви хочете. Можна використовувати декілька значень, розділених комами, щоб дозволити користувачам увійти в систему, використовуючи кілька ідентифікаторів, таких як ім'я користувача або адресу електронної пошти.",
+ "LDAP_BaseDN_Description": "Повний відмітна ім'я (DN) з поддерева LDAP, який потрібно для пошуку користувачів і груп. Ви можете додати стільки, скільки вам подобається; Проте, кожна група повинна бути визначена в тому ж домені, що і базою користувачів, які належать до нього. Якщо вказати обмежені групи користувачів, тільки користувачі, що належать до цих груп буде знаходитися в області видимості. Ми рекомендуємо вам вказати верхній рівень вашого LDAP дерева каталогів в якості домену бази і використовувати фільтр пошуку для управління доступом.",
+ "LDAP_User_Search_Field_Description": "Атрибут LDAP, який ідентифікує користувача LDAP, який намагається аутентифікацію. Це поле повинно бути `sAMAccountName` для установки найбільш Active Directory, але це може бить` uid` для інших рішень LDAP, таких як OpenLDAP. Ви можете використовувати `mail` для ідентифікації користувачів по електронній пошті або будь-який інший атрибут ви хочете. Можна використовувати декілька значень, розділених комами, щоб дозволити користувачам увійти в систему, використовуючи кілька ідентифікаторів, таких як ім'я користувача або адресу електронної пошти.",
+ "LDAP_User_Search_Filter_Description": "Якщо вказано, тільки ті користувачі, які відповідають цьому фільтру буде дозволено увійти в систему. Якщо не вказано ні один фільтр, всі користувачі в межах обсягу зазначеного домену бази матиме можливість увійти в систему. Наприклад, для Active Directory `memberOf = сп = ROCKET_CHAT, НУ = Загальні Groups`. Наприклад, для OpenLDAP (розширюваний пошук матчу) `НУ: дп: = ROCKET_CHAT`.",
+ "LDAP_Authentication_UserDN_Description": "Користувач LDAP, який виконує операцій пошуку користувачів для аутентифікації інших користувачів, коли вони підписують в. Як правило, це обліковий запис служби, створена спеціально для сторонніх інтеграції. Використовуйте повне ім'я, наприклад `CN = Administrator, CN = Users, DC = Example, DC = com`.",
"LDAP_Enable": "включити",
"LDAP_Enable_Description": "Спроба використовувати LDAP для аутентифікації.",
"LDAP_Encryption": "шифрування",
@@ -597,12 +587,9 @@
"LDAP_Sync_User_Data_Description": "Зберігати дані користувача в синхронізації з сервером при вході в систему (наприклад: ім'я, адреса електронної пошти).",
"LDAP_Sync_User_Data_FieldMap": "Дані користувача Карта Поле",
"LDAP_Sync_User_Data_FieldMap_Description": "Налаштування, як поля облікових записів користувачів (наприклад, електронної пошти) заповнюються із запису в LDAP (колись знайшла). Як приклад, `{\" сп \":\" ім'я \",\" пошта \":\" електронна пошта \"}` буде вибрати удобочитаем ім'я людини з атрибута CN, і їх електронну пошту від атрибута пошти. Доступні поля включають `name` і` email`.",
- "LDAP_Sync_Users": "Синхронізація користувачів",
"LDAP_Test_Connection": "Пров.соед",
"LDAP_Unique_Identifier_Field": "Унікальний ідентифікатор поля",
"LDAP_Unique_Identifier_Field_Description": "Яке поле буде використовуватися для з'єднання користувача LDAP і користувач Rocket.Chat. Ви можете повідомити кілька значень, розділених комою, щоб спробувати отримати значення з записи LDAP. Значення за замовчуванням є `ObjectGUID, IBM-entryUUID, ідентифікатор GUID, dominoUNID, nsuniqueId, uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "Використовуйте Пошук користувальницьких доменів",
- "LDAP_Use_Custom_Domain_Search_Description": "Напишіть свій власний фільтр для пошуку користувачів на сервері LDAP.",
"LDAP_Username_Field": "Ім'я користувача поле",
"LDAP_Username_Field_Description": "Яке поле буде використовуватися в якості * Ім'я користувача * для нових користувачів. Залиште порожнім, щоб використовувати ім'я користувача повідомляється на сторінці входу. Ви можете використовувати теги шаблонів теж, як `#{givenName}.#{sn}`. Значення за замовчуванням є `sAMAccountName`.",
"Leave_Group_Warning": "Ви впевнені, що хочете залишити групу \" %s\"?",
@@ -1038,19 +1025,19 @@
"The_user_wont_be_able_to_type_in_s": "Користувач не зможе ввести в %s",
"Theme": "тема",
"theme-color-content-background-color": "Зміст Колір фону",
+ "theme-color-custom-scrollbar-color": "Призначені для користувача Scrollbar Колір",
+ "theme-color-info-font-color": "Інформація Колір шрифту",
+ "theme-color-link-font-color": "Посилання Колір шрифту",
"theme-color-primary-background-color": "Основний колір фону",
"theme-color-primary-font-color": "Первинний Колір шрифту",
"theme-color-secondary-background-color": "Вторинний колір фону",
"theme-color-secondary-font-color": "Вторинний колір шрифту",
- "theme-color-tertiary-background-color": "Третинний Колір фону",
- "theme-color-tertiary-font-color": "Третинний Колір шрифту",
- "theme-color-link-font-color": "Посилання Колір шрифту",
- "theme-color-info-font-color": "Інформація Колір шрифту",
- "theme-color-custom-scrollbar-color": "Призначені для користувача Scrollbar Колір",
"theme-color-status-away": "Відсутня Колір Стан",
"theme-color-status-busy": "Зайнятий Колір Стан",
"theme-color-status-offline": "Offline Колір Статус",
"theme-color-status-online": "Інтернет Колір Статус",
+ "theme-color-tertiary-background-color": "Третинний Колір фону",
+ "theme-color-tertiary-font-color": "Третинний Колір шрифту",
"theme-color-unread-notification-color": "Непрочитана Повідомлення Колір",
"theme-custom-css": "призначені для користувача CSS",
"There_are_no_agents_added_to_this_department_yet": "Там немає доданих в цей відділ поки агенти.",
@@ -1221,4 +1208,4 @@
"Your_mail_was_sent_to_s": "Ваш лист було відправлено в %s",
"Your_password_is_wrong": "Ваш невірний пароль!",
"Your_push_was_sent_to_s_devices": "Ваш поштовх був відправлений в %s пристроїв"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/vi-VN.i18n.json b/packages/rocketchat-i18n/i18n/vi-VN.i18n.json
new file mode 100644
index 0000000000000..ecd61bf39cb86
--- /dev/null
+++ b/packages/rocketchat-i18n/i18n/vi-VN.i18n.json
@@ -0,0 +1,125 @@
+{
+ "#channel": "kênh ",
+ "0_Errors_Only": "0 - Chỉ lỗi",
+ "1_Errors_and_Information": "1- Lỗi và thông tin",
+ "2_Erros_Information_and_Debug": "2 - Lỗi, thông tin và gỡ lỗi",
+ "403": "Bị cấm",
+ "500": "Lỗi máy chủ",
+ "@username": "@username",
+ "Accept": "Đồng ý",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Cho phép gửi yêu cầu livechat ngay cả khi không có nhân viên nào online",
+ "Accept_with_no_online_agents": "Chấp nhận khi không có nhân viên online",
+ "access-mailer": "Truy cập màn hình xử lý mail",
+ "access-mailer_description": "Quyền gửi nhiều email tới tất cả người dùng.",
+ "access-permissions": "Truy cập màn hình cấp quyền",
+ "access-permissions_description": "Chỉnh sửa quyền cho nhiều vai trò.",
+ "Access_not_authorized": "Không được phép truy cập",
+ "Access_Token_URL": "\"Access Token URL\"",
+ "Accessing_permissions": "Truy cập các quyền",
+ "Account_SID": "Tài khoản SID",
+ "Accounts": "Tài khoản",
+ "Accounts_AllowAnonymousRead": "Cho phép tài khoản vô danh đọc",
+ "Accounts_AllowAnonymousWrite": "Cho phép tài khoản vô danh viết",
+ "Accounts_AllowDeleteOwnAccount": "Cho phép người dùng xóa tài khoản của họ",
+ "Accounts_AllowedDomainsList": "Danh sách tên miền hợp lệ",
+ "Accounts_AllowedDomainsList_Description": "Các tên miền hợp lệ cách nhau bởi dấu phẩy",
+ "Accounts_AllowEmailChange": "Cho phép đổi địa chỉ email",
+ "Accounts_AllowPasswordChange": "Cho phép đổi mật khẩu",
+ "Accounts_AllowUserAvatarChange": "Cho phép đổi ảnh đại diện",
+ "Accounts_AllowUsernameChange": "Cho phép đổi tên truy cập",
+ "Accounts_AllowUserProfileChange": "Cho phép thay đổi thông tin cá nhân",
+ "Accounts_AvatarResize": "Thay đổi ảnh đại diện",
+ "Accounts_AvatarSize": "Kích thước ảnh đại diện",
+ "Accounts_BlockedDomainsList": "Danh sách tên miền bị cấm",
+ "Accounts_BlockedDomainsList_Description": "Danh sách tên miền bị cấm cách nhau bằng dấu phẩy",
+ "Accounts_BlockedUsernameList": "Danh sách tên truy cập bị cấm",
+ "Accounts_BlockedUsernameList_Description": "Danh sách tên truy cập bị cấm cách nhau bằng dấu phẩy (không phân biệt hoa thường)",
+ "Accounts_CustomFields_Description": "Phải là cấu trúc JSON hợp lệ, trong đó các key là các trường chứa \"a dictionary of field settings\". Ví dụ:{ \"role\": { \"type\": \"select\", \"defaultValue\": \"student\", \"options\": [\"teacher\", \"student\"], \"required\": true, \"modifyRecordField\": { \"array\": true, \"field\": \"roles\" } }, \"twitter\": { \"type\": \"text\", \"required\": true, \"minLength\": 2, \"maxLength\": 10 }} ",
+ "Accounts_CustomFieldsToShowInUserInfo": "Các trường tùy chỉnh để hiển thị thông tin của người dùng",
+ "Accounts_DefaultUsernamePrefixSuggestion": "Tiền tố tên người dùng mặc định",
+ "Accounts_denyUnverifiedEmail": "Từ chối email chưa xác thực",
+ "Accounts_EmailVerification": "Xác thực email",
+ "Accounts_EmailVerification_Description": "Chắc chắn rằng bạn đã cấu hình thông tin SMTP chính xác trước khi sử dụng tính năng này",
+ "Accounts_Enrollment_Email": "Email đăng ký",
+ "Accounts_Enrollment_Email_Default": "Chào mừng đến [Site_Name] Truy cập [Site_URL] và trải nghiệm nền tảng chat trực tuyến tốt nhất hiện nay!
",
+ "Accounts_Enrollment_Email_Description": "Bạn có thể các sử dụng quy tắc sau: [name], [fname], [lname] tương ứng với họ và tên, tên hoặc họ của người dùng. [email] là địa chỉ email của người dùng. [Site_Name] và [Site_URL] là tên và URL của ứng dụng. ",
+ "Accounts_Enrollment_Email_Subject_Default": "Chào mừng đến [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "Xóa phiên đăng nhập của người dùng khi đóng cửa sổ",
+ "Accounts_Iframe_api_method": "Phương thức API",
+ "Accounts_Iframe_api_url": "API URL",
+ "Accounts_iframe_enabled": "Đã bật",
+ "Accounts_iframe_url": "Iframe Url",
+ "Accounts_LoginExpiration": "Số ngày hết hạn đăng nhập",
+ "Accounts_ManuallyApproveNewUsers": "Xác thực người dùng mới thủ công",
+ "Accounts_OAuth_Custom_Authorize_Path": "Đường dẫn ủy quyền (Authorize)",
+ "Accounts_OAuth_Custom_Button_Color": "Màu của nút",
+ "Accounts_OAuth_Custom_Button_Label_Color": "Màu chữ của nút",
+ "Accounts_OAuth_Custom_Button_Label_Text": "Màu chữ",
+ "Accounts_OAuth_Custom_Enable": "Cho phép",
+ "Accounts_OAuth_Custom_id": "ID",
+ "Accounts_OAuth_Custom_Identity_Path": "Đường dẫn xác thực (Identity Path)",
+ "Accounts_OAuth_Custom_Login_Style": "Kiểu đăng nhập",
+ "Accounts_OAuth_Custom_Merge_Users": "Sát nhập người dùng",
+ "Accounts_OAuth_Custom_Scope": "Phạm vi (Scope)",
+ "Accounts_OAuth_Custom_Secret": "Mã bí mật (Secret)",
+ "Accounts_OAuth_Custom_Token_Path": "Đường dẫn lấy Token (Token Path)",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Token được gửi qua",
+ "Accounts_OAuth_Custom_Username_Field": "Trường username",
+ "Accounts_OAuth_Drupal": "Cho phép đăng nhập qua Drupal",
+ "Accounts_OAuth_Facebook": "Đăng nhập qua facebook",
+ "Accounts_OAuth_Github": "Đã cho phép đăng nhập qua OAuth",
+ "Accounts_OAuth_GitHub_Enterprise": "Đã cho phép đăng nhập qua OAuth",
+ "Accounts_OAuth_Gitlab": "Đã cho phép đăng nhập qua OAuth",
+ "Accounts_OAuth_Meteor": "Đăng nhập qua Meteor",
+ "Accounts_OAuth_Twitter": "Đăng nhập qua Twitter",
+ "Accounts_OAuth_Wordpress": "Đăng nhập qua WordPress",
+ "Accounts_PasswordReset": "Đặt lại mật khẩu",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "Vai trò mặc định của Authentication Services",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "Các vai trò (phân cách bằng dấu phẩy) của người dùng sau khi đăng ký thông qua authentication services",
+ "Accounts_Registration_AuthenticationServices_Enabled": "Đăng ký với Authentication Services",
+ "Accounts_RegistrationForm": "Form đăng ký",
+ "Accounts_RegistrationForm_Disabled": "Không cho phép",
+ "Accounts_RegistrationForm_LinkReplacementText": "Chữ thay cho đường dẫn đến Form đăng ký ",
+ "Accounts_RegistrationForm_Public": "Công khai",
+ "Accounts_RegistrationForm_Secret_URL": "Bí mật",
+ "Accounts_RegistrationForm_SecretURL": "Đường dẫn bí mật đến form đăng ký",
+ "Accounts_RegistrationForm_SecretURL_Description": "Bạn phải sử dụng một chuỗi ký tự ngẫu nhiên để thêm vào đường dẫn đến form đăng ký. Ví dụ: https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "Yêu cầu tên khi đăng ký",
+ "Accounts_RequirePasswordConfirmation": "Yêu cầu xác nhận mật khẩu",
+ "Accounts_SearchFields": "Các trường cho phép tìm kiếm",
+ "Accounts_SetDefaultAvatar": "Lấy Avatar mặc định",
+ "Accounts_SetDefaultAvatar_Description": "Cố gắng lấy avatar mặc định dựa trên tài khoản OAuth hoặc Gravatar",
+ "Accounts_ShowFormLogin": "Hiện form-based đăng nhập",
+ "Accounts_UseDefaultBlockedDomainsList": "Sử dụng danh sách tên miền bị chặn mặc định",
+ "Accounts_UseDNSDomainCheck": "Sử dụng DNS Domain Check",
+ "Accounts_UserAddedEmail_Default": "Chào mừng đến [Site_Name] Hãy truy cập [Site_URL] và trải nghiệm giải pháp mã nguồn mở tuyệt vời nhất hiện nay!
Bạn có thể đăng nhập sử dụng hòm thư: [email] và mật khẩu: [password]. Bạn có thể được yêu cầu thay đổi nó sau lần đăng nhập đầu tiên.",
+ "Accounts_UserAddedEmailSubject_Default": "Bạn đã được thêm vào [Site_Name]",
+ "Activate": "Đang hoạt động",
+ "Activity": "Hoạt động",
+ "Add": "Thêm",
+ "add-oauth-service": "Thêm Oauth Service",
+ "add-oauth-service_description": "Quyền thêm mới Oauth service",
+ "add-user": "Thêm người dùng",
+ "add-user-to-any-c-room": "Thêm người dùng vào bất kỳ kênh công khai nào",
+ "add-user-to-any-c-room_description": "Quyền để thêm người dùng vào bất kỳ kênh công khai nào",
+ "add-user-to-any-p-room": "Thêm người dùng vào bất kỳ kênh riêng tư nào",
+ "add-user-to-any-p-room_description": "Quyền thêm người dùng vào bất kỳ kênh riêng tư nào",
+ "add-user-to-joined-room": "Thêm người dùng vào bất kỳ kênh nào đã tham gia",
+ "add-user-to-joined-room_description": "Quyền thêm người dùng vào bất kỳ kênh nào đang tham gia",
+ "add-user_description": "Quyền thêm thành viên mới vào hệ thống thông qua màn hình quản lý thành viên",
+ "Add_agent": "Thêm nhân viên / đại lý",
+ "Add_custom_oauth": "Thêm OAuth tùy chỉnh",
+ "Add_Domain": "Thêm tên miền",
+ "Add_files_from": "Thêm các file từ",
+ "Add_manager": "Thêm quản lý",
+ "Add_Role": "Thêm vai trò",
+ "Add_user": "Thêm thành viên",
+ "Add_User": "Thêm Thành viên",
+ "Add_users": "Thêm nhiều thành viên",
+ "Adding_OAuth_Services": "Thêm OAuth Service",
+ "Wednesday": "Thứ 4",
+ "Welcome": "Chào mừng %s .",
+ "Welcome_to_the": "Chào mừng đến",
+ "Why_do_you_want_to_report_question_mark": "Tại sao bạn muốn báo cáo?",
+ "Your_push_was_sent_to_s_devices": "Đã được gửi tới % thiết bị"
+}
diff --git a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
index a9a19981f020f..e3365a6452c60 100644
--- a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
@@ -1,8 +1,41 @@
{
- "Accounts": "帐户",
+ "#channel": "#頻道",
+ "500": "內部伺服器錯誤",
+ "@username": "@使用者",
+ "@username_message": "@使用者 ",
+ "__username__is_no_longer__role__defined_by__user_by_": " __user_by__ 已把 __username__ 從 __role__ 中移除",
+ "__username__was_set__role__by__user_by_": " __user_by__ 已把 __username__ 加進 __role__ 中",
+ "Accept": "接受",
+ "Access_not_authorized": "存取被拒",
+ "Access_Token_URL": "訪問 Token 網址",
+ "Accessing_permissions": "內部伺服器錯誤",
+ "Account_SID": "帳户 SID",
+ "Accounts": "帳户",
+ "Accounts_AllowDeleteOwnAccount": "允許使用者刪除自己的帳户",
+ "Accounts_AllowedDomainsList": "允許的網域清單",
+ "Accounts_AllowEmailChange": "允許更改 Email",
+ "Accounts_AllowPasswordChange": "允許更改密碼",
+ "Accounts_AllowUserAvatarChange": "允許使用者更改頭像",
+ "Accounts_AllowUsernameChange": "允許更改使用者名稱",
+ "Accounts_AllowUserProfileChange": "允許使用者變更個人檔案",
+ "Accounts_AvatarResize": "調整頭像大\b小",
+ "Accounts_AvatarSize": "頭像大\b小",
+ "Accounts_BlockedDomainsList": "黑名單網域列表",
"Accounts_denyUnverifiedEmail": "拒绝未经验证的电子邮件",
"Accounts_EmailVerification": "邮件验证",
- "Accounts_ManuallyApproveNewUsers": "手动审核新用户",
+ "Accounts_Iframe_api_method": "API 方法",
+ "Accounts_Iframe_api_url": "API 網址",
+ "Accounts_iframe_enabled": "已啟用",
+ "Accounts_iframe_url": "iframe 網址",
+ "Accounts_LoginExpiration": "登入過期日數",
+ "Accounts_ManuallyApproveNewUsers": "手動審核新使用者",
+ "Accounts_OAuth_Custom_Authorize_Path": "授權路徑",
+ "Accounts_OAuth_Custom_Button_Color": "按鈕顏色",
+ "Accounts_OAuth_Custom_Button_Label_Color": "按鈕文字顏色",
+ "Accounts_OAuth_Custom_Button_Label_Text": "按鈕文字",
+ "Accounts_OAuth_Custom_Enable": "啟用",
+ "Accounts_OAuth_Custom_id": "ID",
+ "Accounts_OAuth_Custom_Identity_Path": "Identity 路徑",
"Accounts_OAuth_Facebook": "Facebook 登入",
"Accounts_OAuth_Facebook_id": "Facebook应用程序ID",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
diff --git a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
index d06f9788e46ef..78444df1c0e8d 100644
--- a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
@@ -25,8 +25,6 @@
"Accounts_AllowUserProfileChange": "允許變更使用者個人檔案",
"Accounts_AvatarResize": "調整大頭貼尺寸",
"Accounts_AvatarSize": "大頭貼尺寸",
- "Accounts_AvatarStorePath": "大頭貼儲存路徑",
- "Accounts_AvatarStoreType": "大頭貼儲存類型",
"Accounts_BlockedDomainsList": "黑名單網域列表",
"Accounts_BlockedDomainsList_Description": "以逗號分隔的網域黑名單",
"Accounts_BlockedUsernameList": "使用者黑名單",
@@ -35,7 +33,7 @@
"Accounts_EmailVerification": "Email驗證",
"Accounts_EmailVerification_Description": "確定 SMTP 設定無誤以使用本功能",
"Accounts_Enrollment_Email": "註冊郵箱",
- "Accounts_Enrollment_Email_Default": "歡迎來到 [Site_Name] 轉到[Site_URL],並嘗試了當今最先進的開源聊天解決方案!
",
+ "Accounts_Enrollment_Email_Default": "歡迎來到 [Site_Name] 轉到[Site_URL] ,並嘗試了當今最先進的開源聊天解決方案!
",
"Accounts_Enrollment_Email_Description": "您可以分別使用[name],[fname],[lname]作為用戶的全名,名字或姓氏。 您可以使用[email]作為用戶的電子郵件。",
"Accounts_Enrollment_Email_Subject_Default": "歡迎來到 [Site_Name]",
"Accounts_Iframe_api_method": "API 方法",
@@ -100,12 +98,12 @@
"Accounts_RegistrationForm_Public": "公開",
"Accounts_RegistrationForm_Secret_URL": "揭秘網址",
"Accounts_RegistrationForm_SecretURL": "登記表秘密網址",
- "Accounts_RegistrationForm_SecretURL_Description": "您必須提供將被添加到您的註冊URL隨機字符串。例如:https://demo.rocket.chat/register/[secret_hash]",
+ "Accounts_RegistrationForm_SecretURL_Description": "您必須提供將被添加到您的註冊URL隨機字符串。例如:https://open.rocket.chat/register/[secret_hash]",
"Accounts_RequireNameForSignUp": "註冊需要名稱",
"Accounts_ShowFormLogin": "顯示基於表單的登入",
"Accounts_UseDefaultBlockedDomainsList": "使用預設的黑名單網域列表",
"Accounts_UseDNSDomainCheck": "使用DNS域名查詢",
- "Accounts_UserAddedEmail_Default": "歡迎來到 [Site_Name] 轉到[Site_URL],並嘗試了當今最先進的開源聊天解決方案!
您可以登陸使用您的電子郵件:[email]和密碼:[password]。您可能需要您首次登錄後更改。",
+ "Accounts_UserAddedEmail_Default": "
歡迎來到 [Site_Name] 轉到[Site_URL] ,並嘗試了當今最先進的開源聊天解決方案!
您可以登陸使用您的電子郵件:[email]和密碼:[password]。您可能需要您首次登錄後更改。",
"Accounts_UserAddedEmail_Description": "您可以使用以下佔位符:
[name],[fname],[lname]為用戶的全名,名字或姓氏,分別。 [email]為用戶的電子郵件。 [password]為用戶的密碼。 [Site_Name]和[Site_URL]分別為應用程序的名稱和網址。 ",
"Accounts_UserAddedEmailSubject_Default": "您已被添加到[Site_Name]",
"Activate": "啟用",
@@ -570,24 +568,12 @@
"Layout_Terms_of_Service": "服務條款",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA證書",
- "LDAP_Custom_Domain_Search": "自定義域搜索",
- "LDAP_Custom_Domain_Search_Description": "一塊JSON的管轄綁定和連接信息,並為下面的形式: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
"LDAP_Default_Domain": "默認域",
"LDAP_Description": "LDAP is a hierarchical database that many companies use to provide single sign on - a facility for sharing one password between multiple sites and services. For advanced configuration information and examples, please consult our wiki: https://rocket.chat/docs/administrator-guides/authentication/ldap/.",
- "LDAP_Domain_Base": "域基",
- "LDAP_Domain_Base_Description": "要搜索用戶和組的LDAP子樹的完全合格的名稱(DN)。您可以添加你喜歡的盡可能多的;然而,每一組必須在相同的域中鹼作為屬於它的用戶來定義。如果指定了受限制的用戶群體,只有屬於這些組的用戶將在範圍內。我們建議您指定的LDAP目錄樹的頂層為您的域名基地,並使用搜索過濾器來控制訪問。",
- "LDAP_Domain_Search_Filter": "域搜索過濾器",
- "LDAP_Domain_Search_Filter_Description": "如果指定,只有符合此過濾器,用戶將被允許登錄。如果沒有指定過濾器,指定域的基本範圍內的所有用戶都將能夠登錄。 例如,對於Active Directory的`的memberOf = CN = ROCKET_CHAT,OU =一般Groups`。 例如,OpenLDAP(可擴展匹配搜索)`OU:DN:= ROCKET_CHAT`。",
- "LDAP_Domain_Search_Object_Category": "域名查詢對象類別",
- "LDAP_Domain_Search_Object_Category_Description": "在* objectCategory屬性*標識用戶。 留空為* OpenLDAP的*。 比如`person`等。",
- "LDAP_Domain_Search_Object_Class": "域名查詢對象類",
- "LDAP_Domain_Search_Object_Class_Description": "在* *對象類標識用戶。 比如`organizationalPerson`,`user`,`inetOrgPerson`等。",
- "LDAP_Domain_Search_Password": "域名查詢密碼",
- "LDAP_Domain_Search_Password_Description": "密碼域搜索用戶。",
- "LDAP_Domain_Search_User": "域名搜索用戶",
- "LDAP_Domain_Search_User_Description": "執行用戶查找驗證其他用戶在登錄的LDAP用戶。 這通常是專為第三方集成創建一個服務帳戶。使用一個完全合格的名稱,比如'CN =管理員,CN =用戶,DC =示例,DC = com`。",
- "LDAP_Domain_Search_User_ID": "域名查詢用戶ID",
- "LDAP_Domain_Search_User_ID_Description": "標識誰試圖驗證的LDAP用戶的LDAP屬性。這個字段應`sAMAccountName`對於大多數活動目錄的安裝,但也可以是對其他LDAP解決方案,如OpenLDAP的`uid`。你可以用`mail`通過電子郵件或任何屬性要識別用戶。 您可以使用逗號分隔的多個值,以允許用戶使用多個標識符喜歡的用戶名或郵箱登錄。",
+ "LDAP_BaseDN_Description": "要搜索用戶和組的LDAP子樹的完全合格的名稱(DN)。您可以添加你喜歡的盡可能多的;然而,每一組必須在相同的域中鹼作為屬於它的用戶來定義。如果指定了受限制的用戶群體,只有屬於這些組的用戶將在範圍內。我們建議您指定的LDAP目錄樹的頂層為您的域名基地,並使用搜索過濾器來控制訪問。",
+ "LDAP_User_Search_Field_Description": "標識誰試圖驗證的LDAP用戶的LDAP屬性。這個字段應`sAMAccountName`對於大多數活動目錄的安裝,但也可以是對其他LDAP解決方案,如OpenLDAP的`uid`。你可以用`mail`通過電子郵件或任何屬性要識別用戶。 您可以使用逗號分隔的多個值,以允許用戶使用多個標識符喜歡的用戶名或郵箱登錄。",
+ "LDAP_User_Search_Filter_Description": "如果指定,只有符合此過濾器,用戶將被允許登錄。如果沒有指定過濾器,指定域的基本範圍內的所有用戶都將能夠登錄。 例如,對於Active Directory的`的memberOf = CN = ROCKET_CHAT,OU =一般Groups`。 例如,OpenLDAP(可擴展匹配搜索)`OU:DN:= ROCKET_CHAT`。",
+ "LDAP_Authentication_UserDN_Description": "執行用戶查找驗證其他用戶在登錄的LDAP用戶。 這通常是專為第三方集成創建一個服務帳戶。使用一個完全合格的名稱,比如'CN =管理員,CN =用戶,DC =示例,DC = com`。",
"LDAP_Enable": "啟用",
"LDAP_Enable_Description": "嘗試使用 LDAP 進行身份驗證。",
"LDAP_Encryption": "加密",
@@ -602,12 +588,9 @@
"LDAP_Sync_User_Data_Description": "在登入時保持與伺服器的使用者資料同步。(例如姓名或電子郵件)",
"LDAP_Sync_User_Data_FieldMap": "User Data Field Map",
"LDAP_Sync_User_Data_FieldMap_Description": "如何配置用戶帳戶字段(如電子郵件)是從LDAP記錄填充(一旦發現)。 作為一個例子,`{“CN”:“姓名”,“郵件”:“電子郵件”}`會選擇從cn屬性一個人的人類可讀的名稱,然後從郵件屬性他們的電子郵件。 可用字段包括`name`和`email`。",
- "LDAP_Sync_Users": "同步用戶",
"LDAP_Test_Connection": "測試連接",
"LDAP_Unique_Identifier_Field": "唯一標識符字段",
"LDAP_Unique_Identifier_Field_Description": "哪個字段將被用於向LDAP用戶和Rocket.Chat用戶聯繫起來。您可以告知以逗號分隔的多個值,從而嘗試從LDAP記錄的值。 默認值是`的objectGUID,IBM-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "使用自定義域名查詢",
- "LDAP_Use_Custom_Domain_Search_Description": "寫自己的過濾器來搜索用戶在LDAP服務器中。",
"LDAP_Username_Field": "用戶名現場",
"LDAP_Username_Field_Description": "這將被用於為*用戶名*為新用戶。留空使用的用戶名告知登錄頁面上。 您可以使用模板標籤太像`#{givenName}.#{sn}`。 默認值是`sAMAccountName`。",
"Leave_Group_Warning": "你確定你要離開組“%s”嗎?",
@@ -1043,19 +1026,19 @@
"The_user_wont_be_able_to_type_in_s": "用戶將不能夠鍵入在%s",
"Theme": "主題",
"theme-color-content-background-color": "內容背景顏色",
+ "theme-color-custom-scrollbar-color": "自定義顏色滾動條",
+ "theme-color-info-font-color": "信息字體顏色",
+ "theme-color-link-font-color": "鏈接字體顏色",
"theme-color-primary-background-color": "主要背景顏色",
"theme-color-primary-font-color": "主要字體顏色",
"theme-color-secondary-background-color": "二級背景顏色",
"theme-color-secondary-font-color": "二級字體顏色",
- "theme-color-tertiary-background-color": "第三背景顏色",
- "theme-color-tertiary-font-color": "第三字體顏色",
- "theme-color-link-font-color": "鏈接字體顏色",
- "theme-color-info-font-color": "信息字體顏色",
- "theme-color-custom-scrollbar-color": "自定義顏色滾動條",
"theme-color-status-away": "客場狀態顏色",
"theme-color-status-busy": "忙碌狀態顏色",
"theme-color-status-offline": "離線狀態顏色",
"theme-color-status-online": "在線狀態顏色",
+ "theme-color-tertiary-background-color": "第三背景顏色",
+ "theme-color-tertiary-font-color": "第三字體顏色",
"theme-color-unread-notification-color": "未讀通知顏色",
"theme-custom-css": "自定義CSS",
"There_are_no_agents_added_to_this_department_yet": "有沒有加入到這個部門還沒有代理商。",
@@ -1226,4 +1209,4 @@
"Your_mail_was_sent_to_s": "您的郵件已發送到%s",
"Your_password_is_wrong": "您的密碼是錯誤的!",
"Your_push_was_sent_to_s_devices": "你的推播被送到 %s 裝置"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/i18n/zh.i18n.json b/packages/rocketchat-i18n/i18n/zh.i18n.json
index 145471928d184..3b68fe80ff9fd 100644
--- a/packages/rocketchat-i18n/i18n/zh.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh.i18n.json
@@ -1,61 +1,72 @@
{
+ "#channel": "#频道",
"0_Errors_Only": "0 - 仅错误 ",
"1_Errors_and_Information": "1 - 错误和信息",
"2_Erros_Information_and_Debug": "2 - 错误、信息和调试信息",
"403": "已被禁止",
"500": "内部服务器错误",
+ "@username": "@用户名",
+ "@username_message": "@用户名 ",
"__username__is_no_longer__role__defined_by__user_by_": "__user_by__ 移除了 __username__ 的 __role__ 角色",
"__username__was_set__role__by__user_by_": "__user_by__ 赋予了 __username__ __role__ 角色",
- "Access_not_authorized": "访问未授权",
- "Access_Token_URL": "访问令牌地址",
+ "Accept": "接受",
+ "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "接受入站在线聊天请求即使没有客服在线",
+ "Accept_with_no_online_agents": "接受无在线客服",
+ "Access_not_authorized": "访问未被授权",
+ "Access_Token_URL": "访问 Token URL",
"Accessing_permissions": "访问权限",
- "Account_SID": "帐户SID",
+ "Account_SID": "帐户 SID",
"Accounts": "帐户",
- "Accounts_AllowDeleteOwnAccount": "允许用户删除自己的帐号",
+ "Accounts_AllowAnonymousRead": "允许匿名阅读",
+ "Accounts_AllowAnonymousWrite": "允许匿名写入",
+ "Accounts_AllowDeleteOwnAccount": "允许用户销毁自己的帐号",
"Accounts_AllowedDomainsList": "允许的域名列表",
- "Accounts_AllowedDomainsList_Description": "以逗号分隔的合法域名列表",
- "Accounts_AllowEmailChange": "允许修改电子邮箱地址",
+ "Accounts_AllowedDomainsList_Description": "以逗号分隔的允许的域名列表",
+ "Accounts_AllowEmailChange": "允许修改Email",
"Accounts_AllowPasswordChange": "允许修改密码",
- "Accounts_AllowUserAvatarChange": "允许修改用户头像",
+ "Accounts_AllowUserAvatarChange": "允许修改头像",
"Accounts_AllowUsernameChange": "允许修改用户名",
"Accounts_AllowUserProfileChange": "允许修改个人资料",
"Accounts_AvatarResize": "调整头像大小",
"Accounts_AvatarSize": "头像大小",
- "Accounts_AvatarStorePath": "头像存储路径",
- "Accounts_AvatarStoreType": "头像存储类型",
"Accounts_BlockedDomainsList": "已屏蔽域名列表",
- "Accounts_BlockedDomainsList_Description": "以逗号分割的屏蔽域名列表",
- "Accounts_BlockedUsernameList": "已禁止的用户名列表",
- "Accounts_BlockedUsernameList_Description": "以逗号分割的禁止用户名列表(不区分大小写)",
+ "Accounts_BlockedDomainsList_Description": "以逗号分隔的屏蔽的域名列表",
+ "Accounts_BlockedUsernameList": "已屏蔽的用户名列表",
+ "Accounts_BlockedUsernameList_Description": "以逗号分隔的已屏蔽用户名列表(不区分大小写)",
+ "Accounts_CustomFields_Description": "应该为 JSON 格式,键为字段名,值为该字段的设置项。例如: \n{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n}",
"Accounts_denyUnverifiedEmail": "拒绝未经验证的电子邮件地址",
- "Accounts_EmailVerification": "电子邮件验证",
+ "Accounts_EmailVerification": "Email 验证",
"Accounts_EmailVerification_Description": "要使用该功能,请确保 SMTP 设置正确",
"Accounts_Enrollment_Email": "注册邮件",
- "Accounts_Enrollment_Email_Default": "欢迎来到 [Site_Name] 转到 [Site_URL] 并尝试当今最先进的开源聊天解决方案!
",
+ "Accounts_Enrollment_Email_Default": "欢迎来到 [Site_Name] 转到 [Site_URL] 并尝试当今最先进的开源聊天解决方案!
",
"Accounts_Enrollment_Email_Description": "你可以使用以下占位符: 姓名[name]、名字[fname]或者姓氏 [lname]。 邮箱[email]。 网站名称[Site_Name]和网站地址[Site_URL]。 ",
"Accounts_Enrollment_Email_Subject_Default": "欢迎访问 [Site_Name]",
+ "Accounts_ForgetUserSessionOnWindowClose": "关闭窗口后忘记用户会话",
"Accounts_Iframe_api_method": "API 方法",
"Accounts_Iframe_api_url": "API URL",
"Accounts_iframe_enabled": "已启用",
- "Accounts_iframe_url": "框架地址",
- "Accounts_LoginExpiration": "登录失效天数",
+ "Accounts_iframe_url": "Iframe Url",
+ "Accounts_LoginExpiration": "登录保持的天数",
"Accounts_ManuallyApproveNewUsers": "手动审核新用户",
- "Accounts_OAuth_Custom_Authorize_Path": "自定义 OAuth 的认证地址 ",
- "Accounts_OAuth_Custom_Button_Color": "底部颜色",
- "Accounts_OAuth_Custom_Button_Label_Color": "底部文字颜色",
- "Accounts_OAuth_Custom_Button_Label_Text": "底部文字",
+ "Accounts_OAuth_Custom_Authorize_Path": "授权路径",
+ "Accounts_OAuth_Custom_Button_Color": "按钮颜色",
+ "Accounts_OAuth_Custom_Button_Label_Color": "按钮文字颜色",
+ "Accounts_OAuth_Custom_Button_Label_Text": "按钮文字",
"Accounts_OAuth_Custom_Enable": "启用",
- "Accounts_OAuth_Custom_id": "客户端 ID",
+ "Accounts_OAuth_Custom_id": "ID",
"Accounts_OAuth_Custom_Identity_Path": "身份路径",
"Accounts_OAuth_Custom_Login_Style": "登录样式",
- "Accounts_OAuth_Custom_Secret": "密钥",
- "Accounts_OAuth_Custom_Token_Path": "Token 地址",
- "Accounts_OAuth_Custom_Token_Sent_Via": "令牌发生通过",
- "Accounts_OAuth_Facebook": "Facebook 登录",
+ "Accounts_OAuth_Custom_Merge_Users": "合并用户",
+ "Accounts_OAuth_Custom_Scope": "范围",
+ "Accounts_OAuth_Custom_Secret": "Secret",
+ "Accounts_OAuth_Custom_Token_Path": "Token 路径",
+ "Accounts_OAuth_Custom_Token_Sent_Via": "Token 发送通过",
+ "Accounts_OAuth_Custom_Username_Field": "用户名 字段",
+ "Accounts_OAuth_Facebook": "Facebook 账户登录",
"Accounts_OAuth_Facebook_callback_url": "Facebook 回调地址",
- "Accounts_OAuth_Facebook_id": "Facebook 应用程序 ID",
+ "Accounts_OAuth_Facebook_id": "Facebook APP ID",
"Accounts_OAuth_Facebook_secret": "Facebook Secret",
- "Accounts_OAuth_Github": "启用 OAuth 登录",
+ "Accounts_OAuth_Github": "OAuth 已启用",
"Accounts_OAuth_Github_callback_url": "Github 回调地址",
"Accounts_OAuth_GitHub_Enterprise": "OAuth 已启用",
"Accounts_OAuth_GitHub_Enterprise_callback_url": "GitHub 企业版回调地址",
@@ -67,90 +78,117 @@
"Accounts_OAuth_Gitlab_callback_url": "GitLab 回调地址",
"Accounts_OAuth_Gitlab_id": "GitLab ID",
"Accounts_OAuth_Gitlab_secret": "客户端 Secret",
- "Accounts_OAuth_Google": "使用 Google 帐号登录",
+ "Accounts_OAuth_Google": "Google 账户登录",
"Accounts_OAuth_Google_callback_url": "Google 回调地址",
"Accounts_OAuth_Google_id": "Google ID",
"Accounts_OAuth_Google_secret": "Google 密钥",
- "Accounts_OAuth_Linkedin": "LinkedIn 帐号登录",
- "Accounts_OAuth_Linkedin_callback_url": "Linkedin 回调地址",
+ "Accounts_OAuth_Linkedin": "LinkedIn 账户登录",
+ "Accounts_OAuth_Linkedin_callback_url": "LinkedIn 回调地址",
"Accounts_OAuth_Linkedin_id": "LinkedIn ID",
- "Accounts_OAuth_Linkedin_secret": "LinkedIn 密钥",
- "Accounts_OAuth_Meteor": "Meteor 帐号登录",
+ "Accounts_OAuth_Linkedin_secret": "LinkedIn Secret",
+ "Accounts_OAuth_Meteor": "Meteor 账户登录",
"Accounts_OAuth_Meteor_callback_url": "Meteor 回调地址",
"Accounts_OAuth_Meteor_id": "Meteor ID",
- "Accounts_OAuth_Meteor_secret": "Meteor 密钥",
- "Accounts_OAuth_Twitter": "Twitter 帐号登录",
+ "Accounts_OAuth_Meteor_secret": "Meteor Secret",
+ "Accounts_OAuth_Proxy_host": "代理主机",
+ "Accounts_OAuth_Proxy_services": "代理服务",
+ "Accounts_OAuth_Twitter": "Twitter 账户登录",
"Accounts_OAuth_Twitter_callback_url": "Twitter 回调地址",
"Accounts_OAuth_Twitter_id": "Twitter ID",
- "Accounts_OAuth_Twitter_secret": "Twitter 密钥",
- "Accounts_OAuth_Wordpress": "WordPress 登录",
- "Accounts_OAuth_Wordpress_callback_url": "Wordpress 回调地址",
- "Accounts_OAuth_Wordpress_id": "WordPress 应用 ID",
- "Accounts_OAuth_Wordpress_secret": "WordPress 应用密钥",
+ "Accounts_OAuth_Twitter_secret": "Twitter Secret",
+ "Accounts_OAuth_Wordpress": "WordPress 账户登录",
+ "Accounts_OAuth_Wordpress_callback_url": "WordPress 回调地址",
+ "Accounts_OAuth_Wordpress_id": "WordPress ID",
+ "Accounts_OAuth_Wordpress_secret": "WordPress Secret",
"Accounts_PasswordReset": "重置密码",
+ "Accounts_Registration_AuthenticationServices_Default_Roles": "认证服务的默认角色",
+ "Accounts_Registration_AuthenticationServices_Default_Roles_Description": "当通过认证服务注册时被授予默认角色的用户(用逗号分隔)",
"Accounts_Registration_AuthenticationServices_Enabled": "使用认证服务注册",
"Accounts_RegistrationForm": "注册表单",
"Accounts_RegistrationForm_Disabled": "已禁用",
"Accounts_RegistrationForm_LinkReplacementText": "注册表单链接的替代文本",
"Accounts_RegistrationForm_Public": "公开",
- "Accounts_RegistrationForm_Secret_URL": "私密地址",
- "Accounts_RegistrationForm_SecretURL": "私密注册表单 ",
- "Accounts_RegistrationForm_SecretURL_Description": "您必须提供一个随机字符串,该字符串将被添加到您的注册地址中。例如:https://demo.rocket.chat/register/[secret_hash]",
- "Accounts_RequireNameForSignUp": "需要填写姓名才能注册",
+ "Accounts_RegistrationForm_Secret_URL": "Secret URL",
+ "Accounts_RegistrationForm_SecretURL": "注册表单 Secret URL",
+ "Accounts_RegistrationForm_SecretURL_Description": "您必须提供一个随机字符串,该字符串将被添加到您的注册地址中。例如:https://open.rocket.chat/register/[secret_hash]",
+ "Accounts_RequireNameForSignUp": "姓名必须填写",
+ "Accounts_RequirePasswordConfirmation": "请再次确认密码",
+ "Accounts_SetDefaultAvatar": "设置默认头像",
+ "Accounts_SetDefaultAvatar_Description": "尝试从 OAuth 账户或 Gravatar 检查默认头像",
"Accounts_ShowFormLogin": "显示基于表单的登录界面",
"Accounts_UseDefaultBlockedDomainsList": "使用默认的屏蔽域名列表",
- "Accounts_UseDNSDomainCheck": "使用 DNS 域名验证",
- "Accounts_UserAddedEmail_Default": "欢迎访问 [Site_Name] 转到 [Site_URL] 并尝试当今最先进的开源聊天解决方案!
您可以使用您的电子邮件地址:[email] 和密码:[password] 进行登陆。您可能需要在您首次登录后更改密码。
",
- "Accounts_UserAddedEmail_Description": "您可以使用以下占位符:[name], [fname], [lname] 分别作为用户的全名、名字或姓氏。 [email] 作为用户的电子邮件。 [password] 作为用户的密码。 [Site_Name] 和 [Site_URL] 分别作为网站名称和网站地址。 ",
+ "Accounts_UseDNSDomainCheck": "使用 DNS 域名检查",
+ "Accounts_UserAddedEmail_Default": "欢迎访问 [Site_Name] 转到 [Site_URL] 并尝试当今最先进的开源聊天解决方案!
您可以使用您的电子邮件地址:[email] 和密码:[password] 进行登陆。您可能需要在您首次登录后更改密码。
",
+ "Accounts_UserAddedEmail_Description": "您可以使用以下占位符:全名 [name],名字 [fname],姓氏 [lname]。 [email] 为用户的email。 [password] 为用户的密码。 [Site_Name] 和 [Site_URL] 分别作为网站名称和网站地址。 ",
"Accounts_UserAddedEmailSubject_Default": "您已被添加到 [Site_Name]",
"Activate": "激活",
"Activity": "活动",
"Add": "添加",
"Add_agent": "添加客服",
"Add_custom_oauth": "添加自定义 OAuth ",
+ "Add_Domain": "添加域名",
"Add_manager": "添加管理员",
- "Add_user": "新增用户",
+ "Add_user": "添加用户",
"Add_User": "添加用户",
"Add_users": "添加用户",
"Adding_OAuth_Services": "添加 OAuth 服务",
"Adding_permission": "正在添加权限",
"Adding_user": "正在添加用户",
- "Additional_emails": "其它电子邮箱地址",
- "Additional_Feedback": "额外反馈",
+ "Additional_emails": "其他 Email",
+ "Additional_Feedback": "其他反馈",
"Administration": "管理",
"After_OAuth2_authentication_users_will_be_redirected_to_this_URL": "通过 OAuth2 认证后,用户将被重定向至此地址",
+ "Agent": "客服",
"Agent_added": "客服已添加",
"Agent_removed": "客服已删除",
"Alias": "别名",
"Alias_Format": "别名格式",
+ "Alias_Format_Description": "从 Slack 导入信息;%s 会被用户的用户名替代。如果留空则不使用别名。",
+ "Alias_Set": "别名设置",
"All": "全部",
"All_channels": "所有频道",
"All_logs": "所有日志",
- "All_messages": "所有信息",
+ "All_messages": "所有消息",
"Allow_Invalid_SelfSigned_Certs": "允许无效的自签名 SSL 证书",
"Allow_Invalid_SelfSigned_Certs_Description": "允许无效的自签名 SSL 证书用于验证和预览链接。",
+ "Always_open_in_new_window": "总是在新窗口中打开",
"Analytics_features_enabled": "功能已启用",
- "Analytics_features_messages_Description": "跟踪与用户在消息中做的操作相关的自定义事件。",
- "Analytics_features_rooms_Description": "跟踪与频道或分组操作相关的自定义事件(创建,离开,删除)。",
+ "Analytics_features_messages_Description": "跟踪与用户对消息的操作相关的自定义事件。",
+ "Analytics_features_rooms_Description": "跟踪与频道或分组操作相关的自定义事件(创建、离开、删除)。",
"Analytics_features_users_Description": "跟踪与用户操作相关的自定义事件(密码重置次数、个人资料图片变化等)。",
+ "Analytics_Google": "Google 统计",
+ "Analytics_Google_id": "跟踪 ID",
"and": "和",
"And_more": "以及其它 __length__ 条",
"Animals_and_Nature": "动物与自然",
+ "Announcement": "公告",
"API": "API",
+ "API_Allow_Infinite_Count": "允许获取一切",
+ "API_Allow_Infinite_Count_Description": "是否允许在一次 REST API 调用中返回所有内容?",
"API_Analytics": "分析",
- "API_Embed": "嵌入",
- "API_EmbedDisabledFor": "禁止用户使用嵌入",
- "API_EmbedDisabledFor_Description": "以逗号分隔的用户名列表",
+ "API_CORS_Origin": "CORS 源",
+ "API_Default_Count": "默认计数",
+ "API_Default_Count_Description": "消费者未提供时 REST API 结果的默认计数",
+ "API_Embed": "嵌入链接预览",
+ "API_Embed_Description": "当用户发布一个网站链接时,是否启用嵌入链接预览。",
+ "API_EmbedCacheExpirationDays": "嵌入缓存有效天数",
+ "API_EmbedDisabledFor": "禁用嵌入的用户",
+ "API_EmbedDisabledFor_Description": "禁止使用嵌入链接预览功能的用户(以逗号分隔的用户名)",
"API_EmbedIgnoredHosts": "嵌入忽略的主机",
"API_EmbedIgnoredHosts_Description": "以逗号分隔的主机或 CIDR 地址,例如:localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16",
"API_EmbedSafePorts": "安全端口",
"API_EmbedSafePorts_Description": "逗号分隔允许预览的端口列表。",
- "API_GitHub_Enterprise_URL": "服务地址",
- "API_GitHub_Enterprise_URL_Description": "例如:http://domain.com (不需要结尾的斜线)",
+ "API_Enable_CORS": "启用 CORS",
+ "API_Enable_Direct_Message_History_EndPoint": "启用 Direct Message History Endpoint",
+ "API_Enable_Direct_Message_History_EndPoint_Description": "这会启用 `/api/v1/im.history.others`,它允许查看其他用户发送的私信。",
+ "API_GitHub_Enterprise_URL": "服务器 URL",
+ "API_GitHub_Enterprise_URL_Description": "例如:http://domain.com (末尾无斜线)",
"API_Gitlab_URL": "GitLab URL",
- "API_Token": "API 令牌",
- "API_User_Limit": "用户限制添加所有用户通道",
- "API_Wordpress_URL": "WordPress 网址",
+ "API_Token": "API Token",
+ "API_Upper_Count_Limit": "最大记录量",
+ "API_Upper_Count_Limit_Description": "REST API 应返回的最大记录数量(在没有限制的条件下)?",
+ "API_User_Limit": "添加所有用户到频道的用户限制",
+ "API_Wordpress_URL": "WordPress URL",
"Apiai_Key": "Api.ai Key",
"Apiai_Language": "Api.ai 语言",
"Appearance": "外观",
@@ -163,13 +201,16 @@
"are_typing": "正在输入",
"Are_you_sure": "你确定吗?",
"Are_you_sure_you_want_to_delete_your_account": "您确定要删除您的帐号吗?",
+ "Assign_admin": "分配管理员",
"at": "在",
- "Auth_Token": "身份验证 Token",
+ "Attachment_File_Uploaded": "文件已上传",
+ "Attribute_handling": "属性处理",
+ "Auth_Token": "Auth Token",
"Author": "作者",
- "Authorization_URL": "授权地址",
+ "Authorization_URL": "授权 URL",
"Authorize": "授权",
"Auto_Load_Images": "自动载入图片",
- "AutoLinker_Email": "自动链接电子邮件地址",
+ "Auto_Translate": "自动翻译",
"AutoLinker_Phone": "自动链接电话号码",
"AutoLinker_Phone_Description": "自动为电话号码添加链接。例如:`(123)456-7890`",
"AutoLinker_StripPrefix": "自动链接显示链接前缀",
@@ -178,6 +219,11 @@
"AutoLinker_Urls_TLD": "自动链接顶级域名的网址",
"AutoLinker_Urls_www": "自动链接以“www”开头的网址",
"AutoLinker_UrlsRegExp": "自动链接网址正则表达式",
+ "Automatic_Translation": "自动翻译",
+ "AutoTranslate_Change_Language_Description": "修改自动翻译的语言不会翻译之前的消息。",
+ "AutoTranslate_Enabled": "启用自动翻译",
+ "AutoTranslate_Enabled_Description": "开启自动翻译功能将允许用户获得自动翻译权限,所有消息都将被自动翻译成用户选择的语言。这可需要付费,请查阅 Google 文档 ",
+ "AutoTranslate_GoogleAPIKey": "Google API Key",
"Available": "可用",
"Available_agents": "空闲客服",
"Avatar": "更改头像",
@@ -192,12 +238,19 @@
"Away_male": "离开",
"Back": "返回",
"Back_to_applications": "返回应用列表",
+ "Back_to_integration_detail": "返回查看集成的详细信息",
"Back_to_integrations": "返回集成页",
"Back_to_login": "返回登录界面",
"Back_to_permissions": "返回权限页",
+ "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "测试功能。需要启用视频会议功能。",
+ "Block_User": "阻止用户",
"Body": "主体",
"bold": "粗体",
+ "bot_request": "Bot 请求",
+ "BotHelpers_userFields": "用户字段",
+ "BotHelpers_userFields_Description": "用户字段中的 CSV 是可以被 bot 帮助器方法访问的。",
"Branch": "分支",
+ "Bugsnag_api_key": "Bugsnag API Key",
"busy": "忙",
"Busy": "忙",
"busy_female": "忙碌",
@@ -205,17 +258,37 @@
"busy_male": "忙碌",
"Busy_male": "忙碌",
"by": "通过",
+ "cache_cleared": "缓存已清理",
"Cancel": "取消",
"Cancel_message_input": "取消",
"Cannot_invite_users_to_direct_rooms": "不能邀请用户加入私聊房间",
+ "CAS_autoclose": "自动关闭登录窗口",
+ "CAS_base_url": "SSO 基本 URL",
+ "CAS_base_url_Description": "外部 SSO 服务的基本 URL,例如:https://sso.example.undef/sso/",
+ "CAS_button_color": "登录按钮背景颜色",
+ "CAS_button_label_color": "登录按钮文字颜色",
+ "CAS_button_label_text": "登录按钮标签",
+ "CAS_enabled": "已启用",
+ "CAS_Login_Layout": "CAS 登录布局",
+ "CAS_login_url": "SSO 登录 URL",
+ "CAS_login_url_Description": "外部 SSO 服务的登录 URL,例如:https://sso.example.undef/sso/login",
+ "CAS_popup_height": "登录框高度",
+ "CAS_popup_width": "登录框宽度",
+ "CAS_Sync_User_Data_Enabled": "始终同步用户数据",
+ "CAS_Sync_User_Data_FieldMap": "属性映射",
+ "CAS_version": "CAS 版本",
"CDN_PREFIX": "CDN 前缀",
"Certificates_and_Keys": "证书和密钥",
+ "Change_Room_Type": "正在修改房间类型",
"Changing_email": "正在更改电子邮件",
+ "channel": "频道",
"Channel": "频道",
"Channel_already_exist": "通道'#%s“已存在。",
"Channel_already_Unarchived": "与名`#%s`通道已经处于未封存状态",
"Channel_Archived": "与名`#%s`通道已成功存档",
+ "Channel_created": "`#%s` 频道已创建。",
"Channel_doesnt_exist": "不存在 `#%s` 频道。",
+ "Channel_to_listen_on": "监听频道",
"Channel_Unarchived": "与名`#%s`通道已取消封存成功",
"Channels": "频道",
"Channels_list": "公共频道列表",
@@ -230,8 +303,12 @@
"Choose_messages": "选择信息",
"Choose_the_alias_that_will_appear_before_the_username_in_messages": "选择将在消息中的用户名前出现的别名。",
"Choose_the_username_that_this_integration_will_post_as": "选择该集成以什么用户名身份发布信息",
+ "clear": "清理",
"Clear_all_unreads_question": "清除所有未读标记?",
+ "clear_cache_now": "立即清理缓存",
+ "clear_history": "清理历史记录",
"Click_here": "点击这里",
+ "Click_here_for_more_info": "点此查看更多信息",
"Client_ID": "客户端 ID",
"Client_Secret": "客户端 Secret",
"Clients_will_refresh_in_a_few_seconds": "客户端将在几秒钟内刷新",
@@ -243,8 +320,10 @@
"Collapse_Embedded_Media_By_Default": "关闭默认的嵌入式媒体",
"Color": "颜色",
"Commands": "指令",
+ "Comment_to_leave_on_closing_session": "为关闭的会话留下评论",
"Compact": "紧凑",
"Confirm_password": "确认密码",
+ "Content": "内容",
"Conversation": "谈话",
"Conversation_closed": "会话已关闭:__comment__。",
"Convert_Ascii_Emojis": "自动识别文字中的表情",
@@ -259,19 +338,46 @@
"Create_new": "新建",
"Created_at": "创建于",
"Created_at_s_by_s": "由 %s 创建于 %s ",
+ "Created_at_s_by_s_triggered_by_s": "由 %s 创建于 %s 被 %s 触发",
+ "CRM_Integration": "CRM 集成",
+ "CROWD_Reject_Unauthorized": "拒绝未经授权的",
"Current_Chats": "当前聊天",
"Custom": "自定义",
+ "Custom_Emoji": "自定义表情",
+ "Custom_Emoji_Add": "添加新表情",
+ "Custom_Emoji_Added_Successfully": "自定义表情添加成功",
+ "Custom_Emoji_Delete_Warning": "表情删除操作无法撤销。",
+ "Custom_Emoji_Error_Invalid_Emoji": "无效的表情",
+ "Custom_Emoji_Error_Name_Or_Alias_Already_In_Use": "自定义表情或别名已经被占用。",
+ "Custom_Emoji_Has_Been_Deleted": "自定义表情已经被删除。",
+ "Custom_Emoji_Info": "自定义表情信息",
+ "Custom_Emoji_Updated_Successfully": "自定义表情更新成功",
"Custom_Fields": "自定义字段",
"Custom_oauth_helper": "设置完 OAuth 提供者之后,你还需要设置回调 URL。请使用 %s 。",
"Custom_oauth_unique_name": "自定义 OAuth 唯一名称 ",
"Custom_Script_Logged_In": "为已登录用户准备的自定义脚本",
"Custom_Script_Logged_Out": "为已登出用户准备的自定义脚本",
+ "Custom_Scripts": "自定义脚本",
+ "Custom_Sound_Add": "添加自定义声音",
+ "Custom_Sound_Delete_Warning": "声音删除操作无法撤销。",
+ "Custom_Sound_Error_Invalid_Sound": "无效的声音",
+ "Custom_Sound_Error_Name_Already_In_Use": "自定义声音的名称已被占用。",
+ "Custom_Sound_Has_Been_Deleted": "自定义声音已删除。",
+ "Custom_Sound_Info": "自定义声音信息",
+ "Custom_Sound_Saved_Successfully": "自定义声音保存成功",
+ "Custom_Sounds": "自定义声音",
+ "Custom_Translations": "自定义翻译",
+ "Custom_Translations_Description": "应使用 JSON 文件格式,键为语言,值为翻译。例如:{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
+ "CustomSoundsFilesystem": "自定义声音文件系统",
"Dashboard": "控制面板",
"Date": "日期",
+ "Date_From": "从",
+ "Date_to": "到",
"days": "天",
"DB_Migration": "数据库迁移",
"DB_Migration_Date": "数据库迁移日期",
"Deactivate": "禁用",
+ "Decline": "下降",
"Default": "默认",
"Delete": "删除",
"Delete_message": "删除消息",
@@ -292,12 +398,15 @@
"Desktop_Notifications_Duration_Description": "多少秒显示桌面通知。这可能会影响OS X通知中心。输入0可使用默认浏览器设置,并不会影响OS X通知中心。",
"Desktop_Notifications_Enabled": "桌面通知已启用",
"Direct_message_someone": "直接给某人发送消息",
- "Direct_Messages": "直接发送消息",
+ "Direct_Messages": "私信",
"Display_offline_form": "显示离线表单",
"Displays_action_text": "显示动作文字",
"Do_you_want_to_change_to_s_question": "您是否想修改为 %s ?",
"Domain": "域名",
+ "Domain_added": "域名已添加",
+ "Domain_removed": "域名已移除",
"Domains": "域名",
+ "Download_Snippet": "下载",
"Drop_to_upload_file": "拖放上传",
"Dry_run": "发送测试",
"Dry_run_description": "表单中的 E-mail 都只会收到一封邮件。邮件必须对应有效用户。",
@@ -309,6 +418,7 @@
"Edit": "编辑",
"Edit_Custom_Field": "编辑自定义字段",
"Edit_Department": "编辑部门",
+ "Edit_Trigger": "编辑触发器",
"edited": "已编辑",
"Editing_room": "正在编辑聊天室",
"Editing_user": "正在编辑用户",
@@ -327,16 +437,22 @@
"Email_subject": "标题",
"Email_verified": "邮箱已验证",
"Emoji": "表情符号",
+ "EmojiCustomFilesystem": "自定义表情文件系统",
"Empty_title": "空标题",
"Enable": "启用",
"Enable_Desktop_Notifications": "启用桌面通知",
+ "Enable_Svg_Favicon": "启用 SVG 图标",
"Enabled": "已启用",
"Encrypted_message": "加密消息",
"End_OTR": "结束无记录对话",
"Enter_a_regex": "输入正则表达式",
"Enter_a_room_name": "在这里输入房间名",
"Enter_a_username": "输入用户名",
+ "Enter_Alternative": "替代模式(Enter + Ctrl/Alt/Shift/CMD 发送消息)",
+ "Enter_Behaviour": "回车键",
+ "Enter_Behaviour_Description": "此项用来设置回车键发送消息还是换行",
"Enter_name_here": "在这里输入名字",
+ "Enter_Normal": "常规模式(Enter 发送消息)",
"Enter_to": "进入",
"Error": "错误",
"error-action-not-allowed": "__action__ 不允许",
@@ -350,8 +466,10 @@
"error-could-not-change-username": "无法更改用户名",
"error-delete-protected-role": "无法删除受保护的角色",
"error-department-not-found": "找不到该部门",
+ "error-direct-message-file-upload-not-allowed": "私信中不允许文件共享",
"error-duplicate-channel-name": "频道 '__channel_name__' 已存在",
"error-email-domain-blacklisted": "电子邮箱域名被列入黑名单",
+ "error-email-send-failed": "尝试发送邮件出错:__message__",
"error-field-unavailable": "__field__ 已被使用 :(",
"error-file-too-large": "文件太大",
"error-importer-not-defined": "导入所用帐号错误,未指定导入class。",
@@ -363,9 +481,11 @@
"error-invalid-channel-start-with-chars": "无效的频道。应该以 @ 或 # 开头",
"error-invalid-custom-field": "无效的自定义字段",
"error-invalid-custom-field-name": "无效的自定义字段名称。只能使用字母、数字、连字符和下划线。",
+ "error-invalid-date": "日期无效。",
"error-invalid-description": "无效的说明",
"error-invalid-domain": "域名无效",
"error-invalid-email": "无效的电子邮件地址 __email__",
+ "error-invalid-email-address": "邮件地址无效",
"error-invalid-file-height": "无效的文件高度",
"error-invalid-file-type": "无效的文件类型",
"error-invalid-file-width": "无效的文件宽度",
@@ -402,12 +522,18 @@
"error-the-field-is-required": "字段 __field__ 必填。",
"error-too-many-requests": "错误,请求过多。请放慢速度。你必须等待__seconds__秒后再次重试。",
"error-user-is-not-activated": "用户未激活",
+ "error-user-limit-exceeded": "你邀请加入 #channel_name 的用户数量超出了管理员设置的最大值限制",
"error-user-not-in-room": "用户不是在这个房间里",
"error-user-registration-disabled": "用户注册被禁用",
"error-user-registration-secret": "用户注册只能通过私密地址",
"error-you-are-last-owner": "你是房间当前的拥有者。请先重设拥有者再离开房间。",
"Error_changing_password": "密码更改失败",
"Esc_to": "退出",
+ "Event_Trigger": "事件触发",
+ "Event_Trigger_Description": "选择将触发此外发 WebHook 集成的事件类型",
+ "every_30_minutes": "每30分钟一次",
+ "every_hour": "每小时一次",
+ "every_six_hours": "每6小时一次",
"Example_s": "例如:%s",
"Exclude_Botnames": "排除机器人",
"False": "否",
@@ -416,11 +542,22 @@
"Features_Enabled": "功能已启用",
"Field": "字段",
"Field_removed": "字段已删除",
+ "Field_required": "字段必须填写",
"File_exceeds_allowed_size_of_bytes": "文件大小超过允许的 __size__ 字节",
+ "File_not_allowed_direct_messages": "私信中不允许文件共享。",
+ "File_type_is_not_accepted": "文件类型不被系统接受。",
+ "File_uploaded": "文件已上传",
"FileUpload": "文件上传",
+ "FileUpload_Disabled": "已禁用文件上传。",
"FileUpload_Enabled": "文件上传已启用",
+ "FileUpload_Enabled_Direct": "私信已启用文件上传",
"FileUpload_File_Empty": "文件为空",
"FileUpload_FileSystemPath": "系统路径",
+ "FileUpload_GoogleStorage_AccessId": "Google 存储 Access ID",
+ "FileUpload_GoogleStorage_Bucket": "Google Storage Bucket 名称",
+ "FileUpload_GoogleStorage_Bucket_Description": "选择存储上传文件的 Bucket 名称",
+ "FileUpload_GoogleStorage_Secret": "Google Storage 密钥",
+ "FileUpload_GoogleStorage_Secret_Description": "请使用这些指令 并将结果粘贴在此处。",
"FileUpload_MaxFileSize": "文件上传大小限制(以字节为单位)",
"FileUpload_MediaType_NotAccepted": "不支持该类型媒体文件",
"FileUpload_MediaTypeWhiteList": "支持的媒体类型",
@@ -437,17 +574,22 @@
"FileUpload_Storage_Type": "存储类型",
"Flags": "旗帜",
"Follow_social_profiles": "关注我们的社交资讯,fork我们在github的项目或者在trello上分享你关于rocket.chat的想法。",
+ "Fonts": "字体",
"Food_and_Drink": "饮食",
"Footer": "页脚",
"For_your_security_you_must_enter_your_current_password_to_continue": "出于安全考虑,您必须输入您的密码以便继续操作",
"Force_SSL": "强制 SSL",
"Force_SSL_Description": "*注意!* _Force SSL_ 不应该与反向代理同时使用。如果您有一个反向代理,您应该在那里设置重定向操作。这个选项用于像 Heroku 的特殊平台,此类平台不允许在反向代理中配置重定向。",
"Forgot_password": "忘记密码",
+ "Forgot_Password_Email": "点此 重置你的密码。",
+ "Forgot_Password_Email_Subject": "[Site_Name] - 密码恢复",
+ "Forgot_password_section": "忘记密码",
"Forward": "转发",
"Forward_chat": "转发对话",
"Forward_to_department": "转到部门",
"Forward_to_user": "转到用户",
"Frequently_Used": "常用",
+ "Friday": "星期五",
"From": "从",
"From_Email": "从电子邮件",
"From_email_warning": "警告 :From 字段来自于邮件服务器的设置。",
@@ -456,14 +598,18 @@
"Give_a_unique_name_for_the_custom_oauth": "请给自定义 OAuth 设置一个唯一的名称",
"Give_the_application_a_name_This_will_be_seen_by_your_users": "给该应用设置一个名称。该名称将被您的用户看到。",
"Global": "全局",
+ "GoogleCloudStorage": "Google 云存储",
"GoogleTagManager_id": "谷歌跟踪代码管理器 ID",
"Hash": "哈希值",
"Header": "头",
+ "Header_and_Footer": "页头和页尾",
+ "Hex_Color_Preview": "Hex 颜色预览",
"Hidden": "已隐藏",
"Hide_Avatars": "隐藏头像",
"Hide_flextab": "通过点击隐藏右边栏",
"Hide_Group_Warning": "您确定要隐藏用户组“%s”吗?",
"Hide_Private_Warning": "您确定要隐藏和“%s”的讨论吗?",
+ "Hide_roles": "隐藏角色",
"Hide_room": "隐藏聊天室",
"Hide_Room_Warning": "您确定要隐藏房间“%s”吗?",
"Hide_usernames": "隐藏用户名",
@@ -473,16 +619,26 @@
"History": "历史",
"Host": "服务器",
"hours": "小时",
+ "Hours": "小时",
"How_friendly_was_the_chat_agent": "在线客服的友善度如何?",
"How_knowledgeable_was_the_chat_agent": "在线客服的知识储备如何",
+ "How_long_to_wait_after_agent_goes_offline": "客服下线后等待的时间",
"How_responsive_was_the_chat_agent": "在线客服的反应速度如何?",
"How_satisfied_were_you_with_this_chat": "您是否满意这次聊天?",
+ "How_to_handle_open_sessions_when_agent_goes_offline": "客服离线时如何处理正在进行的会话",
"If_you_are_sure_type_in_your_password": "如果您确定,请输入您的密码:",
"If_you_are_sure_type_in_your_username": "如果您确定,请输入您的用户名:",
+ "Iframe_Integration_receive_enable": "启用接收",
+ "Iframe_Integration_receive_enable_Description": "允许父窗口发送命令给 Rocket.Chat。",
+ "Iframe_Integration_send_enable": "启用发送",
+ "Iframe_Integration_send_enable_Description": "发送事件到父窗口",
+ "Impersonate_user": "模拟用户",
"Importer_Archived": "已归档",
"Importer_done": "导入已完成!",
"Importer_finishing": "导入即将完成。",
"Importer_From_Description": "将 __from__ 数据导入 Rocket.Chat。",
+ "Importer_HipChatEnterprise_BetaWarning": "请注意,导入功能尚处于开发阶段,如有错误发生请在 GitHub 向我们反馈:",
+ "Importer_HipChatEnterprise_Information": "上传的文件必须为未加密的 tar.gz 文件,请查阅文档进一步了解相关信息:",
"Importer_import_cancelled": "已取消导入。",
"Importer_import_failed": "导入过程中发生错误!",
"Importer_importing_channels": "正在导入频道。",
@@ -490,12 +646,16 @@
"Importer_importing_started": "正在开始导入。",
"Importer_importing_users": "正在导入用户。",
"Importer_not_in_progress": "导入工具没有正常运行。",
+ "Importer_not_setup": "导入器未正确设置,因为它未返回任何数据。",
"Importer_Prepare_Restart_Import": "重新启动导入",
"Importer_Prepare_Start_Import": "开始导入",
"Importer_Prepare_Uncheck_Archived_Channels": "取消选中已归档的频道",
"Importer_Prepare_Uncheck_Deleted_Users": "取消选中已删除的用户",
"Importer_progress_error": "无法获得导入进度。",
"Importer_setup_error": "设置导入工具时发生了错误。",
+ "Importer_Source_File": "选择源文件",
+ "Incoming_Livechats": "入站聊天",
+ "Incoming_WebHook": "入站 WebHook",
"inline_code": "inline_code",
"Install_Extension": "安装扩展程序",
"Install_FxOs": "在火狐浏览器中安装 Rocket.Chat",
@@ -506,11 +666,15 @@
"Installed_at": "安装在",
"Instructions_to_your_visitor_fill_the_form_to_send_a_message": "给你访问者的说明,指导它们填写表格来发送一条消息",
"Integration_added": "集成已添加",
+ "Integration_Advanced_Settings": "高级设置",
+ "Integration_History_Cleared": "已成功清理集成历史记录",
"Integration_Incoming_WebHook": "Incoming WebHook 集成",
"Integration_New": "新的集成",
"Integration_Outgoing_WebHook": "Outgoing WebHook 集成",
"Integration_updated": "集成已更新",
+ "Integration_Word_Trigger_Placement_Description": "激发事件的单词是否允许放在句子中的任何位置,而不仅限于句首?",
"Integrations": "集成",
+ "Integrations_for_all_channels": "输入 all_public_channels 监听所有公共频道,all_private_groups 监听所有私有组,all_direct_messages 监听所有私信。",
"InternalHubot": "内部Hubot",
"InternalHubot_ScriptsToLoad": "需要加载的脚本",
"InternalHubot_ScriptsToLoad_Description": "请输入一个逗号分隔的脚本列表从https://github.com/github/hubot-scripts/tree/master/src/scripts加载",
@@ -524,15 +688,32 @@
"Invalid_pass": "密码不能为空",
"Invalid_room_name": "%s 不是一个有效的房间名称, 只能使用字母、数字、连字符和下划线",
"Invalid_secret_URL_message": "提供的网址无效。",
+ "Invalid_setting_s": "无效的设置:%s",
"invisible": "隐身",
"Invisible": "隐身",
+ "Invitation": "邀请",
"Invitation_HTML": "邀请邮件HTML",
"Invitation_HTML_Default": "您已被邀请到 [Site_Name] 转到[Site_URL],并尝试当今最先进的开源聊天解决方案!
",
"Invitation_HTML_Description": "您可以使用以下占位符: [email] 作为收件人邮箱地址。 [Site_Name] 和 [Site_URL] 分别作为应用程序的名称和网址。 ",
"Invitation_Subject": "邀请邮件主题",
"Invitation_Subject_Default": "您已被邀请到 [Site_Name]",
"Invite_user_to_join_channel": "邀请一位用户加入这个频道",
+ "Invite_user_to_join_channel_all_from": "邀请 [#channel] 的所有用户加入此频道",
+ "Invite_user_to_join_channel_all_to": "邀请此频道所有用户加入 [#channel]",
"Invite_Users": "邀请用户",
+ "IRC_Channel_Join": "JOIN 命令的输出",
+ "IRC_Channel_Leave": "PART 命令的输出",
+ "IRC_Channel_Users": "NAMES 命令的输出",
+ "IRC_Channel_Users_End": "NAMES 命令输出的结尾",
+ "IRC_Description": "互联网中继聊天(IRC)是基于文本的群组通信工具。用户加入具有唯一名称的频道或房间进行开放式的讨论。IRC 也支持个人用户之间的私人消息和文件共享功能。这个包将这些功能层与 Rocket.Chat 集成。",
+ "IRC_Enabled": "为了集成 IRC 支持。修改这个值需要重新启动 Rocket.Chat。",
+ "IRC_Hostname": "要连接的 IRC 主机服务器。",
+ "IRC_Login_Fail": "在连接 IRC 服务器失败时输出。",
+ "IRC_Login_Success": "在成功连接 IRC 服务器时输出。",
+ "IRC_Message_Cache_Size": "处理外发消息的缓存限制。",
+ "IRC_Port": "要绑定的 IRC 主机服务器的端口。",
+ "IRC_Private_Message": "PRIVMSG 命令的输出",
+ "IRC_Quit": "在退出一个 IRC 会话时输出。",
"is_also_typing": "也正在输入",
"is_also_typing_female": "正在输入",
"is_also_typing_male": "正在输入",
@@ -577,30 +758,28 @@
"Layout_Terms_of_Service": "服务条款",
"LDAP": "LDAP",
"LDAP_CA_Cert": "CA 证书",
- "LDAP_Custom_Domain_Search": "自定义域搜索条件",
- "LDAP_Custom_Domain_Search_Description": "这样管理信息绑定和连接的 JSON 数据: {\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}",
+ "LDAP_Connect_Timeout": "连接超时(ms)",
"LDAP_Default_Domain": "默认域名",
"LDAP_Description": "LDAP(轻量目录访问协议)是一种层次数据库,常被企业用于提供单点登录机制——该机制允许用户使用同一套帐号密码登录多个网站或服务。想要了解LDAP认证的设置及示例,可参考我们的wiki页: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
- "LDAP_Domain_Base": "基础域",
- "LDAP_Domain_Base_Description": "请填写有效的 DN 作为基础域(Domain Base),以便在该DN指向的 LDAP 子树中检索用户和组。您可添加多个DN,但组与组内用户必须定义在同一个基础域中。若您限定了某些 DN 作为基础域,则只能检索到这些DN下的用户。建议使用 LDAP 中的顶级目录作为基础域,配合下面的“自定义域搜索”筛选条件来进行用户的限制。",
- "LDAP_Domain_Search_Filter": "筛选条件",
- "LDAP_Domain_Search_Filter_Description": "若在此处指定了筛选条件,则仅有符合条件的用户方可登录。若为指定筛选条件,则 domain base 中的所有用户均可登录。 举例: Windows AD域 `memberOf=cn=ROCKET_CHAT,ou=General Groups`。 OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`。",
- "LDAP_Domain_Search_Object_Category": "检索用户所用的objectCategory ",
- "LDAP_Domain_Search_Object_Category_Description": "请输入 LDAP 中用以识别用户的*objectCategory*。 若使用 *OpenLDAP* 则此项留空。 举例:对于Windows AD,常用分类为`person`。",
- "LDAP_Domain_Search_Object_Class": "检索用户所用的objectclass",
- "LDAP_Domain_Search_Object_Class_Description": "请输入 LDAP 中用以识别用户的*objectclass*。 例如:`user`,`organizationalPerson`,`inetOrgPerson`等。",
- "LDAP_Domain_Search_Password": "域管理员密码",
- "LDAP_Domain_Search_Password_Description": "域管理员登录 LDAP 的密码",
- "LDAP_Domain_Search_User": "域管理员",
- "LDAP_Domain_Search_User_Description": "该LDAP用户将在其他用户登录时被用于在 LDAP 中执行检索和认证。 通常情况下,该用户是在 LDAP 中特地为第三方集成而创建的帐号。请使用有效的全名,如`cn=Administrator,cn=Users,dc=Example,dc=com`。",
- "LDAP_Domain_Search_User_ID": "帐号认证字段",
- "LDAP_Domain_Search_User_ID_Description": "该 LDAP 属性是用于识别登录者的字段。对于 Windows AD,通常应使用 `sAMAccountName` 字段,而其他 LDAP 方案(如 OpenLDAP)可能使用 `uid` 字段。假如要使用邮箱地址作为帐号,可使用 `mail` 之类的字段。 若要同时使用多种认证字段,可通过逗号分隔字段名。 举例:若要同时使用用户名和邮箱作为认证帐号,可使用`sAMAccountName,mail`。",
+ "LDAP_BaseDN_Description": "请填写有效的 DN 作为基础域(Domain Base),以便在该DN指向的 LDAP 子树中检索用户和组。您可添加多个DN,但组与组内用户必须定义在同一个基础域中。若您限定了某些 DN 作为基础域,则只能检索到这些DN下的用户。建议使用 LDAP 中的顶级目录作为基础域,配合下面的“自定义域搜索”筛选条件来进行用户的限制。",
+ "LDAP_User_Search_Field_Description": "该 LDAP 属性是用于识别登录者的字段。对于 Windows AD,通常应使用 `sAMAccountName` 字段,而其他 LDAP 方案(如 OpenLDAP)可能使用 `uid` 字段。假如要使用邮箱地址作为帐号,可使用 `mail` 之类的字段。 若要同时使用多种认证字段,可通过逗号分隔字段名。 举例:若要同时使用用户名和邮箱作为认证帐号,可使用`sAMAccountName,mail`。",
+ "LDAP_User_Search_Filter_Description": "若在此处指定了筛选条件,则仅有符合条件的用户方可登录。若为指定筛选条件,则 domain base 中的所有用户均可登录。 举例: Windows AD域 `memberOf=cn=ROCKET_CHAT,ou=General Groups`。 OpenLDAP (extensible match search) `ou:dn:=ROCKET_CHAT`。",
+ "LDAP_Authentication_UserDN_Description": "该LDAP用户将在其他用户登录时被用于在 LDAP 中执行检索和认证。 通常情况下,该用户是在 LDAP 中特地为第三方集成而创建的帐号。请使用有效的全名,如`cn=Administrator,cn=Users,dc=Example,dc=com`。",
"LDAP_Enable": "启用",
"LDAP_Enable_Description": "尝试使用 LDAP 进行身份验证。",
"LDAP_Encryption": "加密方法",
"LDAP_Encryption_Description": "请指定与 LDAP 服务器通信时,使用何种加密方法。可选方法包括:`不使用加密`,`SSL/LDAPS`(全程启用加密)和`StartTLS`(建立连接后启用加密)",
+ "LDAP_Group_Filter_Enable": "启用 LDAP 用户组过滤",
+ "LDAP_Group_Filter_Enable_Description": "限制对 LDAP 中某个组用户的访问。 对于未设置不允许 *memberOf* 过滤器覆盖的 OpenLDAP 服务器有用。",
+ "LDAP_Group_Filter_ObjectClass": "组 ",
"LDAP_Host": "服务器",
"LDAP_Host_Description": "LDAP服务器的域名或 IP,如 `ldap.example.com` 或 `10.0.0.30`。",
+ "LDAP_Idle_Timeout": "空闲超时(ms)",
+ "LDAP_Import_Users_Description": "设置为 True,同步过程将导入所有 LDAP 用户。 *小心!* 使用搜索过滤排除那些你不想导入的用户。",
+ "LDAP_Login_Fallback": "备用登录",
+ "LDAP_Login_Fallback_Description": "如果无法在 LDAP 上成功登录,则尝试在 默认/本地 账户系统上登录。这在 LDAP 服务器因为某些原因宕机时会有帮助。",
+ "LDAP_Merge_Existing_Users": "合并现有用户",
+ "LDAP_Merge_Existing_Users_Description": "*小心!* 当从 LDAP 导入与当前程序已经存在的同名用户时,LDAP 服务器上的用户信息和密码将会覆盖已存在用户。",
"LDAP_Port": "LDAP 端口",
"LDAP_Port_Description": "LDAP 端口。比如:`389` 或 `636`",
"LDAP_Reject_Unauthorized": "拒绝未授权",
@@ -609,12 +788,9 @@
"LDAP_Sync_User_Data_Description": "登录时保持用户数据和服务器同步(例如:姓名、电子邮箱地址)。",
"LDAP_Sync_User_Data_FieldMap": "用户数据字段映射",
"LDAP_Sync_User_Data_FieldMap_Description": "设置用户数据字段(比如 E-mail)来自 LDAP 何处(如果能找到)。 ;例如:`{\"cn\":\"name\", \"mail\":\"email\"}` 会从属性 cn 中取出名字字段,从 mail 属性中取出 email 字段。 有效字段包括 `name` 和 `email`。",
- "LDAP_Sync_Users": "同步用户",
"LDAP_Test_Connection": "测试连接",
"LDAP_Unique_Identifier_Field": "唯一识别字段",
"LDAP_Unique_Identifier_Field_Description": "使用哪个字段来连接 LDAP 和 Rocket.Chat 的用户信息。可使用逗号分隔的多个字段。 默认值: `objectGUID,ibm-entryUUID,GUID,dominoUNID,nsuniqueId,uidNumber`",
- "LDAP_Use_Custom_Domain_Search": "使用自定义的域搜索",
- "LDAP_Use_Custom_Domain_Search_Description": "请输入在 LDAP 服务器中搜索用户时的筛选条件",
"LDAP_Username_Field": "用户名字段",
"LDAP_Username_Field_Description": "指定新用户登录时,使用 LDAP 中哪个字段的值作为*用户名*。若要使用登录页面所用的用户名,请留空。 可使用模版标签,比如 `#{givenName}.#{sn}`。 默认字段为 `sAMAccountName`。",
"Leave_Group_Warning": "您确定要离开用户组“%s”吗?",
@@ -623,7 +799,7 @@
"Leave_Room_Warning": "您确定要离开房间“%s”吗?",
"line": "行",
"List_of_Channels": "频道列表",
- "List_of_Direct_Messages": "直接对话列表",
+ "List_of_Direct_Messages": "私信列表",
"Livechat_agents": "在线客服",
"Livechat_Dashboard": "在线聊天控制面板",
"Livechat_enabled": "即时聊天启用",
@@ -672,6 +848,7 @@
"Markdown_Headers": "Markdown 标题",
"Markdown_SupportSchemesForLink": "Markdown 支持的链接协议",
"Markdown_SupportSchemesForLink_Description": "由英文逗号分割的协议列表",
+ "Max_length_is": "最大长度 %s",
"Members_List": "成员列表",
"Mentions": "提及",
"Mentions_default": "提及(默认)",
@@ -720,7 +897,7 @@
"Meta_robots": "机器人",
"minutes": "分钟",
"More_channels": "更多频道",
- "More_direct_messages": "更多对话",
+ "More_direct_messages": "更多私信",
"More_groups": "更多私有组",
"More_unreads": "更多未阅读",
"Msgs": "消息",
@@ -888,6 +1065,7 @@
"Refresh_your_page_after_install_to_enable_screen_sharing": "安装完成后需要刷新页面才能支持屏幕共享",
"Register": "注册一个新帐号",
"Registration_Succeeded": "注册成功",
+ "Regular_Expressions": "正则表达式",
"Release": "发布",
"Remove": "移除",
"Remove_Admin": "取消管理员",
@@ -897,10 +1075,12 @@
"Remove_from_room": "从房间中删除",
"Remove_someone_from_room": "将某人从房间中删除",
"Removed": "已删除",
+ "Reply": "回复",
"Report_Abuse": "报告滥用",
"Report_exclamation_mark": "报告!",
"Report_sent": "报告已发送",
"Report_this_message_question_mark": "举报此消息?",
+ "Reporting": "报告",
"Require_password_change": "要求修改密码",
"Resend_verification_email": "重新发送确认邮件",
"Reset": "重置",
@@ -911,19 +1091,25 @@
"Role_Editing": "编辑角色",
"Role_removed": "角色已删除",
"Room": "聊天室",
+ "Room_announcement_changed_successfully": "公告已成功修改",
"Room_archivation_state": "状态",
"Room_archivation_state_false": "活跃",
"Room_archivation_state_true": "已归档",
"Room_archived": "房间已归档",
+ "room_changed_announcement": "__user_by__ 将公告修改为:__room_announcement__ ",
"room_changed_description": "房间描述由 __user_by__ 修改为:__room_description__ ",
"room_changed_privacy": "__user_by__ 将房间类型修改为:__room_type__ ",
"room_changed_topic": "__user_by__ 将房间主题修改为:__room_topic__ ",
"Room_description_changed_successfully": "房间描述修改成功",
+ "Room_has_been_archived": "房间已归档",
"Room_has_been_deleted": "房间已被删除",
+ "Room_has_been_unarchived": "已撤销房间归档",
"Room_Info": "房间信息",
+ "room_name": "房间名",
"Room_name_changed": "聊天室名称更改为: __room_name__ 由 __user_by__ 更改",
"Room_name_changed_successfully": "聊天室名称变更成功",
"Room_not_found": "未找到房间",
+ "Room_password_changed_successfully": "房间密码修改成功",
"Room_topic_changed_successfully": "房间话题已成功修改",
"Room_type_changed_successfully": "房间类型已成功修改",
"Room_unarchived": "房间归档状态已取消",
@@ -936,8 +1122,12 @@
"SAML_Custom_Cert": "自定义凭证",
"SAML_Custom_Entry_point": "自定义入口",
"SAML_Custom_Generate_Username": "生成用户名",
+ "SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO 重定向 URL",
"SAML_Custom_Issuer": "自定义 Issuer",
+ "SAML_Custom_Private_Key": "Private Key",
"SAML_Custom_Provider": "自定义供应商",
+ "SAML_Custom_Public_Cert": "Public Cert",
+ "Saturday": "星期六",
"Save": "保存",
"Save_changes": "保存修改",
"Save_Mobile_Bandwidth": "节约移动带宽",
@@ -1014,7 +1204,10 @@
"SMTP_Port": "SMTP 端口",
"SMTP_Test_Button": "测试 SMTP 设置",
"SMTP_Username": "SMTP 用户名",
+ "Snippet_Added": "创建于 %s",
+ "Snippet_Messages": "消息片段",
"Sound": "声音",
+ "Sound_File_mp3": "声音文件 (mp3)",
"SSL": "SSL",
"Star_Message": "标记信息",
"Starred_Messages": "已标记的信息",
@@ -1038,22 +1231,32 @@
"Stats_Online_Users": "在线用户",
"Stats_Total_Channels": "频道总数",
"Stats_Total_Direct_Messages": "点对点发送消息房间数",
+ "Stats_Total_Livechat_Rooms": "在线聊天房间总计",
"Stats_Total_Messages": "消息总数",
+ "Stats_Total_Messages_Channel": "频道消息总计",
+ "Stats_Total_Messages_Direct": "私信总数",
+ "Stats_Total_Messages_Livechat": "在线聊天消息总计",
+ "Stats_Total_Messages_PrivateGroup": "私有群组消息总计",
"Stats_Total_Private_Groups": "私有组数",
"Stats_Total_Rooms": "房间总数",
"Stats_Total_Users": "用户总数",
+ "Status": "状态",
"Stop_Recording": "停止录制",
"strike": "划线",
"Subject": "标题",
"Submit": "提交",
"Success": "成功",
"Success_message": "成功消息",
+ "Sunday": "星期日",
"Survey": "调查",
"Survey_instructions": "根据问题填写您的满意度,1 代表完全不满意,5 代表非常满意。",
"Symbols": "符号",
"Sync_success": "同步成功",
"Sync_Users": "同步用户",
+ "System_messages": "系统消息",
"Tag": "标签",
+ "TargetRoom": "目标房间",
+ "TargetRoom_Description": "事件被触发所产生的结果将被发送到哪个房间?仅允许设置一个目标房间,且该房间必须是存在的。",
"Test_Connection": "测试连接",
"Test_Desktop_Notifications": "测试桌面通知",
"Thank_you_exclamation_mark": "谢谢!",
@@ -1070,19 +1273,19 @@
"The_user_wont_be_able_to_type_in_s": "该用户将被禁止在 %s 房间中发言",
"Theme": "主题",
"theme-color-content-background-color": "内容的背景色",
+ "theme-color-custom-scrollbar-color": "定制滚动条颜色",
+ "theme-color-info-font-color": "信息字体颜色",
+ "theme-color-link-font-color": "链接字体颜色",
"theme-color-primary-background-color": "主背景颜色",
"theme-color-primary-font-color": "主要字体颜色",
"theme-color-secondary-background-color": "第二背景颜色",
"theme-color-secondary-font-color": "第二字体颜色",
- "theme-color-tertiary-background-color": "第三背景颜色",
- "theme-color-tertiary-font-color": "第三字体颜色",
- "theme-color-link-font-color": "链接字体颜色",
- "theme-color-info-font-color": "信息字体颜色",
- "theme-color-custom-scrollbar-color": "定制滚动条颜色",
"theme-color-status-away": "离开状态颜色",
"theme-color-status-busy": "忙碌状态颜色",
"theme-color-status-offline": "离线状态颜色",
"theme-color-status-online": "在线状态颜色",
+ "theme-color-tertiary-background-color": "第三背景颜色",
+ "theme-color-tertiary-font-color": "第三字体颜色",
"theme-color-unread-notification-color": "未读消息颜色",
"theme-custom-css": "自定义 CSS",
"There_are_no_agents_added_to_this_department_yet": "该部门尚未分配任何客服。",
@@ -1094,6 +1297,7 @@
"This_is_a_push_test_messsage": "这是一条测试信息",
"This_room_has_been_archived_by__username_": "这个房间已被 __username__ 归档",
"This_room_has_been_unarchived_by__username_": "这个房间已被 __username__ 取消归档",
+ "Thursday": "星期四",
"Time_in_seconds": "时间(秒)",
"Title": "标题",
"Title_bar_color": "标题栏颜色",
@@ -1102,6 +1306,7 @@
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "要在您的网站中安装 Rocket.Chat 在线聊天,请将以下代码复制粘贴到您的网页代码中最后一个 </body> 标签之上。",
"to_see_more_details_on_how_to_integrate": "以便查看更多关于集成的细节。",
"To_users": "给用户",
+ "Toggle_original_translated": "切换地区/语言",
"Topic": "话题",
"Travel_and_Places": "旅游与地方",
"Trigger_removed": "触发器已删除",
@@ -1120,14 +1325,17 @@
"Unmute_user": "取消禁言",
"Unnamed": "未命名",
"Unpin_Message": "取消固定",
- "Unread_Alert": "未读警报",
+ "Unread_Messages": "未读消息",
"Unread_Rooms": "未读房间",
"Unread_Rooms_Mode": "未读房间模式",
"Unstar_Message": "取消标记",
+ "Upload_file_description": "文件描述",
+ "Upload_file_name": "文件名",
"Upload_file_question": "上传文件?",
"Uploading_file": "文件上传中……",
"Uptime": "运行时间",
"URL": "网址",
+ "URL_room_prefix": "房间 URL 前缀",
"Use_account_preference": "使用账户特性",
"Use_Emojis": "使用表情",
"Use_Global_Settings": "使用全局设置",
@@ -1151,6 +1359,7 @@
"User_has_been_muted_in_s": "该用户已在 %s 中被禁言",
"User_has_been_removed_from_s": "该用户已从 %s 中被删除",
"User_Info": "用户信息",
+ "User_Interface": "用户界面",
"User_is_no_longer_an_admin": "用户已不再是管理员",
"User_is_now_an_admin": "用户已成为管理员",
"User_joined_channel": "加入了频道。",
@@ -1189,10 +1398,16 @@
"UTF8_Names_Slugify": "着重显示 UTF-8 名字",
"UTF8_Names_Validation": "UTF-8 名称验证",
"UTF8_Names_Validation_Description": "禁止特殊字符和空格。你可以在名字末尾以为的地方使用 -、_ 和 . 。",
+ "Validate_email_address": "验证邮箱",
+ "Verification": "验证",
+ "Verification_Email": "点击这里 验证你的账户。",
"Verification_email_sent": "确认邮件已发送",
+ "Verification_Email_Subject": "[Site_Name] - 验证你的账户",
"Verified": "已验证",
+ "Verify": "验证",
"Version": "版本",
"Video_Chat_Window": "视频聊天",
+ "Video_Conference": "视频会议",
"View_All": "查看全部",
"View_Logs": "查看日志",
"View_mode": "查看模式",
@@ -1206,6 +1421,7 @@
"Visitor_page_URL": "访客页面地址",
"Visitor_time_on_site": "访客网站停留时间",
"Wait_activation_warning": "您的帐户必须由管理员手工启动后才能登录。",
+ "Warnings": "警告",
"We_are_offline_Sorry_for_the_inconvenience": "现在没有人在线,带来不便请您谅解。",
"We_have_sent_password_email": "我们已经向您发送密码重置的电子邮件。如果您没有收到邮件,请重试。",
"We_have_sent_registration_email": "我们已经向您发出一封电子邮件,以确认您的注册。如果您没有收到邮件,请重试。",
@@ -1216,6 +1432,7 @@
"WebRTC_Enable_Private": "启用私有频道",
"WebRTC_Servers": "STUN/TURN 服务器 ",
"WebRTC_Servers_Description": "用逗号分隔STUN和TURN服务器的列表。 用户名,密码和端口被允许在格式`用户名:密码@眩晕:主持人:port`或'用户名:密码@转:主持人:port`。",
+ "Wednesday": "星期三",
"Welcome": "欢迎 %s ",
"Welcome_to_the": "欢迎来到",
"Why_do_you_want_to_report_question_mark": "你为什么要举报?",
@@ -1239,6 +1456,7 @@
"You_have_been_muted": "你已被禁止发言,因此不能在房间内说话",
"You_have_not_verified_your_email": "您尚未验证您的电子邮箱地址。",
"You_have_successfully_unsubscribed": "您已成功从我们的邮件列表中取消订阅。",
+ "You_must_join_to_view_messages_in_this_channel": "你必须先加入此频道才能查看消息",
"You_need_confirm_email": "登录前请验证您的电子邮件!",
"You_need_install_an_extension_to_allow_screen_sharing": "你需要安装扩展程序才能支持屏幕共享",
"You_need_to_change_your_password": "你需要修改密码",
@@ -1255,6 +1473,8 @@
"Your_entry_has_been_deleted": "您的项目已被删除。",
"Your_file_has_been_deleted": "您的文件已被删除。",
"Your_mail_was_sent_to_s": "您的邮件已发送至 %s",
+ "your_message": "你的消息",
+ "your_message_optional": "你的消息(可选)",
"Your_password_is_wrong": "密码错误!",
"Your_push_was_sent_to_s_devices": "您的推送已被送到 %s 台设备"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-i18n/package.js b/packages/rocketchat-i18n/package.js
index de361dc910462..2c535df63c53b 100644
--- a/packages/rocketchat-i18n/package.js
+++ b/packages/rocketchat-i18n/package.js
@@ -8,13 +8,13 @@ Package.describe({
Package.onUse(function(api) {
api.use('templating', 'client');
- var fs = Npm.require('fs');
- var workingDir = process.env.PWD || '.';
- fs.readdirSync(workingDir + '/packages/rocketchat-i18n/i18n').forEach(function(filename) {
- if (filename.indexOf('.json') > -1 && fs.statSync(workingDir + '/packages/rocketchat-i18n/i18n/' + filename).size > 16) {
- api.addFiles('i18n/' + filename);
+ const fs = Npm.require('fs');
+ const workingDir = process.env.PWD || '.';
+ fs.readdirSync(`${ workingDir }/packages/rocketchat-i18n/i18n`).forEach(function(filename) {
+ if (filename.indexOf('.json') > -1 && fs.statSync(`${ workingDir }/packages/rocketchat-i18n/i18n/${ filename }`).size > 16) {
+ api.addFiles(`i18n/${ filename }`);
}
});
api.use('tap:i18n@1.8.2');
-});
\ No newline at end of file
+});
diff --git a/packages/rocketchat-iframe-login/iframe_client.js b/packages/rocketchat-iframe-login/iframe_client.js
index 76c845ca92be3..dcfa7d5d6bbf5 100644
--- a/packages/rocketchat-iframe-login/iframe_client.js
+++ b/packages/rocketchat-iframe-login/iframe_client.js
@@ -1,5 +1,7 @@
/* globals Accounts, Tracker, ReactiveVar, FlowRouter, Accounts, HTTP, facebookConnectPlugin, TwitterConnect, OAuth */
+import _ from 'underscore';
+
const _unstoreLoginToken = Accounts._unstoreLoginToken;
Accounts._unstoreLoginToken = function() {
RocketChat.iframeLogin.tryLogin();
@@ -59,14 +61,14 @@ class IframeLogin {
}
if (window.cordova) {
- iframeUrl += separator + 'client=cordova';
+ iframeUrl += `${ separator }client=cordova`;
} else if (navigator.userAgent.indexOf('Electron') > -1) {
- iframeUrl += separator + 'client=electron';
+ iframeUrl += `${ separator }client=electron`;
}
HTTP.call(this.apiMethod, this.apiUrl, options, (error, result) => {
console.log(error, result);
- if (result && result.data && result.data.token) {
+ if (result && result.data && (result.data.token || result.data.loginToken)) {
this.loginWithToken(result.data, (error, result) => {
if (error) {
this.reactiveIframeUrl.set(iframeUrl);
@@ -82,27 +84,27 @@ class IframeLogin {
});
}
- loginWithToken(token, callback) {
+ loginWithToken(tokenData, callback) {
if (!this.enabled) {
return;
}
- if (Match.test(token, String)) {
- token = {
- token: token
+ if (Match.test(tokenData, String)) {
+ tokenData = {
+ token: tokenData
};
}
console.log('loginWithToken');
- if (token.loginToken) {
- return Meteor.loginWithToken(token.loginToken, callback);
+ if (tokenData.loginToken) {
+ return Meteor.loginWithToken(tokenData.loginToken, callback);
}
Accounts.callLoginMethod({
methodArguments: [{
iframe: true,
- token: token.token
+ token: tokenData.token
}],
userCallback: callback
});
@@ -166,7 +168,7 @@ window.addEventListener('message', (e) => {
console.log('facebook-login-success', response);
e.source.postMessage({
event: 'facebook-login-success',
- response: response
+ response
// authResponse: Object
// accessToken: "a7s6d8a76s8d7..."
// expiresIn: "5172793"
@@ -182,8 +184,8 @@ window.addEventListener('message', (e) => {
console.log('facebook-login-error', error, response);
e.source.postMessage({
event: 'facebook-login-error',
- error: error,
- response: response
+ error,
+ response
}, e.origin);
};
@@ -196,7 +198,7 @@ window.addEventListener('message', (e) => {
authResponse: {
accessToken: serviceData.accessToken,
expiresIn: serviceData.expiresAt,
- secret: secret
+ secret
},
userID: serviceData.id
});
@@ -223,7 +225,7 @@ window.addEventListener('message', (e) => {
console.log('twitter-login-success', response);
e.source.postMessage({
event: 'twitter-login-success',
- response: response
+ response
// {
// "userName": "orodrigok",
// "userId": 293123,
@@ -237,7 +239,7 @@ window.addEventListener('message', (e) => {
console.log('twitter-login-error', error);
e.source.postMessage({
event: 'twitter-login-error',
- error: error
+ error
}, e.origin);
};
@@ -269,7 +271,7 @@ window.addEventListener('message', (e) => {
console.log('google-login-success', response);
e.source.postMessage({
event: 'google-login-success',
- response: response
+ response
// {
// "email": "rodrigoknascimento@gmail.com",
// "userId": "1082039180239",
@@ -288,7 +290,7 @@ window.addEventListener('message', (e) => {
console.log('google-login-error', error);
e.source.postMessage({
event: 'google-login-error',
- error: error
+ error
}, e.origin);
};
diff --git a/packages/rocketchat-iframe-login/iframe_server.js b/packages/rocketchat-iframe-login/iframe_server.js
index ea4d7d968d91c..6809698bb19d3 100644
--- a/packages/rocketchat-iframe-login/iframe_server.js
+++ b/packages/rocketchat-iframe-login/iframe_server.js
@@ -7,7 +7,7 @@ Accounts.registerLoginHandler('iframe', function(result) {
console.log('[Method] registerLoginHandler');
- var user = Meteor.users.findOne({
+ const user = Meteor.users.findOne({
'services.iframe.token': result.token
});
diff --git a/packages/rocketchat-iframe-login/package.js b/packages/rocketchat-iframe-login/package.js
index 79360dd02118c..49e071079c648 100644
--- a/packages/rocketchat-iframe-login/package.js
+++ b/packages/rocketchat-iframe-login/package.js
@@ -13,16 +13,15 @@ Package.onUse(function(api) {
api.use('rocketchat:lib');
api.use('accounts-base');
- api.use('underscore');
api.use('ecmascript');
api.use('reactive-var');
api.use('http');
api.use('tracker');
api.use('check');
- api.imply('facebook');
- api.imply('twitter');
- api.imply('google');
+ api.imply('facebook-oauth');
+ api.imply('twitter-oauth');
+ api.imply('google-oauth');
api.imply('oauth');
// Server files
diff --git a/packages/rocketchat-importer-csv/.npm/package/.gitignore b/packages/rocketchat-importer-csv/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-importer-csv/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-importer-csv/.npm/package/README b/packages/rocketchat-importer-csv/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-importer-csv/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-importer-csv/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-importer-csv/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 7a0f451ebb1c8..0000000000000
--- a/packages/rocketchat-importer-csv/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "dependencies": {
- "csv-parse": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.1.7.tgz",
- "from": "csv-parse@1.1.7"
- }
- }
-}
diff --git a/packages/rocketchat-importer-csv/client/adder.js b/packages/rocketchat-importer-csv/client/adder.js
new file mode 100644
index 0000000000000..b2da9a396eceb
--- /dev/null
+++ b/packages/rocketchat-importer-csv/client/adder.js
@@ -0,0 +1,4 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { CsvImporterInfo } from '../info';
+
+Importers.add(new CsvImporterInfo());
diff --git a/packages/rocketchat-importer-csv/info.js b/packages/rocketchat-importer-csv/info.js
new file mode 100644
index 0000000000000..d3894b5f6cb2d
--- /dev/null
+++ b/packages/rocketchat-importer-csv/info.js
@@ -0,0 +1,10 @@
+import { ImporterInfo } from 'meteor/rocketchat:importer';
+
+export class CsvImporterInfo extends ImporterInfo {
+ constructor() {
+ super('csv', 'CSV', 'application/zip', [{
+ text: 'Importer_CSV_Information',
+ href: 'https://rocket.chat/docs/administrator-guides/import/csv/'
+ }]);
+ }
+}
diff --git a/packages/rocketchat-importer-csv/main.js b/packages/rocketchat-importer-csv/main.js
deleted file mode 100644
index cea869b960b37..0000000000000
--- a/packages/rocketchat-importer-csv/main.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* globals Importer */
-
-Importer.addImporter('csv', Importer.CSV, {
- name: 'CSV',
- warnings: [{
- text: 'Importer_CSV_Information',
- href: 'https://rocket.chat/docs/administrator-guides/import/csv/'
- }],
- mimeType: 'application/zip'
-});
diff --git a/packages/rocketchat-importer-csv/package.js b/packages/rocketchat-importer-csv/package.js
index 33976fbeb1008..090ad8cacde28 100644
--- a/packages/rocketchat-importer-csv/package.js
+++ b/packages/rocketchat-importer-csv/package.js
@@ -11,11 +11,15 @@ Package.onUse(function(api) {
'rocketchat:lib',
'rocketchat:importer'
]);
+
api.use('rocketchat:logger', 'server');
- api.addFiles('server.js', 'server');
- api.addFiles('main.js', ['client', 'server']);
-});
-Npm.depends({
- 'csv-parse': '1.1.7'
+ // Importer information to both server and client
+ api.addFiles('info.js');
+
+ // Server files
+ api.addFiles(['server/importer.js', 'server/adder.js'], 'server');
+
+ // Client files
+ api.addFiles('client/adder.js', 'client');
});
diff --git a/packages/rocketchat-importer-csv/server.js b/packages/rocketchat-importer-csv/server.js
deleted file mode 100644
index 98eec8ea44e1c..0000000000000
--- a/packages/rocketchat-importer-csv/server.js
+++ /dev/null
@@ -1,307 +0,0 @@
-/* globals Importer */
-
-Importer.CSV = class ImporterCSV extends Importer.Base {
- constructor(name, descriptionI18N, mimeType) {
- super(name, descriptionI18N, mimeType);
- this.logger.debug('Constructed a new CSV Importer.');
-
- this.csvParser = Npm.require('csv-parse/lib/sync');
- this.messages = new Map();
- }
-
- prepare(dataURI, sentContentType, fileName) {
- super.prepare(dataURI, sentContentType, fileName);
-
- const uriResult = RocketChatFile.dataURIParse(dataURI);
- const zip = new this.AdmZip(new Buffer(uriResult.image, 'base64'));
- const zipEntries = zip.getEntries();
-
- let tempChannels = [];
- let tempUsers = [];
- const tempMessages = new Map();
- for (let entry of zipEntries) {
- this.logger.debug(`Entry: ${entry.entryName}`);
-
- //Ignore anything that has `__MACOSX` in it's name, as sadly these things seem to mess everything up
- if (entry.entryName.indexOf('__MACOSX') > -1) {
- this.logger.debug(`Ignoring the file: ${entry.entryName}`);
- continue;
- }
-
- //Directories are ignored, since they are "virtual" in a zip file
- if (entry.isDirectory) {
- this.logger.debug(`Ignoring the directory entry: ${entry.entryName}`);
- continue;
- }
-
- //Parse the channels
- if (entry.entryName.toLowerCase() === 'channels.csv') {
- super.updateProgress(Importer.ProgressStep.PREPARING_CHANNELS);
- const parsedChannels = this.csvParser(entry.getData().toString());
- tempChannels = parsedChannels.map((c) => {
- return {
- id: c[0].trim().replace('.', '_'),
- name: c[0].trim(),
- creator: c[1].trim(),
- isPrivate: c[2].trim().toLowerCase() === 'private' ? true : false,
- members: c[3].trim().split(';').map((m) => m.trim())
- };
- });
- continue;
- }
-
- //Parse the users
- if (entry.entryName.toLowerCase() === 'users.csv') {
- super.updateProgress(Importer.ProgressStep.PREPARING_USERS);
- const parsedUsers = this.csvParser(entry.getData().toString());
- tempUsers = parsedUsers.map((u) => { return { id: u[0].trim().replace('.', '_'), username: u[0].trim(), email: u[1].trim(), name: u[2].trim() }; });
- continue;
- }
-
- //Parse the messages
- if (entry.entryName.indexOf('/') > -1) {
- const item = entry.entryName.split('/'); //random/messages.csv
- const channelName = item[0]; //random
- const msgGroupData = item[1].split('.')[0]; //2015-10-04
-
- if (!tempMessages.get(channelName)) {
- tempMessages.set(channelName, new Map());
- }
-
- let msgs = [];
-
- try {
- msgs = this.csvParser(entry.getData().toString());
- } catch (e) {
- this.logger.warn(`The file ${entry.entryName} contains invalid syntax`, e);
- continue;
- }
-
- tempMessages.get(channelName).set(msgGroupData, msgs.map((m) => { return { username: m[0], ts: m[1], text: m[2] }; }));
- continue;
- }
- }
-
- // Insert the users record, eventually this might have to be split into several ones as well
- // if someone tries to import a several thousands users instance
- const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
- this.users = this.collection.findOne(usersId);
- super.updateRecord({ 'count.users': tempUsers.length });
- super.addCountToTotal(tempUsers.length);
-
- // Insert the channels records.
- const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempChannels });
- this.channels = this.collection.findOne(channelsId);
- super.updateRecord({ 'count.channels': tempChannels.length });
- super.addCountToTotal(tempChannels.length);
-
- // Save the messages records to the import record for `startImport` usage
- super.updateProgress(Importer.ProgressStep.PREPARING_MESSAGES);
- let messagesCount = 0;
- for (let [channel, messagesMap] of tempMessages.entries()) {
- if (!this.messages.get(channel)) {
- this.messages.set(channel, new Map());
- }
-
- for (let [msgGroupData, msgs] of messagesMap.entries()) {
- messagesCount += msgs.length;
- super.updateRecord({ 'messagesstatus': `${channel}/${msgGroupData}` });
-
- if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
- Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}/${msgGroupData}.${i}`, 'messages': splitMsg });
- this.messages.get(channel).set(`${msgGroupData}.${i}`, this.collection.findOne(messagesId));
- });
- } else {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}/${msgGroupData}`, 'messages': msgs });
- this.messages.get(channel).set(msgGroupData, this.collection.findOne(messagesId));
- }
- }
- }
-
- super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
- super.addCountToTotal(messagesCount);
-
- //Ensure we have some users, channels, and messages
- if (tempUsers.length === 0 || tempChannels.length === 0 || messagesCount === 0) {
- this.logger.warn(`The loaded users count ${tempUsers.length}, the loaded channels ${tempChannels.length}, and the loaded messages ${messagesCount}`);
- super.updateProgress(Importer.ProgressStep.ERROR);
- return super.getProgress();
- }
-
- const selectionUsers = tempUsers.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, false, false, true));
- const selectionChannels = tempChannels.map((c) => new Importer.SelectionChannel(c.id, c.name, false, true, c.isPrivate));
-
- super.updateProgress(Importer.ProgressStep.USER_SELECTION);
- return new Importer.Selection(this.name, selectionUsers, selectionChannels);
- }
-
- startImport(importSelection) {
- super.startImport(importSelection);
- const started = Date.now();
-
- //Ensure we're only going to import the users that the user has selected
- for (let user of importSelection.users) {
- for (let u of this.users.users) {
- if (u.id === user.user_id) {
- u.do_import = user.do_import;
- }
- }
- }
- this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
-
- //Ensure we're only importing the channels the user has selected.
- for (let channel of importSelection.channels) {
- for (let c of this.channels.channels) {
- if (c.id === channel.channel_id) {
- c.do_import = channel.do_import;
- }
- }
- }
- this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
-
- const startedByUserId = Meteor.userId();
- Meteor.defer(() => {
- super.updateProgress(Importer.ProgressStep.IMPORTING_USERS);
- //Import the users
- for (let u of this.users.users) {
- if (!u.do_import) {
- continue;
- }
-
- Meteor.runAsUser(startedByUserId, () => {
- let existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email);
-
- //If we couldn't find one by their email address, try to find an existing user by their username
- if (!existantUser) {
- existantUser = RocketChat.models.Users.findOneByUsername(u.username);
- }
-
- if (existantUser) {
- //since we have an existing user, let's try a few things
- u.rocketId = existantUser._id;
- RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
- } else {
- const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
- Meteor.runAsUser(userId, () => {
- Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
- RocketChat.models.Users.setName(userId, u.name);
- RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
- u.rocketId = userId;
- });
- }
-
- super.addCountCompleted(1);
- });
- }
- this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
-
- //Import the channels
- super.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS);
- for (let c of this.channels.channels) {
- if (!c.do_import) {
- continue;
- }
-
- Meteor.runAsUser(startedByUserId, () => {
- let existantRoom = RocketChat.models.Rooms.findOneByName(c.name);
- //If the room exists or the name of it is 'general', then we don't need to create it again
- if (existantRoom || c.name.toUpperCase() === 'GENERAL') {
- c.rocketId = c.name.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id;
- RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
- } else {
- //Find the rocketchatId of the user who created this channel
- let creatorId = startedByUserId;
- for (let u of this.users.users) {
- if (u.username === c.creator && u.do_import) {
- creatorId = u.rocketId;
- }
- }
-
- //Create the channel
- Meteor.runAsUser(creatorId, () => {
- const roomInfo = Meteor.call(c.isPrivate ? 'createPrivateGroup' : 'createChannel', c.name, c.members);
- c.rocketId = roomInfo.rid;
- });
-
- RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
- }
-
- super.addCountCompleted(1);
- });
- }
- this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
-
- //Import the Messages
- super.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES);
- for (let [ch, messagesMap] of this.messages.entries()) {
- const csvChannel = this.getChannelFromName(ch);
- if (!csvChannel.do_import) {
- continue;
- }
-
- const room = RocketChat.models.Rooms.findOneById(csvChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
- Meteor.runAsUser(startedByUserId, () => {
- for (let [msgGroupData, msgs] of messagesMap.entries()) {
- super.updateRecord({ 'messagesstatus': `${ch}/${msgGroupData}.${msgs.messages.length}` });
- for (let msg of msgs.messages) {
- if (isNaN(new Date(parseInt(msg.ts)))) {
- this.logger.warn(`Timestamp on a message in ${ch}/${msgGroupData} is invalid`);
- super.addCountCompleted(1);
- continue;
- }
-
- const creator = this.getUserFromUsername(msg.username);
- if (creator) {
- const msgObj = {
- _id: `csv-${csvChannel.id}-${msg.ts}`,
- ts: new Date(parseInt(msg.ts)),
- msg: msg.text,
- rid: room._id,
- u: {
- _id: creator._id,
- username: creator.username
- }
- };
-
- RocketChat.sendMessage(creator, msgObj, room, true);
- }
-
- super.addCountCompleted(1);
- }
- }
- });
- }
-
- super.updateProgress(Importer.ProgressStep.FINISHING);
- super.updateProgress(Importer.ProgressStep.DONE);
- const timeTook = Date.now() - started;
- this.logger.log(`CSV Import took ${timeTook} milliseconds.`);
- });
-
- return super.getProgress();
- }
-
- getSelection() {
- const selectionUsers = this.users.users.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, false, false, true));
- const selectionChannels = this.channels.channels.map((c) => new Importer.SelectionChannel(c.id, c.name, false, true, c.isPrivate));
-
- return new Importer.Selection(this.name, selectionUsers, selectionChannels);
- }
-
- getChannelFromName(channelName) {
- for (let ch of this.channels.channels) {
- if (ch.name === channelName) {
- return ch;
- }
- }
- }
-
- getUserFromUsername(username) {
- for (let u of this.users.users) {
- if (u.username === username) {
- return RocketChat.models.Users.findOneById(u.rocketId, { fields: { username: 1 }});
- }
- }
- }
-};
diff --git a/packages/rocketchat-importer-csv/server/adder.js b/packages/rocketchat-importer-csv/server/adder.js
new file mode 100644
index 0000000000000..41edb79f5f938
--- /dev/null
+++ b/packages/rocketchat-importer-csv/server/adder.js
@@ -0,0 +1,5 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { CsvImporterInfo } from '../info';
+import { CsvImporter } from './importer';
+
+Importers.add(new CsvImporterInfo(), CsvImporter);
diff --git a/packages/rocketchat-importer-csv/server/importer.js b/packages/rocketchat-importer-csv/server/importer.js
new file mode 100644
index 0000000000000..86a904436ff0b
--- /dev/null
+++ b/packages/rocketchat-importer-csv/server/importer.js
@@ -0,0 +1,371 @@
+import {
+ Base,
+ ProgressStep,
+ Selection,
+ SelectionChannel,
+ SelectionUser
+} from 'meteor/rocketchat:importer';
+
+export class CsvImporter extends Base {
+ constructor(info) {
+ super(info);
+
+ this.csvParser = require('csv-parse/lib/sync');
+ this.messages = new Map();
+ }
+
+ prepare(dataURI, sentContentType, fileName) {
+ super.prepare(dataURI, sentContentType, fileName);
+
+ const uriResult = RocketChatFile.dataURIParse(dataURI);
+ const zip = new this.AdmZip(new Buffer(uriResult.image, 'base64'));
+ const zipEntries = zip.getEntries();
+
+ let tempChannels = [];
+ let tempUsers = [];
+ const tempMessages = new Map();
+ for (const entry of zipEntries) {
+ this.logger.debug(`Entry: ${ entry.entryName }`);
+
+ //Ignore anything that has `__MACOSX` in it's name, as sadly these things seem to mess everything up
+ if (entry.entryName.indexOf('__MACOSX') > -1) {
+ this.logger.debug(`Ignoring the file: ${ entry.entryName }`);
+ continue;
+ }
+
+ //Directories are ignored, since they are "virtual" in a zip file
+ if (entry.isDirectory) {
+ this.logger.debug(`Ignoring the directory entry: ${ entry.entryName }`);
+ continue;
+ }
+
+ //Parse the channels
+ if (entry.entryName.toLowerCase() === 'channels.csv') {
+ super.updateProgress(ProgressStep.PREPARING_CHANNELS);
+ const parsedChannels = this.csvParser(entry.getData().toString());
+ tempChannels = parsedChannels.map((c) => {
+ return {
+ id: c[0].trim().replace('.', '_'),
+ name: c[0].trim(),
+ creator: c[1].trim(),
+ isPrivate: c[2].trim().toLowerCase() === 'private' ? true : false,
+ members: c[3].trim().split(';').map((m) => m.trim())
+ };
+ });
+ continue;
+ }
+
+ //Parse the users
+ if (entry.entryName.toLowerCase() === 'users.csv') {
+ super.updateProgress(ProgressStep.PREPARING_USERS);
+ const parsedUsers = this.csvParser(entry.getData().toString());
+ tempUsers = parsedUsers.map((u) => { return { id: u[0].trim().replace('.', '_'), username: u[0].trim(), email: u[1].trim(), name: u[2].trim() }; });
+ continue;
+ }
+
+ //Parse the messages
+ if (entry.entryName.indexOf('/') > -1) {
+ const item = entry.entryName.split('/'); //random/messages.csv
+ const channelName = item[0]; //random
+ const msgGroupData = item[1].split('.')[0]; //2015-10-04
+
+ if (!tempMessages.get(channelName)) {
+ tempMessages.set(channelName, new Map());
+ }
+
+ let msgs = [];
+
+ try {
+ msgs = this.csvParser(entry.getData().toString());
+ } catch (e) {
+ this.logger.warn(`The file ${ entry.entryName } contains invalid syntax`, e);
+ continue;
+ }
+
+ tempMessages.get(channelName).set(msgGroupData, msgs.map((m) => { return { username: m[0], ts: m[1], text: m[2] }; }));
+ continue;
+ }
+ }
+
+ // Insert the users record, eventually this might have to be split into several ones as well
+ // if someone tries to import a several thousands users instance
+ const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
+ this.users = this.collection.findOne(usersId);
+ super.updateRecord({ 'count.users': tempUsers.length });
+ super.addCountToTotal(tempUsers.length);
+
+ // Insert the channels records.
+ const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempChannels });
+ this.channels = this.collection.findOne(channelsId);
+ super.updateRecord({ 'count.channels': tempChannels.length });
+ super.addCountToTotal(tempChannels.length);
+
+ // Save the messages records to the import record for `startImport` usage
+ super.updateProgress(ProgressStep.PREPARING_MESSAGES);
+ let messagesCount = 0;
+ for (const [channel, messagesMap] of tempMessages.entries()) {
+ if (!this.messages.get(channel)) {
+ this.messages.set(channel, new Map());
+ }
+
+ for (const [msgGroupData, msgs] of messagesMap.entries()) {
+ messagesCount += msgs.length;
+ super.updateRecord({ 'messagesstatus': `${ channel }/${ msgGroupData }` });
+
+ if (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) {
+ Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }/${ msgGroupData }.${ i }`, 'messages': splitMsg });
+ this.messages.get(channel).set(`${ msgGroupData }.${ i }`, this.collection.findOne(messagesId));
+ });
+ } else {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }/${ msgGroupData }`, 'messages': msgs });
+ this.messages.get(channel).set(msgGroupData, this.collection.findOne(messagesId));
+ }
+ }
+ }
+
+ super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
+ super.addCountToTotal(messagesCount);
+
+ //Ensure we have at least a single user, channel, or message
+ if (tempUsers.length === 0 && tempChannels.length === 0 && messagesCount === 0) {
+ this.logger.error('No users, channels, or messages found in the import file.');
+ super.updateProgress(ProgressStep.ERROR);
+ return super.getProgress();
+ }
+
+ const selectionUsers = tempUsers.map((u) => new SelectionUser(u.id, u.username, u.email, false, false, true));
+ const selectionChannels = tempChannels.map((c) => new SelectionChannel(c.id, c.name, false, true, c.isPrivate));
+ const selectionMessages = this.importRecord.count.messages;
+
+ super.updateProgress(ProgressStep.USER_SELECTION);
+ return new Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
+ }
+
+ startImport(importSelection) {
+ super.startImport(importSelection);
+ const started = Date.now();
+
+ //Ensure we're only going to import the users that the user has selected
+ for (const user of importSelection.users) {
+ for (const u of this.users.users) {
+ if (u.id === user.user_id) {
+ u.do_import = user.do_import;
+ }
+ }
+ }
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ //Ensure we're only importing the channels the user has selected.
+ for (const channel of importSelection.channels) {
+ for (const c of this.channels.channels) {
+ if (c.id === channel.channel_id) {
+ c.do_import = channel.do_import;
+ }
+ }
+ }
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ const startedByUserId = Meteor.userId();
+ Meteor.defer(() => {
+ super.updateProgress(ProgressStep.IMPORTING_USERS);
+
+ try {
+ //Import the users
+ for (const u of this.users.users) {
+ if (!u.do_import) {
+ continue;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ let existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email);
+
+ //If we couldn't find one by their email address, try to find an existing user by their username
+ if (!existantUser) {
+ existantUser = RocketChat.models.Users.findOneByUsername(u.username);
+ }
+
+ if (existantUser) {
+ //since we have an existing user, let's try a few things
+ u.rocketId = existantUser._id;
+ RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
+ } else {
+ const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
+ RocketChat.models.Users.setName(userId, u.name);
+ RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
+ u.rocketId = userId;
+ });
+ }
+
+ super.addCountCompleted(1);
+ });
+ }
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ //Import the channels
+ super.updateProgress(ProgressStep.IMPORTING_CHANNELS);
+ for (const c of this.channels.channels) {
+ if (!c.do_import) {
+ continue;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantRoom = RocketChat.models.Rooms.findOneByName(c.name);
+ //If the room exists or the name of it is 'general', then we don't need to create it again
+ if (existantRoom || c.name.toUpperCase() === 'GENERAL') {
+ c.rocketId = c.name.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id;
+ RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
+ } else {
+ //Find the rocketchatId of the user who created this channel
+ let creatorId = startedByUserId;
+ for (const u of this.users.users) {
+ if (u.username === c.creator && u.do_import) {
+ creatorId = u.rocketId;
+ }
+ }
+
+ //Create the channel
+ Meteor.runAsUser(creatorId, () => {
+ const roomInfo = Meteor.call(c.isPrivate ? 'createPrivateGroup' : 'createChannel', c.name, c.members);
+ c.rocketId = roomInfo.rid;
+ });
+
+ RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
+ }
+
+ super.addCountCompleted(1);
+ });
+ }
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ //If no channels file, collect channel map from DB for message-only import
+ if (this.channels.channels.length === 0) {
+ for (const cname of this.messages.keys()) {
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantRoom = RocketChat.models.Rooms.findOneByName(cname);
+ if (existantRoom || cname.toUpperCase() === 'GENERAL') {
+ this.channels.channels.push({
+ id: cname.replace('.', '_'),
+ name: cname,
+ rocketId: (cname.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id),
+ do_import: true
+ });
+ }
+ });
+ }
+ }
+
+ //If no users file, collect user map from DB for message-only import
+ if (this.users.users.length === 0) {
+ for (const [ch, messagesMap] of this.messages.entries()) {
+ const csvChannel = this.getChannelFromName(ch);
+ if (!csvChannel || !csvChannel.do_import) {
+ continue;
+ }
+ Meteor.runAsUser(startedByUserId, () => {
+ for (const msgs of messagesMap.values()) {
+ for (const msg of msgs.messages) {
+ if (!this.getUserFromUsername(msg.username)) {
+ const user = RocketChat.models.Users.findOneByUsername(msg.username);
+ if (user) {
+ this.users.users.push({
+ rocketId: user._id,
+ username: user.username
+ });
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+
+ //Import the Messages
+ super.updateProgress(ProgressStep.IMPORTING_MESSAGES);
+ for (const [ch, messagesMap] of this.messages.entries()) {
+ const csvChannel = this.getChannelFromName(ch);
+ if (!csvChannel || !csvChannel.do_import) {
+ continue;
+ }
+
+ const room = RocketChat.models.Rooms.findOneById(csvChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
+ Meteor.runAsUser(startedByUserId, () => {
+ const timestamps = {};
+ for (const [msgGroupData, msgs] of messagesMap.entries()) {
+ super.updateRecord({ 'messagesstatus': `${ ch }/${ msgGroupData }.${ msgs.messages.length }` });
+ for (const msg of msgs.messages) {
+ if (isNaN(new Date(parseInt(msg.ts)))) {
+ this.logger.warn(`Timestamp on a message in ${ ch }/${ msgGroupData } is invalid`);
+ super.addCountCompleted(1);
+ continue;
+ }
+
+ const creator = this.getUserFromUsername(msg.username);
+ if (creator) {
+ let suffix = '';
+ if (timestamps[msg.ts] === undefined) {
+ timestamps[msg.ts] = 1;
+ } else {
+ suffix = `-${ timestamps[msg.ts] }`;
+ timestamps[msg.ts] += 1;
+ }
+ const msgObj = {
+ _id: `csv-${ csvChannel.id }-${ msg.ts }${ suffix }`,
+ ts: new Date(parseInt(msg.ts)),
+ msg: msg.text,
+ rid: room._id,
+ u: {
+ _id: creator._id,
+ username: creator.username
+ }
+ };
+
+ RocketChat.sendMessage(creator, msgObj, room, true);
+ }
+
+ super.addCountCompleted(1);
+ }
+ }
+ });
+ }
+
+ super.updateProgress(ProgressStep.FINISHING);
+ super.updateProgress(ProgressStep.DONE);
+ } catch (e) {
+ this.logger.error(e);
+ super.updateProgress(ProgressStep.ERROR);
+ }
+
+ const timeTook = Date.now() - started;
+ this.logger.log(`CSV Import took ${ timeTook } milliseconds.`);
+ });
+
+ return super.getProgress();
+ }
+
+ getSelection() {
+ const selectionUsers = this.users.users.map((u) => new SelectionUser(u.id, u.username, u.email, false, false, true));
+ const selectionChannels = this.channels.channels.map((c) => new SelectionChannel(c.id, c.name, false, true, c.isPrivate));
+ const selectionMessages = this.importRecord.count.messages;
+
+ return new Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
+ }
+
+ getChannelFromName(channelName) {
+ for (const ch of this.channels.channels) {
+ if (ch.name === channelName) {
+ return ch;
+ }
+ }
+ }
+
+ getUserFromUsername(username) {
+ for (const u of this.users.users) {
+ if (u.username === username) {
+ return RocketChat.models.Users.findOneById(u.rocketId, { fields: { username: 1 }});
+ }
+ }
+ }
+}
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index c064b4aa3200b..0000000000000
--- a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "dependencies": {
- "bl": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
- "from": "bl@>=1.0.0 <2.0.0",
- "dependencies": {
- "readable-stream": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
- "from": "readable-stream@>=2.0.5 <2.1.0"
- }
- }
- },
- "buffer-shims": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
- "from": "buffer-shims@>=1.0.0 <2.0.0"
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "from": "core-util-is@>=1.0.0 <1.1.0"
- },
- "end-of-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz",
- "from": "end-of-stream@>=1.0.0 <2.0.0"
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "from": "inherits@>=2.0.1 <2.1.0"
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "from": "isarray@>=1.0.0 <1.1.0"
- },
- "once": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
- "from": "once@>=1.3.0 <1.4.0"
- },
- "process-nextick-args": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
- "from": "process-nextick-args@>=1.0.6 <1.1.0"
- },
- "readable-stream": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz",
- "from": "readable-stream@>=2.0.0 <3.0.0"
- },
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "from": "string_decoder@>=0.10.0 <0.11.0"
- },
- "tar-stream": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz",
- "from": "tar-stream@1.5.2"
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "from": "util-deprecate@>=1.0.1 <1.1.0"
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "from": "wrappy@>=1.0.0 <2.0.0"
- },
- "xtend": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
- "from": "xtend@>=4.0.0 <5.0.0"
- }
- }
-}
diff --git a/packages/rocketchat-importer-hipchat-enterprise/client/adder.js b/packages/rocketchat-importer-hipchat-enterprise/client/adder.js
new file mode 100644
index 0000000000000..92bfe07d193c7
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/client/adder.js
@@ -0,0 +1,4 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { HipChatEnterpriseImporterInfo } from '../info';
+
+Importers.add(new HipChatEnterpriseImporterInfo());
diff --git a/packages/rocketchat-importer-hipchat-enterprise/info.js b/packages/rocketchat-importer-hipchat-enterprise/info.js
new file mode 100644
index 0000000000000..b24582b5a2bb1
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/info.js
@@ -0,0 +1,15 @@
+import { ImporterInfo } from 'meteor/rocketchat:importer';
+
+export class HipChatEnterpriseImporterInfo extends ImporterInfo {
+ constructor() {
+ super('hipchatenterprise', 'HipChat Enterprise', 'application/gzip', [
+ {
+ text: 'Importer_HipChatEnterprise_Information',
+ href: 'https://rocket.chat/docs/administrator-guides/import/hipchat/enterprise/'
+ }, {
+ text: 'Importer_HipChatEnterprise_BetaWarning',
+ href: 'https://github.com/RocketChat/Rocket.Chat/issues/new'
+ }
+ ]);
+ }
+}
diff --git a/packages/rocketchat-importer-hipchat-enterprise/main.js b/packages/rocketchat-importer-hipchat-enterprise/main.js
deleted file mode 100644
index 69dfcb1f778a1..0000000000000
--- a/packages/rocketchat-importer-hipchat-enterprise/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* globals Importer */
-
-Importer.addImporter('hipchatenterprise', Importer.HipChatEnterprise, {
- name: 'HipChat Enterprise',
- warnings: [
- {
- text: 'Importer_HipChatEnterprise_Information',
- href: 'https://rocket.chat/docs/administrator-guides/import/hipchat/enterprise/'
- }, {
- text: 'Importer_HipChatEnterprise_BetaWarning',
- href: 'https://github.com/RocketChat/Rocket.Chat/issues/new'
- }
- ],
- mimeType: 'application/gzip'
-});
diff --git a/packages/rocketchat-importer-hipchat-enterprise/package.js b/packages/rocketchat-importer-hipchat-enterprise/package.js
index 76844dae9fa62..0c36cce041e0d 100644
--- a/packages/rocketchat-importer-hipchat-enterprise/package.js
+++ b/packages/rocketchat-importer-hipchat-enterprise/package.js
@@ -13,10 +13,13 @@ Package.onUse(function(api) {
]);
api.use('rocketchat:logger', 'server');
- api.addFiles('server.js', 'server');
- api.addFiles('main.js', ['client', 'server']);
-});
-Npm.depends({
- 'tar-stream': '1.5.2'
+ // Importer information to both server and client
+ api.addFiles('info.js');
+
+ // Server files
+ api.addFiles(['server/importer.js', 'server/adder.js'], 'server');
+
+ // Client files
+ api.addFiles('client/adder.js', 'client');
});
diff --git a/packages/rocketchat-importer-hipchat-enterprise/server.js b/packages/rocketchat-importer-hipchat-enterprise/server.js
deleted file mode 100644
index 42e007012eb59..0000000000000
--- a/packages/rocketchat-importer-hipchat-enterprise/server.js
+++ /dev/null
@@ -1,461 +0,0 @@
-/* globals Importer */
-
-Importer.HipChatEnterprise = class ImporterHipChatEnterprise extends Importer.Base {
- constructor(name, descriptionI18N, mimeType) {
- super(name, descriptionI18N, mimeType);
- this.logger.debug('Constructed a new HipChat Enterprise Importer.');
-
- this.Readable = require('stream').Readable;
- this.zlib = require('zlib');
- this.tarStream = Npm.require('tar-stream');
- this.extract = this.tarStream.extract();
- this.path = require('path');
- this.messages = new Map();
- this.directMessages = new Map();
- }
-
- prepare(dataURI, sentContentType, fileName) {
- super.prepare(dataURI, sentContentType, fileName);
-
- const tempUsers = [];
- const tempRooms = [];
- const tempMessages = new Map();
- const tempDirectMessages = new Map();
- const promise = new Promise((resolve, reject) => {
- this.extract.on('entry', Meteor.bindEnvironment((header, stream, next) => {
- if (header.name.indexOf('.json') !== -1) {
- const info = this.path.parse(header.name);
-
- stream.on('data', Meteor.bindEnvironment((chunk) => {
- this.logger.debug(`Processing the file: ${header.name}`);
- const file = JSON.parse(chunk);
-
- if (info.base === 'users.json') {
- super.updateProgress(Importer.ProgressStep.PREPARING_USERS);
- for (let u of file) {
- tempUsers.push({
- id: u.User.id,
- email: u.User.email,
- name: u.User.name,
- username: u.User.mention_name,
- avatar: u.User.avatar.replace(/\n/g, ''),
- timezone: u.User.timezone,
- isDeleted: u.User.is_deleted
- });
- }
- } else if (info.base === 'rooms.json') {
- super.updateProgress(Importer.ProgressStep.PREPARING_CHANNELS);
- for (let r of file) {
- tempRooms.push({
- id: r.Room.id,
- creator: r.Room.owner,
- created: new Date(r.Room.created),
- name: r.Room.name.replace(/ /g, '_').toLowerCase(),
- isPrivate: r.Room.privacy === 'private',
- isArchived: r.Room.is_archived,
- topic: r.Room.topic
- });
- }
- } else if (info.base === 'history.json') {
- const dirSplit = info.dir.split('/'); //['.', 'users', '1']
- const roomIdentifier = `${dirSplit[1]}/${dirSplit[2]}`;
-
- if (dirSplit[1] === 'users') {
- const msgs = [];
- for (let m of file) {
- if (m.PrivateUserMessage) {
- msgs.push({
- type: 'user',
- id: `hipchatenterprise-${m.PrivateUserMessage.id}`,
- senderId: m.PrivateUserMessage.sender.id,
- receiverId: m.PrivateUserMessage.receiver.id,
- text: m.PrivateUserMessage.message.indexOf('/me ') === -1 ? m.PrivateUserMessage.message : `${m.PrivateUserMessage.message.replace(/\/me /, '_')}_`,
- ts: new Date(m.PrivateUserMessage.timestamp.split(' ')[0])
- });
- }
- }
- tempDirectMessages.set(roomIdentifier, msgs);
- } else if (dirSplit[1] === 'rooms') {
- const roomMsgs = [];
-
- for (let m of file) {
- if (m.UserMessage) {
- roomMsgs.push({
- type: 'user',
- id: `hipchatenterprise-${dirSplit[2]}-${m.UserMessage.id}`,
- userId: m.UserMessage.sender.id,
- text: m.UserMessage.message.indexOf('/me ') === -1 ? m.UserMessage.message : `${m.UserMessage.message.replace(/\/me /, '_')}_`,
- ts: new Date(m.UserMessage.timestamp.split(' ')[0])
- });
- } else if (m.TopicRoomMessage) {
- roomMsgs.push({
- type: 'topic',
- id: `hipchatenterprise-${dirSplit[2]}-${m.TopicRoomMessage.id}`,
- userId: m.TopicRoomMessage.sender.id,
- ts: new Date(m.TopicRoomMessage.timestamp.split(' ')[0]),
- text: m.TopicRoomMessage.message
- });
- } else {
- this.logger.warn('HipChat Enterprise importer isn\'t configured to handle this message:', m);
- }
- }
- tempMessages.set(roomIdentifier, roomMsgs);
- } else {
- this.logger.warn(`HipChat Enterprise importer isn't configured to handle "${dirSplit[1]}" files.`);
- }
- } else {
- //What are these files!?
- this.logger.warn(`HipChat Enterprise importer doesn't know what to do with the file "${header.name}" :o`, info);
- }
- }));
-
- stream.on('end', () => next());
- stream.on('error', () => next());
- } else {
- next();
- }
- }));
-
- this.extract.on('error', (err) => {
- this.logger.warn('extract error:', err);
- reject();
- });
-
- this.extract.on('finish', Meteor.bindEnvironment(() => {
- // Insert the users record, eventually this might have to be split into several ones as well
- // if someone tries to import a several thousands users instance
- const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
- this.users = this.collection.findOne(usersId);
- super.updateRecord({ 'count.users': tempUsers.length });
- super.addCountToTotal(tempUsers.length);
-
- // Insert the channels records.
- const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempRooms });
- this.channels = this.collection.findOne(channelsId);
- super.updateRecord({ 'count.channels': tempRooms.length });
- super.addCountToTotal(tempRooms.length);
-
- // Save the messages records to the import record for `startImport` usage
- super.updateProgress(Importer.ProgressStep.PREPARING_MESSAGES);
- let messagesCount = 0;
- for (let [channel, msgs] of tempMessages.entries()) {
- if (!this.messages.get(channel)) {
- this.messages.set(channel, new Map());
- }
-
- messagesCount += msgs.length;
- super.updateRecord({ 'messagesstatus': channel });
-
- if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
- Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}/${i}`, 'messages': splitMsg });
- this.messages.get(channel).set(`${channel}.${i}`, this.collection.findOne(messagesId));
- });
- } else {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}`, 'messages': msgs });
- this.messages.get(channel).set(channel, this.collection.findOne(messagesId));
- }
- }
-
- for (let [directMsgUser, msgs] of tempDirectMessages.entries()) {
- this.logger.debug(`Preparing the direct messages for: ${directMsgUser}`);
- if (!this.directMessages.get(directMsgUser)) {
- this.directMessages.set(directMsgUser, new Map());
- }
-
- messagesCount += msgs.length;
- super.updateRecord({ 'messagesstatus': directMsgUser });
-
- if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
- Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${directMsgUser}/${i}`, 'messages': splitMsg });
- this.directMessages.get(directMsgUser).set(`${directMsgUser}.${i}`, this.collection.findOne(messagesId));
- });
- } else {
- const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${directMsgUser}`, 'messages': msgs });
- this.directMessages.get(directMsgUser).set(directMsgUser, this.collection.findOne(messagesId));
- }
- }
-
- super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
- super.addCountToTotal(messagesCount);
-
- //Ensure we have some users, channels, and messages
- if (tempUsers.length === 0 || tempRooms.length === 0 || messagesCount === 0) {
- this.logger.warn(`The loaded users count ${tempUsers.length}, the loaded rooms ${tempRooms.length}, and the loaded messages ${messagesCount}`);
- super.updateProgress(Importer.ProgressStep.ERROR);
- reject();
- return;
- }
-
- const selectionUsers = tempUsers.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, u.isDeleted, false, true));
- const selectionChannels = tempRooms.map((r) => new Importer.SelectionChannel(r.id, r.name, r.isArchived, true, r.isPrivate));
-
- super.updateProgress(Importer.ProgressStep.USER_SELECTION);
-
- resolve(new Importer.Selection(this.name, selectionUsers, selectionChannels));
- }));
-
- //Wish I could make this cleaner :(
- const split = dataURI.split(',');
- const s = new this.Readable;
- s.push(new Buffer(split[split.length - 1], 'base64'));
- s.push(null);
- s.pipe(this.zlib.createGunzip()).pipe(this.extract);
- });
-
- return promise;
- }
-
- startImport(importSelection) {
- super.startImport(importSelection);
- const started = Date.now();
-
- //Ensure we're only going to import the users that the user has selected
- for (let user of importSelection.users) {
- for (let u of this.users.users) {
- if (u.id === user.user_id) {
- u.do_import = user.do_import;
- }
- }
- }
- this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
-
- //Ensure we're only importing the channels the user has selected.
- for (let channel of importSelection.channels) {
- for (let c of this.channels.channels) {
- if (c.id === channel.channel_id) {
- c.do_import = channel.do_import;
- }
- }
- }
- this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
-
- const startedByUserId = Meteor.userId();
- Meteor.defer(() => {
- super.updateProgress(Importer.ProgressStep.IMPORTING_USERS);
- //Import the users
- for (let u of this.users.users) {
- this.logger.debug(`Starting the user import: ${u.username} and are we importing them? ${u.do_import}`);
- if (!u.do_import) {
- continue;
- }
-
- Meteor.runAsUser(startedByUserId, () => {
- let existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email);
-
- //If we couldn't find one by their email address, try to find an existing user by their username
- if (!existantUser) {
- existantUser = RocketChat.models.Users.findOneByUsername(u.username);
- }
-
- if (existantUser) {
- //since we have an existing user, let's try a few things
- u.rocketId = existantUser._id;
- RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
- } else {
- const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
- Meteor.runAsUser(userId, () => {
- Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
- //TODO: Use moment timezone to calc the time offset - Meteor.call 'userSetUtcOffset', user.tz_offset / 3600
- RocketChat.models.Users.setName(userId, u.name);
- //TODO: Think about using a custom field for the users "title" field
-
- if (u.avatar) {
- Meteor.call('setAvatarFromService', `data:image/png;base64,${u.avatar}`);
- }
-
- //Deleted users are 'inactive' users in Rocket.Chat
- if (u.deleted) {
- Meteor.call('setUserActiveStatus', userId, false);
- }
-
- RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
- u.rocketId = userId;
- });
- }
-
- super.addCountCompleted(1);
- });
- }
- this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
-
- //Import the channels
- super.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS);
- for (let c of this.channels.channels) {
- if (!c.do_import) {
- continue;
- }
-
- Meteor.runAsUser(startedByUserId, () => {
- let existantRoom = RocketChat.models.Rooms.findOneByName(c.name);
- //If the room exists or the name of it is 'general', then we don't need to create it again
- if (existantRoom || c.name.toUpperCase() === 'GENERAL') {
- c.rocketId = c.name.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id;
- RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
- } else {
- //Find the rocketchatId of the user who created this channel
- let creatorId = startedByUserId;
- for (let u of this.users.users) {
- if (u.id === c.creator && u.do_import) {
- creatorId = u.rocketId;
- }
- }
-
- //Create the channel
- Meteor.runAsUser(creatorId, () => {
- const roomInfo = Meteor.call(c.isPrivate ? 'createPrivateGroup' : 'createChannel', c.name, []);
- c.rocketId = roomInfo.rid;
- });
-
- RocketChat.models.Rooms.update({ _id: c.rocketId }, { $set: { ts: c.created, topic: c.topic }, $addToSet: { importIds: c.id } });
- }
-
- super.addCountCompleted(1);
- });
- }
- this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
-
- //Import the Messages
- super.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES);
- for (let [ch, messagesMap] of this.messages.entries()) {
- const hipChannel = this.getChannelFromRoomIdentifier(ch);
- if (!hipChannel.do_import) {
- continue;
- }
-
- const room = RocketChat.models.Rooms.findOneById(hipChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
- Meteor.runAsUser(startedByUserId, () => {
- for (let [msgGroupData, msgs] of messagesMap.entries()) {
- super.updateRecord({ 'messagesstatus': `${ch}/${msgGroupData}.${msgs.messages.length}` });
- for (let msg of msgs.messages) {
- if (isNaN(msg.ts)) {
- this.logger.warn(`Timestamp on a message in ${ch}/${msgGroupData} is invalid`);
- super.addCountCompleted(1);
- continue;
- }
-
- const creator = this.getRocketUserFromUserId(msg.userId);
- if (creator) {
- switch (msg.type) {
- case 'user':
- RocketChat.sendMessage(creator, {
- _id: msg.id,
- ts: msg.ts,
- msg: msg.text,
- rid: room._id,
- u: {
- _id: creator._id,
- username: creator.username
- }
- }, room, true);
- break;
- case 'topic':
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, msg.text, creator, { _id: msg.id, ts: msg.ts });
- break;
- }
- }
-
- super.addCountCompleted(1);
- }
- }
- });
- }
-
- //Import the Direct Messages
- for (let [directMsgRoom, directMessagesMap] of this.directMessages.entries()) {
- const hipUser = this.getUserFromDirectMessageIdentifier(directMsgRoom);
- if (!hipUser.do_import) {
- continue;
- }
-
- //Verify this direct message user's room is valid (confusing but idk how else to explain it)
- if (!this.getRocketUserFromUserId(hipUser.id)) {
- continue;
- }
-
- for (let [msgGroupData, msgs] of directMessagesMap.entries()) {
- super.updateRecord({ 'messagesstatus': `${directMsgRoom}/${msgGroupData}.${msgs.messages.length}` });
- for (let msg of msgs.messages) {
- if (isNaN(msg.ts)) {
- this.logger.warn(`Timestamp on a message in ${directMsgRoom}/${msgGroupData} is invalid`);
- super.addCountCompleted(1);
- continue;
- }
-
- //make sure the message sender is a valid user inside rocket.chat
- const sender = this.getRocketUserFromUserId(msg.senderId);
- if (!sender) {
- continue;
- }
-
- //make sure the receiver of the message is a valid rocket.chat user
- const receiver = this.getRocketUserFromUserId(msg.receiverId);
- if (!receiver) {
- continue;
- }
-
- let room = RocketChat.models.Rooms.findOneById([receiver._id, sender._id].sort().join(''));
- if (!room) {
- Meteor.runAsUser(sender._id, () => {
- const roomInfo = Meteor.call('createDirectMessage', receiver.username);
- room = RocketChat.models.Rooms.findOneById(roomInfo.rid);
- });
- }
-
- Meteor.runAsUser(sender._id, () => {
- RocketChat.sendMessage(sender, {
- _id: msg.id,
- ts: msg.ts,
- msg: msg.text,
- rid: room._id,
- u: {
- _id: sender._id,
- username: sender.username
- }
- }, room, true);
- });
- }
- }
- }
-
- super.updateProgress(Importer.ProgressStep.FINISHING);
- super.updateProgress(Importer.ProgressStep.DONE);
- const timeTook = Date.now() - started;
- this.logger.log(`HipChat Enterprise Import took ${timeTook} milliseconds.`);
- });
-
- return super.getProgress();
- }
-
- getSelection() {
- const selectionUsers = this.users.users.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, false, false, true));
- const selectionChannels = this.channels.channels.map((c) => new Importer.SelectionChannel(c.id, c.name, false, true, c.isPrivate));
-
- return new Importer.Selection(this.name, selectionUsers, selectionChannels);
- }
-
- getChannelFromRoomIdentifier(roomIdentifier) {
- for (let ch of this.channels.channels) {
- if (`rooms/${ch.id}` === roomIdentifier) {
- return ch;
- }
- }
- }
-
- getUserFromDirectMessageIdentifier(directIdentifier) {
- for (let u of this.users.users) {
- if (`users/${u.id}` === directIdentifier) {
- return u;
- }
- }
- }
-
- getRocketUserFromUserId(userId) {
- for (let u of this.users.users) {
- if (u.id === userId) {
- return RocketChat.models.Users.findOneById(u.rocketId, { fields: { username: 1 }});
- }
- }
- }
-};
diff --git a/packages/rocketchat-importer-hipchat-enterprise/server/adder.js b/packages/rocketchat-importer-hipchat-enterprise/server/adder.js
new file mode 100644
index 0000000000000..20ee8203c4699
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/server/adder.js
@@ -0,0 +1,5 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { HipChatEnterpriseImporterInfo } from '../info';
+import { HipChatEnterpriseImporter } from './importer';
+
+Importers.add(new HipChatEnterpriseImporterInfo(), HipChatEnterpriseImporter);
diff --git a/packages/rocketchat-importer-hipchat-enterprise/server/importer.js b/packages/rocketchat-importer-hipchat-enterprise/server/importer.js
new file mode 100644
index 0000000000000..c54f3a42d8650
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/server/importer.js
@@ -0,0 +1,477 @@
+import {
+ Base,
+ ProgressStep,
+ Selection,
+ SelectionChannel,
+ SelectionUser
+} from 'meteor/rocketchat:importer';
+import {Readable} from 'stream';
+import path from 'path';
+
+export class HipChatEnterpriseImporter extends Base {
+ constructor(info) {
+ super(info);
+
+ this.Readable = Readable;
+ this.zlib = require('zlib');
+ this.tarStream = require('tar-stream');
+ this.extract = this.tarStream.extract();
+ this.path = path;
+ this.messages = new Map();
+ this.directMessages = new Map();
+ }
+
+ prepare(dataURI, sentContentType, fileName) {
+ super.prepare(dataURI, sentContentType, fileName);
+
+ const tempUsers = [];
+ const tempRooms = [];
+ const tempMessages = new Map();
+ const tempDirectMessages = new Map();
+ const promise = new Promise((resolve, reject) => {
+ this.extract.on('entry', Meteor.bindEnvironment((header, stream, next) => {
+ if (header.name.indexOf('.json') !== -1) {
+ const info = this.path.parse(header.name);
+
+ stream.on('data', Meteor.bindEnvironment((chunk) => {
+ this.logger.debug(`Processing the file: ${ header.name }`);
+ const file = JSON.parse(chunk);
+
+ if (info.base === 'users.json') {
+ super.updateProgress(ProgressStep.PREPARING_USERS);
+ for (const u of file) {
+ tempUsers.push({
+ id: u.User.id,
+ email: u.User.email,
+ name: u.User.name,
+ username: u.User.mention_name,
+ avatar: u.User.avatar.replace(/\n/g, ''),
+ timezone: u.User.timezone,
+ isDeleted: u.User.is_deleted
+ });
+ }
+ } else if (info.base === 'rooms.json') {
+ super.updateProgress(ProgressStep.PREPARING_CHANNELS);
+ for (const r of file) {
+ tempRooms.push({
+ id: r.Room.id,
+ creator: r.Room.owner,
+ created: new Date(r.Room.created),
+ name: r.Room.name.replace(/ /g, '_').toLowerCase(),
+ isPrivate: r.Room.privacy === 'private',
+ isArchived: r.Room.is_archived,
+ topic: r.Room.topic
+ });
+ }
+ } else if (info.base === 'history.json') {
+ const dirSplit = info.dir.split('/'); //['.', 'users', '1']
+ const roomIdentifier = `${ dirSplit[1] }/${ dirSplit[2] }`;
+
+ if (dirSplit[1] === 'users') {
+ const msgs = [];
+ for (const m of file) {
+ if (m.PrivateUserMessage) {
+ msgs.push({
+ type: 'user',
+ id: `hipchatenterprise-${ m.PrivateUserMessage.id }`,
+ senderId: m.PrivateUserMessage.sender.id,
+ receiverId: m.PrivateUserMessage.receiver.id,
+ text: m.PrivateUserMessage.message.indexOf('/me ') === -1 ? m.PrivateUserMessage.message : `${ m.PrivateUserMessage.message.replace(/\/me /, '_') }_`,
+ ts: new Date(m.PrivateUserMessage.timestamp.split(' ')[0])
+ });
+ }
+ }
+ tempDirectMessages.set(roomIdentifier, msgs);
+ } else if (dirSplit[1] === 'rooms') {
+ const roomMsgs = [];
+
+ for (const m of file) {
+ if (m.UserMessage) {
+ roomMsgs.push({
+ type: 'user',
+ id: `hipchatenterprise-${ dirSplit[2] }-${ m.UserMessage.id }`,
+ userId: m.UserMessage.sender.id,
+ text: m.UserMessage.message.indexOf('/me ') === -1 ? m.UserMessage.message : `${ m.UserMessage.message.replace(/\/me /, '_') }_`,
+ ts: new Date(m.UserMessage.timestamp.split(' ')[0])
+ });
+ } else if (m.TopicRoomMessage) {
+ roomMsgs.push({
+ type: 'topic',
+ id: `hipchatenterprise-${ dirSplit[2] }-${ m.TopicRoomMessage.id }`,
+ userId: m.TopicRoomMessage.sender.id,
+ ts: new Date(m.TopicRoomMessage.timestamp.split(' ')[0]),
+ text: m.TopicRoomMessage.message
+ });
+ } else {
+ this.logger.warn('HipChat Enterprise importer isn\'t configured to handle this message:', m);
+ }
+ }
+ tempMessages.set(roomIdentifier, roomMsgs);
+ } else {
+ this.logger.warn(`HipChat Enterprise importer isn't configured to handle "${ dirSplit[1] }" files.`);
+ }
+ } else {
+ //What are these files!?
+ this.logger.warn(`HipChat Enterprise importer doesn't know what to do with the file "${ header.name }" :o`, info);
+ }
+ }));
+
+ stream.on('end', () => next());
+ stream.on('error', () => next());
+ } else {
+ next();
+ }
+ }));
+
+ this.extract.on('error', (err) => {
+ this.logger.warn('extract error:', err);
+ reject();
+ });
+
+ this.extract.on('finish', Meteor.bindEnvironment(() => {
+ // Insert the users record, eventually this might have to be split into several ones as well
+ // if someone tries to import a several thousands users instance
+ const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
+ this.users = this.collection.findOne(usersId);
+ super.updateRecord({ 'count.users': tempUsers.length });
+ super.addCountToTotal(tempUsers.length);
+
+ // Insert the channels records.
+ const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempRooms });
+ this.channels = this.collection.findOne(channelsId);
+ super.updateRecord({ 'count.channels': tempRooms.length });
+ super.addCountToTotal(tempRooms.length);
+
+ // Save the messages records to the import record for `startImport` usage
+ super.updateProgress(ProgressStep.PREPARING_MESSAGES);
+ let messagesCount = 0;
+ for (const [channel, msgs] of tempMessages.entries()) {
+ if (!this.messages.get(channel)) {
+ this.messages.set(channel, new Map());
+ }
+
+ messagesCount += msgs.length;
+ super.updateRecord({ 'messagesstatus': channel });
+
+ if (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) {
+ Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }/${ i }`, 'messages': splitMsg });
+ this.messages.get(channel).set(`${ channel }.${ i }`, this.collection.findOne(messagesId));
+ });
+ } else {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }`, 'messages': msgs });
+ this.messages.get(channel).set(channel, this.collection.findOne(messagesId));
+ }
+ }
+
+ for (const [directMsgUser, msgs] of tempDirectMessages.entries()) {
+ this.logger.debug(`Preparing the direct messages for: ${ directMsgUser }`);
+ if (!this.directMessages.get(directMsgUser)) {
+ this.directMessages.set(directMsgUser, new Map());
+ }
+
+ messagesCount += msgs.length;
+ super.updateRecord({ 'messagesstatus': directMsgUser });
+
+ if (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) {
+ Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${ directMsgUser }/${ i }`, 'messages': splitMsg });
+ this.directMessages.get(directMsgUser).set(`${ directMsgUser }.${ i }`, this.collection.findOne(messagesId));
+ });
+ } else {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${ directMsgUser }`, 'messages': msgs });
+ this.directMessages.get(directMsgUser).set(directMsgUser, this.collection.findOne(messagesId));
+ }
+ }
+
+ super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
+ super.addCountToTotal(messagesCount);
+
+ //Ensure we have some users, channels, and messages
+ if (tempUsers.length === 0 || tempRooms.length === 0 || messagesCount === 0) {
+ this.logger.warn(`The loaded users count ${ tempUsers.length }, the loaded rooms ${ tempRooms.length }, and the loaded messages ${ messagesCount }`);
+ super.updateProgress(ProgressStep.ERROR);
+ reject();
+ return;
+ }
+
+ const selectionUsers = tempUsers.map((u) => new SelectionUser(u.id, u.username, u.email, u.isDeleted, false, true));
+ const selectionChannels = tempRooms.map((r) => new SelectionChannel(r.id, r.name, r.isArchived, true, r.isPrivate));
+ const selectionMessages = this.importRecord.count.messages;
+
+ super.updateProgress(ProgressStep.USER_SELECTION);
+
+ resolve(new Selection(this.name, selectionUsers, selectionChannels, selectionMessages));
+ }));
+
+ //Wish I could make this cleaner :(
+ const split = dataURI.split(',');
+ const s = new this.Readable;
+ s.push(new Buffer(split[split.length - 1], 'base64'));
+ s.push(null);
+ s.pipe(this.zlib.createGunzip()).pipe(this.extract);
+ });
+
+ return promise;
+ }
+
+ startImport(importSelection) {
+ super.startImport(importSelection);
+ const started = Date.now();
+
+ //Ensure we're only going to import the users that the user has selected
+ for (const user of importSelection.users) {
+ for (const u of this.users.users) {
+ if (u.id === user.user_id) {
+ u.do_import = user.do_import;
+ }
+ }
+ }
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ //Ensure we're only importing the channels the user has selected.
+ for (const channel of importSelection.channels) {
+ for (const c of this.channels.channels) {
+ if (c.id === channel.channel_id) {
+ c.do_import = channel.do_import;
+ }
+ }
+ }
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ const startedByUserId = Meteor.userId();
+ Meteor.defer(() => {
+ super.updateProgress(ProgressStep.IMPORTING_USERS);
+
+ try {
+ //Import the users
+ for (const u of this.users.users) {
+ this.logger.debug(`Starting the user import: ${ u.username } and are we importing them? ${ u.do_import }`);
+ if (!u.do_import) {
+ continue;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ let existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email);
+
+ //If we couldn't find one by their email address, try to find an existing user by their username
+ if (!existantUser) {
+ existantUser = RocketChat.models.Users.findOneByUsername(u.username);
+ }
+
+ if (existantUser) {
+ //since we have an existing user, let's try a few things
+ u.rocketId = existantUser._id;
+ RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
+ } else {
+ const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
+ //TODO: Use moment timezone to calc the time offset - Meteor.call 'userSetUtcOffset', user.tz_offset / 3600
+ RocketChat.models.Users.setName(userId, u.name);
+ //TODO: Think about using a custom field for the users "title" field
+
+ if (u.avatar) {
+ Meteor.call('setAvatarFromService', `data:image/png;base64,${ u.avatar }`);
+ }
+
+ //Deleted users are 'inactive' users in Rocket.Chat
+ if (u.deleted) {
+ Meteor.call('setUserActiveStatus', userId, false);
+ }
+
+ RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
+ u.rocketId = userId;
+ });
+ }
+
+ super.addCountCompleted(1);
+ });
+ }
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ //Import the channels
+ super.updateProgress(ProgressStep.IMPORTING_CHANNELS);
+ for (const c of this.channels.channels) {
+ if (!c.do_import) {
+ continue;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantRoom = RocketChat.models.Rooms.findOneByName(c.name);
+ //If the room exists or the name of it is 'general', then we don't need to create it again
+ if (existantRoom || c.name.toUpperCase() === 'GENERAL') {
+ c.rocketId = c.name.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id;
+ RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
+ } else {
+ //Find the rocketchatId of the user who created this channel
+ let creatorId = startedByUserId;
+ for (const u of this.users.users) {
+ if (u.id === c.creator && u.do_import) {
+ creatorId = u.rocketId;
+ }
+ }
+
+ //Create the channel
+ Meteor.runAsUser(creatorId, () => {
+ const roomInfo = Meteor.call(c.isPrivate ? 'createPrivateGroup' : 'createChannel', c.name, []);
+ c.rocketId = roomInfo.rid;
+ });
+
+ RocketChat.models.Rooms.update({ _id: c.rocketId }, { $set: { ts: c.created, topic: c.topic }, $addToSet: { importIds: c.id } });
+ }
+
+ super.addCountCompleted(1);
+ });
+ }
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ //Import the Messages
+ super.updateProgress(ProgressStep.IMPORTING_MESSAGES);
+ for (const [ch, messagesMap] of this.messages.entries()) {
+ const hipChannel = this.getChannelFromRoomIdentifier(ch);
+ if (!hipChannel.do_import) {
+ continue;
+ }
+
+ const room = RocketChat.models.Rooms.findOneById(hipChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
+ Meteor.runAsUser(startedByUserId, () => {
+ for (const [msgGroupData, msgs] of messagesMap.entries()) {
+ super.updateRecord({ 'messagesstatus': `${ ch }/${ msgGroupData }.${ msgs.messages.length }` });
+ for (const msg of msgs.messages) {
+ if (isNaN(msg.ts)) {
+ this.logger.warn(`Timestamp on a message in ${ ch }/${ msgGroupData } is invalid`);
+ super.addCountCompleted(1);
+ continue;
+ }
+
+ const creator = this.getRocketUserFromUserId(msg.userId);
+ if (creator) {
+ switch (msg.type) {
+ case 'user':
+ RocketChat.sendMessage(creator, {
+ _id: msg.id,
+ ts: msg.ts,
+ msg: msg.text,
+ rid: room._id,
+ u: {
+ _id: creator._id,
+ username: creator.username
+ }
+ }, room, true);
+ break;
+ case 'topic':
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, msg.text, creator, { _id: msg.id, ts: msg.ts });
+ break;
+ }
+ }
+
+ super.addCountCompleted(1);
+ }
+ }
+ });
+ }
+
+ //Import the Direct Messages
+ for (const [directMsgRoom, directMessagesMap] of this.directMessages.entries()) {
+ const hipUser = this.getUserFromDirectMessageIdentifier(directMsgRoom);
+ if (!hipUser.do_import) {
+ continue;
+ }
+
+ //Verify this direct message user's room is valid (confusing but idk how else to explain it)
+ if (!this.getRocketUserFromUserId(hipUser.id)) {
+ continue;
+ }
+
+ for (const [msgGroupData, msgs] of directMessagesMap.entries()) {
+ super.updateRecord({ 'messagesstatus': `${ directMsgRoom }/${ msgGroupData }.${ msgs.messages.length }` });
+ for (const msg of msgs.messages) {
+ if (isNaN(msg.ts)) {
+ this.logger.warn(`Timestamp on a message in ${ directMsgRoom }/${ msgGroupData } is invalid`);
+ super.addCountCompleted(1);
+ continue;
+ }
+
+ //make sure the message sender is a valid user inside rocket.chat
+ const sender = this.getRocketUserFromUserId(msg.senderId);
+ if (!sender) {
+ continue;
+ }
+
+ //make sure the receiver of the message is a valid rocket.chat user
+ const receiver = this.getRocketUserFromUserId(msg.receiverId);
+ if (!receiver) {
+ continue;
+ }
+
+ let room = RocketChat.models.Rooms.findOneById([receiver._id, sender._id].sort().join(''));
+ if (!room) {
+ Meteor.runAsUser(sender._id, () => {
+ const roomInfo = Meteor.call('createDirectMessage', receiver.username);
+ room = RocketChat.models.Rooms.findOneById(roomInfo.rid);
+ });
+ }
+
+ Meteor.runAsUser(sender._id, () => {
+ RocketChat.sendMessage(sender, {
+ _id: msg.id,
+ ts: msg.ts,
+ msg: msg.text,
+ rid: room._id,
+ u: {
+ _id: sender._id,
+ username: sender.username
+ }
+ }, room, true);
+ });
+ }
+ }
+ }
+
+ super.updateProgress(ProgressStep.FINISHING);
+ super.updateProgress(ProgressStep.DONE);
+ } catch (e) {
+ this.logger.error(e);
+ super.updateProgress(ProgressStep.ERROR);
+ }
+
+ const timeTook = Date.now() - started;
+ this.logger.log(`HipChat Enterprise Import took ${ timeTook } milliseconds.`);
+ });
+
+ return super.getProgress();
+ }
+
+ getSelection() {
+ const selectionUsers = this.users.users.map((u) => new SelectionUser(u.id, u.username, u.email, false, false, true));
+ const selectionChannels = this.channels.channels.map((c) => new SelectionChannel(c.id, c.name, false, true, c.isPrivate));
+ const selectionMessages = this.importRecord.count.messages;
+
+ return new Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
+ }
+
+ getChannelFromRoomIdentifier(roomIdentifier) {
+ for (const ch of this.channels.channels) {
+ if (`rooms/${ ch.id }` === roomIdentifier) {
+ return ch;
+ }
+ }
+ }
+
+ getUserFromDirectMessageIdentifier(directIdentifier) {
+ for (const u of this.users.users) {
+ if (`users/${ u.id }` === directIdentifier) {
+ return u;
+ }
+ }
+ }
+
+ getRocketUserFromUserId(userId) {
+ for (const u of this.users.users) {
+ if (u.id === userId) {
+ return RocketChat.models.Users.findOneById(u.rocketId, { fields: { username: 1 }});
+ }
+ }
+ }
+}
diff --git a/packages/rocketchat-importer-hipchat/client/adder.js b/packages/rocketchat-importer-hipchat/client/adder.js
new file mode 100644
index 0000000000000..c9c2944358c63
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat/client/adder.js
@@ -0,0 +1,4 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { HipChatImporterInfo } from '../info';
+
+Importers.add(new HipChatImporterInfo());
diff --git a/packages/rocketchat-importer-hipchat/info.js b/packages/rocketchat-importer-hipchat/info.js
new file mode 100644
index 0000000000000..057cf2afe3bf3
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat/info.js
@@ -0,0 +1,7 @@
+import { ImporterInfo } from 'meteor/rocketchat:importer';
+
+export class HipChatImporterInfo extends ImporterInfo {
+ constructor() {
+ super('hipchat', 'HipChat', 'application/zip');
+ }
+}
diff --git a/packages/rocketchat-importer-hipchat/main.coffee b/packages/rocketchat-importer-hipchat/main.coffee
deleted file mode 100644
index 1198383d75c6a..0000000000000
--- a/packages/rocketchat-importer-hipchat/main.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-Importer.addImporter 'hipchat', Importer.HipChat,
- name: 'HipChat'
- mimeType: 'application/zip'
diff --git a/packages/rocketchat-importer-hipchat/package.js b/packages/rocketchat-importer-hipchat/package.js
index 7461d067475c5..5ffec6cd5afcd 100644
--- a/packages/rocketchat-importer-hipchat/package.js
+++ b/packages/rocketchat-importer-hipchat/package.js
@@ -8,11 +8,18 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'coffeescript',
'rocketchat:lib',
'rocketchat:importer'
]);
+
api.use('rocketchat:logger', 'server');
- api.addFiles('server.coffee', 'server');
- api.addFiles('main.coffee', ['client', 'server']);
+
+ // Importer information to both server and client
+ api.addFiles('info.js');
+
+ // Server files
+ api.addFiles(['server/importer.js', 'server/adder.js'], 'server');
+
+ // Client files
+ api.addFiles('client/adder.js', 'client');
});
diff --git a/packages/rocketchat-importer-hipchat/server.coffee b/packages/rocketchat-importer-hipchat/server.coffee
deleted file mode 100644
index c84a6413b8f1f..0000000000000
--- a/packages/rocketchat-importer-hipchat/server.coffee
+++ /dev/null
@@ -1,241 +0,0 @@
-import moment from 'moment'
-import 'moment-timezone'
-
-Importer.HipChat = class Importer.HipChat extends Importer.Base
- @RoomPrefix = 'hipchat_export/rooms/'
- @UsersPrefix = 'hipchat_export/users/'
-
- constructor: (name, descriptionI18N, mimeType) ->
- super(name, descriptionI18N, mimeType)
- @logger.debug('Constructed a new Slack Importer.')
- @userTags = []
-
- prepare: (dataURI, sentContentType, fileName) =>
- super(dataURI, sentContentType, fileName)
-
- {image, contentType} = RocketChatFile.dataURIParse dataURI
- zip = new @AdmZip(new Buffer(image, 'base64'))
- zipEntries = zip.getEntries()
-
- tempRooms = []
- tempUsers = []
- tempMessages = {}
- for entry in zipEntries
- do (entry) =>
- if entry.entryName.indexOf('__MACOSX') > -1
- #ignore all of the files inside of __MACOSX
- @logger.debug("Ignoring the file: #{entry.entryName}")
- if not entry.isDirectory
- if entry.entryName.indexOf(Importer.HipChat.RoomPrefix) > -1
- roomName = entry.entryName.split(Importer.HipChat.RoomPrefix)[1]
- if roomName is 'list.json'
- @updateProgress Importer.ProgressStep.PREPARING_CHANNELS
- tempRooms = JSON.parse(entry.getData().toString()).rooms
- for room in tempRooms
- room.name = _.slugify room.name
- else if roomName.indexOf('/') > -1
- item = roomName.split('/')
- roomName = _.slugify item[0] #random
- msgGroupData = item[1].split('.')[0] #2015-10-04
- if not tempMessages[roomName]
- tempMessages[roomName] = {}
- # For some reason some of the json files in the HipChat export aren't valid JSON
- # files, so we need to catch those and just ignore them (sadly).
- try
- tempMessages[roomName][msgGroupData] = JSON.parse entry.getData().toString()
- catch
- @logger.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
- else if entry.entryName.indexOf(Importer.HipChat.UsersPrefix) > -1
- usersName = entry.entryName.split(Importer.HipChat.UsersPrefix)[1]
- if usersName is 'list.json'
- @updateProgress Importer.ProgressStep.PREPARING_USERS
- tempUsers = JSON.parse(entry.getData().toString()).users
- else
- @logger.warn "Unexpected file in the #{@name} import: #{entry.entryName}"
-
- # Insert the users record, eventually this might have to be split into several ones as well
- # if someone tries to import a several thousands users instance
- usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
- @users = @collection.findOne usersId
- @updateRecord { 'count.users': tempUsers.length }
- @addCountToTotal tempUsers.length
-
- # Insert the rooms records.
- channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempRooms }
- @channels = @collection.findOne channelsId
- @updateRecord { 'count.channels': tempRooms.length }
- @addCountToTotal tempRooms.length
-
- # Insert the messages records
- @updateProgress Importer.ProgressStep.PREPARING_MESSAGES
- messagesCount = 0
- for channel, messagesObj of tempMessages
- do (channel, messagesObj) =>
- if not @messages[channel]
- @messages[channel] = {}
- for date, msgs of messagesObj
- messagesCount += msgs.length
- @updateRecord { 'messagesstatus': "#{channel}/#{date}" }
-
- if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
- for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
- messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
- @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
- else
- messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
- @messages[channel][date] = @collection.findOne messagesId
-
- @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
- @addCountToTotal messagesCount
-
- if tempUsers.length is 0 or tempRooms.length is 0 or messagesCount is 0
- @logger.warn "The loaded users count #{tempUsers.length}, the loaded channels #{tempRooms.length}, and the loaded messages #{messagesCount}"
- @updateProgress Importer.ProgressStep.ERROR
- return @getProgress()
-
- selectionUsers = tempUsers.map (user) ->
- #HipChat's export doesn't contain bot users, from the data I've seen
- return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot
- selectionChannels = tempRooms.map (room) ->
- return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true, false
-
- @updateProgress Importer.ProgressStep.USER_SELECTION
- return new Importer.Selection @name, selectionUsers, selectionChannels
-
- startImport: (importSelection) =>
- super(importSelection)
- start = Date.now()
-
- for user in importSelection.users
- for u in @users.users when u.user_id is user.user_id
- u.do_import = user.do_import
- @collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
-
- for channel in importSelection.channels
- for c in @channels.channels when c.room_id is channel.channel_id
- c.do_import = channel.do_import
- @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
-
- startedByUserId = Meteor.userId()
- Meteor.defer =>
- @updateProgress Importer.ProgressStep.IMPORTING_USERS
- for user in @users.users when user.do_import
- do (user) =>
- Meteor.runAsUser startedByUserId, () =>
- existantUser = RocketChat.models.Users.findOneByEmailAddress user.email
- if existantUser
- user.rocketId = existantUser._id
- @userTags.push
- hipchat: "@#{user.mention_name}"
- rocket: "@#{existantUser.username}"
- else
- userId = Accounts.createUser { email: user.email, password: Date.now() + user.name + user.email.toUpperCase() }
- user.rocketId = userId
- @userTags.push
- hipchat: "@#{user.mention_name}"
- rocket: "@#{user.mention_name}"
- Meteor.runAsUser userId, () =>
- Meteor.call 'setUsername', user.mention_name, {joinDefaultChannelsSilenced: true}
- Meteor.call 'setAvatarFromService', user.photo_url, undefined, 'url'
- Meteor.call 'userSetUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0]
-
- if user.name?
- RocketChat.models.Users.setName userId, user.name
-
- #Deleted users are 'inactive' users in Rocket.Chat
- if user.is_deleted
- Meteor.call 'setUserActiveStatus', userId, false
- @addCountCompleted 1
- @collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
-
- @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
- for channel in @channels.channels when channel.do_import
- do (channel) =>
- Meteor.runAsUser startedByUserId, () =>
- channel.name = channel.name.replace(/ /g, '')
- existantRoom = RocketChat.models.Rooms.findOneByName channel.name
- if existantRoom
- channel.rocketId = existantRoom._id
- else
- userId = ''
- for user in @users.users when user.user_id is channel.owner_user_id
- userId = user.rocketId
-
- if userId is ''
- @logger.warn "Failed to find the channel creator for #{channel.name}, setting it to the current running user."
- userId = startedByUserId
-
- Meteor.runAsUser userId, () =>
- returned = Meteor.call 'createChannel', channel.name, []
- channel.rocketId = returned.rid
- RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: { 'ts': new Date(channel.created * 1000) }}
- @addCountCompleted 1
- @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
-
- @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
- nousers = {};
- for channel, messagesObj of @messages
- do (channel, messagesObj) =>
- Meteor.runAsUser startedByUserId, () =>
- hipchatChannel = @getHipChatChannelFromName channel
- if hipchatChannel?.do_import
- room = RocketChat.models.Rooms.findOneById hipchatChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
- for date, msgs of messagesObj
- @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
- for message in msgs.messages
- if message.from?
- user = @getRocketUser(message.from.user_id)
- if user?
- msgObj =
- msg: @convertHipChatMessageToRocketChat(message.message)
- ts: new Date(message.date)
- u:
- _id: user._id
- username: user.username
-
- RocketChat.sendMessage user, msgObj, room, true
- else
- if not nousers[message.from.user_id]
- nousers[message.from.user_id] = message.from
- else
- if not _.isArray message
- console.warn 'Please report the following:', message
- @addCountCompleted 1
- @logger.warn 'The following did not have users:', nousers
-
- @updateProgress Importer.ProgressStep.FINISHING
- for channel in @channels.channels when channel.do_import and channel.is_archived
- do (channel) =>
- Meteor.runAsUser startedByUserId, () =>
- Meteor.call 'archiveRoom', channel.rocketId
-
- @updateProgress Importer.ProgressStep.DONE
- timeTook = Date.now() - start
- @logger.log "Import took #{timeTook} milliseconds."
-
- return @getProgress()
-
- getHipChatChannelFromName: (channelName) =>
- for channel in @channels.channels when channel.name is channelName
- return channel
-
- getRocketUser: (hipchatId) =>
- for user in @users.users when user.user_id is hipchatId
- return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1 }}
-
- convertHipChatMessageToRocketChat: (message) =>
- if message?
- for userReplace in @userTags
- message = message.replace userReplace.hipchat, userReplace.rocket
- else
- message = ''
- return message
-
- getSelection: () =>
- selectionUsers = @users.users.map (user) ->
- #HipChat's export doesn't contain bot users, from the data I've seen
- return new Importer.SelectionUser user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot
- selectionChannels = @channels.channels.map (room) ->
- return new Importer.SelectionChannel room.room_id, room.name, room.is_archived, true, false
-
- return new Importer.Selection @name, selectionUsers, selectionChannels
diff --git a/packages/rocketchat-importer-hipchat/server/adder.js b/packages/rocketchat-importer-hipchat/server/adder.js
new file mode 100644
index 0000000000000..d68056b5e8899
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat/server/adder.js
@@ -0,0 +1,5 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { HipChatImporterInfo } from '../info';
+import { HipChatImporter } from './importer';
+
+Importers.add(new HipChatImporterInfo(), HipChatImporter);
diff --git a/packages/rocketchat-importer-hipchat/server/importer.js b/packages/rocketchat-importer-hipchat/server/importer.js
new file mode 100644
index 0000000000000..6f2fcb57f1b36
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat/server/importer.js
@@ -0,0 +1,360 @@
+import {
+ Base,
+ ProgressStep,
+ Selection,
+ SelectionChannel,
+ SelectionUser
+} from 'meteor/rocketchat:importer';
+
+import _ from 'underscore';
+import s from 'underscore.string';
+import moment from 'moment';
+
+import 'moment-timezone';
+
+export class HipChatImporter extends Base {
+ constructor(info) {
+ super(info);
+
+ this.userTags = [];
+ this.roomPrefix = 'hipchat_export/rooms/';
+ this.usersPrefix = 'hipchat_export/users/';
+ }
+
+ prepare(dataURI, sentContentType, fileName) {
+ super.prepare(dataURI, sentContentType, fileName);
+ const image = RocketChatFile.dataURIParse(dataURI).image;
+ // const contentType = ref.contentType;
+ const zip = new this.AdmZip(new Buffer(image, 'base64'));
+ const zipEntries = zip.getEntries();
+ const tempRooms = [];
+ let tempUsers = [];
+ const tempMessages = {};
+
+ zipEntries.forEach(entry => {
+ if (entry.entryName.indexOf('__MACOSX') > -1) {
+ this.logger.debug(`Ignoring the file: ${ entry.entryName }`);
+ }
+ if (entry.isDirectory) {
+ return;
+ }
+ if (entry.entryName.indexOf(this.roomPrefix) > -1) {
+ let roomName = entry.entryName.split(this.roomPrefix)[1];
+ if (roomName === 'list.json') {
+ super.updateProgress(ProgressStep.PREPARING_CHANNELS);
+ const tempRooms = JSON.parse(entry.getData().toString()).rooms;
+ tempRooms.forEach(room => {
+ room.name = s.slugify(room.name);
+ });
+ } else if (roomName.indexOf('/') > -1) {
+ const item = roomName.split('/');
+ roomName = s.slugify(item[0]);
+ const msgGroupData = item[1].split('.')[0];
+ if (!tempMessages[roomName]) {
+ tempMessages[roomName] = {};
+ }
+ try {
+ return tempMessages[roomName][msgGroupData] = JSON.parse(entry.getData().toString());
+ } catch (error) {
+ return this.logger.warn(`${ entry.entryName } is not a valid JSON file! Unable to import it.`);
+ }
+ }
+ } else if (entry.entryName.indexOf(this.usersPrefix) > -1) {
+ const usersName = entry.entryName.split(this.usersPrefix)[1];
+ if (usersName === 'list.json') {
+ super.updateProgress(ProgressStep.PREPARING_USERS);
+ return tempUsers = JSON.parse(entry.getData().toString()).users;
+ } else {
+ return this.logger.warn(`Unexpected file in the ${ this.name } import: ${ entry.entryName }`);
+ }
+ }
+ });
+ const usersId = this.collection.insert({
+ 'import': this.importRecord._id,
+ 'importer': this.name,
+ 'type': 'users',
+ 'users': tempUsers
+ });
+ this.users = this.collection.findOne(usersId);
+ this.updateRecord({
+ 'count.users': tempUsers.length
+ });
+ this.addCountToTotal(tempUsers.length);
+ const channelsId = this.collection.insert({
+ 'import': this.importRecord._id,
+ 'importer': this.name,
+ 'type': 'channels',
+ 'channels': tempRooms
+ });
+ this.channels = this.collection.findOne(channelsId);
+ this.updateRecord({
+ 'count.channels': tempRooms.length
+ });
+ this.addCountToTotal(tempRooms.length);
+ super.updateProgress(ProgressStep.PREPARING_MESSAGES);
+ let messagesCount = 0;
+ Object.keys(tempMessages).forEach(channel => {
+ const messagesObj = tempMessages[channel];
+ this.messages[channel] = this.messages[channel] || {};
+ Object.keys(messagesObj).forEach(date => {
+ const msgs = messagesObj[date];
+ messagesCount += msgs.length;
+ this.updateRecord({
+ 'messagesstatus': `${ channel }/${ date }`
+ });
+ if (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) {
+ Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+ const messagesId = this.collection.insert({
+ 'import': this.importRecord._id,
+ 'importer': this.name,
+ 'type': 'messages',
+ 'name': `${ channel }/${ date }.${ i }`,
+ 'messages': splitMsg
+ });
+ this.messages[channel][`${ date }.${ i }`] = this.collection.findOne(messagesId);
+ });
+ } else {
+ const messagesId = this.collection.insert({
+ 'import': this.importRecord._id,
+ 'importer': this.name,
+ 'type': 'messages',
+ 'name': `${ channel }/${ date }`,
+ 'messages': msgs
+ });
+ this.messages[channel][date] = this.collection.findOne(messagesId);
+ }
+ });
+ });
+ this.updateRecord({
+ 'count.messages': messagesCount,
+ 'messagesstatus': null
+ });
+ this.addCountToTotal(messagesCount);
+ if (tempUsers.length === 0 || tempRooms.length === 0 || messagesCount === 0) {
+ this.logger.warn(`The loaded users count ${ tempUsers.length }, the loaded channels ${ tempRooms.length }, and the loaded messages ${ messagesCount }`);
+ super.updateProgress(ProgressStep.ERROR);
+ return this.getProgress();
+ }
+ const selectionUsers = tempUsers.map(function(user) {
+ return new SelectionUser(user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot);
+ });
+ const selectionChannels = tempRooms.map(function(room) {
+ return new SelectionChannel(room.room_id, room.name, room.is_archived, true, false);
+ });
+ const selectionMessages = this.importRecord.count.messages;
+ super.updateProgress(ProgressStep.USER_SELECTION);
+ return new Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
+ }
+
+ startImport(importSelection) {
+ super.startImport(importSelection);
+ const start = Date.now();
+
+ importSelection.users.forEach(user => {
+ this.users.users.forEach(u => {
+ if (u.user_id === user.user_id) {
+ u.do_import = user.do_import;
+ }
+ });
+ });
+ this.collection.update({_id: this.users._id}, { $set: { 'users': this.users.users } });
+
+ importSelection.channels.forEach(channel =>
+ this.channels.channels.forEach(c => c.room_id === channel.channel_id && (c.do_import = channel.do_import))
+ );
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ const startedByUserId = Meteor.userId();
+ Meteor.defer(() => {
+ super.updateProgress(ProgressStep.IMPORTING_USERS);
+
+ try {
+ this.users.users.forEach(user => {
+ if (!user.do_import) {
+ return;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantUser = RocketChat.models.Users.findOneByEmailAddress(user.email);
+ if (existantUser) {
+ user.rocketId = existantUser._id;
+ this.userTags.push({
+ hipchat: `@${ user.mention_name }`,
+ rocket: `@${ existantUser.username }`
+ });
+ } else {
+ const userId = Accounts.createUser({
+ email: user.email,
+ password: Date.now() + user.name + user.email.toUpperCase()
+ });
+ user.rocketId = userId;
+ this.userTags.push({
+ hipchat: `@${ user.mention_name }`,
+ rocket: `@${ user.mention_name }`
+ });
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setUsername', user.mention_name, {
+ joinDefaultChannelsSilenced: true
+ });
+ Meteor.call('setAvatarFromService', user.photo_url, undefined, 'url');
+ return Meteor.call('userSetUtcOffset', parseInt(moment().tz(user.timezone).format('Z').toString().split(':')[0]));
+ });
+ if (user.name != null) {
+ RocketChat.models.Users.setName(userId, user.name);
+ }
+ if (user.is_deleted) {
+ Meteor.call('setUserActiveStatus', userId, false);
+ }
+ }
+ return this.addCountCompleted(1);
+ });
+ });
+
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ super.updateProgress(ProgressStep.IMPORTING_CHANNELS);
+ this.channels.channels.forEach(channel => {
+ if (!channel.do_import) {
+ return;
+ }
+ Meteor.runAsUser(startedByUserId, () => {
+ channel.name = channel.name.replace(/ /g, '');
+ const existantRoom = RocketChat.models.Rooms.findOneByName(channel.name);
+ if (existantRoom) {
+ channel.rocketId = existantRoom._id;
+ } else {
+ let userId = '';
+ this.users.users.forEach(user => {
+ if (user.user_id === channel.owner_user_id) {
+ userId = user.rocketId;
+ }
+ });
+ if (userId === '') {
+ this.logger.warn(`Failed to find the channel creator for ${ channel.name }, setting it to the current running user.`);
+ userId = startedByUserId;
+ }
+ Meteor.runAsUser(userId, () => {
+ const returned = Meteor.call('createChannel', channel.name, []);
+ return channel.rocketId = returned.rid;
+ });
+ RocketChat.models.Rooms.update({
+ _id: channel.rocketId
+ }, {
+ $set: {
+ 'ts': new Date(channel.created * 1000)
+ }
+ });
+ }
+ return this.addCountCompleted(1);
+ });
+ });
+
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ super.updateProgress(ProgressStep.IMPORTING_MESSAGES);
+ const nousers = {};
+
+ Object.keys(this.messages).forEach(channel => {
+ const messagesObj = this.messages[channel];
+ Meteor.runAsUser(startedByUserId, () => {
+ const hipchatChannel = this.getHipChatChannelFromName(channel);
+ if (hipchatChannel != null ? hipchatChannel.do_import : undefined) {
+ const room = RocketChat.models.Rooms.findOneById(hipchatChannel.rocketId, {
+ fields: {
+ usernames: 1,
+ t: 1,
+ name: 1
+ }
+ });
+
+ Object.keys(messagesObj).forEach(date => {
+ const msgs = messagesObj[date];
+ this.updateRecord({
+ 'messagesstatus': `${ channel }/${ date }.${ msgs.messages.length }`
+ });
+
+ msgs.messages.forEach(message => {
+ if (message.from != null) {
+ const user = this.getRocketUser(message.from.user_id);
+ if (user != null) {
+ const msgObj = {
+ msg: this.convertHipChatMessageToRocketChat(message.message),
+ ts: new Date(message.date),
+ u: {
+ _id: user._id,
+ username: user.username
+ }
+ };
+ RocketChat.sendMessage(user, msgObj, room, true);
+ } else if (!nousers[message.from.user_id]) {
+ nousers[message.from.user_id] = message.from;
+ }
+ } else if (!_.isArray(message)) {
+ console.warn('Please report the following:', message);
+ }
+ this.addCountCompleted(1);
+ });
+ });
+ }
+ });
+ });
+
+ this.logger.warn('The following did not have users:', nousers);
+ super.updateProgress(ProgressStep.FINISHING);
+
+ this.channels.channels.forEach(channel => {
+ if (channel.do_import && channel.is_archived) {
+ Meteor.runAsUser(startedByUserId, () => {
+ return Meteor.call('archiveRoom', channel.rocketId);
+ });
+ }
+ });
+
+ super.updateProgress(ProgressStep.DONE);
+ } catch (e) {
+ this.logger.error(e);
+ super.updateProgress(ProgressStep.ERROR);
+ }
+
+ const timeTook = Date.now() - start;
+ return this.logger.log(`Import took ${ timeTook } milliseconds.`);
+ });
+
+ return this.getProgress();
+ }
+
+ getHipChatChannelFromName(channelName) {
+ return this.channels.channels.find(channel => channel.name === channelName);
+ }
+
+ getRocketUser(hipchatId) {
+ const user = this.users.users.find(user => user.user_id === hipchatId);
+ return user ? RocketChat.models.Users.findOneById(user.rocketId, {
+ fields: {
+ username: 1,
+ name: 1
+ }
+ }) : undefined;
+ }
+
+ convertHipChatMessageToRocketChat(message) {
+ if (message != null) {
+ this.userTags.forEach(userReplace => {
+ message = message.replace(userReplace.hipchat, userReplace.rocket);
+ });
+ } else {
+ message = '';
+ }
+ return message;
+ }
+
+ getSelection() {
+ const selectionUsers = this.users.users.map(function(user) {
+ return new SelectionUser(user.user_id, user.name, user.email, user.is_deleted, false, !user.is_bot);
+ });
+ const selectionChannels = this.channels.channels.map(function(room) {
+ return new SelectionChannel(room.room_id, room.name, room.is_archived, true, false);
+ });
+ return new Selection(this.name, selectionUsers, selectionChannels, this.importRecord.count.messages);
+ }
+}
diff --git a/packages/rocketchat-importer-slack-users/client/adder.js b/packages/rocketchat-importer-slack-users/client/adder.js
new file mode 100644
index 0000000000000..24aa8760c7f68
--- /dev/null
+++ b/packages/rocketchat-importer-slack-users/client/adder.js
@@ -0,0 +1,4 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { SlackUsersImporterInfo } from '../info';
+
+Importers.add(new SlackUsersImporterInfo());
diff --git a/packages/rocketchat-importer-slack-users/info.js b/packages/rocketchat-importer-slack-users/info.js
new file mode 100644
index 0000000000000..9355b5f1acf24
--- /dev/null
+++ b/packages/rocketchat-importer-slack-users/info.js
@@ -0,0 +1,10 @@
+import { ImporterInfo } from 'meteor/rocketchat:importer';
+
+export class SlackUsersImporterInfo extends ImporterInfo {
+ constructor() {
+ super('slack-users', 'Slack_Users', 'text/csv', [{
+ text: 'Importer_Slack_Users_CSV_Information',
+ href: 'https://rocket.chat/docs/administrator-guides/import/slack/users'
+ }]);
+ }
+}
diff --git a/packages/rocketchat-importer-slack-users/package.js b/packages/rocketchat-importer-slack-users/package.js
new file mode 100644
index 0000000000000..0eb3de652db7f
--- /dev/null
+++ b/packages/rocketchat-importer-slack-users/package.js
@@ -0,0 +1,25 @@
+Package.describe({
+ name: 'rocketchat:importer-slack-users',
+ version: '1.0.0',
+ summary: 'Importer for Slack\'s CSV User Export',
+ git: ''
+});
+
+Package.onUse(function(api) {
+ api.use([
+ 'ecmascript',
+ 'rocketchat:lib',
+ 'rocketchat:importer'
+ ]);
+
+ api.use('rocketchat:logger', 'server');
+
+ // Importer information to both server and client
+ api.addFiles('info.js');
+
+ // Server files
+ api.addFiles(['server/importer.js', 'server/adder.js'], 'server');
+
+ // Client files
+ api.addFiles('client/adder.js', 'client');
+});
diff --git a/packages/rocketchat-importer-slack-users/server/adder.js b/packages/rocketchat-importer-slack-users/server/adder.js
new file mode 100644
index 0000000000000..af34e4570db49
--- /dev/null
+++ b/packages/rocketchat-importer-slack-users/server/adder.js
@@ -0,0 +1,5 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { SlackUsersImporterInfo } from '../info';
+import { SlackUsersImporter } from './importer';
+
+Importers.add(new SlackUsersImporterInfo(), SlackUsersImporter);
diff --git a/packages/rocketchat-importer-slack-users/server/importer.js b/packages/rocketchat-importer-slack-users/server/importer.js
new file mode 100644
index 0000000000000..59b5ce53d08f1
--- /dev/null
+++ b/packages/rocketchat-importer-slack-users/server/importer.js
@@ -0,0 +1,142 @@
+import {
+ Base,
+ ProgressStep,
+ Selection,
+ SelectionUser
+} from 'meteor/rocketchat:importer';
+
+export class SlackUsersImporter extends Base {
+ constructor(info) {
+ super(info);
+
+ this.csvParser = require('csv-parse/lib/sync');
+ this.userMap = new Map();
+ this.admins = []; //Array of ids of the users which are admins
+ }
+
+ prepare(dataURI, sentContentType, fileName) {
+ super.prepare(dataURI, sentContentType, fileName, true);
+
+ super.updateProgress(ProgressStep.PREPARING_USERS);
+ const uriResult = RocketChatFile.dataURIParse(dataURI);
+ const buf = new Buffer(uriResult.image, 'base64');
+ const parsed = this.csvParser(buf.toString());
+
+ parsed.forEach((user, index) => {
+ // Ignore the first column
+ if (index === 0) {
+ return;
+ }
+
+ const id = Random.id();
+ const username = user[0];
+ const email = user[1];
+ let isBot = false;
+ let isDeleted = false;
+
+ switch (user[2]) {
+ case 'Admin':
+ this.admins.push(id);
+ break;
+ case 'Bot':
+ isBot = true;
+ break;
+ case 'Deactivated':
+ isDeleted = true;
+ break;
+ }
+
+ this.userMap.set(id, new SelectionUser(id, username, email, isDeleted, isBot, true));
+ });
+
+ const userArray = Array.from(this.userMap.values());
+
+ const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': userArray });
+ this.users = this.collection.findOne(usersId);
+ super.updateRecord({ 'count.users': this.userMap.size });
+ super.addCountToTotal(this.userMap.size);
+
+ if (this.userMap.size === 0) {
+ this.logger.error('No users found in the import file.');
+ super.updateProgress(ProgressStep.ERROR);
+ return super.getProgress();
+ }
+
+ super.updateProgress(ProgressStep.USER_SELECTION);
+ return new Selection(this.name, userArray, [], 0);
+ }
+
+ startImport(importSelection) {
+ super.startImport(importSelection);
+ const started = Date.now();
+
+ for (const user of importSelection.users) {
+ const u = this.userMap.get(user.user_id);
+ u.do_import = user.do_import;
+
+ this.userMap.set(user.user_id, u);
+ }
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': Array.from(this.userMap.values()) }});
+
+ const startedByUserId = Meteor.userId();
+ Meteor.defer(() => {
+ super.updateProgress(ProgressStep.IMPORTING_USERS);
+
+ try {
+ for (const u of this.users.users) {
+ if (!u.do_import) {
+ continue;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email) || RocketChat.models.Users.findOneByUsername(u.username);
+
+ let userId;
+ if (existantUser) {
+ //since we have an existing user, let's try a few things
+ userId = existantUser._id;
+ u.rocketId = existantUser._id;
+ RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
+
+ RocketChat.models.Users.setEmail(existantUser._id, u.email);
+ RocketChat.models.Users.setEmailVerified(existantUser._id, u.email);
+ } else {
+ userId = Accounts.createUser({ username: u.username + Random.id(), password: Date.now() + u.name + u.email.toUpperCase() });
+
+ if (!userId) {
+ console.warn('An error happened while creating a user.');
+ return;
+ }
+
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
+ RocketChat.models.Users.setName(userId, u.name);
+ RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
+ RocketChat.models.Users.setEmail(userId, u.email);
+ RocketChat.models.Users.setEmailVerified(userId, u.email);
+ u.rocketId = userId;
+ });
+ }
+
+ if (this.admins.includes(u.user_id)) {
+ Meteor.call('setAdminStatus', userId, true);
+ }
+
+ super.addCountCompleted(1);
+ });
+ }
+
+ super.updateProgress(ProgressStep.FINISHING);
+ super.updateProgress(ProgressStep.DONE);
+ } catch (e) {
+ this.logger.error(e);
+ super.updateProgress(ProgressStep.ERROR);
+ }
+
+ const timeTook = Date.now() - started;
+ this.logger.log(`Slack Users Import took ${ timeTook } milliseconds.`);
+ });
+
+ return super.getProgress();
+ }
+}
diff --git a/packages/rocketchat-importer-slack/client/adder.js b/packages/rocketchat-importer-slack/client/adder.js
new file mode 100644
index 0000000000000..266bf8bc87dc0
--- /dev/null
+++ b/packages/rocketchat-importer-slack/client/adder.js
@@ -0,0 +1,4 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { SlackImporterInfo } from '../info';
+
+Importers.add(new SlackImporterInfo());
diff --git a/packages/rocketchat-importer-slack/info.js b/packages/rocketchat-importer-slack/info.js
new file mode 100644
index 0000000000000..18c914cdd166a
--- /dev/null
+++ b/packages/rocketchat-importer-slack/info.js
@@ -0,0 +1,7 @@
+import { ImporterInfo } from 'meteor/rocketchat:importer';
+
+export class SlackImporterInfo extends ImporterInfo {
+ constructor() {
+ super('slack', 'Slack', 'application/zip');
+ }
+}
diff --git a/packages/rocketchat-importer-slack/main.coffee b/packages/rocketchat-importer-slack/main.coffee
deleted file mode 100644
index da0518e538746..0000000000000
--- a/packages/rocketchat-importer-slack/main.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-Importer.addImporter 'slack', Importer.Slack,
- name: 'Slack'
- mimeType: 'application/zip'
diff --git a/packages/rocketchat-importer-slack/package.js b/packages/rocketchat-importer-slack/package.js
index e10bc401cca15..295a92000ff1f 100644
--- a/packages/rocketchat-importer-slack/package.js
+++ b/packages/rocketchat-importer-slack/package.js
@@ -8,11 +8,18 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'ecmascript',
- 'coffeescript',
'rocketchat:lib',
'rocketchat:importer'
]);
+
api.use('rocketchat:logger', 'server');
- api.addFiles('server.coffee', 'server');
- api.addFiles('main.coffee', ['client', 'server']);
+
+ // Importer information to both server and client
+ api.addFiles('info.js');
+
+ // Server files
+ api.addFiles(['server/importer.js', 'server/adder.js'], 'server');
+
+ // Client files
+ api.addFiles('client/adder.js', 'client');
});
diff --git a/packages/rocketchat-importer-slack/server.coffee b/packages/rocketchat-importer-slack/server.coffee
deleted file mode 100644
index 04ca574ac1a1f..0000000000000
--- a/packages/rocketchat-importer-slack/server.coffee
+++ /dev/null
@@ -1,373 +0,0 @@
-Importer.Slack = class Importer.Slack extends Importer.Base
- constructor: (name, descriptionI18N, mimeType) ->
- super(name, descriptionI18N, mimeType)
- @userTags = []
- @bots = {}
- @logger.debug('Constructed a new Slack Importer.')
-
- prepare: (dataURI, sentContentType, fileName) =>
- super(dataURI, sentContentType, fileName)
-
- {image, contentType} = RocketChatFile.dataURIParse dataURI
- zip = new @AdmZip(new Buffer(image, 'base64'))
- zipEntries = zip.getEntries()
-
- tempChannels = []
- tempUsers = []
- tempMessages = {}
- for entry in zipEntries
- do (entry) =>
- if entry.entryName.indexOf('__MACOSX') > -1
- #ignore all of the files inside of __MACOSX
- @logger.debug("Ignoring the file: #{entry.entryName}")
- else if entry.entryName == 'channels.json'
- @updateProgress Importer.ProgressStep.PREPARING_CHANNELS
- tempChannels = JSON.parse entry.getData().toString()
- tempChannels = tempChannels.filter (channel) -> channel.creator?
- else if entry.entryName == 'users.json'
- @updateProgress Importer.ProgressStep.PREPARING_USERS
- tempUsers = JSON.parse entry.getData().toString()
-
- for user in tempUsers when user.is_bot
- @bots[user.profile.bot_id] = user
-
- else if not entry.isDirectory and entry.entryName.indexOf('/') > -1
- item = entry.entryName.split('/') #random/2015-10-04.json
- channelName = item[0] #random
- msgGroupData = item[1].split('.')[0] #2015-10-04
- if not tempMessages[channelName]
- tempMessages[channelName] = {}
- # Catch files which aren't valid JSON files, ignore them
- try
- tempMessages[channelName][msgGroupData] = JSON.parse entry.getData().toString()
- catch
- @logger.warn "#{entry.entryName} is not a valid JSON file! Unable to import it."
-
- # Insert the users record, eventually this might have to be split into several ones as well
- # if someone tries to import a several thousands users instance
- usersId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'users', 'users': tempUsers }
- @users = @collection.findOne usersId
- @updateRecord { 'count.users': tempUsers.length }
- @addCountToTotal tempUsers.length
-
- # Insert the channels records.
- channelsId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'channels', 'channels': tempChannels }
- @channels = @collection.findOne channelsId
- @updateRecord { 'count.channels': tempChannels.length }
- @addCountToTotal tempChannels.length
-
- # Insert the messages records
- @updateProgress Importer.ProgressStep.PREPARING_MESSAGES
- messagesCount = 0
- for channel, messagesObj of tempMessages
- do (channel, messagesObj) =>
- if not @messages[channel]
- @messages[channel] = {}
- for date, msgs of messagesObj
- messagesCount += msgs.length
- @updateRecord { 'messagesstatus': "#{channel}/#{date}" }
-
- if Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize
- for splitMsg, i in Importer.Base.getBSONSafeArraysFromAnArray(msgs)
- messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}.#{i}", 'messages': splitMsg }
- @messages[channel]["#{date}.#{i}"] = @collection.findOne messagesId
- else
- messagesId = @collection.insert { 'import': @importRecord._id, 'importer': @name, 'type': 'messages', 'name': "#{channel}/#{date}", 'messages': msgs }
- @messages[channel][date] = @collection.findOne messagesId
-
- @updateRecord { 'count.messages': messagesCount, 'messagesstatus': null }
- @addCountToTotal messagesCount
-
- if tempUsers.length is 0 or tempChannels.length is 0 or messagesCount is 0
- @logger.warn "The loaded users count #{tempUsers.length}, the loaded channels #{tempChannels.length}, and the loaded messages #{messagesCount}"
- @updateProgress Importer.ProgressStep.ERROR
- return @getProgress()
-
- selectionUsers = tempUsers.map (user) ->
- return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot
- selectionChannels = tempChannels.map (channel) ->
- return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true, false
-
- @updateProgress Importer.ProgressStep.USER_SELECTION
- return new Importer.Selection @name, selectionUsers, selectionChannels
-
- startImport: (importSelection) =>
- super(importSelection)
- start = Date.now()
-
- for user in importSelection.users
- for u in @users.users when u.id is user.user_id
- u.do_import = user.do_import
- @collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
-
- for channel in importSelection.channels
- for c in @channels.channels when c.id is channel.channel_id
- c.do_import = channel.do_import
- @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
-
- startedByUserId = Meteor.userId()
- Meteor.defer =>
- @updateProgress Importer.ProgressStep.IMPORTING_USERS
- for user in @users.users when user.do_import
- do (user) =>
- Meteor.runAsUser startedByUserId, () =>
- existantUser = RocketChat.models.Users.findOneByEmailAddress user.profile.email
- if not existantUser
- existantUser = RocketChat.models.Users.findOneByUsername user.name
-
- if existantUser
- user.rocketId = existantUser._id
- RocketChat.models.Users.update { _id: user.rocketId }, { $addToSet: { importIds: user.id } }
- @userTags.push
- slack: "<@#{user.id}>"
- slackLong: "<@#{user.id}|#{user.name}>"
- rocket: "@#{existantUser.username}"
- else
- if user.profile.email
- userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }
- else
- userId = Accounts.createUser { username: user.name, password: Date.now() + user.name, joinDefaultChannelsSilenced: true }
- Meteor.runAsUser userId, () =>
- Meteor.call 'setUsername', user.name, {joinDefaultChannelsSilenced: true}
- url = null
- if user.profile.image_original
- url = user.profile.image_original
- else if user.profile.image_512
- url = user.profile.image_512
-
- try
- Meteor.call 'setAvatarFromService', url, undefined, 'url'
- catch error
- this.logger.warn "Failed to set #{user.name}'s avatar from url #{url}"
-
- # Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
- if user.tz_offset
- Meteor.call 'userSetUtcOffset', user.tz_offset / 3600
-
- RocketChat.models.Users.update { _id: userId }, { $addToSet: { importIds: user.id } }
-
- if user.profile.real_name
- RocketChat.models.Users.setName userId, user.profile.real_name
- #Deleted users are 'inactive' users in Rocket.Chat
- if user.deleted
- Meteor.call 'setUserActiveStatus', userId, false
- #TODO: Maybe send emails?
- user.rocketId = userId
- @userTags.push
- slack: "<@#{user.id}>"
- slackLong: "<@#{user.id}|#{user.name}>"
- rocket: "@#{user.name}"
- @addCountCompleted 1
- @collection.update { _id: @users._id }, { $set: { 'users': @users.users }}
-
- @updateProgress Importer.ProgressStep.IMPORTING_CHANNELS
- for channel in @channels.channels when channel.do_import
- do (channel) =>
- Meteor.runAsUser startedByUserId, () =>
- existantRoom = RocketChat.models.Rooms.findOneByName channel.name
- if existantRoom or channel.is_general
- if channel.is_general and channel.name isnt existantRoom?.name
- Meteor.call 'saveRoomSettings', 'GENERAL', 'roomName', channel.name
- channel.rocketId = if channel.is_general then 'GENERAL' else existantRoom._id
- RocketChat.models.Rooms.update { _id: channel.rocketId }, { $addToSet: { importIds: channel.id } }
- else
- users = []
- for member in channel.members when member isnt channel.creator
- user = @getRocketUser member
- if user?
- users.push user.username
-
- userId = startedByUserId
- for user in @users.users when user.id is channel.creator and user.do_import
- userId = user.rocketId
-
- Meteor.runAsUser userId, () =>
- returned = Meteor.call 'createChannel', channel.name, users
- channel.rocketId = returned.rid
-
- # @TODO implement model specific function
- roomUpdate =
- ts: new Date(channel.created * 1000)
-
- if not _.isEmpty channel.topic?.value
- roomUpdate.topic = channel.topic.value
-
- if not _.isEmpty(channel.purpose?.value)
- roomUpdate.description = channel.purpose.value
-
- RocketChat.models.Rooms.update { _id: channel.rocketId }, { $set: roomUpdate, $addToSet: { importIds: channel.id } }
-
- @addCountCompleted 1
- @collection.update { _id: @channels._id }, { $set: { 'channels': @channels.channels }}
-
- missedTypes = {}
- ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true }
- @updateProgress Importer.ProgressStep.IMPORTING_MESSAGES
- for channel, messagesObj of @messages
- do (channel, messagesObj) =>
- Meteor.runAsUser startedByUserId, () =>
- slackChannel = @getSlackChannelFromName channel
- if slackChannel?.do_import
- room = RocketChat.models.Rooms.findOneById slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } }
- for date, msgs of messagesObj
- @updateRecord { 'messagesstatus': "#{channel}/#{date}.#{msgs.messages.length}" }
- for message in msgs.messages
- msgDataDefaults =
- _id: "slack-#{slackChannel.id}-#{message.ts.replace(/\./g, '-')}"
- ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
-
- if message.type is 'message'
- if message.subtype?
- if message.subtype is 'channel_join'
- if @getRocketUser(message.user)?
- RocketChat.models.Messages.createUserJoinWithRoomIdAndUser room._id, @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'channel_leave'
- if @getRocketUser(message.user)?
- RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser room._id, @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'me_message'
- msgObj =
- msg: "_#{@convertSlackMessageToRocketChat(message.text)}_"
- _.extend msgObj, msgDataDefaults
- RocketChat.sendMessage @getRocketUser(message.user), msgObj, room, true
- else if message.subtype is 'bot_message' or message.subtype is 'slackbot_response'
- botUser = RocketChat.models.Users.findOneById 'rocket.cat', { fields: { username: 1 }}
- botUsername = if @bots[message.bot_id] then @bots[message.bot_id]?.name else message.username
- msgObj =
- msg: @convertSlackMessageToRocketChat(message.text)
- rid: room._id
- bot: true
- attachments: message.attachments
- username: if botUsername then botUsername else undefined
-
- _.extend msgObj, msgDataDefaults
-
- if message.edited?
- msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
- editedBy = @getRocketUser(message.edited.user)
- if editedBy?
- msgObj.editedBy =
- _id: editedBy._id
- username: editedBy.username
-
- if message.icons?
- msgObj.emoji = message.icons.emoji
-
- RocketChat.sendMessage botUser, msgObj, room, true
- else if message.subtype is 'channel_purpose'
- if @getRocketUser(message.user)?
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_description', room._id, message.purpose, @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'channel_topic'
- if @getRocketUser(message.user)?
- RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_topic', room._id, message.topic, @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'channel_name'
- if @getRocketUser(message.user)?
- RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser room._id, message.name, @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'pinned_item'
- if message.attachments
- msgObj =
- attachments: [
- "text" : @convertSlackMessageToRocketChat message.attachments[0].text
- "author_name" : message.attachments[0].author_subname
- "author_icon" : getAvatarUrlFromUsername(message.attachments[0].author_subname)
- ]
- _.extend msgObj, msgDataDefaults
- RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), msgObj
- else
- #TODO: make this better
- @logger.debug('Pinned item with no attachment, needs work.');
- #RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), msgDataDefaults
- else if message.subtype is 'file_share'
- if message.file?.url_private_download isnt undefined
- details =
- message_id: "slack-#{message.ts.replace(/\./g, '-')}"
- name: message.file.name
- size: message.file.size
- type: message.file.mimetype
- rid: room._id
- @uploadFile details, message.file.url_private_download, @getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000)
- else
- if not missedTypes[message.subtype] and not ignoreTypes[message.subtype]
- missedTypes[message.subtype] = message
- else
- user = @getRocketUser(message.user)
- if user?
- msgObj =
- msg: @convertSlackMessageToRocketChat message.text
- rid: room._id
- u:
- _id: user._id
- username: user.username
-
- _.extend msgObj, msgDataDefaults
-
- if message.edited?
- msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000)
- editedBy = @getRocketUser(message.edited.user)
- if editedBy?
- msgObj.editedBy =
- _id: editedBy._id
- username: editedBy.username
-
- RocketChat.sendMessage @getRocketUser(message.user), msgObj, room, true
-
- # Process the reactions
- if RocketChat.models.Messages.findOneById(msgDataDefaults._id)? and message.reactions?.length > 0
- for reaction in message.reactions
- for u in reaction.users
- rcUser = @getRocketUser(u)
- if rcUser?
- Meteor.runAsUser rcUser._id, () =>
- Meteor.call 'setReaction', ":#{reaction.name}:", msgDataDefaults._id
-
- @addCountCompleted 1
-
- if not _.isEmpty missedTypes
- console.log 'Missed import types:', missedTypes
-
- @updateProgress Importer.ProgressStep.FINISHING
- for channel in @channels.channels when channel.do_import and channel.is_archived
- do (channel) =>
- Meteor.runAsUser startedByUserId, () =>
- Meteor.call 'archiveRoom', channel.rocketId
-
- @updateProgress Importer.ProgressStep.DONE
- timeTook = Date.now() - start
- @logger.log "Import took #{timeTook} milliseconds."
-
- return @getProgress()
-
- getSlackChannelFromName: (channelName) =>
- for channel in @channels.channels when channel.name is channelName
- return channel
-
- getRocketUser: (slackId) =>
- for user in @users.users when user.id is slackId
- return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1 }}
-
- convertSlackMessageToRocketChat: (message) =>
- if message?
- message = message.replace //g, '@all'
- message = message.replace //g, '@all'
- message = message.replace //g, '@here'
- message = message.replace />/g, '>'
- message = message.replace /</g, '<'
- message = message.replace /&/g, '&'
- message = message.replace /:simple_smile:/g, ':smile:'
- message = message.replace /:memo:/g, ':pencil:'
- message = message.replace /:piggy:/g, ':pig:'
- message = message.replace /:uk:/g, ':gb:'
- message = message.replace /<(http[s]?:[^>]*)>/g, '$1'
- for userReplace in @userTags
- message = message.replace userReplace.slack, userReplace.rocket
- message = message.replace userReplace.slackLong, userReplace.rocket
- else
- message = ''
- return message
-
- getSelection: () =>
- selectionUsers = @users.users.map (user) ->
- return new Importer.SelectionUser user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot
- selectionChannels = @channels.channels.map (channel) ->
- return new Importer.SelectionChannel channel.id, channel.name, channel.is_archived, true, false
-
- return new Importer.Selection @name, selectionUsers, selectionChannels
diff --git a/packages/rocketchat-importer-slack/server/adder.js b/packages/rocketchat-importer-slack/server/adder.js
new file mode 100644
index 0000000000000..5ba0219863ace
--- /dev/null
+++ b/packages/rocketchat-importer-slack/server/adder.js
@@ -0,0 +1,5 @@
+import { Importers } from 'meteor/rocketchat:importer';
+import { SlackImporterInfo } from '../info';
+import { SlackImporter } from './importer';
+
+Importers.add(new SlackImporterInfo(), SlackImporter);
diff --git a/packages/rocketchat-importer-slack/server/importer.js b/packages/rocketchat-importer-slack/server/importer.js
new file mode 100644
index 0000000000000..d5ff5d5dc4046
--- /dev/null
+++ b/packages/rocketchat-importer-slack/server/importer.js
@@ -0,0 +1,497 @@
+import {
+ Base,
+ ProgressStep,
+ Selection,
+ SelectionChannel,
+ SelectionUser
+} from 'meteor/rocketchat:importer';
+
+import _ from 'underscore';
+
+export class SlackImporter extends Base {
+ constructor(info) {
+ super(info);
+ this.userTags = [];
+ this.bots = {};
+ }
+
+ prepare(dataURI, sentContentType, fileName) {
+ super.prepare(dataURI, sentContentType, fileName);
+
+ const { image } = RocketChatFile.dataURIParse(dataURI);
+ const zip = new this.AdmZip(new Buffer(image, 'base64'));
+ const zipEntries = zip.getEntries();
+
+ let tempChannels = [];
+ let tempUsers = [];
+ const tempMessages = {};
+
+ zipEntries.forEach(entry => {
+ if (entry.entryName.indexOf('__MACOSX') > -1) {
+ return this.logger.debug(`Ignoring the file: ${ entry.entryName }`);
+ }
+
+ if (entry.entryName === 'channels.json') {
+ super.updateProgress(ProgressStep.PREPARING_CHANNELS);
+ tempChannels = JSON.parse(entry.getData().toString()).filter(channel => channel.creator != null);
+ return;
+ }
+
+ if (entry.entryName === 'users.json') {
+ super.updateProgress(ProgressStep.PREPARING_USERS);
+ tempUsers = JSON.parse(entry.getData().toString());
+
+ tempUsers.forEach(user => {
+ if (user.is_bot) {
+ this.bots[user.profile.bot_id] = user;
+ }
+ });
+
+ return;
+ }
+
+ if (!entry.isDirectory && entry.entryName.indexOf('/') > -1) {
+ const item = entry.entryName.split('/');
+ const channelName = item[0];
+ const msgGroupData = item[1].split('.')[0];
+ tempMessages[channelName] = tempMessages[channelName] || {};
+
+ try {
+ tempMessages[channelName][msgGroupData] = JSON.parse(entry.getData().toString());
+ } catch (error) {
+ this.logger.warn(`${ entry.entryName } is not a valid JSON file! Unable to import it.`);
+ }
+ }
+ });
+
+ // Insert the users record, eventually this might have to be split into several ones as well
+ // if someone tries to import a several thousands users instance
+ const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
+ this.users = this.collection.findOne(usersId);
+ this.updateRecord({ 'count.users': tempUsers.length });
+ this.addCountToTotal(tempUsers.length);
+
+ // Insert the channels records.
+ const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempChannels });
+ this.channels = this.collection.findOne(channelsId);
+ this.updateRecord({ 'count.channels': tempChannels.length });
+ this.addCountToTotal(tempChannels.length);
+
+ // Insert the messages records
+ super.updateProgress(ProgressStep.PREPARING_MESSAGES);
+
+ let messagesCount = 0;
+ Object.keys(tempMessages).forEach(channel => {
+ const messagesObj = tempMessages[channel];
+ this.messages[channel] = this.messages[channel] || {};
+
+ Object.keys(messagesObj).forEach(date => {
+ const msgs = messagesObj[date];
+ messagesCount += msgs.length;
+ this.updateRecord({ 'messagesstatus': `${ channel }/${ date }` });
+ if (Base.getBSONSize(msgs) > Base.getMaxBSONSize()) {
+ const tmp = Base.getBSONSafeArraysFromAnArray(msgs);
+ Object.keys(tmp).forEach(i => {
+ const splitMsg = tmp[i];
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }/${ date }.${ i }`, 'messages': splitMsg });
+ this.messages[channel][`${ date }.${ i }`] = this.collection.findOne(messagesId);
+ });
+ } else {
+ const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${ channel }/${ date }`, 'messages': msgs });
+ this.messages[channel][date] = this.collection.findOne(messagesId);
+ }
+ });
+ });
+
+ this.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
+ this.addCountToTotal(messagesCount);
+
+ if ([tempUsers.length, tempChannels.length, messagesCount].some(e => e === 0)) {
+ this.logger.warn(`The loaded users count ${ tempUsers.length }, the loaded channels ${ tempChannels.length }, and the loaded messages ${ messagesCount }`);
+ console.log(`The loaded users count ${ tempUsers.length }, the loaded channels ${ tempChannels.length }, and the loaded messages ${ messagesCount }`);
+ super.updateProgress(ProgressStep.ERROR);
+ return this.getProgress();
+ }
+
+ const selectionUsers = tempUsers.map(user => new SelectionUser(user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot));
+ const selectionChannels = tempChannels.map(channel => new SelectionChannel(channel.id, channel.name, channel.is_archived, true, false));
+ const selectionMessages = this.importRecord.count.messages;
+ super.updateProgress(ProgressStep.USER_SELECTION);
+
+ return new Selection(this.name, selectionUsers, selectionChannels, selectionMessages);
+ }
+
+ startImport(importSelection) {
+ super.startImport(importSelection);
+ const start = Date.now();
+
+ Object.keys(importSelection.users).forEach(key => {
+ const user = importSelection.users[key];
+ Object.keys(this.users.users).forEach(k => {
+ const u = this.users.users[k];
+ if (u.id === user.user_id) {
+ u.do_import = user.do_import;
+ }
+ });
+ });
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ Object.keys(importSelection.channels).forEach(key => {
+ const channel = importSelection.channels[key];
+ Object.keys(this.channels.channels).forEach(k => {
+ const c = this.channels.channels[k];
+ if (c.id === channel.channel_id) {
+ c.do_import = channel.do_import;
+ }
+ });
+ });
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ const startedByUserId = Meteor.userId();
+ Meteor.defer(() => {
+ try {
+ super.updateProgress(ProgressStep.IMPORTING_USERS);
+ this.users.users.forEach(user => {
+ if (!user.do_import) {
+ return;
+ }
+
+ Meteor.runAsUser(startedByUserId, () => {
+ const existantUser = RocketChat.models.Users.findOneByEmailAddress(user.profile.email) || RocketChat.models.Users.findOneByUsername(user.name);
+ if (existantUser) {
+ user.rocketId = existantUser._id;
+ RocketChat.models.Users.update({ _id: user.rocketId }, { $addToSet: { importIds: user.id } });
+ this.userTags.push({
+ slack: `<@${ user.id }>`,
+ slackLong: `<@${ user.id }|${ user.name }>`,
+ rocket: `@${ existantUser.username }`
+ });
+ } else {
+ const userId = user.profile.email ? Accounts.createUser({ email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }) : Accounts.createUser({ username: user.name, password: Date.now() + user.name, joinDefaultChannelsSilenced: true });
+ Meteor.runAsUser(userId, () => {
+ Meteor.call('setUsername', user.name, { joinDefaultChannelsSilenced: true });
+
+ const url = user.profile.image_original || user.profile.image_512;
+ try {
+ Meteor.call('setAvatarFromService', url, undefined, 'url');
+ } catch (error) {
+ this.logger.warn(`Failed to set ${ user.name }'s avatar from url ${ url }`);
+ console.log(`Failed to set ${ user.name }'s avatar from url ${ url }`);
+ }
+
+ // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600
+ if (user.tz_offset) {
+ Meteor.call('userSetUtcOffset', user.tz_offset / 3600);
+ }
+ });
+
+ RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: user.id } });
+
+ if (user.profile.real_name) {
+ RocketChat.models.Users.setName(userId, user.profile.real_name);
+ }
+
+ //Deleted users are 'inactive' users in Rocket.Chat
+ if (user.deleted) {
+ Meteor.call('setUserActiveStatus', userId, false);
+ }
+
+ user.rocketId = userId;
+ this.userTags.push({
+ slack: `<@${ user.id }>`,
+ slackLong: `<@${ user.id }|${ user.name }>`,
+ rocket: `@${ user.name }`
+ });
+ }
+
+ this.addCountCompleted(1);
+ });
+ });
+ this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+ super.updateProgress(ProgressStep.IMPORTING_CHANNELS);
+ this.channels.channels.forEach(channel => {
+ if (!channel.do_import) {
+ return;
+ }
+
+ Meteor.runAsUser (startedByUserId, () => {
+ const existantRoom = RocketChat.models.Rooms.findOneByName(channel.name);
+ if (existantRoom || channel.is_general) {
+ if (channel.is_general && existantRoom && channel.name !== existantRoom.name) {
+ Meteor.call('saveRoomSettings', 'GENERAL', 'roomName', channel.name);
+ }
+
+ channel.rocketId = channel.is_general ? 'GENERAL' : existantRoom._id;
+ RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $addToSet: { importIds: channel.id } });
+ } else {
+ const users = channel.members
+ .reduce((ret, member) => {
+ if (member !== channel.creator) {
+ const user = this.getRocketUser(member);
+ if (user && user.username) {
+ ret.push(user.username);
+ }
+ }
+ return ret;
+ }, []);
+ let userId = startedByUserId;
+ this.users.users.forEach(user => {
+ if (user.id === channel.creator && user.do_import) {
+ userId = user.rocketId;
+ }
+ });
+ Meteor.runAsUser(userId, () => {
+ const returned = Meteor.call('createChannel', channel.name, users);
+ channel.rocketId = returned.rid;
+ });
+
+ // @TODO implement model specific function
+ const roomUpdate = {
+ ts: new Date(channel.created * 1000)
+ };
+ if (!_.isEmpty(channel.topic && channel.topic.value)) {
+ roomUpdate.topic = channel.topic.value;
+ }
+ if (!_.isEmpty(channel.purpose && channel.purpose.value)) {
+ roomUpdate.description = channel.purpose.value;
+ }
+ RocketChat.models.Rooms.update({ _id: channel.rocketId }, { $set: roomUpdate, $addToSet: { importIds: channel.id } });
+ }
+ this.addCountCompleted(1);
+ });
+ });
+ this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+ const missedTypes = {};
+ const ignoreTypes = { 'bot_add': true, 'file_comment': true, 'file_mention': true };
+ super.updateProgress(ProgressStep.IMPORTING_MESSAGES);
+ Object.keys(this.messages).forEach(channel => {
+ const messagesObj = this.messages[channel];
+
+ Meteor.runAsUser(startedByUserId, () =>{
+ const slackChannel = this.getSlackChannelFromName(channel);
+ if (!slackChannel || !slackChannel.do_import) { return; }
+ const room = RocketChat.models.Rooms.findOneById(slackChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
+ Object.keys(messagesObj).forEach(date => {
+ const msgs = messagesObj[date];
+ msgs.messages.forEach(message => {
+ this.updateRecord({ 'messagesstatus': `${ channel }/${ date }.${ msgs.messages.length }` });
+ const msgDataDefaults ={
+ _id: `slack-${ slackChannel.id }-${ message.ts.replace(/\./g, '-') }`,
+ ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
+ };
+
+ // Process the reactions
+ if (message.reactions && message.reactions.length > 0) {
+ msgDataDefaults.reactions = {};
+
+ message.reactions.forEach(reaction => {
+ reaction.name = `:${ reaction.name }:`;
+ msgDataDefaults.reactions[reaction.name] = { usernames: [] };
+
+ reaction.users.forEach(u => {
+ const rcUser = this.getRocketUser(u);
+ if (!rcUser) { return; }
+
+ msgDataDefaults.reactions[reaction.name].usernames.push(rcUser.username);
+ });
+
+ if (msgDataDefaults.reactions[reaction.name].usernames.length === 0) {
+ delete msgDataDefaults.reactions[reaction.name];
+ }
+ });
+ }
+
+ if (message.type === 'message') {
+ if (message.subtype) {
+ if (message.subtype === 'channel_join') {
+ if (this.getRocketUser(message.user)) {
+ RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults);
+ }
+ } else if (message.subtype === 'channel_leave') {
+ if (this.getRocketUser(message.user)) {
+ RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, this.getRocketUser(message.user), msgDataDefaults);
+ }
+ } else if (message.subtype === 'me_message') {
+ const msgObj = {
+ ...msgDataDefaults,
+ msg: `_${ this.convertSlackMessageToRocketChat(message.text) }_`
+ };
+ RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true);
+ } else if (message.subtype === 'bot_message' || message.subtype === 'slackbot_response') {
+ const botUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 }});
+ const botUsername = this.bots[message.bot_id] ? this.bots[message.bot_id].name : message.username;
+ const msgObj = {
+ ...msgDataDefaults,
+ msg: this.convertSlackMessageToRocketChat(message.text),
+ rid: room._id,
+ bot: true,
+ attachments: message.attachments,
+ username: botUsername || undefined
+ };
+
+ if (message.edited) {
+ msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000);
+ const editedBy = this.getRocketUser(message.edited.user);
+ if (editedBy) {
+ msgObj.editedBy = {
+ _id: editedBy._id,
+ username: editedBy.username
+ };
+ }
+ }
+
+ if (message.icons) {
+ msgObj.emoji = message.icons.emoji;
+ }
+ RocketChat.sendMessage(botUser, msgObj, room, true);
+ } else if (message.subtype === 'channel_purpose') {
+ if (this.getRocketUser(message.user)) {
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_description', room._id, message.purpose, this.getRocketUser(message.user), msgDataDefaults);
+ }
+ } else if (message.subtype === 'channel_topic') {
+ if (this.getRocketUser(message.user)) {
+ RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, message.topic, this.getRocketUser(message.user), msgDataDefaults);
+ }
+ } else if (message.subtype === 'channel_name') {
+ if (this.getRocketUser(message.user)) {
+ RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(room._id, message.name, this.getRocketUser(message.user), msgDataDefaults);
+ }
+ } else if (message.subtype === 'pinned_item') {
+ if (message.attachments) {
+ const msgObj = {
+ ...msgDataDefaults,
+ attachments: [{
+ 'text': this.convertSlackMessageToRocketChat(message.attachments[0].text),
+ 'author_name' : message.attachments[0].author_subname,
+ 'author_icon' : getAvatarUrlFromUsername(message.attachments[0].author_subname)
+ }]
+ };
+ RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('message_pinned', room._id, '', this.getRocketUser(message.user), msgObj);
+ } else {
+ //TODO: make this better
+ this.logger.debug('Pinned item with no attachment, needs work.');
+ //RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', room._id, '', @getRocketUser(message.user), msgDataDefaults
+ }
+ } else if (message.subtype === 'file_share') {
+ if (message.file && message.file.url_private_download !== undefined) {
+ const details = {
+ message_id: `slack-${ message.ts.replace(/\./g, '-') }`,
+ name: message.file.name,
+ size: message.file.size,
+ type: message.file.mimetype,
+ rid: room._id
+ };
+ this.uploadFile(details, message.file.url_private_download, this.getRocketUser(message.user), room, new Date(parseInt(message.ts.split('.')[0]) * 1000));
+ }
+ } else if (!missedTypes[message.subtype] && !ignoreTypes[message.subtype]) {
+ missedTypes[message.subtype] = message;
+ }
+ } else {
+ const user = this.getRocketUser(message.user);
+ if (user) {
+ const msgObj = {
+ ...msgDataDefaults,
+ msg: this.convertSlackMessageToRocketChat(message.text),
+ rid: room._id,
+ u: {
+ _id: user._id,
+ username: user.username
+ }
+ };
+
+ if (message.edited) {
+ msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000);
+ const editedBy = this.getRocketUser(message.edited.user);
+ if (editedBy) {
+ msgObj.editedBy = {
+ _id: editedBy._id,
+ username: editedBy.username
+ };
+ }
+ }
+
+ try {
+ RocketChat.sendMessage(this.getRocketUser(message.user), msgObj, room, true);
+ } catch (e) {
+ this.logger.warn(`Failed to import the message: ${ msgDataDefaults._id }`);
+ }
+ }
+ }
+ }
+
+ this.addCountCompleted(1);
+ });
+ });
+ });
+ });
+
+ if (!_.isEmpty(missedTypes)) {
+ console.log('Missed import types:', missedTypes);
+ }
+
+ super.updateProgress(ProgressStep.FINISHING);
+
+ this.channels.channels.forEach(channel => {
+ if (channel.do_import && channel.is_archived) {
+ Meteor.runAsUser(startedByUserId, function() {
+ Meteor.call('archiveRoom', channel.rocketId);
+ });
+ }
+ });
+ super.updateProgress(ProgressStep.DONE);
+
+ this.logger.log(`Import took ${ Date.now() - start } milliseconds.`);
+ } catch (e) {
+ this.logger.error(e);
+ super.updateProgress(ProgressStep.ERROR);
+ }
+ });
+
+ return this.getProgress();
+ }
+
+ getSlackChannelFromName(channelName) {
+ return this.channels.channels.find(channel => channel.name === channelName);
+ }
+
+ getRocketUser(slackId) {
+ const user = this.users.users.find(user => user.id === slackId);
+
+ if (user) {
+ return RocketChat.models.Users.findOneById(user.rocketId, { fields: { username: 1, name: 1 }});
+ }
+ }
+
+ convertSlackMessageToRocketChat(message) {
+ if (message) {
+ message = message.replace(//g, '@all');
+ message = message.replace(//g, '@all');
+ message = message.replace(//g, '@here');
+ message = message.replace(/>/g, '>');
+ message = message.replace(/</g, '<');
+ message = message.replace(/&/g, '&');
+ message = message.replace(/:simple_smile:/g, ':smile:');
+ message = message.replace(/:memo:/g, ':pencil:');
+ message = message.replace(/:piggy:/g, ':pig:');
+ message = message.replace(/:uk:/g, ':gb:');
+ message = message.replace(/<(http[s]?:[^>]*)>/g, '$1');
+
+ for (const userReplace of Array.from(this.userTags)) {
+ message = message.replace(userReplace.slack, userReplace.rocket);
+ message = message.replace(userReplace.slackLong, userReplace.rocket);
+ }
+ } else {
+ message = '';
+ }
+
+ return message;
+ }
+
+ getSelection() {
+ const selectionUsers = this.users.users.map(user => new SelectionUser(user.id, user.name, user.profile.email, user.deleted, user.is_bot, !user.is_bot));
+ const selectionChannels = this.channels.channels.map(channel => new SelectionChannel(channel.id, channel.name, channel.is_archived, true, false));
+ return new Selection(this.name, selectionUsers, selectionChannels, this.importRecord.count.messages);
+ }
+}
diff --git a/packages/rocketchat-importer/.npm/package/.gitignore b/packages/rocketchat-importer/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-importer/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-importer/.npm/package/README b/packages/rocketchat-importer/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-importer/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 238dae99d6986..0000000000000
--- a/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "dependencies": {
- "adm-zip": {
- "version": "0.4.7",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz",
- "from": "adm-zip@0.4.7"
- },
- "bson": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.5.tgz",
- "from": "bson@0.5.5"
- },
- "file-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.0.0.tgz",
- "from": "file-type@4.0.0"
- }
- }
-}
diff --git a/packages/rocketchat-importer/client/ImporterWebsocketReceiver.js b/packages/rocketchat-importer/client/ImporterWebsocketReceiver.js
new file mode 100644
index 0000000000000..1152389f871ec
--- /dev/null
+++ b/packages/rocketchat-importer/client/ImporterWebsocketReceiver.js
@@ -0,0 +1,29 @@
+class ImporterWebsocketReceiverDef {
+ constructor() {
+ this.streamer = new Meteor.Streamer('importers');
+
+ this.callbacks = [];
+ this.streamer.on('progress', this.progressUpdated.bind(this));
+ }
+
+ progressUpdated(progress) {
+ this.callbacks.forEach((c) => c(progress));
+ }
+
+ registerCallback(callback) {
+ if (typeof callback !== 'function') {
+ throw new Error('Callback must be a function.');
+ }
+
+ this.callbacks.push(callback);
+ }
+
+ unregisterCallback(callback) {
+ const i = this.callbacks.indexOf(callback);
+ if (i >= 0) {
+ this.callbacks.splice(i, 1);
+ }
+ }
+}
+
+export const ImporterWebsocketReceiver = new ImporterWebsocketReceiverDef();
diff --git a/packages/rocketchat-importer/client/admin/adminImport.coffee b/packages/rocketchat-importer/client/admin/adminImport.coffee
deleted file mode 100644
index c4a8506248e46..0000000000000
--- a/packages/rocketchat-importer/client/admin/adminImport.coffee
+++ /dev/null
@@ -1,24 +0,0 @@
-Template.adminImport.helpers
- isAdmin: ->
- return RocketChat.authz.hasRole(Meteor.userId(), 'admin')
- isImporters: ->
- return Object.keys(Importer.Importers).length > 0
- getDescription: (importer) ->
- return TAPi18n.__('Importer_From_Description', { from: importer.name })
- importers: ->
- importers = []
- _.each Importer.Importers, (importer, key) ->
- importer.key = key
- importers.push importer
- return importers
-
-Template.adminImport.events
- 'click .start-import': (event) ->
- importer = @
-
- Meteor.call 'setupImporter', importer.key, (error, data) ->
- if error
- console.log t('importer_setup_error'), importer.key, error
- return handleError(error)
- else
- FlowRouter.go '/admin/import/prepare/' + importer.key
diff --git a/packages/rocketchat-importer/client/admin/adminImport.html b/packages/rocketchat-importer/client/admin/adminImport.html
index 3e22cbcbc29db..1d5d3126f69ba 100644
--- a/packages/rocketchat-importer/client/admin/adminImport.html
+++ b/packages/rocketchat-importer/client/admin/adminImport.html
@@ -1,32 +1,23 @@
-
- {{> burger}}
-
- Import
-
-
+ {{> header sectionName="Import"}}
{{#unless isAdmin}}
-
You are not authorized to view this page.
+
{{_ "You_are_not_authorized_to_view_this_page"}}
{{else}}
- {{#if isImporters}}
- {{else}}
- No Importers Available
- {{/if}}
{{/unless}}
diff --git a/packages/rocketchat-importer/client/admin/adminImport.js b/packages/rocketchat-importer/client/admin/adminImport.js
new file mode 100644
index 0000000000000..0441904fda6e5
--- /dev/null
+++ b/packages/rocketchat-importer/client/admin/adminImport.js
@@ -0,0 +1,29 @@
+import { Importers } from 'meteor/rocketchat:importer';
+
+Template.adminImport.helpers({
+ isAdmin() {
+ return RocketChat.authz.hasRole(Meteor.userId(), 'admin');
+ },
+ getDescription(importer) {
+ return TAPi18n.__('Importer_From_Description', { from: importer.name });
+ },
+ importers() {
+ return Importers.getAll();
+ }
+});
+
+Template.adminImport.events({
+ 'click .start-import'() {
+ const importer = this;
+
+ Meteor.call('setupImporter', importer.key, function(error) {
+ if (error) {
+ console.log(t('importer_setup_error'), importer.key, error);
+ handleError(error);
+ return;
+ }
+
+ FlowRouter.go(`/admin/import/prepare/${ importer.key }`);
+ });
+ }
+});
diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee b/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee
deleted file mode 100644
index 823418efed047..0000000000000
--- a/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee
+++ /dev/null
@@ -1,152 +0,0 @@
-import toastr from 'toastr'
-Template.adminImportPrepare.helpers
- isAdmin: ->
- return RocketChat.authz.hasRole(Meteor.userId(), 'admin')
- importer: ->
- importerKey = FlowRouter.getParam('importer')
- importer = undefined
- _.each Importer.Importers, (i, key) ->
- i.key = key
- if key == importerKey
- importer = i
-
- return importer
- isLoaded: ->
- return Template.instance().loaded.get()
- isPreparing: ->
- return Template.instance().preparing.get()
- users: ->
- return Template.instance().users.get()
- channels: ->
- return Template.instance().channels.get()
-
-Template.adminImportPrepare.events
- 'change .import-file-input': (event, template) ->
- importer = @
- return if not importer.key
-
- e = event.originalEvent or event
- files = e.target.files
- if not files or files.length is 0
- files = e.dataTransfer?.files or []
-
- for blob in files
- template.preparing.set true
-
- reader = new FileReader()
- reader.readAsDataURL(blob)
- reader.onloadend = ->
- Meteor.call 'prepareImport', importer.key, reader.result, blob.type, blob.name, (error, data) ->
- if error
- toastr.error t('Invalid_Import_File_Type')
- template.preparing.set false
- return
-
- if !data
- console.warn 'The importer ' + importer.key + ' is not set up correctly, as it did not return any data.'
- toastr.error t('Importer_not_setup')
- template.preparing.set false
- return
-
- if data.step
- console.warn 'Invalid file, contains `data.step`.', data
- toastr.error t('Invalid_Export_File', importer.key)
- template.preparing.set false
- return
-
- template.users.set data.users
- template.channels.set data.channels
- template.loaded.set true
- template.preparing.set false
-
- 'click .button.start': (event, template) ->
- btn = this
- $(btn).prop "disabled", true
- importer = @
- for user in template.users.get()
- user.do_import = $("[name=#{user.user_id}]").is(':checked')
-
- for channel in template.channels.get()
- channel.do_import = $("[name=#{channel.channel_id}]").is(':checked')
-
- Meteor.call 'startImport', FlowRouter.getParam('importer'), { users: template.users.get(), channels: template.channels.get() }, (error, data) ->
- if error
- console.warn 'Error on starting the import:', error
- return handleError(error)
- else
- FlowRouter.go '/admin/import/progress/' + FlowRouter.getParam('importer')
-
- 'click .button.restart': (event, template) ->
- Meteor.call 'restartImport', FlowRouter.getParam('importer'), (error, data) ->
- if error
- console.warn 'Error while restarting the import:', error
- handleError(error)
- return
-
- template.users.set []
- template.channels.set []
- template.loaded.set false
-
- 'click .button.uncheck-deleted-users': (event, template) ->
- for user in template.users.get() when user.is_deleted
- $("[name=#{user.user_id}]").attr('checked', false);
-
- 'click .button.uncheck-archived-channels': (event, template) ->
- for channel in template.channels.get() when channel.is_archived
- $("[name=#{channel.channel_id}]").attr('checked', false);
-
-
-Template.adminImportPrepare.onCreated ->
- instance = @
- @preparing = new ReactiveVar true
- @loaded = new ReactiveVar false
- @users = new ReactiveVar []
- @channels = new ReactiveVar []
-
- loadSelection = (progress) ->
- if progress?.step
- switch progress.step
- #When the import is running, take the user to the progress page
- when 'importer_importing_started', 'importer_importing_users', 'importer_importing_channels', 'importer_importing_messages', 'importer_finishing'
- FlowRouter.go '/admin/import/progress/' + FlowRouter.getParam('importer')
- # when the import is done, restart it (new instance)
- when 'importer_user_selection'
- Meteor.call 'getSelectionData', FlowRouter.getParam('importer'), (error, data) ->
- if error
- handleError error
- instance.users.set data.users
- instance.channels.set data.channels
- instance.loaded.set true
- instance.preparing.set false
- when 'importer_new'
- instance.preparing.set false
- else
- Meteor.call 'restartImport', FlowRouter.getParam('importer'), (error, progress) ->
- if error
- handleError(error)
- loadSelection(progress)
- else
- console.warn 'Invalid progress information.', progress
-
- # Load the initial progress to determine what we need to do
- if FlowRouter.getParam('importer')
- Meteor.call 'getImportProgress', FlowRouter.getParam('importer'), (error, progress) ->
- if error
- console.warn 'Error while getting the import progress:', error
- handleError error
- return
-
- # if the progress isnt defined, that means there currently isn't an instance
- # of the importer, so we need to create it
- if progress is undefined
- Meteor.call 'setupImporter', FlowRouter.getParam('importer'), (err, data) ->
- if err
- handleError(err)
- instance.preparing.set false
- loadSelection(data)
- else
- # Otherwise, we might need to do something based upon the current step
- # of the import
- loadSelection(progress)
- else
- FlowRouter.go '/admin/import'
diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.html b/packages/rocketchat-importer/client/admin/adminImportPrepare.html
index cac461eb89e7b..72e3d05baf78d 100644
--- a/packages/rocketchat-importer/client/admin/adminImportPrepare.html
+++ b/packages/rocketchat-importer/client/admin/adminImportPrepare.html
@@ -1,15 +1,10 @@
You can directly reply to this email. Do not modify previous emails in the thread. Powered by Rocket.Chat ', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Footer_Direct_Reply'
+ });
+ });
+ this.section('Direct_Reply', function() {
+ this.add('Direct_Reply_Enable', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Enable'
+ });
+ this.add('Direct_Reply_Debug', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Debug',
+ i18nDescription: 'Direct_Reply_Debug_Description'
+ });
+ this.add('Direct_Reply_Protocol', 'IMAP', {
+ type: 'select',
+ values: [
+ {
+ key: 'IMAP',
+ i18nLabel: 'IMAP'
+ }, {
+ key: 'POP',
+ i18nLabel: 'POP'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Protocol'
+ });
+ this.add('Direct_Reply_Host', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Host'
+ });
+ this.add('Direct_Reply_Port', '143', {
+ type: 'select',
+ values: [
+ {
+ key: '143',
+ i18nLabel: '143'
+ }, {
+ key: '993',
+ i18nLabel: '993'
+ }, {
+ key: '110',
+ i18nLabel: '110'
+ }, {
+ key: '995',
+ i18nLabel: '995'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Port'
+ });
+ this.add('Direct_Reply_IgnoreTLS', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'IgnoreTLS'
+ });
+ this.add('Direct_Reply_Frequency', 5, {
+ type: 'int',
+ env: true,
+ i18nLabel: 'Direct_Reply_Frequency',
+ enableQuery: {
+ _id: 'Direct_Reply_Protocol',
+ value: 'POP'
+ }
+ });
+ this.add('Direct_Reply_Delete', true, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Delete',
+ enableQuery: {
+ _id: 'Direct_Reply_Protocol',
+ value: 'IMAP'
+ }
+ });
+ this.add('Direct_Reply_Separator', '+', {
+ type: 'select',
+ values: [
+ {
+ key: '!',
+ i18nLabel: '!'
+ }, {
+ key: '#',
+ i18nLabel: '#'
+ }, {
+ key: '$',
+ i18nLabel: '$'
+ }, {
+ key: '%',
+ i18nLabel: '%'
+ }, {
+ key: '&',
+ i18nLabel: '&'
+ }, {
+ key: '\'',
+ i18nLabel: '\''
+ }, {
+ key: '*',
+ i18nLabel: '*'
+ }, {
+ key: '+',
+ i18nLabel: '+'
+ }, {
+ key: '-',
+ i18nLabel: '-'
+ }, {
+ key: '/',
+ i18nLabel: '/'
+ }, {
+ key: '=',
+ i18nLabel: '='
+ }, {
+ key: '?',
+ i18nLabel: '?'
+ }, {
+ key: '^',
+ i18nLabel: '^'
+ }, {
+ key: '_',
+ i18nLabel: '_'
+ }, {
+ key: '`',
+ i18nLabel: '`'
+ }, {
+ key: '{',
+ i18nLabel: '{'
+ }, {
+ key: '|',
+ i18nLabel: '|'
+ }, {
+ key: '}',
+ i18nLabel: '}'
+ }, {
+ key: '~',
+ i18nLabel: '~'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Direct_Reply_Separator'
+ });
+ this.add('Direct_Reply_Username', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Username',
+ placeholder: 'email@domain'
+ });
+ return this.add('Direct_Reply_Password', '', {
+ type: 'password',
+ env: true,
+ i18nLabel: 'Password'
+ });
+ });
+ this.section('SMTP', function() {
+ this.add('SMTP_Protocol', 'smtp', {
+ type: 'select',
+ values: [
+ {
+ key: 'smtp',
+ i18nLabel: 'smtp'
+ }, {
+ key: 'smtps',
+ i18nLabel: 'smtps'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Protocol'
+ });
+ this.add('SMTP_Host', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Host'
+ });
+ this.add('SMTP_Port', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Port'
+ });
+ this.add('SMTP_IgnoreTLS', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'IgnoreTLS',
+ enableQuery: {
+ _id: 'SMTP_Protocol',
+ value: 'smtp'
+ }
+ });
+ this.add('SMTP_Pool', true, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Pool'
+ });
+ this.add('SMTP_Username', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Username'
+ });
+ this.add('SMTP_Password', '', {
+ type: 'password',
+ env: true,
+ i18nLabel: 'Password'
+ });
+ this.add('From_Email', '', {
+ type: 'string',
+ placeholder: 'email@domain'
+ });
+ return this.add('SMTP_Test_Button', 'sendSMTPTestEmail', {
+ type: 'action',
+ actionText: 'Send_a_test_mail_to_my_user'
+ });
+ });
+ this.section('Invitation', function() {
+ this.add('Invitation_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Invitation_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Invitation_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Invitation_Customized',
+ value: false
+ }
+ });
+ return this.add('Invitation_HTML', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Invitation_HTML_Description',
+ enableQuery: {
+ _id: 'Invitation_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Invitation_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Registration', function() {
+ this.add('Accounts_Enrollment_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Accounts_Enrollment_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: false
+ }
+ });
+ return this.add('Accounts_Enrollment_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ enableQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Registration_via_Admin', function() {
+ this.add('Accounts_UserAddedEmail_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Accounts_UserAddedEmailSubject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: false
+ }
+ });
+ return this.add('Accounts_UserAddedEmail', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Accounts_UserAddedEmail_Description',
+ enableQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Forgot_password_section', function() {
+ this.add('Forgot_Password_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Forgot_Password_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: false
+ }
+ });
+ return this.add('Forgot_Password_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Forgot_Password_Description',
+ enableQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: false
+ }
+ });
+ });
+ return this.section('Verification', function() {
+ this.add('Verification_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Verification_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Verification_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Verification_Customized',
+ value: false
+ }
+ });
+ return this.add('Verification_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Verification_Description',
+ enableQuery: {
+ _id: 'Verification_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Verification_Customized',
+ value: false
+ }
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Message', function() {
+ this.section('Message_Attachments', function() {
+ this.add('Message_Attachments_GroupAttach', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nDescription: 'Message_Attachments_GroupAttachDescription'
+ });
+ this.add('Message_AudioRecorderEnabled', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nDescription: 'Message_AudioRecorderEnabledDescription'
+ });
+ });
+ this.add('Message_AllowEditing', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowEditing_BlockEditInMinutes', 0, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_AllowEditing_BlockEditInMinutesDescription'
+ });
+ this.add('Message_AllowDeleting', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowDeleting_BlockDeleteInMinutes', 0, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_AllowDeleting_BlockDeleteInMinutes'
+ });
+ this.add('Message_AllowUnrecognizedSlashCommand', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowDirectMessagesToYourself', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AlwaysSearchRegExp', false, {
+ type: 'boolean'
+ });
+ this.add('Message_ShowEditedStatus', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_ShowDeletedStatus', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowBadWordsFilter', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_BadWordsFilterList', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Message_KeepHistory', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_MaxAll', 0, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_MaxAllowedSize', 5000, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_ShowFormattingTips', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_SetNameToAliasEnabled', false, {
+ type: 'boolean',
+ 'public': false,
+ i18nDescription: 'Message_SetNameToAliasEnabled_Description'
+ });
+ this.add('Message_GroupingPeriod', 300, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_GroupingPeriodDescription'
+ });
+ this.add('API_Embed', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('API_Embed_UserAgent', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('API_EmbedCacheExpirationDays', 30, {
+ type: 'int',
+ 'public': false
+ });
+ this.add('API_Embed_clear_cache_now', 'OEmbedCacheCleanup', {
+ type: 'action',
+ actionText: 'clear',
+ i18nLabel: 'clear_cache_now'
+ });
+ this.add('API_EmbedDisabledFor', '', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'API_EmbedDisabledFor_Description'
+ });
+ this.add('API_EmbedIgnoredHosts', 'localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16', {
+ type: 'string',
+ i18nDescription: 'API_EmbedIgnoredHosts_Description'
+ });
+ this.add('API_EmbedSafePorts', '80, 443', {
+ type: 'string'
+ });
+ this.add('Message_TimeFormat', 'LT', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_TimeFormat_Description'
+ });
+ this.add('Message_DateFormat', 'LL', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_DateFormat_Description'
+ });
+ this.add('Message_TimeAndDateFormat', 'LLL', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_TimeAndDateFormat_Description'
+ });
+ this.add('Message_QuoteChainLimit', 2, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_HideType_uj', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_ul', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_ru', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_au', false, {
+ type: 'boolean',
+ 'public': true
+ });
+
+ this.add('Message_HideType_mute_unmute', false, {
+ type: 'boolean',
+ 'public': true
+ });
+
+ this.add('Message_GlobalSearch', false, {
+ type: 'boolean',
+ 'public': true,
+ alert: 'This feature is currently in beta and could decrease the application performance! Please report bugs to github.com/RocketChat/Rocket.Chat/issues'
+ });
+});
+
+RocketChat.settings.addGroup('Meta', function() {
+ this.add('Meta_language', '', {
+ type: 'string'
+ });
+ this.add('Meta_fb_app_id', '', {
+ type: 'string'
+ });
+ this.add('Meta_robots', 'INDEX,FOLLOW', {
+ type: 'string'
+ });
+ this.add('Meta_google-site-verification', '', {
+ type: 'string'
+ });
+ this.add('Meta_msvalidate01', '', {
+ type: 'string'
+ });
+ return this.add('Meta_custom', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true
+ });
+});
+
+RocketChat.settings.addGroup('Push', function() {
+ this.add('Push_enable', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Push_debug', false, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.add('Push_enable_gateway', true, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.add('Push_gateway', 'https://gateway.rocket.chat', {
+ type: 'string',
+ enableQuery: [
+ {
+ _id: 'Push_enable',
+ value: true
+ }, {
+ _id: 'Push_enable_gateway',
+ value: true
+ }
+ ]
+ });
+ this.add('Push_production', true, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: [
+ {
+ _id: 'Push_enable',
+ value: true
+ }, {
+ _id: 'Push_enable_gateway',
+ value: false
+ }
+ ]
+ });
+ this.add('Push_test_push', 'push_test', {
+ type: 'action',
+ actionText: 'Send_a_test_push_to_my_user',
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.section('Certificates_and_Keys', function() {
+ this.add('Push_apn_passphrase', '', {
+ type: 'string'
+ });
+ this.add('Push_apn_key', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_cert', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_dev_passphrase', '', {
+ type: 'string'
+ });
+ this.add('Push_apn_dev_key', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_dev_cert', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_gcm_api_key', '', {
+ type: 'string'
+ });
+ return this.add('Push_gcm_project_number', '', {
+ type: 'string',
+ 'public': true
+ });
+ });
+ return this.section('Privacy', function() {
+ this.add('Push_show_username_room', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ return this.add('Push_show_message', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Layout', function() {
+ this.section('Content', function() {
+ this.add('Layout_Home_Title', 'Home', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Layout_Home_Body', 'Welcome to Rocket.Chat!
\nThe Rocket.Chat desktops apps for Windows, macOS and Linux are available to download here .
The native mobile app, Rocket.Chat+,\n for Android and iOS is available from Google Play and the App Store .
\nFor further help, please consult the documentation .
\nIf you\'re an admin, feel free to change this content via Administration -> Layout -> Home Body . Or clicking here .
', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Terms_of_Service', 'Terms of Service Go to APP SETTINGS -> Layout to customize this page.', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Login_Terms', 'By proceeding you are agreeing to our Terms of Service and Privacy Policy .', {
+ type: 'string',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Privacy_Policy', 'Privacy Policy Go to APP SETTINGS -> Layout to customize this page.', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ return this.add('Layout_Sidenav_Footer', ' ', {
+ type: 'code',
+ code: 'text/html',
+ 'public': true,
+ i18nDescription: 'Layout_Sidenav_Footer_description'
+ });
+ });
+ this.section('Custom_Scripts', function() {
+ this.add('Custom_Script_Logged_Out', '//Add your script', {
+ type: 'code',
+ multiline: true,
+ 'public': true
+ });
+ return this.add('Custom_Script_Logged_In', '//Add your script', {
+ type: 'code',
+ multiline: true,
+ 'public': true
+ });
+ });
+ return this.section('User_Interface', function() {
+ this.add('UI_DisplayRoles', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Merge_Channels_Groups', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Use_Name_Avatar', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Use_Real_Name', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Click_Direct_Message', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Unread_Counter_Style', 'Different_Style_For_User_Mentions', {
+ type: 'select',
+ values: [
+ {
+ key: 'Same_Style_For_Mentions',
+ i18nLabel: 'Same_Style_For_Mentions'
+ }, {
+ key: 'Different_Style_For_User_Mentions',
+ i18nLabel: 'Different_Style_For_User_Mentions'
+ }
+ ],
+ 'public': true
+ });
+ this.add('UI_Allow_room_names_with_special_chars', false, {
+ type: 'boolean',
+ public: true
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Logs', function() {
+ this.add('Log_Level', '0', {
+ type: 'select',
+ values: [
+ {
+ key: '0',
+ i18nLabel: '0_Errors_Only'
+ }, {
+ key: '1',
+ i18nLabel: '1_Errors_and_Information'
+ }, {
+ key: '2',
+ i18nLabel: '2_Erros_Information_and_Debug'
+ }
+ ],
+ 'public': true
+ });
+ this.add('Log_Package', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Log_File', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ return this.add('Log_View_Limit', 1000, {
+ type: 'int'
+ });
+});
+
+RocketChat.settings.init();
diff --git a/packages/rocketchat-lib-orig/server/startup/settingsOnLoadCdnPrefix.js b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadCdnPrefix.js
new file mode 100644
index 0000000000000..514438f16e272
--- /dev/null
+++ b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadCdnPrefix.js
@@ -0,0 +1,18 @@
+/* globals WebAppInternals*/
+import _ from 'underscore';
+
+function testWebAppInternals(fn) {
+ typeof WebAppInternals !== 'undefined' && fn(WebAppInternals);
+}
+RocketChat.settings.onload('CDN_PREFIX', function(key, value) {
+ if (_.isString(value) && value.trim()) {
+ return testWebAppInternals(WebAppInternals => WebAppInternals.setBundledJsCssPrefix(value));
+ }
+});
+
+Meteor.startup(function() {
+ const value = RocketChat.settings.get('CDN_PREFIX');
+ if (_.isString(value) && value.trim()) {
+ return testWebAppInternals(WebAppInternals => WebAppInternals.setBundledJsCssPrefix(value));
+ }
+});
diff --git a/packages/rocketchat-lib-orig/server/startup/settingsOnLoadDirectReply.js b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadDirectReply.js
new file mode 100644
index 0000000000000..b172e520a93d3
--- /dev/null
+++ b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadDirectReply.js
@@ -0,0 +1,67 @@
+import _ from 'underscore';
+import { IMAPIntercepter } from '../lib/interceptDirectReplyEmails.js';
+import { POP3Helper } from '../lib/interceptDirectReplyEmails.js';
+
+const startEmailIntercepter = _.debounce(Meteor.bindEnvironment(function() {
+ console.log('Starting Email Intercepter...');
+
+ if (RocketChat.settings.get('Direct_Reply_Enable') && RocketChat.settings.get('Direct_Reply_Protocol') && RocketChat.settings.get('Direct_Reply_Host') && RocketChat.settings.get('Direct_Reply_Port') && RocketChat.settings.get('Direct_Reply_Username') && RocketChat.settings.get('Direct_Reply_Password')) {
+ if (RocketChat.settings.get('Direct_Reply_Protocol') === 'IMAP') {
+ // stop already running IMAP instance
+ if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ console.log('Disconnecting already running IMAP instance...');
+ RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }));
+ } else if (RocketChat.POP3 && RocketChat.POP3Helper && RocketChat.POP3Helper.isActive()) {
+ console.log('Disconnecting already running POP instance...');
+ RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }));
+ } else {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }
+ } else if (RocketChat.settings.get('Direct_Reply_Protocol') === 'POP') {
+ // stop already running POP instance
+ if (RocketChat.POP3 && RocketChat.POP3Helper && RocketChat.POP3Helper.isActive()) {
+ console.log('Disconnecting already running POP instance...');
+ RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }));
+ } else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ console.log('Disconnecting already running IMAP instance...');
+ RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }));
+ } else {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }
+ }
+ } else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ // stop IMAP instance
+ RocketChat.IMAP.stop();
+ } else if (RocketChat.POP3 && RocketChat.POP3Helper.isActive()) {
+ // stop POP3 instance
+ RocketChat.POP3Helper.stop();
+ }
+}), 1000);
+
+RocketChat.settings.onload(/^Direct_Reply_.+/, startEmailIntercepter);
diff --git a/packages/rocketchat-lib-orig/server/startup/settingsOnLoadSMTP.js b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadSMTP.js
new file mode 100644
index 0000000000000..d70d684a876a4
--- /dev/null
+++ b/packages/rocketchat-lib-orig/server/startup/settingsOnLoadSMTP.js
@@ -0,0 +1,65 @@
+import _ from 'underscore';
+
+const buildMailURL = _.debounce(function() {
+ console.log('Updating process.env.MAIL_URL');
+
+ if (RocketChat.settings.get('SMTP_Host')) {
+ process.env.MAIL_URL = `${ RocketChat.settings.get('SMTP_Protocol') }://`;
+
+ if (RocketChat.settings.get('SMTP_Username') && RocketChat.settings.get('SMTP_Password')) {
+ process.env.MAIL_URL += `${ encodeURIComponent(RocketChat.settings.get('SMTP_Username')) }:${ encodeURIComponent(RocketChat.settings.get('SMTP_Password')) }@`;
+ }
+
+ process.env.MAIL_URL += encodeURIComponent(RocketChat.settings.get('SMTP_Host'));
+
+ if (RocketChat.settings.get('SMTP_Port')) {
+ process.env.MAIL_URL += `:${ parseInt(RocketChat.settings.get('SMTP_Port')) }`;
+ }
+
+ process.env.MAIL_URL += `?pool=${ RocketChat.settings.get('SMTP_Pool') }`;
+
+ if (RocketChat.settings.get('SMTP_Protocol') === 'smtp' && RocketChat.settings.get('SMTP_IgnoreTLS')) {
+ process.env.MAIL_URL += '&secure=false&ignoreTLS=true';
+ }
+
+ return process.env.MAIL_URL;
+ }
+}, 500);
+
+RocketChat.settings.onload('SMTP_Host', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Port', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_Username', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Password', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Protocol', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_Pool', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_IgnoreTLS', function() {
+ return buildMailURL();
+});
+
+Meteor.startup(function() {
+ return buildMailURL();
+});
diff --git a/packages/rocketchat-lib-orig/server/startup/statsTracker.js b/packages/rocketchat-lib-orig/server/startup/statsTracker.js
new file mode 100644
index 0000000000000..c3c4e9a71ce5f
--- /dev/null
+++ b/packages/rocketchat-lib-orig/server/startup/statsTracker.js
@@ -0,0 +1,45 @@
+import {StatsD} from 'node-dogstatsd';
+
+RocketChat.statsTracker = new (class StatsTracker {
+ constructor() {
+ this.StatsD = StatsD;
+ this.dogstatsd = new this.StatsD();
+ }
+
+ track(type, stats, ...args) {
+ this.dogstatsd[type](`RocketChat.${ stats }`, ...args);
+ }
+
+ now() {
+ const hrtime = process.hrtime();
+ return (hrtime[0] * 1000000 + hrtime[1] / 1000);
+ }
+
+ timing(stats, time, tags) {
+ this.track('timing', stats, time, tags);
+ }
+
+ increment(stats, time, tags) {
+ this.track('increment', stats, time, tags);
+ }
+
+ decrement(stats, time, tags) {
+ this.track('decrement', stats, time, tags);
+ }
+
+ histogram(stats, time, tags) {
+ this.track('histogram', stats, time, tags);
+ }
+
+ gauge(stats, time, tags) {
+ this.track('gauge', stats, time, tags);
+ }
+
+ unique(stats, time, tags) {
+ this.track('unique', stats, time, tags);
+ }
+
+ set(stats, time, tags) {
+ this.track('set', stats, time, tags);
+ }
+});
diff --git a/packages/rocketchat-lib-orig/startup/defaultRoomTypes.js b/packages/rocketchat-lib-orig/startup/defaultRoomTypes.js
new file mode 100644
index 0000000000000..9f9e006f1324b
--- /dev/null
+++ b/packages/rocketchat-lib-orig/startup/defaultRoomTypes.js
@@ -0,0 +1,15 @@
+import {
+ ConversationRoomType,
+ DirectMessageRoomType,
+ FavoriteRoomType,
+ PrivateRoomType,
+ PublicRoomType,
+ UnreadRoomType
+} from '../lib/roomTypes';
+
+RocketChat.roomTypes.add(new UnreadRoomType());
+RocketChat.roomTypes.add(new FavoriteRoomType());
+RocketChat.roomTypes.add(new ConversationRoomType());
+RocketChat.roomTypes.add(new PublicRoomType());
+RocketChat.roomTypes.add(new PrivateRoomType());
+RocketChat.roomTypes.add(new DirectMessageRoomType());
diff --git a/packages/rocketchat-lib/.npm/package/.gitignore b/packages/rocketchat-lib/.npm/package/.gitignore
deleted file mode 100644
index 3c3629e647f5d..0000000000000
--- a/packages/rocketchat-lib/.npm/package/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/packages/rocketchat-lib/.npm/package/README b/packages/rocketchat-lib/.npm/package/README
deleted file mode 100644
index 3d492553a438e..0000000000000
--- a/packages/rocketchat-lib/.npm/package/README
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory and the files immediately inside it are automatically generated
-when you change this package's NPM dependencies. Commit the files in this
-directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
-so that others run the same versions of sub-dependencies.
-
-You should NOT check in the node_modules directory that Meteor automatically
-creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json
deleted file mode 100644
index 1f3369640defe..0000000000000
--- a/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json
+++ /dev/null
@@ -1,532 +0,0 @@
-{
- "dependencies": {
- "acorn": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
- "from": "acorn@>=1.0.3 <2.0.0"
- },
- "amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "from": "amdefine@>=0.0.4"
- },
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "from": "ansi-regex@>=2.0.0 <3.0.0"
- },
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "from": "ansi-styles@>=2.2.1 <3.0.0"
- },
- "asap": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz",
- "from": "asap@>=2.0.3 <2.1.0"
- },
- "asn1": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
- "from": "asn1@>=0.2.3 <0.3.0"
- },
- "assert-plus": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
- "from": "assert-plus@>=0.2.0 <0.3.0"
- },
- "ast-types": {
- "version": "0.8.15",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz",
- "from": "ast-types@0.8.15"
- },
- "asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "from": "asynckit@>=0.4.0 <0.5.0"
- },
- "aws-sign2": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
- "from": "aws-sign2@>=0.6.0 <0.7.0"
- },
- "aws4": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz",
- "from": "aws4@>=1.2.1 <2.0.0"
- },
- "bad-words": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-1.3.1.tgz",
- "from": "bad-words@1.3.1"
- },
- "badwords-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz",
- "from": "badwords-list@>=1.0.0 <2.0.0"
- },
- "base62": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz",
- "from": "base62@0.1.1"
- },
- "bcrypt-pbkdf": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz",
- "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0"
- },
- "bintrees": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz",
- "from": "bintrees@1.0.1"
- },
- "boom": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
- "from": "boom@>=2.0.0 <3.0.0"
- },
- "bugsnag": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/bugsnag/-/bugsnag-1.8.0.tgz",
- "from": "bugsnag@1.8.0"
- },
- "caseless": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
- "from": "caseless@>=0.11.0 <0.12.0"
- },
- "chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "from": "chalk@>=1.1.1 <2.0.0"
- },
- "combined-stream": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
- "from": "combined-stream@>=1.0.5 <1.1.0"
- },
- "commander": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
- "from": "commander@>=2.9.0 <3.0.0"
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "from": "core-util-is@>=1.0.0 <1.1.0"
- },
- "cryptiles": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
- "from": "cryptiles@>=2.0.0 <3.0.0"
- },
- "dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "from": "dashdash@>=1.12.0 <2.0.0",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "from": "assert-plus@>=1.0.0 <2.0.0"
- }
- }
- },
- "delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "from": "delayed-stream@>=1.0.0 <1.1.0"
- },
- "ecc-jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
- "from": "ecc-jsbn@>=0.1.1 <0.2.0"
- },
- "es3ify": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.1.4.tgz",
- "from": "es3ify@>=0.1.3 <0.2.0"
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "from": "escape-string-regexp@>=1.0.2 <2.0.0"
- },
- "esmangle-evaluator": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz",
- "from": "esmangle-evaluator@>=1.0.0 <2.0.0"
- },
- "esprima-fb": {
- "version": "3001.1.0-dev-harmony-fb",
- "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz",
- "from": "esprima-fb@>=3001.1.0-dev-harmony-fb <3001.2.0"
- },
- "extend": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
- "from": "extend@>=3.0.0 <3.1.0"
- },
- "extsprintf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
- "from": "extsprintf@1.0.2"
- },
- "falafel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz",
- "from": "falafel@>=1.0.1 <2.0.0"
- },
- "foreach": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
- "from": "foreach@>=2.0.5 <3.0.0"
- },
- "forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "from": "forever-agent@>=0.6.1 <0.7.0"
- },
- "form-data": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz",
- "from": "form-data@>=2.1.1 <2.2.0"
- },
- "generate-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
- "from": "generate-function@>=2.0.0 <3.0.0"
- },
- "generate-object-property": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
- "from": "generate-object-property@>=1.1.0 <2.0.0"
- },
- "getpass": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz",
- "from": "getpass@>=0.1.1 <0.2.0",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "from": "assert-plus@>=1.0.0 <2.0.0"
- }
- }
- },
- "graceful-readlink": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
- "from": "graceful-readlink@>=1.0.0"
- },
- "har-validator": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
- "from": "har-validator@>=2.0.6 <2.1.0"
- },
- "has-ansi": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
- "from": "has-ansi@>=2.0.0 <3.0.0"
- },
- "hawk": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
- "from": "hawk@>=3.1.3 <3.2.0"
- },
- "hoek": {
- "version": "2.16.3",
- "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
- "from": "hoek@>=2.0.0 <3.0.0"
- },
- "http-signature": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
- "from": "http-signature@>=1.1.0 <1.2.0"
- },
- "immediate": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
- "from": "immediate@>=3.0.5 <3.1.0"
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "from": "inherits@>=2.0.1 <2.1.0"
- },
- "inline-process-browser": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/inline-process-browser/-/inline-process-browser-1.0.0.tgz",
- "from": "inline-process-browser@>=1.0.0 <2.0.0"
- },
- "is-my-json-valid": {
- "version": "2.15.0",
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz",
- "from": "is-my-json-valid@>=2.12.4 <3.0.0"
- },
- "is-property": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
- "from": "is-property@>=1.0.0 <2.0.0"
- },
- "is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "from": "is-typedarray@>=1.0.0 <1.1.0"
- },
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "from": "isarray@0.0.1"
- },
- "isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "from": "isstream@>=0.1.2 <0.2.0"
- },
- "jodid25519": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz",
- "from": "jodid25519@>=1.0.0 <2.0.0"
- },
- "jsbn": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz",
- "from": "jsbn@>=0.1.0 <0.2.0"
- },
- "json-schema": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
- "from": "json-schema@0.2.3"
- },
- "json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "from": "json-stringify-safe@>=5.0.1 <5.1.0"
- },
- "jsonpointer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
- "from": "jsonpointer@>=4.0.0 <5.0.0"
- },
- "jsprim": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz",
- "from": "jsprim@>=1.2.2 <2.0.0"
- },
- "jstransform": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-3.0.0.tgz",
- "from": "jstransform@>=3.0.0 <3.1.0"
- },
- "lie": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/lie/-/lie-3.0.2.tgz",
- "from": "lie@3.0.2"
- },
- "localforage": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.4.2.tgz",
- "from": "localforage@1.4.2"
- },
- "lokijs": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.4.1.tgz",
- "from": "lokijs@1.4.1"
- },
- "mime-db": {
- "version": "1.26.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz",
- "from": "mime-db@>=1.26.0 <1.27.0"
- },
- "mime-types": {
- "version": "2.1.14",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz",
- "from": "mime-types@>=2.1.7 <2.2.0"
- },
- "node-dogstatsd": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/node-dogstatsd/-/node-dogstatsd-0.0.6.tgz",
- "from": "node-dogstatsd@0.0.6"
- },
- "oauth-sign": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
- "from": "oauth-sign@>=0.8.1 <0.9.0"
- },
- "object-keys": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
- "from": "object-keys@>=1.0.6 <2.0.0"
- },
- "object-path": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz",
- "from": "object-path@0.9.2"
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "from": "pinkie@>=2.0.0 <3.0.0"
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "from": "pinkie-promise@>=2.0.0 <3.0.0"
- },
- "private": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz",
- "from": "private@>=0.1.5 <0.2.0"
- },
- "prom-client": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-7.0.1.tgz",
- "from": "prom-client@7.0.1"
- },
- "promise": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz",
- "from": "promise@>=7.0.0 <8.0.0"
- },
- "punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "from": "punycode@>=1.4.1 <2.0.0"
- },
- "qs": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz",
- "from": "qs@>=6.3.0 <6.4.0"
- },
- "readable-stream": {
- "version": "1.0.34",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
- "from": "readable-stream@>=1.0.33-1 <1.1.0-0"
- },
- "recast": {
- "version": "0.10.43",
- "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz",
- "from": "recast@>=0.10.1 <0.11.0",
- "dependencies": {
- "esprima-fb": {
- "version": "15001.1001.0-dev-harmony-fb",
- "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz",
- "from": "esprima-fb@>=15001.1001.0-dev-harmony-fb <15001.1002.0"
- },
- "source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "from": "source-map@>=0.5.0 <0.6.0"
- }
- }
- },
- "request": {
- "version": "2.79.0",
- "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
- "from": "request@>=2.0.0 <3.0.0"
- },
- "sntp": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
- "from": "sntp@>=1.0.0 <2.0.0"
- },
- "source-map": {
- "version": "0.1.31",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz",
- "from": "source-map@0.1.31"
- },
- "sshpk": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.2.tgz",
- "from": "sshpk@>=1.7.0 <2.0.0",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "from": "assert-plus@>=1.0.0 <2.0.0"
- }
- }
- },
- "stack-trace": {
- "version": "0.0.9",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz",
- "from": "stack-trace@0.0.9"
- },
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "from": "string_decoder@>=0.10.0 <0.11.0"
- },
- "stringstream": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
- "from": "stringstream@>=0.0.4 <0.1.0"
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "from": "strip-ansi@>=3.0.0 <4.0.0"
- },
- "supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "from": "supports-color@>=2.0.0 <3.0.0"
- },
- "tdigest": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz",
- "from": "tdigest@>=0.1.1 <0.2.0"
- },
- "through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "from": "through@>=2.3.4 <2.4.0"
- },
- "through2": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
- "from": "through2@>=0.6.5 <0.7.0"
- },
- "tough-cookie": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
- "from": "tough-cookie@>=2.3.0 <2.4.0"
- },
- "tunnel-agent": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
- "from": "tunnel-agent@>=0.4.1 <0.5.0"
- },
- "tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "from": "tweetnacl@>=0.14.0 <0.15.0"
- },
- "unreachable-branch-transform": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz",
- "from": "unreachable-branch-transform@>=0.3.0 <0.4.0"
- },
- "util-extend": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
- "from": "util-extend@>=1.0.1 <2.0.0"
- },
- "uuid": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
- "from": "uuid@>=3.0.0 <4.0.0"
- },
- "verror": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
- "from": "verror@1.3.6"
- },
- "xtend": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
- "from": "xtend@>=4.0.0 <5.0.0"
- }
- }
-}
diff --git a/packages/rocketchat-lib/README.md b/packages/rocketchat-lib/README.md
index 1836472b031ee..bdcdc5b44e504 100644
--- a/packages/rocketchat-lib/README.md
+++ b/packages/rocketchat-lib/README.md
@@ -47,32 +47,78 @@ RocketChat.settings.addGroup('Settings_Group', function() {
* `enableQuery` - Only enable this setting if the correspondent setting has the value specified
* `alert` - Shows an alert message with the given text
-#### roomTypes
+#### Custom Room Types
+Custom room types are now a regular and expected customization to Rocket.Chat. As a result of this, we have expanded
+the capabilities which custom room types are given. Custom room types now have full control over the settings which
+display on the room's setting tab. To achieve this, however, we had to forcefully break the previous behavior in order
+to force the new behavior. If, after merging, you are getting the error `Error: Invalid Room Configuration object, it must extend "RoomTypeConfig"`,
+then you will need to modify your custom room code to the class setup explained below.
+
+Implementing the new types requires two steps. First step is to implement a your own custom class to define the route configuration.
+Then the second step would be to implement your own room class, which will contain all of the required methods and configuration
+for usage in the clients.
+
+##### First Step: RoomTypeRouteConfig
+If your room adds a custom route to the browser, then you will need to create a class which extends `RoomTypeRouteConfig`.
+This class can be imported using es6 style imports `import { RoomTypeRouteConfig } from 'meteor/rocketchat:lib';`. There
+are two fields which are required when constructing your route which is `{ name, path }` and both are strings. Then your
+class must implement the `action(params, queryParams)` method.
-You can create your own room type using (on the client):
+```javascript
+class LivechatRoomRoute extends RoomTypeRouteConfig {
+ constructor() {
+ super({
+ name: 'live',
+ path: '/live/:code(\\d+)'
+ });
+ }
+
+ action(params) {
+ openRoom('l', params.code);
+ }
+
+ link(sub) {
+ return {
+ code: sub.code
+ };
+ }
+}
+```
+
+##### Second Step: RoomTypeConfig
+Next you need to create a class which extends `RoomTypeConfig`. This class can be imported using the es6 style import
+such as `import { RoomTypeConfig } from 'meteor/rocketchat:lib';`. There are two required properties when constructing
+your class which is `{ identifier, order }` with the `identifier` being a string and `order` being a number. There are
+default implementations of the required methods, so unless you want to overwrite the default behavior, such as disallowing
+certain settings, then you will need to implement that method and handle it.
```javascript
-RocketChat.roomTypes.add('l', 5, {
- template: 'livechat',
- icon: 'icon-chat-empty',
- route: {
- name: 'live',
- path: '/live/:name',
- action(params, queryParams) {
- Session.set('showUserInfo');
- openRoom('l', params.name);
- },
- link(sub) {
- return { name: sub.name }
- }
- },
- condition: () => {
- return RocketChat.authz.hasAllPermission('view-l-room');
- }
-});
+class LivechatRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'l',
+ order: 5,
+ icon: 'livechat',
+ label: 'Livechat',
+ route: new LivechatRoomRoute() //defined above, see the example
+ });
+ }
+
+ roomName(roomData) {
+ if (!roomData.name) {
+ return roomData.label;
+ } else {
+ return roomData.name;
+ }
+ }
+
+ condition() {
+ return RocketChat.settings.get('Livechat_enabled') && RocketChat.authz.hasAllPermission('view-l-room');
+ }
+}
```
-You'll need publish information about the new room with (on the server):
+Then for publishing of the data, you will need to provide the information about the new room with (on the server):
```javascript
RocketChat.roomTypes.setPublish('l', (identifier) => {
@@ -104,5 +150,10 @@ AccountBox.addItem({
```
### Functions
+n/a
+
### Methods
+n/a
+
### Publications
+n/a
diff --git a/packages/rocketchat-lib/client/AdminBox.coffee b/packages/rocketchat-lib/client/AdminBox.coffee
deleted file mode 100644
index c2cc37bf180e7..0000000000000
--- a/packages/rocketchat-lib/client/AdminBox.coffee
+++ /dev/null
@@ -1,16 +0,0 @@
-RocketChat.AdminBox = new class
- options = new ReactiveVar []
-
- addOption = (option) ->
- Tracker.nonreactive ->
- actual = options.get()
- actual.push option
- options.set actual
-
- getOptions = ->
- return _.filter options.get(), (option) ->
- if not option.permissionGranted? or option.permissionGranted()
- return true
-
- addOption: addOption
- getOptions: getOptions
diff --git a/packages/rocketchat-lib/client/AdminBox.js b/packages/rocketchat-lib/client/AdminBox.js
new file mode 100644
index 0000000000000..10492de6a265f
--- /dev/null
+++ b/packages/rocketchat-lib/client/AdminBox.js
@@ -0,0 +1,21 @@
+import _ from 'underscore';
+
+RocketChat.AdminBox = new class {
+ constructor() {
+ this.options = new ReactiveVar([]);
+ }
+ addOption(option) {
+ return Tracker.nonreactive(() => {
+ const actual = this.options.get();
+ actual.push(option);
+ return this.options.set(actual);
+ });
+ }
+ getOptions() {
+ return _.filter(this.options.get(), function(option) {
+ if ((option.permissionGranted == null) || option.permissionGranted()) {
+ return true;
+ }
+ });
+ }
+};
diff --git a/packages/rocketchat-lib/client/MessageAction.coffee b/packages/rocketchat-lib/client/MessageAction.coffee
deleted file mode 100644
index 80837c3a0bebe..0000000000000
--- a/packages/rocketchat-lib/client/MessageAction.coffee
+++ /dev/null
@@ -1,247 +0,0 @@
-import moment from 'moment'
-import toastr from 'toastr'
-
-RocketChat.MessageAction = new class
- buttons = new ReactiveVar {}
-
- ###
- config expects the following keys (only id is mandatory):
- id (mandatory)
- icon: string
- i18nLabel: string
- action: function(event, instance)
- validation: function(message)
- order: integer
- ###
- addButton = (config) ->
- unless config?.id
- return false
-
- Tracker.nonreactive ->
- btns = buttons.get()
- btns[config.id] = config
- buttons.set btns
-
- removeButton = (id) ->
- Tracker.nonreactive ->
- btns = buttons.get()
- delete btns[id]
- buttons.set btns
-
- updateButton = (id, config) ->
- Tracker.nonreactive ->
- btns = buttons.get()
- if btns[id]
- btns[id] = _.extend btns[id], config
- buttons.set btns
-
- getButtonById = (id) ->
- allButtons = buttons.get()
- return allButtons[id]
-
- getButtons = (message, context) ->
- allButtons = _.toArray buttons.get()
- if message
- allowedButtons = _.compact _.map allButtons, (button) ->
- if not button.context? or button.context.indexOf(context) > -1
- if not button.validation? or button.validation(message, context)
- return button
- else
- allowedButtons = allButtons
-
- return _.sortBy allowedButtons, 'order'
-
- resetButtons = ->
- buttons.set {}
-
- getPermaLink = (msgId) ->
- roomData = ChatSubscription.findOne({rid: Session.get('openedRoom')})
- if roomData
- routePath = RocketChat.roomTypes.getRouteLink(roomData.t, roomData)
- else
- routePath = document.location.pathname
- return Meteor.absoluteUrl().replace(/\/$/, '') + routePath + '?msg=' + msgId
-
- hideDropDown = () ->
- $('.message-dropdown:visible').hide()
-
- addButton: addButton
- removeButton: removeButton
- updateButton: updateButton
- getButtons: getButtons
- getButtonById: getButtonById
- resetButtons: resetButtons
- getPermaLink: getPermaLink
- hideDropDown: hideDropDown
-
-Meteor.startup ->
-
- $(document).click (event) =>
- target = $(event.target)
- if !target.closest('.message-cog-container').length and !target.is('.message-cog-container')
- RocketChat.MessageAction.hideDropDown()
-
- RocketChat.MessageAction.addButton
- id: 'reply-message'
- icon: 'icon-reply'
- i18nLabel: 'Reply'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (event, instance) ->
- message = @_arguments[1]
- input = instance.find('.input-message')
- url = RocketChat.MessageAction.getPermaLink(message._id)
- text = '[ ](' + url + ') @' + message.u.username + ' '
- if input.value
- input.value += if input.value.endsWith(' ') then '' else ' '
- input.value += text
- input.focus()
- RocketChat.MessageAction.hideDropDown()
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
- return true
- order: 1
-
- RocketChat.MessageAction.addButton
- id: 'edit-message'
- icon: 'icon-pencil'
- i18nLabel: 'Edit'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (e, instance) ->
- message = $(e.currentTarget).closest('.message')[0]
- chatMessages[Session.get('openedRoom')].edit(message)
- RocketChat.MessageAction.hideDropDown()
- input = instance.find('.input-message')
- Meteor.setTimeout ->
- input.focus()
- input.updateAutogrow()
- , 200
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
-
- hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid)
- isEditAllowed = RocketChat.settings.get 'Message_AllowEditing'
- editOwn = message.u?._id is Meteor.userId()
-
- return unless hasPermission or (isEditAllowed and editOwn)
-
- blockEditInMinutes = RocketChat.settings.get 'Message_AllowEditing_BlockEditInMinutes'
- if blockEditInMinutes? and blockEditInMinutes isnt 0
- msgTs = moment(message.ts) if message.ts?
- currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs?
- return currentTsDiff < blockEditInMinutes
- else
- return true
- order: 2
-
- RocketChat.MessageAction.addButton
- id: 'delete-message'
- icon: 'icon-trash-alt'
- i18nLabel: 'Delete'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (event, instance) ->
- message = @_arguments[1]
- RocketChat.MessageAction.hideDropDown()
- chatMessages[Session.get('openedRoom')].confirmDeleteMsg(message)
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
-
- hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid)
- isDeleteAllowed = RocketChat.settings.get 'Message_AllowDeleting'
- deleteOwn = message.u?._id is Meteor.userId()
-
- return unless hasPermission or (isDeleteAllowed and deleteOwn)
-
- blockDeleteInMinutes = RocketChat.settings.get 'Message_AllowDeleting_BlockDeleteInMinutes'
- if blockDeleteInMinutes? and blockDeleteInMinutes isnt 0
- msgTs = moment(message.ts) if message.ts?
- currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs?
- return currentTsDiff < blockDeleteInMinutes
- else
- return true
- order: 3
-
- RocketChat.MessageAction.addButton
- id: 'permalink'
- icon: 'icon-link'
- i18nLabel: 'Permalink'
- classes: 'clipboard'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (event, instance) ->
- message = @_arguments[1]
- permalink = RocketChat.MessageAction.getPermaLink(message._id)
- RocketChat.MessageAction.hideDropDown()
- if Meteor.isCordova
- cordova.plugins.clipboard.copy(permalink);
- else
- $(event.currentTarget).attr('data-clipboard-text', permalink);
- toastr.success(TAPi18n.__('Copied'))
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
-
- return true
- order: 4
-
- RocketChat.MessageAction.addButton
- id: 'copy'
- icon: 'icon-paste'
- i18nLabel: 'Copy'
- classes: 'clipboard'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (event, instance) ->
- message = @_arguments[1].msg
- RocketChat.MessageAction.hideDropDown()
- if Meteor.isCordova
- cordova.plugins.clipboard.copy(message);
- else
- $(event.currentTarget).attr('data-clipboard-text', message)
- toastr.success(TAPi18n.__('Copied'))
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
-
- return true
- order: 5
-
- RocketChat.MessageAction.addButton
- id: 'quote-message'
- icon: 'icon-quote-left'
- i18nLabel: 'Quote'
- context: [
- 'message'
- 'message-mobile'
- ]
- action: (event, instance) ->
- message = @_arguments[1]
- input = instance.find('.input-message')
- url = RocketChat.MessageAction.getPermaLink(message._id)
- text = '[ ](' + url + ') '
- if input.value
- input.value += if input.value.endsWith(' ') then '' else ' '
- input.value += text
- input.focus()
- RocketChat.MessageAction.hideDropDown()
- validation: (message) ->
- if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
- return false
-
- return true
- order: 6
diff --git a/packages/rocketchat-lib/client/MessageAction.js b/packages/rocketchat-lib/client/MessageAction.js
new file mode 100644
index 0000000000000..c473d2de43835
--- /dev/null
+++ b/packages/rocketchat-lib/client/MessageAction.js
@@ -0,0 +1,300 @@
+/* globals chatMessages cordova */
+
+import _ from 'underscore';
+import moment from 'moment';
+import toastr from 'toastr';
+
+RocketChat.MessageAction = new class {
+ /*
+ config expects the following keys (only id is mandatory):
+ id (mandatory)
+ icon: string
+ label: string
+ action: function(event, instance)
+ condition: function(message)
+ order: integer
+ group: string (message or menu)
+ */
+
+ constructor() {
+ this.buttons = new ReactiveVar({});
+ }
+
+ addButton(config) {
+ if (!config || !config.id) {
+ return false;
+ }
+
+ if (!config.group) {
+ config.group = 'menu';
+ }
+
+ return Tracker.nonreactive(() => {
+ const btns = this.buttons.get();
+ btns[config.id] = config;
+ return this.buttons.set(btns);
+ });
+ }
+
+ removeButton(id) {
+ return Tracker.nonreactive(() => {
+ const btns = this.buttons.get();
+ delete btns[id];
+ return this.buttons.set(btns);
+ });
+ }
+
+ updateButton(id, config) {
+ return Tracker.nonreactive(() => {
+ const btns = this.buttons.get();
+ if (btns[id]) {
+ btns[id] = _.extend(btns[id], config);
+ return this.buttons.set(btns);
+ }
+ });
+ }
+
+ getButtonById(id) {
+ const allButtons = this.buttons.get();
+ return allButtons[id];
+ }
+
+ getButtons(message, context, group) {
+ let allButtons = _.toArray(this.buttons.get());
+
+ if (group) {
+ allButtons = allButtons.filter(button => button.group === group);
+ }
+
+ if (message) {
+ allButtons = _.compact(_.map(allButtons, function(button) {
+ if (button.context == null || button.context.includes(context)) {
+ if (button.condition == null || button.condition(message, context)) {
+ return button;
+ }
+ }
+ }));
+ }
+ return _.sortBy(allButtons, 'order');
+ }
+
+ resetButtons() {
+ return this.buttons.set({});
+ }
+
+ getPermaLink(msgId) {
+ const roomData = ChatSubscription.findOne({
+ rid: Session.get('openedRoom')
+ });
+ let routePath = document.location.pathname;
+ if (roomData) {
+ routePath = RocketChat.roomTypes.getRouteLink(roomData.t, roomData);
+ }
+ return `${ Meteor.absoluteUrl().replace(/\/$/, '') + routePath }?msg=${ msgId }`;
+ }
+};
+
+Meteor.startup(function() {
+ RocketChat.MessageAction.addButton({
+ id: 'reply-message',
+ icon: 'message',
+ label: 'Reply',
+ context: ['message', 'message-mobile'],
+ action() {
+ const message = this._arguments[1];
+ const {input} = chatMessages[message.rid];
+ const url = RocketChat.MessageAction.getPermaLink(message._id);
+ const roomInfo = RocketChat.models.Rooms.findOne(message.rid, { fields: { t: 1 } });
+ let text = `[ ](${ url }) `;
+ let inputValue = '';
+
+ if (roomInfo.t !== 'd' && message.u.username !== Meteor.user().username) {
+ text += `@${ message.u.username } `;
+ }
+
+ if (input.value && !input.value.endsWith(' ')) {
+ inputValue += ' ';
+ }
+ inputValue += text;
+
+ $(input)
+ .focus()
+ .val(inputValue)
+ .trigger('change')
+ .trigger('input');
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
+ return false;
+ }
+
+ return true;
+ },
+ order: 1,
+ group: 'menu'
+ });
+
+ RocketChat.MessageAction.addButton({
+ id: 'edit-message',
+ icon: 'edit',
+ label: 'Edit',
+ context: ['message', 'message-mobile'],
+ action() {
+ const messageId = this._arguments[1]._id;
+ chatMessages[Session.get('openedRoom')].edit(document.getElementById(messageId));
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({
+ rid: message.rid
+ }) == null) {
+ return false;
+ }
+ const hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid);
+ const isEditAllowed = RocketChat.settings.get('Message_AllowEditing');
+ const editOwn = message.u && message.u._id === Meteor.userId();
+ if (!(hasPermission || (isEditAllowed && editOwn))) {
+ return;
+ }
+ const blockEditInMinutes = RocketChat.settings.get('Message_AllowEditing_BlockEditInMinutes');
+ if (blockEditInMinutes) {
+ let msgTs;
+ if (message.ts != null) {
+ msgTs = moment(message.ts);
+ }
+ let currentTsDiff;
+ if (msgTs != null) {
+ currentTsDiff = moment().diff(msgTs, 'minutes');
+ }
+ return currentTsDiff < blockEditInMinutes;
+ } else {
+ return true;
+ }
+ },
+ order: 2,
+ group: 'menu'
+ });
+
+ RocketChat.MessageAction.addButton({
+ id: 'delete-message',
+ icon: 'trash',
+ label: 'Delete',
+ context: ['message', 'message-mobile'],
+ color: 'alert',
+ action() {
+ const message = this._arguments[1];
+ chatMessages[Session.get('openedRoom')].confirmDeleteMsg(message);
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
+ return false;
+ }
+ const forceDelete = RocketChat.authz.hasAtLeastOnePermission('force-delete-message', message.rid);
+ const hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid);
+ const isDeleteAllowed = RocketChat.settings.get('Message_AllowDeleting');
+ const deleteOwn = message.u && message.u._id === Meteor.userId();
+ if (!(hasPermission || (isDeleteAllowed && deleteOwn) || forceDelete)) {
+ return;
+ }
+ const blockDeleteInMinutes = RocketChat.settings.get('Message_AllowDeleting_BlockDeleteInMinutes');
+ if (forceDelete) {
+ return true;
+ }
+ if (blockDeleteInMinutes != null && blockDeleteInMinutes !== 0) {
+ let msgTs;
+ if (message.ts != null) {
+ msgTs = moment(message.ts);
+ }
+ let currentTsDiff;
+ if (msgTs != null) {
+ currentTsDiff = moment().diff(msgTs, 'minutes');
+ }
+ return currentTsDiff < blockDeleteInMinutes;
+ } else {
+ return true;
+ }
+ },
+ order: 3,
+ group: 'menu'
+ });
+
+ RocketChat.MessageAction.addButton({
+ id: 'permalink',
+ icon: 'permalink',
+ label: 'Permalink',
+ classes: 'clipboard',
+ context: ['message', 'message-mobile'],
+ action(event) {
+ const message = this._arguments[1];
+ const permalink = RocketChat.MessageAction.getPermaLink(message._id);
+ if (Meteor.isCordova) {
+ cordova.plugins.clipboard.copy(permalink);
+ } else {
+ $(event.currentTarget).attr('data-clipboard-text', permalink);
+ }
+ toastr.success(TAPi18n.__('Copied'));
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
+ return false;
+ }
+
+ return true;
+ },
+ order: 4,
+ group: 'menu'
+ });
+
+ RocketChat.MessageAction.addButton({
+ id: 'copy',
+ icon: 'copy',
+ label: 'Copy',
+ classes: 'clipboard',
+ context: ['message', 'message-mobile'],
+ action(event) {
+ const message = this._arguments[1].msg;
+ if (Meteor.isCordova) {
+ cordova.plugins.clipboard.copy(message);
+ } else {
+ $(event.currentTarget).attr('data-clipboard-text', message);
+ }
+ toastr.success(TAPi18n.__('Copied'));
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
+ return false;
+ }
+
+ return true;
+ },
+ order: 5,
+ group: 'menu'
+ });
+
+ RocketChat.MessageAction.addButton({
+ id: 'quote-message',
+ icon: 'quote',
+ label: 'Quote',
+ context: ['message', 'message-mobile'],
+ action() {
+ const message = this._arguments[1];
+ const {input} = chatMessages[message.rid];
+ const url = RocketChat.MessageAction.getPermaLink(message._id);
+ const text = `[ ](${ url }) `;
+ if (input.value) {
+ input.value += input.value.endsWith(' ') ? '' : ' ';
+ }
+ input.value += text;
+ input.focus();
+ $(input).trigger('change').trigger('input');
+ },
+ condition(message) {
+ if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
+ return false;
+ }
+
+ return true;
+ },
+ order: 6,
+ group: 'menu'
+ });
+});
diff --git a/packages/rocketchat-lib/client/Notifications.coffee b/packages/rocketchat-lib/client/Notifications.coffee
deleted file mode 100644
index 9a51ceca34820..0000000000000
--- a/packages/rocketchat-lib/client/Notifications.coffee
+++ /dev/null
@@ -1,72 +0,0 @@
-RocketChat.Notifications = new class
- constructor: ->
- @logged = Meteor.userId() isnt null
- @loginCb = []
- Tracker.autorun =>
- if Meteor.userId() isnt null and this.logged is false
- cb() for cb in this.loginCb
-
- @logged = Meteor.userId() isnt null
-
- @debug = false
- @streamAll = new Meteor.Streamer 'notify-all'
- @streamLogged = new Meteor.Streamer 'notify-logged'
- @streamRoom = new Meteor.Streamer 'notify-room'
- @streamRoomUsers = new Meteor.Streamer 'notify-room-users'
- @streamUser = new Meteor.Streamer 'notify-user'
-
- if @debug is true
- @onAll -> console.log "RocketChat.Notifications: onAll", arguments
- @onUser -> console.log "RocketChat.Notifications: onAll", arguments
-
- onLogin: (cb) ->
- @loginCb.push(cb)
- if @logged
- cb()
-
- notifyRoom: (room, eventName, args...) ->
- console.log "RocketChat.Notifications: notifyRoom", arguments if @debug is true
-
- args.unshift "#{room}/#{eventName}"
- @streamRoom.emit.apply @streamRoom, args
-
- notifyUser: (userId, eventName, args...) ->
- console.log "RocketChat.Notifications: notifyUser", arguments if @debug is true
-
- args.unshift "#{userId}/#{eventName}"
- @streamUser.emit.apply @streamUser, args
-
- notifyUsersOfRoom: (room, eventName, args...) ->
- console.log "RocketChat.Notifications: notifyUsersOfRoom", arguments if @debug is true
-
- args.unshift "#{room}/#{eventName}"
- @streamRoomUsers.emit.apply @streamRoomUsers, args
-
- onAll: (eventName, callback) ->
- @streamAll.on eventName, callback
-
- onLogged: (eventName, callback) ->
- @onLogin =>
- @streamLogged.on eventName, callback
-
- onRoom: (room, eventName, callback) ->
- if @debug is true
- @streamRoom.on room, -> console.log "RocketChat.Notifications: onRoom #{room}", arguments
-
- @streamRoom.on "#{room}/#{eventName}", callback
-
- onUser: (eventName, callback) ->
- @streamUser.on "#{Meteor.userId()}/#{eventName}", callback
-
-
- unAll: (callback) ->
- @streamAll.removeListener 'notify', callback
-
- unLogged: (callback) ->
- @streamLogged.removeListener 'notify', callback
-
- unRoom: (room, eventName, callback) ->
- @streamRoom.removeListener "#{room}/#{eventName}", callback
-
- unUser: (callback) ->
- @streamUser.removeListener Meteor.userId(), callback
diff --git a/packages/rocketchat-lib/client/Notifications.js b/packages/rocketchat-lib/client/Notifications.js
new file mode 100644
index 0000000000000..d0bb34ec04c5d
--- /dev/null
+++ b/packages/rocketchat-lib/client/Notifications.js
@@ -0,0 +1,86 @@
+RocketChat.Notifications = new class {
+ constructor() {
+ this.logged = Meteor.userId() !== null;
+ this.loginCb = [];
+ Tracker.autorun(() => {
+ if (Meteor.userId() !== null && this.logged === false) {
+ this.loginCb.forEach(cb => cb());
+ }
+ return this.logged = Meteor.userId() !== null;
+ });
+ this.debug = false;
+ this.streamAll = new Meteor.Streamer('notify-all');
+ this.streamLogged = new Meteor.Streamer('notify-logged');
+ this.streamRoom = new Meteor.Streamer('notify-room');
+ this.streamRoomUsers = new Meteor.Streamer('notify-room-users');
+ this.streamUser = new Meteor.Streamer('notify-user');
+ if (this.debug === true) {
+ this.onAll(function() {
+ return console.log('RocketChat.Notifications: onAll', arguments);
+ });
+ this.onUser(function() {
+ return console.log('RocketChat.Notifications: onAll', arguments);
+ });
+ }
+ }
+
+ onLogin(cb) {
+ this.loginCb.push(cb);
+ if (this.logged) {
+ return cb();
+ }
+ }
+ notifyRoom(room, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('RocketChat.Notifications: notifyRoom', arguments);
+ }
+ args.unshift(`${ room }/${ eventName }`);
+ return this.streamRoom.emit.apply(this.streamRoom, args);
+ }
+ notifyUser(userId, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('RocketChat.Notifications: notifyUser', arguments);
+ }
+ args.unshift(`${ userId }/${ eventName }`);
+ return this.streamUser.emit.apply(this.streamUser, args);
+ }
+ notifyUsersOfRoom(room, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('RocketChat.Notifications: notifyUsersOfRoom', arguments);
+ }
+ args.unshift(`${ room }/${ eventName }`);
+ return this.streamRoomUsers.emit.apply(this.streamRoomUsers, args);
+ }
+ onAll(eventName, callback) {
+ return this.streamAll.on(eventName, callback);
+ }
+ onLogged(eventName, callback) {
+ return this.onLogin(() => {
+ return this.streamLogged.on(eventName, callback);
+ });
+ }
+ onRoom(room, eventName, callback) {
+ if (this.debug === true) {
+ this.streamRoom.on(room, function() {
+ return console.log(`RocketChat.Notifications: onRoom ${ room }`, arguments);
+ });
+ }
+ return this.streamRoom.on(`${ room }/${ eventName }`, callback);
+ }
+ onUser(eventName, callback) {
+ return this.streamUser.on(`${ Meteor.userId() }/${ eventName }`, callback);
+ }
+ unAll(callback) {
+ return this.streamAll.removeListener('notify', callback);
+ }
+ unLogged(callback) {
+ return this.streamLogged.removeListener('notify', callback);
+ }
+ unRoom(room, eventName, callback) {
+ return this.streamRoom.removeListener(`${ room }/${ eventName }`, callback);
+ }
+ unUser(eventName, callback) {
+ return this.streamUser.removeListener(`${ Meteor.userId() }/${ eventName }`, callback);
+ }
+
+};
diff --git a/packages/rocketchat-lib/client/OAuthProxy.js b/packages/rocketchat-lib/client/OAuthProxy.js
new file mode 100644
index 0000000000000..b5c36676b0bb7
--- /dev/null
+++ b/packages/rocketchat-lib/client/OAuthProxy.js
@@ -0,0 +1,14 @@
+/* globals OAuth */
+import _ from 'underscore';
+
+OAuth.launchLogin = _.wrap(OAuth.launchLogin, function(func, options) {
+ const proxy = RocketChat.settings.get('Accounts_OAuth_Proxy_services').replace(/\s/g, '').split(',');
+ if (proxy.includes(options.loginService)) {
+ const redirect_uri = options.loginUrl.match(/(&redirect_uri=)([^&]+|$)/)[2];
+ options.loginUrl = options.loginUrl.replace(/(&redirect_uri=)([^&]+|$)/, `$1${ encodeURIComponent(RocketChat.settings.get('Accounts_OAuth_Proxy_host')) }/oauth_redirect`);
+ options.loginUrl = options.loginUrl.replace(/(&state=)([^&]+|$)/, `$1${ redirect_uri }!$2`);
+ options.loginUrl = `${ RocketChat.settings.get('Accounts_OAuth_Proxy_host') }/redirect/${ encodeURIComponent(options.loginUrl) }`;
+ }
+
+ return func(options);
+});
diff --git a/packages/rocketchat-lib/client/defaultTabBars.js b/packages/rocketchat-lib/client/defaultTabBars.js
index aeccd5d4978f0..5d8cf7c0f91b5 100644
--- a/packages/rocketchat-lib/client/defaultTabBars.js
+++ b/packages/rocketchat-lib/client/defaultTabBars.js
@@ -1,8 +1,8 @@
RocketChat.TabBar.addButton({
groups: ['channel', 'group', 'direct'],
id: 'message-search',
- i18nTitle: 'Search',
- icon: 'icon-search',
+ i18nTitle: 'Search_Messages',
+ icon: 'magnifier',
template: 'messageSearch',
order: 1
});
@@ -11,7 +11,7 @@ RocketChat.TabBar.addButton({
groups: ['direct'],
id: 'user-info',
i18nTitle: 'User_Info',
- icon: 'icon-user',
+ icon: 'user',
template: 'membersList',
order: 2
});
@@ -20,16 +20,35 @@ RocketChat.TabBar.addButton({
groups: ['channel', 'group'],
id: 'members-list',
i18nTitle: 'Members_List',
- icon: 'icon-users',
+ icon: 'team',
template: 'membersList',
order: 2
});
+RocketChat.TabBar.addButton({
+ groups: ['channel', 'group'],
+ id: 'addUsers',
+ i18nTitle: 'Add_users',
+ icon: 'user-plus',
+ template: 'inviteUsers',
+ order: 2
+});
+
+
RocketChat.TabBar.addButton({
groups: ['channel', 'group', 'direct'],
id: 'uploaded-files-list',
i18nTitle: 'Room_uploaded_file_list',
- icon: 'icon-attach',
+ icon: 'clip',
template: 'uploadedFilesList',
order: 3
});
+
+RocketChat.TabBar.addButton({
+ groups: ['channel', 'privategroup', 'directmessage'],
+ id: 'keyboard-shortcut-list',
+ i18nTitle: 'Keyboard_Shortcuts_Title',
+ icon: 'keyboard',
+ template: 'keyboardShortcuts',
+ order: 4
+});
diff --git a/packages/rocketchat-lib/client/lib/ChannelActions.js b/packages/rocketchat-lib/client/lib/ChannelActions.js
new file mode 100644
index 0000000000000..6f9a6d2e7f66f
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/ChannelActions.js
@@ -0,0 +1,93 @@
+import { call, UiTextContext } from 'meteor/rocketchat:lib';
+
+export function hide(type, rid, name) {
+ const warnText = RocketChat.roomTypes.roomTypes[type].getUiText(UiTextContext.HIDE_WARNING);
+
+ modal.open({
+ title: t('Are_you_sure'),
+ text: warnText ? t(warnText, name) : '',
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes_hide_it'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: true,
+ html: false
+ }, function() {
+ if (['channel', 'group', 'direct'].includes(FlowRouter.getRouteName()) && (Session.get('openedRoom') === rid)) {
+ FlowRouter.go('home');
+ }
+
+ Meteor.call('hideRoom', rid, function(err) {
+ if (err) {
+ handleError(err);
+ } else if (rid === Session.get('openedRoom')) {
+ Session.delete('openedRoom');
+ }
+ });
+ });
+
+ return false;
+}
+
+export function leave(type, rid, name) {
+ const warnText = RocketChat.roomTypes.roomTypes[type].getUiText(UiTextContext.LEAVE_WARNING);
+
+ modal.open({
+ title: t('Are_you_sure'),
+ text: warnText ? t(warnText, name) : '',
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes_leave_it'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, function(isConfirm) {
+ if (isConfirm) {
+ Meteor.call('leaveRoom', rid, function(err) {
+ if (err) {
+ modal.open({
+ title: t('Warning'),
+ text: handleError(err, false),
+ type: 'warning',
+ html: false
+ });
+ } else {
+ modal.close();
+ if (['channel', 'group', 'direct'].includes(FlowRouter.getRouteName()) && (Session.get('openedRoom') === rid)) {
+ FlowRouter.go('home');
+ }
+
+ RoomManager.close(rid);
+ }
+ });
+ }
+ });
+
+ return false;
+}
+
+export function erase(rid) {
+ modal.open({
+ title: t('Are_you_sure'),
+ text: t('Delete_Room_Warning'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes_delete_it'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, () => {
+ call('eraseRoom', rid).then(() => {
+ modal.open({
+ title: t('Deleted'),
+ text: t('Room_has_been_deleted'),
+ type: 'success',
+ timer: 2000,
+ showConfirmButton: false
+ });
+ });
+ });
+}
diff --git a/packages/rocketchat-lib/client/lib/RestApiClient.js b/packages/rocketchat-lib/client/lib/RestApiClient.js
new file mode 100644
index 0000000000000..cadcbaed02e7d
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/RestApiClient.js
@@ -0,0 +1,109 @@
+RocketChat.API = {
+ delete(endpoint, params) {
+ return RocketChat.API._jqueryCall('DELETE', endpoint, params);
+ },
+
+ get(endpoint, params) {
+ return RocketChat.API._jqueryCall('GET', endpoint, params);
+ },
+
+ post(endpoint, params, body) {
+ if (!body) {
+ body = params;
+ params = {};
+ }
+
+ return RocketChat.API._jqueryCall('POST', endpoint, params, body);
+ },
+
+ upload(endpoint, params, formData) {
+ if (!formData) {
+ formData = params;
+ params = {};
+ }
+
+ return RocketChat.API._jqueryFormDataCall(endpoint, params, formData);
+ },
+
+ _generateQueryFromParams(params) {
+ let query = '';
+ if (params && typeof params === 'object') {
+ Object.keys(params).forEach((key) => {
+ query += query === '' ? '?' : '&';
+
+ query += `${ key }=${ params[key] }`;
+ });
+ }
+
+ return query;
+ },
+
+ _jqueryCall(method, endpoint, params, body) {
+ const query = RocketChat.API._generateQueryFromParams(params);
+
+ return new Promise(function _rlRestApiGet(resolve, reject) {
+ jQuery.ajax({
+ method,
+ url: `${ window.location.origin }/api/${ endpoint }${ query }`,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-User-Id': localStorage['Meteor.userId'],
+ 'X-Auth-Token': localStorage['Meteor.loginToken']
+ },
+ data: JSON.stringify(body),
+ success: function _rlGetSuccess(result) {
+ resolve(result);
+ },
+ error: function _rlGetFailure(xhr, status, errorThrown) {
+ reject(new Error(errorThrown));
+ }
+ });
+ });
+ },
+
+ _jqueryFormDataCall(endpoint, params, formData) {
+ const query = RocketChat.API._generateQueryFromParams(params);
+
+ if (!(formData instanceof FormData)) {
+ throw new Error('The formData parameter MUST be an instance of the FormData class.');
+ }
+
+ return new Promise(function _jqueryFormDataPromise(resolve, reject) {
+ jQuery.ajax({
+ url: `${ Meteor.absoluteUrl() }api/${ endpoint }${ query }`,
+ headers: {
+ 'X-User-Id': localStorage['Meteor.userId'],
+ 'X-Auth-Token': localStorage['Meteor.loginToken']
+ },
+ data: formData,
+ processData: false,
+ contentType: false,
+ type: 'POST',
+ success: function _jqueryFormDataSuccess(result) {
+ resolve(result);
+ },
+ error: function _jqueryFormDataError(xhr, status, errorThrown) {
+ reject(new Error(errorThrown));
+ }
+ });
+ });
+ },
+
+ v1: {
+ delete(endpoint, params) {
+ return RocketChat.API.delete(`v1/${ endpoint }`, params);
+ },
+
+ get(endpoint, params) {
+ return RocketChat.API.get(`v1/${ endpoint }`, params);
+ },
+
+ post(endpoint, params, body) {
+ return RocketChat.API.post(`v1/${ endpoint }`, params, body);
+ },
+
+ upload(endpoint, params, formData) {
+ return RocketChat.API.upload(`v1/${ endpoint }`, params, formData);
+ }
+ }
+};
diff --git a/packages/rocketchat-lib/client/lib/RocketChatTabBar.js b/packages/rocketchat-lib/client/lib/RocketChatTabBar.js
index 6c66c344dddd3..49c36326c801c 100644
--- a/packages/rocketchat-lib/client/lib/RocketChatTabBar.js
+++ b/packages/rocketchat-lib/client/lib/RocketChatTabBar.js
@@ -1,9 +1,7 @@
-/* globals RocketChatTabBar */
-/* exported RocketChatTabBar */
-
-RocketChatTabBar = class RocketChatTabBar {
+export class RocketChatTabBar {
constructor() {
this.template = new ReactiveVar();
+ this.id = new ReactiveVar();
this.group = new ReactiveVar();
this.state = new ReactiveVar();
this.data = new ReactiveVar();
@@ -13,6 +11,10 @@ RocketChatTabBar = class RocketChatTabBar {
return this.template.get();
}
+ getId() {
+ return this.id.get();
+ }
+
setTemplate(template) {
this.template.set(template);
}
@@ -43,30 +45,28 @@ RocketChatTabBar = class RocketChatTabBar {
open(button) {
this.state.set('opened');
-
- if (button) {
- if (typeof button !== 'object' || !button.id) {
- button = RocketChat.TabBar.getButton(button);
- }
- if (button.width) {
- $('.flex-tab').css('width', `${button.width}px`);
- } else {
- $('.flex-tab').css('width', '');
- }
- this.template.set(button.template);
- }
-
Tracker.afterFlush(() => {
- $('.flex-tab').find('input[type=text]:first').focus();
- $('.flex-tab .content').scrollTop(0);
+ $('.contextual-bar__container').scrollTop(0).find('input[type=text]:first').focus();
});
+
+ if (!button) {
+ return;
+ }
+ if (typeof button !== 'object' || !button.id) {
+ button = RocketChat.TabBar.getButton(button);
+ }
+ $('.flex-tab, .contextual-bar').css('width', button.width ? `${ button.width }px` : '');
+ this.template.set(button.template);
+ this.id.set(button.id);
+ return button;
}
close() {
this.state.set('');
- $('.flex-tab').css('width', '');
+ $('.flex-tab, .contextual-bar').css('width', '');
this.template.set();
+ this.id.set();
}
-};
+}
diff --git a/packages/rocketchat-lib/client/lib/TabBar.js b/packages/rocketchat-lib/client/lib/TabBar.js
index 8a73bf412e359..714c4c08ee1f4 100644
--- a/packages/rocketchat-lib/client/lib/TabBar.js
+++ b/packages/rocketchat-lib/client/lib/TabBar.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
RocketChat.TabBar = new (class TabBar {
constructor() {
this.buttons = new ReactiveVar({});
@@ -18,7 +20,7 @@ RocketChat.TabBar = new (class TabBar {
return false;
}
- let btns = this.buttons.curValue;
+ const btns = this.buttons.curValue;
btns[config.id] = config;
if (this.extraGroups[config.id]) {
@@ -29,13 +31,13 @@ RocketChat.TabBar = new (class TabBar {
}
removeButton(id) {
- let btns = this.buttons.curValue;
+ const btns = this.buttons.curValue;
delete btns[id];
this.buttons.set(btns);
}
updateButton(id, config) {
- let btns = this.buttons.curValue;
+ const btns = this.buttons.curValue;
if (btns[id]) {
btns[id] = _.extend(btns[id], config);
this.buttons.set(btns);
@@ -43,7 +45,11 @@ RocketChat.TabBar = new (class TabBar {
}
getButtons() {
- return _.sortBy(_.toArray(this.buttons.get()), 'order');
+ const buttons = _.toArray(this.buttons.get()).filter(button => {
+ return !button.condition || button.condition();
+ });
+
+ return _.sortBy(buttons, 'order');
}
getButton(id) {
@@ -51,7 +57,7 @@ RocketChat.TabBar = new (class TabBar {
}
addGroup(id, groups) {
- let btns = this.buttons.curValue;
+ const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.union((btns[id].groups || []), groups);
this.buttons.set(btns);
@@ -61,7 +67,7 @@ RocketChat.TabBar = new (class TabBar {
}
removeGroup(id, groups) {
- let btns = this.buttons.curValue;
+ const btns = this.buttons.curValue;
if (btns[id]) {
btns[id].groups = _.difference((btns[id].groups || []), groups);
this.buttons.set(btns);
diff --git a/packages/rocketchat-lib/client/lib/cachedCollection.js b/packages/rocketchat-lib/client/lib/cachedCollection.js
index 8d8e03bf8a2f1..ddeaa28880814 100644
--- a/packages/rocketchat-lib/client/lib/cachedCollection.js
+++ b/packages/rocketchat-lib/client/lib/cachedCollection.js
@@ -1,4 +1,5 @@
import localforage from 'localforage';
+import _ from 'underscore';
class CachedCollectionManager {
constructor() {
@@ -97,17 +98,18 @@ class CachedCollection {
userRelated = true,
useSync = true,
useCache = true,
- debug = true,
- version = 6,
- maxCacheTime = 60*60*24*30
+ debug = false,
+ version = 7,
+ maxCacheTime = 60*60*24*30,
+ onSyncData = (/* action, record */) => {}
}) {
- this.collection = collection || new Meteor.Collection(null);
+ this.collection = collection || new Mongo.Collection(null);
this.ready = new ReactiveVar(false);
this.name = name;
- this.methodName = methodName || `${name}/get`;
- this.syncMethodName = syncMethodName || `${name}/get`;
- this.eventName = eventName || `${name}-changed`;
+ this.methodName = methodName || `${ name }/get`;
+ this.syncMethodName = syncMethodName || `${ name }/get`;
+ this.eventName = eventName || `${ name }-changed`;
this.eventType = eventType;
this.useSync = useSync;
this.useCache = useCache;
@@ -116,6 +118,7 @@ class CachedCollection {
this.userRelated = userRelated;
this.updatedAt = new Date(0);
this.maxCacheTime = maxCacheTime;
+ this.onSyncData = onSyncData;
RocketChat.CachedCollectionManager.register(this);
@@ -136,16 +139,16 @@ class CachedCollection {
log(...args) {
if (this.debug === true) {
- console.log(`CachedCollection ${this.name} =>`, ...args);
+ console.log(`CachedCollection ${ this.name } =>`, ...args);
}
}
countQueries() {
- this.log(`${Object.keys(this.collection._collection.queries).length} queries`);
+ this.log(`${ Object.keys(this.collection._collection.queries).length } queries`);
}
recomputeCollectionQueries() {
- this.log(`recomputing ${Object.keys(this.collection._collection.queries).length} queries`);
+ this.log(`recomputing ${ Object.keys(this.collection._collection.queries).length } queries`);
_.each(this.collection._collection.queries, (query) => {
this.collection._collection._recomputeResults(query);
});
@@ -165,7 +168,7 @@ class CachedCollection {
}
localforage.getItem(this.name, (error, data) => {
- if (data && (data.version < this.version || data.token !== this.getToken())) {
+ if (data && (data.version < this.version || data.token !== this.getToken() || this.getToken() === undefined)) {
this.clearCache();
callback(false);
return;
@@ -179,7 +182,7 @@ class CachedCollection {
}
if (data && data.records && data.records.length > 0) {
- this.log(`${data.records.length} records loaded from cache`);
+ this.log(`${ data.records.length } records loaded from cache`);
data.records.forEach((record) => {
record.__cache__ = true;
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
@@ -201,11 +204,13 @@ class CachedCollection {
loadFromServer(callback = () => {}) {
Meteor.call(this.methodName, (error, data) => {
- this.log(`${data.length} records loaded from server`);
+ this.log(`${ data.length } records loaded from server`);
data.forEach((record) => {
delete record.$loki;
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
+ this.onSyncData('changed', record);
+
if (record._updatedAt && record._updatedAt > this.updatedAt) {
this.updatedAt = record._updatedAt;
}
@@ -232,18 +237,18 @@ class CachedCollection {
return false;
}
- this.log(`syncing from ${this.updatedAt}`);
+ this.log(`syncing from ${ this.updatedAt }`);
Meteor.call(this.syncMethodName, this.updatedAt, (error, data) => {
let changes = [];
if (data.update && data.update.length > 0) {
- this.log(`${data.update.length} records updated in sync`);
+ this.log(`${ data.update.length } records updated in sync`);
changes.push(...data.update);
}
if (data.remove && data.remove.length > 0) {
- this.log(`${data.remove.length} records removed in sync`);
+ this.log(`${ data.remove.length } records removed in sync`);
changes.push(...data.remove);
}
@@ -268,12 +273,16 @@ class CachedCollection {
if (record._deletedAt) {
this.collection.remove({ _id: record._id });
+ this.onSyncData('removed', record);
+
if (record._deletedAt && record._deletedAt > this.updatedAt) {
this.updatedAt = record._deletedAt;
}
} else {
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
+ this.onSyncData('changed', record);
+
if (record._updatedAt && record._updatedAt > this.updatedAt) {
this.updatedAt = record._updatedAt;
}
@@ -322,6 +331,7 @@ class CachedCollection {
this.log('record received', t, record);
if (t === 'removed') {
this.collection.remove(record._id);
+ RoomManager.close(record.t+record.name);
} else {
delete record.$loki;
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
diff --git a/packages/rocketchat-lib/client/lib/callMethod.js b/packages/rocketchat-lib/client/lib/callMethod.js
new file mode 100644
index 0000000000000..cd92e9a83f3af
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/callMethod.js
@@ -0,0 +1,17 @@
+/**
+ * Wraps a Meteor method into a Promise.
+ * This is particularly useful for creating information dialogs after execution of a Meteor method
+ * @param {The Meteor method to be calls} method
+ * @param {the method's parameters} params
+ */
+export const call = (method, ...params) => {
+ return new Promise((resolve, reject) => {
+ Meteor.call(method, ...params, (err, result) => {
+ if (err) {
+ handleError(err);
+ return reject(err);
+ }
+ return resolve(result);
+ });
+ });
+};
diff --git a/packages/rocketchat-lib/client/lib/index.js b/packages/rocketchat-lib/client/lib/index.js
new file mode 100644
index 0000000000000..11697b503cbcf
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/index.js
@@ -0,0 +1,24 @@
+/*
+ What is this file? Great question! To make Rocket.Chat more "modular"
+ and to make the "rocketchat:lib" package more of a core package
+ with the libraries, this index file contains the exported members
+ for the *client* pieces of code which does include the shared
+ library files.
+*/
+
+import { RocketChatTabBar } from './RocketChatTabBar';
+import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext } from '../../lib/RoomTypeConfig';
+import { hide, leave, erase } from './ChannelActions';
+import { call } from './callMethod';
+
+export {
+ call,
+ erase,
+ hide,
+ leave,
+ RocketChatTabBar,
+ RoomSettingsEnum,
+ RoomTypeConfig,
+ RoomTypeRouteConfig,
+ UiTextContext
+};
diff --git a/packages/rocketchat-lib/client/lib/openRoom.coffee b/packages/rocketchat-lib/client/lib/openRoom.coffee
deleted file mode 100644
index af932dfc5aa38..0000000000000
--- a/packages/rocketchat-lib/client/lib/openRoom.coffee
+++ /dev/null
@@ -1,79 +0,0 @@
-currentTracker = undefined
-
-@openRoom = (type, name) ->
- Session.set 'openedRoom', null
-
- Meteor.defer ->
- currentTracker = Tracker.autorun (c) ->
- if RoomManager.open(type + name).ready() isnt true
- BlazeLayout.render 'main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' }
- return
-
- user = Meteor.user()
- unless user?.username
- return
-
- currentTracker = undefined
- c.stop()
-
- room = RocketChat.roomTypes.findRoom(type, name, user)
- if not room?
- if type is 'd'
- Meteor.call 'createDirectMessage', name, (err) ->
- if !err
- RoomManager.close(type + name)
- openRoom('d', name)
- else
- Session.set 'roomNotFound', {type: type, name: name}
- BlazeLayout.render 'main', {center: 'roomNotFound'}
- return
- else
- Meteor.call 'getRoomByTypeAndName', type, name, (err, record) ->
- if err?
- Session.set 'roomNotFound', {type: type, name: name}
- BlazeLayout.render 'main', {center: 'roomNotFound'}
- else
- delete record.$loki
- RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'))
- RoomManager.close(type + name)
- openRoom(type, name)
-
- return
-
- mainNode = document.querySelector('.main-content')
- if mainNode?
- for child in mainNode.children
- mainNode.removeChild child if child?
- roomDom = RoomManager.getDomOfRoom(type + name, room._id)
- mainNode.appendChild roomDom
- if roomDom.classList.contains('room-container')
- roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop
-
- Session.set 'openedRoom', room._id
-
- fireGlobalEvent 'room-opened', _.omit room, 'usernames'
-
- Session.set 'editRoomTitle', false
- RoomManager.updateMentionsMarksOfRoom type + name
- Meteor.setTimeout ->
- readMessage.readNow()
- , 2000
- # KonchatNotification.removeRoomNotification(params._id)
-
- if Meteor.Device.isDesktop() and window.chatMessages?[room._id]?
- setTimeout ->
- $('.message-form .input-message').focus()
- , 100
-
- # update user's room subscription
- sub = ChatSubscription.findOne({rid: room._id})
- if sub?.open is false
- Meteor.call 'openRoom', room._id, (err) ->
- if err
- return handleError(err)
-
- if FlowRouter.getQueryParam('msg')
- msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id }
- RoomHistoryManager.getSurroundingMessages(msg);
-
- RocketChat.callbacks.run 'enter-room', sub
diff --git a/packages/rocketchat-lib/client/lib/openRoom.js b/packages/rocketchat-lib/client/lib/openRoom.js
new file mode 100644
index 0000000000000..a82257b0c1524
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/openRoom.js
@@ -0,0 +1,99 @@
+/* globals fireGlobalEvent readMessage currentTracker*/
+import _ from 'underscore';
+
+currentTracker = undefined;
+
+function openRoom(type, name) {
+ Session.set('openedRoom', null);
+
+ return Meteor.defer(() =>
+ currentTracker = Tracker.autorun(function(c) {
+ const user = Meteor.user();
+ if ((user && user.username == null) || user == null && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
+ BlazeLayout.render('main');
+ return;
+ }
+
+ if (RoomManager.open(type + name).ready() !== true) {
+ BlazeLayout.render('main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' });
+ return;
+ }
+ if (currentTracker) {
+ currentTracker = undefined;
+ }
+ c.stop();
+
+ const room = RocketChat.roomTypes.findRoom(type, name, user);
+ if (room == null || room === undefined) {
+ if (type === 'd') {
+ Meteor.call('createDirectMessage', name, function(err) {
+ if (!err) {
+ RoomManager.close(type + name);
+ return openRoom('d', name);
+ } else {
+ Session.set('roomNotFound', {type, name});
+ BlazeLayout.render('main', {center: 'roomNotFound'});
+ return;
+ }
+ });
+ } else {
+ Meteor.call('getRoomByTypeAndName', type, name, Session.get('currentServer'), function(err, record) {
+ if (err) {
+ Session.set('roomNotFound', {type, name});
+ return BlazeLayout.render('main', {center: 'roomNotFound'});
+ } else {
+ delete record.$loki;
+ // RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'));
+ RoomManager.close(type + name);
+ return openRoom(type, name);
+ // return Meteor.defer(() => {
+ // return FlowRouter.goToRoomById(record._id);
+ // });
+ }
+ });
+ }
+ return;
+ }
+
+ const mainNode = document.querySelector('.main-content');
+ if (mainNode) {
+ for (const child of Array.from(mainNode.children)) {
+ if (child) { mainNode.removeChild(child); }
+ }
+ const roomDom = RoomManager.getDomOfRoom(type + name, room._id);
+ mainNode.appendChild(roomDom);
+ if (roomDom.classList.contains('room-container')) {
+ roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop;
+ }
+ }
+
+ Session.set('openedRoom', room._id);
+ RocketChat.openedRoom = room._id;
+
+ fireGlobalEvent('room-opened', _.omit(room, 'usernames'));
+
+ Session.set('editRoomTitle', false);
+ RoomManager.updateMentionsMarksOfRoom(type + name);
+ Meteor.setTimeout(() => readMessage.readNow(), 2000);
+ // KonchatNotification.removeRoomNotification(params._id)
+ // update user's room subscription
+ const sub = ChatSubscription.findOne({rid: room._id});
+ if (sub && sub.open === false) {
+ Meteor.call('openRoom', room._id, function(err) {
+ if (err) {
+ return handleError(err);
+ }
+ });
+ }
+
+ if (FlowRouter.getQueryParam('msg')) {
+ const msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id };
+ RoomHistoryManager.getSurroundingMessages(msg);
+ }
+
+ return RocketChat.callbacks.run('enter-room', sub);
+ })
+ );
+}
+export { openRoom };
+this.openRoom = openRoom;
diff --git a/packages/rocketchat-lib/client/lib/roomExit.coffee b/packages/rocketchat-lib/client/lib/roomExit.coffee
deleted file mode 100644
index d7da9ed4a8718..0000000000000
--- a/packages/rocketchat-lib/client/lib/roomExit.coffee
+++ /dev/null
@@ -1,20 +0,0 @@
-@roomExit = ->
- RocketChat.callbacks.run 'roomExit'
-
- BlazeLayout.render 'main', {center: 'none'}
-
- if currentTracker?
- currentTracker.stop()
-
- mainNode = document.querySelector('.main-content')
- if mainNode?
- for child in mainNode.children
- if child?
- if child.classList.contains('room-container')
- wrapper = child.querySelector('.messages-box > .wrapper')
- if wrapper
- if wrapper.scrollTop >= wrapper.scrollHeight - wrapper.clientHeight
- child.oldScrollTop = 10e10
- else
- child.oldScrollTop = wrapper.scrollTop
- mainNode.removeChild child
diff --git a/packages/rocketchat-lib/client/lib/roomExit.js b/packages/rocketchat-lib/client/lib/roomExit.js
new file mode 100644
index 0000000000000..3b036d282e80b
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/roomExit.js
@@ -0,0 +1,39 @@
+/*globals currentTracker */
+this.roomExit = function() {
+ // 7370 - Close flex-tab when opening a room on mobile UI
+ if (window.matchMedia('(max-width: 500px)').matches) {
+ const flex = document.querySelector('.flex-tab');
+ if (flex) {
+ const templateData = Blaze.getData(flex);
+ templateData && templateData.tabBar && templateData.tabBar.close();
+ }
+ }
+ RocketChat.callbacks.run('roomExit');
+ BlazeLayout.render('main', {
+ center: 'none'
+ });
+
+ if (typeof currentTracker !== 'undefined') {
+ currentTracker.stop();
+ }
+ const mainNode = document.querySelector('.main-content');
+ if (mainNode == null) {
+ return;
+ }
+ return [...mainNode.children].forEach(child => {
+ if (child == null) {
+ return;
+ }
+ if (child.classList.contains('room-container')) {
+ const wrapper = child.querySelector('.messages-box > .wrapper');
+ if (wrapper) {
+ if (wrapper.scrollTop >= wrapper.scrollHeight - wrapper.clientHeight) {
+ child.oldScrollTop = 10e10;
+ } else {
+ child.oldScrollTop = wrapper.scrollTop;
+ }
+ }
+ }
+ mainNode.removeChild(child);
+ });
+};
diff --git a/packages/rocketchat-lib/client/lib/roomTypes.coffee b/packages/rocketchat-lib/client/lib/roomTypes.coffee
deleted file mode 100644
index 53689c00fff49..0000000000000
--- a/packages/rocketchat-lib/client/lib/roomTypes.coffee
+++ /dev/null
@@ -1,85 +0,0 @@
-RocketChat.roomTypes = new class roomTypesClient extends roomTypesCommon
- checkCondition: (roomType) ->
- return not roomType.condition? or roomType.condition()
-
- getTypes: ->
- orderedTypes = []
-
- _.sortBy(@roomTypesOrder, 'order').forEach (type) =>
- orderedTypes.push @roomTypes[type.identifier]
-
- return orderedTypes
-
- getIcon: (roomType) ->
- return @roomTypes[roomType]?.icon
-
- getRoomName: (roomType, roomData) ->
- return @roomTypes[roomType]?.roomName roomData
-
- getIdentifiers: (except) ->
- except = [].concat except
- list = _.reject @roomTypesOrder, (t) -> return except.indexOf(t.identifier) isnt -1
- return _.map list, (t) -> return t.identifier
-
- getUserStatus: (roomType, roomId) ->
- return @roomTypes[roomType]?.getUserStatus?(roomId)
-
- findRoom: (roomType, identifier, user) ->
- return @roomTypes[roomType]?.findRoom identifier, user
-
- canSendMessage: (roomId) ->
- return ChatSubscription.find({ rid: roomId }).count() > 0
-
- readOnly: (roomId, user) ->
-
- fields = { ro: 1 }
-
- # if a user has been specified then we want to see if that user has been muted in the room
- if user
- fields.muted = 1
-
- room = ChatRoom.findOne({ _id: roomId }, fields : fields)
-
- unless user
- return room?.ro;
-
- return room?.ro is true and Array.isArray(room?.muted) and room?.muted.indexOf(user.username) != -1
-
- archived: (roomId) ->
- fields = { archived: 1 }
-
- room = ChatRoom.findOne({ _id: roomId }, fields : fields)
-
- return room?.archived is true
-
- verifyCanSendMessage: (roomId) ->
- room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
- return if not room?.t?
-
- roomType = room.t
-
- return @roomTypes[roomType]?.canSendMessage roomId if @roomTypes[roomType]?.canSendMessage?
-
- return @canSendMessage roomId
-
- verifyShowJoinLink: (roomId) ->
- room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
- return if not room?.t?
-
- roomType = room.t
-
- if not @roomTypes[roomType]?.showJoinLink?
- return false
-
- return @roomTypes[roomType].showJoinLink roomId
-
- getNotSubscribedTpl: (roomId) ->
- room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
- return if not room?.t?
-
- roomType = room.t
-
- if not @roomTypes[roomType]?.notSubscribedTpl?
- return false
-
- return @roomTypes[roomType].notSubscribedTpl
diff --git a/packages/rocketchat-lib/client/lib/roomTypes.js b/packages/rocketchat-lib/client/lib/roomTypes.js
new file mode 100644
index 0000000000000..101bb0b3f4297
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/roomTypes.js
@@ -0,0 +1,116 @@
+import _ from 'underscore';
+
+import { RoomTypesCommon } from '../../lib/RoomTypesCommon';
+
+RocketChat.roomTypes = new class RocketChatRoomTypes extends RoomTypesCommon {
+ checkCondition(roomType) {
+ return roomType.condition == null || roomType.condition();
+ }
+ getTypes() {
+ return _.sortBy(this.roomTypesOrder, 'order').map((type) => this.roomTypes[type.identifier]).filter(type => !type.condition || type.condition());
+ }
+ getIcon(roomType) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].icon;
+ }
+ getRoomName(roomType, roomData) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].roomName && this.roomTypes[roomType].roomName(roomData);
+ }
+ getSecondaryRoomName(roomType, roomData) {
+ return this.roomTypes[roomType] && typeof this.roomTypes[roomType].secondaryRoomName === 'function' && this.roomTypes[roomType].secondaryRoomName(roomData);
+ }
+ getIdentifiers(e) {
+ const except = [].concat(e);
+ const list = _.reject(this.roomTypesOrder, (t) => except.indexOf(t.identifier) !== -1);
+ return _.map(list, (t) => t.identifier);
+ }
+ getUserStatus(roomType, roomId) {
+ return this.roomTypes[roomType] && typeof this.roomTypes[roomType].getUserStatus === 'function' && this.roomTypes[roomType].getUserStatus(roomId);
+ }
+ findRoom(roomType, identifier, user) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].findRoom(identifier, user);
+ }
+ canSendMessage(roomId) {
+ return ChatSubscription.find({
+ rid: roomId
+ }).count() > 0;
+ }
+ readOnly(roomId, user) {
+ const fields = {
+ ro: 1
+ };
+ if (user) {
+ fields.muted = 1;
+ }
+ const room = ChatRoom.findOne({
+ _id: roomId
+ }, {
+ fields
+ });
+ if (!user) {
+ return room && room.ro;
+ }
+ /* globals RoomRoles */
+ const userOwner = RoomRoles.findOne({
+ rid: roomId,
+ 'u._id': user._id,
+ roles: 'owner'
+ }, {
+ fields: {
+ _id: 1
+ }
+ });
+ return room && (room.ro === true && Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !userOwner);
+ }
+ archived(roomId) {
+ const fields = {
+ archived: 1
+ };
+ const room = ChatRoom.findOne({
+ _id: roomId
+ }, {
+ fields
+ });
+ return room && room.archived === true;
+ }
+ verifyCanSendMessage(roomId) {
+ const room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 }});
+
+ if (!room || !room.t) {
+ return;
+ }
+
+ const roomType = room.t;
+ if (this.roomTypes[roomType] && this.roomTypes[roomType].canSendMessage) {
+ return this.roomTypes[roomType].canSendMessage(roomId);
+ }
+ return this.canSendMessage(roomId);
+ }
+ verifyShowJoinLink(roomId) {
+ const room = ChatRoom.findOne({
+ _id: roomId
+ }, {
+ fields: {
+ t: 1
+ }
+ });
+ if (!room || !room.t) {
+ return;
+ }
+ const roomType = room.t;
+ if (this.roomTypes[roomType] && !this.roomTypes[roomType].showJoinLink) {
+ return false;
+ }
+ return this.roomTypes[roomType].showJoinLink(roomId);
+ }
+ getNotSubscribedTpl(roomId) {
+ const room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 }});
+ if (!room || !room.t) {
+ return;
+ }
+ const roomType = room.t;
+ if (this.roomTypes[roomType] && !this.roomTypes[roomType].notSubscribedTpl) {
+ return false;
+ }
+ return this.roomTypes[roomType].notSubscribedTpl;
+ }
+};
diff --git a/packages/rocketchat-lib/client/lib/settings.coffee b/packages/rocketchat-lib/client/lib/settings.coffee
deleted file mode 100644
index 38c08e546ba26..0000000000000
--- a/packages/rocketchat-lib/client/lib/settings.coffee
+++ /dev/null
@@ -1,65 +0,0 @@
-###
-# RocketChat.settings holds all packages settings
-# @namespace RocketChat.settings
-###
-
-RocketChat.settings.cachedCollection = new RocketChat.CachedCollection({ name: 'public-settings', eventType: 'onAll', userRelated: false })
-RocketChat.settings.collection = RocketChat.settings.cachedCollection.collection
-RocketChat.settings.cachedCollection.init()
-
-RocketChat.settings.dict = new ReactiveDict 'settings'
-
-RocketChat.settings.get = (_id) ->
- return RocketChat.settings.dict.get(_id)
-
-RocketChat.settings.init = ->
- initialLoad = true
- RocketChat.settings.collection.find().observe
- added: (record) ->
- Meteor.settings[record._id] = record.value
- RocketChat.settings.dict.set record._id, record.value
- RocketChat.settings.load record._id, record.value, initialLoad
- changed: (record) ->
- Meteor.settings[record._id] = record.value
- RocketChat.settings.dict.set record._id, record.value
- RocketChat.settings.load record._id, record.value, initialLoad
- removed: (record) ->
- delete Meteor.settings[record._id]
- RocketChat.settings.dict.set record._id, undefined
- RocketChat.settings.load record._id, undefined, initialLoad
- initialLoad = false
-
-RocketChat.settings.init()
-
-Meteor.startup ->
- if Meteor.isCordova is false
- Tracker.autorun (c) ->
- siteUrl = RocketChat.settings.get('Site_Url')
- if not siteUrl or not Meteor.userId()?
- return
-
- if RocketChat.authz.hasRole(Meteor.userId(), 'admin') is false or Meteor.settings.public.sandstorm
- return c.stop()
-
- Meteor.setTimeout ->
- if __meteor_runtime_config__.ROOT_URL isnt location.origin
- currentUrl = location.origin + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX
- swal
- type: 'warning'
- title: t('Warning')
- text: t("The_setting_s_is_configured_to_s_and_you_are_accessing_from_s", t('Site_Url'), siteUrl, currentUrl) + ' ' + t("Do_you_want_to_change_to_s_question", currentUrl)
- showCancelButton: true
- confirmButtonText: t('Yes')
- cancelButtonText: t('Cancel')
- closeOnConfirm: false
- html: true
- , ->
- Meteor.call 'saveSetting', 'Site_Url', currentUrl, ->
- swal
- title: t('Saved')
- type: 'success'
- timer: 1000
- showConfirmButton: false
- , 100
-
- return c.stop()
diff --git a/packages/rocketchat-lib/client/lib/settings.js b/packages/rocketchat-lib/client/lib/settings.js
new file mode 100644
index 0000000000000..5614cf2b7c1ee
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/settings.js
@@ -0,0 +1,87 @@
+
+/*
+* RocketChat.settings holds all packages settings
+* @namespace RocketChat.settings
+*/
+
+/* globals ReactiveDict*/
+
+RocketChat.settings.cachedCollection = new RocketChat.CachedCollection({
+ name: 'public-settings',
+ eventType: 'onAll',
+ userRelated: false
+});
+
+RocketChat.settings.collection = RocketChat.settings.cachedCollection.collection;
+
+RocketChat.settings.cachedCollection.init();
+
+RocketChat.settings.dict = new ReactiveDict('settings');
+
+RocketChat.settings.get = function(_id) {
+ return RocketChat.settings.dict.get(_id);
+};
+
+RocketChat.settings.init = function() {
+ let initialLoad = true;
+ RocketChat.settings.collection.find().observe({
+ added(record) {
+ Meteor.settings[record._id] = record.value;
+ RocketChat.settings.dict.set(record._id, record.value);
+ RocketChat.settings.load(record._id, record.value, initialLoad);
+ },
+ changed(record) {
+ Meteor.settings[record._id] = record.value;
+ RocketChat.settings.dict.set(record._id, record.value);
+ RocketChat.settings.load(record._id, record.value, initialLoad);
+ },
+ removed(record) {
+ delete Meteor.settings[record._id];
+ RocketChat.settings.dict.set(record._id, null);
+ RocketChat.settings.load(record._id, null, initialLoad);
+ }
+ });
+ initialLoad = false;
+};
+
+RocketChat.settings.init();
+
+Meteor.startup(function() {
+ if (Meteor.isCordova === true) {
+ return;
+ }
+ Tracker.autorun(function(c) {
+ const siteUrl = RocketChat.settings.get('Site_Url');
+ if (!siteUrl || (Meteor.userId() == null)) {
+ return;
+ }
+ if (RocketChat.authz.hasRole(Meteor.userId(), 'admin') === false || Meteor.settings['public'].sandstorm) {
+ return c.stop();
+ }
+ Meteor.setTimeout(function() {
+ const currentUrl = location.origin + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
+ if (__meteor_runtime_config__.ROOT_URL.replace(/\/$/, '') !== currentUrl) {
+ modal.open({
+ type: 'warning',
+ title: t('Warning'),
+ text: `${ t('The_setting_s_is_configured_to_s_and_you_are_accessing_from_s', t('Site_Url'), siteUrl, currentUrl) } ${ t('Do_you_want_to_change_to_s_question', currentUrl) }`,
+ showCancelButton: true,
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: true
+ }, function() {
+ Meteor.call('saveSetting', 'Site_Url', currentUrl, function() {
+ modal.open({
+ title: t('Saved'),
+ type: 'success',
+ timer: 1000,
+ showConfirmButton: false
+ });
+ });
+ });
+ }
+ }, 100);
+ return c.stop();
+ });
+});
diff --git a/packages/rocketchat-lib/client/lib/startup/commands.js b/packages/rocketchat-lib/client/lib/startup/commands.js
new file mode 100644
index 0000000000000..91456a9eed650
--- /dev/null
+++ b/packages/rocketchat-lib/client/lib/startup/commands.js
@@ -0,0 +1,17 @@
+//Track logins and when they login, get the commands
+(() => {
+ let oldUserId = null;
+
+ Meteor.autorun(() => {
+ const newUserId = Meteor.userId();
+ if (oldUserId === null && newUserId) {
+ RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) {
+ result.commands.forEach((command) => {
+ RocketChat.slashCommands.commands[command.command] = command;
+ });
+ });
+ }
+
+ oldUserId = Meteor.userId();
+ });
+})();
diff --git a/packages/rocketchat-lib/client/lib/userRoles.js b/packages/rocketchat-lib/client/lib/userRoles.js
index c3ae397f3181f..a2dbd4cbe79cb 100644
--- a/packages/rocketchat-lib/client/lib/userRoles.js
+++ b/packages/rocketchat-lib/client/lib/userRoles.js
@@ -8,7 +8,7 @@ Meteor.startup(function() {
return handleError(error);
}
- for (let record of results) {
+ for (const record of results) {
UserRoles.upsert({ _id: record._id }, record);
}
});
diff --git a/packages/rocketchat-lib/client/methods/sendMessage.coffee b/packages/rocketchat-lib/client/methods/sendMessage.coffee
deleted file mode 100644
index c8ae9426c32a3..0000000000000
--- a/packages/rocketchat-lib/client/methods/sendMessage.coffee
+++ /dev/null
@@ -1,22 +0,0 @@
-Meteor.methods
- sendMessage: (message) ->
- if not Meteor.userId()
- return false
-
- if _.trim(message.msg) isnt ''
- if isNaN(TimeSync.serverOffset())
- message.ts = new Date()
- else
- message.ts = new Date(Date.now() + TimeSync.serverOffset())
-
- message.u =
- _id: Meteor.userId()
- username: Meteor.user().username
-
- message.temp = true
-
- message = RocketChat.callbacks.run 'beforeSaveMessage', message
-
- RocketChat.promises.run('onClientMessageReceived', message).then (message) ->
- ChatMessage.insert message
- RocketChat.callbacks.run 'afterSaveMessage', message
diff --git a/packages/rocketchat-lib/client/methods/sendMessage.js b/packages/rocketchat-lib/client/methods/sendMessage.js
new file mode 100644
index 0000000000000..6fa83bfbb2c20
--- /dev/null
+++ b/packages/rocketchat-lib/client/methods/sendMessage.js
@@ -0,0 +1,27 @@
+import s from 'underscore.string';
+
+Meteor.methods({
+ sendMessage(message) {
+ if (!Meteor.userId() || s.trim(message.msg) === '') {
+ return false;
+ }
+ const user = Meteor.user();
+ message.ts = isNaN(TimeSync.serverOffset()) ? new Date() : new Date(Date.now() + TimeSync.serverOffset());
+ message.u = {
+ _id: Meteor.userId(),
+ username: user.username
+ };
+ if (RocketChat.settings.get('UI_Use_Real_Name')) {
+ message.u.name = user.name;
+ }
+ message.temp = true;
+ if (RocketChat.settings.get('Message_Read_Receipt_Enabled')) {
+ message.unread = true;
+ }
+ message = RocketChat.callbacks.run('beforeSaveMessage', message);
+ RocketChat.promises.run('onClientMessageReceived', message).then(function(message) {
+ ChatMessage.insert(message);
+ return RocketChat.callbacks.run('afterSaveMessage', message);
+ });
+ }
+});
diff --git a/packages/rocketchat-lib/client/models/Avatars.js b/packages/rocketchat-lib/client/models/Avatars.js
new file mode 100644
index 0000000000000..bd8804e746c83
--- /dev/null
+++ b/packages/rocketchat-lib/client/models/Avatars.js
@@ -0,0 +1,6 @@
+RocketChat.models.Avatars = new class extends RocketChat.models._Base {
+ constructor() {
+ super();
+ this._initModel('avatars');
+ }
+};
diff --git a/packages/rocketchat-lib/client/models/Uploads.coffee b/packages/rocketchat-lib/client/models/Uploads.coffee
deleted file mode 100644
index 4572e735b99b6..0000000000000
--- a/packages/rocketchat-lib/client/models/Uploads.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.models.Uploads = new class extends RocketChat.models._Base
- constructor: ->
- @_initModel 'uploads'
diff --git a/packages/rocketchat-lib/client/models/Uploads.js b/packages/rocketchat-lib/client/models/Uploads.js
new file mode 100644
index 0000000000000..eefe630c708c4
--- /dev/null
+++ b/packages/rocketchat-lib/client/models/Uploads.js
@@ -0,0 +1,7 @@
+
+RocketChat.models.Uploads = new class extends RocketChat.models._Base {
+ constructor() {
+ super();
+ this._initModel('uploads');
+ }
+};
diff --git a/packages/rocketchat-lib/client/models/_Base.coffee b/packages/rocketchat-lib/client/models/_Base.coffee
deleted file mode 100644
index fb485723241a0..0000000000000
--- a/packages/rocketchat-lib/client/models/_Base.coffee
+++ /dev/null
@@ -1,44 +0,0 @@
-RocketChat.models._Base = class
- _baseName: ->
- return 'rocketchat_'
-
- _initModel: (name) ->
- check name, String
-
- @model = new Mongo.Collection @_baseName() + name
-
- find: ->
- return @model.find.apply @model, arguments
-
- findOne: ->
- return @model.findOne.apply @model, arguments
-
- insert: ->
- return @model.insert.apply @model, arguments
-
- update: ->
- return @model.update.apply @model, arguments
-
- upsert: ->
- return @model.upsert.apply @model, arguments
-
- remove: ->
- return @model.remove.apply @model, arguments
-
- allow: ->
- return @model.allow.apply @model, arguments
-
- deny: ->
- return @model.deny.apply @model, arguments
-
- ensureIndex: ->
- return
-
- dropIndex: ->
- return
-
- tryEnsureIndex: ->
- return
-
- tryDropIndex: ->
- return
diff --git a/packages/rocketchat-lib/client/models/_Base.js b/packages/rocketchat-lib/client/models/_Base.js
new file mode 100644
index 0000000000000..55623317be663
--- /dev/null
+++ b/packages/rocketchat-lib/client/models/_Base.js
@@ -0,0 +1,52 @@
+RocketChat.models._Base = class {
+
+ _baseName() {
+ return 'rocketchat_';
+ }
+
+ _initModel(name) {
+ check(name, String);
+ return this.model = new Mongo.Collection(this._baseName() + name);
+ }
+
+ find() {
+ return this.model.find.apply(this.model, arguments);
+ }
+
+ findOne() {
+ return this.model.findOne.apply(this.model, arguments);
+ }
+
+ insert() {
+ return this.model.insert.apply(this.model, arguments);
+ }
+
+ update() {
+ return this.model.update.apply(this.model, arguments);
+ }
+
+ upsert() {
+ return this.model.upsert.apply(this.model, arguments);
+ }
+
+ remove() {
+ return this.model.remove.apply(this.model, arguments);
+ }
+
+ allow() {
+ return this.model.allow.apply(this.model, arguments);
+ }
+
+ deny() {
+ return this.model.deny.apply(this.model, arguments);
+ }
+
+ ensureIndex() {}
+
+ dropIndex() {}
+
+ tryEnsureIndex() {}
+
+ tryDropIndex() {}
+
+};
diff --git a/packages/rocketchat-lib/client/views/customFieldsForm.html b/packages/rocketchat-lib/client/views/customFieldsForm.html
index 5b067a372a072..a1a5d2c9845bd 100644
--- a/packages/rocketchat-lib/client/views/customFieldsForm.html
+++ b/packages/rocketchat-lib/client/views/customFieldsForm.html
@@ -1,26 +1,55 @@
- {{#each customFields}}
- {{#if $eq field.type 'select'}}
-
-
{{_ fieldName}}
-
-
- {{#each field.options}}
- {{_ .}}
- {{/each}}
-
-
-
+{{#if customFields}}
+
+{{/if}}
diff --git a/packages/rocketchat-lib/client/views/customFieldsForm.js b/packages/rocketchat-lib/client/views/customFieldsForm.js
index 56d5ae7e22724..57f5e6cdeabf0 100644
--- a/packages/rocketchat-lib/client/views/customFieldsForm.js
+++ b/packages/rocketchat-lib/client/views/customFieldsForm.js
@@ -1,4 +1,7 @@
Template.customFieldsForm.helpers({
+ new() {
+ return this.new;
+ },
customFields() {
const customFields = Template.instance().customFields.get();
diff --git a/packages/rocketchat-lib/lib/Message.coffee b/packages/rocketchat-lib/lib/Message.coffee
deleted file mode 100644
index cbf6e92a89ff0..0000000000000
--- a/packages/rocketchat-lib/lib/Message.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-RocketChat.Message =
- parse: (msg, language) ->
- messageType = RocketChat.MessageTypes.getType(msg)
- if messageType?.render?
- return messageType.render(msg)
- else if messageType?.template?
- # render template
- else if messageType?.message?
- if not language and localStorage?.getItem('userLanguage')
- language = localStorage.getItem('userLanguage')
- if messageType.data?(msg)?
- return TAPi18n.__(messageType.message, messageType.data(msg), language)
- else
- return TAPi18n.__(messageType.message, {}, language)
- else
- if msg.u?.username is RocketChat.settings.get('Chatops_Username')
- msg.html = msg.msg
- return msg.html
-
- msg.html = msg.msg
- if _.trim(msg.html) isnt ''
- msg.html = _.escapeHTML msg.html
-
- # message = RocketChat.callbacks.run 'renderMessage', msg
- msg.html = msg.html.replace /\n/gm, '
'
- return msg.html
diff --git a/packages/rocketchat-lib/lib/Message.js b/packages/rocketchat-lib/lib/Message.js
new file mode 100644
index 0000000000000..23ee2128e6c03
--- /dev/null
+++ b/packages/rocketchat-lib/lib/Message.js
@@ -0,0 +1,31 @@
+import s from 'underscore.string';
+
+RocketChat.Message = {
+ parse(msg, language) {
+ const messageType = RocketChat.MessageTypes.getType(msg);
+ if (messageType) {
+ if (messageType.render) {
+ return messageType.render(msg);
+ } else if (messageType.template) {
+ // Render message
+ return;
+ } else if (messageType.message) {
+ if (!language && typeof localStorage !== 'undefined') {
+ language = localStorage.getItem('userLanguage');
+ }
+ const data = (typeof messageType.data === 'function' && messageType.data(msg)) || {};
+ return TAPi18n.__(messageType.message, data, language);
+ }
+ }
+ if (msg.u && msg.u.username === RocketChat.settings.get('Chatops_Username')) {
+ msg.html = msg.msg;
+ return msg.html;
+ }
+ msg.html = msg.msg;
+ if (s.trim(msg.html) !== '') {
+ msg.html = s.escapeHTML(msg.html);
+ }
+ msg.html = msg.html.replace(/\n/gm, '
');
+ return msg.html;
+ }
+};
diff --git a/packages/rocketchat-lib/lib/MessageTypes.coffee b/packages/rocketchat-lib/lib/MessageTypes.coffee
deleted file mode 100644
index 7912e7fb943de..0000000000000
--- a/packages/rocketchat-lib/lib/MessageTypes.coffee
+++ /dev/null
@@ -1,112 +0,0 @@
-RocketChat.MessageTypes = new class
- types = {}
-
- registerType = (options) ->
- types[options.id] = options
-
- getType = (message) ->
- return types[message?.t]
-
- isSystemMessage = (message) ->
- return types[message?.t]?.system
-
- registerType: registerType
- getType: getType
- isSystemMessage: isSystemMessage
-
-Meteor.startup ->
- RocketChat.MessageTypes.registerType
- id: 'r'
- system: true
- message: 'Room_name_changed'
- data: (message) ->
- return { room_name: message.msg, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'au'
- system: true
- message: 'User_added_by'
- data: (message) ->
- return { user_added: message.msg, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'ru'
- system: true
- message: 'User_removed_by'
- data: (message) ->
- return { user_removed: message.msg, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'ul'
- system: true
- message: 'User_left'
- data: (message) ->
- return { user_left: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'uj'
- system: true
- message: 'User_joined_channel'
- data: (message) ->
- return { user: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'wm'
- system: true
- message: 'Welcome'
- data: (message) ->
- return { user: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'rm'
- system: true
- message: 'Message_removed'
- data: (message) ->
- return { user: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'rtc'
- render: (message) ->
- RocketChat.callbacks.run 'renderRtcMessage', message
-
- RocketChat.MessageTypes.registerType
- id: 'user-muted'
- system: true
- message: 'User_muted_by'
- data: (message) ->
- return { user_muted: message.msg, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'user-unmuted'
- system: true
- message: 'User_unmuted_by'
- data: (message) ->
- return { user_unmuted: message.msg, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'subscription-role-added'
- system: true
- message: '__username__was_set__role__by__user_by_'
- data: (message) ->
- return { username: message.msg, role: message.role, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'subscription-role-removed'
- system: true
- message: '__username__is_no_longer__role__defined_by__user_by_'
- data: (message) ->
- return { username: message.msg, role: message.role, user_by: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'room-archived'
- system: true
- message: 'This_room_has_been_archived_by__username_'
- data: (message) ->
- return { username: message.u.username }
-
- RocketChat.MessageTypes.registerType
- id: 'room-unarchived'
- system: true
- message: 'This_room_has_been_unarchived_by__username_'
- data: (message) ->
- return { username: message.u.username }
diff --git a/packages/rocketchat-lib/lib/MessageTypes.js b/packages/rocketchat-lib/lib/MessageTypes.js
new file mode 100644
index 0000000000000..db57c899ad683
--- /dev/null
+++ b/packages/rocketchat-lib/lib/MessageTypes.js
@@ -0,0 +1,167 @@
+RocketChat.MessageTypes = new class {
+ constructor() {
+ this.types = {};
+ }
+
+ registerType(options) {
+ return this.types[options.id] = options;
+ }
+
+ getType(message) {
+ return this.types[message && message.t];
+ }
+
+ isSystemMessage(message) {
+ const type = this.types[message && message.t];
+ return type && type.system;
+ }
+
+};
+
+Meteor.startup(function() {
+ RocketChat.MessageTypes.registerType({
+ id: 'r',
+ system: true,
+ message: 'Room_name_changed',
+ data(message) {
+ return {
+ room_name: message.msg,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'au',
+ system: true,
+ message: 'User_added_by',
+ data(message) {
+ return {
+ user_added: message.msg,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'ru',
+ system: true,
+ message: 'User_removed_by',
+ data(message) {
+ return {
+ user_removed: message.msg,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'ul',
+ system: true,
+ message: 'User_left',
+ data(message) {
+ return {
+ user_left: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'uj',
+ system: true,
+ message: 'User_joined_channel',
+ data(message) {
+ return {
+ user: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'wm',
+ system: true,
+ message: 'Welcome',
+ data(message) {
+ return {
+ user: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'rm',
+ system: true,
+ message: 'Message_removed',
+ data(message) {
+ return {
+ user: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'rtc',
+ render(message) {
+ return RocketChat.callbacks.run('renderRtcMessage', message);
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'user-muted',
+ system: true,
+ message: 'User_muted_by',
+ data(message) {
+ return {
+ user_muted: message.msg,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'user-unmuted',
+ system: true,
+ message: 'User_unmuted_by',
+ data(message) {
+ return {
+ user_unmuted: message.msg,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'subscription-role-added',
+ system: true,
+ message: '__username__was_set__role__by__user_by_',
+ data(message) {
+ return {
+ username: message.msg,
+ role: message.role,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'subscription-role-removed',
+ system: true,
+ message: '__username__is_no_longer__role__defined_by__user_by_',
+ data(message) {
+ return {
+ username: message.msg,
+ role: message.role,
+ user_by: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'room-archived',
+ system: true,
+ message: 'This_room_has_been_archived_by__username_',
+ data(message) {
+ return {
+ username: message.u.username
+ };
+ }
+ });
+ RocketChat.MessageTypes.registerType({
+ id: 'room-unarchived',
+ system: true,
+ message: 'This_room_has_been_unarchived_by__username_',
+ data(message) {
+ return {
+ username: message.u.username
+ };
+ }
+ });
+});
diff --git a/packages/rocketchat-lib/lib/RoomTypeConfig.js b/packages/rocketchat-lib/lib/RoomTypeConfig.js
new file mode 100644
index 0000000000000..43027c05dada6
--- /dev/null
+++ b/packages/rocketchat-lib/lib/RoomTypeConfig.js
@@ -0,0 +1,204 @@
+export const RoomSettingsEnum = {
+ NAME: 'roomName',
+ TOPIC: 'roomTopic',
+ ANNOUNCEMENT: 'roomAnnouncement',
+ DESCRIPTION: 'roomDescription',
+ READ_ONLY: 'readOnly',
+ REACT_WHEN_READ_ONLY: 'reactWhenReadOnly',
+ ARCHIVE_OR_UNARCHIVE: 'archiveOrUnarchive',
+ JOIN_CODE: 'joinCode'
+};
+
+export const UiTextContext = {
+ CLOSE_WARNING: 'closeWarning',
+ HIDE_WARNING: 'hideWarning',
+ LEAVE_WARNING: 'leaveWarning',
+ NO_ROOMS_SUBSCRIBED: 'noRoomsSubscribed'
+};
+
+export class RoomTypeRouteConfig {
+ constructor({ name, path }) {
+ if (typeof name !== 'undefined' && (typeof name !== 'string' || name.length === 0)) {
+ throw new Error('The name must be a string.');
+ }
+
+ if (typeof path !== 'undefined' && (typeof path !== 'string' || path.length === 0)) {
+ throw new Error('The path must be a string.');
+ }
+
+ this._name = name;
+ this._path = path;
+ }
+
+ get name() {
+ return this._name;
+ }
+
+ get path() {
+ return this._path;
+ }
+}
+
+export class RoomTypeConfig {
+ constructor({
+ identifier = Random.id(),
+ order,
+ icon,
+ header,
+ label,
+ route
+ }) {
+ if (typeof identifier !== 'string' || identifier.length === 0) {
+ throw new Error('The identifier must be a string.');
+ }
+
+ if (typeof order !== 'number') {
+ throw new Error('The order must be a number.');
+ }
+
+ if (typeof icon !== 'undefined' && (typeof icon !== 'string' || icon.length === 0)) {
+ throw new Error('The icon must be a string.');
+ }
+
+ if (typeof header !== 'undefined' && (typeof header !== 'string' || header.length === 0)) {
+ throw new Error('The header must be a string.');
+ }
+
+ if (typeof label !== 'undefined' && (typeof label !== 'string' || label.length === 0)) {
+ throw new Error('The label must be a string.');
+ }
+
+ if (typeof route !== 'undefined' && !(route instanceof RoomTypeRouteConfig)) {
+ throw new Error('Room\'s route is not a valid route configuration. Must be an instance of "RoomTypeRouteConfig".');
+ }
+
+ this._identifier = identifier;
+ this._order = order;
+ this._icon = icon;
+ this._header = header;
+ this._label = label;
+ this._route = route;
+ }
+
+ /**
+ * The room type's internal identifier.
+ */
+ get identifier() {
+ return this._identifier;
+ }
+
+ /**
+ * The order of this room type for the display.
+ */
+ get order() {
+ return this._order;
+ }
+
+ /**
+ * Sets the order of this room type for the display.
+ *
+ * @param {number} order the number value for the order
+ */
+ set order(order) {
+ if (typeof order !== 'number') {
+ throw new Error('The order must be a number.');
+ }
+
+ this._order = order;
+ }
+
+ /**
+ * The icon class, css, to use as the visual aid.
+ */
+ get icon() {
+ return this._icon;
+ }
+
+ /**
+ * The header name of this type.
+ */
+ get header() {
+ return this._header;
+ }
+
+ /**
+ * The i18n label for this room type.
+ */
+ get label() {
+ return this._label;
+ }
+
+ /**
+ * The route config for this room type.
+ */
+ get route() {
+ return this._route;
+ }
+
+ /**
+ * Gets the room's name to display in the UI.
+ *
+ * @param {object} room
+ */
+ getDisplayName(room) {
+ return room.name;
+ }
+
+ allowRoomSettingChange(/* room, setting */) {
+ return true;
+ }
+
+ canBeCreated() {
+ return Meteor.isServer ?
+ RocketChat.authz.hasAtLeastOnePermission(Meteor.userId(), [`create-${ this._identifier }`]) :
+ RocketChat.authz.hasAtLeastOnePermission([`create-${ this._identifier }`]);
+ }
+
+ canBeDeleted(room) {
+ return Meteor.isServer ?
+ RocketChat.authz.hasAtLeastOnePermission(Meteor.userId(), [`delete-${ room.t }`], room._id) :
+ RocketChat.authz.hasAtLeastOnePermission([`delete-${ room.t }`], room._id);
+ }
+
+ supportMembersList(/* room */) {
+ return true;
+ }
+
+ isGroupChat() {
+ return false;
+ }
+
+ canAddUser(/* userId, room */) {
+ return false;
+ }
+
+ userDetailShowAll(/* room */) {
+ return true;
+ }
+
+ userDetailShowAdmin(/* room */) {
+ return true;
+ }
+
+ preventRenaming(/* room */) {
+ return false;
+ }
+
+ includeInRoomSearch() {
+ return false;
+ }
+
+ enableMembersListProfile() {
+ return false;
+ }
+
+ /**
+ * Returns a text which can be used in generic UIs.
+ * @param context The role of the text in the UI-Element
+ * @return {string} A text or a translation key - the consumers of this method will pass the
+ * returned value to an internationalization library
+ */
+ getUiText(/* context */) {
+ return '';
+ }
+}
diff --git a/packages/rocketchat-lib/lib/RoomTypesCommon.js b/packages/rocketchat-lib/lib/RoomTypesCommon.js
new file mode 100644
index 0000000000000..e7cead3d9dded
--- /dev/null
+++ b/packages/rocketchat-lib/lib/RoomTypesCommon.js
@@ -0,0 +1,93 @@
+/* globals roomExit */
+import { RoomTypeConfig } from './RoomTypeConfig';
+
+export class RoomTypesCommon {
+ constructor() {
+ this.roomTypes = {};
+ this.roomTypesOrder = [];
+ this.mainOrder = 1;
+ }
+
+ /**
+ * Adds a room type to the application.
+ *
+ * @param {RoomTypeConfig} roomConfig
+ * @returns {void}
+ */
+ add(roomConfig) {
+ if (!(roomConfig instanceof RoomTypeConfig)) {
+ throw new Error('Invalid Room Configuration object, it must extend "RoomTypeConfig"');
+ }
+
+ if (this.roomTypes[roomConfig.identifier]) {
+ return false;
+ }
+
+ if (!roomConfig.order) {
+ roomConfig.order = this.mainOrder + 10;
+ this.mainOrder += 10;
+ }
+
+ this.roomTypesOrder.push({
+ identifier: roomConfig.identifier,
+ order: roomConfig.order
+ });
+
+ this.roomTypes[roomConfig.identifier] = roomConfig;
+
+ if (roomConfig.route && roomConfig.route.path && roomConfig.route.name && roomConfig.route.action) {
+ const routeConfig = {
+ name: roomConfig.route.name,
+ action: roomConfig.route.action
+ };
+
+ if (Meteor.isClient) {
+ routeConfig.triggersExit = [roomExit];
+ }
+
+ return FlowRouter.route(roomConfig.route.path, routeConfig);
+ }
+ }
+
+ hasCustomLink(roomType) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link != null;
+ }
+
+ /**
+ * @param {string} roomType room type (e.g.: c (for channels), d (for direct channels))
+ * @param {object} subData the user's subscription data
+ */
+ getRouteLink(roomType, subData) {
+ if (!this.roomTypes[roomType]) {
+ return false;
+ }
+
+ let routeData = {};
+ if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) {
+ routeData = this.roomTypes[roomType].route.link(subData);
+ } else if (subData && subData.name) {
+ routeData = {
+ name: subData.name
+ };
+ }
+
+ return FlowRouter.path(this.roomTypes[roomType].route.name, routeData);
+ }
+
+ openRouteLink(roomType, subData, queryParams) {
+ if (!this.roomTypes[roomType]) {
+ return false;
+ }
+
+ let routeData = {};
+ if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) {
+ routeData = this.roomTypes[roomType].route.link(subData);
+ } else if (subData && subData.name) {
+ routeData = {
+ name: subData.name
+ };
+ }
+
+ return FlowRouter.go(this.roomTypes[roomType].route.name, routeData, queryParams);
+ }
+}
diff --git a/packages/rocketchat-lib/lib/callbacks.coffee b/packages/rocketchat-lib/lib/callbacks.coffee
deleted file mode 100644
index 7cda012cb30b5..0000000000000
--- a/packages/rocketchat-lib/lib/callbacks.coffee
+++ /dev/null
@@ -1,129 +0,0 @@
-# https://github.com/TelescopeJS/Telescope/blob/master/packages/telescope-lib/lib/callbacks.js
-
-###
-# Callback hooks provide an easy way to add extra steps to common operations.
-# @namespace RocketChat.callbacks
-###
-RocketChat.callbacks = {}
-
-if Meteor.isServer
- RocketChat.callbacks.showTime = true
- RocketChat.callbacks.showTotalTime = true
-else
- RocketChat.callbacks.showTime = false
- RocketChat.callbacks.showTotalTime = false
-
-###
-# Callback priorities
-###
-RocketChat.callbacks.priority =
- HIGH: -1000
- MEDIUM: 0
- LOW: 1000
-
-###
-# Add a callback function to a hook
-# @param {String} hook - The name of the hook
-# @param {Function} callback - The callback function
-###
-RocketChat.callbacks.add = (hook, callback, priority, id) ->
- # if callback array doesn't exist yet, initialize it
- priority ?= RocketChat.callbacks.priority.MEDIUM
- unless _.isNumber priority
- priority = RocketChat.callbacks.priority.MEDIUM
- callback.priority = priority
- callback.id = id or Random.id()
- RocketChat.callbacks[hook] ?= []
-
- if RocketChat.callbacks.showTime is true
- err = new Error
- callback.stack = err.stack
-
- # if not id?
- # console.log('Callback without id', callback.stack)
-
- # Avoid adding the same callback twice
- for cb in RocketChat.callbacks[hook]
- if cb.id is callback.id
- return
-
- RocketChat.callbacks[hook].push callback
- return
-
-###
-# Remove a callback from a hook
-# @param {string} hook - The name of the hook
-# @param {string} id - The callback's id
-###
-
-RocketChat.callbacks.remove = (hookName, id) ->
- RocketChat.callbacks[hookName] = _.reject RocketChat.callbacks[hookName], (callback) ->
- callback.id is id
- return
-
-###
-# Successively run all of a hook's callbacks on an item
-# @param {String} hook - The name of the hook
-# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
-# @param {Object} [constant] - An optional constant that will be passed along to each callback
-# @returns {Object} Returns the item after it's been through all the callbacks for this hook
-###
-
-RocketChat.callbacks.run = (hook, item, constant) ->
- callbacks = RocketChat.callbacks[hook]
- if !!callbacks?.length
- if RocketChat.callbacks.showTotalTime is true
- totalTime = 0
-
- # if the hook exists, and contains callbacks to run
- result = _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.callbacks.priority.MEDIUM).reduce (result, callback) ->
- # console.log(callback.name);
- if RocketChat.callbacks.showTime is true or RocketChat.callbacks.showTotalTime is true
- time = Date.now()
-
- callbackResult = callback result, constant
-
- if RocketChat.callbacks.showTime is true or RocketChat.callbacks.showTotalTime is true
- currentTime = Date.now() - time
- totalTime += currentTime
- if RocketChat.callbacks.showTime is true
- if Meteor.isServer
- RocketChat.statsTracker.timing('callbacks.time', currentTime, ["hook:#{hook}", "callback:#{callback.id}"]);
- else
- console.log String(currentTime), hook, callback.id, callback.stack?.split?('\n')[2]?.match(/\(.+\)/)?[0]
-
- return callbackResult
- , item
-
- if RocketChat.callbacks.showTotalTime is true
- if Meteor.isServer
- RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, ["hook:#{hook}"]);
- else
- console.log hook+':', totalTime
-
- return result
- else
- # else, just return the item unchanged
- return item
-
-###
-# Successively run all of a hook's callbacks on an item, in async mode (only works on server)
-# @param {String} hook - The name of the hook
-# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
-# @param {Object} [constant] - An optional constant that will be passed along to each callback
-###
-
-RocketChat.callbacks.runAsync = (hook, item, constant) ->
- callbacks = RocketChat.callbacks[hook]
- if Meteor.isServer and !!callbacks?.length
- # use defer to avoid holding up client
- Meteor.defer ->
- # run all post submit server callbacks on post object successively
- _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.callbacks.priority.MEDIUM).forEach (callback) ->
- # console.log(callback.name);
- callback item, constant
- return
- return
- else
- return item
- return
diff --git a/packages/rocketchat-lib/lib/callbacks.js b/packages/rocketchat-lib/lib/callbacks.js
new file mode 100644
index 0000000000000..f4f8e70865acd
--- /dev/null
+++ b/packages/rocketchat-lib/lib/callbacks.js
@@ -0,0 +1,133 @@
+import _ from 'underscore';
+
+/*
+* Callback hooks provide an easy way to add extra steps to common operations.
+* @namespace RocketChat.callbacks
+*/
+
+RocketChat.callbacks = {};
+
+if (Meteor.isServer) {
+ RocketChat.callbacks.showTime = true;
+ RocketChat.callbacks.showTotalTime = true;
+} else {
+ RocketChat.callbacks.showTime = false;
+ RocketChat.callbacks.showTotalTime = false;
+}
+
+
+/*
+* Callback priorities
+*/
+
+RocketChat.callbacks.priority = {
+ HIGH: -1000,
+ MEDIUM: 0,
+ LOW: 1000
+};
+
+
+/*
+* Add a callback function to a hook
+* @param {String} hook - The name of the hook
+* @param {Function} callback - The callback function
+*/
+
+RocketChat.callbacks.add = function(hook, callback, priority, id) {
+ if (priority == null) {
+ priority = RocketChat.callbacks.priority.MEDIUM;
+ }
+ if (!_.isNumber(priority)) {
+ priority = RocketChat.callbacks.priority.MEDIUM;
+ }
+ callback.priority = priority;
+ callback.id = id || Random.id();
+ RocketChat.callbacks[hook] = RocketChat.callbacks[hook] || [];
+ if (RocketChat.callbacks.showTime === true) {
+ const err = new Error;
+ callback.stack = err.stack;
+ }
+ if (RocketChat.callbacks[hook].find((cb) => cb.id === callback.id)) {
+ return;
+ }
+ RocketChat.callbacks[hook].push(callback);
+};
+
+
+/*
+* Remove a callback from a hook
+* @param {string} hook - The name of the hook
+* @param {string} id - The callback's id
+*/
+
+RocketChat.callbacks.remove = function(hookName, id) {
+ RocketChat.callbacks[hookName] = _.reject(RocketChat.callbacks[hookName], (callback) => callback.id === id);
+};
+
+
+/*
+* Successively run all of a hook's callbacks on an item
+* @param {String} hook - The name of the hook
+* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
+* @param {Object} [constant] - An optional constant that will be passed along to each callback
+* @returns {Object} Returns the item after it's been through all the callbacks for this hook
+*/
+
+RocketChat.callbacks.run = function(hook, item, constant) {
+ const callbacks = RocketChat.callbacks[hook];
+ if (callbacks && callbacks.length) {
+ let totalTime = 0;
+ const result = _.sortBy(callbacks, function(callback) {
+ return callback.priority || RocketChat.callbacks.priority.MEDIUM;
+ }).reduce(function(result, callback) {
+ let time = 0;
+ if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
+ time = Date.now();
+ }
+ const callbackResult = callback(result, constant);
+ if (RocketChat.callbacks.showTime === true || RocketChat.callbacks.showTotalTime === true) {
+ const currentTime = Date.now() - time;
+ totalTime += currentTime;
+ if (RocketChat.callbacks.showTime === true) {
+ if (Meteor.isServer) {
+ RocketChat.statsTracker.timing('callbacks.time', currentTime, [`hook:${ hook }`, `callback:${ callback.id }`]);
+ } else {
+ let stack = callback.stack && typeof callback.stack.split === 'function' && callback.stack.split('\n');
+ stack = stack && stack[2] && (stack[2].match(/\(.+\)/)||[])[0];
+ console.log(String(currentTime), hook, callback.id, stack);
+ }
+ }
+ }
+ return (typeof callbackResult === 'undefined') ? result : callbackResult;
+ }, item);
+ if (RocketChat.callbacks.showTotalTime === true) {
+ if (Meteor.isServer) {
+ RocketChat.statsTracker.timing('callbacks.totalTime', totalTime, [`hook:${ hook }`]);
+ } else {
+ console.log(`${ hook }:`, totalTime);
+ }
+ }
+ return result;
+ } else {
+ return item;
+ }
+};
+
+
+/*
+* Successively run all of a hook's callbacks on an item, in async mode (only works on server)
+* @param {String} hook - The name of the hook
+* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
+* @param {Object} [constant] - An optional constant that will be passed along to each callback
+*/
+
+RocketChat.callbacks.runAsync = function(hook, item, constant) {
+ const callbacks = RocketChat.callbacks[hook];
+ if (Meteor.isServer && callbacks && callbacks.length) {
+ Meteor.defer(function() {
+ _.sortBy(callbacks, (callback) => callback.priority || RocketChat.callbacks.priority.MEDIUM).forEach((callback) => callback(item, constant));
+ });
+ } else {
+ return item;
+ }
+};
diff --git a/packages/rocketchat-lib/lib/configLogger.coffee b/packages/rocketchat-lib/lib/configLogger.coffee
deleted file mode 100644
index 37496802ad5ef..0000000000000
--- a/packages/rocketchat-lib/lib/configLogger.coffee
+++ /dev/null
@@ -1,12 +0,0 @@
-RocketChat.settings.get 'Log_Package', (key, value) ->
- LoggerManager?.showPackage = value
-
-RocketChat.settings.get 'Log_File', (key, value) ->
- LoggerManager?.showFileAndLine = value
-
-RocketChat.settings.get 'Log_Level', (key, value) ->
- if value?
- LoggerManager?.logLevel = parseInt value
- Meteor.setTimeout ->
- LoggerManager?.enable(true)
- , 200
diff --git a/packages/rocketchat-lib/lib/core.coffee b/packages/rocketchat-lib/lib/core.coffee
deleted file mode 100644
index ab59434d54c78..0000000000000
--- a/packages/rocketchat-lib/lib/core.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-###
-# Kick off the global namespace for RocketChat.
-# @namespace RocketChat
-###
-
-RocketChat =
- models: {}
diff --git a/packages/rocketchat-lib/lib/core.js b/packages/rocketchat-lib/lib/core.js
new file mode 100644
index 0000000000000..31abca0cce3d7
--- /dev/null
+++ b/packages/rocketchat-lib/lib/core.js
@@ -0,0 +1,7 @@
+import EventEmitter from 'wolfy87-eventemitter';
+RocketChat = new EventEmitter();
+/*
+* Kick off the global namespace for RocketChat.
+* @namespace RocketChat
+*/
+RocketChat.models = {};
diff --git a/packages/rocketchat-lib/lib/fileUploadRestrictions.js b/packages/rocketchat-lib/lib/fileUploadRestrictions.js
index 69ff860c02531..763d11ca69166 100644
--- a/packages/rocketchat-lib/lib/fileUploadRestrictions.js
+++ b/packages/rocketchat-lib/lib/fileUploadRestrictions.js
@@ -1,5 +1,7 @@
+import _ from 'underscore';
+
RocketChat.fileUploadMediaWhiteList = function() {
- var mediaTypeWhiteList = RocketChat.settings.get('FileUpload_MediaTypeWhiteList');
+ const mediaTypeWhiteList = RocketChat.settings.get('FileUpload_MediaTypeWhiteList');
if (!mediaTypeWhiteList || mediaTypeWhiteList === '*') {
return;
@@ -10,13 +12,20 @@ RocketChat.fileUploadMediaWhiteList = function() {
};
RocketChat.fileUploadIsValidContentType = function(type) {
- var list, wildCardGlob, wildcards;
- list = RocketChat.fileUploadMediaWhiteList();
- if (!list || _.contains(list, type)) {
+ const list = RocketChat.fileUploadMediaWhiteList();
+ if (!list) {
+ return true;
+ }
+
+ if (!type) {
+ return false;
+ }
+
+ if (_.contains(list, type)) {
return true;
} else {
- wildCardGlob = '/*';
- wildcards = _.filter(list, function(item) {
+ const wildCardGlob = '/*';
+ const wildcards = _.filter(list, function(item) {
return item.indexOf(wildCardGlob) > 0;
});
if (_.contains(wildcards, type.replace(/(\/.*)$/, wildCardGlob))) {
diff --git a/packages/rocketchat-lib/lib/getAvatarColor.js b/packages/rocketchat-lib/lib/getAvatarColor.js
new file mode 100644
index 0000000000000..ccc93b345820b
--- /dev/null
+++ b/packages/rocketchat-lib/lib/getAvatarColor.js
@@ -0,0 +1,5 @@
+const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B'];
+
+RocketChat.getAvatarColor = function(name) {
+ return colors[name.length % colors.length];
+};
diff --git a/packages/rocketchat-lib/lib/getURL.js b/packages/rocketchat-lib/lib/getURL.js
index 3965627c10c61..6802a153b713f 100644
--- a/packages/rocketchat-lib/lib/getURL.js
+++ b/packages/rocketchat-lib/lib/getURL.js
@@ -1,10 +1,12 @@
+import s from 'underscore.string';
+
RocketChat.getURL = (path, { cdn = true, full = false } = {}) => {
- const cdnPrefix = _.rtrim(_.trim(RocketChat.settings.get('CDN_PREFIX') || ''), '/');
- const pathPrefix = _.rtrim(_.trim(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''), '/');
+ const cdnPrefix = s.rtrim(s.trim(RocketChat.settings.get('CDN_PREFIX') || ''), '/');
+ const pathPrefix = s.rtrim(s.trim(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''), '/');
let basePath;
- let finalPath = _.ltrim(_.trim(path), '/');
+ const finalPath = s.ltrim(s.trim(path), '/');
if (cdn && cdnPrefix !== '') {
basePath = cdnPrefix + pathPrefix;
@@ -14,5 +16,5 @@ RocketChat.getURL = (path, { cdn = true, full = false } = {}) => {
basePath = pathPrefix;
}
- return basePath + '/' + finalPath;
+ return `${ basePath }/${ finalPath }`;
};
diff --git a/packages/rocketchat-lib/lib/getUserPreference.js b/packages/rocketchat-lib/lib/getUserPreference.js
new file mode 100644
index 0000000000000..1d516996784de
--- /dev/null
+++ b/packages/rocketchat-lib/lib/getUserPreference.js
@@ -0,0 +1,16 @@
+/**
+ * Tries to retrieve the user preference falling back to a default system
+ * value or to a default value if it is passed as argument
+*/
+RocketChat.getUserPreference = function(user, key, defaultValue=undefined) {
+ let preference;
+
+ if (user && user.settings && user.settings.preferences &&
+ user.settings.preferences.hasOwnProperty(key)) {
+ preference = user.settings.preferences[key];
+ } else if (defaultValue === undefined) {
+ preference = RocketChat.settings.get(`Accounts_Default_User_Preferences_${ key }`);
+ }
+
+ return preference !== undefined ? preference : defaultValue;
+};
diff --git a/packages/rocketchat-lib/lib/getValidRoomName.js b/packages/rocketchat-lib/lib/getValidRoomName.js
new file mode 100644
index 0000000000000..48166c003ee25
--- /dev/null
+++ b/packages/rocketchat-lib/lib/getValidRoomName.js
@@ -0,0 +1,48 @@
+import s from 'underscore.string';
+
+RocketChat.getValidRoomName = function getValidRoomName(displayName, serverId, rid = '') {
+ let slugifiedName = displayName;
+
+ if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ const room = RocketChat.models.Rooms.findOneByDisplayName(displayName, serverId);
+ if (room && room._id !== rid) {
+ if (room.archived) {
+ throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ displayName }`, { function: 'RocketChat.getValidRoomName', channel_name: displayName });
+ } else {
+ throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ displayName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: displayName });
+ }
+ }
+ slugifiedName = s.slugify(displayName);
+ }
+
+ let nameValidation;
+ try {
+ nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
+ } catch (error) {
+ nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
+ }
+ if (!nameValidation.test(slugifiedName)) {
+ throw new Meteor.Error('error-invalid-room-name', `${ slugifiedName } is not a valid room name.`, {
+ 'function': 'RocketChat.getValidRoomName',
+ channel_name: slugifiedName
+ });
+ }
+
+ const room = RocketChat.models.Rooms.findOneByName(slugifiedName, serverId);
+ if (room && room._id !== rid) {
+ if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ let tmpName = slugifiedName;
+ let next = 0;
+ while (RocketChat.models.Rooms.findOneByNameAndNotId(tmpName, rid)) {
+ tmpName = `${ slugifiedName }-${ ++next }`;
+ }
+ slugifiedName = tmpName;
+ } else if (room.archived) {
+ throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ slugifiedName }`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName });
+ } else {
+ throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ slugifiedName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName });
+ }
+ }
+
+ return slugifiedName;
+};
diff --git a/packages/rocketchat-lib/lib/messageBox.js b/packages/rocketchat-lib/lib/messageBox.js
new file mode 100644
index 0000000000000..9b5522eff81ce
--- /dev/null
+++ b/packages/rocketchat-lib/lib/messageBox.js
@@ -0,0 +1,60 @@
+RocketChat.messageBox = {};
+
+RocketChat.messageBox.actions = new class {
+ constructor() {
+ this.actions = {};
+ }
+
+ /* Add a action to messagebox
+ @param group
+ @param label
+ @param config
+ icon: icon class
+ action: action function
+ condition: condition to display the action
+ */
+
+ add(group, label, config) {
+ if (!group && !label && !config) {
+ return;
+ }
+
+ if (!this.actions[group]) {
+ this.actions[group] = [];
+ }
+
+ const actionExists = this.actions[group].find((action) => {
+ return action.label === label;
+ });
+
+ if (actionExists) {
+ return;
+ }
+
+ this.actions[group].push({...config, label});
+ }
+
+ get(group) {
+ if (!group) {
+ return Object.keys(this.actions).reduce((ret, key) => {
+ const actions = this.actions[key].filter(action => !action.condition || action.condition());
+ if (actions.length) {
+ ret[key] = actions;
+ }
+ return ret;
+ }, {});
+ }
+
+ return this.actions[group].filter(action => !action.condition || action.condition());
+ }
+
+ getById(id) {
+ const messageActions = this.actions;
+ let actions = [];
+ Object.keys(messageActions).forEach(function(action) {
+ actions = actions.concat(messageActions[action]);
+ });
+
+ return actions.filter(action => action.id === id);
+ }
+};
diff --git a/packages/rocketchat-lib/lib/placeholders.js b/packages/rocketchat-lib/lib/placeholders.js
index 82fb613d050a5..45f996e86173c 100644
--- a/packages/rocketchat-lib/lib/placeholders.js
+++ b/packages/rocketchat-lib/lib/placeholders.js
@@ -1,3 +1,5 @@
+import s from 'underscore.string';
+
RocketChat.placeholders = {};
RocketChat.placeholders.replace = function(str, data) {
@@ -10,10 +12,13 @@ RocketChat.placeholders.replace = function(str, data) {
if (data) {
str = str.replace(/\[name\]/g, data.name || '');
- str = str.replace(/\[fname\]/g, _.strLeft(data.name, ' ') || '');
- str = str.replace(/\[lname\]/g, _.strRightBack(data.name, ' ') || '');
+ str = str.replace(/\[fname\]/g, s.strLeft(data.name, ' ') || '');
+ str = str.replace(/\[lname\]/g, s.strRightBack(data.name, ' ') || '');
str = str.replace(/\[email\]/g, data.email || '');
str = str.replace(/\[password\]/g, data.password || '');
+ str = str.replace(/\[reason\]/g, data.reason || '');
+ str = str.replace(/\[User\]/g, data.user || '');
+ str = str.replace(/\[Room\]/g, data.room || '');
if (data.unsubscribe) {
str = str.replace(/\[unsubscribe\]/g, data.unsubscribe);
diff --git a/packages/rocketchat-lib/lib/promises.coffee b/packages/rocketchat-lib/lib/promises.coffee
deleted file mode 100644
index a23ab907b738c..0000000000000
--- a/packages/rocketchat-lib/lib/promises.coffee
+++ /dev/null
@@ -1,93 +0,0 @@
-# https://github.com/TelescopeJS/Telescope/blob/master/packages/telescope-lib/lib/callbacks.js
-
-###
-# Callback hooks provide an easy way to add extra steps to common operations.
-# @namespace RocketChat.promises
-###
-RocketChat.promises = {}
-
-###
-# Callback priorities
-###
-RocketChat.promises.priority =
- HIGH: -1000
- MEDIUM: 0
- LOW: 1000
-
-###
-# Add a callback function to a hook
-# @param {String} hook - The name of the hook
-# @param {Function} callback - The callback function
-###
-
-RocketChat.promises.add = (hook, callback, priority, id) ->
- # if callback array doesn't exist yet, initialize it
- priority ?= RocketChat.promises.priority.MEDIUM
- unless _.isNumber priority
- priority = RocketChat.promises.priority.MEDIUM
- callback.priority = priority
- callback.id = id or Random.id()
- RocketChat.promises[hook] ?= []
-
- # Avoid adding the same callback twice
- for cb in RocketChat.promises[hook]
- if cb.id is callback.id
- return
-
- RocketChat.promises[hook].push callback
- return
-
-###
-# Remove a callback from a hook
-# @param {string} hook - The name of the hook
-# @param {string} id - The callback's id
-###
-
-RocketChat.promises.remove = (hookName, id) ->
- RocketChat.promises[hookName] = _.reject RocketChat.promises[hookName], (callback) ->
- callback.id is id
- return
-
-###
-# Successively run all of a hook's callbacks on an item
-# @param {String} hook - The name of the hook
-# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
-# @param {Object} [constant] - An optional constant that will be passed along to each callback
-# @returns {Object} Returns the item after it's been through all the callbacks for this hook
-###
-
-RocketChat.promises.run = (hook, item, constant) ->
- callbacks = RocketChat.promises[hook]
- if !!callbacks?.length
- # if the hook exists, and contains callbacks to run
- callbacks = _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.promises.priority.MEDIUM)
- return callbacks.reduce (previousPromise, callback) ->
- return new Promise (resolve, reject) ->
- previousPromise.then (result) ->
- callback(result, constant).then(resolve, reject)
- , Promise.resolve(item)
- else
- # else, just return the item unchanged
- return Promise.resolve(item)
-
-###
-# Successively run all of a hook's callbacks on an item, in async mode (only works on server)
-# @param {String} hook - The name of the hook
-# @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
-# @param {Object} [constant] - An optional constant that will be passed along to each callback
-###
-
-RocketChat.promises.runAsync = (hook, item, constant) ->
- callbacks = RocketChat.promises[hook]
- if Meteor.isServer and !!callbacks?.length
- # use defer to avoid holding up client
- Meteor.defer ->
- # run all post submit server callbacks on post object successively
- _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.promises.priority.MEDIUM).forEach (callback) ->
- # console.log(callback.name);
- callback item, constant
- return
- return
- else
- return item
- return
diff --git a/packages/rocketchat-lib/lib/promises.js b/packages/rocketchat-lib/lib/promises.js
new file mode 100644
index 0000000000000..6a52e562ae912
--- /dev/null
+++ b/packages/rocketchat-lib/lib/promises.js
@@ -0,0 +1,90 @@
+import _ from 'underscore';
+
+/*
+* Callback hooks provide an easy way to add extra steps to common operations.
+* @namespace RocketChat.promises
+*/
+
+RocketChat.promises = {};
+
+
+/*
+* Callback priorities
+*/
+
+RocketChat.promises.priority = {
+ HIGH: -1000,
+ MEDIUM: 0,
+ LOW: 1000
+};
+
+
+/*
+* Add a callback function to a hook
+* @param {String} hook - The name of the hook
+* @param {Function} callback - The callback function
+*/
+
+RocketChat.promises.add = function(hook, callback, p = RocketChat.promises.priority.MEDIUM, id) {
+ const priority = !_.isNumber(p) ? RocketChat.promises.priority.MEDIUM : p;
+ callback.priority = priority;
+ callback.id = id || Random.id();
+ RocketChat.promises[hook] = RocketChat.promises[hook] || [];
+ if (RocketChat.promises[hook].find(cb => cb.id === callback.id)) {
+ return;
+ }
+ RocketChat.promises[hook].push(callback);
+};
+
+
+/*
+* Remove a callback from a hook
+* @param {string} hook - The name of the hook
+* @param {string} id - The callback's id
+*/
+
+RocketChat.promises.remove = function(hookName, id) {
+ RocketChat.promises[hookName] = _.reject(RocketChat.promises[hookName], (callback) => callback.id === id);
+};
+
+
+/*
+* Successively run all of a hook's callbacks on an item
+* @param {String} hook - The name of the hook
+* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
+* @param {Object} [constant] - An optional constant that will be passed along to each callback
+* @returns {Object} Returns the item after it's been through all the callbacks for this hook
+*/
+
+RocketChat.promises.run = function(hook, item, constant) {
+ let callbacks = RocketChat.promises[hook];
+ if (callbacks == null || callbacks.length === 0) {
+ return Promise.resolve(item);
+ }
+ callbacks = _.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM);
+ return callbacks.reduce(function(previousPromise, callback) {
+ return new Promise(function(resolve, reject) {
+ return previousPromise.then((result) => callback(result, constant).then(resolve, reject));
+ });
+ }, Promise.resolve(item));
+};
+
+
+/*
+* Successively run all of a hook's callbacks on an item, in async mode (only works on server)
+* @param {String} hook - The name of the hook
+* @param {Object} item - The post, comment, modifier, etc. on which to run the callbacks
+* @param {Object} [constant] - An optional constant that will be passed along to each callback
+*/
+
+RocketChat.promises.runAsync = function(hook, item, constant) {
+ const callbacks = RocketChat.promises[hook];
+ if (!Meteor.isServer || callbacks == null || callbacks.length === 0) {
+ return item;
+ }
+ Meteor.defer(() => {
+ _.sortBy(callbacks, (callback) => callback.priority || RocketChat.promises.priority.MEDIUM).forEach(function(callback) {
+ callback(item, constant);
+ });
+ });
+};
diff --git a/packages/rocketchat-lib/lib/roomTypes/conversation.js b/packages/rocketchat-lib/lib/roomTypes/conversation.js
new file mode 100644
index 0000000000000..4d7e53c3bf4e3
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/conversation.js
@@ -0,0 +1,16 @@
+import { RoomTypeConfig } from '../RoomTypeConfig';
+
+export class ConversationRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'merged',
+ order: 60,
+ label: 'Conversations'
+ });
+ }
+
+ condition() {
+ const user = Meteor.user();
+ return RocketChat.getUserPreference(user, 'mergeChannels');
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypes/direct.js b/packages/rocketchat-lib/lib/roomTypes/direct.js
new file mode 100644
index 0000000000000..ca87c31373f1c
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/direct.js
@@ -0,0 +1,114 @@
+/* globals openRoom */
+import {RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext} from '../RoomTypeConfig';
+
+export class DirectMessageRoomRoute extends RoomTypeRouteConfig {
+ constructor() {
+ super({
+ name: 'direct',
+ path: '/direct/:username'
+ });
+ }
+
+ action(params) {
+ return openRoom('d', params.username);
+ }
+
+ link(sub) {
+ return {username: sub.name};
+ }
+}
+
+export class DirectMessageRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'd',
+ order: 30,
+ label: 'Direct_Messages',
+ route: new DirectMessageRoomRoute()
+ });
+ }
+
+ findRoom(identifier) {
+ const query = {
+ t: 'd',
+ name: identifier
+ };
+
+ const subscription = ChatSubscription.findOne(query);
+ if (subscription && subscription.rid) {
+ return ChatRoom.findOne(subscription.rid);
+ }
+ }
+
+ roomName(roomData) {
+ const subscription = ChatSubscription.findOne({rid: roomData._id}, {fields: {name: 1, fname: 1}});
+ if (!subscription) {
+ return '';
+ }
+
+ if (RocketChat.settings.get('UI_Use_Real_Name') && subscription.fname) {
+ return subscription.fname;
+ }
+
+ return subscription.name;
+ }
+
+ secondaryRoomName(roomData) {
+ if (RocketChat.settings.get('UI_Use_Real_Name')) {
+ const subscription = ChatSubscription.findOne({rid: roomData._id}, {fields: {name: 1}});
+ return subscription && subscription.name;
+ }
+ }
+
+ condition() {
+ const user = Meteor.user();
+ const mergeChannels = RocketChat.getUserPreference(user, 'mergeChannels');
+ return !mergeChannels && RocketChat.authz.hasAtLeastOnePermission(['view-d-room', 'view-joined-room']);
+ }
+
+ getUserStatus(roomId) {
+ const subscription = RocketChat.models.Subscriptions.findOne({rid: roomId});
+ if (subscription == null) {
+ return;
+ }
+
+ return Session.get(`user_${ subscription.name }_status`);
+ }
+
+ getDisplayName(room) {
+ return room.usernames.join(' x ');
+ }
+
+ allowRoomSettingChange(room, setting) {
+ switch (setting) {
+ case RoomSettingsEnum.NAME:
+ case RoomSettingsEnum.DESCRIPTION:
+ case RoomSettingsEnum.READ_ONLY:
+ case RoomSettingsEnum.REACT_WHEN_READ_ONLY:
+ case RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE:
+ case RoomSettingsEnum.JOIN_CODE:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ enableMembersListProfile() {
+ return true;
+ }
+
+ userDetailShowAll(/* room */) {
+ return false;
+ }
+
+ getUiText(context) {
+ switch (context) {
+ case UiTextContext.HIDE_WARNING:
+ return 'Hide_Private_Warning';
+ case UiTextContext.LEAVE_WARNING:
+ return 'Leave_Private_Warning';
+ default:
+ return '';
+ }
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypes/favorite.js b/packages/rocketchat-lib/lib/roomTypes/favorite.js
new file mode 100644
index 0000000000000..8f69af9701d13
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/favorite.js
@@ -0,0 +1,17 @@
+import { RoomTypeConfig } from '../RoomTypeConfig';
+
+export class FavoriteRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'f',
+ order: 10,
+ header: 'favorite',
+ icon: 'star',
+ label: 'Favorites'
+ });
+ }
+ condition() {
+ const user = Meteor.user();
+ return RocketChat.settings.get('Favorite_Rooms') && RocketChat.getUserPreference(user, 'sidebarShowFavorites');
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypes/index.js b/packages/rocketchat-lib/lib/roomTypes/index.js
new file mode 100644
index 0000000000000..4c0fd94d732d1
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/index.js
@@ -0,0 +1,15 @@
+import { ConversationRoomType } from './conversation';
+import { DirectMessageRoomType } from './direct';
+import { FavoriteRoomType } from './favorite';
+import { PrivateRoomType } from './private';
+import { PublicRoomType } from './public';
+import { UnreadRoomType } from './unread';
+
+export {
+ ConversationRoomType,
+ DirectMessageRoomType,
+ FavoriteRoomType,
+ PrivateRoomType,
+ PublicRoomType,
+ UnreadRoomType
+};
diff --git a/packages/rocketchat-lib/lib/roomTypes/private.js b/packages/rocketchat-lib/lib/roomTypes/private.js
new file mode 100644
index 0000000000000..787d196a71114
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/private.js
@@ -0,0 +1,82 @@
+/* globals openRoom */
+import {RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext} from '../RoomTypeConfig';
+
+export class PrivateRoomRoute extends RoomTypeRouteConfig {
+ constructor() {
+ super({
+ name: 'group',
+ path: '/group/:name'
+ });
+ }
+
+ action(params) {
+ return openRoom('p', params.name);
+ }
+}
+
+export class PrivateRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'p',
+ order: 50,
+ icon: 'lock',
+ label: 'Private_Groups',
+ route: new PrivateRoomRoute()
+ });
+ }
+
+ findRoom(identifier) {
+ const query = {
+ t: 'p',
+ name: identifier
+ };
+
+ return ChatRoom.findOne(query);
+ }
+
+ roomName(roomData) {
+ if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ return roomData.fname || roomData.name;
+ }
+
+ return roomData.name;
+ }
+
+ condition() {
+ const user = Meteor.user();
+ const mergeChannels = RocketChat.getUserPreference(user, 'mergeChannels');
+ return !mergeChannels && RocketChat.authz.hasAllPermission('view-p-room');
+ }
+
+ isGroupChat() {
+ return true;
+ }
+
+ canAddUser(room) {
+ return RocketChat.authz.hasAtLeastOnePermission(['add-user-to-any-p-room', 'add-user-to-joined-room'], room._id);
+ }
+
+ allowRoomSettingChange(room, setting) {
+ switch (setting) {
+ case RoomSettingsEnum.JOIN_CODE:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ enableMembersListProfile() {
+ return true;
+ }
+
+ getUiText(context) {
+ switch (context) {
+ case UiTextContext.HIDE_WARNING:
+ return 'Hide_Group_Warning';
+ case UiTextContext.LEAVE_WARNING:
+ return 'Leave_Group_Warning';
+ default:
+ return '';
+ }
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypes/public.js b/packages/rocketchat-lib/lib/roomTypes/public.js
new file mode 100644
index 0000000000000..8c7cc07995048
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/public.js
@@ -0,0 +1,84 @@
+/* globals openRoom */
+import {RoomTypeConfig, RoomTypeRouteConfig, UiTextContext} from '../RoomTypeConfig';
+
+export class PublicRoomRoute extends RoomTypeRouteConfig {
+ constructor() {
+ super({
+ name: 'channel',
+ path: '/channel/:name'
+ });
+ }
+
+ action(params) {
+ return openRoom('c', params.name);
+ }
+}
+
+export class PublicRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'c',
+ order: 40,
+ icon: 'hashtag',
+ label: 'Channels',
+ route: new PublicRoomRoute()
+ });
+ }
+
+ findRoom(identifier) {
+ const query = {
+ t: 'c',
+ name: identifier
+ };
+ return ChatRoom.findOne(query);
+ }
+
+ roomName(roomData) {
+ if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
+ return roomData.fname || roomData.name;
+ }
+ return roomData.name;
+ }
+
+ condition() {
+ const user = Meteor.user();
+ // const roomsListExhibitionMode = RocketChat.getUserPreference(user, 'roomsListExhibitionMode');
+ const mergeChannels = RocketChat.getUserPreference(user, 'mergeChannels');
+ return !mergeChannels && (RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousRead') === true);
+ }
+
+ showJoinLink(roomId) {
+ return !!ChatRoom.findOne({_id: roomId, t: 'c'});
+ }
+
+ includeInRoomSearch() {
+ return true;
+ }
+
+ isGroupChat() {
+ return true;
+ }
+
+ canAddUser(room) {
+ return RocketChat.authz.hasAtLeastOnePermission(['add-user-to-any-c-room', 'add-user-to-joined-room'], room._id);
+ }
+
+ allowRoomSettingChange() {
+ return true;
+ }
+
+ enableMembersListProfile() {
+ return true;
+ }
+
+ getUiText(context) {
+ switch (context) {
+ case UiTextContext.HIDE_WARNING:
+ return 'Hide_Room_Warning';
+ case UiTextContext.LEAVE_WARNING:
+ return 'Leave_Room_Warning';
+ default:
+ return '';
+ }
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypes/unread.js b/packages/rocketchat-lib/lib/roomTypes/unread.js
new file mode 100644
index 0000000000000..f67109310face
--- /dev/null
+++ b/packages/rocketchat-lib/lib/roomTypes/unread.js
@@ -0,0 +1,18 @@
+import { RoomTypeConfig } from '../RoomTypeConfig';
+
+export class UnreadRoomType extends RoomTypeConfig {
+ constructor() {
+ super({
+ identifier: 'unread',
+ order: 20,
+ label: 'Unread'
+ });
+
+ this.unread = true;
+ }
+
+ condition() {
+ const user = Meteor.user();
+ return RocketChat.getUserPreference(user, 'sidebarShowUnread');
+ }
+}
diff --git a/packages/rocketchat-lib/lib/roomTypesCommon.coffee b/packages/rocketchat-lib/lib/roomTypesCommon.coffee
deleted file mode 100644
index a351dc258922d..0000000000000
--- a/packages/rocketchat-lib/lib/roomTypesCommon.coffee
+++ /dev/null
@@ -1,75 +0,0 @@
-class @roomTypesCommon
- roomTypes: {}
- roomTypesOrder: []
- mainOrder: 1
-
- ### Adds a room type to app
- @param identifier An identifier to the room type. If a real room, MUST BE the same of `db.rocketchat_room.t` field, if not, can be null
- @param order Order number of the type
- @param config
- template: template name to render on sideNav
- icon: icon class
- route:
- name: route name
- action: route action function
- ###
- add: (identifier, order, config) ->
- unless identifier?
- identifier = Random.id()
-
- if @roomTypes[identifier]?
- return false
-
- if not order?
- order = @mainOrder + 10
- @mainOrder += 10
-
- # @TODO validate config options
- @roomTypesOrder.push
- identifier: identifier
- order: order
- @roomTypes[identifier] = config
-
- if config.route?.path? and config.route?.name? and config.route?.action?
- routeConfig =
- name: config.route.name
- action: config.route.action
-
- if Meteor.isClient
- routeConfig.triggersExit = [ roomExit ]
-
- FlowRouter.route config.route.path, routeConfig
-
- hasCustomLink: (roomType) ->
- return @roomTypes[roomType]?.route?.link?
-
- ###
- @param roomType: room type (e.g.: c (for channels), d (for direct channels))
- @param subData: the user's subscription data
- ###
- getRouteLink: (roomType, subData) ->
- unless @roomTypes[roomType]?
- return false
-
- routeData = {}
-
- if @roomTypes[roomType]?.route?.link?
- routeData = @roomTypes[roomType].route.link(subData)
- else if subData?.name?
- routeData = { name: subData.name }
-
- return FlowRouter.path @roomTypes[roomType].route.name, routeData
-
- openRouteLink: (roomType, subData, queryParams) ->
- unless @roomTypes[roomType]?
- return false
-
- routeData = {}
-
- if @roomTypes[roomType]?.route?.link?
- routeData = @roomTypes[roomType].route.link(subData)
- else if subData?.name?
- routeData = { name: subData.name }
-
- return FlowRouter.go @roomTypes[roomType].route.name, routeData, queryParams
-
diff --git a/packages/rocketchat-lib/lib/settings.coffee b/packages/rocketchat-lib/lib/settings.coffee
deleted file mode 100644
index cdc221064b39a..0000000000000
--- a/packages/rocketchat-lib/lib/settings.coffee
+++ /dev/null
@@ -1,83 +0,0 @@
-###
-# RocketChat.settings holds all packages settings
-# @namespace RocketChat.settings
-###
-RocketChat.settings =
- callbacks: {}
- regexCallbacks: {}
- ts: new Date
-
- get: (_id, callback) ->
- if callback?
- RocketChat.settings.onload _id, callback
- if _id is '*' and Meteor.settings?
- for key, value of Meteor.settings
- callback key, value
- return
-
- if _.isRegExp(_id)
- for key, value of Meteor.settings when _id.test(key)
- callback key, value
- return
-
- if Meteor.settings?[_id]?
- callback _id, Meteor.settings?[_id]
- else
- if _.isRegExp(_id)
- items = []
- for key, value of Meteor.settings when _id.test(key)
- items.push
- key: key
- value: value
- return items
-
- return Meteor.settings?[_id]
-
- set: (_id, value, callback) ->
- Meteor.call 'saveSetting', _id, value, callback
-
- batchSet: (settings, callback) ->
-
- # async -> sync
- # http://daemon.co.za/2012/04/simple-async-with-only-underscore/
-
- save = (setting) ->
- return (callback) ->
- Meteor.call 'saveSetting', setting._id, setting.value, setting.editor, callback
-
- actions = _.map settings, (setting) -> save(setting)
- _(actions).reduceRight(_.wrap, (err, success) -> return callback err, success)()
-
- load: (key, value, initialLoad) ->
- if RocketChat.settings.callbacks[key]?
- for callback in RocketChat.settings.callbacks[key]
- callback key, value, initialLoad
-
- if RocketChat.settings.callbacks['*']?
- for callback in RocketChat.settings.callbacks['*']
- callback key, value, initialLoad
-
- for cbKey, cbValue of RocketChat.settings.regexCallbacks
- if cbValue.regex.test(key)
- callback(key, value, initialLoad) for callback in cbValue.callbacks
-
-
- onload: (key, callback) ->
- # if key is '*'
- # for key, value in Meteor.settings
- # callback key, value, false
- # else if Meteor.settings?[_id]?
- # callback key, Meteor.settings[_id], false
-
- keys = [].concat key
-
- for k in keys
- if _.isRegExp k
- RocketChat.settings.regexCallbacks[k.source] ?= {
- regex: k
- callbacks: []
- }
- RocketChat.settings.regexCallbacks[k.source].callbacks.push callback
- else
- RocketChat.settings.callbacks[k] ?= []
- RocketChat.settings.callbacks[k].push callback
diff --git a/packages/rocketchat-lib/lib/settings.js b/packages/rocketchat-lib/lib/settings.js
new file mode 100644
index 0000000000000..407aa3b26c192
--- /dev/null
+++ b/packages/rocketchat-lib/lib/settings.js
@@ -0,0 +1,100 @@
+import _ from 'underscore';
+
+/*
+* RocketChat.settings holds all packages settings
+* @namespace RocketChat.settings
+*/
+RocketChat.settings = {
+ callbacks: {},
+ regexCallbacks: {},
+ ts: new Date,
+ get(_id, callback) {
+ if (callback != null) {
+ RocketChat.settings.onload(_id, callback);
+ if (!Meteor.settings) {
+ return;
+ }
+ if (_id === '*') {
+ return Object.keys(Meteor.settings).forEach(key => {
+ const value = Meteor.settings[key];
+ callback(key, value);
+ });
+ }
+ if (_.isRegExp(_id) && Meteor.settings) {
+ return Object.keys(Meteor.settings).forEach(key => {
+ if (!_id.test(key)) {
+ return;
+ }
+ const value = Meteor.settings[key];
+ callback(key, value);
+ });
+ }
+ return Meteor.settings[_id] != null && callback(_id, Meteor.settings[_id]);
+ } else {
+ if (!Meteor.settings) {
+ return;
+ }
+ if (_.isRegExp(_id)) {
+ return Object.keys(Meteor.settings).reduce((items, key) => {
+ const value = Meteor.settings[key];
+ if (_id.test(key)) {
+ items.push({
+ key,
+ value
+ });
+ }
+ return items;
+ }, []);
+ }
+ return Meteor.settings && Meteor.settings[_id];
+ }
+ },
+ set(_id, value, callback) {
+ return Meteor.call('saveSetting', _id, value, callback);
+ },
+ batchSet(settings, callback) {
+ // async -> sync
+ // http://daemon.co.za/2012/04/simple-async-with-only-underscore/
+ const save = function(setting) {
+ return function(callback) {
+ return Meteor.call('saveSetting', setting._id, setting.value, setting.editor, callback);
+ };
+ };
+ const actions = _.map(settings, (setting) => save(setting));
+ return _(actions).reduceRight(_.wrap, (err, success) => callback(err, success))();
+ },
+ load(key, value, initialLoad) {
+ ['*', key].forEach(item => {
+ if (RocketChat.settings.callbacks[item]) {
+ RocketChat.settings.callbacks[item].forEach(callback => callback(key, value, initialLoad));
+ }
+ });
+ Object.keys(RocketChat.settings.regexCallbacks).forEach(cbKey => {
+ const cbValue = RocketChat.settings.regexCallbacks[cbKey];
+ if (!cbValue.regex.test(key)) {
+ return;
+ }
+ cbValue.callbacks.forEach(callback => callback(key, value, initialLoad));
+ });
+ },
+ onload(key, callback) {
+ // if key is '*'
+ // for key, value in Meteor.settings
+ // callback key, value, false
+ // else if Meteor.settings?[_id]?
+ // callback key, Meteor.settings[_id], false
+ const keys = [].concat(key);
+ keys.forEach(k => {
+ if (_.isRegExp(k)) {
+ RocketChat.settings.regexCallbacks[name = k.source] = RocketChat.settings.regexCallbacks[name = k.source] || {
+ regex: k,
+ callbacks: []
+ };
+ RocketChat.settings.regexCallbacks[k.source].callbacks.push(callback);
+ } else {
+ RocketChat.settings.callbacks[k] = RocketChat.settings.callbacks[k] || [];
+ RocketChat.settings.callbacks[k].push(callback);
+ }
+ });
+ }
+};
diff --git a/packages/rocketchat-lib/lib/slashCommand.coffee b/packages/rocketchat-lib/lib/slashCommand.coffee
deleted file mode 100644
index 0fad4644a4f07..0000000000000
--- a/packages/rocketchat-lib/lib/slashCommand.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-RocketChat.slashCommands =
- commands: {}
-
-RocketChat.slashCommands.add = (command, callback, options) ->
- RocketChat.slashCommands.commands[command] =
- command: command
- callback: callback
- params: options?.params
- description: options?.description
- clientOnly: options?.clientOnly or false
-
- return
-
-RocketChat.slashCommands.run = (command, params, item) ->
- if RocketChat.slashCommands.commands[command]?.callback?
- callback = RocketChat.slashCommands.commands[command].callback
- callback command, params, item
-
-
-Meteor.methods
- slashCommand: (command) ->
- if not Meteor.userId()
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'slashCommand' }
-
- RocketChat.slashCommands.run command.cmd, command.params, command.msg
-
diff --git a/packages/rocketchat-lib/lib/slashCommand.js b/packages/rocketchat-lib/lib/slashCommand.js
new file mode 100644
index 0000000000000..69bb56b56b48f
--- /dev/null
+++ b/packages/rocketchat-lib/lib/slashCommand.js
@@ -0,0 +1,33 @@
+RocketChat.slashCommands = {
+ commands: {}
+};
+
+RocketChat.slashCommands.add = function(command, callback, options = {}, result) {
+ RocketChat.slashCommands.commands[command] = {
+ command,
+ callback,
+ params: options.params,
+ description: options.description,
+ permission: options.permission,
+ clientOnly: options.clientOnly || false,
+ result
+ };
+};
+
+RocketChat.slashCommands.run = function(command, params, item) {
+ if (RocketChat.slashCommands.commands[command] && RocketChat.slashCommands.commands[command].callback) {
+ return RocketChat.slashCommands.commands[command].callback(command, params, item);
+ }
+};
+
+Meteor.methods({
+ slashCommand(command) {
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'slashCommand'
+ });
+ }
+
+ return RocketChat.slashCommands.run(command.cmd, command.params, command.msg);
+ }
+});
diff --git a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee
deleted file mode 100644
index 96504f5d73e1f..0000000000000
--- a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.coffee
+++ /dev/null
@@ -1,22 +0,0 @@
-RocketChat.settings.get 'Site_Url', (key, value) ->
- if value?.trim() isnt ''
- host = value.replace(/\/$/, '')
- prefix = ""
- match = value.match(/([^/]+\/{2}[^/]+)(\/.+)/)
- if match?
- host = match[1]
- prefix = match[2].replace(/\/$/, '')
-
- __meteor_runtime_config__.ROOT_URL = host
- # __meteor_runtime_config__.ROOT_URL_PATH_PREFIX = prefix
-
- if Meteor.absoluteUrl.defaultOptions?.rootUrl?
- Meteor.absoluteUrl.defaultOptions.rootUrl = host
-
- if Meteor.isServer
- RocketChat.hostname = host.replace(/^https?:\/\//, '')
-
- process.env.MOBILE_ROOT_URL = host
- process.env.MOBILE_DDP_URL = host
- if WebAppInternals?.generateBoilerplate
- WebAppInternals.generateBoilerplate()
diff --git a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js
new file mode 100644
index 0000000000000..8e4c7d987e6f3
--- /dev/null
+++ b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js
@@ -0,0 +1,26 @@
+/* globals WebAppInternals */
+RocketChat.settings.get('Site_Url', function(key, value) {
+ if (value == null || value.trim() === '') {
+ return;
+ }
+ let host = value.replace(/\/$/, '');
+ // let prefix = '';
+ const match = value.match(/([^\/]+\/{2}[^\/]+)(\/.+)/);
+ if (match != null) {
+ host = match[1];
+ // prefix = match[2].replace(/\/$/, '');
+ }
+ __meteor_runtime_config__.ROOT_URL = value;
+
+ if (Meteor.absoluteUrl.defaultOptions && Meteor.absoluteUrl.defaultOptions.rootUrl) {
+ Meteor.absoluteUrl.defaultOptions.rootUrl = value;
+ }
+ if (Meteor.isServer) {
+ RocketChat.hostname = host.replace(/^https?:\/\//, '');
+ process.env.MOBILE_ROOT_URL = host;
+ process.env.MOBILE_DDP_URL = host;
+ if (typeof WebAppInternals !== 'undefined' && WebAppInternals.generateBoilerplate) {
+ return WebAppInternals.generateBoilerplate();
+ }
+ }
+});
diff --git a/packages/rocketchat-lib/lib/templateVarHandler.js b/packages/rocketchat-lib/lib/templateVarHandler.js
new file mode 100644
index 0000000000000..294520a550d5c
--- /dev/null
+++ b/packages/rocketchat-lib/lib/templateVarHandler.js
@@ -0,0 +1,37 @@
+let logger;
+
+if (Meteor.isServer) {
+ logger = new Logger('TemplateVarHandler', {});
+}
+
+RocketChat.templateVarHandler = function(variable, object) {
+
+ const templateRegex = /#{([\w\-]+)}/gi;
+ let match = templateRegex.exec(variable);
+ let tmpVariable = variable;
+
+ if (match == null) {
+ if (!object.hasOwnProperty(variable)) {
+ logger && logger.debug(`user does not have attribute: ${ variable }`);
+ return;
+ }
+ return object[variable];
+ } else {
+ logger && logger.debug('template found. replacing values');
+ while (match != null) {
+ const tmplVar = match[0];
+ const tmplAttrName = match[1];
+
+ if (!object.hasOwnProperty(tmplAttrName)) {
+ logger && logger.debug(`user does not have attribute: ${ tmplAttrName }`);
+ return;
+ }
+
+ const attrVal = object[tmplAttrName];
+ logger && logger.debug(`replacing template var: ${ tmplVar } with value: ${ attrVal }`);
+ tmpVariable = tmpVariable.replace(tmplVar, attrVal);
+ match = templateRegex.exec(variable);
+ }
+ return tmpVariable;
+ }
+};
diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js
index 61bcc5cd1a746..d20d1d69433d0 100644
--- a/packages/rocketchat-lib/package.js
+++ b/packages/rocketchat-lib/package.js
@@ -5,34 +5,25 @@ Package.describe({
git: ''
});
-Npm.depends({
- 'bad-words': '1.3.1',
- 'object-path': '0.9.2',
- 'node-dogstatsd': '0.0.6',
- 'localforage': '1.4.2',
- 'lokijs': '1.4.1',
- 'bugsnag': '1.8.0',
- 'prom-client': '7.0.1'
-});
-
Package.onUse(function(api) {
api.use('rate-limit');
+ api.use('webapp');
api.use('session');
api.use('reactive-var');
api.use('reactive-dict');
api.use('accounts-base');
- api.use('coffeescript');
api.use('ecmascript');
api.use('random');
api.use('check');
api.use('tracker');
api.use('ddp-rate-limiter');
- api.use('underscore');
api.use('mongo');
- api.use('underscorestring:underscore.string@3.3.4');
+ api.use('oauth');
api.use('matb33:collection-hooks');
api.use('service-configuration');
api.use('check');
+ api.use('rocketchat:accounts');
+ api.use('modules');
api.use('rocketchat:i18n');
api.use('rocketchat:streamer');
api.use('rocketchat:version');
@@ -44,70 +35,102 @@ Package.onUse(function(api) {
api.use('templating', 'client');
api.use('kadira:flow-router');
- api.addFiles('lib/core.coffee');
+ api.addFiles('lib/core.js');
// DEBUGGER
api.addFiles('server/lib/debug.js', 'server');
+ // ROOM TYPES
+ api.addFiles('lib/RoomTypeConfig.js');
+ api.addFiles([
+ 'lib/roomTypes/conversation.js',
+ 'lib/roomTypes/direct.js',
+ 'lib/roomTypes/favorite.js',
+ 'lib/roomTypes/index.js',
+ 'lib/roomTypes/private.js',
+ 'lib/roomTypes/public.js',
+ 'lib/roomTypes/unread.js'
+ ]);
+
// COMMON LIB
api.addFiles('lib/getURL.js');
- api.addFiles('lib/settings.coffee');
- api.addFiles('lib/configLogger.coffee');
- api.addFiles('lib/callbacks.coffee');
+ api.addFiles('lib/settings.js');
+ api.addFiles('lib/callbacks.js');
api.addFiles('lib/fileUploadRestrictions.js');
+ api.addFiles('lib/getAvatarColor.js');
+ api.addFiles('lib/getValidRoomName.js');
api.addFiles('lib/placeholders.js');
- api.addFiles('lib/promises.coffee');
- api.addFiles('lib/roomTypesCommon.coffee');
- api.addFiles('lib/slashCommand.coffee');
- api.addFiles('lib/Message.coffee');
- api.addFiles('lib/MessageTypes.coffee');
+ api.addFiles('lib/promises.js');
+ api.addFiles('lib/RoomTypesCommon.js');
+ api.addFiles('lib/slashCommand.js');
+ api.addFiles('lib/Message.js');
+ api.addFiles('lib/messageBox.js');
+ api.addFiles('lib/MessageTypes.js');
+ api.addFiles('lib/templateVarHandler.js');
+
+ api.addFiles('lib/getUserPreference.js');
api.addFiles('server/lib/bugsnag.js', 'server');
api.addFiles('server/lib/metrics.js', 'server');
- api.addFiles('server/lib/RateLimiter.coffee', 'server');
+ api.addFiles('server/lib/RateLimiter.js', 'server');
// SERVER FUNCTIONS
api.addFiles('server/functions/isDocker.js', 'server');
api.addFiles('server/functions/addUserToDefaultChannels.js', 'server');
api.addFiles('server/functions/addUserToRoom.js', 'server');
api.addFiles('server/functions/archiveRoom.js', 'server');
- api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server');
+ api.addFiles('server/functions/checkUsernameAvailability.js', 'server');
api.addFiles('server/functions/checkEmailAvailability.js', 'server');
api.addFiles('server/functions/createRoom.js', 'server');
api.addFiles('server/functions/deleteMessage.js', 'server');
api.addFiles('server/functions/deleteUser.js', 'server');
api.addFiles('server/functions/getFullUserData.js', 'server');
+ api.addFiles('server/functions/getRoomByNameOrIdWithOptionToJoin.js', 'server');
+ api.addFiles('server/functions/loadMessageHistory.js', 'server');
api.addFiles('server/functions/removeUserFromRoom.js', 'server');
api.addFiles('server/functions/saveUser.js', 'server');
api.addFiles('server/functions/saveCustomFields.js', 'server');
- api.addFiles('server/functions/sendMessage.coffee', 'server');
- api.addFiles('server/functions/settings.coffee', 'server');
+ api.addFiles('server/functions/saveCustomFieldsWithoutValidation.js', 'server');
+ api.addFiles('server/functions/sendMessage.js', 'server');
+ api.addFiles('server/functions/settings.js', 'server');
api.addFiles('server/functions/setUserAvatar.js', 'server');
- api.addFiles('server/functions/setUsername.coffee', 'server');
+ api.addFiles('server/functions/setUsername.js', 'server');
+ api.addFiles('server/functions/setRealName.js', 'server');
api.addFiles('server/functions/setEmail.js', 'server');
api.addFiles('server/functions/unarchiveRoom.js', 'server');
api.addFiles('server/functions/updateMessage.js', 'server');
- api.addFiles('server/functions/Notifications.coffee', 'server');
+ api.addFiles('server/functions/validateCustomFields.js', 'server');
+ api.addFiles('server/functions/Notifications.js', 'server');
// SERVER LIB
+ api.addFiles('server/lib/configLogger.js', 'server');
api.addFiles('server/lib/PushNotification.js', 'server');
api.addFiles('server/lib/defaultBlockedDomainsList.js', 'server');
+ api.addFiles('server/lib/interceptDirectReplyEmails.js', 'server');
+ api.addFiles('server/lib/loginErrorMessageOverride.js', 'server');
api.addFiles('server/lib/notifyUsersOnMessage.js', 'server');
- api.addFiles('server/lib/roomTypes.coffee', 'server');
+ api.addFiles('server/lib/processDirectEmail.js', 'server');
+ api.addFiles('server/lib/roomTypes.js', 'server');
api.addFiles('server/lib/sendEmailOnMessage.js', 'server');
api.addFiles('server/lib/sendNotificationsOnMessage.js', 'server');
api.addFiles('server/lib/validateEmailDomain.js', 'server');
// SERVER MODELS
api.addFiles('server/models/_Base.js', 'server');
- api.addFiles('server/models/Messages.coffee', 'server');
- api.addFiles('server/models/Reports.coffee', 'server');
- api.addFiles('server/models/Rooms.coffee', 'server');
- api.addFiles('server/models/Settings.coffee', 'server');
- api.addFiles('server/models/Subscriptions.coffee', 'server');
- api.addFiles('server/models/Uploads.coffee', 'server');
- api.addFiles('server/models/Users.coffee', 'server');
+ api.addFiles('server/models/Avatars.js', 'server');
+ api.addFiles('server/models/Messages.js', 'server');
+ api.addFiles('server/models/Reports.js', 'server');
+ api.addFiles('server/models/Rooms.js', 'server');
+ api.addFiles('server/models/Settings.js', 'server');
+ api.addFiles('server/models/Subscriptions.js', 'server');
+ api.addFiles('server/models/Uploads.js', 'server');
+ api.addFiles('server/models/Users.js', 'server');
+ api.addFiles('server/models/Servers.js', 'server');
+
+ api.addFiles('server/oauth/oauth.js', 'server');
+ api.addFiles('server/oauth/google.js', 'server');
+ api.addFiles('server/oauth/proxy.js', 'server');
api.addFiles('server/startup/statsTracker.js', 'server');
@@ -115,7 +138,7 @@ Package.onUse(function(api) {
api.addFiles('server/startup/cache/CacheLoad.js', 'server');
// SERVER PUBLICATIONS
- api.addFiles('server/publications/settings.coffee', 'server');
+ api.addFiles('server/publications/settings.js', 'server');
// SERVER METHODS
api.addFiles('server/methods/addOAuthService.js', 'server');
@@ -125,17 +148,22 @@ Package.onUse(function(api) {
api.addFiles('server/methods/archiveRoom.js', 'server');
api.addFiles('server/methods/blockUser.js', 'server');
api.addFiles('server/methods/checkRegistrationSecretURL.js', 'server');
+ api.addFiles('server/methods/checkUsernameAvailability.js', 'server');
api.addFiles('server/methods/cleanChannelHistory.js', 'server');
api.addFiles('server/methods/createChannel.js', 'server');
+ api.addFiles('server/methods/createToken.js', 'server');
api.addFiles('server/methods/createPrivateGroup.js', 'server');
- api.addFiles('server/methods/deleteMessage.coffee', 'server');
+ api.addFiles('server/methods/deleteMessage.js', 'server');
api.addFiles('server/methods/deleteUserOwnAccount.js', 'server');
api.addFiles('server/methods/filterBadWords.js', ['server']);
api.addFiles('server/methods/filterATAllTag.js', 'server');
+ api.addFiles('server/methods/filterATHereTag.js', 'server');
api.addFiles('server/methods/getChannelHistory.js', 'server');
api.addFiles('server/methods/getFullUserData.js', 'server');
+ api.addFiles('server/methods/getRoomJoinCode.js', 'server');
api.addFiles('server/methods/getRoomRoles.js', 'server');
api.addFiles('server/methods/getServerInfo.js', 'server');
+ api.addFiles('server/methods/getSingleMessage.js', 'server');
api.addFiles('server/methods/getUserRoles.js', 'server');
api.addFiles('server/methods/insertOrUpdateUser.js', 'server');
api.addFiles('server/methods/joinDefaultChannels.js', 'server');
@@ -143,11 +171,11 @@ Package.onUse(function(api) {
api.addFiles('server/methods/leaveRoom.js', 'server');
api.addFiles('server/methods/removeOAuthService.js', 'server');
api.addFiles('server/methods/restartServer.js', 'server');
- api.addFiles('server/methods/robotMethods.coffee', 'server');
+ api.addFiles('server/methods/robotMethods.js', 'server');
api.addFiles('server/methods/saveSetting.js', 'server');
- api.addFiles('server/methods/sendInvitationEmail.coffee', 'server');
- api.addFiles('server/methods/sendMessage.coffee', 'server');
- api.addFiles('server/methods/sendSMTPTestEmail.coffee', 'server');
+ api.addFiles('server/methods/sendInvitationEmail.js', 'server');
+ api.addFiles('server/methods/sendMessage.js', 'server');
+ api.addFiles('server/methods/sendSMTPTestEmail.js', 'server');
api.addFiles('server/methods/setAdminStatus.js', 'server');
api.addFiles('server/methods/setRealName.js', 'server');
api.addFiles('server/methods/setUsername.js', 'server');
@@ -157,37 +185,45 @@ Package.onUse(function(api) {
api.addFiles('server/methods/updateMessage.js', 'server');
// SERVER STARTUP
- api.addFiles('server/startup/settingsOnLoadCdnPrefix.coffee', 'server');
- api.addFiles('server/startup/settingsOnLoadSMTP.coffee', 'server');
- api.addFiles('server/startup/oAuthServicesUpdate.coffee', 'server');
- api.addFiles('server/startup/settings.coffee', 'server');
+ api.addFiles('server/startup/settingsOnLoadCdnPrefix.js', 'server');
+ api.addFiles('server/startup/settingsOnLoadDirectReply.js', 'server');
+ api.addFiles('server/startup/settingsOnLoadSMTP.js', 'server');
+ api.addFiles('server/startup/oAuthServicesUpdate.js', 'server');
+ api.addFiles('server/startup/settings.js', 'server');
// COMMON STARTUP
- api.addFiles('lib/startup/settingsOnLoadSiteUrl.coffee');
+ api.addFiles('lib/startup/settingsOnLoadSiteUrl.js');
// CLIENT LIB
- api.addFiles('client/Notifications.coffee', 'client');
+ api.addFiles('client/Notifications.js', 'client');
+ api.addFiles('client/OAuthProxy.js', 'client');
+ api.addFiles('client/lib/RestApiClient.js', 'client');
api.addFiles('client/lib/TabBar.js', 'client');
api.addFiles('client/lib/RocketChatTabBar.js', 'client');
+ api.addFiles('client/lib/RestApiClient.js', 'client');
api.addFiles('client/lib/cachedCollection.js', 'client');
- api.addFiles('client/lib/openRoom.coffee', 'client');
- api.addFiles('client/lib/roomExit.coffee', 'client');
- api.addFiles('client/lib/settings.coffee', 'client');
- api.addFiles('client/lib/roomTypes.coffee', 'client');
+ api.addFiles('client/lib/openRoom.js', 'client');
+ api.addFiles('client/lib/roomExit.js', 'client');
+ api.addFiles('client/lib/settings.js', 'client');
+ api.addFiles('client/lib/roomTypes.js', 'client');
api.addFiles('client/lib/userRoles.js', 'client');
api.addFiles('client/lib/Layout.js', 'client');
+ // CLIENT LIB STARTUP
+ api.addFiles('client/lib/startup/commands.js', 'client');
+
// CLIENT METHODS
- api.addFiles('client/methods/sendMessage.coffee', 'client');
- api.addFiles('client/AdminBox.coffee', 'client');
- api.addFiles('client/MessageAction.coffee', 'client');
+ api.addFiles('client/methods/sendMessage.js', 'client');
+ api.addFiles('client/AdminBox.js', 'client');
+ api.addFiles('client/MessageAction.js', 'client');
api.addFiles('client/defaultTabBars.js', 'client');
api.addFiles('client/CustomTranslations.js', 'client');
// CLIENT MODELS
- api.addFiles('client/models/_Base.coffee', 'client');
- api.addFiles('client/models/Uploads.coffee', 'client');
+ api.addFiles('client/models/_Base.js', 'client');
+ api.addFiles('client/models/Avatars.js', 'client');
+ api.addFiles('client/models/Uploads.js', 'client');
// CLIENT VIEWS
api.addFiles('client/views/customFieldsForm.html', 'client');
@@ -200,14 +236,10 @@ Package.onUse(function(api) {
// EXPORT
api.export('RocketChat');
- api.export('RocketChatTabBar');
- api.imply('tap:i18n');
-});
+ // exports
+ api.mainModule('server/lib/index.js', 'server');
+ api.mainModule('client/lib/index.js', 'client');
-Package.onTest(function(api) {
- api.use('coffeescript');
- api.use('sanjo:jasmine@0.20.2');
- api.use('rocketchat:lib');
- api.addFiles('tests/jasmine/server/unit/models/_Base.spec.coffee', 'server');
+ api.imply('tap:i18n');
});
diff --git a/packages/rocketchat-lib/rocketchat.info b/packages/rocketchat-lib/rocketchat.info
index db1d7979a7eaf..5db7177fdf214 100644
--- a/packages/rocketchat-lib/rocketchat.info
+++ b/packages/rocketchat-lib/rocketchat.info
@@ -1,3 +1,3 @@
{
- "version": "0.51.0-develop"
+ "version": "0.63.0-develop"
}
diff --git a/packages/rocketchat-lib/server/functions/Notifications.coffee b/packages/rocketchat-lib/server/functions/Notifications.coffee
deleted file mode 100644
index 9e08663db6cd6..0000000000000
--- a/packages/rocketchat-lib/server/functions/Notifications.coffee
+++ /dev/null
@@ -1,119 +0,0 @@
-RocketChat.Notifications = new class
- constructor: ->
- self = @
-
- @debug = false
-
- @streamAll = new Meteor.Streamer 'notify-all'
- @streamLogged = new Meteor.Streamer 'notify-logged'
- @streamRoom = new Meteor.Streamer 'notify-room'
- @streamRoomUsers = new Meteor.Streamer 'notify-room-users'
- @streamUser = new Meteor.Streamer 'notify-user'
-
-
- @streamAll.allowWrite('none')
- @streamLogged.allowWrite('none')
- @streamRoom.allowWrite('none')
- @streamRoomUsers.allowWrite (eventName, args...) ->
- [roomId, e] = eventName.split('/')
-
- user = Meteor.users.findOne @userId, {fields: {username: 1}}
- if RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, @userId)?
- subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndNotUserId(roomId, @userId).fetch()
- for subscription in subscriptions
- RocketChat.Notifications.notifyUser(subscription.u._id, e, args...)
-
- return false
-
- @streamUser.allowWrite('logged')
-
- @streamAll.allowRead('all')
-
- @streamLogged.allowRead('logged')
-
- @streamRoom.allowRead (eventName) ->
- if not @userId? then return false
-
- roomId = eventName.split('/')[0]
-
- user = Meteor.users.findOne @userId, {fields: {username: 1}}
- room = RocketChat.models.Rooms.findOneById(roomId)
- if room.t is 'l' and room.v._id is user._id
- return true
-
- return room.usernames.indexOf(user.username) > -1
-
- @streamRoomUsers.allowRead('none');
-
- @streamUser.allowRead (eventName) ->
- userId = eventName.split('/')[0]
- return @userId? and @userId is userId
-
-
- notifyAll: (eventName, args...) ->
- console.log 'notifyAll', arguments if @debug is true
-
- args.unshift eventName
- @streamAll.emit.apply @streamAll, args
-
- notifyLogged: (eventName, args...) ->
- console.log 'notifyLogged', arguments if @debug is true
-
- args.unshift eventName
- @streamLogged.emit.apply @streamLogged, args
-
- notifyRoom: (room, eventName, args...) ->
- console.log 'notifyRoom', arguments if @debug is true
-
- args.unshift "#{room}/#{eventName}"
- @streamRoom.emit.apply @streamRoom, args
-
- notifyUser: (userId, eventName, args...) ->
- console.log 'notifyUser', arguments if @debug is true
-
- args.unshift "#{userId}/#{eventName}"
- @streamUser.emit.apply @streamUser, args
-
-
- notifyAllInThisInstance: (eventName, args...) ->
- console.log 'notifyAll', arguments if @debug is true
-
- args.unshift eventName
- @streamAll.emitWithoutBroadcast.apply @streamAll, args
-
- notifyLoggedInThisInstance: (eventName, args...) ->
- console.log 'notifyLogged', arguments if @debug is true
-
- args.unshift eventName
- @streamLogged.emitWithoutBroadcast.apply @streamLogged, args
-
- notifyRoomInThisInstance: (room, eventName, args...) ->
- console.log 'notifyRoomAndBroadcast', arguments if @debug is true
-
- args.unshift "#{room}/#{eventName}"
- @streamRoom.emitWithoutBroadcast.apply @streamRoom, args
-
- notifyUserInThisInstance: (userId, eventName, args...) ->
- console.log 'notifyUserAndBroadcast', arguments if @debug is true
-
- args.unshift "#{userId}/#{eventName}"
- @streamUser.emitWithoutBroadcast.apply @streamUser, args
-
-
-## Permissions for client
-
-# Enable emit for event typing for rooms and add username to event data
-func = (eventName, username) ->
- [room, e] = eventName.split('/')
-
- if e is 'webrtc'
- return true
-
- if e is 'typing'
- user = Meteor.users.findOne(@userId, {fields: {username: 1}})
- if user?.username is username
- return true
-
- return false
-
-RocketChat.Notifications.streamRoom.allowWrite func
diff --git a/packages/rocketchat-lib/server/functions/Notifications.js b/packages/rocketchat-lib/server/functions/Notifications.js
new file mode 100644
index 0000000000000..808d0b8bb9028
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/Notifications.js
@@ -0,0 +1,145 @@
+RocketChat.Notifications = new class {
+ constructor() {
+ this.debug = false;
+ this.streamAll = new Meteor.Streamer('notify-all');
+ this.streamLogged = new Meteor.Streamer('notify-logged');
+ this.streamRoom = new Meteor.Streamer('notify-room');
+ this.streamRoomUsers = new Meteor.Streamer('notify-room-users');
+ this.streamUser = new Meteor.Streamer('notify-user');
+ this.streamAll.allowWrite('none');
+ this.streamLogged.allowWrite('none');
+ this.streamRoom.allowWrite('none');
+ this.streamRoomUsers.allowWrite(function(eventName, ...args) {
+ const [roomId, e] = eventName.split('/');
+ // const user = Meteor.users.findOne(this.userId, {
+ // fields: {
+ // username: 1
+ // }
+ // });
+ if (RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, this.userId) != null) {
+ const subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndNotUserId(roomId, this.userId).fetch();
+ subscriptions.forEach(subscription => RocketChat.Notifications.notifyUser(subscription.u._id, e, ...args));
+ }
+ return false;
+ });
+ this.streamUser.allowWrite('logged');
+ this.streamAll.allowRead('all');
+ this.streamLogged.allowRead('logged');
+ this.streamRoom.allowRead(function(eventName, extraData) {
+ const [roomId] = eventName.split('/');
+ const user = Meteor.users.findOne(this.userId, {
+ fields: {
+ username: 1
+ }
+ });
+ const room = RocketChat.models.Rooms.findOneById(roomId);
+ if (!room) {
+ console.warn(`Invalid streamRoom eventName: "${ eventName }"`);
+ return false;
+ }
+ if (room.t === 'l' && extraData && extraData.token && room.v.token === extraData.token) {
+ return true;
+ }
+ if (this.userId == null) {
+ return false;
+ }
+ return room.usernames.indexOf(user.username) > -1;
+ });
+ this.streamRoomUsers.allowRead('none');
+ this.streamUser.allowRead(function(eventName) {
+ const [userId] = eventName.split('/');
+ return (this.userId != null) && this.userId === userId;
+ });
+ }
+
+ notifyAll(eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyAll', arguments);
+ }
+ args.unshift(eventName);
+ return this.streamAll.emit.apply(this.streamAll, args);
+ }
+
+ notifyLogged(eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyLogged', arguments);
+ }
+ args.unshift(eventName);
+ return this.streamLogged.emit.apply(this.streamLogged, args);
+ }
+
+ notifyRoom(room, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyRoom', arguments);
+ }
+ args.unshift(`${ room }/${ eventName }`);
+ return this.streamRoom.emit.apply(this.streamRoom, args);
+ }
+
+ notifyUser(userId, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyUser', arguments);
+ }
+ args.unshift(`${ userId }/${ eventName }`);
+ return this.streamUser.emit.apply(this.streamUser, args);
+ }
+
+ notifyAllInThisInstance(eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyAll', arguments);
+ }
+ args.unshift(eventName);
+ return this.streamAll.emitWithoutBroadcast.apply(this.streamAll, args);
+ }
+
+ notifyLoggedInThisInstance(eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyLogged', arguments);
+ }
+ args.unshift(eventName);
+ return this.streamLogged.emitWithoutBroadcast.apply(this.streamLogged, args);
+ }
+
+ notifyRoomInThisInstance(room, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyRoomAndBroadcast', arguments);
+ }
+ args.unshift(`${ room }/${ eventName }`);
+ return this.streamRoom.emitWithoutBroadcast.apply(this.streamRoom, args);
+ }
+
+ notifyUserInThisInstance(userId, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('notifyUserAndBroadcast', arguments);
+ }
+ args.unshift(`${ userId }/${ eventName }`);
+ return this.streamUser.emitWithoutBroadcast.apply(this.streamUser, args);
+ }
+};
+
+RocketChat.Notifications.streamRoom.allowWrite(function(eventName, username, typing, extraData) {
+ const [roomId, e] = eventName.split('/');
+ if (e === 'webrtc') {
+ return true;
+ }
+ if (e === 'typing') {
+
+ // typing from livechat widget
+ if (extraData && extraData.token) {
+ const room = RocketChat.models.Rooms.findOneById(roomId);
+ if (room && room.t === 'l' && room.v.token === extraData.token) {
+ return true;
+ }
+ }
+
+ const user = Meteor.users.findOne(this.userId, {
+ fields: {
+ username: 1
+ }
+ });
+ if (user != null && user.username === username) {
+ return true;
+ }
+ }
+ return false;
+});
diff --git a/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js b/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
index e63628c8f915a..40d1bfbc22f3c 100644
--- a/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
+++ b/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
@@ -1,4 +1,5 @@
-RocketChat.addUserToDefaultChannels = function(user, silenced) {
+// XXX
+RocketChat.addUserToDefaultChannels = function(user, serverId, silenced) {
RocketChat.callbacks.run('beforeJoinDefaultChannels', user);
const defaultRooms = RocketChat.models.Rooms.findByDefaultAndTypes(true, ['c', 'p'], {fields: {usernames: 0}}).fetch();
defaultRooms.forEach((room) => {
@@ -10,11 +11,13 @@ RocketChat.addUserToDefaultChannels = function(user, silenced) {
if (!RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id)) {
// Add a subscription to this user
- RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
+ RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, serverId, {
ts: new Date(),
open: true,
alert: true,
- unread: 1
+ unread: 1,
+ userMentions: 1,
+ groupMentions: 0
});
// Insert user joined message
diff --git a/packages/rocketchat-lib/server/functions/addUserToRoom.js b/packages/rocketchat-lib/server/functions/addUserToRoom.js
index 41573b2c126f3..527b68fab3f88 100644
--- a/packages/rocketchat-lib/server/functions/addUserToRoom.js
+++ b/packages/rocketchat-lib/server/functions/addUserToRoom.js
@@ -1,24 +1,26 @@
RocketChat.addUserToRoom = function(rid, user, inviter, silenced) {
- let now = new Date();
- let room = RocketChat.models.Rooms.findOneById(rid);
+ const now = new Date();
+ const room = RocketChat.models.Rooms.findOneById(rid);
// Check if user is already in room
- let subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (subscription) {
return;
}
- if (room.t === 'c') {
+ if (room.t === 'c' || room.t === 'p') {
RocketChat.callbacks.run('beforeJoinRoom', user, room);
}
- var muted = room.ro && !RocketChat.authz.hasPermission(user._id, 'post-readonly');
+ const muted = room.ro && !RocketChat.authz.hasPermission(user._id, 'post-readonly');
RocketChat.models.Rooms.addUsernameById(rid, user.username, muted);
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,
alert: true,
- unread: 1
+ unread: 1,
+ userMentions: 1,
+ groupMentions: 0
});
if (!silenced) {
@@ -35,7 +37,7 @@ RocketChat.addUserToRoom = function(rid, user, inviter, silenced) {
}
}
- if (room.t === 'c') {
+ if (room.t === 'c' || room.t === 'p') {
Meteor.defer(function() {
RocketChat.callbacks.run('afterJoinRoom', user, room);
});
diff --git a/packages/rocketchat-lib/server/functions/archiveRoom.js b/packages/rocketchat-lib/server/functions/archiveRoom.js
index ef2aafeffe47a..f48be588c92f3 100644
--- a/packages/rocketchat-lib/server/functions/archiveRoom.js
+++ b/packages/rocketchat-lib/server/functions/archiveRoom.js
@@ -1,4 +1,6 @@
RocketChat.archiveRoom = function(rid) {
RocketChat.models.Rooms.archiveById(rid);
RocketChat.models.Subscriptions.archiveByRoomId(rid);
+
+ RocketChat.callbacks.run('afterRoomArchived', RocketChat.models.Rooms.findOneById(rid), Meteor.user());
};
diff --git a/packages/rocketchat-lib/server/functions/checkEmailAvailability.js b/packages/rocketchat-lib/server/functions/checkEmailAvailability.js
index 8d8e9322e7500..b60d92741b2a6 100644
--- a/packages/rocketchat-lib/server/functions/checkEmailAvailability.js
+++ b/packages/rocketchat-lib/server/functions/checkEmailAvailability.js
@@ -1,3 +1,5 @@
+import s from 'underscore.string';
+
RocketChat.checkEmailAvailability = function(email) {
- return !Meteor.users.findOne({ 'emails.address': { $regex : new RegExp('^' + s.trim(s.escapeRegExp(email)) + '$', 'i') } });
+ return !Meteor.users.findOne({ 'emails.address': { $regex : new RegExp(`^${ s.trim(s.escapeRegExp(email)) }$`, 'i') } });
};
diff --git a/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee b/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee
deleted file mode 100644
index 987b8e2af2b2f..0000000000000
--- a/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee
+++ /dev/null
@@ -1,10 +0,0 @@
-RocketChat.checkUsernameAvailability = (username) ->
- usernameBlackList = []
- RocketChat.settings.get('Accounts_BlockedUsernameList', (key, value) =>
- usernameBlackList = _.map(value.split(','), (username) => username.trim())
- if usernameBlackList.length isnt 0
- for restrictedUsername in usernameBlackList
- regex = new RegExp('^' + s.escapeRegExp(restrictedUsername) + '$', 'i')
- return false if regex.test(s.trim(s.escapeRegExp(username)))
- return not Meteor.users.findOne({ username: { $regex : new RegExp("^" + s.trim(s.escapeRegExp(username)) + "$", "i") } });
- )
diff --git a/packages/rocketchat-lib/server/functions/checkUsernameAvailability.js b/packages/rocketchat-lib/server/functions/checkUsernameAvailability.js
new file mode 100644
index 0000000000000..b29ddde8c312b
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/checkUsernameAvailability.js
@@ -0,0 +1,23 @@
+import _ from 'underscore';
+import s from 'underscore.string';
+
+RocketChat.checkUsernameAvailability = function(username) {
+ return RocketChat.settings.get('Accounts_BlockedUsernameList', function(key, value) {
+ const usernameBlackList = _.map(value.split(','), function(username) {
+ return username.trim();
+ });
+ if (usernameBlackList.length !== 0) {
+ if (usernameBlackList.every(restrictedUsername => {
+ const regex = new RegExp(`^${ s.escapeRegExp(restrictedUsername) }$`, 'i');
+ return !regex.test(s.trim(s.escapeRegExp(username)));
+ })) {
+ return !Meteor.users.findOne({
+ username: {
+ $regex: new RegExp(`^${ s.trim(s.escapeRegExp(username)) }$`, 'i')
+ }
+ });
+ }
+ return false;
+ }
+ });
+};
diff --git a/packages/rocketchat-lib/server/functions/createPrivateGroup.js b/packages/rocketchat-lib/server/functions/createPrivateGroup.js
deleted file mode 100644
index 3038bac2315fc..0000000000000
--- a/packages/rocketchat-lib/server/functions/createPrivateGroup.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* globals RocketChat */
-RocketChat.createPrivateGroup = function(name, owner, members) {
- name = s.trim(name);
- owner = s.trim(owner);
- members = [].concat(members);
-
- if (!name) {
- throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createPrivateGroup' });
- }
-
- if (!owner) {
- throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'RocketChat.createPrivateGroup' });
- }
-
- let nameValidation;
- try {
- nameValidation = new RegExp('^' + RocketChat.settings.get('UTF8_Names_Validation') + '$');
- } catch (error) {
- nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
- }
-
- if (!nameValidation.test(name)) {
- throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createPrivateGroup' });
- }
-
- let now = new Date();
- if (!_.contains(members, owner)) {
- members.push(owner);
- }
-
- // avoid duplicate names
- let room = RocketChat.models.Rooms.findOneByName(name);
- if (room) {
- if (room.archived) {
- throw new Meteor.Error('error-archived-duplicate-name', 'There\'s an archived channel with name ' + name, { function: 'RocketChat.createPrivateGroup', room_name: name });
- } else {
- throw new Meteor.Error('error-duplicate-channel-name', 'A channel with name \'' + name + '\' exists', { function: 'RocketChat.createPrivateGroup', room_name: name });
- }
- }
-
- room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames('p', name, owner, members, { ts: now });
-
- for (let username of members) {
- let member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }});
- if (!member) {
- continue;
- }
-
- let extra = { open: true };
-
- if (username === owner) {
- extra.ls = now;
- }
-
- RocketChat.models.Subscriptions.createWithRoomAndUser(room, member, extra);
- }
-
- // set owner
- owner = RocketChat.models.Users.findOneByUsername(owner, { fields: { username: 1 }});
- RocketChat.authz.addUserRoles(owner._id, ['owner'], room._id);
-
- return {
- rid: room._id
- };
-};
diff --git a/packages/rocketchat-lib/server/functions/createRoom.js b/packages/rocketchat-lib/server/functions/createRoom.js
index db9bfe672efe4..7e2227600e547 100644
--- a/packages/rocketchat-lib/server/functions/createRoom.js
+++ b/packages/rocketchat-lib/server/functions/createRoom.js
@@ -1,5 +1,8 @@
/* globals RocketChat */
-RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData={}) {
+import _ from 'underscore';
+import s from 'underscore.string';
+
+RocketChat.createRoom = function(type, name, serverId, owner, members, readOnly, extraData={}) {
name = s.trim(name);
owner = s.trim(owner);
members = [].concat(members);
@@ -8,41 +11,27 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createRoom' });
}
+ if (!serverId) {
+ throw new Meteor.Error('error-invalid-serverId', 'Invalid serverId', { function: 'RocketChat.createRoom' });
+ }
+
owner = RocketChat.models.Users.findOneByUsername(owner, { fields: { username: 1 }});
if (!owner) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'RocketChat.createRoom' });
}
- let nameValidation;
- try {
- nameValidation = new RegExp('^' + RocketChat.settings.get('UTF8_Names_Validation') + '$');
- } catch (error) {
- nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
- }
-
- if (!nameValidation.test(name)) {
- throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'RocketChat.createRoom' });
- }
+ const slugifiedRoomName = RocketChat.getValidRoomName(name, serverId);
- let now = new Date();
+ const now = new Date();
if (!_.contains(members, owner.username)) {
members.push(owner.username);
}
- // avoid duplicate names
- let room = RocketChat.models.Rooms.findOneByName(name);
- if (room) {
- if (room.archived) {
- throw new Meteor.Error('error-archived-duplicate-name', 'There\'s an archived channel with name ' + name, { function: 'RocketChat.createRoom', room_name: name });
- } else {
- throw new Meteor.Error('error-duplicate-channel-name', 'A channel with name \'' + name + '\' exists', { function: 'RocketChat.createRoom', room_name: name });
- }
- }
-
if (type === 'c') {
RocketChat.callbacks.run('beforeCreateChannel', owner, {
t: 'c',
- name: name,
+ name: slugifiedRoomName,
+ fname: name,
ts: now,
ro: readOnly === true,
sysMes: readOnly !== true,
@@ -60,10 +49,10 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
sysMes: readOnly !== true
});
- room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner, members, extraData);
+ const room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, serverId, slugifiedRoomName, name, owner, members, extraData);
- for (let username of members) {
- let member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }});
+ for (const username of members) {
+ const member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }});
if (!member) {
continue;
}
@@ -73,13 +62,13 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
RocketChat.models.Rooms.muteUsernameByRoomId(room._id, username);
}
- let extra = { open: true };
+ const extra = { open: true };
if (username === owner.username) {
extra.ls = now;
}
- RocketChat.models.Subscriptions.createWithRoomAndUser(room, member, extra);
+ RocketChat.models.Subscriptions.createWithRoomAndUser(room, member, serverId, extra);
}
RocketChat.authz.addUserRoles(owner._id, ['owner'], room._id);
@@ -88,9 +77,14 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
Meteor.defer(() => {
RocketChat.callbacks.run('afterCreateChannel', owner, room);
});
+ } else if (type === 'p') {
+ Meteor.defer(() => {
+ RocketChat.callbacks.run('afterCreatePrivateGroup', owner, room);
+ });
}
return {
- rid: room._id
+ rid: room._id,
+ name: slugifiedRoomName
};
};
diff --git a/packages/rocketchat-lib/server/functions/deleteMessage.js b/packages/rocketchat-lib/server/functions/deleteMessage.js
index a193308fb2ebb..9111557397d1c 100644
--- a/packages/rocketchat-lib/server/functions/deleteMessage.js
+++ b/packages/rocketchat-lib/server/functions/deleteMessage.js
@@ -1,7 +1,7 @@
/* globals FileUpload */
RocketChat.deleteMessage = function(message, user) {
- let keepHistory = RocketChat.settings.get('Message_KeepHistory');
- let showDeletedStatus = RocketChat.settings.get('Message_ShowDeletedStatus');
+ const keepHistory = RocketChat.settings.get('Message_KeepHistory');
+ const showDeletedStatus = RocketChat.settings.get('Message_ShowDeletedStatus');
let deletedMsg;
if (keepHistory) {
@@ -21,7 +21,7 @@ RocketChat.deleteMessage = function(message, user) {
}
if (message.file && message.file._id) {
- FileUpload.delete(message.file._id);
+ FileUpload.getStore('Uploads').deleteById(message.file._id);
}
Meteor.defer(function() {
@@ -29,6 +29,15 @@ RocketChat.deleteMessage = function(message, user) {
});
}
+ // update last message
+ if (RocketChat.settings.get('Store_Last_Message')) {
+ const room = RocketChat.models.Rooms.findOneById(message.rid, { fields: { lastMessage: 1 } });
+ if (!room.lastMessage || room.lastMessage._id === message._id) {
+ const lastMessage = RocketChat.models.Messages.getLastVisibleMessageSentWithNoTypeByRoomId(message.rid, message._id);
+ RocketChat.models.Rooms.setLastMessageById(message.rid, lastMessage);
+ }
+ }
+
if (showDeletedStatus) {
RocketChat.models.Messages.setAsDeletedByIdAndUser(message._id, user);
} else {
diff --git a/packages/rocketchat-lib/server/functions/deleteUser.js b/packages/rocketchat-lib/server/functions/deleteUser.js
index ad6b5a3f7e8a3..d54743f93e036 100644
--- a/packages/rocketchat-lib/server/functions/deleteUser.js
+++ b/packages/rocketchat-lib/server/functions/deleteUser.js
@@ -1,28 +1,32 @@
-/* globals RocketChat */
RocketChat.deleteUser = function(userId) {
const user = RocketChat.models.Users.findOneById(userId);
- RocketChat.models.Messages.removeByUserId(userId); // Remove user messages
- RocketChat.models.Subscriptions.findByUserId(userId).forEach((subscription) => {
- let room = RocketChat.models.Rooms.findOneById(subscription.rid);
- if (room) {
- if (room.t !== 'c' && room.usernames.length === 1) {
- RocketChat.models.Rooms.removeById(subscription.rid); // Remove non-channel rooms with only 1 user (the one being deleted)
+ // Users without username can't do anything, so there is nothing to remove
+ if (user.username != null) {
+ RocketChat.models.Messages.removeByUserId(userId); // Remove user messages
+ RocketChat.models.Subscriptions.db.findByUserId(userId).forEach((subscription) => {
+ const room = RocketChat.models.Rooms.findOneById(subscription.rid);
+ if (room) {
+ if (room.t !== 'c' && room.usernames.length === 1) {
+ RocketChat.models.Rooms.removeById(subscription.rid); // Remove non-channel rooms with only 1 user (the one being deleted)
+ }
+ if (room.t === 'd') {
+ RocketChat.models.Subscriptions.removeByRoomId(subscription.rid);
+ RocketChat.models.Messages.removeByRoomId(subscription.rid);
+ }
}
- if (room.t === 'd') {
- RocketChat.models.Subscriptions.removeByRoomId(subscription.rid);
- RocketChat.models.Messages.removeByRoomId(subscription.rid);
- }
- }
- });
+ });
- RocketChat.models.Subscriptions.removeByUserId(userId); // Remove user subscriptions
- RocketChat.models.Rooms.removeByTypeContainingUsername('d', user.username); // Remove direct rooms with the user
- RocketChat.models.Rooms.removeUsernameFromAll(user.username); // Remove user from all other rooms
+ RocketChat.models.Subscriptions.removeByUserId(userId); // Remove user subscriptions
+ RocketChat.models.Rooms.removeByTypeContainingUsername('d', user.username); // Remove direct rooms with the user
+ RocketChat.models.Rooms.removeUsernameFromAll(user.username); // Remove user from all other rooms
+
+ // removes user's avatar
+ if (user.avatarOrigin === 'upload' || user.avatarOrigin === 'url') {
+ FileUpload.getStore('Avatars').deleteByName(user.username);
+ }
- // removes user's avatar
- if (user.avatarOrigin === 'upload' || user.avatarOrigin === 'url') {
- RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(user.username + '.jpg'));
+ RocketChat.models.Integrations.disableByUserId(userId); // Disables all the integrations which rely on the user being deleted.
}
RocketChat.models.Users.removeById(userId); // Remove user from users database
diff --git a/packages/rocketchat-lib/server/functions/getFullUserData.js b/packages/rocketchat-lib/server/functions/getFullUserData.js
index 7e77af13e3603..056c4643d90f1 100644
--- a/packages/rocketchat-lib/server/functions/getFullUserData.js
+++ b/packages/rocketchat-lib/server/functions/getFullUserData.js
@@ -1,4 +1,7 @@
/* globals RocketChat */
+import _ from 'underscore';
+import s from 'underscore.string';
+
RocketChat.getFullUserData = function({userId, filter, limit}) {
let fields = {
name: 1,
@@ -6,7 +9,8 @@ RocketChat.getFullUserData = function({userId, filter, limit}) {
status: 1,
utcOffset: 1,
type: 1,
- active: 1
+ active: 1,
+ reason: 1
};
if (RocketChat.authz.hasPermission(userId, 'view-full-other-user-info')) {
@@ -33,8 +37,8 @@ RocketChat.getFullUserData = function({userId, filter, limit}) {
}
const options = {
- fields: fields,
- limit: limit,
+ fields,
+ limit,
sort: { username: 1 }
};
diff --git a/packages/rocketchat-lib/server/functions/getRoomByNameOrIdWithOptionToJoin.js b/packages/rocketchat-lib/server/functions/getRoomByNameOrIdWithOptionToJoin.js
new file mode 100644
index 0000000000000..17aa5c6d7dad3
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/getRoomByNameOrIdWithOptionToJoin.js
@@ -0,0 +1,80 @@
+/* globals RocketChat */
+import _ from 'underscore';
+
+RocketChat.getRoomByNameOrIdWithOptionToJoin = function _getRoomByNameOrIdWithOptionToJoin({ currentUserId, nameOrId, type='', tryDirectByUserIdOnly=false, joinChannel=true, errorOnEmpty=true }) {
+ let room;
+
+ //If the nameOrId starts with #, then let's try to find a channel or group
+ if (nameOrId.startsWith('#')) {
+ nameOrId = nameOrId.substring(1);
+ room = RocketChat.models.Rooms.findOneByIdOrName(nameOrId);
+ } else if (nameOrId.startsWith('@') || type === 'd') {
+ //If the nameOrId starts with @ OR type is 'd', then let's try just a direct message
+ nameOrId = nameOrId.replace('@', '');
+
+ let roomUser;
+ if (tryDirectByUserIdOnly) {
+ roomUser = RocketChat.models.Users.findOneById(nameOrId);
+ } else {
+ roomUser = RocketChat.models.Users.findOne({
+ $or: [{ _id: nameOrId }, { username: nameOrId }]
+ });
+ }
+
+ const rid = _.isObject(roomUser) ? [currentUserId, roomUser._id].sort().join('') : nameOrId;
+ room = RocketChat.models.Rooms.findOneById(rid);
+
+ //If the room hasn't been found yet, let's try some more
+ if (!_.isObject(room)) {
+ //If the roomUser wasn't found, then there's no destination to point towards
+ //so return out based upon errorOnEmpty
+ if (!_.isObject(roomUser)) {
+ if (errorOnEmpty) {
+ throw new Meteor.Error('invalid-channel');
+ } else {
+ return;
+ }
+ }
+
+ room = Meteor.runAsUser(currentUserId, function() {
+ const {rid} = Meteor.call('createDirectMessage', roomUser.username);
+ return RocketChat.models.Rooms.findOneById(rid);
+ });
+ }
+ } else {
+ //Otherwise, we'll treat this as a channel or group.
+ room = RocketChat.models.Rooms.findOneByIdOrName(nameOrId);
+ }
+
+ //If no room was found, handle the room return based upon errorOnEmpty
+ if (!room && errorOnEmpty) {
+ throw new Meteor.Error('invalid-channel');
+ } else if (!room) {
+ return;
+ }
+
+ //If a room was found and they provided a type to search, then check
+ //and if the type found isn't what we're looking for then handle
+ //the return based upon errorOnEmpty
+ if (type && room.t !== type) {
+ if (errorOnEmpty) {
+ throw new Meteor.Error('invalid-channel');
+ } else {
+ return;
+ }
+ }
+
+ //If the room type is channel and joinChannel has been passed, try to join them
+ //if they can't join the room, this will error out!
+ if (room.t === 'c' && joinChannel) {
+ const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, currentUserId);
+
+ if (!sub) {
+ Meteor.runAsUser(currentUserId, function() {
+ return Meteor.call('joinRoom', room._id);
+ });
+ }
+ }
+
+ return room;
+};
diff --git a/packages/rocketchat-lib/server/functions/loadMessageHistory.js b/packages/rocketchat-lib/server/functions/loadMessageHistory.js
new file mode 100644
index 0000000000000..f09d9030353f2
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/loadMessageHistory.js
@@ -0,0 +1,88 @@
+import _ from 'underscore';
+
+const hideMessagesOfType = [];
+
+RocketChat.settings.get(/Message_HideType_.+/, function(key, value) {
+ const type = key.replace('Message_HideType_', '');
+ const types = type === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [type];
+
+ return types.forEach((type) => {
+ const index = hideMessagesOfType.indexOf(type);
+
+ if (value === true && index === -1) {
+ return hideMessagesOfType.push(type);
+ }
+
+ if (index > -1) {
+ return hideMessagesOfType.splice(index, 1);
+ }
+ });
+});
+
+RocketChat.loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls }) {
+ const options = {
+ sort: {
+ ts: -1
+ },
+ limit
+ };
+
+ if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
+ options.fields = {
+ editedAt: 0
+ };
+ }
+
+ let records;
+ if (end != null) {
+ records = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, hideMessagesOfType, options).fetch();
+ } else {
+ records = RocketChat.models.Messages.findVisibleByRoomIdNotContainingTypes(rid, hideMessagesOfType, options).fetch();
+ }
+
+ const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
+
+ const messages = records.map((message) => {
+ message.starred = _.findWhere(message.starred, {
+ _id: userId
+ });
+ if (message.u && message.u._id && UI_Use_Real_Name) {
+ const user = RocketChat.models.Users.findOneById(message.u._id);
+ message.u.name = user && user.name;
+ }
+ if (message.mentions && message.mentions.length && UI_Use_Real_Name) {
+ message.mentions.forEach((mention) => {
+ const user = RocketChat.models.Users.findOneById(mention._id);
+ mention.name = user && user.name;
+ });
+ }
+ return message;
+ });
+
+ let unreadNotLoaded = 0;
+ let firstUnread;
+
+ if (ls != null) {
+ const firstMessage = messages[messages.length - 1];
+
+ if ((firstMessage != null ? firstMessage.ts : undefined) > ls) {
+ delete options.limit;
+
+ const unreadMessages = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, hideMessagesOfType, {
+ limit: 1,
+ sort: {
+ ts: 1
+ }
+ });
+
+ firstUnread = unreadMessages.fetch()[0];
+ unreadNotLoaded = unreadMessages.count();
+ }
+ }
+
+ return {
+ messages,
+ firstUnread,
+ unreadNotLoaded
+ };
+};
diff --git a/packages/rocketchat-lib/server/functions/removeUserFromRoom.js b/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
index 57fa231c86bb0..87b9faf5d0861 100644
--- a/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
+++ b/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
@@ -1,12 +1,12 @@
RocketChat.removeUserFromRoom = function(rid, user) {
- let room = RocketChat.models.Rooms.findOneById(rid);
+ const room = RocketChat.models.Rooms.findOneById(rid);
if (room) {
RocketChat.callbacks.run('beforeLeaveRoom', user, room);
RocketChat.models.Rooms.removeUsernameById(rid, user.username);
if (room.usernames.indexOf(user.username) !== -1) {
- let removedUser = user;
+ const removedUser = user;
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(rid, removedUser);
}
diff --git a/packages/rocketchat-lib/server/functions/saveCustomFields.js b/packages/rocketchat-lib/server/functions/saveCustomFields.js
index 1cb1794ac0b5e..7336a6056c537 100644
--- a/packages/rocketchat-lib/server/functions/saveCustomFields.js
+++ b/packages/rocketchat-lib/server/functions/saveCustomFields.js
@@ -1,56 +1,8 @@
+import s from 'underscore.string';
+
RocketChat.saveCustomFields = function(userId, formData) {
if (s.trim(RocketChat.settings.get('Accounts_CustomFields')) !== '') {
- let customFieldsMeta;
- try {
- customFieldsMeta = JSON.parse(RocketChat.settings.get('Accounts_CustomFields'));
- } catch (e) {
- throw new Meteor.Error('error-invalid-customfield-json', 'Invalid JSON for Custom Fields');
- }
-
- let customFields = {};
-
- Object.keys(customFieldsMeta).forEach((fieldName) => {
- let field = customFieldsMeta[fieldName];
-
- customFields[fieldName] = formData[fieldName];
- if (field.required && !formData[fieldName]) {
- throw new Meteor.Error('error-user-registration-custom-field', `Field ${fieldName} is required`, { method: 'registerUser' });
- }
-
- if (field.type === 'select' && field.options.indexOf(formData[fieldName]) === -1) {
- throw new Meteor.Error('error-user-registration-custom-field', `Value for field ${fieldName} is invalid`, { method: 'registerUser' });
- }
-
- if (field.maxLength && formData[fieldName].length > field.maxLength) {
- throw new Meteor.Error('error-user-registration-custom-field', `Max length of field ${fieldName} ${field.maxLength}`, { method: 'registerUser' });
- }
-
- if (field.minLength && formData[fieldName].length < field.minLength) {
- throw new Meteor.Error('error-user-registration-custom-field', `Min length of field ${fieldName} ${field.minLength}`, { method: 'registerUser' });
- }
- });
-
- // for fieldName, field of customFieldsMeta
- RocketChat.models.Users.setCustomFields(userId, customFields);
-
- Object.keys(customFields).forEach((fieldName) => {
- if (!customFieldsMeta[fieldName].modifyRecordField) {
- return;
- }
-
- let modifyRecordField = customFieldsMeta[fieldName].modifyRecordField;
- let update = {};
- if (modifyRecordField.array) {
- update.$addToSet = {};
- update.$addToSet[modifyRecordField.field] = customFields[fieldName];
- } else {
- update.$set = {};
- update.$set[modifyRecordField.field] = customFields[fieldName];
- }
-
- RocketChat.models.Users.update(userId, update);
- });
-
- return true;
+ RocketChat.validateCustomFields(formData);
+ return RocketChat.saveCustomFieldsWithoutValidation(userId, formData);
}
};
diff --git a/packages/rocketchat-lib/server/functions/saveCustomFieldsWithoutValidation.js b/packages/rocketchat-lib/server/functions/saveCustomFieldsWithoutValidation.js
new file mode 100644
index 0000000000000..4b76441089d18
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/saveCustomFieldsWithoutValidation.js
@@ -0,0 +1,37 @@
+import s from 'underscore.string';
+
+RocketChat.saveCustomFieldsWithoutValidation = function(userId, formData) {
+ if (s.trim(RocketChat.settings.get('Accounts_CustomFields')) !== '') {
+ let customFieldsMeta;
+ try {
+ customFieldsMeta = JSON.parse(RocketChat.settings.get('Accounts_CustomFields'));
+ } catch (e) {
+ throw new Meteor.Error('error-invalid-customfield-json', 'Invalid JSON for Custom Fields');
+ }
+
+ const customFields = {};
+ Object.keys(customFieldsMeta).forEach(key => customFields[key] = formData[key]);
+ RocketChat.models.Users.setCustomFields(userId, customFields);
+
+ // Update customFields of all Direct Messages' Rooms for userId
+ RocketChat.models.Subscriptions.setCustomFieldsDirectMessagesByUserId(userId, customFields);
+
+ Object.keys(customFields).forEach((fieldName) => {
+ if (!customFieldsMeta[fieldName].modifyRecordField) {
+ return;
+ }
+
+ const modifyRecordField = customFieldsMeta[fieldName].modifyRecordField;
+ const update = {};
+ if (modifyRecordField.array) {
+ update.$addToSet = {};
+ update.$addToSet[modifyRecordField.field] = customFields[fieldName];
+ } else {
+ update.$set = {};
+ update.$set[modifyRecordField.field] = customFields[fieldName];
+ }
+
+ RocketChat.models.Users.update(userId, update);
+ });
+ }
+};
diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js
index ac322efd23104..9f45ed155c338 100644
--- a/packages/rocketchat-lib/server/functions/saveUser.js
+++ b/packages/rocketchat-lib/server/functions/saveUser.js
@@ -1,7 +1,10 @@
/* globals Gravatar */
+import _ from 'underscore';
+import s from 'underscore.string';
+
RocketChat.saveUser = function(userId, userData) {
const user = RocketChat.models.Users.findOneById(userId);
- let existingRoles = _.pluck(RocketChat.authz.getRoles(), '_id');
+ const existingRoles = _.pluck(RocketChat.authz.getRoles(), '_id');
if (userData._id && userId !== userData._id && !RocketChat.authz.hasPermission(userId, 'edit-other-user-info')) {
throw new Meteor.Error('error-action-not-allowed', 'Editing user is not allowed', { method: 'insertOrUpdateUser', action: 'Editing_user' });
@@ -30,13 +33,13 @@ RocketChat.saveUser = function(userId, userData) {
let nameValidation;
try {
- nameValidation = new RegExp('^' + RocketChat.settings.get('UTF8_Names_Validation') + '$');
+ nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
} catch (e) {
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
}
if (userData.username && !nameValidation.test(userData.username)) {
- throw new Meteor.Error('error-input-is-not-a-valid-field', `${_.escape(userData.username)} is not a valid username`, { method: 'insertOrUpdateUser', input: userData.username, field: 'Username' });
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${ _.escape(userData.username) } is not a valid username`, { method: 'insertOrUpdateUser', input: userData.username, field: 'Username' });
}
if (!userData._id && !userData.password) {
@@ -45,11 +48,11 @@ RocketChat.saveUser = function(userId, userData) {
if (!userData._id) {
if (!RocketChat.checkUsernameAvailability(userData.username)) {
- throw new Meteor.Error('error-field-unavailable', `${_.escape(userData.username)} is already in use :(`, { method: 'insertOrUpdateUser', field: userData.username });
+ throw new Meteor.Error('error-field-unavailable', `${ _.escape(userData.username) } is already in use :(`, { method: 'insertOrUpdateUser', field: userData.username });
}
if (userData.email && !RocketChat.checkEmailAvailability(userData.email)) {
- throw new Meteor.Error('error-field-unavailable', `${_.escape(userData.email)} is already in use :(`, { method: 'insertOrUpdateUser', field: userData.email });
+ throw new Meteor.Error('error-field-unavailable', `${ _.escape(userData.email) } is already in use :(`, { method: 'insertOrUpdateUser', field: userData.email });
}
RocketChat.validateEmailDomain(userData.email);
@@ -69,11 +72,12 @@ RocketChat.saveUser = function(userId, userData) {
const updateUser = {
$set: {
name: userData.name,
- roles: userData.roles || ['user']
+ roles: userData.roles || ['user'],
+ settings: userData.settings
}
};
- if (userData.requirePasswordChange) {
+ if (typeof userData.requirePasswordChange !== 'undefined') {
updateUser.$set.requirePasswordChange = userData.requirePasswordChange;
}
@@ -81,13 +85,14 @@ RocketChat.saveUser = function(userId, userData) {
updateUser.$set['emails.0.verified'] = true;
}
- Meteor.users.update({ _id: _id }, updateUser);
+ Meteor.users.update({ _id }, updateUser);
if (userData.sendWelcomeEmail) {
const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
- let subject, html, email;
+ let subject;
+ let html;
if (RocketChat.settings.get('Accounts_UserAddedEmail_Customized')) {
subject = RocketChat.settings.get('Accounts_UserAddedEmailSubject');
@@ -104,10 +109,10 @@ RocketChat.saveUser = function(userId, userData) {
password: userData.password
});
- email = {
+ const email = {
to: userData.email,
from: RocketChat.settings.get('From_Email'),
- subject: subject,
+ subject,
html: header + html + footer
};
@@ -115,7 +120,7 @@ RocketChat.saveUser = function(userId, userData) {
try {
Email.send(email);
} catch (error) {
- throw new Meteor.Error('error-email-send-failed', 'Error trying to send email: ' + error.message, { function: 'RocketChat.saveUser', message: error.message });
+ throw new Meteor.Error('error-email-send-failed', `Error trying to send email: ${ error.message }`, { function: 'RocketChat.saveUser', message: error.message });
}
});
}
@@ -123,7 +128,7 @@ RocketChat.saveUser = function(userId, userData) {
userData._id = _id;
if (RocketChat.settings.get('Accounts_SetDefaultAvatar') === true && userData.email) {
- let gravatarUrl = Gravatar.imageUrl(userData.email, {default: '404', size: 200, secure: true});
+ const gravatarUrl = Gravatar.imageUrl(userData.email, {default: '404', size: 200, secure: true});
try {
RocketChat.setUserAvatar(userData, gravatarUrl, '', 'url');
@@ -139,6 +144,10 @@ RocketChat.saveUser = function(userId, userData) {
RocketChat.setUsername(userData._id, userData.username);
}
+ if (userData.name) {
+ RocketChat.setRealName(userData._id, userData.name);
+ }
+
if (userData.email) {
RocketChat.setEmail(userData._id, userData.email);
}
@@ -151,22 +160,20 @@ RocketChat.saveUser = function(userId, userData) {
$set: {}
};
- if (userData.name) {
- updateUser.$set.name = userData.name;
- }
-
if (userData.roles) {
updateUser.$set.roles = userData.roles;
}
- if (userData.requirePasswordChange) {
- updateUser.$set.requirePasswordChange = userData.requirePasswordChange;
+ if (userData.settings) {
+ updateUser.$set.settings = { preferences: userData.settings.preferences };
}
- if (userData.verified) {
- updateUser.$set['emails.0.verified'] = userData.verified;
+ if (typeof userData.requirePasswordChange !== 'undefined') {
+ updateUser.$set.requirePasswordChange = userData.requirePasswordChange;
}
+ updateUser.$set['emails.0.verified'] = !!userData.verified;
+
Meteor.users.update({ _id: userData._id }, updateUser);
return true;
diff --git a/packages/rocketchat-lib/server/functions/sendMessage.coffee b/packages/rocketchat-lib/server/functions/sendMessage.coffee
deleted file mode 100644
index bdce87faba4d4..0000000000000
--- a/packages/rocketchat-lib/server/functions/sendMessage.coffee
+++ /dev/null
@@ -1,50 +0,0 @@
-RocketChat.sendMessage = (user, message, room, upsert = false) ->
- if not user or not message or not room._id
- return false
-
- unless message.ts?
- message.ts = new Date()
-
- message.u = _.pick user, ['_id','username']
-
- if not Match.test(message.msg, String)
- message.msg = ''
-
- message.rid = room._id
-
- if not room.usernames? || room.usernames.length is 0
- updated_room = RocketChat.models.Rooms.findOneById(room._id)
- if updated_room?
- room = updated_room
- else
- room.usernames = []
-
- if message.parseUrls isnt false
- if urls = message.msg.match /([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g
- message.urls = urls.map (url) -> url: url
-
- message = RocketChat.callbacks.run 'beforeSaveMessage', message
-
- # Avoid saving sandstormSessionId to the database
- sandstormSessionId = null
- if message.sandstormSessionId
- sandstormSessionId = message.sandstormSessionId
- delete message.sandstormSessionId
-
- if message._id? and upsert
- _id = message._id
- delete message._id
- RocketChat.models.Messages.upsert {_id: _id, 'u._id': message.u._id}, message
- message._id = _id
- else
- message._id = RocketChat.models.Messages.insert message
-
- ###
- Defer other updates as their return is not interesting to the user
- ###
- Meteor.defer ->
- # Execute all callbacks
- message.sandstormSessionId = sandstormSessionId
- RocketChat.callbacks.run 'afterSaveMessage', message, room
-
- return message
diff --git a/packages/rocketchat-lib/server/functions/sendMessage.js b/packages/rocketchat-lib/server/functions/sendMessage.js
new file mode 100644
index 0000000000000..197ca28729fd1
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/sendMessage.js
@@ -0,0 +1,69 @@
+import _ from 'underscore';
+
+RocketChat.sendMessage = function(user, message, room, upsert = false) {
+ if (!user || !message || !room._id) {
+ return false;
+ }
+ if (message.ts == null) {
+ message.ts = new Date();
+ }
+ message.u = _.pick(user, ['_id', 'username', 'name']);
+ if (!Match.test(message.msg, String)) {
+ message.msg = '';
+ }
+ message.rid = room._id;
+ if (!room.usernames || room.usernames.length === 0) {
+ const updated_room = RocketChat.models.Rooms.findOneById(room._id);
+ if (updated_room != null) {
+ room = updated_room;
+ } else {
+ room.usernames = [];
+ }
+ }
+ if (message.parseUrls !== false) {
+ const urls = message.msg.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g);
+
+ if (urls) {
+ message.urls = urls.map(function(url) {
+ return {
+ url
+ };
+ });
+ }
+ }
+
+ if (RocketChat.settings.get('Message_Read_Receipt_Enabled')) {
+ message.unread = true;
+ }
+
+ message = RocketChat.callbacks.run('beforeSaveMessage', message);
+ if (message) {
+ // Avoid saving sandstormSessionId to the database
+ let sandstormSessionId = null;
+ if (message.sandstormSessionId) {
+ sandstormSessionId = message.sandstormSessionId;
+ delete message.sandstormSessionId;
+ }
+ if (message._id && upsert) {
+ const _id = message._id;
+ delete message._id;
+ RocketChat.models.Messages.upsert({
+ _id,
+ 'u._id': message.u._id
+ }, message);
+ message._id = _id;
+ } else {
+ message._id = RocketChat.models.Messages.insert(message);
+ }
+
+ /*
+ Defer other updates as their return is not interesting to the user
+ */
+ Meteor.defer(() => {
+ // Execute all callbacks
+ message.sandstormSessionId = sandstormSessionId;
+ return RocketChat.callbacks.run('afterSaveMessage', message, room, user._id);
+ });
+ return message;
+ }
+};
diff --git a/packages/rocketchat-lib/server/functions/setEmail.js b/packages/rocketchat-lib/server/functions/setEmail.js
index 2a60737ff6b0d..b63f39cb83230 100644
--- a/packages/rocketchat-lib/server/functions/setEmail.js
+++ b/packages/rocketchat-lib/server/functions/setEmail.js
@@ -1,3 +1,5 @@
+import s from 'underscore.string';
+
RocketChat._setEmail = function(userId, email) {
email = s.trim(email);
if (!userId) {
@@ -19,7 +21,7 @@ RocketChat._setEmail = function(userId, email) {
// Check email availability
if (!RocketChat.checkEmailAvailability(email)) {
- throw new Meteor.Error('error-field-unavailable', email + ' is already in use :(', { function: '_setEmail', field: email });
+ throw new Meteor.Error('error-field-unavailable', `${ email } is already in use :(`, { function: '_setEmail', field: email });
}
// Set new email
@@ -29,5 +31,5 @@ RocketChat._setEmail = function(userId, email) {
};
RocketChat.setEmail = RocketChat.RateLimiter.limitFunction(RocketChat._setEmail, 1, 60000, {
- 0: function(userId) { return !userId || !RocketChat.authz.hasPermission(userId, 'edit-other-user-info'); } // Administrators have permission to change others emails, so don't limit those
+ 0() { return !Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-info'); } // Administrators have permission to change others emails, so don't limit those
});
diff --git a/packages/rocketchat-lib/server/functions/setRealName.js b/packages/rocketchat-lib/server/functions/setRealName.js
new file mode 100644
index 0000000000000..da7be9783ca08
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/setRealName.js
@@ -0,0 +1,33 @@
+import s from 'underscore.string';
+
+RocketChat._setRealName = function(userId, name) {
+ name = s.trim(name);
+ if (!userId || !name) {
+ return false;
+ }
+
+ const user = RocketChat.models.Users.findOneById(userId);
+
+ // User already has desired name, return
+ if (user.name === name) {
+ return user;
+ }
+
+ // Set new name
+ RocketChat.models.Users.setName(user._id, name);
+ user.name = name;
+
+ if (RocketChat.settings.get('UI_Use_Real_Name') === true) {
+ RocketChat.Notifications.notifyLogged('Users:NameChanged', {
+ _id: user._id,
+ name: user.name,
+ username: user.username
+ });
+ }
+
+ return user;
+};
+
+RocketChat.setRealName = RocketChat.RateLimiter.limitFunction(RocketChat._setRealName, 1, 60000, {
+ 0() { return !Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-info'); } // Administrators have permission to change others names, so don't limit those
+});
diff --git a/packages/rocketchat-lib/server/functions/setUserAvatar.js b/packages/rocketchat-lib/server/functions/setUserAvatar.js
index 03af163dd7c23..480688d7904b3 100644
--- a/packages/rocketchat-lib/server/functions/setUserAvatar.js
+++ b/packages/rocketchat-lib/server/functions/setUserAvatar.js
@@ -1,5 +1,6 @@
RocketChat.setUserAvatar = function(user, dataURI, contentType, service) {
- let encoding, image;
+ let encoding;
+ let image;
if (service === 'initials') {
return RocketChat.models.Users.setAvatarOrigin(user._id, service);
@@ -9,20 +10,20 @@ RocketChat.setUserAvatar = function(user, dataURI, contentType, service) {
try {
result = HTTP.get(dataURI, { npmRequestOptions: {encoding: 'binary'} });
} catch (error) {
- if (error.response.statusCode !== 404) {
- console.log(`Error while handling the setting of the avatar from a url (${dataURI}) for ${user.username}:`, error);
- throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${dataURI}) for ${user.username}`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username });
+ if (!error.response || error.response.statusCode !== 404) {
+ console.log(`Error while handling the setting of the avatar from a url (${ dataURI }) for ${ user.username }:`, error);
+ throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${ dataURI }) for ${ user.username }`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username });
}
}
if (result.statusCode !== 200) {
- console.log(`Not a valid response, ${result.statusCode}, from the avatar url: ${dataURI}`);
- throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${dataURI}`, { function: 'RocketChat.setUserAvatar', url: dataURI });
+ console.log(`Not a valid response, ${ result.statusCode }, from the avatar url: ${ dataURI }`);
+ throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ dataURI }`, { function: 'RocketChat.setUserAvatar', url: dataURI });
}
if (!/image\/.+/.test(result.headers['content-type'])) {
- console.log(`Not a valid content-type from the provided url, ${result.headers['content-type']}, from the avatar url: ${dataURI}`);
- throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${dataURI}`, { function: 'RocketChat.setUserAvatar', url: dataURI });
+ console.log(`Not a valid content-type from the provided url, ${ result.headers['content-type'] }, from the avatar url: ${ dataURI }`);
+ throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ dataURI }`, { function: 'RocketChat.setUserAvatar', url: dataURI });
}
encoding = 'binary';
@@ -32,20 +33,26 @@ RocketChat.setUserAvatar = function(user, dataURI, contentType, service) {
encoding = 'binary';
image = dataURI;
} else {
- let fileData = RocketChatFile.dataURIParse(dataURI);
+ const fileData = RocketChatFile.dataURIParse(dataURI);
encoding = 'base64';
image = fileData.image;
contentType = fileData.contentType;
}
- let rs = RocketChatFile.bufferToStream(new Buffer(image, encoding));
- RocketChatFileAvatarInstance.deleteFile(encodeURIComponent(`${user.username}.jpg`));
- let ws = RocketChatFileAvatarInstance.createWriteStream(encodeURIComponent(`${user.username}.jpg`), contentType);
- ws.on('end', Meteor.bindEnvironment(function() {
+ const buffer = new Buffer(image, encoding);
+ const fileStore = FileUpload.getStore('Avatars');
+ fileStore.deleteByName(user.username);
+
+ const file = {
+ userId: user._id,
+ type: contentType,
+ size: buffer.length
+ };
+
+ fileStore.insert(file, buffer, () => {
Meteor.setTimeout(function() {
RocketChat.models.Users.setAvatarOrigin(user._id, service);
RocketChat.Notifications.notifyLogged('updateAvatar', {username: user.username});
}, 500);
- }));
- rs.pipe(ws);
+ });
};
diff --git a/packages/rocketchat-lib/server/functions/setUsername.coffee b/packages/rocketchat-lib/server/functions/setUsername.coffee
deleted file mode 100644
index 66163088f331f..0000000000000
--- a/packages/rocketchat-lib/server/functions/setUsername.coffee
+++ /dev/null
@@ -1,77 +0,0 @@
-RocketChat._setUsername = (userId, username) ->
- username = s.trim username
- if not userId or not username
- return false
-
- try
- nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$'
- catch
- nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$'
-
- if not nameValidation.test username
- return false
-
- user = RocketChat.models.Users.findOneById userId
-
- # User already has desired username, return
- if user.username is username
- return user
-
- previousUsername = user.username
-
- # Check username availability or if the user already owns a different casing of the name
- if ( !previousUsername or !(username.toLowerCase() == previousUsername.toLowerCase()))
- unless RocketChat.checkUsernameAvailability username
- return false
-
- # If first time setting username, send Enrollment Email
- try
- if not previousUsername and user.emails?.length > 0 and RocketChat.settings.get 'Accounts_Enrollment_Email'
- Accounts.sendEnrollmentEmail(user._id)
- catch error
-
- user.username = username
-
- # If first time setting username, check if should set default avatar
- if not previousUsername and RocketChat.settings.get('Accounts_SetDefaultAvatar') is true
- avatarSuggestions = getAvatarSuggestionForUser user
- for service, avatarData of avatarSuggestions
- if service isnt 'gravatar'
- RocketChat.setUserAvatar(user, avatarData.blob, avatarData.contentType, service)
- gravatar = null
- break
- else
- gravatar = avatarData
- if gravatar?
- RocketChat.setUserAvatar(user, gravatar.blob, gravatar.contentType, 'gravatar')
-
- # Username is available; if coming from old username, update all references
- if previousUsername
- RocketChat.models.Messages.updateAllUsernamesByUserId user._id, username
- RocketChat.models.Messages.updateUsernameOfEditByUserId user._id, username
-
- RocketChat.models.Messages.findByMention(previousUsername).forEach (msg) ->
- updatedMsg = msg.msg.replace(new RegExp("@#{previousUsername}", "ig"), "@#{username}")
- RocketChat.models.Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername msg._id, previousUsername, username, updatedMsg
-
- RocketChat.models.Rooms.replaceUsername previousUsername, username
- RocketChat.models.Rooms.replaceMutedUsername previousUsername, username
- RocketChat.models.Rooms.replaceUsernameOfUserByUserId user._id, username
-
- RocketChat.models.Subscriptions.setUserUsernameByUserId user._id, username
- RocketChat.models.Subscriptions.setNameForDirectRoomsWithOldName previousUsername, username
-
- rs = RocketChatFileAvatarInstance.getFileWithReadStream(encodeURIComponent("#{previousUsername}.jpg"))
- if rs?
- RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{username}.jpg")
- ws = RocketChatFileAvatarInstance.createWriteStream encodeURIComponent("#{username}.jpg"), rs.contentType
- ws.on 'end', Meteor.bindEnvironment ->
- RocketChatFileAvatarInstance.deleteFile encodeURIComponent("#{previousUsername}.jpg")
- rs.readStream.pipe(ws)
-
- # Set new username
- RocketChat.models.Users.setUsername user._id, username
- return user
-
-RocketChat.setUsername = RocketChat.RateLimiter.limitFunction RocketChat._setUsername, 1, 60000,
- 0: (userId) -> return not userId or not RocketChat.authz.hasPermission(userId, 'edit-other-user-info') # Administrators have permission to change others usernames, so don't limit those
diff --git a/packages/rocketchat-lib/server/functions/setUsername.js b/packages/rocketchat-lib/server/functions/setUsername.js
new file mode 100644
index 0000000000000..96b57d1a7c8e3
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/setUsername.js
@@ -0,0 +1,85 @@
+import s from 'underscore.string';
+
+RocketChat._setUsername = function(userId, u) {
+ const username = s.trim(u);
+ if (!userId || !username) {
+ return false;
+ }
+ let nameValidation;
+ try {
+ nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
+ } catch (error) {
+ nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
+ }
+ if (!nameValidation.test(username)) {
+ return false;
+ }
+ const user = RocketChat.models.Users.findOneById(userId);
+ // User already has desired username, return
+ if (user.username === username) {
+ return user;
+ }
+ const previousUsername = user.username;
+ // Check username availability or if the user already owns a different casing of the name
+ if (!previousUsername || !(username.toLowerCase() === previousUsername.toLowerCase())) {
+ if (!RocketChat.checkUsernameAvailability(username)) {
+ return false;
+ }
+ }
+ //If first time setting username, send Enrollment Email
+ try {
+ if (!previousUsername && user.emails && user.emails.length > 0 && RocketChat.settings.get('Accounts_Enrollment_Email')) {
+ Accounts.sendEnrollmentEmail(user._id);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ /* globals getAvatarSuggestionForUser */
+ user.username = username;
+ if (!previousUsername && RocketChat.settings.get('Accounts_SetDefaultAvatar') === true) {
+ const avatarSuggestions = getAvatarSuggestionForUser(user);
+ let gravatar;
+ Object.keys(avatarSuggestions).some(service => {
+ const avatarData = avatarSuggestions[service];
+ if (service !== 'gravatar') {
+ RocketChat.setUserAvatar(user, avatarData.blob, avatarData.contentType, service);
+ gravatar = null;
+ return true;
+ } else {
+ gravatar = avatarData;
+ }
+ });
+ if (gravatar != null) {
+ RocketChat.setUserAvatar(user, gravatar.blob, gravatar.contentType, 'gravatar');
+ }
+ }
+ // Username is available; if coming from old username, update all references
+ if (previousUsername) {
+ RocketChat.models.Messages.updateAllUsernamesByUserId(user._id, username);
+ RocketChat.models.Messages.updateUsernameOfEditByUserId(user._id, username);
+ RocketChat.models.Messages.findByMention(previousUsername).forEach(function(msg) {
+ const updatedMsg = msg.msg.replace(new RegExp(`@${ previousUsername }`, 'ig'), `@${ username }`);
+ return RocketChat.models.Messages.updateUsernameAndMessageOfMentionByIdAndOldUsername(msg._id, previousUsername, username, updatedMsg);
+ });
+ RocketChat.models.Rooms.replaceUsername(previousUsername, username);
+ RocketChat.models.Rooms.replaceMutedUsername(previousUsername, username);
+ RocketChat.models.Rooms.replaceUsernameOfUserByUserId(user._id, username);
+ RocketChat.models.Subscriptions.setUserUsernameByUserId(user._id, username);
+ RocketChat.models.Subscriptions.setNameForDirectRoomsWithOldName(previousUsername, username);
+
+ const fileStore = FileUpload.getStore('Avatars');
+ const file = fileStore.model.findOneByName(previousUsername);
+ if (file) {
+ fileStore.model.updateFileNameById(file._id, username);
+ }
+ }
+ // Set new username*
+ RocketChat.models.Users.setUsername(user._id, username);
+ return user;
+};
+
+RocketChat.setUsername = RocketChat.RateLimiter.limitFunction(RocketChat._setUsername, 1, 60000, {
+ [0](userId) {
+ return !userId || !RocketChat.authz.hasPermission(userId, 'edit-other-user-info');
+ }
+});
diff --git a/packages/rocketchat-lib/server/functions/settings.coffee b/packages/rocketchat-lib/server/functions/settings.coffee
deleted file mode 100644
index f8348261c5f00..0000000000000
--- a/packages/rocketchat-lib/server/functions/settings.coffee
+++ /dev/null
@@ -1,247 +0,0 @@
-blockedSettings = {}
-process.env.SETTINGS_BLOCKED?.split(',').forEach (settingId) ->
- blockedSettings[settingId] = 1
-
-hiddenSettings = {}
-process.env.SETTINGS_HIDDEN?.split(',').forEach (settingId) ->
- hiddenSettings[settingId] = 1
-
-RocketChat.settings._sorter = {}
-
-###
-# Add a setting
-# @param {String} _id
-# @param {Mixed} value
-# @param {Object} setting
-###
-RocketChat.settings.add = (_id, value, options = {}) ->
- # console.log '[functions] RocketChat.settings.add -> '.green, 'arguments:', arguments
-
- if not _id or not value?
- return false
-
- RocketChat.settings._sorter[options.group] ?= 0
-
- options.packageValue = value
- options.valueSource = 'packageValue'
- options.hidden = false
- options.blocked = options.blocked || false
- options.sorter ?= RocketChat.settings._sorter[options.group]++
-
- if options.enableQuery?
- options.enableQuery = JSON.stringify options.enableQuery
-
- if options.i18nDefaultQuery?
- options.i18nDefaultQuery = JSON.stringify options.i18nDefaultQuery
-
- if process?.env?[_id]?
- value = process.env[_id]
- if value.toLowerCase() is "true"
- value = true
- else if value.toLowerCase() is "false"
- value = false
- options.processEnvValue = value
- options.valueSource = 'processEnvValue'
-
- else if Meteor.settings?[_id]?
- value = Meteor.settings[_id]
- options.meteorSettingsValue = value
- options.valueSource = 'meteorSettingsValue'
-
- if not options.i18nLabel?
- options.i18nLabel = _id
-
- # Default description i18n key will be the setting name + "_Description" (eg: LDAP_Enable -> LDAP_Enable_Description)
- if not options.i18nDescription?
- options.i18nDescription = "#{_id}_Description"
-
- if blockedSettings[_id]?
- options.blocked = true
-
- if hiddenSettings[_id]?
- options.hidden = true
-
- if process?.env?['OVERWRITE_SETTING_' + _id]?
- value = process.env['OVERWRITE_SETTING_' + _id]
- if value.toLowerCase() is "true"
- value = true
- else if value.toLowerCase() is "false"
- value = false
- options.value = value
- options.processEnvValue = value
- options.valueSource = 'processEnvValue'
-
- updateOperations =
- $set: options
- $setOnInsert:
- createdAt: new Date
-
- if options.editor?
- updateOperations.$setOnInsert.editor = options.editor
- delete options.editor
-
- if not options.value?
- if options.force is true
- updateOperations.$set.value = options.packageValue
- else
- updateOperations.$setOnInsert.value = value
-
- query = _.extend { _id: _id }, updateOperations.$set
-
- if not options.section?
- updateOperations.$unset = { section: 1 }
- query.section = { $exists: false }
-
- existantSetting = RocketChat.models.Settings.db.findOne(query)
-
- if existantSetting?
- if not existantSetting.editor? and updateOperations.$setOnInsert.editor?
- updateOperations.$set.editor = updateOperations.$setOnInsert.editor
- delete updateOperations.$setOnInsert.editor
- else
- updateOperations.$set.ts = new Date
-
- return RocketChat.models.Settings.upsert { _id: _id }, updateOperations
-
-
-
-###
-# Add a setting group
-# @param {String} _id
-###
-RocketChat.settings.addGroup = (_id, options = {}, cb) ->
- # console.log '[functions] RocketChat.settings.addGroup -> '.green, 'arguments:', arguments
-
- if not _id
- return false
-
- if _.isFunction(options)
- cb = options
- options = {}
-
- if not options.i18nLabel?
- options.i18nLabel = _id
-
- if not options.i18nDescription?
- options.i18nDescription = "#{_id}_Description"
-
- options.ts = new Date
- options.blocked = false
- options.hidden = false
-
- if blockedSettings[_id]?
- options.blocked = true
-
- if hiddenSettings[_id]?
- options.hidden = true
-
- RocketChat.models.Settings.upsert { _id: _id },
- $set: options
- $setOnInsert:
- type: 'group'
- createdAt: new Date
-
- if cb?
- cb.call
- add: (id, value, options = {}) ->
- options.group = _id
- RocketChat.settings.add id, value, options
-
- section: (section, cb) ->
- cb.call
- add: (id, value, options = {}) ->
- options.group = _id
- options.section = section
- RocketChat.settings.add id, value, options
-
- return
-
-
-###
-# Remove a setting by id
-# @param {String} _id
-###
-RocketChat.settings.removeById = (_id) ->
- # console.log '[functions] RocketChat.settings.add -> '.green, 'arguments:', arguments
-
- if not _id
- return false
-
- return RocketChat.models.Settings.removeById _id
-
-
-###
-# Update a setting by id
-# @param {String} _id
-###
-RocketChat.settings.updateById = (_id, value, editor) ->
- # console.log '[functions] RocketChat.settings.updateById -> '.green, 'arguments:', arguments
-
- if not _id or not value?
- return false
-
- if editor?
- return RocketChat.models.Settings.updateValueAndEditorById _id, value, editor
-
- return RocketChat.models.Settings.updateValueById _id, value
-
-
-###
-# Update options of a setting by id
-# @param {String} _id
-###
-RocketChat.settings.updateOptionsById = (_id, options) ->
- # console.log '[functions] RocketChat.settings.updateOptionsById -> '.green, 'arguments:', arguments
-
- if not _id or not options?
- return false
-
- return RocketChat.models.Settings.updateOptionsById _id, options
-
-
-###
-# Update a setting by id
-# @param {String} _id
-###
-RocketChat.settings.clearById = (_id) ->
- # console.log '[functions] RocketChat.settings.clearById -> '.green, 'arguments:', arguments
-
- if not _id?
- return false
-
- return RocketChat.models.Settings.updateValueById _id, undefined
-
-
-###
-# Update a setting by id
-###
-RocketChat.settings.init = ->
- RocketChat.settings.initialLoad = true
- RocketChat.models.Settings.find().observe
- added: (record) ->
- Meteor.settings[record._id] = record.value
- if record.env is true
- process.env[record._id] = record.value
- RocketChat.settings.load record._id, record.value, RocketChat.settings.initialLoad
- changed: (record) ->
- Meteor.settings[record._id] = record.value
- if record.env is true
- process.env[record._id] = record.value
- RocketChat.settings.load record._id, record.value, RocketChat.settings.initialLoad
- removed: (record) ->
- delete Meteor.settings[record._id]
- if record.env is true
- delete process.env[record._id]
- RocketChat.settings.load record._id, undefined, RocketChat.settings.initialLoad
- RocketChat.settings.initialLoad = false
-
- for fn in RocketChat.settings.afterInitialLoad
- fn(Meteor.settings)
-
-
-RocketChat.settings.afterInitialLoad = []
-
-RocketChat.settings.onAfterInitialLoad = (fn) ->
- RocketChat.settings.afterInitialLoad.push(fn)
- if RocketChat.settings.initialLoad is false
- fn(Meteor.settings)
diff --git a/packages/rocketchat-lib/server/functions/settings.js b/packages/rocketchat-lib/server/functions/settings.js
new file mode 100644
index 0000000000000..cef8a2d960e64
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/settings.js
@@ -0,0 +1,289 @@
+import _ from 'underscore';
+
+const blockedSettings = {};
+
+if (process.env.SETTINGS_BLOCKED) {
+ process.env.SETTINGS_BLOCKED.split(',').forEach((settingId) => blockedSettings[settingId] = 1);
+}
+
+const hiddenSettings = {};
+if (process.env.SETTINGS_HIDDEN) {
+ process.env.SETTINGS_HIDDEN.split(',').forEach((settingId) => hiddenSettings[settingId] = 1);
+}
+
+RocketChat.settings._sorter = {};
+
+
+/*
+* Add a setting
+* @param {String} _id
+* @param {Mixed} value
+* @param {Object} setting
+*/
+
+RocketChat.settings.add = function(_id, value, options = {}) {
+ if (options == null) {
+ options = {};
+ }
+ if (!_id || value == null) {
+ return false;
+ }
+ if (RocketChat.settings._sorter[options.group] == null) {
+ RocketChat.settings._sorter[options.group] = 0;
+ }
+ options.packageValue = value;
+ options.valueSource = 'packageValue';
+ options.hidden = options.hidden || false;
+ options.blocked = options.blocked || false;
+ if (options.sorter == null) {
+ options.sorter = RocketChat.settings._sorter[options.group]++;
+ }
+ if (options.enableQuery != null) {
+ options.enableQuery = JSON.stringify(options.enableQuery);
+ }
+ if (options.i18nDefaultQuery != null) {
+ options.i18nDefaultQuery = JSON.stringify(options.i18nDefaultQuery);
+ }
+ if (typeof process !== 'undefined' && process.env && process.env[_id]) {
+ value = process.env[_id];
+ if (value.toLowerCase() === 'true') {
+ value = true;
+ } else if (value.toLowerCase() === 'false') {
+ value = false;
+ }
+ options.processEnvValue = value;
+ options.valueSource = 'processEnvValue';
+ } else if (Meteor.settings && typeof Meteor.settings[_id] !== 'undefined') {
+ if (Meteor.settings[_id] == null) {
+ return false;
+ }
+
+ value = Meteor.settings[_id];
+ options.meteorSettingsValue = value;
+ options.valueSource = 'meteorSettingsValue';
+ }
+ if (options.i18nLabel == null) {
+ options.i18nLabel = _id;
+ }
+ if (options.i18nDescription == null) {
+ options.i18nDescription = `${ _id }_Description`;
+ }
+ if (blockedSettings[_id] != null) {
+ options.blocked = true;
+ }
+ if (hiddenSettings[_id] != null) {
+ options.hidden = true;
+ }
+ if (typeof process !== 'undefined' && process.env && process.env[`OVERWRITE_SETTING_${ _id }`]) {
+ let value = process.env[`OVERWRITE_SETTING_${ _id }`];
+ if (value.toLowerCase() === 'true') {
+ value = true;
+ } else if (value.toLowerCase() === 'false') {
+ value = false;
+ }
+ options.value = value;
+ options.processEnvValue = value;
+ options.valueSource = 'processEnvValue';
+ }
+ const updateOperations = {
+ $set: options,
+ $setOnInsert: {
+ createdAt: new Date
+ }
+ };
+ if (options.editor != null) {
+ updateOperations.$setOnInsert.editor = options.editor;
+ delete options.editor;
+ }
+ if (options.value == null) {
+ if (options.force === true) {
+ updateOperations.$set.value = options.packageValue;
+ } else {
+ updateOperations.$setOnInsert.value = value;
+ }
+ }
+ const query = _.extend({
+ _id
+ }, updateOperations.$set);
+ if (options.section == null) {
+ updateOperations.$unset = {
+ section: 1
+ };
+ query.section = {
+ $exists: false
+ };
+ }
+ const existantSetting = RocketChat.models.Settings.db.findOne(query);
+ if (existantSetting != null) {
+ if (existantSetting.editor == null && updateOperations.$setOnInsert.editor != null) {
+ updateOperations.$set.editor = updateOperations.$setOnInsert.editor;
+ delete updateOperations.$setOnInsert.editor;
+ }
+ } else {
+ updateOperations.$set.ts = new Date;
+ }
+ return RocketChat.models.Settings.upsert({
+ _id
+ }, updateOperations);
+};
+
+
+/*
+* Add a setting group
+* @param {String} _id
+*/
+
+RocketChat.settings.addGroup = function(_id, options = {}, cb) {
+ if (!_id) {
+ return false;
+ }
+ if (_.isFunction(options)) {
+ cb = options;
+ options = {};
+ }
+ if (options.i18nLabel == null) {
+ options.i18nLabel = _id;
+ }
+ if (options.i18nDescription == null) {
+ options.i18nDescription = `${ _id }_Description`;
+ }
+ options.ts = new Date;
+ options.blocked = false;
+ options.hidden = false;
+ if (blockedSettings[_id] != null) {
+ options.blocked = true;
+ }
+ if (hiddenSettings[_id] != null) {
+ options.hidden = true;
+ }
+ RocketChat.models.Settings.upsert({
+ _id
+ }, {
+ $set: options,
+ $setOnInsert: {
+ type: 'group',
+ createdAt: new Date
+ }
+ });
+ if (cb != null) {
+ cb.call({
+ add(id, value, options) {
+ if (options == null) {
+ options = {};
+ }
+ options.group = _id;
+ return RocketChat.settings.add(id, value, options);
+ },
+ section(section, cb) {
+ return cb.call({
+ add(id, value, options) {
+ if (options == null) {
+ options = {};
+ }
+ options.group = _id;
+ options.section = section;
+ return RocketChat.settings.add(id, value, options);
+ }
+ });
+ }
+ });
+ }
+};
+
+
+/*
+* Remove a setting by id
+* @param {String} _id
+*/
+
+RocketChat.settings.removeById = function(_id) {
+ if (!_id) {
+ return false;
+ }
+ return RocketChat.models.Settings.removeById(_id);
+};
+
+
+/*
+* Update a setting by id
+* @param {String} _id
+*/
+
+RocketChat.settings.updateById = function(_id, value, editor) {
+ if (!_id || value == null) {
+ return false;
+ }
+ if (editor != null) {
+ return RocketChat.models.Settings.updateValueAndEditorById(_id, value, editor);
+ }
+ return RocketChat.models.Settings.updateValueById(_id, value);
+};
+
+
+/*
+* Update options of a setting by id
+* @param {String} _id
+*/
+
+RocketChat.settings.updateOptionsById = function(_id, options) {
+ if (!_id || options == null) {
+ return false;
+ }
+ return RocketChat.models.Settings.updateOptionsById(_id, options);
+};
+
+
+/*
+* Update a setting by id
+* @param {String} _id
+*/
+
+RocketChat.settings.clearById = function(_id) {
+ if (_id == null) {
+ return false;
+ }
+ return RocketChat.models.Settings.updateValueById(_id, undefined);
+};
+
+
+/*
+* Update a setting by id
+*/
+
+RocketChat.settings.init = function() {
+ RocketChat.settings.initialLoad = true;
+ RocketChat.models.Settings.find().observe({
+ added(record) {
+ Meteor.settings[record._id] = record.value;
+ if (record.env === true) {
+ process.env[record._id] = record.value;
+ }
+ return RocketChat.settings.load(record._id, record.value, RocketChat.settings.initialLoad);
+ },
+ changed(record) {
+ Meteor.settings[record._id] = record.value;
+ if (record.env === true) {
+ process.env[record._id] = record.value;
+ }
+ return RocketChat.settings.load(record._id, record.value, RocketChat.settings.initialLoad);
+ },
+ removed(record) {
+ delete Meteor.settings[record._id];
+ if (record.env === true) {
+ delete process.env[record._id];
+ }
+ return RocketChat.settings.load(record._id, undefined, RocketChat.settings.initialLoad);
+ }
+ });
+ RocketChat.settings.initialLoad = false;
+ RocketChat.settings.afterInitialLoad.forEach(fn => fn(Meteor.settings));
+};
+
+RocketChat.settings.afterInitialLoad = [];
+
+RocketChat.settings.onAfterInitialLoad = function(fn) {
+ RocketChat.settings.afterInitialLoad.push(fn);
+ if (RocketChat.settings.initialLoad === false) {
+ return fn(Meteor.settings);
+ }
+};
diff --git a/packages/rocketchat-lib/server/functions/updateMessage.js b/packages/rocketchat-lib/server/functions/updateMessage.js
index 38141a03d61cb..0c8d988df5586 100644
--- a/packages/rocketchat-lib/server/functions/updateMessage.js
+++ b/packages/rocketchat-lib/server/functions/updateMessage.js
@@ -10,21 +10,21 @@ RocketChat.updateMessage = function(message, user) {
username: user.username
};
- let urls = message.msg.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g);
+ const urls = message.msg.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g);
if (urls) {
- message.urls = urls.map((url) => { return { url: url }; });
+ message.urls = urls.map((url) => { return { url }; });
}
message = RocketChat.callbacks.run('beforeSaveMessage', message);
- let tempid = message._id;
+ const tempid = message._id;
delete message._id;
RocketChat.models.Messages.update({ _id: tempid }, { $set: message });
- let room = RocketChat.models.Rooms.findOneById(message.rid);
+ const room = RocketChat.models.Rooms.findOneById(message.rid);
Meteor.defer(function() {
- RocketChat.callbacks.run('afterSaveMessage', RocketChat.models.Messages.findOneById(tempid), room);
+ RocketChat.callbacks.run('afterSaveMessage', RocketChat.models.Messages.findOneById(tempid), room, user._id);
});
};
diff --git a/packages/rocketchat-lib/server/functions/validateCustomFields.js b/packages/rocketchat-lib/server/functions/validateCustomFields.js
new file mode 100644
index 0000000000000..2994ad9ed0b60
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/validateCustomFields.js
@@ -0,0 +1,41 @@
+import s from 'underscore.string';
+
+RocketChat.validateCustomFields = function(fields) {
+ // Special Case:
+ // If an admin didn't set any custom fields there's nothing to validate against so consider any customFields valid
+ if (s.trim(RocketChat.settings.get('Accounts_CustomFields')) === '') {
+ return;
+ }
+
+ let customFieldsMeta;
+ try {
+ customFieldsMeta = JSON.parse(RocketChat.settings.get('Accounts_CustomFields'));
+ } catch (e) {
+ throw new Meteor.Error('error-invalid-customfield-json', 'Invalid JSON for Custom Fields');
+ }
+
+ const customFields = {};
+
+ Object.keys(customFieldsMeta).forEach((fieldName) => {
+ const field = customFieldsMeta[fieldName];
+
+ customFields[fieldName] = fields[fieldName];
+ const fieldValue = s.trim(fields[fieldName]);
+
+ if (field.required && fieldValue === '') {
+ throw new Meteor.Error('error-user-registration-custom-field', `Field ${ fieldName } is required`, {method: 'registerUser'});
+ }
+
+ if (field.type === 'select' && field.options.indexOf(fields[fieldName]) === -1) {
+ throw new Meteor.Error('error-user-registration-custom-field', `Value for field ${ fieldName } is invalid`, {method: 'registerUser'});
+ }
+
+ if (field.maxLength && fieldValue.length > field.maxLength) {
+ throw new Meteor.Error('error-user-registration-custom-field', `Max length of field ${ fieldName } ${ field.maxLength }`, {method: 'registerUser'});
+ }
+
+ if (field.minLength && fieldValue.length < field.minLength) {
+ throw new Meteor.Error('error-user-registration-custom-field', `Min length of field ${ fieldName } ${ field.minLength }`, {method: 'registerUser'});
+ }
+ });
+};
diff --git a/packages/rocketchat-lib/server/lib/PushNotification.js b/packages/rocketchat-lib/server/lib/PushNotification.js
index ec754b4d05869..15e50c780fe04 100644
--- a/packages/rocketchat-lib/server/lib/PushNotification.js
+++ b/packages/rocketchat-lib/server/lib/PushNotification.js
@@ -1,13 +1,13 @@
/* globals Push */
class PushNotification {
getNotificationId(roomId) {
- let serverId = RocketChat.settings.get('uniqueID');
- return this.hash(`${serverId}|${roomId}`); // hash
+ const serverId = RocketChat.settings.get('uniqueID');
+ return this.hash(`${ serverId }|${ roomId }`); // hash
}
hash(str) {
- let hash = 0,
- i = str.length;
+ let hash = 0;
+ let i = str.length;
while (i) {
hash = ((hash << 5) - hash) + str.charCodeAt(--i);
@@ -16,20 +16,20 @@ class PushNotification {
return hash;
}
- send({ roomName, roomId, username, message, usersTo, payload }) {
+ send({ roomName, roomId, username, message, usersTo, payload, badge = 1, category }) {
let title;
if (roomName && roomName !== '') {
- title = `${roomName}`;
- message = `${username}: ${message}`;
+ title = `${ roomName }`;
+ message = `${ username }: ${ message }`;
} else {
- title = `${username}`;
+ title = `${ username }`;
}
- let icon = RocketChat.settings.get('Assets_favicon_192').url || RocketChat.settings.get('Assets_favicon_192').defaultUrl;
+ const icon = RocketChat.settings.get('Assets_favicon_192').url || RocketChat.settings.get('Assets_favicon_192').defaultUrl;
const config = {
from: 'push',
- badge: 1,
+ badge,
sound: 'default',
- title: title,
+ title,
text: message,
payload,
query: usersTo,
@@ -38,12 +38,15 @@ class PushNotification {
style: 'inbox',
summaryText: '%n% new messages',
image: RocketChat.getURL(icon, { full: true })
- },
- apn: {
- text: title + ((title !== '' && message !== '') ? '\n' : '') + message
}
};
+ if (category !== '') {
+ config.apn = {
+ category
+ };
+ }
+
return Push.send(config);
}
}
diff --git a/packages/rocketchat-lib/server/lib/RateLimiter.coffee b/packages/rocketchat-lib/server/lib/RateLimiter.coffee
deleted file mode 100644
index b4637012210e8..0000000000000
--- a/packages/rocketchat-lib/server/lib/RateLimiter.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-RocketChat.RateLimiter = new class
- limitFunction: (fn, numRequests, timeInterval, matchers) ->
- rateLimiter = new RateLimiter()
- rateLimiter.addRule matchers, numRequests, timeInterval
- return ->
- match = {}
- args = arguments
- _.each matchers, (matcher, key) ->
- match[key] = args[key]
-
- rateLimiter.increment match
- rateLimitResult = rateLimiter.check match
- if rateLimitResult.allowed
- return fn.apply null, arguments
- else
- throw new Meteor.Error 'error-too-many-requests', "Error, too many requests. Please slow down. You must wait #{Math.ceil(rateLimitResult.timeToReset / 1000)} seconds before trying again.", { timeToReset: rateLimitResult.timeToReset, seconds: Math.ceil(rateLimitResult.timeToReset / 1000) }
-
- limitMethod: (methodName, numRequests, timeInterval, matchers) ->
- match =
- type: 'method'
- name: methodName
-
- _.each matchers, (matcher, key) ->
- match[key] = matchers[key]
-
- DDPRateLimiter.addRule match, numRequests, timeInterval
diff --git a/packages/rocketchat-lib/server/lib/RateLimiter.js b/packages/rocketchat-lib/server/lib/RateLimiter.js
new file mode 100644
index 0000000000000..c812ad3d67f3d
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/RateLimiter.js
@@ -0,0 +1,43 @@
+/* globals RateLimiter */
+import _ from 'underscore';
+
+RocketChat.RateLimiter = new class {
+ limitFunction(fn, numRequests, timeInterval, matchers) {
+ if (process.env.TEST_MODE === 'true') {
+ return fn;
+ }
+ const rateLimiter = new RateLimiter();
+ rateLimiter.addRule(matchers, numRequests, timeInterval);
+ return function(...args) {
+ const match = {};
+ _.each(matchers, function(matcher, key) {
+ return match[key] = args[key];
+ });
+ rateLimiter.increment(match);
+ const rateLimitResult = rateLimiter.check(match);
+ if (rateLimitResult.allowed) {
+ return fn.apply(null, arguments);
+ } else {
+ throw new Meteor.Error('error-too-many-requests', `Error, too many requests. Please slow down. You must wait ${ Math.ceil(rateLimitResult.timeToReset / 1000) } seconds before trying again.`, {
+ timeToReset: rateLimitResult.timeToReset,
+ seconds: Math.ceil(rateLimitResult.timeToReset / 1000)
+ });
+ }
+ };
+ }
+
+ limitMethod(methodName, numRequests, timeInterval, matchers) {
+ if (process.env.TEST_MODE === 'true') {
+ return;
+ }
+ const match = {
+ type: 'method',
+ name: methodName
+ };
+ _.each(matchers, function(matcher, key) {
+ return match[key] = matchers[key];
+ });
+ return DDPRateLimiter.addRule(match, numRequests, timeInterval);
+ }
+
+};
diff --git a/packages/rocketchat-lib/server/lib/bugsnag.js b/packages/rocketchat-lib/server/lib/bugsnag.js
index cfe1fa9853be5..43c1e46d9feee 100644
--- a/packages/rocketchat-lib/server/lib/bugsnag.js
+++ b/packages/rocketchat-lib/server/lib/bugsnag.js
@@ -10,7 +10,7 @@ RocketChat.settings.get('Bugsnag_api_key', (key, value) => {
const notify = function(message, stack) {
if (typeof stack === 'string') {
- message += ' ' + stack;
+ message += ` ${ stack }`;
}
let options = {};
if (RocketChat.Info) {
@@ -26,7 +26,7 @@ process.on('uncaughtException', Meteor.bindEnvironment((error) => {
throw error;
}));
-let originalMeteorDebug = Meteor._debug;
+const originalMeteorDebug = Meteor._debug;
Meteor._debug = function() {
notify(...arguments);
return originalMeteorDebug(...arguments);
diff --git a/packages/rocketchat-lib/server/lib/configLogger.js b/packages/rocketchat-lib/server/lib/configLogger.js
new file mode 100644
index 0000000000000..657f535e6f798
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/configLogger.js
@@ -0,0 +1,17 @@
+/* globals LoggerManager */
+RocketChat.settings.get('Log_Package', function(key, value) {
+ return LoggerManager.showPackage = value;
+});
+
+RocketChat.settings.get('Log_File', function(key, value) {
+ return LoggerManager.showFileAndLine = value;
+});
+
+RocketChat.settings.get('Log_Level', function(key, value) {
+ if (value != null) {
+ LoggerManager.logLevel = parseInt(value);
+ Meteor.setTimeout(() => {
+ return LoggerManager.enable(true);
+ }, 200);
+ }
+});
diff --git a/packages/rocketchat-lib/server/lib/debug.js b/packages/rocketchat-lib/server/lib/debug.js
index 0880acf36eeb2..1a000e44b17a2 100644
--- a/packages/rocketchat-lib/server/lib/debug.js
+++ b/packages/rocketchat-lib/server/lib/debug.js
@@ -1,4 +1,7 @@
-var logger = new Logger('Meteor', {
+/* global InstanceStatus */
+import _ from 'underscore';
+
+const logger = new Logger('Meteor', {
methods: {
method: {
type: 'debug'
@@ -9,16 +12,16 @@ var logger = new Logger('Meteor', {
}
});
-var wrapMethods = function(name, originalHandler, methodsMap) {
+const wrapMethods = function(name, originalHandler, methodsMap) {
methodsMap[name] = function() {
- var args = name === 'ufsWrite' ? Array.prototype.slice.call(arguments, 1) : arguments;
+ const args = name === 'ufsWrite' ? Array.prototype.slice.call(arguments, 1) : arguments;
logger.method(name, '-> userId:', Meteor.userId(), ', arguments: ', args);
return originalHandler.apply(this, arguments);
};
};
-var originalMeteorMethods = Meteor.methods;
+const originalMeteorMethods = Meteor.methods;
Meteor.methods = function(methodMap) {
_.each(methodMap, function(handler, name) {
@@ -27,7 +30,7 @@ Meteor.methods = function(methodMap) {
originalMeteorMethods(methodMap);
};
-var originalMeteorPublish = Meteor.publish;
+const originalMeteorPublish = Meteor.publish;
Meteor.publish = function(name, func) {
return originalMeteorPublish(name, function() {
@@ -36,3 +39,8 @@ Meteor.publish = function(name, func) {
return func.apply(this, arguments);
});
};
+
+WebApp.rawConnectHandlers.use(function(req, res, next) {
+ res.setHeader('X-Instance-ID', InstanceStatus.id());
+ return next();
+});
diff --git a/packages/rocketchat-lib/server/lib/index.js b/packages/rocketchat-lib/server/lib/index.js
new file mode 100644
index 0000000000000..0a29fe0b32d27
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/index.js
@@ -0,0 +1,15 @@
+/*
+ What is this file? Great question! To make Rocket.Chat more "modular"
+ and to make the "rocketchat:lib" package more of a core package
+ with the libraries, this index file contains the exported members
+ for the *server* pieces of code which does include the shared
+ library files.
+*/
+
+import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig } from '../../lib/RoomTypeConfig';
+
+export {
+ RoomSettingsEnum,
+ RoomTypeConfig,
+ RoomTypeRouteConfig
+};
diff --git a/packages/rocketchat-lib/server/lib/interceptDirectReplyEmails.js b/packages/rocketchat-lib/server/lib/interceptDirectReplyEmails.js
new file mode 100644
index 0000000000000..c7cde0bd5239b
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/interceptDirectReplyEmails.js
@@ -0,0 +1,264 @@
+import IMAP from 'imap';
+import POP3 from 'poplib';
+import { simpleParser } from 'mailparser';
+
+export class IMAPIntercepter {
+ constructor() {
+ this.imap = new IMAP({
+ user: RocketChat.settings.get('Direct_Reply_Username'),
+ password: RocketChat.settings.get('Direct_Reply_Password'),
+ host: RocketChat.settings.get('Direct_Reply_Host'),
+ port: RocketChat.settings.get('Direct_Reply_Port'),
+ debug: RocketChat.settings.get('Direct_Reply_Debug') ? console.log : false,
+ tls: !RocketChat.settings.get('Direct_Reply_IgnoreTLS'),
+ connTimeout: 30000,
+ keepalive: true
+ });
+
+ this.delete = RocketChat.settings.get('Direct_Reply_Delete') ? RocketChat.settings.get('Direct_Reply_Delete') : true;
+
+ // On successfully connected.
+ this.imap.on('ready', Meteor.bindEnvironment(() => {
+ if (this.imap.state !== 'disconnected') {
+ this.openInbox(Meteor.bindEnvironment((err) => {
+ if (err) {
+ throw err;
+ }
+ // fetch new emails & wait [IDLE]
+ this.getEmails();
+
+ // If new message arrived, fetch them
+ this.imap.on('mail', Meteor.bindEnvironment(() => {
+ this.getEmails();
+ }));
+ }));
+ } else {
+ console.log('IMAP didnot connected.');
+ this.imap.end();
+ }
+ }));
+
+ this.imap.on('error', (err) => {
+ console.log('Error occurred ...');
+ throw err;
+ });
+ }
+
+ openInbox(cb) {
+ this.imap.openBox('INBOX', false, cb);
+ }
+
+ start() {
+ this.imap.connect();
+ }
+
+ isActive() {
+ if (this.imap && this.imap.state && this.imap.state === 'disconnected') {
+ return false;
+ }
+
+ return true;
+ }
+
+ stop(callback = new Function) {
+ this.imap.end();
+ this.imap.once('end', callback);
+ }
+
+ restart() {
+ this.stop(() => {
+ console.log('Restarting IMAP ....');
+ this.start();
+ });
+ }
+
+ // Fetch all UNSEEN messages and pass them for further processing
+ getEmails() {
+ this.imap.search(['UNSEEN'], Meteor.bindEnvironment((err, newEmails) => {
+ if (err) {
+ console.log(err);
+ throw err;
+ }
+
+ // newEmails => array containing serials of unseen messages
+ if (newEmails.length > 0) {
+ const f = this.imap.fetch(newEmails, {
+ // fetch headers & first body part.
+ bodies: ['HEADER.FIELDS (FROM TO DATE MESSAGE-ID)', '1'],
+ struct: true,
+ markSeen: true
+ });
+
+ f.on('message', Meteor.bindEnvironment((msg, seqno) => {
+ const email = {};
+
+ msg.on('body', (stream, info) => {
+ let headerBuffer = '';
+ let bodyBuffer = '';
+
+ stream.on('data', (chunk) => {
+ if (info.which === '1') {
+ bodyBuffer += chunk.toString('utf8');
+ } else {
+ headerBuffer += chunk.toString('utf8');
+ }
+ });
+
+ stream.once('end', () => {
+ if (info.which === '1') {
+ email.body = bodyBuffer;
+ } else {
+ // parse headers
+ email.headers = IMAP.parseHeader(headerBuffer);
+
+ email.headers.to = email.headers.to[0];
+ email.headers.date = email.headers.date[0];
+ email.headers.from = email.headers.from[0];
+ }
+ });
+ });
+
+ // On fetched each message, pass it further
+ msg.once('end', Meteor.bindEnvironment(() => {
+ // delete message from inbox
+ if (this.delete) {
+ this.imap.seq.addFlags(seqno, 'Deleted', (err) => {
+ if (err) { console.log(`Mark deleted error: ${ err }`); }
+ });
+ }
+ RocketChat.processDirectEmail(email);
+ }));
+ }));
+ f.once('error', (err) => {
+ console.log(`Fetch error: ${ err }`);
+ });
+ }
+ }));
+ }
+}
+
+export class POP3Intercepter {
+ constructor() {
+ this.pop3 = new POP3(RocketChat.settings.get('Direct_Reply_Port'), RocketChat.settings.get('Direct_Reply_Host'), {
+ enabletls: !RocketChat.settings.get('Direct_Reply_IgnoreTLS'),
+ debug: RocketChat.settings.get('Direct_Reply_Debug') ? console.log : false
+ });
+
+ this.totalMsgCount = 0;
+ this.currentMsgCount = 0;
+
+ this.pop3.on('connect', Meteor.bindEnvironment(() => {
+ this.pop3.login(RocketChat.settings.get('Direct_Reply_Username'), RocketChat.settings.get('Direct_Reply_Password'));
+ }));
+
+ this.pop3.on('login', Meteor.bindEnvironment((status) => {
+ if (status) {
+ // run on start
+ this.pop3.list();
+ } else {
+ console.log('Unable to Log-in ....');
+ }
+ }));
+
+ // on getting list of all emails
+ this.pop3.on('list', Meteor.bindEnvironment((status, msgcount) => {
+ if (status) {
+ if (msgcount > 0) {
+ this.totalMsgCount = msgcount;
+ this.currentMsgCount = 1;
+ // Retrieve email
+ this.pop3.retr(this.currentMsgCount);
+ } else {
+ this.pop3.quit();
+ }
+ } else {
+ console.log('Cannot Get Emails ....');
+ }
+ }));
+
+ // on retrieved email
+ this.pop3.on('retr', Meteor.bindEnvironment((status, msgnumber, data) => {
+ if (status) {
+ // parse raw email data to JSON object
+ simpleParser(data, Meteor.bindEnvironment((err, mail) => {
+ this.initialProcess(mail);
+ }));
+
+ this.currentMsgCount += 1;
+
+ // delete email
+ this.pop3.dele(msgnumber);
+ } else {
+ console.log('Cannot Retrieve Message ....');
+ }
+ }));
+
+ // on email deleted
+ this.pop3.on('dele', Meteor.bindEnvironment((status) => {
+ if (status) {
+ // get next email
+ if (this.currentMsgCount <= this.totalMsgCount) {
+ this.pop3.retr(this.currentMsgCount);
+ } else {
+ // parsed all messages.. so quitting
+ this.pop3.quit();
+ }
+ } else {
+ console.log('Cannot Delete Message....');
+ }
+ }));
+
+ // invalid server state
+ this.pop3.on('invalid-state', function(cmd) {
+ console.log(`Invalid state. You tried calling ${ cmd }`);
+ });
+
+ // locked => command already running, not finished yet
+ this.pop3.on('locked', function(cmd) {
+ console.log(`Current command has not finished yet. You tried calling ${ cmd }`);
+ });
+ }
+
+ initialProcess(mail) {
+ const email = {
+ headers: {
+ from: mail.from.text,
+ to: mail.to.text,
+ date: mail.date,
+ 'message-id': mail.messageId
+ },
+ body: mail.text
+ };
+
+ RocketChat.processDirectEmail(email);
+ }
+}
+
+export class POP3Helper {
+ constructor() {
+ this.running = false;
+ }
+
+ start() {
+ // run every x-minutes
+ if (RocketChat.settings.get('Direct_Reply_Frequency')) {
+ RocketChat.POP3 = new POP3Intercepter();
+
+ this.running = Meteor.setInterval(() => {
+ // get new emails and process
+ RocketChat.POP3 = new POP3Intercepter();
+ }, Math.max(RocketChat.settings.get('Direct_Reply_Frequency')*60*1000, 2*60*1000));
+ }
+ }
+
+ isActive() {
+ return this.running;
+ }
+
+ stop(callback = new Function) {
+ if (this.isActive()) {
+ Meteor.clearInterval(this.running);
+ }
+ callback();
+ }
+}
diff --git a/packages/rocketchat-lib/server/lib/loginErrorMessageOverride.js b/packages/rocketchat-lib/server/lib/loginErrorMessageOverride.js
new file mode 100644
index 0000000000000..bdd3255b2ff4e
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/loginErrorMessageOverride.js
@@ -0,0 +1,11 @@
+// Do not disclose if user exists when password is invalid
+const _runLoginHandlers = Accounts._runLoginHandlers;
+Accounts._runLoginHandlers = function(methodInvocation, options) {
+ const result = _runLoginHandlers.call(Accounts, methodInvocation, options);
+
+ if (result.error && result.error.reason === 'Incorrect password') {
+ result.error = new Meteor.Error(403, 'User not found');
+ }
+
+ return result;
+};
diff --git a/packages/rocketchat-lib/server/lib/metrics.js b/packages/rocketchat-lib/server/lib/metrics.js
index 0ae0ed29eafc8..43cf6590f7b26 100644
--- a/packages/rocketchat-lib/server/lib/metrics.js
+++ b/packages/rocketchat-lib/server/lib/metrics.js
@@ -1,4 +1,4 @@
-var client = require('prom-client');
+import client from 'prom-client';
RocketChat.promclient = client;
@@ -6,4 +6,4 @@ RocketChat.metrics = {};
// one sample metrics only - a counter
-RocketChat.metrics.messagesSent = new client.Counter('messages_sent', 'cumulated number of messages sent');
+RocketChat.metrics.messagesSent = new client.Counter({'name': 'message_sent', 'help': 'cumulated number of messages sent'});
diff --git a/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js b/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js
index bd61e4a197d71..f673c56ec1034 100644
--- a/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js
@@ -1,12 +1,24 @@
+import _ from 'underscore';
+import s from 'underscore.string';
import moment from 'moment';
RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
- // skips this callback if the message was edited
- if (message.editedAt) {
+ // skips this callback if the message was edited and increments it if the edit was way in the past (aka imported)
+ if (message.editedAt && Math.abs(moment(message.editedAt).diff()) > 60000) {
+ //TODO: Review as I am not sure how else to get around this as the incrementing of the msgs count shouldn't be in this callback
+ RocketChat.models.Rooms.incMsgCountById(message.rid, 1);
+ return message;
+ } else if (message.editedAt) {
+
+ // only updates last message if it was edited (skip rest of callback)
+ if (RocketChat.settings.get('Store_Last_Message') && (!room.lastMessage || room.lastMessage._id === message._id)) {
+ RocketChat.models.Rooms.setLastMessageById(message.rid, message);
+ }
return message;
}
if (message.ts && Math.abs(moment(message.ts).diff()) > 60000) {
+ RocketChat.models.Rooms.incMsgCountById(message.rid, 1);
return message;
}
@@ -21,9 +33,9 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
function messageContainsHighlight(message, highlights) {
if (! highlights || highlights.length === 0) { return false; }
- var has = false;
+ let has = false;
highlights.some(function(highlight) {
- var regexp = new RegExp(s.escapeRegExp(highlight), 'i');
+ const regexp = new RegExp(s.escapeRegExp(highlight), 'i');
if (regexp.test(message.msg)) {
has = true;
return true;
@@ -33,22 +45,21 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
return has;
}
- if (room.t != null && room.t === 'd') {
- // Update the other subscriptions
- RocketChat.models.Subscriptions.incUnreadOfDirectForRoomIdExcludingUserId(message.rid, message.u._id, 1);
- } else {
- var mentionIds, toAll, highlightsIds, highlights;
-
- mentionIds = [];
- highlightsIds = [];
- toAll = false;
- highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch();
+ if (room != null) {
+ let toAll = false;
+ let toHere = false;
+ const mentionIds = [];
+ const highlightsIds = [];
+ const highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch();
if (message.mentions != null) {
message.mentions.forEach(function(mention) {
if (!toAll && mention._id === 'all') {
toAll = true;
}
+ if (!toHere && mention._id === 'here') {
+ toHere = true;
+ }
if (mention._id !== message.u._id) {
mentionIds.push(mention._id);
}
@@ -56,22 +67,47 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
}
highlights.forEach(function(user) {
- if (user && user.settings && user.settings.preferences && messageContainsHighlight(message, user.settings.preferences.highlights)) {
+ const userHighlights = RocketChat.getUserPreference(user, 'highlights');
+ if (userHighlights && messageContainsHighlight(message, userHighlights)) {
if (user._id !== message.u._id) {
highlightsIds.push(user._id);
}
}
});
- if (toAll) {
- RocketChat.models.Subscriptions.incUnreadForRoomIdExcludingUserId(room._id, message.u._id);
- } else if ((mentionIds && mentionIds.length > 0) || (highlightsIds && highlightsIds.length > 0)) {
- RocketChat.models.Subscriptions.incUnreadForRoomIdAndUserIds(room._id, _.compact(_.unique(mentionIds.concat(highlightsIds))));
+ if (room.t === 'd') {
+ const unreadCountDM = RocketChat.settings.get('Unread_Count_DM');
+
+ if (unreadCountDM === 'all_messages') {
+ RocketChat.models.Subscriptions.incUnreadForRoomIdExcludingUserId(room._id, message.u._id);
+ } else if (toAll || toHere) {
+ RocketChat.models.Subscriptions.incGroupMentionsAndUnreadForRoomIdExcludingUserId(room._id, message.u._id, 1, 1);
+ } else if ((mentionIds && mentionIds.length > 0) || (highlightsIds && highlightsIds.length > 0)) {
+ RocketChat.models.Subscriptions.incUserMentionsAndUnreadForRoomIdAndUserIds(room._id, _.compact(_.unique(mentionIds.concat(highlightsIds))), 1, 1);
+ }
+ } else {
+ const unreadCount = RocketChat.settings.get('Unread_Count');
+
+ if (toAll || toHere) {
+ let incUnread = 0;
+ if (['all_messages', 'group_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount)) {
+ incUnread = 1;
+ }
+ RocketChat.models.Subscriptions.incGroupMentionsAndUnreadForRoomIdExcludingUserId(room._id, message.u._id, 1, incUnread);
+ } else if ((mentionIds && mentionIds.length > 0) || (highlightsIds && highlightsIds.length > 0)) {
+ let incUnread = 0;
+ if (['all_messages', 'user_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount)) {
+ incUnread = 1;
+ }
+ RocketChat.models.Subscriptions.incUserMentionsAndUnreadForRoomIdAndUserIds(room._id, _.compact(_.unique(mentionIds.concat(highlightsIds))), 1, incUnread);
+ } else if (unreadCount === 'all_messages') {
+ RocketChat.models.Subscriptions.incUnreadForRoomIdExcludingUserId(room._id, message.u._id);
+ }
}
}
// Update all the room activity tracker fields
- RocketChat.models.Rooms.incMsgCountAndSetLastMessageTimestampById(message.rid, 1, message.ts);
+ RocketChat.models.Rooms.incMsgCountAndSetLastMessageById(message.rid, 1, message.ts, RocketChat.settings.get('Store_Last_Message') && message);
// Update all other subscriptions to alert their owners but witout incrementing
// the unread counter, as it is only for mentions and direct messages
diff --git a/packages/rocketchat-lib/server/lib/processDirectEmail.js b/packages/rocketchat-lib/server/lib/processDirectEmail.js
new file mode 100644
index 0000000000000..0dfbcb128af81
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/processDirectEmail.js
@@ -0,0 +1,118 @@
+import {EmailReplyParser as reply} from 'emailreplyparser';
+import moment from 'moment';
+
+RocketChat.processDirectEmail = function(email) {
+ function sendMessage(email) {
+ const message = {
+ ts: new Date(email.headers.date),
+ msg: email.body,
+ sentByEmail: true,
+ groupable: false
+ };
+
+ if (message.ts) {
+ const tsDiff = Math.abs(moment(message.ts).diff());
+ if (tsDiff > 10000) {
+ message.ts = new Date();
+ }
+ } else {
+ message.ts = new Date();
+ }
+
+ if (message.msg && message.msg.length > RocketChat.settings.get('Message_MaxAllowedSize')) {
+ return false;
+ }
+
+ // reduce new lines in multiline message
+ message.msg = message.msg.split('\n\n').join('\n');
+
+ const user = RocketChat.models.Users.findOneByEmailAddress(email.headers.from, {
+ fields: {
+ username: 1,
+ name: 1
+ }
+ });
+ if (!user) {
+ // user not found
+ return false;
+ }
+
+ const prevMessage = RocketChat.models.Messages.findOneById(email.headers.mid, {
+ rid: 1,
+ u: 1
+ });
+ if (!prevMessage) {
+ // message doesn't exist anymore
+ return false;
+ }
+ message.rid = prevMessage.rid;
+
+ const room = Meteor.call('canAccessRoom', message.rid, user._id);
+ if (!room) {
+ return false;
+ }
+
+ const roomInfo = RocketChat.models.Rooms.findOneById(message.rid, {
+ t: 1,
+ name: 1
+ });
+
+ // check mention
+ if (message.msg.indexOf(`@${ prevMessage.u.username }`) === -1 && roomInfo.t !== 'd') {
+ message.msg = `@${ prevMessage.u.username } ${ message.msg }`;
+ }
+
+ // reply message link
+ let prevMessageLink = `[ ](${ Meteor.absoluteUrl().replace(/\/$/, '') }`;
+ if (roomInfo.t === 'c') {
+ prevMessageLink += `/channel/${ roomInfo.name }?msg=${ email.headers.mid }) `;
+ } else if (roomInfo.t === 'd') {
+ prevMessageLink += `/direct/${ prevMessage.u.username }?msg=${ email.headers.mid }) `;
+ } else if (roomInfo.t === 'p') {
+ prevMessageLink += `/group/${ roomInfo.name }?msg=${ email.headers.mid }) `;
+ }
+ // add reply message link
+ message.msg = prevMessageLink + message.msg;
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, user._id);
+ if (subscription && subscription.blocked || subscription.blocker) {
+ // room is blocked
+ return false;
+ }
+
+ if ((room.muted || []).includes(user.username)) {
+ // room is muted
+ return false;
+ }
+
+ if (message.alias == null && RocketChat.settings.get('Message_SetNameToAliasEnabled')) {
+ message.alias = user.name;
+ }
+
+ RocketChat.metrics.messagesSent.inc(); // TODO This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736
+
+ return RocketChat.sendMessage(user, message, room);
+ }
+
+ // Extract/parse reply from email body
+ email.body = reply.parse_reply(email.body);
+
+ // if 'To' email format is "Name
"
+ if (email.headers.to.indexOf('<') >= 0 && email.headers.to.indexOf('>') >= 0) {
+ email.headers.to = email.headers.to.split('<')[1].split('>')[0];
+ }
+
+ // if 'From' email format is "Name "
+ if (email.headers.from.indexOf('<') >= 0 && email.headers.from.indexOf('>') >= 0) {
+ email.headers.from = email.headers.from.split('<')[1].split('>')[0];
+ }
+
+ // 'To' email format "username+messageId@domain"
+ if (email.headers.to.indexOf('+') >= 0) {
+ // Valid 'To' format
+ email.headers.mid = email.headers.to.split('@')[0].split('+')[1];
+ sendMessage(email);
+ } else {
+ console.log('Invalid Email....If not. Please report it.');
+ }
+};
diff --git a/packages/rocketchat-lib/server/lib/roomTypes.coffee b/packages/rocketchat-lib/server/lib/roomTypes.coffee
deleted file mode 100644
index db0a3d2f17a38..0000000000000
--- a/packages/rocketchat-lib/server/lib/roomTypes.coffee
+++ /dev/null
@@ -1,35 +0,0 @@
-RocketChat.roomTypes = new class roomTypesServer extends roomTypesCommon
- ### add a publish for a room type
- @param roomType: room type (e.g.: c (for channels), d (for direct channels))
- @param callback: function that will return the publish's data
- ###
- setPublish: (roomType, callback) ->
- if @roomTypes[roomType]?.publish?
- throw new Meteor.Error 'route-publish-exists', 'Publish for the given type already exists'
-
- unless @roomTypes[roomType]?
- @roomTypes[roomType] = {}
-
- @roomTypes[roomType].publish = callback
-
- setRoomFind: (roomType, callback) ->
- if @roomTypes[roomType]?.roomFind?
- throw new Meteor.Error 'room-find-exists', 'Room find for the given type already exists'
-
- unless @roomTypes[roomType]?
- @roomTypes[roomType] = {}
-
- @roomTypes[roomType].roomFind = callback
-
- getRoomFind: (roomType) ->
- return unless @roomTypes[roomType]?.roomFind?
- return @roomTypes[roomType].roomFind
-
- ### run the publish for a room type
- @param scope: Meteor publish scope
- @param roomType: room type (e.g.: c (for channels), d (for direct channels))
- @param identifier: identifier of the room
- ###
- runPublish: (scope, roomType, identifier) ->
- return unless @roomTypes[roomType]?.publish?
- return @roomTypes[roomType].publish.call scope, identifier
diff --git a/packages/rocketchat-lib/server/lib/roomTypes.js b/packages/rocketchat-lib/server/lib/roomTypes.js
new file mode 100644
index 0000000000000..68aec9b5ef6fa
--- /dev/null
+++ b/packages/rocketchat-lib/server/lib/roomTypes.js
@@ -0,0 +1,46 @@
+import { RoomTypesCommon } from '../../lib/RoomTypesCommon';
+
+RocketChat.roomTypes = new class roomTypesServer extends RoomTypesCommon {
+ /**
+ * Add a publish for a room type
+ *
+ * @param {string} roomType room type (e.g.: c (for channels), d (for direct channels))
+ * @param {function} callback function that will return the publish's data
+ */
+ setPublish(roomType, callback) {
+ if (this.roomTypes[roomType] && this.roomTypes[roomType].publish != null) {
+ throw new Meteor.Error('route-publish-exists', 'Publish for the given type already exists');
+ }
+ if (this.roomTypes[roomType] == null) {
+ this.roomTypes[roomType] = {};
+ }
+ return this.roomTypes[roomType].publish = callback;
+ }
+
+ setRoomFind(roomType, callback) {
+ if (this.roomTypes[roomType] && this.roomTypes[roomType].roomFind != null) {
+ throw new Meteor.Error('room-find-exists', 'Room find for the given type already exists');
+ }
+ if (this.roomTypes[roomType] == null) {
+ this.roomTypes[roomType] = {};
+ }
+ return this.roomTypes[roomType].roomFind = callback;
+ }
+
+ getRoomFind(roomType) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].roomFind;
+ }
+
+
+ /**
+ * Run the publish for a room type
+ *
+ * @param scope Meteor publish scope
+ * @param {string} roomType room type (e.g.: c (for channels), d (for direct channels))
+ * @param identifier identifier of the room
+ */
+ runPublish(scope, roomType, identifier) {
+ return this.roomTypes[roomType] && this.roomTypes[roomType].publish && this.roomTypes[roomType].publish.call(scope, identifier);
+ }
+
+};
diff --git a/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js b/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js
index 67e75ce24748a..779b1c57b8884 100644
--- a/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js
@@ -1,107 +1,192 @@
import moment from 'moment';
+import s from 'underscore.string';
-RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
- // skips this callback if the message was edited
- if (message.editedAt) {
- return message;
- }
+function getEmailContent({ messageContent, message, user, room }) {
+ const lng = user && user.language || RocketChat.settings.get('language') || 'en';
- if (message.ts && Math.abs(moment(message.ts).diff()) > 60000) {
- return message;
- }
+ const roomName = `#${ RocketChat.settings.get('UI_Allow_room_names_with_special_chars') ? room.fname || room.name : room.name }`;
+
+ const userName = RocketChat.settings.get('UI_Use_Real_Name') ? message.u.name || message.u.username : message.u.username;
- var emailSubject, usersToSendEmail = {};
- var directMessage = room.t === 'd';
+ const header = TAPi18n.__(room.t === 'd' ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', {
+ username: userName,
+ channel: roomName,
+ lng
+ });
- if (directMessage) {
- usersToSendEmail[message.rid.replace(message.u._id, '')] = 1;
+ if (messageContent) {
+ return `${ header } ${ messageContent }`;
+ }
- emailSubject = TAPi18n.__('Offline_DM_Email', {
- user: message.u.username
+ if (message.file) {
+ const fileHeader = TAPi18n.__(room.t === 'd' ? 'User_uploaded_a_file_to_you' : 'User_uploaded_a_file_on_channel', {
+ username: userName,
+ channel: roomName,
+ lng
});
- } else {
- if (message.mentions) {
- message.mentions.forEach(function(mention) {
- usersToSendEmail[mention._id] = 1;
- });
+ let content = `${ TAPi18n.__('Attachment_File_Uploaded') }: ${ message.file.name }`;
+
+ if (message.attachments && message.attachments.length === 1 && message.attachments[0].description !== '') {
+ content += ` ${ message.attachments[0].description }`;
}
- emailSubject = TAPi18n.__('Offline_Mention_Email', {
- user: message.u.username,
- room: room.name
- });
+ return `${ fileHeader } ${ content }`;
}
- var getMessageLink = (room, sub) => {
- var roomPath = RocketChat.roomTypes.getRouteLink(room.t, sub);
- var path = Meteor.absoluteUrl(roomPath ? roomPath.replace(/^\//, '') : '');
- var style = [
+ if (message.attachments.length > 0) {
+ const [ attachment ] = message.attachments;
+
+ let content = '';
+
+ if (attachment.title) {
+ content += `${ attachment.title } `;
+ }
+ if (attachment.text) {
+ content += `${ attachment.text } `;
+ }
+
+ return `${ header } ${ content }`;
+ }
+
+ return header;
+}
+
+RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
+ // skips this callback if the message was edited
+ if (message.editedAt) {
+ return message;
+ }
+
+ if (message.ts && Math.abs(moment(message.ts).diff()) > 60000) {
+ return message;
+ }
+
+ const getMessageLink = (room, sub) => {
+ const roomPath = RocketChat.roomTypes.getRouteLink(room.t, sub);
+ const path = Meteor.absoluteUrl(roomPath ? roomPath.replace(/^\//, '') : '');
+ const style = [
'color: #fff;',
'padding: 9px 12px;',
'border-radius: 4px;',
'background-color: #04436a;',
'text-decoration: none;'
].join(' ');
- var message = TAPi18n.__('Offline_Link_Message');
+ const message = TAPi18n.__('Offline_Link_Message');
return `${ message } `;
};
- var divisorMessage = '
';
- var messageHTML = s.escapeHTML(message.msg);
+ const divisorMessage = ' ';
- message = RocketChat.callbacks.run('renderMessage', message);
- if (message.tokens && message.tokens.length > 0) {
- message.tokens.forEach((token) => {
- token.text = token.text.replace(/([^\$])(\$[^\$])/gm, '$1$$$2');
- messageHTML = messageHTML.replace(token.token, token.text);
- });
+ let messageHTML;
+
+ if (message.msg !== '') {
+ messageHTML = s.escapeHTML(message.msg);
+ message = RocketChat.callbacks.run('renderMessage', message);
+ if (message.tokens && message.tokens.length > 0) {
+ message.tokens.forEach((token) => {
+ token.text = token.text.replace(/([^\$])(\$[^\$])/gm, '$1$$$2');
+ messageHTML = messageHTML.replace(token.token, token.text);
+ });
+ }
+ messageHTML = messageHTML.replace(/\n/gm, ' ');
}
- var header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
- var footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
- messageHTML = messageHTML.replace(/\n/gm, ' ');
-
- RocketChat.models.Subscriptions.findWithSendEmailByRoomId(room._id).forEach((sub) => {
- switch (sub.emailNotifications) {
- case 'all':
- usersToSendEmail[sub.u._id] = 'force';
- break;
- case 'mentions':
- if (usersToSendEmail[sub.u._id]) {
- usersToSendEmail[sub.u._id] = 'force';
- }
- break;
- case 'nothing':
- delete usersToSendEmail[sub.u._id];
- break;
- case 'default':
- break;
+ const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
+ let footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
+
+ const usersToSendEmail = {};
+ if (room.t === 'd') {
+ usersToSendEmail[message.rid.replace(message.u._id, '')] = 'direct';
+ } else {
+ let isMentionAll = message.mentions.find(mention => mention._id === 'all');
+
+ if (isMentionAll) {
+ const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members');
+ if (maxMembersForNotification !== 0 && room.usernames.length > maxMembersForNotification) {
+ isMentionAll = undefined;
+ }
+ }
+
+ let query;
+ if (isMentionAll) {
+ // Query all users in room limited by the max room members setting
+ query = RocketChat.models.Subscriptions.findByRoomId(room._id);
+ } else {
+ // Query only mentioned users, will be always a few users
+ const userIds = message.mentions.map(mention => mention._id);
+ query = RocketChat.models.Subscriptions.findByRoomIdAndUserIdsOrAllMessages(room._id, userIds);
}
- });
- var userIdsToSendEmail = Object.keys(usersToSendEmail);
+ query.forEach((sub) => {
+ if (sub.disableNotifications) {
+ return delete usersToSendEmail[sub.u._id];
+ }
+
+ const emailNotifications = sub.emailNotifications;
+
+ if (emailNotifications === 'nothing') {
+ return delete usersToSendEmail[sub.u._id];
+ }
+
+ const mentionedUser = isMentionAll || message.mentions.find(mention => mention._id === sub.u._id);
+
+ if (emailNotifications === 'default' || emailNotifications == null) {
+ if (mentionedUser) {
+ return usersToSendEmail[sub.u._id] = 'default';
+ }
+ return delete usersToSendEmail[sub.u._id];
+ }
+
+ if (emailNotifications === 'mentions' && mentionedUser) {
+ return usersToSendEmail[sub.u._id] = 'mention';
+ }
+
+ if (emailNotifications === 'all') {
+ return usersToSendEmail[sub.u._id] = 'all';
+ }
+ });
+ }
+ const userIdsToSendEmail = Object.keys(usersToSendEmail);
- var defaultLink;
+ let defaultLink;
- var linkByUser = {};
+ const linkByUser = {};
if (RocketChat.roomTypes.hasCustomLink(room.t)) {
RocketChat.models.Subscriptions.findByRoomIdAndUserIds(room._id, userIdsToSendEmail).forEach((sub) => {
linkByUser[sub.u._id] = getMessageLink(room, sub);
});
} else {
- defaultLink = getMessageLink(room, { name: room.name });
+ defaultLink = getMessageLink(room, {
+ name: room.name
+ });
}
if (userIdsToSendEmail.length > 0) {
- var usersOfMention = RocketChat.models.Users.getUsersToSendOfflineEmail(userIdsToSendEmail).fetch();
+ const usersOfMention = RocketChat.models.Users.getUsersToSendOfflineEmail(userIdsToSendEmail).fetch();
if (usersOfMention && usersOfMention.length > 0) {
- var siteName = RocketChat.settings.get('Site_Name');
-
usersOfMention.forEach((user) => {
- if (user.settings && user.settings.preferences && user.settings.preferences.emailNotificationMode && user.settings.preferences.emailNotificationMode === 'disabled' && usersToSendEmail[user._id] !== 'force') {
- return;
+ const emailNotificationMode = RocketChat.getUserPreference(user, 'emailNotificationMode');
+ if (usersToSendEmail[user._id] === 'default') {
+ if (emailNotificationMode === 'all') { //Mention/DM
+ usersToSendEmail[user._id] = 'mention';
+ } else {
+ return;
+ }
+ }
+
+ if (usersToSendEmail[user._id] === 'direct') {
+ const userEmailPreferenceIsDisabled = emailNotificationMode === 'disabled';
+ const directMessageEmailPreference = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, message.rid.replace(message.u._id, '')).emailNotifications;
+
+ if (directMessageEmailPreference === 'nothing') {
+ return;
+ }
+
+ if ((directMessageEmailPreference === 'default' || directMessageEmailPreference == null) && userEmailPreferenceIsDisabled) {
+ return;
+ }
}
// Checks if user is in the room he/she is mentioned (unless it's public channel)
@@ -109,14 +194,60 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
return;
}
+ // Footer in case direct reply is enabled.
+ if (RocketChat.settings.get('Direct_Reply_Enable')) {
+ footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer_Direct_Reply') || '');
+ }
+
+ let emailSubject;
+ const username = RocketChat.settings.get('UI_Use_Real_Name') ? message.u.name : message.u.username;
+ const roomName = RocketChat.settings.get('UI_Allow_room_names_with_special_chars') ? room.fname : room.name;
+ switch (usersToSendEmail[user._id]) {
+ case 'all':
+ emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_All_Email'), {
+ user: username,
+ room: roomName || room.label
+ });
+ break;
+ case 'direct':
+ emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_DM_Email'), {
+ user: username,
+ room: roomName
+ });
+ break;
+ case 'mention':
+ emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_Email'), {
+ user: username,
+ room: roomName
+ });
+ break;
+ }
user.emails.some((email) => {
if (email.verified) {
+ const content = getEmailContent({
+ messageContent: messageHTML,
+ message,
+ user,
+ room
+ });
email = {
to: email.address,
- from: RocketChat.settings.get('From_Email'),
- subject: `[${ siteName }] ${ emailSubject }`,
- html: header + messageHTML + divisorMessage + (linkByUser[user._id] || defaultLink) + footer
+ subject: emailSubject,
+ html: header + content + divisorMessage + (linkByUser[user._id] || defaultLink) + footer
};
+ // using user full-name/channel name in from address
+ if (room.t === 'd') {
+ email.from = `${ message.u.name } <${ RocketChat.settings.get('From_Email') }>`;
+ } else {
+ email.from = `${ room.name } <${ RocketChat.settings.get('From_Email') }>`;
+ }
+ // If direct reply enabled, email content with headers
+ if (RocketChat.settings.get('Direct_Reply_Enable')) {
+ email.headers = {
+ // Reply-To header with format "username+messageId@domain"
+ 'Reply-To': `${ RocketChat.settings.get('Direct_Reply_Username').split('@')[0].split(RocketChat.settings.get('Direct_Reply_Separator'))[0] }${ RocketChat.settings.get('Direct_Reply_Separator') }${ message._id }@${ RocketChat.settings.get('Direct_Reply_Username').split('@')[1] }`
+ };
+ }
Meteor.defer(() => {
Email.send(email);
diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
index 7427242648414..dab8e6de7fa03 100644
--- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
@@ -1,7 +1,158 @@
/* globals Push */
+import _ from 'underscore';
+import s from 'underscore.string';
import moment from 'moment';
-RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
+const CATEGORY_MESSAGE = 'MESSAGE';
+const CATEGORY_MESSAGE_NOREPLY = 'MESSAGE_NOREPLY';
+
+/**
+ * Replaces @username with full name
+ *
+ * @param {string} message The message to replace
+ * @param {object[]} mentions Array of mentions used to make replacements
+ *
+ * @returns {string}
+ */
+function replaceMentionedUsernamesWithFullNames(message, mentions) {
+ if (!mentions || !mentions.length) {
+ return message;
+ }
+ mentions.forEach((mention) => {
+ const user = RocketChat.models.Users.findOneById(mention._id);
+ if (user && user.name) {
+ message = message.replace(`@${ mention.username }`, user.name);
+ }
+ });
+ return message;
+}
+
+function canSendMessageToRoom(room, username) {
+ return !((room.muted || []).includes(username));
+}
+
+/**
+ * This function returns a string ready to be shown in the notification
+ *
+ * @param {object} message the message to be parsed
+ */
+function parseMessageText(message, userId) {
+ const user = RocketChat.models.Users.findOneById(userId);
+ const lng = user && user.language || RocketChat.settings.get('language') || 'en';
+
+ if (!message.msg && message.attachments && message.attachments[0]) {
+ message.msg = message.attachments[0].image_type ? TAPi18n.__('User_uploaded_image', {lng}) : TAPi18n.__('User_uploaded_file', {lng});
+ }
+ message.msg = RocketChat.callbacks.run('beforeNotifyUser', message.msg);
+
+ return message.msg;
+}
+/**
+ * Send notification to user
+ *
+ * @param {string} userId The user to notify
+ * @param {object} user The sender
+ * @param {object} room The room send from
+ * @param {number} duration Duration of notification
+ */
+function notifyDesktopUser(userId, user, message, room, duration) {
+
+ const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
+ message.msg = parseMessageText(message, userId);
+
+ if (UI_Use_Real_Name) {
+ message.msg = replaceMentionedUsernamesWithFullNames(message.msg, message.mentions);
+ }
+ let title = UI_Use_Real_Name ? user.name : `@${ user.username }`;
+ if (room.t !== 'd' && room.name) {
+ title += ` @ #${ room.name }`;
+ }
+ RocketChat.Notifications.notifyUser(userId, 'notification', {
+ title,
+ text: message.msg,
+ duration,
+ payload: {
+ _id: message._id,
+ rid: message.rid,
+ sender: message.u,
+ type: room.t,
+ name: room.name
+ }
+ });
+}
+
+function notifyAudioUser(userId, message, room) {
+ RocketChat.Notifications.notifyUser(userId, 'audioNotification', {
+ payload: {
+ _id: message._id,
+ rid: message.rid,
+ sender: message.u,
+ type: room.t,
+ name: room.name
+ }
+ });
+}
+
+/**
+ * Checks if a message contains a user highlight
+ *
+ * @param {string} message
+ * @param {array|undefined} highlights
+ *
+ * @returns {boolean}
+ */
+function messageContainsHighlight(message, highlights) {
+ if (! highlights || highlights.length === 0) { return false; }
+
+ let has = false;
+ highlights.some(function(highlight) {
+ const regexp = new RegExp(s.escapeRegExp(highlight), 'i');
+ if (regexp.test(message.msg)) {
+ has = true;
+ return true;
+ }
+ });
+
+ return has;
+}
+
+function getBadgeCount(userId) {
+ const subscriptions = RocketChat.models.Subscriptions.findUnreadByUserId(userId).fetch();
+
+ return subscriptions.reduce((unread, sub) => {
+ return sub.unread + unread;
+ }, 0);
+}
+
+const sendPushNotifications = (userIdsToPushNotify = [], message, room, push_room, push_username, push_message, pushUsernames) => {
+ if (userIdsToPushNotify.length > 0 && Push.enabled === true) {
+ // send a push notification for each user individually (to get his/her badge count)
+ userIdsToPushNotify.forEach((userIdToNotify) => {
+ RocketChat.PushNotification.send({
+ roomId: message.rid,
+ roomName: push_room,
+ username: push_username,
+ message: push_message,
+ badge: getBadgeCount(userIdToNotify),
+ payload: {
+ host: Meteor.absoluteUrl(),
+ rid: message.rid,
+ sender: message.u,
+ type: room.t,
+ name: room.name
+ },
+ usersTo: {
+ userId: userIdToNotify
+ },
+ category: canSendMessageToRoom(room, pushUsernames[userIdToNotify]) ? CATEGORY_MESSAGE : CATEGORY_MESSAGE_NOREPLY
+ });
+ });
+ }
+};
+
+const callJoin = (user, rid) => user.active && Meteor.runAsUser(user._id, () => Meteor.call('joinRoom', rid));
+RocketChat.callbacks.add('afterSaveMessage', function(message, room, userId) {
+
// skips this callback if the message was edited
if (message.editedAt) {
return message;
@@ -11,22 +162,29 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
return message;
}
- var user = RocketChat.models.Users.findOneById(message.u._id);
+ const pushUsernames = {};
+
+ const user = RocketChat.models.Users.findOneById(message.u._id);
+
+ // might be a livechat visitor
+ if (!user) {
+ return message;
+ }
/*
Increment unread couter if direct messages
*/
- var indexOf = [].indexOf || function(item) {
- for (var i = 0, l = this.length; i < l; i++) {
- if (i in this && this[i] === item) {
- return i;
- }
- }
- return -1;
+ const settings = {
+ alwaysNotifyDesktopUsers: [],
+ dontNotifyDesktopUsers: [],
+ alwaysNotifyMobileUsers: [],
+ dontNotifyMobileUsers: [],
+ desktopNotificationDurations: {},
+ alwaysNotifyAudioUsers: [],
+ dontNotifyAudioUsers: [],
+ audioNotificationValues: {}
};
- var settings, desktopMentionIds, i, j, len, len1, highlights, mentionIds, highlightsIds, usersWithHighlights, mobileMentionIds, ref, ref1, toAll, toHere, userIdsToNotify, userIdsToPushNotify, userOfMention, userOfMentionId, usersOfDesktopMentions, usersOfMentionId, usersOfMentionItem, usersOfMobileMentions;
-
/**
* Checks if a given user can be notified
*
@@ -36,93 +194,84 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
* @returns {boolean}
*/
function canBeNotified(id, type) {
- var types = {
- mobile: [ 'dontNotifyDesktopUsers', 'alwaysNotifyDesktopUsers' ],
- desktop: [ 'dontNotifyMobileUsers', 'alwaysNotifyMobileUsers' ]
+ const types = {
+ desktop: [ 'dontNotifyDesktopUsers', 'alwaysNotifyDesktopUsers' ],
+ mobile: [ 'dontNotifyMobileUsers', 'alwaysNotifyMobileUsers' ],
+ audio: [ 'dontNotifyAudioUsers', 'alwaysNotifyAudioUsers' ]
};
return (settings[types[type][0]].indexOf(id) === -1 || settings[types[type][1]].indexOf(id) !== -1);
}
- /**
- * Checks if a message contains a user highlight
- *
- * @param {string} message
- * @param {array|undefined} highlights
- *
- * @returns {boolean}
- */
- function messageContainsHighlight(message, highlights) {
- if (! highlights || highlights.length === 0) { return false; }
-
- var has = false;
- highlights.some(function(highlight) {
- var regexp = new RegExp(s.escapeRegExp(highlight), 'i');
- if (regexp.test(message.msg)) {
- has = true;
- return true;
- }
- });
-
- return has;
- }
+ // Don't fetch all users if room exceeds max members
+ const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members');
+ const disableAllMessageNotifications = room.usernames.length > maxMembersForNotification && maxMembersForNotification !== 0;
+ const subscriptions = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id, disableAllMessageNotifications);
+ const userIds = [];
+ subscriptions.forEach((s) => {
+ userIds.push(s.u._id);
+ });
+ const users = {};
+ RocketChat.models.Users.findUsersByIds(userIds, { fields: { 'settings.preferences': 1 } }).forEach((user) => {
+ users[user._id] = user;
+ });
- settings = {};
+ subscriptions.forEach(subscription => {
+ if (subscription.disableNotifications) {
+ settings.dontNotifyDesktopUsers.push(subscription.u._id);
+ settings.dontNotifyMobileUsers.push(subscription.u._id);
+ settings.dontNotifyAudioUsers.push(subscription.u._id);
+ return;
+ }
- settings.alwaysNotifyDesktopUsers = [];
- settings.dontNotifyDesktopUsers = [];
- settings.alwaysNotifyMobileUsers = [];
- settings.dontNotifyMobileUsers = [];
- settings.desktopNotificationDurations = {};
+ const {
+ audioNotifications = RocketChat.getUserPreference(users[subscription.u._id], 'audioNotifications'),
+ desktopNotifications = RocketChat.getUserPreference(users[subscription.u._id], 'desktopNotifications'),
+ mobilePushNotifications = RocketChat.getUserPreference(users[subscription.u._id], 'mobileNotifications')
+ } = subscription;
- const notificationPreferencesByRoom = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id);
- notificationPreferencesByRoom.forEach(function(subscription) {
- if (subscription.desktopNotifications === 'all') {
+ if (audioNotifications === 'all' && !disableAllMessageNotifications) {
+ settings.alwaysNotifyAudioUsers.push(subscription.u._id);
+ }
+ if (desktopNotifications === 'all' && !disableAllMessageNotifications) {
settings.alwaysNotifyDesktopUsers.push(subscription.u._id);
- } else if (subscription.desktopNotifications === 'nothing') {
+ } else if (desktopNotifications === 'nothing') {
settings.dontNotifyDesktopUsers.push(subscription.u._id);
}
- if (subscription.mobilePushNotifications === 'all') {
+ if (mobilePushNotifications === 'all' && !disableAllMessageNotifications) {
settings.alwaysNotifyMobileUsers.push(subscription.u._id);
- } else if (subscription.mobilePushNotifications === 'nothing') {
+ } else if (mobilePushNotifications === 'nothing') {
settings.dontNotifyMobileUsers.push(subscription.u._id);
}
+
+ settings.audioNotificationValues[subscription.u._id] = subscription.audioNotificationValue;
settings.desktopNotificationDurations[subscription.u._id] = subscription.desktopNotificationDuration;
});
+ let userIdsForAudio = [];
+ let userIdsToNotify = [];
+ let userIdsToPushNotify = [];
+ const mentions = [];
+ const alwaysNotifyMobileBoolean = RocketChat.settings.get('Notifications_Always_Notify_Mobile');
- userIdsToNotify = [];
- userIdsToPushNotify = [];
- usersWithHighlights = [];
-
- highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch();
-
- highlights.forEach(function(user) {
- if (messageContainsHighlight(message, user.settings.preferences.highlights)) {
- usersWithHighlights.push(user);
- }
- });
+ const usersWithHighlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch()
+ .filter(user => messageContainsHighlight(message, user.settings.preferences.highlights));
- let push_message;
+ let push_message = ' ';
//Set variables depending on Push Notification settings
if (RocketChat.settings.get('Push_show_message')) {
- push_message = message.msg;
- } else {
- push_message = ' ';
+ push_message = parseMessageText(message, userId);
}
- let push_username;
- let push_room;
+ let push_username = '';
+ let push_room = '';
if (RocketChat.settings.get('Push_show_username_room')) {
push_username = user.username;
- push_room = '#' + room.name;
- } else {
- push_username = '';
- push_room = '';
+ push_room = `#${ room.name }`;
}
- if ((room.t == null) || room.t === 'd') {
- userOfMentionId = message.rid.replace(message.u._id, '');
- userOfMention = RocketChat.models.Users.findOne({
+ if (room.t == null || room.t === 'd') {
+ const userOfMentionId = message.rid.replace(message.u._id, '');
+ const userOfMention = RocketChat.models.Users.findOne({
_id: userOfMentionId
}, {
fields: {
@@ -134,59 +283,47 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
// Always notify Sandstorm
if (userOfMention != null) {
RocketChat.Sandstorm.notify(message, [userOfMention._id],
- '@' + user.username + ': ' + message.msg, 'privateMessage');
+ `@${ user.username }: ${ message.msg }`, 'privateMessage');
- }
- if ((userOfMention != null) && canBeNotified(userOfMentionId, 'mobile')) {
- RocketChat.Notifications.notifyUser(userOfMention._id, 'notification', {
- title: '@' + user.username,
- text: message.msg,
- duration: settings.desktopNotificationDurations[userOfMention._id],
- payload: {
- _id: message._id,
- rid: message.rid,
- sender: message.u,
- type: room.t,
- name: room.name
- }
- });
- }
+ if (canBeNotified(userOfMentionId, 'desktop')) {
+ const duration = settings.desktopNotificationDurations[userOfMention._id];
+ notifyDesktopUser(userOfMention._id, user, message, room, duration);
+ }
- if ((userOfMention != null) && canBeNotified(userOfMentionId, 'desktop')) {
- if (Push.enabled === true && userOfMention.statusConnection !== 'online') {
- RocketChat.PushNotification.send({
- roomId: message.rid,
- username: push_username,
- message: push_message,
- payload: {
- host: Meteor.absoluteUrl(),
- rid: message.rid,
- sender: message.u,
- type: room.t,
- name: room.name
- },
- usersTo: {
- userId: userOfMention._id
- }
- });
- return message;
+ if (canBeNotified(userOfMentionId, 'mobile')) {
+ if (Push.enabled === true && (userOfMention.statusConnection !== 'online' || alwaysNotifyMobileBoolean === true)) {
+ RocketChat.PushNotification.send({
+ roomId: message.rid,
+ username: push_username,
+ message: push_message,
+ badge: getBadgeCount(userOfMention._id),
+ payload: {
+ host: Meteor.absoluteUrl(),
+ rid: message.rid,
+ sender: message.u,
+ type: room.t,
+ name: room.name
+ },
+ usersTo: {
+ userId: userOfMention._id
+ },
+ category: canSendMessageToRoom(room, userOfMention.username) ? CATEGORY_MESSAGE : CATEGORY_MESSAGE_NOREPLY
+ });
+ return message;
+ }
}
}
} else {
- mentionIds = [];
- if ((ref = message.mentions) != null) {
- ref.forEach(function(mention) {
- return mentionIds.push(mention._id);
- });
- }
- toAll = mentionIds.indexOf('all') > -1;
- toHere = mentionIds.indexOf('here') > -1;
- if (mentionIds.length > 0 || settings.alwaysNotifyDesktopUsers.length > 0) {
- desktopMentionIds = _.union(mentionIds, settings.alwaysNotifyDesktopUsers);
+ const mentionIds = (message.mentions || []).map(({_id}) => _id);
+ const toAll = mentionIds.includes('all');
+ const toHere = mentionIds.includes('here');
+
+ if (mentionIds.length + settings.alwaysNotifyDesktopUsers.length > 0) {
+ let desktopMentionIds = _.union(mentionIds, settings.alwaysNotifyDesktopUsers);
desktopMentionIds = _.difference(desktopMentionIds, settings.dontNotifyDesktopUsers);
- usersOfDesktopMentions = RocketChat.models.Users.find({
+ let usersOfDesktopMentions = RocketChat.models.Users.find({
_id: {
$in: desktopMentionIds
}
@@ -197,22 +334,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
active: 1
}
}).fetch();
- if (room.t === 'c' && !toAll) {
- const callJoin = function(usersOfMentionItem) {
- if (usersOfMentionItem.active) {
- Meteor.runAsUser(usersOfMentionItem._id, function() {
- return Meteor.call('joinRoom', room._id);
- });
- }
- };
- for (i = 0, len = usersOfDesktopMentions.length; i < len; i++) {
- usersOfMentionItem = usersOfDesktopMentions[i];
- if (room.usernames.indexOf(usersOfMentionItem.username) === -1) {
- callJoin(usersOfMentionItem);
- }
- }
- }
-
+ mentions.push(...usersOfDesktopMentions);
if (room.t !== 'c') {
usersOfDesktopMentions = _.reject(usersOfDesktopMentions, (usersOfMentionItem) => {
return room.usernames.indexOf(usersOfMentionItem.username) === -1;
@@ -222,41 +344,72 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
userIdsToNotify = _.pluck(usersOfDesktopMentions, '_id');
}
- if (mentionIds.length > 0 || settings.alwaysNotifyMobileUsers.length > 0) {
- mobileMentionIds = _.union(mentionIds, settings.alwaysNotifyMobileUsers);
+ if (mentionIds.length + settings.alwaysNotifyMobileUsers.length > 0) {
+ let mobileMentionIds = _.union(mentionIds, settings.alwaysNotifyMobileUsers);
mobileMentionIds = _.difference(mobileMentionIds, settings.dontNotifyMobileUsers);
- usersOfMobileMentions = RocketChat.models.Users.find({
+ const usersOfMobileMentionsQuery = {
_id: {
$in: mobileMentionIds
}
- }, {
+ };
+
+ if (alwaysNotifyMobileBoolean !== true) {
+ usersOfMobileMentionsQuery.statusConnection = { $ne: 'online' };
+ }
+
+ let usersOfMobileMentions = RocketChat.models.Users.find(usersOfMobileMentionsQuery, {
fields: {
_id: 1,
username: 1,
- statusConnection: 1
+ statusConnection: 1,
+ active: 1
}
}).fetch();
+ mentions.push(...usersOfMobileMentions);
if (room.t !== 'c') {
- usersOfMobileMentions = _.reject(usersOfMobileMentions, (usersOfMentionItem) => {
+ usersOfMobileMentions = _.reject(usersOfMobileMentions, usersOfMentionItem => !room.usernames.includes(usersOfMentionItem.username));
+ }
+
+ userIdsToPushNotify = usersOfMobileMentions.map(userMobile => {
+ pushUsernames[userMobile._id] = userMobile.username;
+ return userMobile._id;
+ });
+ }
+
+ if (mentionIds.length + settings.alwaysNotifyAudioUsers.length > 0) {
+ let audioMentionIds = _.union(mentionIds, settings.alwaysNotifyAudioUsers);
+ audioMentionIds = _.difference(audioMentionIds, userIdsToNotify);
+
+ let usersOfAudioMentions = RocketChat.models.Users.find({ _id: { $in: audioMentionIds }, statusConnection: {
+ $ne:'offline'
+ } }, {
+ fields: {
+ _id: 1,
+ username: 1,
+ active: 1
+ }
+ }).fetch();
+ mentions.push(...usersOfAudioMentions);
+ if (room.t !== 'c') {
+ usersOfAudioMentions = _.reject(usersOfAudioMentions, (usersOfMentionItem) => {
return room.usernames.indexOf(usersOfMentionItem.username) === -1;
});
}
- userIdsToPushNotify = _.pluck(_.filter(usersOfMobileMentions, function(user) {
- return user.statusConnection !== 'online';
- }), '_id');
+ userIdsForAudio = _.pluck(usersOfAudioMentions, '_id');
}
- if ((toAll || toHere) && ((ref1 = room.usernames) != null ? ref1.length : void 0) > 0) {
+ if (room.t === 'c') {
+ mentions.filter(user => !room.usernames.includes(user.username))
+ .forEach(user =>callJoin(user, room._id));
+ }
+
+ if ([toAll, toHere].some(e => e) && room.usernames && room.usernames.length > 0) {
RocketChat.models.Users.find({
- username: {
- $in: room.usernames
- },
- _id: {
- $ne: user._id
- }
+ username: { $in: room.usernames },
+ _id: { $ne: user._id }
}, {
fields: {
_id: 1,
@@ -265,78 +418,43 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
statusConnection: 1
}
}).forEach(function(user) {
- var ref2, ref3, ref4;
- if (((ref2 = user.status) === 'online' || ref2 === 'away' || ref2 === 'busy') && (ref3 = user._id, indexOf.call(settings.dontNotifyDesktopUsers, ref3) < 0)) {
+ if (['online', 'away', 'busy'].includes(user.status) && !(settings.dontNotifyDesktopUsers || []).includes(user._id)) {
userIdsToNotify.push(user._id);
+ userIdsForAudio.push(user._id);
}
- if (toAll && user.statusConnection !== 'online' && (ref4 = user._id, indexOf.call(settings.dontNotifyMobileUsers, ref4) < 0)) {
+ if (toAll && user.statusConnection !== 'online' && !(settings.dontNotifyMobileUsers || []).includes(user._id)) {
+ pushUsernames[user._id] = user.username;
return userIdsToPushNotify.push(user._id);
}
+ if (toAll && user.statusConnection !== 'online') {
+ userIdsForAudio.push(user._id);
+ }
});
}
if (usersWithHighlights.length > 0) {
- highlightsIds = _.pluck(usersWithHighlights, '_id');
+ const highlightsIds = _.pluck(usersWithHighlights, '_id');
+ userIdsForAudio = userIdsForAudio.concat(highlightsIds);
userIdsToNotify = userIdsToNotify.concat(highlightsIds);
userIdsToPushNotify = userIdsToPushNotify.concat(highlightsIds);
}
userIdsToNotify = _.without(_.compact(_.unique(userIdsToNotify)), message.u._id);
userIdsToPushNotify = _.without(_.compact(_.unique(userIdsToPushNotify)), message.u._id);
+ userIdsForAudio = _.without(_.compact(_.unique(userIdsForAudio)), message.u._id);
- if (userIdsToNotify.length > 0) {
- for (j = 0, len1 = userIdsToNotify.length; j < len1; j++) {
- usersOfMentionId = userIdsToNotify[j];
- let title = '@' + user.username;
- if (room.name) {
- title += ' @ #' + room.name;
- }
- RocketChat.Notifications.notifyUser(usersOfMentionId, 'notification', {
- title: title,
- text: message.msg,
- duration: settings.desktopNotificationDurations[usersOfMentionId],
- payload: {
- _id: message._id,
- rid: message.rid,
- sender: message.u,
- type: room.t,
- name: room.name
- }
- });
- }
+ for (const usersOfMentionId of userIdsToNotify) {
+ const duration = settings.desktopNotificationDurations[usersOfMentionId];
+ notifyDesktopUser(usersOfMentionId, user, message, room, duration);
}
-
- if (userIdsToPushNotify.length > 0) {
- if (Push.enabled === true) {
- RocketChat.PushNotification.send({
- roomId: message.rid,
- roomName: push_room,
- username: push_username,
- message: push_message,
- payload: {
- host: Meteor.absoluteUrl(),
- rid: message.rid,
- sender: message.u,
- type: room.t,
- name: room.name
- },
- usersTo: {
- userId: {
- $in: userIdsToPushNotify
- }
- }
- });
- }
+ for (const usersOfMentionId of userIdsForAudio) {
+ notifyAudioUser(usersOfMentionId, message, room);
}
+ sendPushNotifications(userIdsToPushNotify, message, room, push_room, push_username, push_message, pushUsernames);
const allUserIdsToNotify = _.unique(userIdsToNotify.concat(userIdsToPushNotify));
- if (room.t === 'p') {
- RocketChat.Sandstorm.notify(message, allUserIdsToNotify,
- '@' + user.username + ': ' + message.msg, 'privateMessage');
- } else {
- RocketChat.Sandstorm.notify(message, allUserIdsToNotify,
- '@' + user.username + ': ' + message.msg, 'message');
- }
+ RocketChat.Sandstorm.notify(message, allUserIdsToNotify,
+ `@${ user.username }: ${ message.msg }`, room.t === 'p' ? 'privateMessage' : 'message');
}
return message;
diff --git a/packages/rocketchat-lib/server/lib/validateEmailDomain.js b/packages/rocketchat-lib/server/lib/validateEmailDomain.js
index 3a34487bb668b..d964b6b631860 100644
--- a/packages/rocketchat-lib/server/lib/validateEmailDomain.js
+++ b/packages/rocketchat-lib/server/lib/validateEmailDomain.js
@@ -1,9 +1,10 @@
-const dns = Npm.require('dns');
+import _ from 'underscore';
+import dns from 'dns';
-var emailDomainBlackList = [];
-var emailDomainWhiteList = [];
-var useDefaultBlackList = false;
-var useDNSDomainCheck = false;
+let emailDomainBlackList = [];
+let emailDomainWhiteList = [];
+let useDefaultBlackList = false;
+let useDNSDomainCheck = false;
RocketChat.settings.get('Accounts_BlockedDomainsList', function(key, value) {
emailDomainBlackList = _.map(value.split(','), (domain) => domain.trim());
@@ -21,7 +22,7 @@ RocketChat.settings.get('Accounts_UseDNSDomainCheck', function(key, value) {
RocketChat.validateEmailDomain = function(email) {
const emailValidation = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
if (!emailValidation.test(email)) {
- throw new Meteor.Error('error-invalid-email', 'Invalid email ' + email, { function: 'RocketChat.validateEmailDomain', email: email });
+ throw new Meteor.Error('error-invalid-email', `Invalid email ${ email }`, { function: 'RocketChat.validateEmailDomain', email });
}
const emailDomain = email.substr(email.lastIndexOf('@') + 1);
diff --git a/packages/rocketchat-lib/server/methods/addOAuthService.js b/packages/rocketchat-lib/server/methods/addOAuthService.js
index b378b87afcf61..bb442ade86a73 100644
--- a/packages/rocketchat-lib/server/methods/addOAuthService.js
+++ b/packages/rocketchat-lib/server/methods/addOAuthService.js
@@ -1,5 +1,6 @@
/* eslint no-multi-spaces: 0 */
/* eslint comma-spacing: 0 */
+import s from 'underscore.string';
Meteor.methods({
addOAuthService(name) {
@@ -16,19 +17,20 @@ Meteor.methods({
name = name.toLowerCase().replace(/[^a-z0-9_]/g, '');
name = s.capitalize(name);
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Enable', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-url` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'URL', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-token_path` , '/oauth/token' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Token_Path', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-identity_path` , '/me' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Identity_Path', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-authorize_path` , '/oauth/authorize', { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Authorize_Path', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-scope` , 'openid' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Scope', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-token_sent_via` , 'payload' , { type: 'select' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Token_Sent_Via', persistent: true, values: [ { key: 'header', i18nLabel: 'Header' }, { key: 'payload', i18nLabel: 'Payload' } ] });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-id` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_id', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-secret` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Secret', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-login_style` , 'popup' , { type: 'select' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Login_Style', persistent: true, values: [ { key: 'redirect', i18nLabel: 'Redirect' }, { key: 'popup', i18nLabel: 'Popup' }, { key: '', i18nLabel: 'Default' } ] });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-button_label_text` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-button_label_color`, '#FFFFFF' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-button_color` , '#13679A' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Button_Color', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-username_field` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Username_Field', persistent: true });
- RocketChat.settings.add(`Accounts_OAuth_Custom-${name}-merge_users` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${name}`, i18nLabel: 'Accounts_OAuth_Custom_Merge_Users', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Enable', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-url` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'URL', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-token_path` , '/oauth/token' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Token_Path', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-token_sent_via` , 'payload' , { type: 'select' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Token_Sent_Via', persistent: true, values: [ { key: 'header', i18nLabel: 'Header' }, { key: 'payload', i18nLabel: 'Payload' } ] });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-identity_token_sent_via`, 'default' , { type: 'select' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Identity_Token_Sent_Via', persistent: true, values: [ { key: 'default', i18nLabel: 'Same_As_Token_Sent_Via' }, { key: 'header', i18nLabel: 'Header' }, { key: 'payload', i18nLabel: 'Payload' } ] });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-identity_path` , '/me' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Identity_Path', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-authorize_path` , '/oauth/authorize', { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Authorize_Path', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-scope` , 'openid' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Scope', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-id` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_id', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-secret` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Secret', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-login_style` , 'popup' , { type: 'select' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Login_Style', persistent: true, values: [ { key: 'redirect', i18nLabel: 'Redirect' }, { key: 'popup', i18nLabel: 'Popup' }, { key: '', i18nLabel: 'Default' } ] });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-button_label_text` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-button_label_color` , '#FFFFFF' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-button_color` , '#13679A' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Button_Color', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-username_field` , '' , { type: 'string' , group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Username_Field', persistent: true });
+ RocketChat.settings.add(`Accounts_OAuth_Custom-${ name }-merge_users` , false , { type: 'boolean', group: 'OAuth', section: `Custom OAuth: ${ name }`, i18nLabel: 'Accounts_OAuth_Custom_Merge_Users', persistent: true });
}});
diff --git a/packages/rocketchat-lib/server/methods/addUserToRoom.js b/packages/rocketchat-lib/server/methods/addUserToRoom.js
index 2c507b8a6f0c5..3b1871a49a526 100644
--- a/packages/rocketchat-lib/server/methods/addUserToRoom.js
+++ b/packages/rocketchat-lib/server/methods/addUserToRoom.js
@@ -1,36 +1,8 @@
Meteor.methods({
addUserToRoom(data) {
- if (!Meteor.userId()) {
- throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'addUserToRoom' });
- }
-
- if (!Match.test(data && data.rid, String)) {
- throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'addUserToRoom' });
- }
-
- if (!Match.test(data && data.username, String)) {
- throw new Meteor.Error('error-invalid-username', 'Invalid username', { method: 'addUserToRoom' });
- }
-
- const room = RocketChat.models.Rooms.findOneById(data.rid);
-
- if (room.usernames.indexOf(Meteor.user().username) === -1) {
- throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'addUserToRoom' });
- }
-
- const fromId = Meteor.userId();
- if (!RocketChat.authz.hasPermission(fromId, 'add-user-to-room', room._id)) {
- throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'addUserToRoom' });
- }
-
- if (room.t === 'd') {
- throw new Meteor.Error('error-cant-invite-for-direct-room', 'Can\'t invite user to direct rooms', { method: 'addUserToRoom' });
- }
-
-
- const newUser = RocketChat.models.Users.findOneByUsername(data.username);
- RocketChat.addUserToRoom(data.rid, newUser, Meteor.user());
-
- return true;
+ return Meteor.call('addUsersToRoom', {
+ rid: data.rid,
+ users: [ data.username ]
+ });
}
});
diff --git a/packages/rocketchat-lib/server/methods/addUsersToRoom.js b/packages/rocketchat-lib/server/methods/addUsersToRoom.js
index 644603885f623..b00c42350d314 100644
--- a/packages/rocketchat-lib/server/methods/addUsersToRoom.js
+++ b/packages/rocketchat-lib/server/methods/addUsersToRoom.js
@@ -1,40 +1,67 @@
Meteor.methods({
- addUsersToRoom: function(data) {
- var fromId, room;
+ addUsersToRoom(data = {}) {
+ // Validate user and room
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
- method: 'addUserToRoom'
+ method: 'addUsersToRoom'
});
}
- if (!Match.test(data != null ? data.rid : void 0, String)) {
+
+ if (!Match.test(data.rid, String)) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
- method: 'addUserToRoom'
+ method: 'addUsersToRoom'
});
}
- room = RocketChat.models.Rooms.findOneById(data.rid);
- if (room.usernames.indexOf(Meteor.user().username) === -1) {
- throw new Meteor.Error('error-not-allowed', 'Not allowed', {
- method: 'addUserToRoom'
+ // Get user and room details
+ const room = RocketChat.models.Rooms.findOneById(data.rid);
+ const userId = Meteor.userId();
+ const user = Meteor.user();
+ const userInRoom = Array.isArray(room.usernames) && room.usernames.includes(user.username);
+
+ // Can't add to direct room ever
+ if (room.t === 'd') {
+ throw new Meteor.Error('error-cant-invite-for-direct-room', 'Can\'t invite user to direct rooms', {
+ method: 'addUsersToRoom'
});
}
- fromId = Meteor.userId();
- if (!RocketChat.authz.hasPermission(fromId, 'add-user-to-room', room._id)) {
+ // Can add to any room you're in, with permission, otherwise need specific room type permission
+ let canAddUser = false;
+ if (userInRoom && RocketChat.authz.hasPermission(userId, 'add-user-to-joined-room', room._id)) {
+ canAddUser = true;
+ } else if (room.t === 'c' && RocketChat.authz.hasPermission(userId, 'add-user-to-any-c-room')) {
+ canAddUser = true;
+ } else if (room.t === 'p' && RocketChat.authz.hasPermission(userId, 'add-user-to-any-p-room')) {
+ canAddUser = true;
+ }
+
+ // Adding wasn't allowed
+ if (!canAddUser) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
- method: 'addUserToRoom'
+ method: 'addUsersToRoom'
});
}
- if (room.t === 'd') {
- throw new Meteor.Error('error-cant-invite-for-direct-room', 'Can\'t invite user to direct rooms', {
- method: 'addUserToRoom'
+
+ // Missing the users to be added
+ if (!Array.isArray(data.users)) {
+ throw new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {
+ method: 'addUsersToRoom'
});
}
- data.users = Array.isArray(data.users) ? data.users : [];
- data.users.forEach(function(username) {
- let newUser = RocketChat.models.Users.findOneByUsername(username);
- RocketChat.addUserToRoom(data.rid, newUser, Meteor.user());
+
+ // Validate each user, then add to room
+ data.users.forEach((username) => {
+ const newUser = RocketChat.models.Users.findOneByUsername(username);
+ if (!newUser) {
+ throw new Meteor.Error('error-invalid-username', 'Invalid username', {
+ method: 'addUsersToRoom'
+ });
+ }
+
+ RocketChat.addUserToRoom(data.rid, newUser, user);
});
+
return true;
}
-});
\ No newline at end of file
+});
diff --git a/packages/rocketchat-lib/server/methods/archiveRoom.js b/packages/rocketchat-lib/server/methods/archiveRoom.js
index 75df0fe4d8d23..9f79b9539af5b 100644
--- a/packages/rocketchat-lib/server/methods/archiveRoom.js
+++ b/packages/rocketchat-lib/server/methods/archiveRoom.js
@@ -17,6 +17,10 @@ Meteor.methods({
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'archiveRoom' });
}
+ if (room.t === 'd') {
+ throw new Meteor.Error('error-direct-message-room', 'Direct Messages can not be archived', { method: 'archiveRoom' });
+ }
+
return RocketChat.archiveRoom(rid);
}
});
diff --git a/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js b/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js
new file mode 100644
index 0000000000000..4304b06d21ac3
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/checkUsernameAvailability.js
@@ -0,0 +1,24 @@
+Meteor.methods({
+ checkUsernameAvailability(username) {
+ check(username, String);
+
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setUsername' });
+ }
+
+ const user = Meteor.user();
+
+ if (user.username && !RocketChat.settings.get('Accounts_AllowUsernameChange')) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setUsername' });
+ }
+
+ if (user.username === username) {
+ return true;
+ }
+ return RocketChat.checkUsernameAvailability(username);
+ }
+});
+
+RocketChat.RateLimiter.limitMethod('checkUsernameAvailability', 1, 1000, {
+ userId() { return true; }
+});
diff --git a/packages/rocketchat-lib/server/methods/createChannel.js b/packages/rocketchat-lib/server/methods/createChannel.js
index 1515ecd3f228d..d3f85b8a145cb 100644
--- a/packages/rocketchat-lib/server/methods/createChannel.js
+++ b/packages/rocketchat-lib/server/methods/createChannel.js
@@ -1,6 +1,7 @@
Meteor.methods({
- createChannel(name, members, readOnly = false, customFields = {}) {
+ createChannel(name, serverId, members, readOnly = false, customFields = {}) {
check(name, String);
+ check(serverId, String);
check(members, Match.Optional([String]));
if (!Meteor.userId()) {
@@ -11,6 +12,6 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createChannel' });
}
- return RocketChat.createRoom('c', name, Meteor.user() && Meteor.user().username, members, readOnly, {customFields});
+ return RocketChat.createRoom('c', name, serverId, Meteor.user() && Meteor.user().username, members, readOnly, {customFields});
}
});
diff --git a/packages/rocketchat-lib/server/methods/createPrivateGroup.js b/packages/rocketchat-lib/server/methods/createPrivateGroup.js
index f50ada1debba9..82ceaebb1fec0 100644
--- a/packages/rocketchat-lib/server/methods/createPrivateGroup.js
+++ b/packages/rocketchat-lib/server/methods/createPrivateGroup.js
@@ -1,6 +1,7 @@
Meteor.methods({
- createPrivateGroup(name, members, readOnly = false, customFields = {}) {
+ createPrivateGroup(name, serverId, members, readOnly = false, customFields = {}, extraData = {}) {
check(name, String);
+ check(serverId, String);
check(members, Match.Optional([String]));
if (!Meteor.userId()) {
@@ -11,6 +12,17 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createPrivateGroup' });
}
- return RocketChat.createRoom('p', name, Meteor.user() && Meteor.user().username, members, readOnly, {customFields});
+ // validate extra data schema
+ check(extraData, Match.ObjectIncluding({
+ tokenpass: Match.Maybe({
+ require: String,
+ tokens: [{
+ token: String,
+ balance: String
+ }]
+ })
+ }));
+
+ return RocketChat.createRoom('p', name, serverId, Meteor.user() && Meteor.user().username, members, readOnly, {customFields, ...extraData});
}
});
diff --git a/packages/rocketchat-lib/server/methods/createToken.js b/packages/rocketchat-lib/server/methods/createToken.js
new file mode 100644
index 0000000000000..29879093c1c55
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/createToken.js
@@ -0,0 +1,13 @@
+Meteor.methods({
+ createToken(userId) {
+ if (Meteor.userId() !== userId && !RocketChat.authz.hasPermission(Meteor.userId(), 'user-generate-access-token')) {
+ throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'createToken' });
+ }
+ const token = Accounts._generateStampedLoginToken();
+ Accounts._insertLoginToken(userId, token);
+ return {
+ userId,
+ authToken: token.token
+ };
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/deleteMessage.coffee b/packages/rocketchat-lib/server/methods/deleteMessage.coffee
deleted file mode 100644
index 04ab2e6f5f9bc..0000000000000
--- a/packages/rocketchat-lib/server/methods/deleteMessage.coffee
+++ /dev/null
@@ -1,30 +0,0 @@
-import moment from 'moment'
-
-Meteor.methods
- deleteMessage: (message) ->
-
- check message, Match.ObjectIncluding({_id:String})
-
- if not Meteor.userId()
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'deleteMessage' }
-
- originalMessage = RocketChat.models.Messages.findOneById message._id, {fields: {u: 1, rid: 1, file: 1}}
- if not originalMessage?
- throw new Meteor.Error 'error-action-not-allowed', 'Not allowed', { method: 'deleteMessage', action: 'Delete_message' }
-
- hasPermission = RocketChat.authz.hasPermission(Meteor.userId(), 'delete-message', originalMessage.rid)
- deleteAllowed = RocketChat.settings.get 'Message_AllowDeleting'
-
- deleteOwn = originalMessage?.u?._id is Meteor.userId()
-
- unless hasPermission or (deleteAllowed and deleteOwn)
- throw new Meteor.Error 'error-action-not-allowed', 'Not allowed', { method: 'deleteMessage', action: 'Delete_message' }
-
- blockDeleteInMinutes = RocketChat.settings.get 'Message_AllowDeleting_BlockDeleteInMinutes'
- if blockDeleteInMinutes? and blockDeleteInMinutes isnt 0
- msgTs = moment(originalMessage.ts) if originalMessage.ts?
- currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs?
- if currentTsDiff > blockDeleteInMinutes
- throw new Meteor.Error 'error-message-deleting-blocked', 'Message deleting is blocked', { method: 'deleteMessage' }
-
- RocketChat.deleteMessage(originalMessage, Meteor.user());
diff --git a/packages/rocketchat-lib/server/methods/deleteMessage.js b/packages/rocketchat-lib/server/methods/deleteMessage.js
new file mode 100644
index 0000000000000..829c77e45eae0
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/deleteMessage.js
@@ -0,0 +1,55 @@
+import moment from 'moment';
+
+Meteor.methods({
+ deleteMessage(message) {
+ check(message, Match.ObjectIncluding({
+ _id: String
+ }));
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'deleteMessage'
+ });
+ }
+ const originalMessage = RocketChat.models.Messages.findOneById(message._id, {
+ fields: {
+ u: 1,
+ rid: 1,
+ file: 1,
+ ts: 1
+ }
+ });
+ if (originalMessage == null) {
+ throw new Meteor.Error('error-action-not-allowed', 'Not allowed', {
+ method: 'deleteMessage',
+ action: 'Delete_message'
+ });
+ }
+ const forceDelete = RocketChat.authz.hasPermission(Meteor.userId(), 'force-delete-message', originalMessage.rid);
+ const hasPermission = RocketChat.authz.hasPermission(Meteor.userId(), 'delete-message', originalMessage.rid);
+ const deleteAllowed = RocketChat.settings.get('Message_AllowDeleting');
+ const deleteOwn = originalMessage && originalMessage.u && originalMessage.u._id === Meteor.userId();
+ if (!(hasPermission || (deleteAllowed && deleteOwn)) && !(forceDelete)) {
+ throw new Meteor.Error('error-action-not-allowed', 'Not allowed', {
+ method: 'deleteMessage',
+ action: 'Delete_message'
+ });
+ }
+ const blockDeleteInMinutes = RocketChat.settings.get('Message_AllowDeleting_BlockDeleteInMinutes');
+ if (blockDeleteInMinutes != null && blockDeleteInMinutes !== 0 && !forceDelete) {
+ if (originalMessage.ts == null) {
+ return;
+ }
+ const msgTs = moment(originalMessage.ts);
+ if (msgTs == null) {
+ return;
+ }
+ const currentTsDiff = moment().diff(msgTs, 'minutes');
+ if (currentTsDiff > blockDeleteInMinutes) {
+ throw new Meteor.Error('error-message-deleting-blocked', 'Message deleting is blocked', {
+ method: 'deleteMessage'
+ });
+ }
+ }
+ return RocketChat.deleteMessage(originalMessage, Meteor.user());
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/deleteUserOwnAccount.js b/packages/rocketchat-lib/server/methods/deleteUserOwnAccount.js
index ed7f361c4d3b3..33d0343b0892e 100644
--- a/packages/rocketchat-lib/server/methods/deleteUserOwnAccount.js
+++ b/packages/rocketchat-lib/server/methods/deleteUserOwnAccount.js
@@ -1,5 +1,7 @@
+import s from 'underscore.string';
+
Meteor.methods({
- deleteUserOwnAccount: function(password) {
+ deleteUserOwnAccount(password) {
check(password, String);
diff --git a/packages/rocketchat-lib/server/methods/filterATAllTag.js b/packages/rocketchat-lib/server/methods/filterATAllTag.js
index beb41870819c9..d4205e0c947ad 100644
--- a/packages/rocketchat-lib/server/methods/filterATAllTag.js
+++ b/packages/rocketchat-lib/server/methods/filterATAllTag.js
@@ -1,14 +1,16 @@
+import _ from 'underscore';
+
RocketChat.callbacks.add('beforeSaveMessage', function(message) {
// Test if the message mentions include @all.
if (message.mentions != null &&
_.pluck(message.mentions, '_id').some((item) => item === 'all')) {
- // Check if the user has permissions to use @all.
- if (!RocketChat.authz.hasPermission(message.u._id, 'mention-all')) {
+ // Check if the user has permissions to use @all in both global and room scopes.
+ if (!RocketChat.authz.hasPermission(message.u._id, 'mention-all') && !RocketChat.authz.hasPermission(message.u._id, 'mention-all', message.rid)) {
// Get the language of the user for the error notification.
- let language = RocketChat.models.Users.findOneById(message.u._id).language;
- let action = TAPi18n.__('Notify_all_in_this_room', {}, language);
+ const language = RocketChat.models.Users.findOneById(message.u._id).language;
+ const action = TAPi18n.__('Notify_all_in_this_room', {}, language);
// Add a notification to the chat, informing the user that this
// action is not allowed.
@@ -20,14 +22,10 @@ RocketChat.callbacks.add('beforeSaveMessage', function(message) {
});
// Also throw to stop propagation of 'sendMessage'.
- throw new Meteor.Error(
- 'error-action-not-allowed',
- 'Notify all in this room not allowed',
- {
- method: 'filterATAllTag',
- action: 'Notify_all_in_this_room'
- }
- );
+ throw new Meteor.Error('error-action-not-allowed', 'Notify all in this room not allowed', {
+ method: 'filterATAllTag',
+ action: 'Notify_all_in_this_room'
+ });
}
}
diff --git a/packages/rocketchat-lib/server/methods/filterATHereTag.js b/packages/rocketchat-lib/server/methods/filterATHereTag.js
new file mode 100644
index 0000000000000..c2df29e7d58ed
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/filterATHereTag.js
@@ -0,0 +1,34 @@
+import _ from 'underscore';
+
+RocketChat.callbacks.add('beforeSaveMessage', function(message) {
+ // Test if the message mentions include @here.
+ if (message.mentions != null &&
+ _.pluck(message.mentions, '_id').some((item) => item === 'here')) {
+
+ // Check if the user has permissions to use @here in both global and room scopes.
+ if (!RocketChat.authz.hasPermission(message.u._id, 'mention-here') && !RocketChat.authz.hasPermission(message.u._id, 'mention-here', message.rid)) {
+
+ // Get the language of the user for the error notification.
+ const language = RocketChat.models.Users.findOneById(message.u._id).language;
+ const action = TAPi18n.__('Notify_active_in_this_room', {}, language);
+
+ // Add a notification to the chat, informing the user that this
+ // action is not allowed.
+ RocketChat.Notifications.notifyUser(message.u._id, 'message', {
+ _id: Random.id(),
+ rid: message.rid,
+ ts: new Date,
+ msg: TAPi18n.__('error-action-not-allowed', { action }, language)
+ });
+
+ // Also throw to stop propagation of 'sendMessage'.
+ throw new Meteor.Error('error-action-not-allowed', 'Notify here in this room not allowed', {
+ method: 'filterATHereTag',
+ action: 'Notify_active_in_this_room'
+ });
+ }
+ }
+
+ return message;
+
+}, 1, 'filterATHereTag');
diff --git a/packages/rocketchat-lib/server/methods/filterBadWords.js b/packages/rocketchat-lib/server/methods/filterBadWords.js
index f52c5050129aa..e04dba42d2dbc 100644
--- a/packages/rocketchat-lib/server/methods/filterBadWords.js
+++ b/packages/rocketchat-lib/server/methods/filterBadWords.js
@@ -1,10 +1,10 @@
-var Filter = Npm.require('bad-words');
+import Filter from 'bad-words';
RocketChat.callbacks.add('beforeSaveMessage', function(message) {
if (RocketChat.settings.get('Message_AllowBadWordsFilter')) {
- var badWordsList = RocketChat.settings.get('Message_BadWordsFilterList');
- var options;
+ const badWordsList = RocketChat.settings.get('Message_BadWordsFilterList');
+ let options;
// Add words to the blacklist
if (!!badWordsList && badWordsList.length) {
@@ -12,7 +12,7 @@ RocketChat.callbacks.add('beforeSaveMessage', function(message) {
list: badWordsList.split(',')
};
}
- var filter = new Filter(options);
+ const filter = new Filter(options);
message.msg = filter.clean(message.msg);
}
diff --git a/packages/rocketchat-lib/server/methods/getChannelHistory.js b/packages/rocketchat-lib/server/methods/getChannelHistory.js
index 03958a40fae56..b3583cb253eae 100644
--- a/packages/rocketchat-lib/server/methods/getChannelHistory.js
+++ b/packages/rocketchat-lib/server/methods/getChannelHistory.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
Meteor.methods({
getChannelHistory({rid, latest, oldest, inclusive, count = 20, unreads}) {
check(rid, String);
@@ -49,8 +51,20 @@ Meteor.methods({
records = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestamps(rid, oldest, latest, options).fetch();
}
+ const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
+
const messages = _.map(records, (message) => {
message.starred = _.findWhere(message.starred, { _id: fromUserId });
+ if (message.u && message.u._id && UI_Use_Real_Name) {
+ const user = RocketChat.models.Users.findOneById(message.u._id);
+ message.u.name = user && user.name;
+ }
+ if (message.mentions && message.mentions.length && UI_Use_Real_Name) {
+ message.mentions.forEach((mention) => {
+ const user = RocketChat.models.Users.findOneById(mention._id);
+ mention.name = user && user.name;
+ });
+ }
return message;
});
@@ -68,14 +82,14 @@ Meteor.methods({
}
return {
- messages,
+ messages: messages || [],
firstUnread,
unreadNotLoaded
};
}
return {
- messages
+ messages: messages || []
};
}
});
diff --git a/packages/rocketchat-lib/server/methods/getRoomJoinCode.js b/packages/rocketchat-lib/server/methods/getRoomJoinCode.js
new file mode 100644
index 0000000000000..fe127a084e9ca
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/getRoomJoinCode.js
@@ -0,0 +1,17 @@
+Meteor.methods({
+ getRoomJoinCode(rid) {
+ check(rid, String);
+
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getJoinCode' });
+ }
+
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'view-join-code')) {
+ throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'getJoinCode' });
+ }
+
+ const [ room ] = RocketChat.models.Rooms.findById(rid).fetch();
+
+ return room && room.joinCode;
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/getRoomRoles.js b/packages/rocketchat-lib/server/methods/getRoomRoles.js
index 18ccaed6dbefd..4ea535ea62cdc 100644
--- a/packages/rocketchat-lib/server/methods/getRoomRoles.js
+++ b/packages/rocketchat-lib/server/methods/getRoomRoles.js
@@ -1,9 +1,10 @@
+import _ from 'underscore';
+
Meteor.methods({
getRoomRoles(rid) {
-
check(rid, String);
- if (!Meteor.userId()) {
+ if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });
}
@@ -20,7 +21,19 @@ Meteor.methods({
}
};
+ const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
+
const roles = RocketChat.models.Roles.find({ scope: 'Subscriptions', description: { $exists: 1, $ne: '' } }).fetch();
- return RocketChat.models.Subscriptions.findByRoomIdAndRoles(rid, _.pluck(roles, '_id'), options).fetch();
+ const subscriptions = RocketChat.models.Subscriptions.findByRoomIdAndRoles(rid, _.pluck(roles, '_id'), options).fetch();
+
+ if (!UI_Use_Real_Name) {
+ return subscriptions;
+ } else {
+ return subscriptions.map(subscription => {
+ const user = RocketChat.models.Users.findOneById(subscription.u._id);
+ subscription.u.name = user && user.name;
+ return subscription;
+ });
+ }
}
});
diff --git a/packages/rocketchat-lib/server/methods/getSingleMessage.js b/packages/rocketchat-lib/server/methods/getSingleMessage.js
new file mode 100644
index 0000000000000..72dc1a8516a3b
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/getSingleMessage.js
@@ -0,0 +1,19 @@
+Meteor.methods({
+ getSingleMessage(msgId) {
+ check(msgId, String);
+
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getSingleMessage' });
+ }
+
+ const msg = RocketChat.models.Messages.findOneById(msgId);
+
+ if (!msg && !msg.rid) {
+ return undefined;
+ }
+
+ Meteor.call('canAccessRoom', msg.rid, Meteor.userId());
+
+ return msg;
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/getUserRoles.js b/packages/rocketchat-lib/server/methods/getUserRoles.js
index f51e7c9e75885..db6d6a0d936ed 100644
--- a/packages/rocketchat-lib/server/methods/getUserRoles.js
+++ b/packages/rocketchat-lib/server/methods/getUserRoles.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
Meteor.methods({
getUserRoles() {
@@ -20,8 +22,8 @@ Meteor.methods({
// Security issue: we should not send all user's roles to all clients, only the 'public' roles
// We must remove all roles that are not part of the query from the returned users
- let users = RocketChat.models.Users.findUsersInRoles(roleIds, null, options).fetch();
- for (let user of users) {
+ const users = RocketChat.models.Users.findUsersInRoles(roleIds, null, options).fetch();
+ for (const user of users) {
user.roles = _.intersection(user.roles, roleIds);
}
return users;
diff --git a/packages/rocketchat-lib/server/methods/joinDefaultChannels.js b/packages/rocketchat-lib/server/methods/joinDefaultChannels.js
index 9090ecb1009cc..e5939f2f9813b 100644
--- a/packages/rocketchat-lib/server/methods/joinDefaultChannels.js
+++ b/packages/rocketchat-lib/server/methods/joinDefaultChannels.js
@@ -1,5 +1,7 @@
+// XXX
Meteor.methods({
- joinDefaultChannels(silenced) {
+ joinDefaultChannels(serverId, silenced) {
+ check(serverId, String);
check(silenced, Match.Optional(Boolean));
if (!Meteor.userId()) {
@@ -7,6 +9,6 @@ Meteor.methods({
}
this.unblock();
- return RocketChat.addUserToDefaultChannels(Meteor.user(), silenced);
+ return RocketChat.addUserToDefaultChannels(Meteor.user(), serverId, silenced);
}
});
diff --git a/packages/rocketchat-lib/server/methods/joinRoom.js b/packages/rocketchat-lib/server/methods/joinRoom.js
index c95d5a2df3001..d92fb6da8617e 100644
--- a/packages/rocketchat-lib/server/methods/joinRoom.js
+++ b/packages/rocketchat-lib/server/methods/joinRoom.js
@@ -1,6 +1,5 @@
Meteor.methods({
joinRoom(rid, code) {
-
check(rid, String);
if (!Meteor.userId()) {
@@ -13,14 +12,24 @@ Meteor.methods({
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'joinRoom' });
}
- if ((room.t !== 'c') || (RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') !== true)) {
- throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'joinRoom' });
- }
+ // TODO we should have a 'beforeJoinRoom' call back so external services can do their own validations
+ const user = Meteor.user();
+ if (room.tokenpass && user && user.services && user.services.tokenpass) {
+ const balances = RocketChat.updateUserTokenpassBalances(user);
+
+ if (!RocketChat.Tokenpass.validateAccess(room.tokenpass, balances)) {
+ throw new Meteor.Error('error-not-allowed', 'Token required', { method: 'joinRoom' });
+ }
+ } else {
+ if ((room.t !== 'c') || (RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') !== true)) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'joinRoom' });
+ }
- if ((room.joinCodeRequired === true) && (code !== room.joinCode)) {
- throw new Meteor.Error('error-code-invalid', 'Invalid Code', { method: 'joinRoom' });
+ if ((room.joinCodeRequired === true) && (code !== room.joinCode) && !RocketChat.authz.hasPermission(Meteor.userId(), 'join-without-join-code')) {
+ throw new Meteor.Error('error-code-invalid', 'Invalid Room Password', { method: 'joinRoom' });
+ }
}
- return RocketChat.addUserToRoom(rid, Meteor.user());
+ return RocketChat.addUserToRoom(rid, user);
}
});
diff --git a/packages/rocketchat-lib/server/methods/leaveRoom.js b/packages/rocketchat-lib/server/methods/leaveRoom.js
index 4ac4278d88f66..603e785acdbea 100644
--- a/packages/rocketchat-lib/server/methods/leaveRoom.js
+++ b/packages/rocketchat-lib/server/methods/leaveRoom.js
@@ -22,7 +22,7 @@ Meteor.methods({
// If user is room owner, check if there are other owners. If there isn't anyone else, warn user to set a new owner.
if (RocketChat.authz.hasRole(user._id, 'owner', room._id)) {
- let numOwners = RocketChat.authz.getUsersInRole('owner', room._id).fetch().length;
+ const numOwners = RocketChat.authz.getUsersInRole('owner', room._id).fetch().length;
if (numOwners === 1) {
throw new Meteor.Error('error-you-are-last-owner', 'You are the last owner. Please set new owner before leaving the room.', { method: 'leaveRoom' });
}
diff --git a/packages/rocketchat-lib/server/methods/removeOAuthService.js b/packages/rocketchat-lib/server/methods/removeOAuthService.js
index 0520bb84b8bb4..6231eb22218b0 100644
--- a/packages/rocketchat-lib/server/methods/removeOAuthService.js
+++ b/packages/rocketchat-lib/server/methods/removeOAuthService.js
@@ -1,3 +1,5 @@
+import s from 'underscore.string';
+
Meteor.methods({
removeOAuthService(name) {
@@ -13,20 +15,21 @@ Meteor.methods({
name = name.toLowerCase().replace(/[^a-z0-9_]/g, '');
name = s.capitalize(name);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-url`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-token_path`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-identity_path`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-authorize_path`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-scope`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-token_sent_via`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-id`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-secret`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-button_label_text`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-button_label_color`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-button_color`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-login_style`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-username_field`);
- RocketChat.settings.removeById(`Accounts_OAuth_Custom-${name}-merge_users`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-url`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-token_path`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-identity_path`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-authorize_path`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-scope`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-token_sent_via`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-identity_token_sent_via`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-id`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-secret`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-button_label_text`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-button_label_color`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-button_color`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-login_style`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-username_field`);
+ RocketChat.settings.removeById(`Accounts_OAuth_Custom-${ name }-merge_users`);
}
});
diff --git a/packages/rocketchat-lib/server/methods/restartServer.js b/packages/rocketchat-lib/server/methods/restartServer.js
index f6e72b8c6410d..41d617d2d4344 100644
--- a/packages/rocketchat-lib/server/methods/restartServer.js
+++ b/packages/rocketchat-lib/server/methods/restartServer.js
@@ -8,8 +8,13 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'restart_server' });
}
- Meteor.setTimeout(() => process.exit(1)
- , 2000);
+ Meteor.setTimeout(() => {
+ Meteor.setTimeout(() => {
+ console.warn('Call to process.exit() timed out, aborting.');
+ process.abort();
+ }, 1000);
+ process.exit(1);
+ }, 1000);
return {
message: 'The_server_will_restart_in_s_seconds',
diff --git a/packages/rocketchat-lib/server/methods/robotMethods.coffee b/packages/rocketchat-lib/server/methods/robotMethods.coffee
deleted file mode 100644
index 593a915416ab4..0000000000000
--- a/packages/rocketchat-lib/server/methods/robotMethods.coffee
+++ /dev/null
@@ -1,21 +0,0 @@
-Meteor.methods
- 'robot.modelCall': (model, method, args) ->
-
- check model, String
- check method, String
-
- unless Meteor.userId()
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'robot.modelCall' }
-
- unless RocketChat.authz.hasRole Meteor.userId(), 'robot'
- throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'robot.modelCall' }
-
- unless _.isFunction RocketChat.models[model]?[method]
- throw new Meteor.Error 'error-invalid-method', 'Invalid method', { method: 'robot.modelCall' }
-
- call = RocketChat.models[model][method].apply(RocketChat.models[model], args)
-
- if call?.fetch?()?
- return call.fetch()
- else
- return call
diff --git a/packages/rocketchat-lib/server/methods/robotMethods.js b/packages/rocketchat-lib/server/methods/robotMethods.js
new file mode 100644
index 0000000000000..cb81c24d04a41
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/robotMethods.js
@@ -0,0 +1,27 @@
+import _ from 'underscore';
+
+Meteor.methods({
+ 'robot.modelCall'(model, method, args) {
+ check(model, String);
+ check(method, String);
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'robot.modelCall'
+ });
+ }
+ if (!RocketChat.authz.hasRole(Meteor.userId(), 'robot')) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', {
+ method: 'robot.modelCall'
+ });
+ }
+ const m = RocketChat.models[model];
+
+ if (!m || !_.isFunction(m[method])) {
+ throw new Meteor.Error('error-invalid-method', 'Invalid method', {
+ method: 'robot.modelCall'
+ });
+ }
+ const cursor = RocketChat.models[model][method].apply(RocketChat.models[model], args);
+ return cursor && cursor.fetch ? cursor.fetch() : cursor;
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/saveSetting.js b/packages/rocketchat-lib/server/methods/saveSetting.js
index f938092260701..963876864e317 100644
--- a/packages/rocketchat-lib/server/methods/saveSetting.js
+++ b/packages/rocketchat-lib/server/methods/saveSetting.js
@@ -1,5 +1,7 @@
+/* eslint new-cap: 0 */
+
Meteor.methods({
- saveSetting: function(_id, value, editor) {
+ saveSetting(_id, value, editor) {
if (Meteor.userId() === null) {
throw new Meteor.Error('error-action-not-allowed', 'Editing settings is not allowed', {
method: 'saveSetting'
@@ -20,7 +22,7 @@ Meteor.methods({
//Verify the value is what it should be
switch (setting.type) {
case 'roomPick':
- check(value, [Object]);
+ check(value, Match.OneOf([Object], ''));
break;
case 'boolean':
check(value, Boolean);
diff --git a/packages/rocketchat-lib/server/methods/sendInvitationEmail.coffee b/packages/rocketchat-lib/server/methods/sendInvitationEmail.coffee
deleted file mode 100644
index 16a7f0396ec20..0000000000000
--- a/packages/rocketchat-lib/server/methods/sendInvitationEmail.coffee
+++ /dev/null
@@ -1,42 +0,0 @@
-Meteor.methods
- sendInvitationEmail: (emails) ->
-
- check emails, [String]
-
- if not Meteor.userId()
- throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'sendInvitationEmail' }
-
- unless RocketChat.authz.hasRole(Meteor.userId(), 'admin')
- throw new Meteor.Error 'error-not-allowed', "Not allowed", { method: 'sendInvitationEmail' }
-
- rfcMailPattern = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
- validEmails = _.compact _.map emails, (email) -> return email if rfcMailPattern.test email
-
- header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || "")
- footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || "")
-
- if RocketChat.settings.get('Invitation_Customized')
- subject = RocketChat.settings.get('Invitation_Subject')
- html = RocketChat.settings.get('Invitation_HTML')
- else
- subject = TAPi18n.__('Invitation_Subject_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
- html = TAPi18n.__('Invitation_HTML_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
-
- subject = RocketChat.placeholders.replace(subject);
-
- for email in validEmails
- @unblock()
-
- html = RocketChat.placeholders.replace(html, { email: email });
-
- try
- Email.send
- to: email
- from: RocketChat.settings.get 'From_Email'
- subject: subject
- html: header + html + footer
- catch error
- throw new Meteor.Error 'error-email-send-failed', 'Error trying to send email: ' + error.message, { method: 'sendInvitationEmail', message: error.message }
-
-
- return validEmails
diff --git a/packages/rocketchat-lib/server/methods/sendInvitationEmail.js b/packages/rocketchat-lib/server/methods/sendInvitationEmail.js
new file mode 100644
index 0000000000000..72b7a8fdddef6
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/sendInvitationEmail.js
@@ -0,0 +1,61 @@
+import _ from 'underscore';
+
+Meteor.methods({
+ sendInvitationEmail(emails) {
+ check(emails, [String]);
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'sendInvitationEmail'
+ });
+ }
+ if (!RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', {
+ method: 'sendInvitationEmail'
+ });
+ }
+ const rfcMailPattern = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
+ const validEmails = _.compact(_.map(emails, function(email) {
+ if (rfcMailPattern.test(email)) {
+ return email;
+ }
+ }));
+ const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
+ const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
+ let html;
+ let subject;
+ const user = Meteor.user();
+ const lng = user.language || RocketChat.settings.get('language') || 'en';
+ if (RocketChat.settings.get('Invitation_Customized')) {
+ subject = RocketChat.settings.get('Invitation_Subject');
+ html = RocketChat.settings.get('Invitation_HTML');
+ } else {
+ subject = TAPi18n.__('Invitation_Subject_Default', {
+ lng
+ });
+ html = TAPi18n.__('Invitation_HTML_Default', {
+ lng
+ });
+ }
+ subject = RocketChat.placeholders.replace(subject);
+ validEmails.forEach(email => {
+ this.unblock();
+ html = RocketChat.placeholders.replace(html, {
+ email
+ });
+ try {
+ Email.send({
+ to: email,
+ from: RocketChat.settings.get('From_Email'),
+ subject,
+ html: header + html + footer
+ });
+ } catch ({message}) {
+ throw new Meteor.Error('error-email-send-failed', `Error trying to send email: ${ message }`, {
+ method: 'sendInvitationEmail',
+ message
+ });
+ }
+ });
+ return validEmails;
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/sendMessage.coffee b/packages/rocketchat-lib/server/methods/sendMessage.coffee
deleted file mode 100644
index 2d121dc4ed221..0000000000000
--- a/packages/rocketchat-lib/server/methods/sendMessage.coffee
+++ /dev/null
@@ -1,64 +0,0 @@
-import moment from 'moment'
-
-Meteor.methods
- sendMessage: (message) ->
-
- check message, Object
-
- if not Meteor.userId()
- throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'sendMessage' })
-
- if message.ts
- tsDiff = Math.abs(moment(message.ts).diff())
- if tsDiff > 60000
- throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', { method: 'sendMessage', message_ts: message.ts, server_ts: new Date().getTime() })
- else if tsDiff > 10000
- message.ts = new Date()
- else
- message.ts = new Date()
-
- if message.msg?.length > RocketChat.settings.get('Message_MaxAllowedSize')
- throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', { method: 'sendMessage' })
-
- user = RocketChat.models.Users.findOneById Meteor.userId(), fields: username: 1, name: 1
-
- room = Meteor.call 'canAccessRoom', message.rid, user._id
-
- if not room
- return false
-
- subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId());
- if subscription and (subscription.blocked or subscription.blocker)
- RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
- _id: Random.id()
- rid: room._id
- ts: new Date
- msg: TAPi18n.__('room_is_blocked', {}, user.language)
- }
- return false
-
- if user.username in (room.muted or [])
- RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
- _id: Random.id()
- rid: room._id
- ts: new Date
- msg: TAPi18n.__('You_have_been_muted', {}, user.language)
- }
- return false
-
- message.alias = user.name if not message.alias? and RocketChat.settings.get 'Message_SetNameToAliasEnabled'
- if Meteor.settings.public.sandstorm
- message.sandstormSessionId = this.connection.sandstormSessionId()
-
- RocketChat.sendMessage user, message, room
- RocketChat.metrics.messagesSent.inc()
-
-# Limit a user, who does not have the "bot" role, to sending 5 msgs/second
-DDPRateLimiter.addRule
- type: 'method'
- name: 'sendMessage'
- userId: (userId) ->
- user = RocketChat.models.Users.findOneById(userId)
- return true if not user?.roles
- return 'bot' not in user.roles
-, 5, 1000
diff --git a/packages/rocketchat-lib/server/methods/sendMessage.js b/packages/rocketchat-lib/server/methods/sendMessage.js
new file mode 100644
index 0000000000000..03e4272efaf93
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/sendMessage.js
@@ -0,0 +1,84 @@
+import moment from 'moment';
+
+Meteor.methods({
+ sendMessage(message) {
+ check(message, Object);
+
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'sendMessage'
+ });
+ }
+
+ if (message.ts) {
+ const tsDiff = Math.abs(moment(message.ts).diff());
+ if (tsDiff > 60000) {
+ throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', {
+ method: 'sendMessage',
+ message_ts: message.ts,
+ server_ts: new Date().getTime()
+ });
+ } else if (tsDiff > 10000) {
+ message.ts = new Date();
+ }
+ } else {
+ message.ts = new Date();
+ }
+
+ if (message.msg && message.msg.length > RocketChat.settings.get('Message_MaxAllowedSize')) {
+ throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', {
+ method: 'sendMessage'
+ });
+ }
+
+ const user = RocketChat.models.Users.findOneById(Meteor.userId(), {
+ fields: {
+ username: 1,
+ name: 1
+ }
+ });
+
+ const room = Meteor.call('canAccessRoom', message.rid, user._id);
+ if (!room) {
+ return false;
+ }
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId());
+ if (subscription && subscription.blocked || subscription.blocker) {
+ RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ _id: Random.id(),
+ rid: room._id,
+ ts: new Date,
+ msg: TAPi18n.__('room_is_blocked', {}, user.language)
+ });
+ return false;
+ }
+
+ if ((room.muted||[]).includes(user.username)) {
+ RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ _id: Random.id(),
+ rid: room._id,
+ ts: new Date,
+ msg: TAPi18n.__('You_have_been_muted', {}, user.language)
+ });
+ return false;
+ }
+
+ if (message.alias == null && RocketChat.settings.get('Message_SetNameToAliasEnabled')) {
+ message.alias = user.name;
+ }
+
+ if (Meteor.settings['public'].sandstorm) {
+ message.sandstormSessionId = this.connection.sandstormSessionId();
+ }
+
+ RocketChat.metrics.messagesSent.inc(); // TODO This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736
+ return RocketChat.sendMessage(user, message, room);
+ }
+});
+// Limit a user, who does not have the "bot" role, to sending 5 msgs/second
+RocketChat.RateLimiter.limitMethod('sendMessage', 5, 1000, {
+ userId(userId) {
+ return !RocketChat.authz.hasPermission(userId, 'send-many-messages');
+ }
+});
diff --git a/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.coffee b/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.coffee
deleted file mode 100644
index 10759ecdea5fa..0000000000000
--- a/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.coffee
+++ /dev/null
@@ -1,37 +0,0 @@
-Meteor.methods
- sendSMTPTestEmail: ->
- if not Meteor.userId()
- throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'sendSMTPTestEmail' }
-
- user = Meteor.user()
- unless user.emails?[0]?.address
- throw new Meteor.Error 'error-invalid-email', "Invalid email", { method: 'sendSMTPTestEmail' }
-
- this.unblock()
-
- header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
- footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
-
- console.log 'Sending test email to ' + user.emails[0].address
-
- try
- Email.send
- to: user.emails[0].address
- from: RocketChat.settings.get('From_Email')
- subject: "SMTP Test Email"
- html: header + "You have successfully sent an email
" + footer
- catch error
- throw new Meteor.Error 'error-email-send-failed', 'Error trying to send email: ' + error.message, { method: 'sendSMTPTestEmail', message: error.message }
-
- return {
- message: "Your_mail_was_sent_to_s"
- params: [user.emails[0].address]
- }
-
-# Limit a user to sending 1 test mail/second
-DDPRateLimiter.addRule
- type: 'method'
- name: 'sendSMTPTestEmail'
- userId: (userId) ->
- return true
-, 1, 1000
diff --git a/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.js b/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.js
new file mode 100644
index 0000000000000..df861fd6a3402
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/sendSMTPTestEmail.js
@@ -0,0 +1,44 @@
+Meteor.methods({
+ sendSMTPTestEmail() {
+ if (!Meteor.userId()) {
+ throw new Meteor.Error('error-invalid-user', 'Invalid user', {
+ method: 'sendSMTPTestEmail'
+ });
+ }
+ const user = Meteor.user();
+ if (!user.emails && !user.emails[0] && user.emails[0].address) {
+ throw new Meteor.Error('error-invalid-email', 'Invalid email', {
+ method: 'sendSMTPTestEmail'
+ });
+ }
+ this.unblock();
+ const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
+ const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
+ console.log(`Sending test email to ${ user.emails[0].address }`);
+ try {
+ Email.send({
+ to: user.emails[0].address,
+ from: RocketChat.settings.get('From_Email'),
+ subject: 'SMTP Test Email',
+ html: `${ header }You have successfully sent an email
${ footer }`
+ });
+ } catch ({message}) {
+ throw new Meteor.Error('error-email-send-failed', `Error trying to send email: ${ message }`, {
+ method: 'sendSMTPTestEmail',
+ message
+ });
+ }
+ return {
+ message: 'Your_mail_was_sent_to_s',
+ params: [user.emails[0].address]
+ };
+ }
+});
+
+DDPRateLimiter.addRule({
+ type: 'method',
+ name: 'sendSMTPTestEmail',
+ userId() {
+ return true;
+ }
+}, 1, 1000);
diff --git a/packages/rocketchat-lib/server/methods/setEmail.js b/packages/rocketchat-lib/server/methods/setEmail.js
index e71db53808d4e..4e5d39681a4cd 100644
--- a/packages/rocketchat-lib/server/methods/setEmail.js
+++ b/packages/rocketchat-lib/server/methods/setEmail.js
@@ -1,5 +1,5 @@
Meteor.methods({
- setEmail: function(email) {
+ setEmail(email) {
check (email, String);
@@ -26,5 +26,5 @@ Meteor.methods({
});
RocketChat.RateLimiter.limitMethod('setEmail', 1, 1000, {
- userId: function(/*userId*/) { return true; }
+ userId(/*userId*/) { return true; }
});
diff --git a/packages/rocketchat-lib/server/methods/setRealName.js b/packages/rocketchat-lib/server/methods/setRealName.js
index 16f7068f9ea65..4bfd7e9d6e864 100644
--- a/packages/rocketchat-lib/server/methods/setRealName.js
+++ b/packages/rocketchat-lib/server/methods/setRealName.js
@@ -7,20 +7,18 @@ Meteor.methods({
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setRealName' });
}
- const user = Meteor.user();
-
- if (user.name === name) {
- return name;
- }
-
- if (_.trim(name)) {
- name = _.trim(name);
+ if (!RocketChat.settings.get('Accounts_AllowRealNameChange')) {
+ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setRealName' });
}
- if (!RocketChat.models.Users.setName(Meteor.userId(), name)) {
+ if (!RocketChat.setRealName(Meteor.userId(), name)) {
throw new Meteor.Error('error-could-not-change-name', 'Could not change name', { method: 'setRealName' });
}
return name;
}
});
+
+RocketChat.RateLimiter.limitMethod('setRealName', 1, 1000, {
+ userId: () => true
+});
diff --git a/packages/rocketchat-lib/server/methods/setUsername.js b/packages/rocketchat-lib/server/methods/setUsername.js
index c61b74f16d4cd..4fad4ac2b16b9 100644
--- a/packages/rocketchat-lib/server/methods/setUsername.js
+++ b/packages/rocketchat-lib/server/methods/setUsername.js
@@ -1,3 +1,5 @@
+import _ from 'underscore';
+
Meteor.methods({
setUsername(username, param = {}) {
const { joinDefaultChannelsSilenced } = param;
@@ -13,29 +15,23 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setUsername' });
}
- if (user.username === username) {
+ if (user.username === username || (user.username && user.username.toLowerCase() === username.toLowerCase())) {
return username;
}
let nameValidation;
try {
- nameValidation = new RegExp(`^${RocketChat.settings.get('UTF8_Names_Validation')}$`);
+ nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
} catch (error) {
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
}
if (!nameValidation.test(username)) {
- throw new Meteor.Error('username-invalid', `${_.escape(username)} is not a valid username, use only letters, numbers, dots, hyphens and underscores`);
+ throw new Meteor.Error('username-invalid', `${ _.escape(username) } is not a valid username, use only letters, numbers, dots, hyphens and underscores`);
}
- if (user.username !== undefined) {
- if (!username.toLowerCase() === user.username.toLowerCase()) {
- if (!RocketChat.checkUsernameAvailability(username)) {
- throw new Meteor.Error('error-field-unavailable', `${_.escape(username)} is already in use :(`, { method: 'setUsername', field: username });
- }
- }
- } else if (!RocketChat.checkUsernameAvailability(username)) {
- throw new Meteor.Error('error-field-unavailable', `${_.escape(username)} is already in use :(`, { method: 'setUsername', field: username });
+ if (!RocketChat.checkUsernameAvailability(username)) {
+ throw new Meteor.Error('error-field-unavailable', `${ _.escape(username) } is already in use :(`, { method: 'setUsername', field: username });
}
if (!RocketChat.setUsername(user._id, username)) {
@@ -44,6 +40,9 @@ Meteor.methods({
if (!user.username) {
Meteor.runAsUser(user._id, () => Meteor.call('joinDefaultChannels', joinDefaultChannelsSilenced));
+ Meteor.defer(function() {
+ return RocketChat.callbacks.run('afterCreateUser', RocketChat.models.Users.findOneById(user._id));
+ });
}
return username;
diff --git a/packages/rocketchat-lib/server/methods/updateMessage.js b/packages/rocketchat-lib/server/methods/updateMessage.js
index f2c983ef00fd8..f279bb353d674 100644
--- a/packages/rocketchat-lib/server/methods/updateMessage.js
+++ b/packages/rocketchat-lib/server/methods/updateMessage.js
@@ -25,14 +25,29 @@ Meteor.methods({
const blockEditInMinutes = RocketChat.settings.get('Message_AllowEditing_BlockEditInMinutes');
if (Match.test(blockEditInMinutes, Number) && blockEditInMinutes !== 0) {
- let currentTsDiff, msgTs;
- if (Match.test(originalMessage.ts, Number)) { msgTs = moment(originalMessage.ts); }
- if (msgTs) { currentTsDiff = moment().diff(msgTs, 'minutes'); }
+ let currentTsDiff;
+ let msgTs;
+
+ if (Match.test(originalMessage.ts, Number)) {
+ msgTs = moment(originalMessage.ts);
+ }
+ if (msgTs) {
+ currentTsDiff = moment().diff(msgTs, 'minutes');
+ }
if (currentTsDiff > blockEditInMinutes) {
throw new Meteor.Error('error-message-editing-blocked', 'Message editing is blocked', { method: 'updateMessage' });
}
}
+ // It is possible to have an empty array as the attachments property, so ensure both things exist
+ if (originalMessage.attachments && originalMessage.attachments.length > 0 && originalMessage.attachments[0].description !== undefined) {
+ message.attachments = originalMessage.attachments;
+ message.attachments[0].description = message.msg;
+ message.msg = originalMessage.msg;
+ }
+
+ message.u = originalMessage.u;
+
return RocketChat.updateMessage(message, Meteor.user());
}
});
diff --git a/packages/rocketchat-lib/server/models/Avatars.js b/packages/rocketchat-lib/server/models/Avatars.js
new file mode 100644
index 0000000000000..0b82ed5977193
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Avatars.js
@@ -0,0 +1,113 @@
+/* globals InstanceStatus */
+import _ from 'underscore';
+import s from 'underscore.string';
+
+RocketChat.models.Avatars = new class extends RocketChat.models._Base {
+ constructor() {
+ super('avatars');
+
+ this.model.before.insert((userId, doc) => {
+ doc.instanceId = InstanceStatus.id();
+ });
+
+ this.tryEnsureIndex({ name: 1 });
+ }
+
+ insertAvatarFileInit(name, userId, store, file, extra) {
+ const fileData = {
+ _id: name,
+ name,
+ userId,
+ store,
+ complete: false,
+ uploading: true,
+ progress: 0,
+ extension: s.strRightBack(file.name, '.'),
+ uploadedAt: new Date()
+ };
+
+ _.extend(fileData, file, extra);
+
+ return this.insertOrUpsert(fileData);
+ }
+
+ updateFileComplete(fileId, userId, file) {
+ if (!fileId) {
+ return;
+ }
+
+ const filter = {
+ _id: fileId,
+ userId
+ };
+
+ const update = {
+ $set: {
+ complete: true,
+ uploading: false,
+ progress: 1
+ }
+ };
+
+ update.$set = _.extend(file, update.$set);
+
+ if (this.model.direct && this.model.direct.update) {
+ return this.model.direct.update(filter, update);
+ } else {
+ return this.update(filter, update);
+ }
+ }
+
+ findOneByName(name) {
+ return this.findOne({ name });
+ }
+
+ updateFileNameById(fileId, name) {
+ const filter = { _id: fileId };
+ const update = {
+ $set: {
+ name
+ }
+ };
+ if (this.model.direct && this.model.direct.update) {
+ return this.model.direct.update(filter, update);
+ } else {
+ return this.update(filter, update);
+ }
+ }
+
+ // @TODO deprecated
+ updateFileCompleteByNameAndUserId(name, userId, url) {
+ if (!name) {
+ return;
+ }
+
+ const filter = {
+ name,
+ userId
+ };
+
+ const update = {
+ $set: {
+ complete: true,
+ uploading: false,
+ progress: 1,
+ url
+ }
+ };
+
+ if (this.model.direct && this.model.direct.update) {
+ return this.model.direct.update(filter, update);
+ } else {
+ return this.update(filter, update);
+ }
+ }
+
+ deleteFile(fileId) {
+ if (this.model.direct && this.model.direct.remove) {
+ return this.model.direct.remove({ _id: fileId });
+ } else {
+ return this.remove({ _id: fileId });
+ }
+ }
+};
diff --git a/packages/rocketchat-lib/server/models/Messages.coffee b/packages/rocketchat-lib/server/models/Messages.coffee
deleted file mode 100644
index 363fd2cac7a49..0000000000000
--- a/packages/rocketchat-lib/server/models/Messages.coffee
+++ /dev/null
@@ -1,461 +0,0 @@
-RocketChat.models.Messages = new class extends RocketChat.models._Base
- constructor: ->
- super('message')
-
- @tryEnsureIndex { 'rid': 1, 'ts': 1 }
- @tryEnsureIndex { 'ts': 1 }
- @tryEnsureIndex { 'u._id': 1 }
- @tryEnsureIndex { 'editedAt': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'editedBy._id': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'rid': 1, 't': 1, 'u._id': 1 }
- @tryEnsureIndex { 'expireAt': 1 }, { expireAfterSeconds: 0 }
- @tryEnsureIndex { 'msg': 'text' }
- @tryEnsureIndex { 'file._id': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'mentions.username': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'pinned': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'snippeted': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'location': '2dsphere' }
- @tryEnsureIndex { 'slackBotId': 1, 'slackTs': 1 }, { sparse: 1 }
-
- # FIND
- findByMention: (username, options) ->
- query =
- "mentions.username": username
-
- return @find query, options
-
- findVisibleByMentionAndRoomId: (username, rid, options) ->
- query =
- _hidden: { $ne: true }
- "mentions.username": username
- "rid": rid
-
- return @find query, options
-
- findVisibleByRoomId: (roomId, options) ->
- query =
- _hidden:
- $ne: true
-
- rid: roomId
-
- return @find query, options
-
- findVisibleByRoomIdNotContainingTypes: (roomId, types, options) ->
- query =
- _hidden:
- $ne: true
-
- rid: roomId
-
- if Match.test(types, [String]) and types.length > 0
- query.t =
- $nin: types
-
- return @find query, options
-
- findInvisibleByRoomId: (roomId, options) ->
- query =
- _hidden: true
- rid: roomId
-
- return @find query, options
-
- findVisibleByRoomIdAfterTimestamp: (roomId, timestamp, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $gt: timestamp
-
- return @find query, options
-
- findVisibleByRoomIdBeforeTimestamp: (roomId, timestamp, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $lt: timestamp
-
- return @find query, options
-
- findVisibleByRoomIdBeforeTimestampInclusive: (roomId, timestamp, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $lte: timestamp
-
- return @find query, options
-
- findVisibleByRoomIdBetweenTimestamps: (roomId, afterTimestamp, beforeTimestamp, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $gt: afterTimestamp
- $lt: beforeTimestamp
-
- return @find query, options
-
- findVisibleByRoomIdBetweenTimestampsInclusive: (roomId, afterTimestamp, beforeTimestamp, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $gte: afterTimestamp
- $lte: beforeTimestamp
-
- return @find query, options
-
- findVisibleByRoomIdBeforeTimestampNotContainingTypes: (roomId, timestamp, types, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $lt: timestamp
-
- if Match.test(types, [String]) and types.length > 0
- query.t =
- $nin: types
-
- return @find query, options
-
- findVisibleByRoomIdBetweenTimestampsNotContainingTypes: (roomId, afterTimestamp, beforeTimestamp, types, options) ->
- query =
- _hidden:
- $ne: true
- rid: roomId
- ts:
- $gt: afterTimestamp
- $lt: beforeTimestamp
-
- if Match.test(types, [String]) and types.length > 0
- query.t =
- $nin: types
-
- return @find query, options
-
- findVisibleCreatedOrEditedAfterTimestamp: (timestamp, options) ->
- query =
- _hidden: { $ne: true }
- $or: [
- ts:
- $gt: timestamp
- ,
- 'editedAt':
- $gt: timestamp
- ]
-
- return @find query, options
-
- findStarredByUserAtRoom: (userId, roomId, options) ->
- query =
- _hidden: { $ne: true }
- 'starred._id': userId
- rid: roomId
-
- return @find query, options
-
- findPinnedByRoom: (roomId, options) ->
- query =
- t: { $ne: 'rm' }
- _hidden: { $ne: true }
- pinned: true
- rid: roomId
-
- return @find query, options
-
- findSnippetedByRoom: (roomId, options) ->
- query =
- _hidden: { $ne: true }
- snippeted: true
- rid: roomId
-
- return @find query, options
-
- getLastTimestamp: (options = {}) ->
- query = { ts: { $exists: 1 } }
- options.sort = { ts: -1 }
- options.limit = 1
-
- return @find(query, options)?.fetch?()?[0]?.ts
-
- findByRoomIdAndMessageIds: (rid, messageIds, options) ->
- query =
- rid: rid
- _id:
- $in: messageIds
-
- return @find query, options
-
- findOneBySlackBotIdAndSlackTs: (slackBotId, slackTs) ->
- query =
- slackBotId: slackBotId
- slackTs: slackTs
-
- return @findOne query
-
- findOneBySlackTs: (slackTs) ->
- query =
- slackTs: slackTs
-
- return @findOne query
-
- cloneAndSaveAsHistoryById: (_id) ->
- me = RocketChat.models.Users.findOneById Meteor.userId()
- record = @findOneById _id
- record._hidden = true
- record.parent = record._id
- record.editedAt = new Date
- record.editedBy =
- _id: Meteor.userId()
- username: me.username
- delete record._id
- return @insert record
-
- # UPDATE
- setHiddenById: (_id, hidden=true) ->
- query =
- _id: _id
-
- update =
- $set:
- _hidden: hidden
-
- return @update query, update
-
- setAsDeletedByIdAndUser: (_id, user) ->
- query =
- _id: _id
-
- update =
- $set:
- msg: ''
- t: 'rm'
- urls: []
- mentions: []
- attachments: []
- reactions: []
- editedAt: new Date()
- editedBy:
- _id: user._id
- username: user.username
-
- return @update query, update
-
- setPinnedByIdAndUserId: (_id, pinnedBy, pinned=true, pinnedAt=0) ->
- query =
- _id: _id
-
- update =
- $set:
- pinned: pinned
- pinnedAt: pinnedAt || new Date
- pinnedBy: pinnedBy
-
- return @update query, update
-
- setSnippetedByIdAndUserId: (message, snippetName, snippetedBy, snippeted=true, snippetedAt=0) ->
- query =
- _id: message._id
-
- msg = "```" + message.msg + "```"
-
- update =
- $set:
- msg: msg
- snippeted: snippeted
- snippetedAt: snippetedAt || new Date
- snippetedBy: snippetedBy
- snippetName: snippetName
-
- return @update query, update
-
- setUrlsById: (_id, urls) ->
- query =
- _id: _id
-
- update =
- $set:
- urls: urls
-
- return @update query, update
-
- updateAllUsernamesByUserId: (userId, username) ->
- query =
- 'u._id': userId
-
- update =
- $set:
- "u.username": username
-
- return @update query, update, { multi: true }
-
- updateUsernameOfEditByUserId: (userId, username) ->
- query =
- 'editedBy._id': userId
-
- update =
- $set:
- "editedBy.username": username
-
- return @update query, update, { multi: true }
-
- updateUsernameAndMessageOfMentionByIdAndOldUsername: (_id, oldUsername, newUsername, newMessage) ->
- query =
- _id: _id
- "mentions.username": oldUsername
-
- update =
- $set:
- "mentions.$.username": newUsername
- "msg": newMessage
-
- return @update query, update
-
- updateUserStarById: (_id, userId, starred) ->
- query =
- _id: _id
-
- if starred
- update =
- $addToSet:
- starred: { _id: userId }
- else
- update =
- $pull:
- starred: { _id: Meteor.userId() }
-
- return @update query, update
-
- upgradeEtsToEditAt: ->
- query =
- ets: { $exists: 1 }
-
- update =
- $rename:
- "ets": "editedAt"
-
- return @update query, update, { multi: true }
-
- setMessageAttachments: (_id, attachments) ->
- query =
- _id: _id
-
- update =
- $set:
- attachments: attachments
-
- return @update query, update
-
- setSlackBotIdAndSlackTs: (_id, slackBotId, slackTs) ->
- query =
- _id: _id
-
- update =
- $set:
- slackBotId: slackBotId
- slackTs: slackTs
-
- return @update query, update
-
-
- # INSERT
- createWithTypeRoomIdMessageAndUser: (type, roomId, message, user, extraData) ->
- room = RocketChat.models.Rooms.findOneById roomId, { fields: { sysMes: 1 }}
- if room?.sysMes is false
- return
- record =
- t: type
- rid: roomId
- ts: new Date
- msg: message
- u:
- _id: user._id
- username: user.username
- groupable: false
-
- _.extend record, extraData
-
- record._id = @insertOrUpsert record
- return record
-
- createUserJoinWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'uj', roomId, message, user, extraData
-
- createUserLeaveWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'ul', roomId, message, user, extraData
-
- createUserRemovedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'ru', roomId, message, user, extraData
-
- createUserAddedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'au', roomId, message, user, extraData
-
- createCommandWithRoomIdAndUser: (command, roomId, user, extraData) ->
- return @createWithTypeRoomIdMessageAndUser 'command', roomId, command, user, extraData
-
- createUserMutedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'user-muted', roomId, message, user, extraData
-
- createUserUnmutedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'user-unmuted', roomId, message, user, extraData
-
- createNewModeratorWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'new-moderator', roomId, message, user, extraData
-
- createModeratorRemovedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'moderator-removed', roomId, message, user, extraData
-
- createNewOwnerWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'new-owner', roomId, message, user, extraData
-
- createOwnerRemovedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'owner-removed', roomId, message, user, extraData
-
- createSubscriptionRoleAddedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'subscription-role-added', roomId, message, user, extraData
-
- createSubscriptionRoleRemovedWithRoomIdAndUser: (roomId, user, extraData) ->
- message = user.username
- return @createWithTypeRoomIdMessageAndUser 'subscription-role-removed', roomId, message, user, extraData
-
- # REMOVE
- removeById: (_id) ->
- query =
- _id: _id
-
- return @remove query
-
- removeByRoomId: (roomId) ->
- query =
- rid: roomId
-
- return @remove query
-
- removeByUserId: (userId) ->
- query =
- "u._id": userId
-
- return @remove query
-
- getMessageByFileId: (fileID) ->
- return @findOne { 'file._id': fileID }
diff --git a/packages/rocketchat-lib/server/models/Messages.js b/packages/rocketchat-lib/server/models/Messages.js
new file mode 100644
index 0000000000000..a52fcdaa1843e
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Messages.js
@@ -0,0 +1,670 @@
+import _ from 'underscore';
+
+RocketChat.models.Messages = new class extends RocketChat.models._Base {
+ constructor() {
+ super('message');
+
+ this.tryEnsureIndex({ 'rid': 1, 'ts': 1 });
+ this.tryEnsureIndex({ 'ts': 1 });
+ this.tryEnsureIndex({ 'u._id': 1 });
+ this.tryEnsureIndex({ 'editedAt': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'editedBy._id': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'rid': 1, 't': 1, 'u._id': 1 });
+ this.tryEnsureIndex({ 'expireAt': 1 }, { expireAfterSeconds: 0 });
+ this.tryEnsureIndex({ 'msg': 'text' });
+ this.tryEnsureIndex({ 'file._id': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'mentions.username': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'pinned': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'snippeted': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'location': '2dsphere' });
+ this.tryEnsureIndex({ 'slackBotId': 1, 'slackTs': 1 }, { sparse: 1 });
+ }
+
+ // FIND
+ findByMention(username, options) {
+ const query = {'mentions.username': username};
+
+ return this.find(query, options);
+ }
+
+ findVisibleByMentionAndRoomId(username, rid, options) {
+ const query = {
+ _hidden: { $ne: true },
+ 'mentions.username': username,
+ rid
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomId(roomId, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+
+ rid: roomId
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdNotContainingTypes(roomId, types, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+
+ rid: roomId
+ };
+
+ if (Match.test(types, [String]) && (types.length > 0)) {
+ query.t =
+ {$nin: types};
+ }
+
+ return this.find(query, options);
+ }
+
+ findInvisibleByRoomId(roomId, options) {
+ const query = {
+ _hidden: true,
+ rid: roomId
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdAfterTimestamp(roomId, timestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $gt: timestamp
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findForUpdates(roomId, timestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ _updatedAt: {
+ $gt: timestamp
+ }
+ };
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBeforeTimestamp(roomId, timestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $lt: timestamp
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBeforeTimestampInclusive(roomId, timestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $lte: timestamp
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBetweenTimestamps(roomId, afterTimestamp, beforeTimestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $gt: afterTimestamp,
+ $lt: beforeTimestamp
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBetweenTimestampsInclusive(roomId, afterTimestamp, beforeTimestamp, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $gte: afterTimestamp,
+ $lte: beforeTimestamp
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $lt: timestamp
+ }
+ };
+
+ if (Match.test(types, [String]) && (types.length > 0)) {
+ query.t =
+ {$nin: types};
+ }
+
+ return this.find(query, options);
+ }
+
+ findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options) {
+ const query = {
+ _hidden: {
+ $ne: true
+ },
+ rid: roomId,
+ ts: {
+ $gt: afterTimestamp,
+ $lt: beforeTimestamp
+ }
+ };
+
+ if (Match.test(types, [String]) && (types.length > 0)) {
+ query.t =
+ {$nin: types};
+ }
+
+ return this.find(query, options);
+ }
+
+ findVisibleCreatedOrEditedAfterTimestamp(timestamp, options) {
+ const query = {
+ _hidden: { $ne: true },
+ $or: [{
+ ts: {
+ $gt: timestamp
+ }
+ },
+ {
+ 'editedAt': {
+ $gt: timestamp
+ }
+ }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findStarredByUserAtRoom(userId, roomId, options) {
+ const query = {
+ _hidden: { $ne: true },
+ 'starred._id': userId,
+ rid: roomId
+ };
+
+ return this.find(query, options);
+ }
+
+ findPinnedByRoom(roomId, options) {
+ const query = {
+ t: { $ne: 'rm' },
+ _hidden: { $ne: true },
+ pinned: true,
+ rid: roomId
+ };
+
+ return this.find(query, options);
+ }
+
+ findSnippetedByRoom(roomId, options) {
+ const query = {
+ _hidden: { $ne: true },
+ snippeted: true,
+ rid: roomId
+ };
+
+ return this.find(query, options);
+ }
+
+ getLastTimestamp(options) {
+ if (options == null) { options = {}; }
+ const query = { ts: { $exists: 1 } };
+ options.sort = { ts: -1 };
+ options.limit = 1;
+ const [message] = this.find(query, options).fetch();
+ return message && message.ts;
+ }
+
+ findByRoomIdAndMessageIds(rid, messageIds, options) {
+ const query = {
+ rid,
+ _id: {
+ $in: messageIds
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findOneBySlackBotIdAndSlackTs(slackBotId, slackTs) {
+ const query = {
+ slackBotId,
+ slackTs
+ };
+
+ return this.findOne(query);
+ }
+
+ findOneBySlackTs(slackTs) {
+ const query = {slackTs};
+
+ return this.findOne(query);
+ }
+
+ getLastVisibleMessageSentWithNoTypeByRoomId(rid, messageId) {
+ const query = {
+ rid,
+ _hidden: { $ne: true },
+ t: { $exists: false }
+ };
+
+ if (messageId) {
+ query._id = { $ne: messageId };
+ }
+
+ const options = {
+ sort: {
+ ts: -1
+ }
+ };
+
+ return this.findOne(query, options);
+ }
+
+ cloneAndSaveAsHistoryById(_id) {
+ const me = RocketChat.models.Users.findOneById(Meteor.userId());
+ const record = this.findOneById(_id);
+ record._hidden = true;
+ record.parent = record._id;
+ record.editedAt = new Date;
+ record.editedBy = {
+ _id: Meteor.userId(),
+ username: me.username
+ };
+ delete record._id;
+ return this.insert(record);
+ }
+
+ // UPDATE
+ setHiddenById(_id, hidden) {
+ if (hidden == null) { hidden = true; }
+ const query = {_id};
+
+ const update = {
+ $set: {
+ _hidden: hidden
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setAsDeletedByIdAndUser(_id, user) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ msg: '',
+ t: 'rm',
+ urls: [],
+ mentions: [],
+ attachments: [],
+ reactions: [],
+ editedAt: new Date(),
+ editedBy: {
+ _id: user._id,
+ username: user.username
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setPinnedByIdAndUserId(_id, pinnedBy, pinned, pinnedAt) {
+ if (pinned == null) { pinned = true; }
+ if (pinnedAt == null) { pinnedAt = 0; }
+ const query = {_id};
+
+ const update = {
+ $set: {
+ pinned,
+ pinnedAt: pinnedAt || new Date,
+ pinnedBy
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setSnippetedByIdAndUserId(message, snippetName, snippetedBy, snippeted, snippetedAt) {
+ if (snippeted == null) { snippeted = true; }
+ if (snippetedAt == null) { snippetedAt = 0; }
+ const query = {_id: message._id};
+
+ const msg = `\`\`\`${ message.msg }\`\`\``;
+
+ const update = {
+ $set: {
+ msg,
+ snippeted,
+ snippetedAt: snippetedAt || new Date,
+ snippetedBy,
+ snippetName
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setUrlsById(_id, urls) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ urls
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateAllUsernamesByUserId(userId, username) {
+ const query = {'u._id': userId};
+
+ const update = {
+ $set: {
+ 'u.username': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ updateUsernameOfEditByUserId(userId, username) {
+ const query = {'editedBy._id': userId};
+
+ const update = {
+ $set: {
+ 'editedBy.username': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ updateUsernameAndMessageOfMentionByIdAndOldUsername(_id, oldUsername, newUsername, newMessage) {
+ const query = {
+ _id,
+ 'mentions.username': oldUsername
+ };
+
+ const update = {
+ $set: {
+ 'mentions.$.username': newUsername,
+ 'msg': newMessage
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateUserStarById(_id, userId, starred) {
+ let update;
+ const query = {_id};
+
+ if (starred) {
+ update = {
+ $addToSet: {
+ starred: { _id: userId }
+ }
+ };
+ } else {
+ update = {
+ $pull: {
+ starred: { _id: Meteor.userId() }
+ }
+ };
+ }
+
+ return this.update(query, update);
+ }
+
+ upgradeEtsToEditAt() {
+ const query = {ets: { $exists: 1 }};
+
+ const update = {
+ $rename: {
+ 'ets': 'editedAt'
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ setMessageAttachments(_id, attachments) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ attachments
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setSlackBotIdAndSlackTs(_id, slackBotId, slackTs) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ slackBotId,
+ slackTs
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+
+ // INSERT
+ createWithTypeRoomIdMessageAndUser(type, roomId, message, user, extraData) {
+ const room = RocketChat.models.Rooms.findOneById(roomId, { fields: { sysMes: 1 }});
+ if ((room != null ? room.sysMes : undefined) === false) {
+ return;
+ }
+ const record = {
+ t: type,
+ rid: roomId,
+ ts: new Date,
+ msg: message,
+ u: {
+ _id: user._id,
+ username: user.username
+ },
+ groupable: false
+ };
+
+ if (RocketChat.settings.get('Message_Read_Receipt_Enabled')) {
+ record.unread = true;
+ }
+
+ _.extend(record, extraData);
+
+ record._id = this.insertOrUpsert(record);
+ RocketChat.models.Rooms.incMsgCountById(room._id, 1);
+ return record;
+ }
+
+ createUserJoinWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('uj', roomId, message, user, extraData);
+ }
+
+ createUserLeaveWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('ul', roomId, message, user, extraData);
+ }
+
+ createUserRemovedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('ru', roomId, message, user, extraData);
+ }
+
+ createUserAddedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('au', roomId, message, user, extraData);
+ }
+
+ createCommandWithRoomIdAndUser(command, roomId, user, extraData) {
+ return this.createWithTypeRoomIdMessageAndUser('command', roomId, command, user, extraData);
+ }
+
+ createUserMutedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('user-muted', roomId, message, user, extraData);
+ }
+
+ createUserUnmutedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('user-unmuted', roomId, message, user, extraData);
+ }
+
+ createNewModeratorWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('new-moderator', roomId, message, user, extraData);
+ }
+
+ createModeratorRemovedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('moderator-removed', roomId, message, user, extraData);
+ }
+
+ createNewOwnerWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('new-owner', roomId, message, user, extraData);
+ }
+
+ createOwnerRemovedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('owner-removed', roomId, message, user, extraData);
+ }
+
+ createNewLeaderWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('new-leader', roomId, message, user, extraData);
+ }
+
+ createLeaderRemovedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('leader-removed', roomId, message, user, extraData);
+ }
+
+ createSubscriptionRoleAddedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('subscription-role-added', roomId, message, user, extraData);
+ }
+
+ createSubscriptionRoleRemovedWithRoomIdAndUser(roomId, user, extraData) {
+ const message = user.username;
+ return this.createWithTypeRoomIdMessageAndUser('subscription-role-removed', roomId, message, user, extraData);
+ }
+
+ // REMOVE
+ removeById(_id) {
+ const query = {_id};
+
+ return this.remove(query);
+ }
+
+ removeByRoomId(roomId) {
+ const query = {rid: roomId};
+
+ return this.remove(query);
+ }
+
+ removeByUserId(userId) {
+ const query = {'u._id': userId};
+
+ return this.remove(query);
+ }
+
+ getMessageByFileId(fileID) {
+ return this.findOne({ 'file._id': fileID });
+ }
+
+ setAsRead(rid, until) {
+ return this.update({
+ rid,
+ unread: true,
+ ts: { $lt: until }
+ }, {
+ $unset: {
+ unread: 1
+ }
+ }, {
+ multi: true
+ });
+ }
+
+ setAsReadById(_id) {
+ return this.update({
+ _id
+ }, {
+ $unset: {
+ unread: 1
+ }
+ });
+ }
+
+ findUnreadMessagesByRoomAndDate(rid, after) {
+ const query = {
+ unread: true,
+ rid
+ };
+
+ if (after) {
+ query.ts = { $gt: after };
+ }
+
+ return this.find(query, {
+ fields: {
+ _id: 1
+ }
+ });
+ }
+};
diff --git a/packages/rocketchat-lib/server/models/Reports.coffee b/packages/rocketchat-lib/server/models/Reports.coffee
deleted file mode 100644
index c37b2735aba38..0000000000000
--- a/packages/rocketchat-lib/server/models/Reports.coffee
+++ /dev/null
@@ -1,17 +0,0 @@
-RocketChat.models.Reports = new class extends RocketChat.models._Base
- constructor: ->
- super('reports')
-
-
- # INSERT
- createWithMessageDescriptionAndUserId: (message, description, userId, extraData) ->
- record =
- message: message
- description: description
- ts: new Date()
- userId: userId
-
- _.extend record, extraData
-
- record._id = @insert record
- return record
diff --git a/packages/rocketchat-lib/server/models/Reports.js b/packages/rocketchat-lib/server/models/Reports.js
new file mode 100644
index 0000000000000..366670f29dbf0
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Reports.js
@@ -0,0 +1,18 @@
+import _ from 'underscore';
+
+RocketChat.models.Reports = new class extends RocketChat.models._Base {
+ constructor() {
+ super('reports');
+ }
+ createWithMessageDescriptionAndUserId(message, description, userId, extraData) {
+ const record = {
+ message,
+ description,
+ ts: new Date(),
+ userId
+ };
+ _.extend(record, extraData);
+ record._id = this.insert(record);
+ return record;
+ }
+};
diff --git a/packages/rocketchat-lib/server/models/Rooms.coffee b/packages/rocketchat-lib/server/models/Rooms.coffee
deleted file mode 100644
index 1c497021c2aad..0000000000000
--- a/packages/rocketchat-lib/server/models/Rooms.coffee
+++ /dev/null
@@ -1,593 +0,0 @@
-class ModelRooms extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
-
- @tryEnsureIndex { 'name': 1 }, { unique: 1, sparse: 1 }
- @tryEnsureIndex { 'default': 1 }
- @tryEnsureIndex { 'usernames': 1 }
- @tryEnsureIndex { 't': 1 }
- @tryEnsureIndex { 'u._id': 1 }
-
- this.cache.ignoreUpdatedFields.push('msgs', 'lm')
- this.cache.ensureIndex(['t', 'name'], 'unique')
- this.cache.options = {fields: {usernames: 0}}
-
- findOneByIdOrName: (_idOrName, options) ->
- query = {
- $or: [{
- _id: _idOrName
- }, {
- name: _idOrName
- }]
- }
-
- return this.findOne(query, options)
-
- findOneByImportId: (_id, options) ->
- query =
- importIds: _id
-
- return @findOne query, options
-
- findOneByName: (name, options) ->
- query =
- name: name
-
- return @findOne query, options
-
- findOneByNameAndType: (name, type, options) ->
- query =
- name: name
- t: type
-
- return @findOne query, options
-
- findOneByIdContainingUsername: (_id, username, options) ->
- query =
- _id: _id
- usernames: username
-
- return @findOne query, options
-
- findOneByNameAndTypeNotContainingUsername: (name, type, username, options) ->
- query =
- name: name
- t: type
- usernames:
- $ne: username
-
- return @findOne query, options
-
-
- # FIND
-
- findById: (roomId, options) ->
- return @find { _id: roomId }, options
-
- findByIds: (roomIds, options) ->
- return @find { _id: $in: [].concat roomIds }, options
-
- findByType: (type, options) ->
- query =
- t: type
-
- return @find query, options
-
- findByTypes: (types, options) ->
- query =
- t:
- $in: types
-
- return @find query, options
-
- findByUserId: (userId, options) ->
- query =
- "u._id": userId
-
- return @find query, options
-
- findBySubscriptionUserId: (userId, options) ->
- if this.useCache
- data = RocketChat.models.Subscriptions.findByUserId(userId).fetch()
- data = data.map (item) ->
- if item._room
- return item._room
- console.log('Empty Room for Subscription', item);
- return {}
- return this.arrayToCursor this.processQueryOptionsOnResult(data, options)
-
- data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch()
- data = data.map (item) -> item.rid
-
- query =
- _id:
- $in: data
-
- this.find query, options
-
- findBySubscriptionUserIdUpdatedAfter: (userId, _updatedAt, options) ->
- if this.useCache
- data = RocketChat.models.Subscriptions.findByUserId(userId).fetch()
- data = data.map (item) ->
- if item._room
- return item._room
- console.log('Empty Room for Subscription', item);
- return {}
- data = data.filter (item) -> item._updatedAt > _updatedAt
- return this.arrayToCursor this.processQueryOptionsOnResult(data, options)
-
- ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch()
- ids = ids.map (item) -> item.rid
-
- query =
- _id:
- $in: ids
- _updatedAt:
- $gt: _updatedAt
-
- this.find query, options
-
- findByNameContaining: (name, options) ->
- nameRegex = new RegExp s.trim(s.escapeRegExp(name)), "i"
-
- query =
- $or: [
- name: nameRegex
- ,
- t: 'd'
- usernames: nameRegex
- ]
-
- return @find query, options
-
- findByNameContainingTypesWithUsername: (name, types, options) ->
- nameRegex = new RegExp s.trim(s.escapeRegExp(name)), "i"
-
- $or = []
- for type in types
- obj = {name: nameRegex, t: type.type}
- if type.username?
- obj.usernames = type.username
- if type.ids?
- obj._id = $in: type.ids
- $or.push obj
-
- query =
- $or: $or
-
- return @find query, options
-
- findContainingTypesWithUsername: (types, options) ->
-
- $or = []
- for type in types
- obj = {t: type.type}
- if type.username?
- obj.usernames = type.username
- if type.ids?
- obj._id = $in: type.ids
- $or.push obj
-
- query =
- $or: $or
-
- return @find query, options
-
- findByNameContainingAndTypes: (name, types, options) ->
- nameRegex = new RegExp s.trim(s.escapeRegExp(name)), "i"
-
- query =
- t:
- $in: types
- $or: [
- name: nameRegex
- ,
- t: 'd'
- usernames: nameRegex
- ]
-
- return @find query, options
-
- findByNameAndTypeNotContainingUsername: (name, type, username, options) ->
- query =
- t: type
- name: name
- usernames:
- $ne: username
-
- return @find query, options
-
- findByNameStartingAndTypes: (name, types, options) ->
- nameRegex = new RegExp "^" + s.trim(s.escapeRegExp(name)), "i"
-
- query =
- t:
- $in: types
- $or: [
- name: nameRegex
- ,
- t: 'd'
- usernames: nameRegex
- ]
-
- return @find query, options
-
- findByDefaultAndTypes: (defaultValue, types, options) ->
- query =
- default: defaultValue
- t:
- $in: types
-
- return @find query, options
-
- findByTypeContainingUsername: (type, username, options) ->
- query =
- t: type
- usernames: username
-
- return @find query, options
-
- findByTypeContainingUsernames: (type, username, options) ->
- query =
- t: type
- usernames: { $all: [].concat(username) }
-
- return @find query, options
-
- findByTypesAndNotUserIdContainingUsername: (types, userId, username, options) ->
- query =
- t:
- $in: types
- uid:
- $ne: userId
- usernames: username
-
- return @find query, options
-
- findByContainingUsername: (username, options) ->
- query =
- usernames: username
-
- return @find query, options
-
- findByTypeAndName: (type, name, options) ->
- if this.useCache
- return this.cache.findByIndex('t,name', [type, name], options)
-
- query =
- name: name
- t: type
-
- return @find query, options
-
- findByTypeAndNameContainingUsername: (type, name, username, options) ->
- query =
- name: name
- t: type
- usernames: username
-
- return @find query, options
-
- findByTypeAndArchivationState: (type, archivationstate, options) ->
- query =
- t: type
-
- if archivationstate
- query.archived = true
- else
- query.archived = { $ne: true }
-
- return @find query, options
-
- # UPDATE
- addImportIds: (_id, importIds) ->
- importIds = [].concat(importIds);
- query =
- _id: _id
-
- update =
- $addToSet:
- importIds:
- $each: importIds
-
- return @update query, update
-
- archiveById: (_id) ->
- query =
- _id: _id
-
- update =
- $set:
- archived: true
-
- return @update query, update
-
- unarchiveById: (_id) ->
- query =
- _id: _id
-
- update =
- $set:
- archived: false
-
- return @update query, update
-
- addUsernameById: (_id, username, muted) ->
- query =
- _id: _id
-
- update =
- $addToSet:
- usernames: username
-
- if muted
- update.$addToSet.muted = username
-
- return @update query, update
-
- addUsernamesById: (_id, usernames) ->
- query =
- _id: _id
-
- update =
- $addToSet:
- usernames:
- $each: usernames
-
- return @update query, update
-
- addUsernameByName: (name, username) ->
- query =
- name: name
-
- update =
- $addToSet:
- usernames: username
-
- return @update query, update
-
- removeUsernameById: (_id, username) ->
- query =
- _id: _id
-
- update =
- $pull:
- usernames: username
-
- return @update query, update
-
- removeUsernamesById: (_id, usernames) ->
- query =
- _id: _id
-
- update =
- $pull:
- usernames:
- $in: usernames
-
- return @update query, update
-
- removeUsernameFromAll: (username) ->
- query =
- usernames: username
-
- update =
- $pull:
- usernames: username
-
- return @update query, update, { multi: true }
-
- removeUsernameByName: (name, username) ->
- query =
- name: name
-
- update =
- $pull:
- usernames: username
-
- return @update query, update
-
- setNameById: (_id, name) ->
- query =
- _id: _id
-
- update =
- $set:
- name: name
-
- return @update query, update
-
- incMsgCountAndSetLastMessageTimestampById: (_id, inc=1, lastMessageTimestamp) ->
- query =
- _id: _id
-
- update =
- $set:
- lm: lastMessageTimestamp
- $inc:
- msgs: inc
-
- return @update query, update
-
- replaceUsername: (previousUsername, username) ->
- query =
- usernames: previousUsername
-
- update =
- $set:
- "usernames.$": username
-
- return @update query, update, { multi: true }
-
- replaceMutedUsername: (previousUsername, username) ->
- query =
- muted: previousUsername
-
- update =
- $set:
- "muted.$": username
-
- return @update query, update, { multi: true }
-
- replaceUsernameOfUserByUserId: (userId, username) ->
- query =
- "u._id": userId
-
- update =
- $set:
- "u.username": username
-
- return @update query, update, { multi: true }
-
- setJoinCodeById: (_id, joinCode) ->
- query =
- _id: _id
-
- if joinCode?.trim() isnt ''
- update =
- $set:
- joinCodeRequired: true
- joinCode: joinCode
- else
- update =
- $set:
- joinCodeRequired: false
- $unset:
- joinCode: 1
-
- return @update query, update
-
- setUserById: (_id, user) ->
- query =
- _id: _id
-
- update =
- $set:
- u:
- _id: user._id
- username: user.username
-
- return @update query, update
-
- setTypeById: (_id, type) ->
- query =
- _id: _id
-
- update =
- $set:
- t: type
-
- return @update query, update
-
- setTopicById: (_id, topic) ->
- query =
- _id: _id
-
- update =
- $set:
- topic: topic
-
- return @update query, update
-
- muteUsernameByRoomId: (_id, username) ->
- query =
- _id: _id
-
- update =
- $addToSet:
- muted: username
-
- return @update query, update
-
- unmuteUsernameByRoomId: (_id, username) ->
- query =
- _id: _id
-
- update =
- $pull:
- muted: username
-
- return @update query, update
-
- saveDefaultById: (_id, defaultValue) ->
- query =
- _id: _id
-
- update =
- $set:
- default: defaultValue is 'true'
-
- return @update query, update
-
- saveRoomById: (_id, data) ->
- setData = {}
- unsetData = {}
-
- if data.topic?
- if not _.isEmpty(s.trim(data.topic))
- setData.topic = s.trim(data.topic)
- else
- unsetData.topic = 1
-
- if data.tags?
- if not _.isEmpty(s.trim(data.tags))
- setData.tags = s.trim(data.tags).split(',').map((tag) => return s.trim(tag))
- else
- unsetData.tags = 1
-
- update = {}
-
- if not _.isEmpty setData
- update.$set = setData
-
- if not _.isEmpty unsetData
- update.$unset = unsetData
-
- return @update { _id: _id }, update
-
- # INSERT
- createWithTypeNameUserAndUsernames: (type, name, user, usernames, extraData) ->
- room =
- name: name
- t: type
- usernames: usernames
- msgs: 0
- u:
- _id: user._id
- username: user.username
-
- _.extend room, extraData
-
- room._id = @insert room
- return room
-
- createWithIdTypeAndName: (_id, type, name, extraData) ->
- room =
- _id: _id
- ts: new Date()
- t: type
- name: name
- usernames: []
- msgs: 0
-
- _.extend room, extraData
-
- @insert room
- return room
-
-
- # REMOVE
- removeById: (_id) ->
- query =
- _id: _id
-
- return @remove query
-
- removeByTypeContainingUsername: (type, username) ->
- query =
- t: type
- usernames: username
-
- return @remove query
-
-RocketChat.models.Rooms = new ModelRooms('room', true)
diff --git a/packages/rocketchat-lib/server/models/Rooms.js b/packages/rocketchat-lib/server/models/Rooms.js
new file mode 100644
index 0000000000000..412011b1e4af7
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Rooms.js
@@ -0,0 +1,909 @@
+import _ from 'underscore';
+import s from 'underscore.string';
+
+class ModelRooms extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+
+ this.tryEnsureIndex({ 'name': 1, 'serverId': 1 }, { unique: 1, sparse: 1 });
+ this.tryEnsureIndex({ 'default': 1, 'serverId': 1 });
+ this.tryEnsureIndex({ 'usernames': 1, 'serverId': 1 });
+ this.tryEnsureIndex({ 't': 1, 'serverId': 1 });
+ this.tryEnsureIndex({ 'u._id': 1, 'serverId': 1 });
+
+ this.cache.ignoreUpdatedFields = ['msgs', 'lm'];
+ this.cache.ensureIndex(['t', 'name', 'serverId'], 'unique');
+ this.cache.options = {fields: {usernames: 0}};
+ }
+
+ findOneByIdOrName(_idOrName, options) {
+ const query = {
+ $or: [{
+ _id: _idOrName
+ }, {
+ name: _idOrName
+ }]
+ };
+
+ return this.findOne(query, options);
+ }
+
+ findOneByImportId(_id, options) {
+ const query = {importIds: _id};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByName(name, serverId, options) {
+ const query = {name, serverId};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByNameAndNotId(name, rid) {
+ const query = {
+ _id: { $ne: rid },
+ name
+ };
+
+ return this.findOne(query);
+ }
+
+ findOneByDisplayName(fname, serverId, options) {
+ const query = {fname, serverId};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByNameAndType(name, type, options) {
+ const query = {
+ name,
+ t: type
+ };
+
+ return this.findOne(query, options);
+ }
+
+ findOneByIdContainingUsername(_id, username, options) {
+ const query = {
+ _id,
+ usernames: username
+ };
+
+ return this.findOne(query, options);
+ }
+
+ findOneByNameAndTypeNotContainingUsername(name, type, username, options) {
+ const query = {
+ name,
+ t: type,
+ usernames: {
+ $ne: username
+ }
+ };
+
+ return this.findOne(query, options);
+ }
+
+
+ // FIND
+
+ findById(roomId, options) {
+ return this.find({ _id: roomId }, options);
+ }
+
+ findByIds(roomIds, options) {
+ return this.find({ _id: {$in: [].concat(roomIds)} }, options);
+ }
+
+ findByType(type, options) {
+ const query = {t: type};
+
+ return this.find(query, options);
+ }
+
+ findByTypes(types, options) {
+ const query = {
+ t: {
+ $in: types
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByUserId(userId, options) {
+ const query = {'u._id': userId};
+
+ return this.find(query, options);
+ }
+
+ findBySubscriptionUserId(userId, options) {
+ let data;
+ if (this.useCache) {
+ data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
+ data = data.map(function(item) {
+ if (item._room) {
+ return item._room;
+ }
+ console.log('Empty Room for Subscription', item);
+ });
+ data = data.filter(item => item);
+ return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
+ }
+
+ data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
+ data = data.map(item => item.rid);
+
+ const query = {
+ _id: {
+ $in: data
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findBySubscriptionUserIdUpdatedAfter(userId, _updatedAt, options) {
+ if (this.useCache) {
+ let data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
+ data = data.map(function(item) {
+ if (item._room) {
+ return item._room;
+ }
+ console.log('Empty Room for Subscription', item);
+ });
+ data = data.filter(item => item && item._updatedAt > _updatedAt);
+ return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
+ }
+
+ let ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
+ ids = ids.map(item => item.rid);
+
+ const query = {
+ _id: {
+ $in: ids
+ },
+ _updatedAt: {
+ $gt: _updatedAt
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findBySubscriptionUserIdServerIds(userId, serverIds, options) {
+ let data;
+ if (this.useCache) {
+ data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
+ data = data.map(function(item) {
+ if (item._room) {
+ return item._room;
+ }
+ console.log('Empty Room for Subscription', item);
+ });
+ data = data.filter(item => item);
+ return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
+ }
+
+ data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
+ data = data.map(item => item.rid);
+
+ const query = {
+ _id: { $in: data },
+ $or: [
+ { 'serverId': { $in: serverIds } },
+ { t: 'd' }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findBySubscriptionUserIdServerIdsUpdatedAfter(userId, serverIds, _updatedAt, options) {
+ if (this.useCache) {
+ let data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
+ data = data.map(function(item) {
+ if (item._room) {
+ return item._room;
+ }
+ console.log('Empty Room for Subscription', item);
+ });
+ data = data.filter(item => item && item._updatedAt > _updatedAt);
+ return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
+ }
+
+ let ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
+ ids = ids.map(item => item.rid);
+
+ const query = {
+ _id: { $in: ids },
+ _updatedAt: {
+ $gt: _updatedAt
+ },
+ $or: [
+ { 'serverId': { $in: serverIds } },
+ { t: 'd' }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByNameContaining(name, options) {
+ const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
+
+ const query = {
+ $or: [
+ {name: nameRegex},
+ {
+ t: 'd',
+ usernames: nameRegex
+ }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByNameContainingTypesWithUsername(name, types, options) {
+ const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
+
+ const $or = [];
+ for (const type of Array.from(types)) {
+ const obj = {name: nameRegex, t: type.type};
+ if (type.username != null) {
+ obj.usernames = type.username;
+ }
+ if (type.ids != null) {
+ obj._id = {$in: type.ids};
+ }
+ $or.push(obj);
+ }
+
+ const query = {$or};
+
+ return this.find(query, options);
+ }
+
+ findContainingTypesWithUsername(types, options) {
+
+ const $or = [];
+ for (const type of Array.from(types)) {
+ const obj = {t: type.type};
+ if (type.username != null) {
+ obj.usernames = type.username;
+ }
+ if (type.ids != null) {
+ obj._id = {$in: type.ids};
+ }
+ $or.push(obj);
+ }
+
+ const query = {$or};
+
+ return this.find(query, options);
+ }
+
+ findByNameContainingAndTypes(name, types, options) {
+ const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
+
+ const query = {
+ t: {
+ $in: types
+ },
+ $or: [
+ {name: nameRegex},
+ {
+ t: 'd',
+ usernames: nameRegex
+ }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByNameTypeAndServer(name, type, serverId, options) {
+ const query = {
+ t: type,
+ name,
+ serverId
+ };
+
+ // do not use cache
+ return this._db.find(query, options);
+ }
+
+ findByNameAndTypeNotDefault(name, type, options) {
+ const query = {
+ t: type,
+ name,
+ default: {
+ $ne: true
+ }
+ };
+
+ // do not use cache
+ return this._db.find(query, options);
+ }
+
+ findByNameAndTypesNotContainingUsername(name, types, username, options) {
+ const query = {
+ t: {
+ $in: types
+ },
+ name,
+ usernames: {
+ $ne: username
+ }
+ };
+
+ // do not use cache
+ return this._db.find(query, options);
+ }
+
+ findByNameStartingAndTypes(name, types, options) {
+ const nameRegex = new RegExp(`^${ s.trim(s.escapeRegExp(name)) }`, 'i');
+
+ const query = {
+ t: {
+ $in: types
+ },
+ $or: [
+ {name: nameRegex},
+ {
+ t: 'd',
+ usernames: nameRegex
+ }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByDefaultAndTypes(defaultValue, types, options) {
+ const query = {
+ default: defaultValue,
+ t: {
+ $in: types
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypeContainingUsername(type, username, options) {
+ const query = {
+ t: type,
+ usernames: username
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypeContainingUsernames(type, username, options) {
+ const query = {
+ t: type,
+ usernames: { $all: [].concat(username) }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypesAndNotUserIdContainingUsername(types, userId, username, options) {
+ const query = {
+ t: {
+ $in: types
+ },
+ uid: {
+ $ne: userId
+ },
+ usernames: username
+ };
+
+ return this.find(query, options);
+ }
+
+ findByContainingUsername(username, options) {
+ const query = {usernames: username};
+
+ return this.find(query, options);
+ }
+
+ findByTypeAndName(type, name, options) {
+ if (this.useCache) {
+ return this.cache.findByIndex('t,name', [type, name], options);
+ }
+
+ const query = {
+ name,
+ t: type
+ };
+
+ return this.find(query, options);
+ }
+
+ findOneByTypeNameServerId(type, name, serverId, options) {
+ if (this.useCache) {
+ return this.cache.findByIndex('t,name', [type, name], options);
+ }
+
+ const query = {
+ name,
+ $or: [
+ { serverId, t: type },
+ { t: 'd' }
+ ]
+ };
+
+ return this.findOne(query, options);
+ }
+
+ findByTypeAndNameContainingUsername(type, name, username, options) {
+ const query = {
+ name,
+ t: type,
+ usernames: username
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypeAndArchivationState(type, archivationstate, options) {
+ const query = {t: type};
+
+ if (archivationstate) {
+ query.archived = true;
+ } else {
+ query.archived = { $ne: true };
+ }
+
+ return this.find(query, options);
+ }
+
+ // UPDATE
+
+ setServerId(_id, serverId) {
+ const query = {_id};
+ const update = {
+ $set: {
+ serverId
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ addImportIds(_id, importIds) {
+ importIds = [].concat(importIds);
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ importIds: {
+ $each: importIds
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ archiveById(_id) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ archived: true
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ unarchiveById(_id) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ archived: false
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ addUsernameById(_id, username, muted) {
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ usernames: username
+ }
+ };
+
+ if (muted) {
+ update.$addToSet.muted = username;
+ }
+
+ return this.update(query, update);
+ }
+
+ addUsernamesById(_id, usernames) {
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ usernames: {
+ $each: usernames
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ addUsernameByName(name, username) {
+ const query = {name};
+
+ const update = {
+ $addToSet: {
+ usernames: username
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ removeUsernameById(_id, username) {
+ const query = {_id};
+
+ const update = {
+ $pull: {
+ usernames: username
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ removeUsernamesById(_id, usernames) {
+ const query = {_id};
+
+ const update = {
+ $pull: {
+ usernames: {
+ $in: usernames
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ removeUsernameFromAll(username) {
+ const query = {usernames: username};
+
+ const update = {
+ $pull: {
+ usernames: username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ removeUsernameByName(name, username) {
+ const query = {name};
+
+ const update = {
+ $pull: {
+ usernames: username
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setNameById(_id, name, fname) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ name,
+ fname
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ incMsgCountById(_id, inc) {
+ if (inc == null) { inc = 1; }
+ const query = {_id};
+
+ const update = {
+ $inc: {
+ msgs: inc
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ incMsgCountAndSetLastMessageById(_id, inc, lastMessageTimestamp, lastMessage) {
+ if (inc == null) { inc = 1; }
+ const query = {_id};
+
+ const update = {
+ $set: {
+ lm: lastMessageTimestamp
+ },
+ $inc: {
+ msgs: inc
+ }
+ };
+
+ if (lastMessage) {
+ update.$set.lastMessage = lastMessage;
+ }
+
+ return this.update(query, update);
+ }
+
+ setLastMessageById(_id, lastMessage) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ lastMessage
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ replaceUsername(previousUsername, username) {
+ const query = {usernames: previousUsername};
+
+ const update = {
+ $set: {
+ 'usernames.$': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ replaceMutedUsername(previousUsername, username) {
+ const query = {muted: previousUsername};
+
+ const update = {
+ $set: {
+ 'muted.$': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ replaceUsernameOfUserByUserId(userId, username) {
+ const query = {'u._id': userId};
+
+ const update = {
+ $set: {
+ 'u.username': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ setJoinCodeById(_id, joinCode) {
+ let update;
+ const query = {_id};
+
+ if ((joinCode != null ? joinCode.trim() : undefined) !== '') {
+ update = {
+ $set: {
+ joinCodeRequired: true,
+ joinCode
+ }
+ };
+ } else {
+ update = {
+ $set: {
+ joinCodeRequired: false
+ },
+ $unset: {
+ joinCode: 1
+ }
+ };
+ }
+
+ return this.update(query, update);
+ }
+
+ setUserById(_id, user) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ u: {
+ _id: user._id,
+ username: user.username
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setTypeById(_id, type) {
+ const query = {_id};
+ const update = {
+ $set: {
+ t: type
+ }
+ };
+ if (type === 'p') {
+ update.$unset = {default: ''};
+ }
+
+ return this.update(query, update);
+ }
+
+ setTopicById(_id, topic) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ topic
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setAnnouncementById(_id, announcement) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ announcement
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ muteUsernameByRoomId(_id, username) {
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ muted: username
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ unmuteUsernameByRoomId(_id, username) {
+ const query = {_id};
+
+ const update = {
+ $pull: {
+ muted: username
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ saveDefaultById(_id, defaultValue) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ default: defaultValue === 'true'
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setTopicAndTagsById(_id, topic, tags) {
+ const setData = {};
+ const unsetData = {};
+
+ if (topic != null) {
+ if (!_.isEmpty(s.trim(topic))) {
+ setData.topic = s.trim(topic);
+ } else {
+ unsetData.topic = 1;
+ }
+ }
+
+ if (tags != null) {
+ if (!_.isEmpty(s.trim(tags))) {
+ setData.tags = s.trim(tags).split(',').map(tag => s.trim(tag));
+ } else {
+ unsetData.tags = 1;
+ }
+ }
+
+ const update = {};
+
+ if (!_.isEmpty(setData)) {
+ update.$set = setData;
+ }
+
+ if (!_.isEmpty(unsetData)) {
+ update.$unset = unsetData;
+ }
+
+ if (_.isEmpty(update)) {
+ return;
+ }
+
+ return this.update({ _id }, update);
+ }
+
+ // INSERT
+ createWithTypeNameUserAndUsernames(type, serverId, name, fname, user, usernames, extraData) {
+ const room = {
+ name,
+ fname,
+ t: type,
+ serverId,
+ usernames,
+ msgs: 0,
+ u: {
+ _id: user._id,
+ username: user.username
+ }
+ };
+
+ _.extend(room, extraData);
+
+ room._id = this.insert(room);
+ return room;
+ }
+
+ createWithIdTypeAndName(_id, type, name, extraData) {
+ const room = {
+ _id,
+ ts: new Date(),
+ t: type,
+ name,
+ usernames: [],
+ msgs: 0
+ };
+
+ _.extend(room, extraData);
+
+ this.insert(room);
+ return room;
+ }
+
+
+ // REMOVE
+ removeById(_id) {
+ const query = {_id};
+
+ return this.remove(query);
+ }
+
+ removeByTypeContainingUsername(type, username) {
+ const query = {
+ t: type,
+ usernames: username
+ };
+
+ return this.remove(query);
+ }
+}
+
+RocketChat.models.Rooms = new ModelRooms('room');
diff --git a/packages/rocketchat-lib/server/models/Servers.js b/packages/rocketchat-lib/server/models/Servers.js
new file mode 100644
index 0000000000000..27490f47536f6
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Servers.js
@@ -0,0 +1,158 @@
+import _ from 'underscore';
+
+class ModelServers extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+
+ this.tryEnsureIndex({name: 1});
+ this.tryEnsureIndex({active: 1}, {sparse: 1});
+ }
+
+ // INSERT
+ create(data) {
+ const server = {
+ createdAt: new Date(),
+ active: true,
+ type: 'text'
+ };
+
+ _.extend(server, data);
+
+ return this.insert(server);
+ }
+
+ // FIND
+ findOneById(_id, options) {
+ const query = {_id};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByname(name, options) {
+ if (typeof name === 'string') {
+ name = new RegExp(`^${ name }$`, 'i');
+ }
+
+ const query = {name};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByUserId(userId, options) {
+ const query = {userIds: userId};
+
+ return this.findOne(query, options);
+ }
+
+ // UPDATE
+ setName(_id, name) {
+ const update = {
+ $set: {
+ name
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ editServerName(_id, name) {
+ const update = {
+ $set: {name}
+ };
+
+ return this.update(_id, update);
+ }
+
+ setServerActive(_id, active) {
+ if (active == null) {
+ active = true;
+ }
+ const update = {
+ $set: {
+ active
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setDefaultRoom(_id, roomId) {
+ const update = {
+ $set: {
+ defaultRoom: roomId
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ addUserById(_id, userId) {
+ const update = {
+ $addToSet: {
+ userIds: userId
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ addInvitedEmail(_id, email) {
+ this.removeInvitedEmail(_id, email);
+
+ const update = {
+ $push: {
+ invitedEmails: email
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ removeInvitedEmail(_id, email) {
+ const update = {
+ $pull: {
+ invitedEmails: email
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setAvatar(_id, avatarUrl) {
+ const update = {
+ $set: {
+ avatarUrl
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ unsetAvatar(_id) {
+ const update = {
+ $unset: {
+ avatarUrl: 1
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ // REMOVE
+ removeById(_id) {
+ return this.remove(_id);
+ }
+}
+
+RocketChat.models.Servers = new ModelServers('servers');
+
+/*
+ name: String
+ active: Boolean
+ type: String, (text : voice)
+ defaultRoom: String
+ admin: String
+ userIds: [String]
+ invitedEmails: [String]
+ avatarUrl: String
+*/
diff --git a/packages/rocketchat-lib/server/models/Settings.coffee b/packages/rocketchat-lib/server/models/Settings.coffee
deleted file mode 100644
index ce0d805be06fb..0000000000000
--- a/packages/rocketchat-lib/server/models/Settings.coffee
+++ /dev/null
@@ -1,144 +0,0 @@
-class ModelSettings extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
-
- @tryEnsureIndex { 'blocked': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'hidden': 1 }, { sparse: 1 }
-
- # FIND
- findById: (_id) ->
- query =
- _id: _id
-
- return @find query
-
- findOneNotHiddenById: (_id) ->
- query =
- _id: _id
- hidden: { $ne: true }
-
- return @findOne query
-
- findByIds: (_id = []) ->
- _id = [].concat _id
-
- query =
- _id:
- $in: _id
-
- return @find query
-
- findByRole: (role, options) ->
- query =
- role: role
-
- return @find query, options
-
- findPublic: (options) ->
- query =
- public: true
-
- return @find query, options
-
- findNotHiddenPublic: (ids = [])->
- filter =
- hidden: { $ne: true }
- public: true
-
- if ids.length > 0
- filter._id =
- $in: ids
-
- return @find filter, { fields: _id: 1, value: 1 }
-
- findNotHiddenPublicUpdatedAfter: (updatedAt) ->
- filter =
- hidden: { $ne: true }
- public: true
- _updatedAt:
- $gt: updatedAt
-
- return @find filter, { fields: _id: 1, value: 1 }
-
- findNotHiddenPrivate: ->
- return @find {
- hidden: { $ne: true }
- public: { $ne: true }
- }
-
- findNotHidden: (options) ->
- return @find { hidden: { $ne: true } }, options
-
- findNotHiddenUpdatedAfter: (updatedAt)->
- return @find {
- hidden: { $ne: true }
- _updatedAt:
- $gt: updatedAt
- }
-
- # UPDATE
- updateValueById: (_id, value) ->
- query =
- blocked: { $ne: true }
- value: { $ne: value }
- _id: _id
-
- update =
- $set:
- value: value
-
- return @update query, update
-
- updateValueAndEditorById: (_id, value, editor) ->
- query =
- blocked: { $ne: true }
- value: { $ne: value }
- _id: _id
-
- update =
- $set:
- value: value
- editor: editor
-
- return @update query, update
-
- updateValueNotHiddenById: (_id, value) ->
- query =
- _id: _id
- hidden: { $ne: true }
- blocked: { $ne: true }
-
- update =
- $set:
- value: value
-
- return @update query, update
-
- updateOptionsById: (_id, options) ->
- query =
- blocked: { $ne: true }
- _id: _id
-
- update =
- $set: options
-
- return @update query, update
-
- # INSERT
- createWithIdAndValue: (_id, value) ->
- record =
- _id: _id
- value: value
- _createdAt: new Date
-
- return @insert record
-
- # REMOVE
- removeById: (_id) ->
- query =
- blocked: { $ne: true }
- _id: _id
-
- return @remove query
-
-RocketChat.models.Settings = new ModelSettings('settings', true)
diff --git a/packages/rocketchat-lib/server/models/Settings.js b/packages/rocketchat-lib/server/models/Settings.js
new file mode 100644
index 0000000000000..7da29bee37faf
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Settings.js
@@ -0,0 +1,178 @@
+class ModelSettings extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+
+ this.tryEnsureIndex({ 'blocked': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'hidden': 1 }, { sparse: 1 });
+ }
+
+ // FIND
+ findById(_id) {
+ const query = {_id};
+
+ return this.find(query);
+ }
+
+ findOneNotHiddenById(_id) {
+ const query = {
+ _id,
+ hidden: { $ne: true }
+ };
+
+ return this.findOne(query);
+ }
+
+ findByIds(_id = []) {
+ _id = [].concat(_id);
+
+ const query = {
+ _id: {
+ $in: _id
+ }
+ };
+
+ return this.find(query);
+ }
+
+ findByRole(role, options) {
+ const query = {role};
+
+ return this.find(query, options);
+ }
+
+ findPublic(options) {
+ const query = {public: true};
+
+ return this.find(query, options);
+ }
+
+ findNotHiddenPublic(ids = []) {
+ const filter = {
+ hidden: { $ne: true },
+ public: true
+ };
+
+ if (ids.length > 0) {
+ filter._id =
+ {$in: ids};
+ }
+
+ return this.find(filter, { fields: {_id: 1, value: 1} });
+ }
+
+ findNotHiddenPublicUpdatedAfter(updatedAt) {
+ const filter = {
+ hidden: { $ne: true },
+ public: true,
+ _updatedAt: {
+ $gt: updatedAt
+ }
+ };
+
+ return this.find(filter, { fields: {_id: 1, value: 1} });
+ }
+
+ findNotHiddenPrivate() {
+ return this.find({
+ hidden: { $ne: true },
+ public: { $ne: true }
+ });
+ }
+
+ findNotHidden(options) {
+ return this.find({ hidden: { $ne: true } }, options);
+ }
+
+ findNotHiddenUpdatedAfter(updatedAt) {
+ return this.find({
+ hidden: { $ne: true },
+ _updatedAt: {
+ $gt: updatedAt
+ }
+ });
+ }
+
+ // UPDATE
+ updateValueById(_id, value) {
+ const query = {
+ blocked: { $ne: true },
+ value: { $ne: value },
+ _id
+ };
+
+ const update = {
+ $set: {
+ value
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateValueAndEditorById(_id, value, editor) {
+ const query = {
+ blocked: { $ne: true },
+ value: { $ne: value },
+ _id
+ };
+
+ const update = {
+ $set: {
+ value,
+ editor
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateValueNotHiddenById(_id, value) {
+ const query = {
+ _id,
+ hidden: { $ne: true },
+ blocked: { $ne: true }
+ };
+
+ const update = {
+ $set: {
+ value
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateOptionsById(_id, options) {
+ const query = {
+ blocked: { $ne: true },
+ _id
+ };
+
+ const update = {$set: options};
+
+ return this.update(query, update);
+ }
+
+ // INSERT
+ createWithIdAndValue(_id, value) {
+ const record = {
+ _id,
+ value,
+ _createdAt: new Date
+ };
+
+ return this.insert(record);
+ }
+
+ // REMOVE
+ removeById(_id) {
+ const query = {
+ blocked: { $ne: true },
+ _id
+ };
+
+ return this.remove(query);
+ }
+}
+
+RocketChat.models.Settings = new ModelSettings('settings', true);
diff --git a/packages/rocketchat-lib/server/models/Subscriptions.coffee b/packages/rocketchat-lib/server/models/Subscriptions.coffee
deleted file mode 100644
index c2376b0692731..0000000000000
--- a/packages/rocketchat-lib/server/models/Subscriptions.coffee
+++ /dev/null
@@ -1,434 +0,0 @@
-class ModelSubscriptions extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
-
- @tryEnsureIndex { 'rid': 1, 'u._id': 1 }, { unique: 1 }
- @tryEnsureIndex { 'rid': 1, 'alert': 1, 'u._id': 1 }
- @tryEnsureIndex { 'rid': 1, 'roles': 1 }
- @tryEnsureIndex { 'u._id': 1, 'name': 1, 't': 1 }
- @tryEnsureIndex { 'u._id': 1, 'name': 1, 't': 1, 'code': 1 }, { unique: 1 }
- @tryEnsureIndex { 'open': 1 }
- @tryEnsureIndex { 'alert': 1 }
- @tryEnsureIndex { 'unread': 1 }
- @tryEnsureIndex { 'ts': 1 }
- @tryEnsureIndex { 'ls': 1 }
- @tryEnsureIndex { 'desktopNotifications': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'mobilePushNotifications': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'emailNotifications': 1 }, { sparse: 1 }
-
- this.cache.ensureIndex('rid', 'array')
- this.cache.ensureIndex('u._id', 'array')
- this.cache.ensureIndex(['rid', 'u._id'], 'unique')
- this.cache.ensureIndex(['name', 'u._id'], 'unique')
-
-
- # FIND ONE
- findOneByRoomIdAndUserId: (roomId, userId) ->
- if this.useCache
- return this.cache.findByIndex('rid,u._id', [roomId, userId]).fetch()
- query =
- rid: roomId
- "u._id": userId
-
- return @findOne query
-
- findOneByRoomNameAndUserId: (roomName, userId) ->
- if this.useCache
- return this.cache.findByIndex('name,u._id', [roomName, userId]).fetch()
- query =
- name: roomName
- "u._id": userId
-
- return @findOne query
-
- # FIND
- findByUserId: (userId, options) ->
- if this.useCache
- return this.cache.findByIndex('u._id', userId, options)
-
- query =
- "u._id": userId
-
- return @find query, options
-
- findByUserIdUpdatedAfter: (userId, updatedAt, options) ->
- query =
- "u._id": userId
- _updatedAt:
- $gt: updatedAt
-
- return @find query, options
-
- # FIND
- findByRoomIdAndRoles: (roomId, roles, options) ->
- roles = [].concat roles
- query =
- "rid": roomId
- "roles": { $in: roles }
-
- return @find query, options
-
- findByType: (types, options) ->
- query =
- t:
- $in: types
-
- return @find query, options
-
- findByTypeAndUserId: (type, userId, options) ->
- query =
- t: type
- 'u._id': userId
-
- return @find query, options
-
- findByTypeNameAndUserId: (type, name, userId, options) ->
- query =
- t: type
- name: name
- 'u._id': userId
-
- return @find query, options
-
- findByRoomId: (roomId, options) ->
- if this.useCache
- return this.cache.findByIndex('rid', roomId, options)
-
- query =
- rid: roomId
-
- return @find query, options
-
- findByRoomIdAndNotUserId: (roomId, userId, options) ->
- query =
- rid: roomId
- 'u._id':
- $ne: userId
-
- return @find query, options
-
- getLastSeen: (options = {}) ->
- query = { ls: { $exists: 1 } }
- options.sort = { ls: -1 }
- options.limit = 1
-
- return @find(query, options)?.fetch?()?[0]?.ls
-
- findByRoomIdAndUserIds: (roomId, userIds) ->
- query =
- rid: roomId
- 'u._id':
- $in: userIds
-
- return @find query
-
- # UPDATE
- archiveByRoomId: (roomId) ->
- query =
- rid: roomId
-
- update =
- $set:
- alert: false
- open: false
- archived: true
-
- return @update query, update, { multi: true }
-
- unarchiveByRoomId: (roomId) ->
- query =
- rid: roomId
-
- update =
- $set:
- alert: false
- open: true
- archived: false
-
- return @update query, update, { multi: true }
-
- hideByRoomIdAndUserId: (roomId, userId) ->
- query =
- rid: roomId
- 'u._id': userId
-
- update =
- $set:
- alert: false
- open: false
-
- return @update query, update
-
- openByRoomIdAndUserId: (roomId, userId) ->
- query =
- rid: roomId
- 'u._id': userId
-
- update =
- $set:
- open: true
-
- return @update query, update
-
- setAsReadByRoomIdAndUserId: (roomId, userId) ->
- query =
- rid: roomId
- 'u._id': userId
-
- update =
- $set:
- open: true
- alert: false
- unread: 0
- ls: new Date
-
- return @update query, update
-
- setAsUnreadByRoomIdAndUserId: (roomId, userId, firstMessageUnreadTimestamp) ->
- query =
- rid: roomId
- 'u._id': userId
-
- update =
- $set:
- open: true
- alert: true
- ls: firstMessageUnreadTimestamp
-
- return @update query, update
-
- setFavoriteByRoomIdAndUserId: (roomId, userId, favorite=true) ->
- query =
- rid: roomId
- 'u._id': userId
-
- update =
- $set:
- f: favorite
-
- return @update query, update
-
- updateNameAndAlertByRoomId: (roomId, name) ->
- query =
- rid: roomId
-
- update =
- $set:
- name: name
- alert: true
-
- return @update query, update, { multi: true }
-
- updateNameByRoomId: (roomId, name) ->
- query =
- rid: roomId
-
- update =
- $set:
- name: name
-
- return @update query, update, { multi: true }
-
- setUserUsernameByUserId: (userId, username) ->
- query =
- "u._id": userId
-
- update =
- $set:
- "u.username": username
-
- return @update query, update, { multi: true }
-
- setNameForDirectRoomsWithOldName: (oldName, name) ->
- query =
- name: oldName
- t: "d"
-
- update =
- $set:
- name: name
-
- return @update query, update, { multi: true }
-
- incUnreadOfDirectForRoomIdExcludingUserId: (roomId, userId, inc=1) ->
- query =
- rid: roomId
- t: 'd'
- 'u._id':
- $ne: userId
-
- update =
- $set:
- alert: true
- open: true
- $inc:
- unread: inc
-
- return @update query, update, { multi: true }
-
- incUnreadForRoomIdExcludingUserId: (roomId, userId, inc=1) ->
- query =
- rid: roomId
- 'u._id':
- $ne: userId
-
- update =
- $set:
- alert: true
- open: true
- $inc:
- unread: inc
-
- return @update query, update, { multi: true }
-
- incUnreadForRoomIdAndUserIds: (roomId, userIds, inc=1) ->
- query =
- rid: roomId
- 'u._id':
- $in: userIds
-
- update =
- $set:
- alert: true
- open: true
- $inc:
- unread: inc
-
- return @update query, update, { multi: true }
-
- setAlertForRoomIdExcludingUserId: (roomId, userId) ->
- query =
- rid: roomId
- 'u._id':
- $ne: userId
- $or: [
- { alert: { $ne: true } }
- { open: { $ne: true } }
- ]
-
- update =
- $set:
- alert: true
- open: true
-
- return @update query, update, { multi: true }
-
- setBlockedByRoomId: (rid, blocked, blocker) ->
- query =
- rid: rid
- 'u._id': blocked
-
- update =
- $set:
- blocked: true
-
- query2 =
- rid: rid
- 'u._id': blocker
-
- update2 =
- $set:
- blocker: true
-
- return @update(query, update) and @update(query2, update2)
-
- unsetBlockedByRoomId: (rid, blocked, blocker) ->
- query =
- rid: rid
- 'u._id': blocked
-
- update =
- $unset:
- blocked: 1
-
- query2 =
- rid: rid
- 'u._id': blocker
-
- update2 =
- $unset:
- blocker: 1
-
- return @update(query, update) and @update(query2, update2)
-
- updateTypeByRoomId: (roomId, type) ->
- query =
- rid: roomId
-
- update =
- $set:
- t: type
-
- return @update query, update, { multi: true }
-
- addRoleById: (_id, role) ->
- query =
- _id: _id
-
- update =
- $addToSet:
- roles: role
-
- return @update query, update
-
- removeRoleById: (_id, role) ->
- query =
- _id: _id
-
- update =
- $pull:
- roles: role
-
- return @update query, update
-
- setArchivedByUsername: (username, archived) ->
- query =
- t: 'd'
- name: username
-
- update =
- $set:
- archived: archived
-
- return @update query, update, { multi: true }
-
- # INSERT
- createWithRoomAndUser: (room, user, extraData) ->
- subscription =
- open: false
- alert: false
- unread: 0
- ts: room.ts
- rid: room._id
- name: room.name
- t: room.t
- u:
- _id: user._id
- username: user.username
-
- _.extend subscription, extraData
-
- return @insert subscription
-
-
- # REMOVE
- removeByUserId: (userId) ->
- query =
- "u._id": userId
-
- return @remove query
-
- removeByRoomId: (roomId) ->
- query =
- rid: roomId
-
- return @remove query
-
- removeByRoomIdAndUserId: (roomId, userId) ->
- query =
- rid: roomId
- "u._id": userId
-
- return @remove query
-
-RocketChat.models.Subscriptions = new ModelSubscriptions('subscription', true)
diff --git a/packages/rocketchat-lib/server/models/Subscriptions.js b/packages/rocketchat-lib/server/models/Subscriptions.js
new file mode 100644
index 0000000000000..760be01abb2ce
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Subscriptions.js
@@ -0,0 +1,643 @@
+import _ from 'underscore';
+
+class ModelSubscriptions extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+
+ this.tryEnsureIndex({ 'rid': 1, 'u._id': 1, 'serverId': 1 }, { unique: 1 });
+ this.tryEnsureIndex({ 'rid': 1, 'alert': 1, 'u._id': 1 });
+ this.tryEnsureIndex({ 'rid': 1, 'roles': 1 });
+ this.tryEnsureIndex({ 'u._id': 1, 'name': 1, 't': 1, 'serverId': 1 });
+ this.tryEnsureIndex({ 'u._id': 1, 'name': 1, 't': 1, 'code': 1, 'serverId': 1 }, { unique: 1 });
+ this.tryEnsureIndex({ 'open': 1 });
+ this.tryEnsureIndex({ 'alert': 1 });
+ this.tryEnsureIndex({ 'unread': 1 });
+ this.tryEnsureIndex({ 'ts': 1 });
+ this.tryEnsureIndex({ 'ls': 1 });
+ this.tryEnsureIndex({ 'audioNotifications': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'desktopNotifications': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'mobilePushNotifications': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'emailNotifications': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'autoTranslate': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'autoTranslateLanguage': 1 }, { sparse: 1 });
+
+ this.cache.ensureIndex('rid', 'array');
+ this.cache.ensureIndex('u._id', 'array');
+ this.cache.ensureIndex('name', 'array');
+ this.cache.ensureIndex(['rid', 'u._id', 'serverId'], 'unique');
+ this.cache.ensureIndex(['name', 'u._id', 'serverId'], 'unique');
+ }
+
+
+ // FIND ONE
+ findOneByRoomIdAndUserId(roomId, userId) {
+ if (this.useCache) {
+ return this.cache.findByIndex('rid,u._id', [roomId, userId]).fetch();
+ }
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ return this.findOne(query);
+ }
+
+ findOneByRoomNameAndUserId(roomName, userId) {
+ if (this.useCache) {
+ return this.cache.findByIndex('name,u._id', [roomName, userId]).fetch();
+ }
+ const query = {
+ name: roomName,
+ 'u._id': userId
+ };
+
+ return this.findOne(query);
+ }
+
+ // FIND
+ findByUserId(userId, options) {
+ if (this.useCache) {
+ return this.cache.findByIndex('u._id', userId, options);
+ }
+
+ const query =
+ {'u._id': userId};
+
+ return this.find(query, options);
+ }
+
+ findByUserIdAndServers(userId, serverIds, options) {
+ serverIds = [].concat(serverIds);
+ const query = {
+ 'u._id': userId,
+ $or: [
+ { 'serverId': { $in: serverIds } },
+ { t: 'd' }
+ ]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByUserIdUpdatedAfter(userId, updatedAt, options) {
+ const query = {
+ 'u._id': userId,
+ _updatedAt: {
+ $gt: updatedAt
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ // FIND
+ findByRoomIdAndRoles(roomId, roles, options) {
+ roles = [].concat(roles);
+ const query = {
+ 'rid': roomId,
+ 'roles': { $in: roles }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByType(types, options) {
+ const query = {
+ t: {
+ $in: types
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypeAndUserId(type, userId, options) {
+ const query = {
+ t: type,
+ 'u._id': userId
+ };
+
+ return this.find(query, options);
+ }
+
+ findByTypeNameAndUserId(type, name, userId, options) {
+ const query = {
+ t: type,
+ name,
+ 'u._id': userId
+ };
+
+ return this.find(query, options);
+ }
+
+ findByRoomId(roomId, options) {
+ if (this.useCache) {
+ return this.cache.findByIndex('rid', roomId, options);
+ }
+
+ const query =
+ {rid: roomId};
+
+ return this.find(query, options);
+ }
+
+ findByRoomIdAndNotUserId(roomId, userId, options) {
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $ne: userId
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ getLastSeen(options) {
+ if (options == null) { options = {}; }
+ const query = { ls: { $exists: 1 } };
+ options.sort = { ls: -1 };
+ options.limit = 1;
+ const [subscription] = this.find(query, options).fetch();
+ return subscription && subscription.ls;
+ }
+
+ findByRoomIdAndUserIds(roomId, userIds) {
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $in: userIds
+ }
+ };
+
+ return this.find(query);
+ }
+
+ findByRoomIdAndUserIdsOrAllMessages(roomId, userIds) {
+ const query = {
+ rid: roomId,
+ $or: [
+ { 'u._id': { $in: userIds } },
+ { emailNotifications: 'all' }
+ ]
+ };
+
+ return this.find(query);
+ }
+
+ findUnreadByUserId(userId) {
+ const query = {
+ 'u._id': userId,
+ unread: {
+ $gt: 0
+ }
+ };
+
+ return this.find(query, { fields: { unread: 1 } });
+ }
+
+ getMinimumLastSeenByRoomId(rid) {
+ return this.db.findOne({
+ rid
+ }, {
+ sort: {
+ ls: 1
+ },
+ fields: {
+ ls: 1
+ }
+ });
+ }
+
+ // UPDATE
+ archiveByRoomId(roomId) {
+ const query =
+ {rid: roomId};
+
+ const update = {
+ $set: {
+ alert: false,
+ open: false,
+ archived: true
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ unarchiveByRoomId(roomId) {
+ const query =
+ {rid: roomId};
+
+ const update = {
+ $set: {
+ alert: false,
+ open: true,
+ archived: false
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ hideByRoomIdAndUserId(roomId, userId) {
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ const update = {
+ $set: {
+ alert: false,
+ open: false
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ openByRoomIdAndUserId(roomId, userId) {
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ const update = {
+ $set: {
+ open: true
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setAsReadByRoomIdAndUserId(roomId, userId) {
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ const update = {
+ $set: {
+ open: true,
+ alert: false,
+ unread: 0,
+ userMentions: 0,
+ groupMentions: 0,
+ ls: new Date
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setAsUnreadByRoomIdAndUserId(roomId, userId, firstMessageUnreadTimestamp) {
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ const update = {
+ $set: {
+ open: true,
+ alert: true,
+ ls: firstMessageUnreadTimestamp
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setCustomFieldsDirectMessagesByUserId(userId, fields) {
+ const values = {};
+ Object.keys(fields).forEach(key => {
+ values[`customFields.${ key }`] = fields[key];
+ });
+
+ const query = {
+ 'u._id': userId,
+ 't': 'd'
+ };
+ const update = { $set: values };
+ const options = { 'multi': true };
+
+ return this.update(query, update, options);
+ }
+
+ setFavoriteByRoomIdAndUserId(roomId, userId, favorite) {
+ if (favorite == null) { favorite = true; }
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ const update = {
+ $set: {
+ f: favorite
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateNameAndAlertByRoomId(roomId, name, fname) {
+ const query =
+ {rid: roomId};
+
+ const update = {
+ $set: {
+ name,
+ fname,
+ alert: true
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ updateNameByRoomId(roomId, name) {
+ const query =
+ {rid: roomId};
+
+ const update = {
+ $set: {
+ name
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ setUserUsernameByUserId(userId, username) {
+ const query =
+ {'u._id': userId};
+
+ const update = {
+ $set: {
+ 'u.username': username
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ setNameForDirectRoomsWithOldName(oldName, name) {
+ const query = {
+ name: oldName,
+ t: 'd'
+ };
+
+ const update = {
+ $set: {
+ name
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ incUnreadForRoomIdExcludingUserId(roomId, userId, inc) {
+ if (inc == null) { inc = 1; }
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $ne: userId
+ }
+ };
+
+ const update = {
+ $set: {
+ alert: true,
+ open: true
+ },
+ $inc: {
+ unread: inc
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ incGroupMentionsAndUnreadForRoomIdExcludingUserId(roomId, userId, incGroup = 1, incUnread = 1) {
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $ne: userId
+ }
+ };
+
+ const update = {
+ $set: {
+ alert: true,
+ open: true
+ },
+ $inc: {
+ unread: incUnread,
+ groupMentions: incGroup
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ incUserMentionsAndUnreadForRoomIdAndUserIds(roomId, userIds, incUser = 1, incUnread = 1) {
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $in: userIds
+ }
+ };
+
+ const update = {
+ $set: {
+ alert: true,
+ open: true
+ },
+ $inc: {
+ unread: incUnread,
+ userMentions: incUser
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+ setAlertForRoomIdExcludingUserId(roomId, userId) {
+ const query = {
+ rid: roomId,
+ 'u._id': {
+ $ne: userId
+ },
+ $or: [
+ { alert: { $ne: true } },
+ { open: { $ne: true } }
+ ]
+ };
+
+ const update = {
+ $set: {
+ alert: true,
+ open: true
+ }
+ };
+ return this.update(query, update, { multi: true });
+ }
+
+ setBlockedByRoomId(rid, blocked, blocker) {
+ const query = {
+ rid,
+ 'u._id': blocked
+ };
+
+ const update = {
+ $set: {
+ blocked: true
+ }
+ };
+
+ const query2 = {
+ rid,
+ 'u._id': blocker
+ };
+
+ const update2 = {
+ $set: {
+ blocker: true
+ }
+ };
+
+ return this.update(query, update) && this.update(query2, update2);
+ }
+
+ unsetBlockedByRoomId(rid, blocked, blocker) {
+ const query = {
+ rid,
+ 'u._id': blocked
+ };
+
+ const update = {
+ $unset: {
+ blocked: 1
+ }
+ };
+
+ const query2 = {
+ rid,
+ 'u._id': blocker
+ };
+
+ const update2 = {
+ $unset: {
+ blocker: 1
+ }
+ };
+
+ return this.update(query, update) && this.update(query2, update2);
+ }
+
+ updateTypeByRoomId(roomId, type) {
+ const query =
+ {rid: roomId};
+
+ const update = {
+ $set: {
+ t: type
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ addRoleById(_id, role) {
+ const query =
+ {_id};
+
+ const update = {
+ $addToSet: {
+ roles: role
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ removeRoleById(_id, role) {
+ const query =
+ {_id};
+
+ const update = {
+ $pull: {
+ roles: role
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setArchivedByUsername(username, archived) {
+ const query = {
+ t: 'd',
+ name: username
+ };
+
+ const update = {
+ $set: {
+ archived
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
+ // INSERT
+ createWithRoomAndUser(room, user, serverId, extraData) {
+ const subscription = {
+ open: false,
+ alert: false,
+ unread: 0,
+ userMentions: 0,
+ groupMentions: 0,
+ ts: room.ts,
+ rid: room._id,
+ name: room.name,
+ fname: room.fname,
+ customFields: room.customFields,
+ t: room.t,
+ serverId,
+ u: {
+ _id: user._id,
+ username: user.username,
+ name: user.name
+ }
+ };
+
+ _.extend(subscription, extraData);
+
+ return this.insert(subscription);
+ }
+
+
+ // REMOVE
+ removeByUserId(userId) {
+ const query =
+ {'u._id': userId};
+
+ return this.remove(query);
+ }
+
+ removeByRoomId(roomId) {
+ const query =
+ {rid: roomId};
+
+ return this.remove(query);
+ }
+
+ removeByRoomIdAndUserId(roomId, userId) {
+ const query = {
+ rid: roomId,
+ 'u._id': userId
+ };
+
+ return this.remove(query);
+ }
+}
+
+RocketChat.models.Subscriptions = new ModelSubscriptions('subscription');
diff --git a/packages/rocketchat-lib/server/models/Uploads.coffee b/packages/rocketchat-lib/server/models/Uploads.coffee
deleted file mode 100644
index 53dd792568919..0000000000000
--- a/packages/rocketchat-lib/server/models/Uploads.coffee
+++ /dev/null
@@ -1,73 +0,0 @@
-RocketChat.models.Uploads = new class extends RocketChat.models._Base
- constructor: ->
- super('uploads')
-
- @tryEnsureIndex { 'rid': 1 }
- @tryEnsureIndex { 'uploadedAt': 1 }
-
- findNotHiddenFilesOfRoom: (roomId, limit) ->
- fileQuery =
- rid: roomId
- complete: true
- uploading: false
- _hidden:
- $ne: true
-
- fileOptions =
- limit: limit
- sort:
- uploadedAt: -1
- fields:
- _id: 1
- userId: 1
- rid: 1
- name: 1
- description: 1
- type: 1
- url: 1
- uploadedAt: 1
-
- return @find fileQuery, fileOptions
-
- insertFileInit: (roomId, userId, store, file, extra) ->
- fileData =
- rid: roomId
- userId: userId
- store: store
- complete: false
- uploading: true
- progress: 0
- extension: s.strRightBack(file.name, '.')
- uploadedAt: new Date()
-
- _.extend(fileData, file, extra);
-
- if @model.direct?.insert?
- file = @model.direct.insert fileData
- else
- file = @insert fileData
-
- return file
-
- updateFileComplete: (fileId, userId, file) ->
- if not fileId
- return
-
- filter =
- _id: fileId
- userId: userId
-
- update =
- $set:
- complete: true
- uploading: false
- progress: 1
-
- update.$set = _.extend file, update.$set
-
- if @model.direct?.insert?
- result = @model.direct.update filter, update
- else
- result = @update filter, update
-
- return result
diff --git a/packages/rocketchat-lib/server/models/Uploads.js b/packages/rocketchat-lib/server/models/Uploads.js
new file mode 100644
index 0000000000000..49693c06b39ec
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Uploads.js
@@ -0,0 +1,106 @@
+/* globals InstanceStatus */
+import _ from 'underscore';
+import s from 'underscore.string';
+
+RocketChat.models.Uploads = new class extends RocketChat.models._Base {
+ constructor() {
+ super('uploads');
+
+ this.model.before.insert((userId, doc) => {
+ doc.instanceId = InstanceStatus.id();
+ });
+
+ this.tryEnsureIndex({ 'rid': 1 });
+ this.tryEnsureIndex({ 'uploadedAt': 1 });
+ }
+
+ findNotHiddenFilesOfRoom(roomId, limit) {
+ const fileQuery = {
+ rid: roomId,
+ complete: true,
+ uploading: false,
+ _hidden: {
+ $ne: true
+ }
+ };
+
+ const fileOptions = {
+ limit,
+ sort: {
+ uploadedAt: -1
+ },
+ fields: {
+ _id: 1,
+ userId: 1,
+ rid: 1,
+ name: 1,
+ description: 1,
+ type: 1,
+ url: 1,
+ uploadedAt: 1
+ }
+ };
+
+ return this.find(fileQuery, fileOptions);
+ }
+
+ insertFileInit(userId, store, file, extra) {
+ const fileData = {
+ userId,
+ store,
+ complete: false,
+ uploading: true,
+ progress: 0,
+ extension: s.strRightBack(file.name, '.'),
+ uploadedAt: new Date()
+ };
+
+ _.extend(fileData, file, extra);
+
+ if (this.model.direct && this.model.direct.insert != null) {
+ file = this.model.direct.insert(fileData);
+ } else {
+ file = this.insert(fileData);
+ }
+
+ return file;
+ }
+
+ updateFileComplete(fileId, userId, file) {
+ let result;
+ if (!fileId) {
+ return;
+ }
+
+ const filter = {
+ _id: fileId,
+ userId
+ };
+
+ const update = {
+ $set: {
+ complete: true,
+ uploading: false,
+ progress: 1
+ }
+ };
+
+ update.$set = _.extend(file, update.$set);
+
+ if (this.model.direct && this.model.direct.update != null) {
+ result = this.model.direct.update(filter, update);
+ } else {
+ result = this.update(filter, update);
+ }
+
+ return result;
+ }
+
+ deleteFile(fileId) {
+ if (this.model.direct && this.model.direct.remove != null) {
+ return this.model.direct.remove({ _id: fileId });
+ } else {
+ return this.remove({ _id: fileId });
+ }
+ }
+};
diff --git a/packages/rocketchat-lib/server/models/Users.coffee b/packages/rocketchat-lib/server/models/Users.coffee
deleted file mode 100644
index f5c6a201f3c1f..0000000000000
--- a/packages/rocketchat-lib/server/models/Users.coffee
+++ /dev/null
@@ -1,419 +0,0 @@
-class ModelUsers extends RocketChat.models._Base
- constructor: ->
- super(arguments...)
-
- @tryEnsureIndex { 'roles': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'name': 1 }
- @tryEnsureIndex { 'lastLogin': 1 }
- @tryEnsureIndex { 'status': 1 }
- @tryEnsureIndex { 'active': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'statusConnection': 1 }, { sparse: 1 }
- @tryEnsureIndex { 'type': 1 }
-
- findOneByImportId: (_id, options) ->
- return @findOne { importIds: _id }, options
-
- findOneByUsername: (username, options) ->
- query =
- username: username
-
- return @findOne query, options
-
- findOneByEmailAddress: (emailAddress, options) ->
- query =
- 'emails.address': new RegExp("^" + s.escapeRegExp(emailAddress) + "$", 'i')
-
- return @findOne query, options
-
- findOneAdmin: (admin, options) ->
- query =
- admin: admin
-
- return @findOne query, options
-
- findOneByIdAndLoginToken: (_id, token, options) ->
- query =
- _id: _id
- 'services.resume.loginTokens.hashedToken' : Accounts._hashLoginToken(token)
-
- return @findOne query, options
-
-
- # FIND
- findById: (userId) ->
- query =
- _id: userId
-
- return @find query
-
- findUsersNotOffline: (options) ->
- query =
- username:
- $exists: 1
- status:
- $in: ['online', 'away', 'busy']
-
- return @find query, options
-
-
- findByUsername: (username, options) ->
- query =
- username: username
-
- return @find query, options
-
- findUsersByUsernamesWithHighlights: (usernames, options) ->
- if this.useCache
- result =
- fetch: () ->
- return RocketChat.models.Users.getDynamicView('highlights').data().filter (record) ->
- return usernames.indexOf(record.username) > -1
- count: () ->
- return result.fetch().length
- forEach: (fn) ->
- return result.fetch().forEach(fn)
- return result
-
- query =
- username: { $in: usernames }
- 'settings.preferences.highlights.0':
- $exists: true
-
- return @find query, options
-
- findActiveByUsernameOrNameRegexWithExceptions: (searchTerm, exceptions = [], options = {}) ->
- if not _.isArray exceptions
- exceptions = [ exceptions ]
-
- termRegex = new RegExp s.escapeRegExp(searchTerm), 'i'
- query = {
- $or: [{
- username: termRegex
- }, {
- name: termRegex
- }],
- active: true,
- type: {
- $in: ['user', 'bot']
- },
- $and: [{
- username: {
- $exists: true
- }
- }, {
- username: {
- $nin: exceptions
- }
- }]
- }
-
- return @find query, options
-
- findByActiveUsersUsernameExcept: (searchTerm, exceptions = [], options = {}) ->
- if not _.isArray exceptions
- exceptions = [ exceptions ]
-
- termRegex = new RegExp s.escapeRegExp(searchTerm), 'i'
- query =
- $and: [
- {
- active: true
- username: termRegex
- }
- {
- username: { $nin: exceptions }
- }
- ]
-
- return @find query, options
-
- findUsersByNameOrUsername: (nameOrUsername, options) ->
- query =
- username:
- $exists: 1
-
- $or: [
- {name: nameOrUsername}
- {username: nameOrUsername}
- ]
-
- type:
- $in: ['user']
-
- return @find query, options
-
- findByUsernameNameOrEmailAddress: (usernameNameOrEmailAddress, options) ->
- query =
- $or: [
- {name: usernameNameOrEmailAddress}
- {username: usernameNameOrEmailAddress}
- {'emails.address': usernameNameOrEmailAddress}
- ]
- type:
- $in: ['user', 'bot']
-
- return @find query, options
-
- findLDAPUsers: (options) ->
- query =
- ldap: true
-
- return @find query, options
-
- findCrowdUsers: (options) ->
- query =
- crowd: true
-
- return @find query, options
-
- getLastLogin: (options = {}) ->
- query = { lastLogin: { $exists: 1 } }
- options.sort = { lastLogin: -1 }
- options.limit = 1
-
- return @find(query, options)?.fetch?()?[0]?.lastLogin
-
- findUsersByUsernames: (usernames, options) ->
- query =
- username:
- $in: usernames
-
- return @find query, options
-
- # UPDATE
- addImportIds: (_id, importIds) ->
- importIds = [].concat(importIds)
-
- query =
- _id: _id
-
- update =
- $addToSet:
- importIds:
- $each: importIds
-
- return @update query, update
-
- updateLastLoginById: (_id) ->
- update =
- $set:
- lastLogin: new Date
-
- return @update _id, update
-
- setServiceId: (_id, serviceName, serviceId) ->
- update =
- $set: {}
-
- serviceIdKey = "services.#{serviceName}.id"
- update.$set[serviceIdKey] = serviceId
-
- return @update _id, update
-
- setUsername: (_id, username) ->
- update =
- $set: username: username
-
- return @update _id, update
-
- setEmail: (_id, email) ->
- update =
- $set:
- emails: [
- address: email
- verified: false
- ]
-
- return @update _id, update
-
- setEmailVerified: (_id, email) ->
- query =
- _id: _id
- emails:
- $elemMatch:
- address: email
- verified: false
-
- update =
- $set:
- 'emails.$.verified': true
-
- return @update query, update
-
- setName: (_id, name) ->
- update =
- $set:
- name: name
-
- return @update _id, update
-
- setCustomFields: (_id, fields) ->
- values = {}
- for key, value of fields
- values["customFields.#{key}"] = value
-
- update =
- $set: values
-
- return @update _id, update
-
- setAvatarOrigin: (_id, origin) ->
- update =
- $set:
- avatarOrigin: origin
-
- return @update _id, update
-
- unsetAvatarOrigin: (_id) ->
- update =
- $unset:
- avatarOrigin: 1
-
- return @update _id, update
-
- setUserActive: (_id, active=true) ->
- update =
- $set:
- active: active
-
- return @update _id, update
-
- setAllUsersActive: (active) ->
- update =
- $set:
- active: active
-
- return @update {}, update, { multi: true }
-
- unsetLoginTokens: (_id) ->
- update =
- $set:
- "services.resume.loginTokens" : []
-
- return @update _id, update
-
- unsetRequirePasswordChange: (_id) ->
- update =
- $unset:
- "requirePasswordChange" : true
- "requirePasswordChangeReason" : true
-
- return @update _id, update
-
- resetPasswordAndSetRequirePasswordChange: (_id, requirePasswordChange, requirePasswordChangeReason) ->
- update =
- $unset:
- "services.password": 1
- $set:
- "requirePasswordChange" : requirePasswordChange,
- "requirePasswordChangeReason": requirePasswordChangeReason
-
- return @update _id, update
-
- setLanguage: (_id, language) ->
- update =
- $set:
- language: language
-
- return @update _id, update
-
- setProfile: (_id, profile) ->
- update =
- $set:
- "settings.profile": profile
-
- return @update _id, update
-
- setPreferences: (_id, preferences) ->
- update =
- $set:
- "settings.preferences": preferences
-
- return @update _id, update
-
- setUtcOffset: (_id, utcOffset) ->
- query =
- _id: _id
- utcOffset:
- $ne: utcOffset
-
- update =
- $set:
- utcOffset: utcOffset
-
- return @update query, update
-
- saveUserById: (_id, data) ->
- setData = {}
- unsetData = {}
-
- if data.name?
- if not _.isEmpty(s.trim(data.name))
- setData.name = s.trim(data.name)
- else
- unsetData.name = 1
-
- if data.email?
- if not _.isEmpty(s.trim(data.email))
- setData.emails = [
- address: s.trim(data.email)
- ]
- else
- unsetData.emails = 1
-
- if data.phone?
- if not _.isEmpty(s.trim(data.phone))
- setData.phone = [
- phoneNumber: s.trim(data.phone)
- ]
- else
- unsetData.phone = 1
-
- update = {}
-
- if not _.isEmpty setData
- update.$set = setData
-
- if not _.isEmpty unsetData
- update.$unset = unsetData
-
- if _.isEmpty update
- return true
-
- return @update { _id: _id }, update
-
- # INSERT
- create: (data) ->
- user =
- createdAt: new Date
- avatarOrigin: 'none'
-
- _.extend user, data
-
- return @insert user
-
-
- # REMOVE
- removeById: (_id) ->
- return @remove _id
-
- ###
- Find users to send a message by email if:
- - he is not online
- - has a verified email
- - has not disabled email notifications
- - `active` is equal to true (false means they were deactivated and can't login)
- ###
- getUsersToSendOfflineEmail: (usersIds) ->
- query =
- _id:
- $in: usersIds
- active: true
- status: 'offline'
- statusConnection:
- $ne: 'online'
- 'emails.verified': true
-
- return @find query, { fields: { name: 1, username: 1, emails: 1, 'settings.preferences.emailNotificationMode': 1 } }
-
-RocketChat.models.Users = new ModelUsers(Meteor.users, true)
diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js
new file mode 100644
index 0000000000000..55b10463cdf0f
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/Users.js
@@ -0,0 +1,631 @@
+import _ from 'underscore';
+import s from 'underscore.string';
+
+class ModelUsers extends RocketChat.models._Base {
+ constructor() {
+ super(...arguments);
+
+ this.tryEnsureIndex({ 'roles': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'name': 1 });
+ this.tryEnsureIndex({ 'lastLogin': 1 });
+ this.tryEnsureIndex({ 'status': 1 });
+ this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 });
+ this.tryEnsureIndex({ 'type': 1 });
+
+ this.cache.ensureIndex('username', 'unique');
+ }
+
+ findOneByImportId(_id, options) {
+ return this.findOne({ importIds: _id }, options);
+ }
+
+ findOneByUsername(username, options) {
+ if (typeof username === 'string') {
+ username = new RegExp(`^${ username }$`, 'i');
+ }
+
+ const query = {username};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByEmailAddress(emailAddress, options) {
+ const query = {'emails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')};
+
+ return this.findOne(query, options);
+ }
+
+ findOneAdmin(admin, options) {
+ const query = {admin};
+
+ return this.findOne(query, options);
+ }
+
+ findOneByIdAndLoginToken(_id, token, options) {
+ const query = {
+ _id,
+ 'services.resume.loginTokens.hashedToken' : Accounts._hashLoginToken(token)
+ };
+
+ return this.findOne(query, options);
+ }
+
+
+ // FIND
+ findById(userId) {
+ const query = {_id: userId};
+
+ return this.find(query);
+ }
+
+ findUsersNotOffline(options) {
+ const query = {
+ username: {
+ $exists: 1
+ },
+ status: {
+ $in: ['online', 'away', 'busy']
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+
+ findByUsername(username, options) {
+ const query = {username};
+
+ return this.find(query, options);
+ }
+
+ findUsersByUsernamesWithHighlights(usernames, options) {
+ if (this.useCache) {
+ const result = {
+ fetch() {
+ return RocketChat.models.Users.getDynamicView('highlights').data().filter(record => usernames.indexOf(record.username) > -1);
+ },
+ count() {
+ return result.fetch().length;
+ },
+ forEach(fn) {
+ return result.fetch().forEach(fn);
+ }
+ };
+ return result;
+ }
+
+ const query = {
+ username: { $in: usernames },
+ 'settings.preferences.highlights.0': {
+ $exists: true
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findActiveByUsernameOrNameRegexWithExceptions(searchTerm, exceptions, options) {
+ if (exceptions == null) { exceptions = []; }
+ if (options == null) { options = {}; }
+ if (!_.isArray(exceptions)) {
+ exceptions = [ exceptions ];
+ }
+
+ const termRegex = new RegExp(s.escapeRegExp(searchTerm), 'i');
+ const query = {
+ $or: [{
+ username: termRegex
+ }, {
+ name: termRegex
+ }],
+ active: true,
+ type: {
+ $in: ['user', 'bot']
+ },
+ $and: [{
+ username: {
+ $exists: true
+ }
+ }, {
+ username: {
+ $nin: exceptions
+ }
+ }]
+ };
+
+ return this.find(query, options);
+ }
+
+ findByActiveUsersExcept(searchTerm, exceptions, options) {
+ if (exceptions == null) { exceptions = []; }
+ if (options == null) { options = {}; }
+ if (!_.isArray(exceptions)) {
+ exceptions = [ exceptions ];
+ }
+
+ const termRegex = new RegExp(s.escapeRegExp(searchTerm), 'i');
+
+ const orStmt = _.reduce(RocketChat.settings.get('Accounts_SearchFields').trim().split(','), function(acc, el) {
+ acc.push({ [el.trim()]: termRegex });
+ return acc;
+ }, []);
+ const query = {
+ $and: [
+ {
+ active: true,
+ $or: orStmt
+ },
+ {
+ username: { $exists: true, $nin: exceptions }
+ }
+ ]
+ };
+
+ // do not use cache
+ return this._db.find(query, options);
+ }
+
+ findUsersByNameOrUsername(nameOrUsername, options) {
+ const query = {
+ username: {
+ $exists: 1
+ },
+
+ $or: [
+ {name: nameOrUsername},
+ {username: nameOrUsername}
+ ],
+
+ type: {
+ $in: ['user']
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findByUsernameNameOrEmailAddress(usernameNameOrEmailAddress, options) {
+ const query = {
+ $or: [
+ {name: usernameNameOrEmailAddress},
+ {username: usernameNameOrEmailAddress},
+ {'emails.address': usernameNameOrEmailAddress}
+ ],
+ type: {
+ $in: ['user', 'bot']
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findLDAPUsers(options) {
+ const query = {ldap: true};
+
+ return this.find(query, options);
+ }
+
+ findCrowdUsers(options) {
+ const query = {crowd: true};
+
+ return this.find(query, options);
+ }
+
+ getLastLogin(options) {
+ if (options == null) { options = {}; }
+ const query = { lastLogin: { $exists: 1 } };
+ options.sort = { lastLogin: -1 };
+ options.limit = 1;
+ const [user] = this.find(query, options).fetch();
+ return user && user.lastLogin;
+ }
+
+ findUsersByUsernames(usernames, options) {
+ const query = {
+ username: {
+ $in: usernames
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findUsersByIds(ids, options) {
+ const query = {
+ _id: {
+ $in: ids
+ }
+ };
+ return this.find(query, options);
+ }
+
+ // UPDATE
+ addImportIds(_id, importIds) {
+ importIds = [].concat(importIds);
+
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ importIds: {
+ $each: importIds
+ }
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setLastOpenServer(_id, serverId) {
+ const query = {_id};
+
+ const update = {
+ $set: {
+ lastOpenServer: serverId
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ addServer(_id, serverId) {
+ const query = {_id};
+
+ const update = {
+ $addToSet: {
+ servers: serverId
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ updateLastLoginById(_id) {
+ const update = {
+ $set: {
+ lastLogin: new Date
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setServiceId(_id, serviceName, serviceId) {
+ const update =
+ {$set: {}};
+
+ const serviceIdKey = `services.${ serviceName }.id`;
+ update.$set[serviceIdKey] = serviceId;
+
+ return this.update(_id, update);
+ }
+
+ setUsername(_id, username) {
+ const update =
+ {$set: {username}};
+
+ return this.update(_id, update);
+ }
+
+ setEmail(_id, email) {
+ const update = {
+ $set: {
+ emails: [{
+ address: email,
+ verified: false
+ }
+ ]
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setEmailVerified(_id, email) {
+ const query = {
+ _id,
+ emails: {
+ $elemMatch: {
+ address: email,
+ verified: false
+ }
+ }
+ };
+
+ const update = {
+ $set: {
+ 'emails.$.verified': true
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ setName(_id, name) {
+ const update = {
+ $set: {
+ name
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setCustomFields(_id, fields) {
+ const values = {};
+ Object.keys(fields).forEach(key => {
+ values[`customFields.${ key }`] = fields[key];
+ });
+
+ const update = {$set: values};
+
+ return this.update(_id, update);
+ }
+
+ setAvatarOrigin(_id, origin) {
+ const update = {
+ $set: {
+ avatarOrigin: origin
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ unsetAvatarOrigin(_id) {
+ const update = {
+ $unset: {
+ avatarOrigin: 1
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setUserActive(_id, active) {
+ if (active == null) { active = true; }
+ const update = {
+ $set: {
+ active
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setAllUsersActive(active) {
+ const update = {
+ $set: {
+ active
+ }
+ };
+
+ return this.update({}, update, { multi: true });
+ }
+
+ unsetLoginTokens(_id) {
+ const update = {
+ $set: {
+ 'services.resume.loginTokens' : []
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ unsetRequirePasswordChange(_id) {
+ const update = {
+ $unset: {
+ 'requirePasswordChange' : true,
+ 'requirePasswordChangeReason' : true
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ resetPasswordAndSetRequirePasswordChange(_id, requirePasswordChange, requirePasswordChangeReason) {
+ const update = {
+ $unset: {
+ 'services.password': 1
+ },
+ $set: {
+ requirePasswordChange,
+ requirePasswordChangeReason
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setLanguage(_id, language) {
+ const update = {
+ $set: {
+ language
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setProfile(_id, profile) {
+ const update = {
+ $set: {
+ 'settings.profile': profile
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ setPreferences(_id, preferences) {
+ const settings = Object.assign(
+ {},
+ ...Object.keys(preferences).map(key => {
+ return {[`settings.preferences.${ key }`]: preferences[key]};
+ })
+ );
+
+ const update = {
+ $set: settings
+ };
+
+ return this.update(_id, update);
+ }
+
+ setUtcOffset(_id, utcOffset) {
+ const query = {
+ _id,
+ utcOffset: {
+ $ne: utcOffset
+ }
+ };
+
+ const update = {
+ $set: {
+ utcOffset
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ saveUserById(_id, data) {
+ const setData = {};
+ const unsetData = {};
+
+ if (data.name != null) {
+ if (!_.isEmpty(s.trim(data.name))) {
+ setData.name = s.trim(data.name);
+ } else {
+ unsetData.name = 1;
+ }
+ }
+
+ if (data.email != null) {
+ if (!_.isEmpty(s.trim(data.email))) {
+ setData.emails = [{address: s.trim(data.email)}];
+ } else {
+ unsetData.emails = 1;
+ }
+ }
+
+ if (data.phone != null) {
+ if (!_.isEmpty(s.trim(data.phone))) {
+ setData.phone = [{phoneNumber: s.trim(data.phone)}];
+ } else {
+ unsetData.phone = 1;
+ }
+ }
+
+ const update = {};
+
+ if (!_.isEmpty(setData)) {
+ update.$set = setData;
+ }
+
+ if (!_.isEmpty(unsetData)) {
+ update.$unset = unsetData;
+ }
+
+ if (_.isEmpty(update)) {
+ return true;
+ }
+
+ return this.update({ _id }, update);
+ }
+
+ setReason(_id, reason) {
+ const update = {
+ $set: {
+ reason
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ unsetReason(_id) {
+ const update = {
+ $unset: {
+ reason: true
+ }
+ };
+
+ return this.update(_id, update);
+ }
+
+ addBannerById(_id, banner) {
+ const update = {
+ $set: {
+ [`banners.${ banner.id }`]: banner
+ }
+ };
+
+ return this.update({ _id }, update);
+ }
+
+ removeBannerById(_id, banner) {
+ const update = {
+ $unset: {
+ [`banners.${ banner.id }`]: true
+ }
+ };
+
+ return this.update({ _id }, update);
+ }
+
+ // INSERT
+ create(data) {
+ const user = {
+ createdAt: new Date,
+ avatarOrigin: 'none'
+ };
+
+ _.extend(user, data);
+
+ return this.insert(user);
+ }
+
+
+ // REMOVE
+ removeById(_id) {
+ return this.remove(_id);
+ }
+
+ /*
+Find users to send a message by email if:
+- he is not online
+- has a verified email
+- has not disabled email notifications
+- `active` is equal to true (false means they were deactivated and can't login)
+*/
+ getUsersToSendOfflineEmail(usersIds) {
+ const query = {
+ _id: {
+ $in: usersIds
+ },
+ active: true,
+ status: 'offline',
+ statusConnection: {
+ $ne: 'online'
+ },
+ 'emails.verified': true
+ };
+
+ const options = {
+ fields: {
+ name: 1,
+ username: 1,
+ emails: 1,
+ 'settings.preferences.emailNotificationMode': 1,
+ language: 1
+ }
+ };
+
+ return this.find(query, options);
+ }
+}
+
+RocketChat.models.Users = new ModelUsers(Meteor.users);
diff --git a/packages/rocketchat-lib/server/models/_BaseCache.js b/packages/rocketchat-lib/server/models/_BaseCache.js
index 6f9cd4a2ac0d9..1e01cabb86619 100644
--- a/packages/rocketchat-lib/server/models/_BaseCache.js
+++ b/packages/rocketchat-lib/server/models/_BaseCache.js
@@ -1,5 +1,5 @@
/* eslint new-cap: 0 */
-
+import _ from 'underscore';
import loki from 'lokijs';
import {EventEmitter} from 'events';
import objectPath from 'object-path';
@@ -35,6 +35,10 @@ loki.LokiOps.$nin = function(a, b) {
return !loki.LokiOps.$in(a, b);
};
+loki.LokiOps.$all = function(a, b) {
+ return b.every(subB => a.includes(subB));
+};
+
loki.LokiOps.$exists = function(a, b) {
if (b) {
return loki.LokiOps.$ne(a, undefined);
@@ -86,7 +90,7 @@ function traceMethodCalls(target) {
setInterval(function() {
for (const property in target._stats) {
if (target._stats.hasOwnProperty(property) && target._stats[property].time > 0) {
- const tags = [`property:${property}`, `collection:${target.collectionName}`];
+ const tags = [`property:${ property }`, `collection:${ target.collectionName }`];
RocketChat.statsTracker.timing('cache.methods.time', target._stats[property].avg, tags);
RocketChat.statsTracker.increment('cache.methods.totalTime', target._stats[property].time, tags);
RocketChat.statsTracker.increment('cache.methods.count', target._stats[property].calls, tags);
@@ -164,32 +168,32 @@ class ModelsBaseCache extends EventEmitter {
join({join, field, link, multi}) {
if (!RocketChat.models[join]) {
- console.log(`Invalid cache model ${join}`);
+ console.log(`Invalid cache model ${ join }`);
return;
}
RocketChat.models[join].cache.on('inserted', (record) => {
- this.processRemoteJoinInserted({join, field, link, multi, record: record});
+ this.processRemoteJoinInserted({join, field, link, multi, record});
});
RocketChat.models[join].cache.on('beforeupdate', (record, diff) => {
if (diff[link.remote]) {
- this.processRemoteJoinRemoved({join, field, link, multi, record: record});
+ this.processRemoteJoinRemoved({join, field, link, multi, record});
}
});
RocketChat.models[join].cache.on('updated', (record, diff) => {
if (diff[link.remote]) {
- this.processRemoteJoinInserted({join, field, link, multi, record: record});
+ this.processRemoteJoinInserted({join, field, link, multi, record});
}
});
RocketChat.models[join].cache.on('removed', (record) => {
- this.processRemoteJoinRemoved({join, field, link, multi, record: record});
+ this.processRemoteJoinRemoved({join, field, link, multi, record});
});
this.on('inserted', (localRecord) => {
- this.processLocalJoinInserted({join, field, link, multi, localRecord: localRecord});
+ this.processLocalJoinInserted({join, field, link, multi, localRecord});
});
this.on('beforeupdate', (localRecord, diff) => {
@@ -204,7 +208,7 @@ class ModelsBaseCache extends EventEmitter {
this.on('updated', (localRecord, diff) => {
if (diff[link.local]) {
- this.processLocalJoinInserted({join, field, link, multi, localRecord: localRecord});
+ this.processLocalJoinInserted({join, field, link, multi, localRecord});
}
});
}
@@ -220,24 +224,30 @@ class ModelsBaseCache extends EventEmitter {
localRecords = [localRecords];
}
- for (var i = 0; i < localRecords.length; i++) {
+ for (let i = 0; i < localRecords.length; i++) {
const localRecord = localRecords[i];
if (multi === true && !localRecord[field]) {
localRecord[field] = [];
}
+ if (typeof link.where === 'function' && link.where(localRecord, record) === false) {
+ continue;
+ }
+
+ let mutableRecord = record;
+
if (typeof link.transform === 'function') {
- record = link.transform(localRecord, record);
+ mutableRecord = link.transform(localRecord, mutableRecord);
}
if (multi === true) {
- localRecord[field].push(record);
+ localRecord[field].push(mutableRecord);
} else {
- localRecord[field] = record;
+ localRecord[field] = mutableRecord;
}
- this.emit(`join:${field}:inserted`, localRecord, record);
- this.emit(`join:${field}:changed`, 'inserted', localRecord, record);
+ this.emit(`join:${ field }:inserted`, localRecord, mutableRecord);
+ this.emit(`join:${ field }:changed`, 'inserted', localRecord, mutableRecord);
}
}
@@ -251,6 +261,10 @@ class ModelsBaseCache extends EventEmitter {
for (let i = 0; i < records.length; i++) {
let record = records[i];
+ if (typeof link.where === 'function' && link.where(localRecord, record) === false) {
+ continue;
+ }
+
if (typeof link.transform === 'function') {
record = link.transform(localRecord, record);
}
@@ -261,8 +275,8 @@ class ModelsBaseCache extends EventEmitter {
localRecord[field] = record;
}
- this.emit(`join:${field}:inserted`, localRecord, record);
- this.emit(`join:${field}:changed`, 'inserted', localRecord, record);
+ this.emit(`join:${ field }:inserted`, localRecord, record);
+ this.emit(`join:${ field }:changed`, 'inserted', localRecord, record);
}
}
@@ -277,7 +291,7 @@ class ModelsBaseCache extends EventEmitter {
localRecords = [localRecords];
}
- for (var i = 0; i < localRecords.length; i++) {
+ for (let i = 0; i < localRecords.length; i++) {
const localRecord = localRecords[i];
if (multi === true) {
@@ -292,8 +306,8 @@ class ModelsBaseCache extends EventEmitter {
localRecord[field] = undefined;
}
- this.emit(`join:${field}:removed`, localRecord, record);
- this.emit(`join:${field}:changed`, 'removed', localRecord, record);
+ this.emit(`join:${ field }:removed`, localRecord, record);
+ this.emit(`join:${ field }:changed`, 'removed', localRecord, record);
}
}
@@ -303,8 +317,8 @@ class ModelsBaseCache extends EventEmitter {
}
this.indexes[fields.join(',')] = {
- type: type,
- fields: fields,
+ type,
+ fields,
data: {}
};
}
@@ -320,7 +334,7 @@ class ModelsBaseCache extends EventEmitter {
addToIndex(indexName, record) {
const index = this.indexes[indexName];
if (!index) {
- console.error(`Index not defined ${indexName}`);
+ console.error(`Index not defined ${ indexName }`);
return;
}
@@ -355,7 +369,7 @@ class ModelsBaseCache extends EventEmitter {
removeFromIndex(indexName, record) {
const index = this.indexes[indexName];
if (!this.indexes[indexName]) {
- console.error(`Index not defined ${indexName}`);
+ console.error(`Index not defined ${ indexName }`);
return;
}
@@ -444,7 +458,7 @@ class ModelsBaseCache extends EventEmitter {
this.insert(data[i]);
}
console.log(String(data.length), 'records load from', this.collectionName);
- RocketChat.statsTracker.timing('cache.load', RocketChat.statsTracker.now() - time, [`collection:${this.collectionName}`]);
+ RocketChat.statsTracker.timing('cache.load', RocketChat.statsTracker.now() - time, [`collection:${ this.collectionName }`]);
this.startSync();
this.loaded = true;
@@ -552,8 +566,8 @@ class ModelsBaseCache extends EventEmitter {
fieldsToGet.push('_id');
}
- let pickFields = (obj, fields) => {
- let picked = {};
+ const pickFields = (obj, fields) => {
+ const picked = {};
fields.forEach((field) => {
if (field.indexOf('.') !== -1) {
objectPath.set(picked, field, objectPath.get(obj, field));
@@ -749,6 +763,7 @@ class ModelsBaseCache extends EventEmitter {
console.error('Cache.updateDiffById: No record', this.collectionName, id, diff);
return;
}
+ this.removeFromAllIndexes(record);
const updatedFields = _.without(Object.keys(diff), ...this.ignoreUpdatedFields);
@@ -756,13 +771,14 @@ class ModelsBaseCache extends EventEmitter {
this.emit('beforeupdate', record, diff);
}
- for (let key in diff) {
+ for (const key in diff) {
if (diff.hasOwnProperty(key)) {
objectPath.set(record, key, diff[key]);
}
}
this.collection.update(record);
+ this.addToAllIndexes(record);
if (updatedFields.length > 0) {
this.emit('updated', record, diff);
@@ -778,6 +794,8 @@ class ModelsBaseCache extends EventEmitter {
}
}
+ this.removeFromAllIndexes(record);
+
const topLevelFields = Object.keys(update).map(field => field.split('.')[0]);
const updatedFields = _.without(topLevelFields, ...this.ignoreUpdatedFields);
@@ -799,7 +817,7 @@ class ModelsBaseCache extends EventEmitter {
if (update.$min) {
_.each(update.$min, (value, field) => {
- let curValue = objectPath.get(record, field);
+ const curValue = objectPath.get(record, field);
if (curValue === undefined || value < curValue) {
objectPath.set(record, field, value);
}
@@ -808,7 +826,7 @@ class ModelsBaseCache extends EventEmitter {
if (update.$max) {
_.each(update.$max, (value, field) => {
- let curValue = objectPath.get(record, field);
+ const curValue = objectPath.get(record, field);
if (curValue === undefined || value > curValue) {
objectPath.set(record, field, value);
}
@@ -841,7 +859,7 @@ class ModelsBaseCache extends EventEmitter {
if (update.$rename) {
_.each(update.$rename, (value, field) => {
- let curValue = objectPath.get(record, field);
+ const curValue = objectPath.get(record, field);
if (curValue !== undefined) {
objectPath.set(record, value, curValue);
objectPath.del(record, field);
@@ -861,7 +879,7 @@ class ModelsBaseCache extends EventEmitter {
if (update.$pop) {
_.each(update.$pop, (value, field) => {
- let curValue = objectPath.get(record, field);
+ const curValue = objectPath.get(record, field);
if (Array.isArray(curValue)) {
if (value === -1) {
curValue.shift();
@@ -900,6 +918,7 @@ class ModelsBaseCache extends EventEmitter {
}
this.collection.update(record);
+ this.addToAllIndexes(record);
if (updatedFields.length > 0) {
this.emit('updated', record, record);
diff --git a/packages/rocketchat-lib/server/models/_BaseDb.js b/packages/rocketchat-lib/server/models/_BaseDb.js
index bb78cf583a181..60dee3248d2b5 100644
--- a/packages/rocketchat-lib/server/models/_BaseDb.js
+++ b/packages/rocketchat-lib/server/models/_BaseDb.js
@@ -1,9 +1,10 @@
/* globals MongoInternals */
+import _ from 'underscore';
const baseName = 'rocketchat_';
import {EventEmitter} from 'events';
-const trash = new Mongo.Collection(baseName + '_trash');
+const trash = new Mongo.Collection(`${ baseName }_trash`);
try {
trash._ensureIndex({ collection: 1 });
trash._ensureIndex({ _deletedAt: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 30 });
@@ -11,7 +12,7 @@ try {
console.log(e);
}
-let isOplogAvailable = MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle && !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry;
+const isOplogAvailable = MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle && !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry;
let isOplogEnabled = isOplogAvailable;
RocketChat.settings.get('Force_Disable_OpLog_For_Cache', (key, value) => {
isOplogEnabled = isOplogAvailable && value === false;
@@ -159,21 +160,7 @@ class ModelsBaseDb extends EventEmitter {
}
updateHasPositionalOperator(update) {
- for (const key in update) {
- if (key.includes('.$')) {
- return true;
- }
-
- const value = update[key];
-
- if (Match.test(value, Object)) {
- if (this.updateHasPositionalOperator(value) === true) {
- return true;
- }
- }
- }
-
- return false;
+ return Object.keys(update).some(key => key.includes('.$') || (!Match.test(update[key], Object) && this.updateHasPositionalOperator(update[key])));
}
processOplogRecord(action) {
@@ -202,9 +189,9 @@ class ModelsBaseDb extends EventEmitter {
return;
}
- let diff = {};
+ const diff = {};
if (action.op.o.$set) {
- for (let key in action.op.o.$set) {
+ for (const key in action.op.o.$set) {
if (action.op.o.$set.hasOwnProperty(key)) {
diff[key] = action.op.o.$set[key];
}
@@ -212,7 +199,7 @@ class ModelsBaseDb extends EventEmitter {
}
if (action.op.o.$unset) {
- for (let key in action.op.o.$unset) {
+ for (const key in action.op.o.$unset) {
if (action.op.o.$unset.hasOwnProperty(key)) {
diff[key] = undefined;
}
@@ -259,7 +246,7 @@ class ModelsBaseDb extends EventEmitter {
update(query, update, options = {}) {
this.setUpdatedAt(update, true, query);
- let strategy = this.defineSyncStrategy(query, update, options);
+ const strategy = this.defineSyncStrategy(query, update, options);
let ids = [];
if (!isOplogEnabled && this.listenerCount('change') > 0 && strategy === 'db') {
const findOptions = {fields: {_id: 1}};
@@ -317,9 +304,9 @@ class ModelsBaseDb extends EventEmitter {
action: 'update:query',
id: undefined,
data: {
- query: query,
- update: update,
- options: options
+ query,
+ update,
+ options
},
oplog: false
});
@@ -370,7 +357,7 @@ class ModelsBaseDb extends EventEmitter {
const _id = args[0]._id;
delete args[0]._id;
args.unshift({
- _id: _id
+ _id
});
this.upsert(...args);
diff --git a/packages/rocketchat-lib/server/oauth/google.js b/packages/rocketchat-lib/server/oauth/google.js
new file mode 100644
index 0000000000000..03cd045920f67
--- /dev/null
+++ b/packages/rocketchat-lib/server/oauth/google.js
@@ -0,0 +1,61 @@
+/* globals Google */
+import _ from 'underscore';
+
+function getIdentity(accessToken) {
+ try {
+ return HTTP.get(
+ 'https://www.googleapis.com/oauth2/v1/userinfo',
+ {params: {access_token: accessToken}}).data;
+ } catch (err) {
+ throw _.extend(new Error(`Failed to fetch identity from Google. ${ err.message }`), {response: err.response});
+ }
+}
+
+function getScopes(accessToken) {
+ try {
+ return HTTP.get(
+ 'https://www.googleapis.com/oauth2/v1/tokeninfo',
+ {params: {access_token: accessToken}}).data.scope.split(' ');
+ } catch (err) {
+ throw _.extend(new Error(`Failed to fetch tokeninfo from Google. ${ err.message }`), {response: err.response});
+ }
+}
+
+
+RocketChat.registerAccessTokenService('google', function(options) {
+ check(options, Match.ObjectIncluding({
+ accessToken: String,
+ idToken: String,
+ expiresIn: Match.Integer,
+ scope: Match.Maybe(String),
+ identity: Match.Maybe(Object)
+ }));
+
+ const identity = options.identity || getIdentity(options.accessToken);
+
+ const serviceData = {
+ accessToken: options.accessToken,
+ idToken: options.idToken,
+ expiresAt: (+new Date) + (1000 * parseInt(options.expiresIn, 10)),
+ scope: options.scopes || getScopes(options.accessToken)
+ };
+
+ const fields = _.pick(identity, Google.whitelistedFields);
+ _.extend(serviceData, fields);
+
+ // only set the token in serviceData if it's there. this ensures
+ // that we don't lose old ones (since we only get this on the first
+ // log in attempt)
+ if (options.refreshToken) {
+ serviceData.refreshToken = options.refreshToken;
+ }
+
+ return {
+ serviceData,
+ options: {
+ profile: {
+ name: identity.name
+ }
+ }
+ };
+});
diff --git a/packages/rocketchat-lib/server/oauth/oauth.js b/packages/rocketchat-lib/server/oauth/oauth.js
new file mode 100644
index 0000000000000..cf6375136b01e
--- /dev/null
+++ b/packages/rocketchat-lib/server/oauth/oauth.js
@@ -0,0 +1,54 @@
+import _ from 'underscore';
+
+const AccessTokenServices = {};
+
+RocketChat.registerAccessTokenService = function(serviceName, handleAccessTokenRequest) {
+ AccessTokenServices[serviceName] = {
+ serviceName,
+ handleAccessTokenRequest
+ };
+};
+
+// Listen to calls to `login` with an oauth option set. This is where
+// users actually get logged in to meteor via oauth.
+Accounts.registerLoginHandler(function(options) {
+ if (!options.accessToken) {
+ return undefined; // don't handle
+ }
+
+ check(options, Match.ObjectIncluding({
+ serviceName: String
+ }));
+
+ const service = AccessTokenServices[options.serviceName];
+
+ // Skip everything if there's no service set by the oauth middleware
+ if (!service) {
+ throw new Error(`Unexpected AccessToken service ${ options.serviceName }`);
+ }
+
+ // Make sure we're configured
+ if (!ServiceConfiguration.configurations.findOne({service: service.serviceName})) {
+ throw new ServiceConfiguration.ConfigError();
+ }
+
+ if (!_.contains(Accounts.oauth.serviceNames(), service.serviceName)) {
+ // serviceName was not found in the registered services list.
+ // This could happen because the service never registered itself or
+ // unregisterService was called on it.
+ return {
+ type: 'oauth',
+ error: new Meteor.Error(
+ Accounts.LoginCancelledError.numericError,
+ `No registered oauth service found for: ${ service.serviceName }`
+ )
+ };
+ }
+
+ const oauthResult = service.handleAccessTokenRequest(options);
+
+ return Accounts.updateOrCreateUserFromExternalService(service.serviceName, oauthResult.serviceData, oauthResult.options);
+});
+
+
+
diff --git a/packages/rocketchat-lib/server/oauth/proxy.js b/packages/rocketchat-lib/server/oauth/proxy.js
new file mode 100644
index 0000000000000..8886aabba8a0a
--- /dev/null
+++ b/packages/rocketchat-lib/server/oauth/proxy.js
@@ -0,0 +1,12 @@
+/* globals OAuth */
+import _ from 'underscore';
+
+OAuth._redirectUri = _.wrap(OAuth._redirectUri, function(func, serviceName, ...args) {
+ const proxy = RocketChat.settings.get('Accounts_OAuth_Proxy_services').replace(/\s/g, '').split(',');
+ if (proxy.includes(serviceName)) {
+ return `${ RocketChat.settings.get('Accounts_OAuth_Proxy_host') }/oauth_redirect`;
+ } else {
+ return func(serviceName, ...args);
+ }
+
+});
diff --git a/packages/rocketchat-lib/server/publications/settings.coffee b/packages/rocketchat-lib/server/publications/settings.coffee
deleted file mode 100644
index 7f9223acb6781..0000000000000
--- a/packages/rocketchat-lib/server/publications/settings.coffee
+++ /dev/null
@@ -1,50 +0,0 @@
-Meteor.methods
- 'public-settings/get': (updatedAt) ->
- this.unblock()
-
- records = RocketChat.models.Settings.find().fetch().filter (record) ->
- return record.hidden isnt true and record.public is true
-
- if updatedAt instanceof Date
- result =
- update: records.filter (record) ->
- return record._updatedAt > updatedAt
- remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {hidden: { $ne: true }, public: true}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
-
- return result
-
- return records
-
- 'private-settings/get': (updatedAt) ->
- unless Meteor.userId()
- return []
-
- this.unblock()
-
- if not RocketChat.authz.hasPermission Meteor.userId(), 'view-privileged-setting'
- return []
-
- records = RocketChat.models.Settings.find().fetch().filter (record) ->
- return record.hidden isnt true
-
- if updatedAt instanceof Date
- return {
- update: records.filter (record) ->
- return record._updatedAt > updatedAt
- remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {hidden: { $ne: true }}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
- }
-
- return records
-
-
-RocketChat.models.Settings.cache.on 'changed', (type, setting) ->
- if setting.public is true
- RocketChat.Notifications.notifyAllInThisInstance 'public-settings-changed', type, _.pick(setting, '_id', 'value')
-
- RocketChat.Notifications.notifyLoggedInThisInstance 'private-settings-changed', type, setting
-
-
-RocketChat.Notifications.streamAll.allowRead 'private-settings-changed', ->
- if not @userId? then return false
-
- return RocketChat.authz.hasPermission @userId, 'view-privileged-setting'
diff --git a/packages/rocketchat-lib/server/publications/settings.js b/packages/rocketchat-lib/server/publications/settings.js
new file mode 100644
index 0000000000000..5707468422bf5
--- /dev/null
+++ b/packages/rocketchat-lib/server/publications/settings.js
@@ -0,0 +1,73 @@
+import _ from 'underscore';
+
+Meteor.methods({
+ 'public-settings/get'(updatedAt) {
+ this.unblock();
+ const records = RocketChat.models.Settings.find().fetch().filter(function(record) {
+ return record.hidden !== true && record['public'] === true;
+ });
+ if (updatedAt instanceof Date) {
+ return {
+ update: records.filter(function(record) {
+ return record._updatedAt > updatedAt;
+ }),
+ remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {
+ hidden: {
+ $ne: true
+ },
+ 'public': true
+ }, {
+ fields: {
+ _id: 1,
+ _deletedAt: 1
+ }
+ }).fetch()
+ };
+ }
+ return records;
+ },
+ 'private-settings/get'(updatedAt) {
+ if (!Meteor.userId()) {
+ return [];
+ }
+ this.unblock();
+ if (!RocketChat.authz.hasPermission(Meteor.userId(), 'view-privileged-setting')) {
+ return [];
+ }
+ const records = RocketChat.models.Settings.find().fetch().filter(function(record) {
+ return record.hidden !== true;
+ });
+ if (updatedAt instanceof Date) {
+ return {
+ update: records.filter(function(record) {
+ return record._updatedAt > updatedAt;
+ }),
+ remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {
+ hidden: {
+ $ne: true
+ }
+ }, {
+ fields: {
+ _id: 1,
+ _deletedAt: 1
+ }
+ }).fetch()
+ };
+ }
+ return records;
+ }
+});
+
+RocketChat.models.Settings.cache.on('changed', function(type, setting) {
+ if (setting['public'] === true) {
+ RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', type, _.pick(setting, '_id', 'value', 'editor', 'properties'));
+ }
+ return RocketChat.Notifications.notifyLoggedInThisInstance('private-settings-changed', type, setting);
+});
+
+RocketChat.Notifications.streamAll.allowRead('private-settings-changed', function() {
+ if (this.userId == null) {
+ return false;
+ }
+ return RocketChat.authz.hasPermission(this.userId, 'view-privileged-setting');
+});
diff --git a/packages/rocketchat-lib/server/startup/cache/CacheLoad.js b/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
index ac56be599002e..8f555fc454c7d 100644
--- a/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
+++ b/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
@@ -32,6 +32,28 @@ RocketChat.models.Subscriptions.cache.hasOne('Users', {
}
});
+RocketChat.models.Subscriptions.cache.hasOne('Users', {
+ field: 'fname',
+ link: {
+ local: 'name',
+ remote: 'username',
+ where(subscription/*, user*/) {
+ return subscription.t === 'd';
+ },
+ transform(subscription, user) {
+ if (user == null || subscription == null) {
+ return undefined;
+ }
+ // Prevent client cache for old subscriptions with new names
+ // Cuz when a user change his name, the subscription's _updateAt
+ // will not change
+ if (subscription._updatedAt < user._updatedAt) {
+ subscription._updatedAt = user._updatedAt;
+ }
+ return user.name;
+ }
+ }
+});
RocketChat.models.Users.cache.load();
RocketChat.models.Rooms.cache.load();
diff --git a/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee b/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee
deleted file mode 100644
index d5fb356dc4729..0000000000000
--- a/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee
+++ /dev/null
@@ -1,78 +0,0 @@
-logger = new Logger 'rocketchat:lib',
- methods:
- oauth_updated:
- type: 'info'
-
-timer = undefined
-OAuthServicesUpdate = ->
- Meteor.clearTimeout timer if timer?
-
- timer = Meteor.setTimeout ->
- services = RocketChat.settings.get(/^(Accounts_OAuth_|Accounts_OAuth_Custom-)[a-z0-9_]+$/i)
- for service in services
- logger.oauth_updated service.key
-
- serviceName = service.key.replace('Accounts_OAuth_', '')
- if serviceName is 'Meteor'
- serviceName = 'meteor-developer'
-
- if /Accounts_OAuth_Custom-/.test service.key
- serviceName = service.key.replace('Accounts_OAuth_Custom-', '')
-
- if service.value is true
- data =
- clientId: RocketChat.settings.get("#{service.key}_id")
- secret: RocketChat.settings.get("#{service.key}_secret")
-
-
- if /Accounts_OAuth_Custom-/.test service.key
- data.custom = true
- data.clientId = RocketChat.settings.get("#{service.key}-id")
- data.secret = RocketChat.settings.get("#{service.key}-secret")
- data.serverURL = RocketChat.settings.get("#{service.key}-url")
- data.tokenPath = RocketChat.settings.get("#{service.key}-token_path")
- data.identityPath = RocketChat.settings.get("#{service.key}-identity_path")
- data.authorizePath = RocketChat.settings.get("#{service.key}-authorize_path")
- data.scope = RocketChat.settings.get("#{service.key}-scope")
- data.buttonLabelText = RocketChat.settings.get("#{service.key}-button_label_text")
- data.buttonLabelColor = RocketChat.settings.get("#{service.key}-button_label_color")
- data.loginStyle = RocketChat.settings.get("#{service.key}-login_style")
- data.buttonColor = RocketChat.settings.get("#{service.key}-button_color")
- data.tokenSentVia = RocketChat.settings.get("#{service.key}-token_sent_via")
- data.usernameField = RocketChat.settings.get("#{service.key}-username_field")
- data.mergeUsers = RocketChat.settings.get("#{service.key}-merge_users")
- new CustomOAuth serviceName.toLowerCase(),
- serverURL: data.serverURL
- tokenPath: data.tokenPath
- identityPath: data.identityPath
- authorizePath: data.authorizePath
- scope: data.scope
- loginStyle: data.loginStyle
- tokenSentVia: data.tokenSentVia
- usernameField: data.usernameField
- mergeUsers: data.mergeUsers
-
- if serviceName is 'Facebook'
- data.appId = data.clientId
- delete data.clientId
-
- if serviceName is 'Twitter'
- data.consumerKey = data.clientId
- delete data.clientId
- ServiceConfiguration.configurations.upsert {service: serviceName.toLowerCase()}, $set: data
- else
- ServiceConfiguration.configurations.remove {service: serviceName.toLowerCase()}
- , 2000
-
-
-OAuthServicesRemove = (_id) ->
- serviceName = _id.replace('Accounts_OAuth_Custom-', '')
- ServiceConfiguration.configurations.remove {service: serviceName.toLowerCase()}
-
-
-RocketChat.settings.get /^Accounts_OAuth_.+/, (key, value) ->
- OAuthServicesUpdate()
-
-RocketChat.settings.get /^Accounts_OAuth_Custom-[a-z0-9_]+/, (key, value) ->
- if not value
- OAuthServicesRemove key
diff --git a/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.js b/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.js
new file mode 100644
index 0000000000000..2c6e9c3f49150
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.js
@@ -0,0 +1,96 @@
+/* globals CustomOAuth */
+import _ from 'underscore';
+
+const logger = new Logger('rocketchat:lib', {
+ methods: {
+ oauth_updated: {
+ type: 'info'
+ }
+ }
+});
+
+function _OAuthServicesUpdate() {
+ const services = RocketChat.settings.get(/^(Accounts_OAuth_|Accounts_OAuth_Custom-)[a-z0-9_]+$/i);
+ services.forEach((service) => {
+ logger.oauth_updated(service.key);
+ let serviceName = service.key.replace('Accounts_OAuth_', '');
+ if (serviceName === 'Meteor') {
+ serviceName = 'meteor-developer';
+ }
+ if (/Accounts_OAuth_Custom-/.test(service.key)) {
+ serviceName = service.key.replace('Accounts_OAuth_Custom-', '');
+ }
+ if (service.value === true) {
+ const data = {
+ clientId: RocketChat.settings.get(`${ service.key }_id`),
+ secret: RocketChat.settings.get(`${ service.key }_secret`)
+ };
+ if (/Accounts_OAuth_Custom-/.test(service.key)) {
+ data.custom = true;
+ data.clientId = RocketChat.settings.get(`${ service.key }-id`);
+ data.secret = RocketChat.settings.get(`${ service.key }-secret`);
+ data.serverURL = RocketChat.settings.get(`${ service.key }-url`);
+ data.tokenPath = RocketChat.settings.get(`${ service.key }-token_path`);
+ data.identityPath = RocketChat.settings.get(`${ service.key }-identity_path`);
+ data.authorizePath = RocketChat.settings.get(`${ service.key }-authorize_path`);
+ data.scope = RocketChat.settings.get(`${ service.key }-scope`);
+ data.buttonLabelText = RocketChat.settings.get(`${ service.key }-button_label_text`);
+ data.buttonLabelColor = RocketChat.settings.get(`${ service.key }-button_label_color`);
+ data.loginStyle = RocketChat.settings.get(`${ service.key }-login_style`);
+ data.buttonColor = RocketChat.settings.get(`${ service.key }-button_color`);
+ data.tokenSentVia = RocketChat.settings.get(`${ service.key }-token_sent_via`);
+ data.identityTokenSentVia = RocketChat.settings.get(`${ service.key }-identity_token_sent_via`);
+ data.usernameField = RocketChat.settings.get(`${ service.key }-username_field`);
+ data.mergeUsers = RocketChat.settings.get(`${ service.key }-merge_users`);
+ new CustomOAuth(serviceName.toLowerCase(), {
+ serverURL: data.serverURL,
+ tokenPath: data.tokenPath,
+ identityPath: data.identityPath,
+ authorizePath: data.authorizePath,
+ scope: data.scope,
+ loginStyle: data.loginStyle,
+ tokenSentVia: data.tokenSentVia,
+ identityTokenSentVia: data.identityTokenSentVia,
+ usernameField: data.usernameField,
+ mergeUsers: data.mergeUsers
+ });
+ }
+ if (serviceName === 'Facebook') {
+ data.appId = data.clientId;
+ delete data.clientId;
+ }
+ if (serviceName === 'Twitter') {
+ data.consumerKey = data.clientId;
+ delete data.clientId;
+ }
+ ServiceConfiguration.configurations.upsert({
+ service: serviceName.toLowerCase()
+ }, {
+ $set: data
+ });
+ } else {
+ ServiceConfiguration.configurations.remove({
+ service: serviceName.toLowerCase()
+ });
+ }
+ });
+}
+
+const OAuthServicesUpdate = _.debounce(Meteor.bindEnvironment(_OAuthServicesUpdate), 2000);
+
+function OAuthServicesRemove(_id) {
+ const serviceName = _id.replace('Accounts_OAuth_Custom-', '');
+ return ServiceConfiguration.configurations.remove({
+ service: serviceName.toLowerCase()
+ });
+}
+
+RocketChat.settings.get(/^Accounts_OAuth_.+/, function() {
+ return OAuthServicesUpdate(); // eslint-disable-line new-cap
+});
+
+RocketChat.settings.get(/^Accounts_OAuth_Custom-[a-z0-9_]+/, function(key, value) {
+ if (!value) {
+ return OAuthServicesRemove(key);// eslint-disable-line new-cap
+ }
+});
diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee
deleted file mode 100644
index 97d226b2e713b..0000000000000
--- a/packages/rocketchat-lib/server/startup/settings.coffee
+++ /dev/null
@@ -1,274 +0,0 @@
-# Insert server unique id if it doesn't exist
-RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID or Random.id(), { public: true, hidden: true });
-
-# When you define a setting and want to add a description, you don't need to automatically define the i18nDescription
-# if you add a node to the i18n.json with the same setting name but with `_Description` it will automatically work.
-RocketChat.settings.addGroup 'Accounts', ->
- @add 'Accounts_AllowDeleteOwnAccount', false, { type: 'boolean', public: true, enableQuery: { _id: 'Accounts_AllowUserProfileChange', value: true } }
- @add 'Accounts_AllowUserProfileChange', true, { type: 'boolean', public: true }
- @add 'Accounts_AllowUserAvatarChange', true, { type: 'boolean', public: true }
- @add 'Accounts_AllowUsernameChange', true, { type: 'boolean', public: true }
- @add 'Accounts_AllowEmailChange', true, { type: 'boolean', public: true }
- @add 'Accounts_AllowPasswordChange', true, { type: 'boolean', public: true }
- @add 'Accounts_LoginExpiration', 90, { type: 'int', public: true }
- @add 'Accounts_ShowFormLogin', true, { type: 'boolean', public: true }
- @add 'Accounts_EmailOrUsernamePlaceholder', '', { type: 'string', public: true, i18nLabel: 'Placeholder_for_email_or_username_login_field' }
- @add 'Accounts_PasswordPlaceholder', '', { type: 'string', public: true, i18nLabel: 'Placeholder_for_password_login_field' }
- @add 'Accounts_ForgetUserSessionOnWindowClose', false, { type: 'boolean', public: true }
-
- @section 'Registration', ->
- @add 'Accounts_RequireNameForSignUp', true, { type: 'boolean', public: true }
- @add 'Accounts_RequirePasswordConfirmation', true, { type: 'boolean', public: true }
- @add 'Accounts_EmailVerification', false, { type: 'boolean', public: true, enableQuery: {_id: 'SMTP_Host', value: { $exists: 1, $ne: "" } } }
- @add 'Accounts_ManuallyApproveNewUsers', false, { type: 'boolean' }
- @add 'Accounts_AllowedDomainsList', '', { type: 'string', public: true }
-
- @add 'Accounts_BlockedDomainsList', '', { type: 'string' }
- @add 'Accounts_BlockedUsernameList', '', { type: 'string' }
- @add 'Accounts_UseDefaultBlockedDomainsList', true, { type: 'boolean' }
- @add 'Accounts_UseDNSDomainCheck', false, { type: 'boolean' }
-
- @add 'Accounts_RegistrationForm', 'Public', { type: 'select', public: true, values: [ { key: 'Public', i18nLabel: 'Accounts_RegistrationForm_Public' }, { key: 'Disabled', i18nLabel: 'Accounts_RegistrationForm_Disabled' }, { key: 'Secret URL', i18nLabel: 'Accounts_RegistrationForm_Secret_URL' } ] }
- @add 'Accounts_RegistrationForm_SecretURL', Random.id(), { type: 'string' }
- @add 'Accounts_RegistrationForm_LinkReplacementText', 'New user registration is currently disabled', { type: 'string', public: true }
- @add 'Accounts_Registration_AuthenticationServices_Enabled', true, { type: 'boolean', public: true }
- @add 'Accounts_PasswordReset', true, { type: 'boolean', public: true }
-
- @add 'Accounts_CustomFields', '', { type: 'code', public: true, i18nLabel: 'Custom_Fields' }
-
- @section 'Avatar', ->
- @add 'Accounts_AvatarResize', true, { type: 'boolean' }
- @add 'Accounts_AvatarSize', 200, { type: 'int', enableQuery: {_id: 'Accounts_AvatarResize', value: true} }
- @add 'Accounts_AvatarStoreType', 'GridFS', { type: 'select', values: [ { key: 'GridFS', i18nLabel: 'GridFS' }, { key: 'FileSystem', i18nLabel: 'FileSystem' } ] }
- @add 'Accounts_AvatarStorePath', '', { type: 'string', enableQuery: {_id: 'Accounts_AvatarStoreType', value: 'FileSystem'} }
- @add 'Accounts_SetDefaultAvatar', true, { type: 'boolean' }
-
-RocketChat.settings.addGroup 'OAuth', ->
-
- @section 'Facebook', ->
- enableQuery = { _id: 'Accounts_OAuth_Facebook', value: true }
- @add 'Accounts_OAuth_Facebook', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Facebook_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Facebook_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Facebook_callback_url', '_oauth/facebook', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
- @section 'Google', ->
- enableQuery = { _id: 'Accounts_OAuth_Google', value: true }
- @add 'Accounts_OAuth_Google', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Google_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Google_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Google_callback_url', '_oauth/google', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
- @section 'GitHub', ->
- enableQuery = { _id: 'Accounts_OAuth_Github', value: true }
- @add 'Accounts_OAuth_Github', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Github_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Github_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Github_callback_url', '_oauth/github', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
- @section 'Linkedin', ->
- enableQuery = { _id: 'Accounts_OAuth_Linkedin', value: true }
- @add 'Accounts_OAuth_Linkedin', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Linkedin_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Linkedin_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Linkedin_callback_url', '_oauth/linkedin', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
- @section 'Meteor', ->
- enableQuery = { _id: 'Accounts_OAuth_Meteor', value: true }
- @add 'Accounts_OAuth_Meteor', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Meteor_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Meteor_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Meteor_callback_url', '_oauth/meteor', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
- @section 'Twitter', ->
- enableQuery = { _id: 'Accounts_OAuth_Twitter', value: true }
- @add 'Accounts_OAuth_Twitter', false, { type: 'boolean', public: true }
- @add 'Accounts_OAuth_Twitter_id', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Twitter_secret', '', { type: 'string', enableQuery: enableQuery }
- @add 'Accounts_OAuth_Twitter_callback_url', '_oauth/twitter', { type: 'relativeUrl', readonly: true, force: true, enableQuery: enableQuery }
-
-
-RocketChat.settings.addGroup 'General', ->
-
- @add 'Site_Url', __meteor_runtime_config__?.ROOT_URL, { type: 'string', i18nDescription: 'Site_Url_Description', public: true }
- @add 'Site_Name', 'Rocket.Chat', { type: 'string', public: true }
- @add 'Language', '', { type: 'language', public: true }
- @add 'Allow_Invalid_SelfSigned_Certs', false, { type: 'boolean' }
- @add 'Favorite_Rooms', true, { type: 'boolean', public: true }
- @add 'CDN_PREFIX', '', { type: 'string', public: true }
- @add 'Force_SSL', false, { type: 'boolean', public: true }
- @add 'GoogleTagManager_id', '', { type: 'string', public: true }
- @add 'Bugsnag_api_key', '', { type: 'string', public: false }
- @add 'Force_Disable_OpLog_For_Cache', false, { type: 'boolean', public: false }
- @add 'Restart', 'restart_server', { type: 'action', actionText: 'Restart_the_server' }
-
- @section 'UTF8', ->
- @add 'UTF8_Names_Validation', '[0-9a-zA-Z-_.]+', { type: 'string', public: true, i18nDescription: 'UTF8_Names_Validation_Description'}
- @add 'UTF8_Names_Slugify', true, { type: 'boolean', public: true }
-
- @section 'Reporting', ->
- @add 'Statistics_reporting', true, { type: 'boolean' }
-
- @section 'Notifications', ->
- @add 'Desktop_Notifications_Duration', 0, { type: 'int', public: true, i18nDescription: 'Desktop_Notification_Durations_Description' }
-
- @section 'REST API', ->
- @add 'API_User_Limit', 500, { type: 'int', public: true, i18nDescription: 'API_User_Limit' }
-
- @section 'Iframe Integration', ->
- @add 'Iframe_Integration_send_enable', false, { type: 'boolean', public: true }
- @add 'Iframe_Integration_send_target_origin', '*', { type: 'string', public: true, enableQuery: { _id: 'Iframe_Integration_send_enable', value: true } }
-
- @add 'Iframe_Integration_receive_enable', false, { type: 'boolean', public: true }
- @add 'Iframe_Integration_receive_origin', '*', { type: 'string', public: true, enableQuery: { _id: 'Iframe_Integration_receive_enable', value: true } }
-
- @section 'Translations', ->
- @add 'Custom_Translations', '', { type: 'code', public: true }
-
- @section 'Stream Cast', ->
- @add 'Stream_Cast_Address', '', { type: 'string' }
-
-RocketChat.settings.addGroup 'Email', ->
- @section 'Header and Footer', ->
- @add 'Email_Header', '[Site_Name] ', {
- type: 'code',
- code: 'text/html',
- multiline: true,
- i18nLabel: 'Header'
- }
- @add 'Email_Footer', '
Powered by Rocket.Chat
', {
- type: 'code',
- code: 'text/html',
- multiline: true,
- i18nLabel: 'Footer'
- }
-
- @section 'SMTP', ->
- @add 'SMTP_Host', '', { type: 'string', env: true, i18nLabel: 'Host' }
- @add 'SMTP_Port', '', { type: 'string', env: true, i18nLabel: 'Port' }
- @add 'SMTP_Username', '', { type: 'string', env: true, i18nLabel: 'Username' }
- @add 'SMTP_Password', '', { type: 'password', env: true, i18nLabel: 'Password' }
- @add 'From_Email', '', { type: 'string', placeholder: 'email@domain' }
- @add 'SMTP_Test_Button', 'sendSMTPTestEmail', { type: 'action', actionText: 'Send_a_test_mail_to_my_user' }
-
- @section 'Invitation', ->
- @add 'Invitation_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
- @add 'Invitation_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Invitation_Customized', value: true }, i18nDefaultQuery: { _id: 'Invitation_Customized', value: false } }
- @add 'Invitation_HTML', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Invitation_HTML_Description', enableQuery: { _id: 'Invitation_Customized', value: true }, i18nDefaultQuery: { _id: 'Invitation_Customized', value: false } }
-
- @section 'Registration', ->
- @add 'Accounts_Enrollment_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
- @add 'Accounts_Enrollment_Email_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Accounts_Enrollment_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_Enrollment_Customized', value: false } }
- @add 'Accounts_Enrollment_Email', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', enableQuery: { _id: 'Accounts_Enrollment_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_Enrollment_Customized', value: false } }
-
- @section 'Registration via Admin', ->
- @add 'Accounts_UserAddedEmail_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
- @add 'Accounts_UserAddedEmailSubject', '', { type: 'string', i18nLabel: "Subject", enableQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: false } }
- @add 'Accounts_UserAddedEmail', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Accounts_UserAddedEmail_Description', enableQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: false } }
-
- @section 'Forgot Password', ->
- @add 'Forgot_Password_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
- @add 'Forgot_Password_Email_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Forgot_Password_Customized', value: true }, i18nDefaultQuery: { _id: 'Forgot_Password_Customized', value: false } }
- @add 'Forgot_Password_Email', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Forgot_Password_Description', enableQuery: { _id: 'Forgot_Password_Customized', value: true }, i18nDefaultQuery: { _id: 'Forgot_Password_Customized', value: false } }
-
- @section 'Verification', ->
- @add 'Verification_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
- @add 'Verification_Email_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Verification_Customized', value: true }, i18nDefaultQuery: { _id: 'Verification_Customized', value: false } }
- @add 'Verification_Email', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Verification_Description', enableQuery: { _id: 'Verification_Customized', value: true }, i18nDefaultQuery: { _id: 'Verification_Customized', value: false } }
-
-RocketChat.settings.addGroup 'Message', ->
- @add 'Message_AllowEditing', true, { type: 'boolean', public: true }
- @add 'Message_AllowEditing_BlockEditInMinutes', 0, { type: 'int', public: true, i18nDescription: 'Message_AllowEditing_BlockEditInMinutesDescription' }
- @add 'Message_AllowDeleting', true, { type: 'boolean', public: true }
- @add 'Message_AllowDeleting_BlockDeleteInMinutes', 0, { type: 'int', public: true, i18nDescription: 'Message_AllowDeleting_BlockDeleteInMinutes' }
- @add 'Message_AllowUnrecognizedSlashCommand', false, { type: 'boolean', public: true}
- @add 'Message_AlwaysSearchRegExp', false, { type: 'boolean' }
- @add 'Message_ShowEditedStatus', true, { type: 'boolean', public: true }
- @add 'Message_ShowDeletedStatus', false, { type: 'boolean', public: true }
- @add 'Message_AllowBadWordsFilter', false, { type: 'boolean', public: true}
- @add 'Message_BadWordsFilterList', '', {type: 'string', public: true}
- @add 'Message_KeepHistory', false, { type: 'boolean', public: true }
- @add 'Message_MaxAll', 0, { type: 'int', public: true }
- @add 'Message_MaxAllowedSize', 5000, { type: 'int', public: true }
- @add 'Message_ShowFormattingTips', true, { type: 'boolean', public: true }
- @add 'Message_SetNameToAliasEnabled', false, { type: 'boolean', public: false, i18nDescription: 'Message_SetNameToAliasEnabled_Description' }
- @add 'Message_AudioRecorderEnabled', true, { type: 'boolean', public: true, i18nDescription: 'Message_AudioRecorderEnabledDescription' }
- @add 'Message_GroupingPeriod', 300, { type: 'int', public: true, i18nDescription: 'Message_GroupingPeriodDescription' }
- @add 'API_Embed', true, { type: 'boolean', public: true }
- @add 'API_EmbedCacheExpirationDays', 30, { type: 'int', public: false }
- @add 'API_Embed_clear_cache_now', 'OEmbedCacheCleanup', { type: 'action', actionText: 'clear', i18nLabel: 'clear_cache_now' }
- @add 'API_EmbedDisabledFor', '', { type: 'string', public: true, i18nDescription: 'API_EmbedDisabledFor_Description' }
- @add 'API_EmbedIgnoredHosts', 'localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16', { type: 'string', i18nDescription: 'API_EmbedIgnoredHosts_Description' }
- @add 'API_EmbedSafePorts', '80, 443', { type: 'string' }
- @add 'Message_TimeFormat', 'LT', { type: 'string', public: true, i18nDescription: 'Message_TimeFormat_Description' }
- @add 'Message_DateFormat', 'LL', { type: 'string', public: true, i18nDescription: 'Message_DateFormat_Description' }
- @add 'Message_HideType_uj', false, { type: 'boolean', public: true }
- @add 'Message_HideType_ul', false, { type: 'boolean', public: true }
- @add 'Message_HideType_ru', false, { type: 'boolean', public: true }
- @add 'Message_HideType_au', false, { type: 'boolean', public: true }
- @add 'Message_HideType_mute_unmute', false, { type: 'boolean', public: true }
-
-RocketChat.settings.addGroup 'Meta', ->
- @add 'Meta_language', '', { type: 'string' }
- @add 'Meta_fb_app_id', '', { type: 'string' }
- @add 'Meta_robots', 'INDEX,FOLLOW', { type: 'string' }
- @add 'Meta_google-site-verification', '', { type: 'string' }
- @add 'Meta_msvalidate01', '', { type: 'string' }
- @add 'Meta_custom', '', { type: 'code', code: 'text/html', multiline: true }
-
-
-RocketChat.settings.addGroup 'Push', ->
- @add 'Push_enable', true, { type: 'boolean', public: true }
- @add 'Push_debug', false, { type: 'boolean', public: true, enableQuery: { _id: 'Push_enable', value: true } }
- @add 'Push_enable_gateway', true, { type: 'boolean', enableQuery: { _id: 'Push_enable', value: true } }
- @add 'Push_gateway', 'https://gateway.rocket.chat', { type: 'string', enableQuery: [{ _id: 'Push_enable', value: true }, { _id: 'Push_enable_gateway', value: true }] }
- @add 'Push_production', true, { type: 'boolean', public: true, enableQuery: [{ _id: 'Push_enable', value: true }, { _id: 'Push_enable_gateway', value: false }] }
- @add 'Push_test_push', 'push_test', { type: 'action', actionText: 'Send_a_test_push_to_my_user', enableQuery: { _id: 'Push_enable', value: true } }
-
- @section 'Certificates_and_Keys', ->
- @add 'Push_apn_passphrase', '', { type: 'string' }
- @add 'Push_apn_key', '', { type: 'string', multiline: true }
- @add 'Push_apn_cert', '', { type: 'string', multiline: true }
- @add 'Push_apn_dev_passphrase', '', { type: 'string' }
- @add 'Push_apn_dev_key', '', { type: 'string', multiline: true }
- @add 'Push_apn_dev_cert', '', { type: 'string', multiline: true }
- @add 'Push_gcm_api_key', '', { type: 'string' }
- @add 'Push_gcm_project_number', '', { type: 'string', public: true }
-
- @section 'Privacy', ->
- @add 'Push_show_username_room', true, { type: 'boolean', public: true }
- @add 'Push_show_message', true, { type: 'boolean', public: true }
-
-
-RocketChat.settings.addGroup 'Layout', ->
-
- @section 'Content', ->
- @add 'Layout_Home_Title', 'Home', { type: 'string', public: true }
- @add 'Layout_Home_Body', 'Welcome to Rocket.Chat Go to APP SETTINGS -> Layout to customize this intro.', { type: 'code', code: 'text/html', multiline: true, public: true }
- @add 'Layout_Terms_of_Service', 'Terms of Service Go to APP SETTINGS -> Layout to customize this page.', { type: 'code', code: 'text/html', multiline: true, public: true }
- @add 'Layout_Login_Terms', 'By proceeding you are agreeing to our Terms of Service and Privacy Policy .', { type: 'string', multiline: true, public: true }
- @add 'Layout_Privacy_Policy', 'Privacy Policy Go to APP SETTINGS -> Layout to customize this page.', { type: 'code', code: 'text/html', multiline: true, public: true }
- @add 'Layout_Sidenav_Footer', ' ', { type: 'code', code: 'text/html', public: true, i18nDescription: 'Layout_Sidenav_Footer_description' }
-
- @section 'Custom Scripts', ->
- @add 'Custom_Script_Logged_Out', '//Add your script', { type: 'code', multiline: true, public: true }
- @add 'Custom_Script_Logged_In', '//Add your script', { type: 'code', multiline: true, public: true }
-
- @section 'User Interface', ->
- @add 'UI_DisplayRoles', true, { type: 'boolean', public: true }
- @add 'UI_Merge_Channels_Groups', true, { type: 'boolean', public: true }
- @add 'UI_Use_Name_Avatar', false, { type: 'boolean', public: true }
-
-
-RocketChat.settings.addGroup 'Logs', ->
- @add 'Log_Level', '0', { type: 'select', values: [ { key: '0', i18nLabel: '0_Errors_Only' }, { key: '1', i18nLabel: '1_Errors_and_Information' }, { key: '2', i18nLabel: '2_Erros_Information_and_Debug' } ] , public: true }
- @add 'Log_Package', false, { type: 'boolean', public: true }
- @add 'Log_File', false, { type: 'boolean', public: true }
- @add 'Log_View_Limit', 1000, { type: 'int' }
-
-
-RocketChat.settings.init()
-
-# # Remove runtime settings (non-persistent)
-# Meteor.startup ->
-# RocketChat.models.Settings.update({ ts: { $lt: RocketChat.settings.ts }, persistent: { $ne: true } }, { $set: { hidden: true } }, { multi: true })
diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js
new file mode 100644
index 0000000000000..771d298bc0b39
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/settings.js
@@ -0,0 +1,1582 @@
+// Insert server unique id if it doesn't exist
+RocketChat.settings.add('uniqueID', process.env.DEPLOYMENT_ID || Random.id(), {
+ 'public': true,
+ hidden: true
+});
+
+// When you define a setting and want to add a description, you don't need to automatically define the i18nDescription
+// if you add a node to the i18n.json with the same setting name but with `_Description` it will automatically work.
+
+RocketChat.settings.addGroup('Accounts', function() {
+ this.add('Accounts_AllowAnonymousRead', false, {
+ type: 'boolean',
+ public: true
+ });
+ this.add('Accounts_AllowAnonymousWrite', false, {
+ type: 'boolean',
+ public: true,
+ enableQuery: {
+ _id: 'Accounts_AllowAnonymousRead',
+ value: true
+ }
+ });
+ this.add('Accounts_AllowDeleteOwnAccount', false, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: {
+ _id: 'Accounts_AllowUserProfileChange',
+ value: true
+ }
+ });
+ this.add('Accounts_AllowUserProfileChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_AllowUserAvatarChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_AllowRealNameChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_AllowUsernameChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_AllowEmailChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_AllowPasswordChange', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_CustomFieldsToShowInUserInfo', '', {
+ type: 'string',
+ public: true
+ });
+ this.add('Accounts_LoginExpiration', 90, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Accounts_ShowFormLogin', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_EmailOrUsernamePlaceholder', '', {
+ type: 'string',
+ 'public': true,
+ i18nLabel: 'Placeholder_for_email_or_username_login_field'
+ });
+ this.add('Accounts_PasswordPlaceholder', '', {
+ type: 'string',
+ 'public': true,
+ i18nLabel: 'Placeholder_for_password_login_field'
+ });
+ this.add('Accounts_ForgetUserSessionOnWindowClose', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_SearchFields', 'username, name, emails.address', {
+ type: 'string',
+ public: true
+ });
+
+ this.section('Registration', function() {
+ this.add('Accounts_DefaultUsernamePrefixSuggestion', 'user', {
+ type: 'string'
+ });
+ this.add('Accounts_RequireNameForSignUp', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_RequirePasswordConfirmation', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_EmailVerification', false, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: {
+ _id: 'SMTP_Host',
+ value: {
+ $exists: 1,
+ $ne: ''
+ }
+ }
+ });
+ this.add('Accounts_ManuallyApproveNewUsers', false, {
+ 'public': true,
+ type: 'boolean'
+ });
+ this.add('Accounts_AllowedDomainsList', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Accounts_BlockedDomainsList', '', {
+ type: 'string'
+ });
+ this.add('Accounts_BlockedUsernameList', '', {
+ type: 'string'
+ });
+ this.add('Accounts_UseDefaultBlockedDomainsList', true, {
+ type: 'boolean'
+ });
+ this.add('Accounts_UseDNSDomainCheck', false, {
+ type: 'boolean'
+ });
+ this.add('Accounts_RegistrationForm', 'Public', {
+ type: 'select',
+ 'public': true,
+ values: [
+ {
+ key: 'Public',
+ i18nLabel: 'Accounts_RegistrationForm_Public'
+ }, {
+ key: 'Disabled',
+ i18nLabel: 'Accounts_RegistrationForm_Disabled'
+ }, {
+ key: 'Secret URL',
+ i18nLabel: 'Accounts_RegistrationForm_Secret_URL'
+ }
+ ]
+ });
+ this.add('Accounts_RegistrationForm_SecretURL', Random.id(), {
+ type: 'string'
+ });
+ this.add('Accounts_RegistrationForm_LinkReplacementText', 'New user registration is currently disabled', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Accounts_Registration_AuthenticationServices_Enabled', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_Registration_AuthenticationServices_Default_Roles', 'user', {
+ type: 'string',
+ enableQuery: {
+ _id: 'Accounts_Registration_AuthenticationServices_Enabled',
+ value: true
+ }
+ });
+ this.add('Accounts_PasswordReset', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_CustomFields', '', {
+ type: 'code',
+ 'public': true,
+ i18nLabel: 'Custom_Fields'
+ });
+ });
+
+ this.section('Accounts_Default_User_Preferences', function() {
+ this.add('Accounts_Default_User_Preferences_enableAutoAway', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Enable_Auto_Away'
+ });
+ this.add('Accounts_Default_User_Preferences_idleTimeoutLimit', 300000, {
+ type: 'int',
+ 'public': true,
+ i18nLabel: 'Idle_Time_Limit'
+ });
+ this.add('Accounts_Default_User_Preferences_desktopNotificationDuration', 0, {
+ type: 'int',
+ 'public': true,
+ i18nLabel: 'Notification_Duration'
+ });
+ this.add('Accounts_Default_User_Preferences_audioNotifications', 'mentions', {
+ type: 'select',
+ values: [
+ {
+ key: 'all',
+ i18nLabel: 'All_messages'
+ },
+ {
+ key: 'mentions',
+ i18nLabel: 'Mentions'
+ },
+ {
+ key: 'nothing',
+ i18nLabel: 'Nothing'
+ }
+ ],
+ public: true
+ });
+ this.add('Accounts_Default_User_Preferences_desktopNotifications', 'mentions', {
+ type: 'select',
+ values: [
+ {
+ key: 'all',
+ i18nLabel: 'All_messages'
+ },
+ {
+ key: 'mentions',
+ i18nLabel: 'Mentions'
+ },
+ {
+ key: 'nothing',
+ i18nLabel: 'Nothing'
+ }
+ ],
+ 'public': true
+ });
+ this.add('Accounts_Default_User_Preferences_mobileNotifications', 'mentions', {
+ type: 'select',
+ values: [
+ {
+ key : 'all',
+ i18nLabel : 'All_messages'
+ },
+ {
+ key : 'mentions',
+ i18nLabel : 'Mentions'
+ },
+ {
+ key : 'nothing',
+ i18nLabel : 'Nothing'
+ }
+ ],
+ 'public': true
+ });
+ this.add('Accounts_Default_User_Preferences_unreadAlert', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Unread_Tray_Icon_Alert'
+ });
+ this.add('Accounts_Default_User_Preferences_useEmojis', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Use_Emojis'
+ });
+ this.add('Accounts_Default_User_Preferences_convertAsciiEmoji', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Convert_Ascii_Emojis'
+ });
+ this.add('Accounts_Default_User_Preferences_autoImageLoad', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Auto_Load_Images'
+ });
+ this.add('Accounts_Default_User_Preferences_saveMobileBandwidth', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Save_Mobile_Bandwidth'
+ });
+ this.add('Accounts_Default_User_Preferences_collapseMediaByDefault', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Collapse_Embedded_Media_By_Default'
+ });
+ this.add('Accounts_Default_User_Preferences_hideUsernames', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Hide_usernames'
+ });
+ this.add('Accounts_Default_User_Preferences_hideRoles', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Hide_roles'
+ });
+ this.add('Accounts_Default_User_Preferences_hideFlexTab', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Hide_flextab'
+ });
+ this.add('Accounts_Default_User_Preferences_hideAvatars', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Hide_Avatars'
+ });
+ this.add('Accounts_Default_User_Preferences_roomsListExhibitionMode', 'category', {
+ type: 'select',
+ values: [
+ {
+ key: 'unread',
+ i18nLabel: 'Unread_Rooms_Mode'
+ },
+ {
+ key: 'activity',
+ i18nLabel: 'Sort_by_activity'
+ },
+ {
+ key: 'category',
+ i18nLabel: 'Split_by_categories'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'Sidebar_list_mode'
+ });
+ this.add('Accounts_Default_User_Preferences_mergeChannels', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'UI_Merge_Channels_Groups'
+ });
+ this.add('Accounts_Default_User_Preferences_sidebarShowUnread', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Unread_on_top'
+ });
+ this.add('Accounts_Default_User_Preferences_sidebarShowFavorites', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Group_favorites'
+ });
+ this.add('Accounts_Default_User_Preferences_sendOnEnter', 'normal', {
+ type: 'select',
+ values: [
+ {
+ key: 'normal',
+ i18nLabel: 'Enter_Normal'
+ },
+ {
+ key: 'alternative',
+ i18nLabel: 'Enter_Alternative'
+ },
+ {
+ key: 'desktop',
+ i18nLabel: 'Only_On_Desktop'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'Enter_Behaviour'
+ });
+ this.add('Accounts_Default_User_Preferences_viewMode', 0, {
+ type: 'select',
+ values: [
+ {
+ key: 0,
+ i18nLabel: 'Normal'
+ },
+ {
+ key: 1,
+ i18nLabel: 'Cozy'
+ },
+ {
+ key: 2,
+ i18nLabel: 'Compact'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'View_mode'
+ });
+ this.add('Accounts_Default_User_Preferences_emailNotificationMode', 'all', {
+ type: 'select',
+ values: [
+ {
+ key: 'disabled',
+ i18nLabel: 'Email_Notification_Mode_Disabled'
+ },
+ {
+ key: 'all',
+ i18nLabel: 'Email_Notification_Mode_All'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'Email_Notification_Mode'
+ });
+ this.add('Accounts_Default_User_Preferences_roomCounterSidebar', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Show_room_counter_on_sidebar'
+ });
+ this.add('Accounts_Default_User_Preferences_newRoomNotification', 'door', {
+ type: 'select',
+ values: [
+ {
+ key: 'none',
+ i18nLabel: 'None'
+ },
+ {
+ key: 'door',
+ i18nLabel: 'Default'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'New_Room_Notification'
+ });
+ this.add('Accounts_Default_User_Preferences_newMessageNotification', 'chime', {
+ type: 'select',
+ values: [
+ {
+ key: 'none',
+ i18nLabel: 'None'
+ },
+ {
+ key: 'chime',
+ i18nLabel: 'Default'
+ }
+ ],
+ 'public': true,
+ i18nLabel: 'New_Message_Notification'
+ });
+ this.add('Accounts_Default_User_Preferences_muteFocusedConversations', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nLabel: 'Mute_Focused_Conversations'
+ });
+ this.add('Accounts_Default_User_Preferences_notificationsSoundVolume', 100, {
+ type: 'int',
+ 'public': true,
+ i18nLabel: 'Notifications_Sound_Volume'
+ });
+ });
+
+ this.section('Avatar', function() {
+ this.add('Accounts_AvatarResize', true, {
+ type: 'boolean'
+ });
+ this.add('Accounts_AvatarSize', 200, {
+ type: 'int',
+ enableQuery: {
+ _id: 'Accounts_AvatarResize',
+ value: true
+ }
+ });
+
+ return this.add('Accounts_SetDefaultAvatar', true, {
+ type: 'boolean'
+ });
+ });
+});
+
+RocketChat.settings.addGroup('OAuth', function() {
+ this.section('Facebook', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Facebook',
+ value: true
+ };
+ this.add('Accounts_OAuth_Facebook', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Facebook_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Facebook_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Facebook_callback_url', '_oauth/facebook', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ this.section('Google', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Google',
+ value: true
+ };
+ this.add('Accounts_OAuth_Google', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Google_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Google_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Google_callback_url', '_oauth/google', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ this.section('GitHub', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Github',
+ value: true
+ };
+ this.add('Accounts_OAuth_Github', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Github_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Github_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Github_callback_url', '_oauth/github', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ this.section('Linkedin', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Linkedin',
+ value: true
+ };
+ this.add('Accounts_OAuth_Linkedin', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Linkedin_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Linkedin_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Linkedin_callback_url', '_oauth/linkedin', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ this.section('Meteor', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Meteor',
+ value: true
+ };
+ this.add('Accounts_OAuth_Meteor', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Meteor_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Meteor_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Meteor_callback_url', '_oauth/meteor', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ this.section('Twitter', function() {
+ const enableQuery = {
+ _id: 'Accounts_OAuth_Twitter',
+ value: true
+ };
+ this.add('Accounts_OAuth_Twitter', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Accounts_OAuth_Twitter_id', '', {
+ type: 'string',
+ enableQuery
+ });
+ this.add('Accounts_OAuth_Twitter_secret', '', {
+ type: 'string',
+ enableQuery
+ });
+ return this.add('Accounts_OAuth_Twitter_callback_url', '_oauth/twitter', {
+ type: 'relativeUrl',
+ readonly: true,
+ force: true,
+ enableQuery
+ });
+ });
+ return this.section('Proxy', function() {
+ this.add('Accounts_OAuth_Proxy_host', 'https://oauth-proxy.rocket.chat', {
+ type: 'string',
+ 'public': true
+ });
+ return this.add('Accounts_OAuth_Proxy_services', '', {
+ type: 'string',
+ 'public': true
+ });
+ });
+});
+
+RocketChat.settings.addGroup('General', function() {
+ this.add('Site_Url', typeof __meteor_runtime_config__ !== 'undefined' && __meteor_runtime_config__ !== null ? __meteor_runtime_config__.ROOT_URL : null, {
+ type: 'string',
+ i18nDescription: 'Site_Url_Description',
+ 'public': true
+ });
+ this.add('Site_Name', 'Rocket.Chat', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Language', '', {
+ type: 'language',
+ 'public': true
+ });
+ this.add('Allow_Invalid_SelfSigned_Certs', false, {
+ type: 'boolean'
+ });
+ this.add('Favorite_Rooms', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('First_Channel_After_Login', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Unread_Count', 'user_and_group_mentions_only', {
+ type: 'select',
+ values: [
+ {
+ key: 'all_messages',
+ i18nLabel: 'All_messages'
+ }, {
+ key: 'user_mentions_only',
+ i18nLabel: 'User_mentions_only'
+ }, {
+ key: 'group_mentions_only',
+ i18nLabel: 'Group_mentions_only'
+ }, {
+ key: 'user_and_group_mentions_only',
+ i18nLabel: 'User_and_group_mentions_only'
+ }
+ ],
+ 'public': true
+ });
+ this.add('Unread_Count_DM', 'all_messages', {
+ type: 'select',
+ values: [
+ {
+ key: 'all_messages',
+ i18nLabel: 'All_messages'
+ }, {
+ key: 'mentions_only',
+ i18nLabel: 'Mentions_only'
+ }
+ ],
+ 'public': true
+ });
+ this.add('CDN_PREFIX', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Force_SSL', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('GoogleTagManager_id', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Bugsnag_api_key', '', {
+ type: 'string',
+ 'public': false
+ });
+ this.add('Force_Disable_OpLog_For_Cache', false, {
+ type: 'boolean',
+ 'public': false
+ });
+ this.add('Restart', 'restart_server', {
+ type: 'action',
+ actionText: 'Restart_the_server'
+ });
+ this.add('Store_Last_Message', false, {
+ type: 'boolean',
+ public: true,
+ i18nDescription: 'Store_Last_Message_Sent_per_Room'
+ });
+ this.section('UTF8', function() {
+ this.add('UTF8_Names_Validation', '[0-9a-zA-Z-_.]+', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'UTF8_Names_Validation_Description'
+ });
+ return this.add('UTF8_Names_Slugify', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ });
+ this.section('Reporting', function() {
+ return this.add('Statistics_reporting', true, {
+ type: 'boolean'
+ });
+ });
+ this.section('Notifications', function() {
+ this.add('Notifications_Max_Room_Members', 100, {
+ type: 'int',
+ public: true,
+ i18nDescription: 'Notifications_Max_Room_Members_Description'
+ });
+
+ this.add('Notifications_Always_Notify_Mobile', false, {
+ type: 'boolean',
+ public: true,
+ i18nDescription: 'Notifications_Always_Notify_Mobile_Description'
+ });
+ });
+ this.section('REST API', function() {
+ return this.add('API_User_Limit', 500, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'API_User_Limit'
+ });
+ });
+ this.section('Iframe_Integration', function() {
+ this.add('Iframe_Integration_send_enable', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Iframe_Integration_send_target_origin', '*', {
+ type: 'string',
+ 'public': true,
+ enableQuery: {
+ _id: 'Iframe_Integration_send_enable',
+ value: true
+ }
+ });
+ this.add('Iframe_Integration_receive_enable', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ return this.add('Iframe_Integration_receive_origin', '*', {
+ type: 'string',
+ 'public': true,
+ enableQuery: {
+ _id: 'Iframe_Integration_receive_enable',
+ value: true
+ }
+ });
+ });
+ this.section('Translations', function() {
+ return this.add('Custom_Translations', '', {
+ type: 'code',
+ 'public': true
+ });
+ });
+ return this.section('Stream_Cast', function() {
+ return this.add('Stream_Cast_Address', '', {
+ type: 'string'
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Email', function() {
+ this.section('Subject', function() {
+ this.add('Offline_DM_Email', '[[Site_Name]] You have been direct messaged by [User]', {
+ type: 'code',
+ code: 'text',
+ multiline: true,
+ i18nLabel: 'Offline_DM_Email',
+ i18nDescription: 'Offline_Email_Subject_Description'
+ });
+ this.add('Offline_Mention_Email', '[[Site_Name]] You have been mentioned by [User] in #[Room]', {
+ type: 'code',
+ code: 'text',
+ multiline: true,
+ i18nLabel: 'Offline_Mention_Email',
+ i18nDescription: 'Offline_Email_Subject_Description'
+ });
+ return this.add('Offline_Mention_All_Email', '[User] has posted a message in #[Room]', {
+ type: 'code',
+ code: 'text',
+ multiline: true,
+ i18nLabel: 'Offline_Mention_All_Email',
+ i18nDescription: 'Offline_Email_Subject_Description'
+ });
+ });
+ this.section('Header_and_Footer', function() {
+ this.add('Email_Header', '[Site_Name] ', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Header'
+ });
+ this.add('Email_Footer', '
Powered by Rocket.Chat
', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Footer'
+ });
+ return this.add('Email_Footer_Direct_Reply', 'You can directly reply to this email. Do not modify previous emails in the thread. Powered by Rocket.Chat ', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Footer_Direct_Reply'
+ });
+ });
+ this.section('Direct_Reply', function() {
+ this.add('Direct_Reply_Enable', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Enable'
+ });
+ this.add('Direct_Reply_Debug', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Debug',
+ i18nDescription: 'Direct_Reply_Debug_Description'
+ });
+ this.add('Direct_Reply_Protocol', 'IMAP', {
+ type: 'select',
+ values: [
+ {
+ key: 'IMAP',
+ i18nLabel: 'IMAP'
+ }, {
+ key: 'POP',
+ i18nLabel: 'POP'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Protocol'
+ });
+ this.add('Direct_Reply_Host', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Host'
+ });
+ this.add('Direct_Reply_Port', '143', {
+ type: 'select',
+ values: [
+ {
+ key: '143',
+ i18nLabel: '143'
+ }, {
+ key: '993',
+ i18nLabel: '993'
+ }, {
+ key: '110',
+ i18nLabel: '110'
+ }, {
+ key: '995',
+ i18nLabel: '995'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Port'
+ });
+ this.add('Direct_Reply_IgnoreTLS', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'IgnoreTLS'
+ });
+ this.add('Direct_Reply_Frequency', 5, {
+ type: 'int',
+ env: true,
+ i18nLabel: 'Direct_Reply_Frequency',
+ enableQuery: {
+ _id: 'Direct_Reply_Protocol',
+ value: 'POP'
+ }
+ });
+ this.add('Direct_Reply_Delete', true, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Direct_Reply_Delete',
+ enableQuery: {
+ _id: 'Direct_Reply_Protocol',
+ value: 'IMAP'
+ }
+ });
+ this.add('Direct_Reply_Separator', '+', {
+ type: 'select',
+ values: [
+ {
+ key: '!',
+ i18nLabel: '!'
+ }, {
+ key: '#',
+ i18nLabel: '#'
+ }, {
+ key: '$',
+ i18nLabel: '$'
+ }, {
+ key: '%',
+ i18nLabel: '%'
+ }, {
+ key: '&',
+ i18nLabel: '&'
+ }, {
+ key: '\'',
+ i18nLabel: '\''
+ }, {
+ key: '*',
+ i18nLabel: '*'
+ }, {
+ key: '+',
+ i18nLabel: '+'
+ }, {
+ key: '-',
+ i18nLabel: '-'
+ }, {
+ key: '/',
+ i18nLabel: '/'
+ }, {
+ key: '=',
+ i18nLabel: '='
+ }, {
+ key: '?',
+ i18nLabel: '?'
+ }, {
+ key: '^',
+ i18nLabel: '^'
+ }, {
+ key: '_',
+ i18nLabel: '_'
+ }, {
+ key: '`',
+ i18nLabel: '`'
+ }, {
+ key: '{',
+ i18nLabel: '{'
+ }, {
+ key: '|',
+ i18nLabel: '|'
+ }, {
+ key: '}',
+ i18nLabel: '}'
+ }, {
+ key: '~',
+ i18nLabel: '~'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Direct_Reply_Separator'
+ });
+ this.add('Direct_Reply_Username', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Username',
+ placeholder: 'email@domain'
+ });
+ return this.add('Direct_Reply_Password', '', {
+ type: 'password',
+ env: true,
+ i18nLabel: 'Password'
+ });
+ });
+ this.section('SMTP', function() {
+ this.add('SMTP_Protocol', 'smtp', {
+ type: 'select',
+ values: [
+ {
+ key: 'smtp',
+ i18nLabel: 'smtp'
+ }, {
+ key: 'smtps',
+ i18nLabel: 'smtps'
+ }
+ ],
+ env: true,
+ i18nLabel: 'Protocol'
+ });
+ this.add('SMTP_Host', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Host'
+ });
+ this.add('SMTP_Port', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Port'
+ });
+ this.add('SMTP_IgnoreTLS', false, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'IgnoreTLS',
+ enableQuery: {
+ _id: 'SMTP_Protocol',
+ value: 'smtp'
+ }
+ });
+ this.add('SMTP_Pool', true, {
+ type: 'boolean',
+ env: true,
+ i18nLabel: 'Pool'
+ });
+ this.add('SMTP_Username', '', {
+ type: 'string',
+ env: true,
+ i18nLabel: 'Username'
+ });
+ this.add('SMTP_Password', '', {
+ type: 'password',
+ env: true,
+ i18nLabel: 'Password'
+ });
+ this.add('From_Email', '', {
+ type: 'string',
+ placeholder: 'email@domain'
+ });
+ return this.add('SMTP_Test_Button', 'sendSMTPTestEmail', {
+ type: 'action',
+ actionText: 'Send_a_test_mail_to_my_user'
+ });
+ });
+ this.section('Invitation', function() {
+ this.add('Invitation_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Invitation_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Invitation_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Invitation_Customized',
+ value: false
+ }
+ });
+ return this.add('Invitation_HTML', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Invitation_HTML_Description',
+ enableQuery: {
+ _id: 'Invitation_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Invitation_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Registration', function() {
+ this.add('Accounts_Enrollment_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Accounts_Enrollment_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: false
+ }
+ });
+ return this.add('Accounts_Enrollment_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ enableQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_Enrollment_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Registration_via_Admin', function() {
+ this.add('Accounts_UserAddedEmail_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Accounts_UserAddedEmailSubject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: false
+ }
+ });
+ return this.add('Accounts_UserAddedEmail', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Accounts_UserAddedEmail_Description',
+ enableQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Accounts_UserAddedEmail_Customized',
+ value: false
+ }
+ });
+ });
+ this.section('Forgot_password_section', function() {
+ this.add('Forgot_Password_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Forgot_Password_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: false
+ }
+ });
+ return this.add('Forgot_Password_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Forgot_Password_Description',
+ enableQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Forgot_Password_Customized',
+ value: false
+ }
+ });
+ });
+ return this.section('Verification', function() {
+ this.add('Verification_Customized', false, {
+ type: 'boolean',
+ i18nLabel: 'Custom'
+ });
+ this.add('Verification_Email_Subject', '', {
+ type: 'string',
+ i18nLabel: 'Subject',
+ enableQuery: {
+ _id: 'Verification_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Verification_Customized',
+ value: false
+ }
+ });
+ return this.add('Verification_Email', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ i18nLabel: 'Body',
+ i18nDescription: 'Verification_Description',
+ enableQuery: {
+ _id: 'Verification_Customized',
+ value: true
+ },
+ i18nDefaultQuery: {
+ _id: 'Verification_Customized',
+ value: false
+ }
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Message', function() {
+ this.section('Message_Attachments', function() {
+ this.add('Message_Attachments_GroupAttach', false, {
+ type: 'boolean',
+ 'public': true,
+ i18nDescription: 'Message_Attachments_GroupAttachDescription'
+ });
+ this.add('Message_AudioRecorderEnabled', true, {
+ type: 'boolean',
+ 'public': true,
+ i18nDescription: 'Message_AudioRecorderEnabledDescription'
+ });
+ });
+ this.add('Message_AllowEditing', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowEditing_BlockEditInMinutes', 0, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_AllowEditing_BlockEditInMinutesDescription'
+ });
+ this.add('Message_AllowDeleting', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowDeleting_BlockDeleteInMinutes', 0, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_AllowDeleting_BlockDeleteInMinutes'
+ });
+ this.add('Message_AllowUnrecognizedSlashCommand', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowDirectMessagesToYourself', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AlwaysSearchRegExp', false, {
+ type: 'boolean'
+ });
+ this.add('Message_ShowEditedStatus', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_ShowDeletedStatus', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_AllowBadWordsFilter', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_BadWordsFilterList', '', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Message_KeepHistory', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_MaxAll', 0, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_MaxAllowedSize', 5000, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_ShowFormattingTips', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_SetNameToAliasEnabled', false, {
+ type: 'boolean',
+ 'public': false,
+ i18nDescription: 'Message_SetNameToAliasEnabled_Description'
+ });
+ this.add('Message_GroupingPeriod', 300, {
+ type: 'int',
+ 'public': true,
+ i18nDescription: 'Message_GroupingPeriodDescription'
+ });
+ this.add('API_Embed', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('API_Embed_UserAgent', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('API_EmbedCacheExpirationDays', 30, {
+ type: 'int',
+ 'public': false
+ });
+ this.add('API_Embed_clear_cache_now', 'OEmbedCacheCleanup', {
+ type: 'action',
+ actionText: 'clear',
+ i18nLabel: 'clear_cache_now'
+ });
+ this.add('API_EmbedDisabledFor', '', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'API_EmbedDisabledFor_Description'
+ });
+ this.add('API_EmbedIgnoredHosts', 'localhost, 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16', {
+ type: 'string',
+ i18nDescription: 'API_EmbedIgnoredHosts_Description'
+ });
+ this.add('API_EmbedSafePorts', '80, 443', {
+ type: 'string'
+ });
+ this.add('Message_TimeFormat', 'LT', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_TimeFormat_Description'
+ });
+ this.add('Message_DateFormat', 'LL', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_DateFormat_Description'
+ });
+ this.add('Message_TimeAndDateFormat', 'LLL', {
+ type: 'string',
+ 'public': true,
+ i18nDescription: 'Message_TimeAndDateFormat_Description'
+ });
+ this.add('Message_QuoteChainLimit', 2, {
+ type: 'int',
+ 'public': true
+ });
+ this.add('Message_HideType_uj', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_ul', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_ru', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Message_HideType_au', false, {
+ type: 'boolean',
+ 'public': true
+ });
+
+ this.add('Message_HideType_mute_unmute', false, {
+ type: 'boolean',
+ 'public': true
+ });
+
+ this.add('Message_GlobalSearch', false, {
+ type: 'boolean',
+ 'public': true,
+ alert: 'This feature is currently in beta and could decrease the application performance! Please report bugs to github.com/RocketChat/Rocket.Chat/issues'
+ });
+});
+
+RocketChat.settings.addGroup('Meta', function() {
+ this.add('Meta_language', '', {
+ type: 'string'
+ });
+ this.add('Meta_fb_app_id', '', {
+ type: 'string'
+ });
+ this.add('Meta_robots', 'INDEX,FOLLOW', {
+ type: 'string'
+ });
+ this.add('Meta_google-site-verification', '', {
+ type: 'string'
+ });
+ this.add('Meta_msvalidate01', '', {
+ type: 'string'
+ });
+ return this.add('Meta_custom', '', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true
+ });
+});
+
+RocketChat.settings.addGroup('Push', function() {
+ this.add('Push_enable', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Push_debug', false, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.add('Push_enable_gateway', true, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.add('Push_gateway', 'https://gateway.rocket.chat', {
+ type: 'string',
+ enableQuery: [
+ {
+ _id: 'Push_enable',
+ value: true
+ }, {
+ _id: 'Push_enable_gateway',
+ value: true
+ }
+ ]
+ });
+ this.add('Push_production', true, {
+ type: 'boolean',
+ 'public': true,
+ enableQuery: [
+ {
+ _id: 'Push_enable',
+ value: true
+ }, {
+ _id: 'Push_enable_gateway',
+ value: false
+ }
+ ]
+ });
+ this.add('Push_test_push', 'push_test', {
+ type: 'action',
+ actionText: 'Send_a_test_push_to_my_user',
+ enableQuery: {
+ _id: 'Push_enable',
+ value: true
+ }
+ });
+ this.section('Certificates_and_Keys', function() {
+ this.add('Push_apn_passphrase', '', {
+ type: 'string'
+ });
+ this.add('Push_apn_key', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_cert', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_dev_passphrase', '', {
+ type: 'string'
+ });
+ this.add('Push_apn_dev_key', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_apn_dev_cert', '', {
+ type: 'string',
+ multiline: true
+ });
+ this.add('Push_gcm_api_key', '', {
+ type: 'string'
+ });
+ return this.add('Push_gcm_project_number', '', {
+ type: 'string',
+ 'public': true
+ });
+ });
+ return this.section('Privacy', function() {
+ this.add('Push_show_username_room', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ return this.add('Push_show_message', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Layout', function() {
+ this.section('Content', function() {
+ this.add('Layout_Home_Title', 'Home', {
+ type: 'string',
+ 'public': true
+ });
+ this.add('Layout_Home_Body', 'Welcome to Rocket.Chat!
\nThe Rocket.Chat desktops apps for Windows, macOS and Linux are available to download here .
The native mobile app, Rocket.Chat+,\n for Android and iOS is available from Google Play and the App Store .
\nFor further help, please consult the documentation .
\nIf you\'re an admin, feel free to change this content via Administration -> Layout -> Home Body . Or clicking here .
', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Terms_of_Service', 'Terms of Service Go to APP SETTINGS -> Layout to customize this page.', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Login_Terms', 'By proceeding you are agreeing to our Terms of Service and Privacy Policy .', {
+ type: 'string',
+ multiline: true,
+ 'public': true
+ });
+ this.add('Layout_Privacy_Policy', 'Privacy Policy Go to APP SETTINGS -> Layout to customize this page.', {
+ type: 'code',
+ code: 'text/html',
+ multiline: true,
+ 'public': true
+ });
+ return this.add('Layout_Sidenav_Footer', ' ', {
+ type: 'code',
+ code: 'text/html',
+ 'public': true,
+ i18nDescription: 'Layout_Sidenav_Footer_description'
+ });
+ });
+ this.section('Custom_Scripts', function() {
+ this.add('Custom_Script_Logged_Out', '//Add your script', {
+ type: 'code',
+ multiline: true,
+ 'public': true
+ });
+ return this.add('Custom_Script_Logged_In', '//Add your script', {
+ type: 'code',
+ multiline: true,
+ 'public': true
+ });
+ });
+ return this.section('User_Interface', function() {
+ this.add('UI_DisplayRoles', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Merge_Channels_Groups', true, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Use_Name_Avatar', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Use_Real_Name', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Click_Direct_Message', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('UI_Unread_Counter_Style', 'Different_Style_For_User_Mentions', {
+ type: 'select',
+ values: [
+ {
+ key: 'Same_Style_For_Mentions',
+ i18nLabel: 'Same_Style_For_Mentions'
+ }, {
+ key: 'Different_Style_For_User_Mentions',
+ i18nLabel: 'Different_Style_For_User_Mentions'
+ }
+ ],
+ 'public': true
+ });
+ this.add('UI_Allow_room_names_with_special_chars', false, {
+ type: 'boolean',
+ public: true
+ });
+ });
+});
+
+RocketChat.settings.addGroup('Logs', function() {
+ this.add('Log_Level', '0', {
+ type: 'select',
+ values: [
+ {
+ key: '0',
+ i18nLabel: '0_Errors_Only'
+ }, {
+ key: '1',
+ i18nLabel: '1_Errors_and_Information'
+ }, {
+ key: '2',
+ i18nLabel: '2_Erros_Information_and_Debug'
+ }
+ ],
+ 'public': true
+ });
+ this.add('Log_Package', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ this.add('Log_File', false, {
+ type: 'boolean',
+ 'public': true
+ });
+ return this.add('Log_View_Limit', 1000, {
+ type: 'int'
+ });
+});
+
+RocketChat.settings.init();
diff --git a/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.coffee b/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.coffee
deleted file mode 100644
index 2685d5fd1859b..0000000000000
--- a/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.coffee
+++ /dev/null
@@ -1,10 +0,0 @@
-RocketChat.settings.onload 'CDN_PREFIX', (key, value, initialLoad) ->
- if _.isString value
- if !!value
- WebAppInternals?.setBundledJsCssPrefix value
-
-Meteor.startup ->
- value = RocketChat.settings.get 'CDN_PREFIX'
- if _.isString value
- if !!value
- WebAppInternals?.setBundledJsCssPrefix value
diff --git a/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.js b/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.js
new file mode 100644
index 0000000000000..514438f16e272
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/settingsOnLoadCdnPrefix.js
@@ -0,0 +1,18 @@
+/* globals WebAppInternals*/
+import _ from 'underscore';
+
+function testWebAppInternals(fn) {
+ typeof WebAppInternals !== 'undefined' && fn(WebAppInternals);
+}
+RocketChat.settings.onload('CDN_PREFIX', function(key, value) {
+ if (_.isString(value) && value.trim()) {
+ return testWebAppInternals(WebAppInternals => WebAppInternals.setBundledJsCssPrefix(value));
+ }
+});
+
+Meteor.startup(function() {
+ const value = RocketChat.settings.get('CDN_PREFIX');
+ if (_.isString(value) && value.trim()) {
+ return testWebAppInternals(WebAppInternals => WebAppInternals.setBundledJsCssPrefix(value));
+ }
+});
diff --git a/packages/rocketchat-lib/server/startup/settingsOnLoadDirectReply.js b/packages/rocketchat-lib/server/startup/settingsOnLoadDirectReply.js
new file mode 100644
index 0000000000000..b172e520a93d3
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/settingsOnLoadDirectReply.js
@@ -0,0 +1,67 @@
+import _ from 'underscore';
+import { IMAPIntercepter } from '../lib/interceptDirectReplyEmails.js';
+import { POP3Helper } from '../lib/interceptDirectReplyEmails.js';
+
+const startEmailIntercepter = _.debounce(Meteor.bindEnvironment(function() {
+ console.log('Starting Email Intercepter...');
+
+ if (RocketChat.settings.get('Direct_Reply_Enable') && RocketChat.settings.get('Direct_Reply_Protocol') && RocketChat.settings.get('Direct_Reply_Host') && RocketChat.settings.get('Direct_Reply_Port') && RocketChat.settings.get('Direct_Reply_Username') && RocketChat.settings.get('Direct_Reply_Password')) {
+ if (RocketChat.settings.get('Direct_Reply_Protocol') === 'IMAP') {
+ // stop already running IMAP instance
+ if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ console.log('Disconnecting already running IMAP instance...');
+ RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }));
+ } else if (RocketChat.POP3 && RocketChat.POP3Helper && RocketChat.POP3Helper.isActive()) {
+ console.log('Disconnecting already running POP instance...');
+ RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }));
+ } else {
+ console.log('Starting new IMAP instance......');
+ RocketChat.IMAP = new IMAPIntercepter();
+ RocketChat.IMAP.start();
+ return true;
+ }
+ } else if (RocketChat.settings.get('Direct_Reply_Protocol') === 'POP') {
+ // stop already running POP instance
+ if (RocketChat.POP3 && RocketChat.POP3Helper && RocketChat.POP3Helper.isActive()) {
+ console.log('Disconnecting already running POP instance...');
+ RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }));
+ } else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ console.log('Disconnecting already running IMAP instance...');
+ RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }));
+ } else {
+ console.log('Starting new POP instance......');
+ RocketChat.POP3Helper = new POP3Helper();
+ RocketChat.POP3Helper.start();
+ return true;
+ }
+ }
+ } else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
+ // stop IMAP instance
+ RocketChat.IMAP.stop();
+ } else if (RocketChat.POP3 && RocketChat.POP3Helper.isActive()) {
+ // stop POP3 instance
+ RocketChat.POP3Helper.stop();
+ }
+}), 1000);
+
+RocketChat.settings.onload(/^Direct_Reply_.+/, startEmailIntercepter);
diff --git a/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.coffee b/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.coffee
deleted file mode 100644
index 823460e03c14e..0000000000000
--- a/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.coffee
+++ /dev/null
@@ -1,28 +0,0 @@
-buildMailURL = _.debounce ->
- console.log 'Updating process.env.MAIL_URL'
- if RocketChat.settings.get('SMTP_Host')
- process.env.MAIL_URL = "smtp://"
- if RocketChat.settings.get('SMTP_Username') and RocketChat.settings.get('SMTP_Password')
- process.env.MAIL_URL += encodeURIComponent(RocketChat.settings.get('SMTP_Username')) + ':' + encodeURIComponent(RocketChat.settings.get('SMTP_Password')) + '@'
- process.env.MAIL_URL += encodeURIComponent(RocketChat.settings.get('SMTP_Host'))
- if RocketChat.settings.get('SMTP_Port')
- process.env.MAIL_URL += ':' + parseInt(RocketChat.settings.get('SMTP_Port'))
-, 500
-
-RocketChat.settings.onload 'SMTP_Host', (key, value, initialLoad) ->
- if _.isString value
- buildMailURL()
-
-RocketChat.settings.onload 'SMTP_Port', (key, value, initialLoad) ->
- buildMailURL()
-
-RocketChat.settings.onload 'SMTP_Username', (key, value, initialLoad) ->
- if _.isString value
- buildMailURL()
-
-RocketChat.settings.onload 'SMTP_Password', (key, value, initialLoad) ->
- if _.isString value
- buildMailURL()
-
-Meteor.startup ->
- buildMailURL()
diff --git a/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.js b/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.js
new file mode 100644
index 0000000000000..d70d684a876a4
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/settingsOnLoadSMTP.js
@@ -0,0 +1,65 @@
+import _ from 'underscore';
+
+const buildMailURL = _.debounce(function() {
+ console.log('Updating process.env.MAIL_URL');
+
+ if (RocketChat.settings.get('SMTP_Host')) {
+ process.env.MAIL_URL = `${ RocketChat.settings.get('SMTP_Protocol') }://`;
+
+ if (RocketChat.settings.get('SMTP_Username') && RocketChat.settings.get('SMTP_Password')) {
+ process.env.MAIL_URL += `${ encodeURIComponent(RocketChat.settings.get('SMTP_Username')) }:${ encodeURIComponent(RocketChat.settings.get('SMTP_Password')) }@`;
+ }
+
+ process.env.MAIL_URL += encodeURIComponent(RocketChat.settings.get('SMTP_Host'));
+
+ if (RocketChat.settings.get('SMTP_Port')) {
+ process.env.MAIL_URL += `:${ parseInt(RocketChat.settings.get('SMTP_Port')) }`;
+ }
+
+ process.env.MAIL_URL += `?pool=${ RocketChat.settings.get('SMTP_Pool') }`;
+
+ if (RocketChat.settings.get('SMTP_Protocol') === 'smtp' && RocketChat.settings.get('SMTP_IgnoreTLS')) {
+ process.env.MAIL_URL += '&secure=false&ignoreTLS=true';
+ }
+
+ return process.env.MAIL_URL;
+ }
+}, 500);
+
+RocketChat.settings.onload('SMTP_Host', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Port', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_Username', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Password', function(key, value) {
+ if (_.isString(value)) {
+ return buildMailURL();
+ }
+});
+
+RocketChat.settings.onload('SMTP_Protocol', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_Pool', function() {
+ return buildMailURL();
+});
+
+RocketChat.settings.onload('SMTP_IgnoreTLS', function() {
+ return buildMailURL();
+});
+
+Meteor.startup(function() {
+ return buildMailURL();
+});
diff --git a/packages/rocketchat-lib/server/startup/statsTracker.js b/packages/rocketchat-lib/server/startup/statsTracker.js
index dea74cdbb3dde..c3c4e9a71ce5f 100644
--- a/packages/rocketchat-lib/server/startup/statsTracker.js
+++ b/packages/rocketchat-lib/server/startup/statsTracker.js
@@ -1,11 +1,13 @@
+import {StatsD} from 'node-dogstatsd';
+
RocketChat.statsTracker = new (class StatsTracker {
constructor() {
- this.StatsD = Npm.require('node-dogstatsd').StatsD;
+ this.StatsD = StatsD;
this.dogstatsd = new this.StatsD();
}
track(type, stats, ...args) {
- this.dogstatsd[type](`RocketChat.${stats}`, ...args);
+ this.dogstatsd[type](`RocketChat.${ stats }`, ...args);
}
now() {
diff --git a/packages/rocketchat-lib/startup/defaultRoomTypes.js b/packages/rocketchat-lib/startup/defaultRoomTypes.js
index c4a73a56ccd5f..9f9e006f1324b 100644
--- a/packages/rocketchat-lib/startup/defaultRoomTypes.js
+++ b/packages/rocketchat-lib/startup/defaultRoomTypes.js
@@ -1,109 +1,15 @@
-/* globals openRoom */
-
-RocketChat.roomTypes.add(null, 0, {
- template: 'starredRooms',
- icon: 'icon-star'
-});
-
-RocketChat.roomTypes.add('c', 10, {
- template: 'channels',
- icon: 'icon-hash',
- route: {
- name: 'channel',
- path: '/channel/:name',
- action(params) {
- return openRoom('c', params.name);
- }
- },
-
- findRoom(identifier) {
- const query = {
- t: 'c',
- name: identifier
- };
- return ChatRoom.findOne(query);
- },
-
- roomName(roomData) {
- return roomData.name;
- },
-
- condition() {
- return RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']);
- },
-
- showJoinLink(roomId) {
- return !!ChatRoom.findOne({ _id: roomId, t: 'c' });
- }
-});
-
-RocketChat.roomTypes.add('d', 20, {
- template: 'directMessages',
- icon: 'icon-at',
- route: {
- name: 'direct',
- path: '/direct/:username',
- action(params) {
- return openRoom('d', params.username);
- },
- link(sub) {
- return { username: sub.name };
- }
- },
-
- findRoom(identifier) {
- const query = {
- t: 'd',
- name: identifier
- };
-
- const subscription = ChatSubscription.findOne(query);
- if (subscription && subscription.rid) {
- return ChatRoom.findOne(subscription.rid);
- }
- },
-
- roomName(roomData) {
- const room = ChatSubscription.findOne({ rid: roomData._id }, { fields: { name: 1 } });
- return room && room.name;
- },
-
- condition() {
- return RocketChat.authz.hasAtLeastOnePermission(['view-d-room', 'view-joined-room']);
- },
-
- getUserStatus(roomId) {
- const subscription = RocketChat.models.Subscriptions.findOne({rid: roomId});
- if (subscription == null) { return; }
-
- return Session.get(`user_${subscription.name}_status`);
- }
-});
-
-RocketChat.roomTypes.add('p', 30, {
- template: 'privateGroups',
- icon: 'icon-lock',
- route: {
- name: 'group',
- path: '/group/:name',
- action(params) {
- return openRoom('p', params.name);
- }
- },
-
- findRoom(identifier) {
- const query = {
- t: 'p',
- name: identifier
- };
- return ChatRoom.findOne(query);
- },
-
- roomName(roomData) {
- return roomData.name;
- },
-
- condition() {
- return RocketChat.authz.hasAllPermission('view-p-room');
- }
-});
+import {
+ ConversationRoomType,
+ DirectMessageRoomType,
+ FavoriteRoomType,
+ PrivateRoomType,
+ PublicRoomType,
+ UnreadRoomType
+} from '../lib/roomTypes';
+
+RocketChat.roomTypes.add(new UnreadRoomType());
+RocketChat.roomTypes.add(new FavoriteRoomType());
+RocketChat.roomTypes.add(new ConversationRoomType());
+RocketChat.roomTypes.add(new PublicRoomType());
+RocketChat.roomTypes.add(new PrivateRoomType());
+RocketChat.roomTypes.add(new DirectMessageRoomType());
diff --git a/packages/rocketchat-lib/tests/jasmine/server/unit/models/_Base.spec.coffee b/packages/rocketchat-lib/tests/jasmine/server/unit/models/_Base.spec.coffee
deleted file mode 100644
index 422fb80e1a067..0000000000000
--- a/packages/rocketchat-lib/tests/jasmine/server/unit/models/_Base.spec.coffee
+++ /dev/null
@@ -1,24 +0,0 @@
-describe 'rocketchat:lib Server | Models | Base', ->
-
- beforeEach ->
- MeteorStubs.install()
- this.obj = new RocketChat.models._Base
-
- afterEach ->
- MeteorStubs.uninstall()
-
- it 'should exist', ->
- expect(this.obj).toBeDefined()
-
- it 'should provide a basename for collections', ->
- expect(typeof this.obj._baseName()).toBe('string')
-
- it 'should carry a Meteor.Collection object when initialized', ->
- expect(this.obj.model).toBeFalsy()
- expect(this.obj._initModel('carry')).toBeTruthy()
- expect(typeof this.obj.model).toBe('object')
-
- it 'should apply a basename to the Meteor.Collection created', ->
- name = 'apply'
- expect(this.obj._initModel(name)).toBeTruthy()
- expect(this.obj.model._name).toBe(this.obj._baseName() + name)
diff --git a/packages/rocketchat-livechat/app/.meteor/.finished-upgraders b/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders
similarity index 87%
rename from packages/rocketchat-livechat/app/.meteor/.finished-upgraders
rename to packages/rocketchat-livechat/.app/.meteor/.finished-upgraders
index a541808f2b3d7..2a56593d3f827 100644
--- a/packages/rocketchat-livechat/app/.meteor/.finished-upgraders
+++ b/packages/rocketchat-livechat/.app/.meteor/.finished-upgraders
@@ -14,3 +14,5 @@ notices-for-facebook-graph-api-2
1.3.5-remove-old-dev-bundle-link
1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package
+1.4.3-split-account-service-packages
+1.5-add-dynamic-import-package
diff --git a/packages/rocketchat-livechat/app/.meteor/.gitignore b/packages/rocketchat-livechat/.app/.meteor/.gitignore
similarity index 100%
rename from packages/rocketchat-livechat/app/.meteor/.gitignore
rename to packages/rocketchat-livechat/.app/.meteor/.gitignore
diff --git a/packages/rocketchat-livechat/app/.meteor/.id b/packages/rocketchat-livechat/.app/.meteor/.id
similarity index 100%
rename from packages/rocketchat-livechat/app/.meteor/.id
rename to packages/rocketchat-livechat/.app/.meteor/.id
diff --git a/packages/rocketchat-livechat/.app/.meteor/packages b/packages/rocketchat-livechat/.app/.meteor/packages
new file mode 100644
index 0000000000000..f656261d6cc12
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/.meteor/packages
@@ -0,0 +1,42 @@
+# Meteor packages used by this project, one per line.
+# Check this file (and the other files in this directory) into your repository.
+#
+# 'meteor add' and 'meteor remove' will edit this file for you,
+# but you can also edit it by hand.
+
+meteor@1.8.2
+webapp@1.5.0
+logging@1.1.19
+tracker@1.1.3
+deps@1.0.12
+session@1.1.7
+ddp@1.4.0
+livedata@1.0.18
+mongo@1.4.2
+blaze
+ui
+spacebars
+templating
+check@1.3.0
+jquery@1.11.10
+random@1.1.0
+ejson@1.1.0
+rocketchat:streamer
+kadira:flow-router
+kadira:blaze-layout
+konecty:nrr
+less@2.7.11
+momentjs:moment
+mizzao:timesync
+reactive-var@1.0.11
+accounts-password@1.5.0
+tap:i18n
+smoral:sweetalert
+ecmascript@0.10.0
+es5-shim@4.7.0
+standard-minifier-css@1.4.0
+standard-minifier-js@2.3.1
+shell-server@0.3.1
+dynamic-import@0.3.0
+
+konecty:user-presence
diff --git a/packages/rocketchat-livechat/app/.meteor/platforms b/packages/rocketchat-livechat/.app/.meteor/platforms
similarity index 100%
rename from packages/rocketchat-livechat/app/.meteor/platforms
rename to packages/rocketchat-livechat/.app/.meteor/platforms
diff --git a/packages/rocketchat-livechat/.app/.meteor/release b/packages/rocketchat-livechat/.app/.meteor/release
new file mode 100644
index 0000000000000..d502dc0d921a9
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/.meteor/release
@@ -0,0 +1 @@
+METEOR@1.6.1
diff --git a/packages/rocketchat-livechat/.app/.meteor/versions b/packages/rocketchat-livechat/.app/.meteor/versions
new file mode 100644
index 0000000000000..784906b61781e
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/.meteor/versions
@@ -0,0 +1,98 @@
+accounts-base@1.4.2
+accounts-password@1.5.0
+aldeed:simple-schema@1.5.3
+allow-deny@1.1.0
+babel-compiler@7.0.4
+babel-runtime@1.2.2
+base64@1.0.11
+binary-heap@1.0.10
+blaze@2.3.2
+blaze-tools@1.0.10
+boilerplate-generator@1.4.0
+caching-compiler@1.1.11
+caching-html-compiler@1.1.2
+callback-hook@1.1.0
+cfs:http-methods@0.0.32
+check@1.3.0
+coffeescript@1.0.17
+ddp@1.4.0
+ddp-client@2.3.1
+ddp-common@1.4.0
+ddp-rate-limiter@1.0.7
+ddp-server@2.1.2
+deps@1.0.12
+diff-sequence@1.1.0
+dynamic-import@0.3.0
+ecmascript@0.10.4
+ecmascript-runtime@0.5.0
+ecmascript-runtime-client@0.6.2
+ecmascript-runtime-server@0.5.0
+ejson@1.1.0
+email@1.2.3
+es5-shim@4.7.3
+geojson-utils@1.0.10
+html-tools@1.0.11
+htmljs@1.0.11
+http@1.4.0
+id-map@1.1.0
+jquery@1.11.11
+kadira:blaze-layout@2.3.0
+kadira:flow-router@2.12.1
+konecty:nrr@2.0.2
+konecty:user-presence@2.0.1
+less@2.7.12
+livedata@1.0.18
+localstorage@1.2.0
+logging@1.1.19
+mdg:validation-error@0.5.1
+meteor@1.8.2
+meteorspark:util@0.2.0
+minifier-css@1.3.1
+minifier-js@2.3.2
+minimongo@1.4.3
+mizzao:timesync@0.5.0
+modules@0.11.4
+modules-runtime@0.9.2
+momentjs:moment@2.20.1
+mongo@1.4.3
+mongo-dev-server@1.1.0
+mongo-id@1.0.6
+nooitaf:colors@1.1.2_1
+npm-bcrypt@0.9.3
+npm-mongo@2.2.34
+observe-sequence@1.0.16
+ordered-dict@1.1.0
+promise@0.10.2
+raix:eventemitter@0.1.3
+random@1.1.0
+rate-limit@1.0.9
+reactive-dict@1.2.0
+reactive-var@1.0.11
+reload@1.2.0
+retry@1.1.0
+rocketchat:streamer@0.6.1
+routepolicy@1.0.12
+server-render@0.3.0
+service-configuration@1.0.11
+session@1.1.7
+sha@1.0.9
+shell-server@0.3.1
+shim-common@0.1.0
+smoral:sweetalert@1.1.1
+socket-stream-client@0.1.0
+spacebars@1.0.15
+spacebars-compiler@1.1.3
+srp@1.0.10
+standard-minifier-css@1.4.1
+standard-minifier-js@2.3.2
+tap:i18n@1.8.2
+templating@1.3.2
+templating-compiler@1.3.3
+templating-runtime@1.3.2
+templating-tools@1.1.2
+tracker@1.1.3
+ui@1.0.13
+underscore@1.0.10
+url@1.2.0
+webapp@1.5.0
+webapp-hashing@1.0.9
diff --git a/packages/rocketchat-livechat/app/client/components/modal.html b/packages/rocketchat-livechat/.app/client/components/modal.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/components/modal.html
rename to packages/rocketchat-livechat/.app/client/components/modal.html
diff --git a/packages/rocketchat-livechat/.app/client/lib/CustomFields.js b/packages/rocketchat-livechat/.app/client/lib/CustomFields.js
new file mode 100644
index 0000000000000..36132c9aa7146
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/CustomFields.js
@@ -0,0 +1,34 @@
+import visitor from '../../imports/client/visitor';
+
+this.CustomFields = (function() {
+ let queue = {};
+ let initiated = false;
+
+ const setCustomField = function(token, key, value, overwrite = true) {
+ if (!initiated) {
+ // queue by key
+ queue[key] = { token, value, overwrite };
+ return;
+ }
+ Meteor.call('livechat:setCustomField', token, key, value, overwrite);
+ };
+
+ const init = function() {
+ Tracker.autorun(function() {
+ if (visitor.getId()) {
+ initiated = true;
+ Object.keys(queue).forEach((key) => {
+ setCustomField.call(this, queue[key].token, key, queue[key].value, queue[key].overwrite);
+ });
+ queue = {};
+ } else {
+ initiated = false;
+ }
+ });
+ };
+
+ return {
+ init,
+ setCustomField
+ };
+}());
diff --git a/packages/rocketchat-livechat/app/client/lib/LivechatVideoCall.js b/packages/rocketchat-livechat/.app/client/lib/LivechatVideoCall.js
similarity index 91%
rename from packages/rocketchat-livechat/app/client/lib/LivechatVideoCall.js
rename to packages/rocketchat-livechat/.app/client/lib/LivechatVideoCall.js
index e2b3bfba9cf08..e31490bb45f02 100644
--- a/packages/rocketchat-livechat/app/client/lib/LivechatVideoCall.js
+++ b/packages/rocketchat-livechat/.app/client/lib/LivechatVideoCall.js
@@ -1,4 +1,5 @@
/* globals LivechatVideoCall, cordova, JitsiMeetExternalAPI */
+import visitor from '../../imports/client/visitor';
LivechatVideoCall = new (class LivechatVideoCall {
constructor() {
@@ -7,7 +8,7 @@ LivechatVideoCall = new (class LivechatVideoCall {
if (typeof JitsiMeetExternalAPI === 'undefined') {
const prefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
- $.getScript(`${prefix}/packages/rocketchat_videobridge/client/public/external_api.js`);
+ $.getScript(`${ prefix }/packages/rocketchat_videobridge/client/public/external_api.js`);
}
}
@@ -46,7 +47,7 @@ LivechatVideoCall = new (class LivechatVideoCall {
start(domain, room) {
Meteor.defer(() => {
- let interfaceConfig = {};
+ const interfaceConfig = {};
interfaceConfig['TOOLBAR_BUTTONS'] = '[""]';
interfaceConfig['APP_NAME'] = '"Livechat"';
interfaceConfig['INITIAL_TOOLBAR_TIMEOUT'] = '5000';
diff --git a/packages/rocketchat-livechat/app/client/lib/_livechat.js b/packages/rocketchat-livechat/.app/client/lib/_livechat.js
similarity index 84%
rename from packages/rocketchat-livechat/app/client/lib/_livechat.js
rename to packages/rocketchat-livechat/.app/client/lib/_livechat.js
index 0e84b0f7eaae5..c0185a16b436e 100644
--- a/packages/rocketchat-livechat/app/client/lib/_livechat.js
+++ b/packages/rocketchat-livechat/.app/client/lib/_livechat.js
@@ -1,3 +1,5 @@
+import visitor from '../../imports/client/visitor';
+
this.Livechat = new (class Livechat {
constructor() {
this._online = new ReactiveVar(null);
@@ -12,6 +14,8 @@ this.Livechat = new (class Livechat {
this._title = new ReactiveVar('Rocket.Chat');
this._registrationForm = new ReactiveVar(true);
+ this._showSwitchDepartmentForm = new ReactiveVar(false);
+ this._allowSwitchingDepartments = new ReactiveVar(false);
this._offlineMessage = new ReactiveVar('');
this._offlineUnavailableMessage = new ReactiveVar('');
this._displayOfflineForm = new ReactiveVar(true);
@@ -28,17 +32,17 @@ this.Livechat = new (class Livechat {
this.stream = new Meteor.Streamer('livechat-room');
Tracker.autorun(() => {
- if (this._room.get() && Meteor.userId()) {
+ if (this._room.get() && visitor.getId()) {
RoomHistoryManager.getMoreIfIsEmpty(this._room.get());
visitor.subscribeToRoom(this._room.get());
visitor.setRoom(this._room.get());
- Meteor.call('livechat:getAgentData', this._room.get(), (error, result) => {
+ Meteor.call('livechat:getAgentData', { roomId: this._room.get(), token: visitor.getToken() }, (error, result) => {
if (!error) {
this._agent.set(result);
}
});
- this.stream.on(this._room.get(), (eventData) => {
+ this.stream.on(this._room.get(), { token: visitor.getToken() }, (eventData) => {
if (!eventData || !eventData.type) {
return;
}
@@ -72,6 +76,12 @@ this.Livechat = new (class Livechat {
get registrationForm() {
return this._registrationForm.get();
}
+ get showSwitchDepartmentForm() {
+ return this._showSwitchDepartmentForm.get();
+ }
+ get allowSwitchingDepartments() {
+ return this._allowSwitchingDepartments.get();
+ }
get offlineMessage() {
return this._offlineMessage.get();
}
@@ -109,6 +119,12 @@ this.Livechat = new (class Livechat {
set registrationForm(value) {
this._registrationForm.set(value);
}
+ set showSwitchDepartmentForm(value) {
+ this._showSwitchDepartmentForm.set(value);
+ }
+ set allowSwitchingDepartments(value) {
+ this._allowSwitchingDepartments.set(value);
+ }
set offlineMessage(value) {
this._offlineMessage.set(value);
}
diff --git a/packages/rocketchat-livechat/app/client/lib/autolinker.js b/packages/rocketchat-livechat/.app/client/lib/autolinker.js
similarity index 100%
rename from packages/rocketchat-livechat/app/client/lib/autolinker.js
rename to packages/rocketchat-livechat/.app/client/lib/autolinker.js
diff --git a/packages/rocketchat-livechat/.app/client/lib/chatMessages.js b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js
new file mode 100644
index 0000000000000..d2619ac69c62e
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/chatMessages.js
@@ -0,0 +1,270 @@
+/* globals MsgTyping, showError, Livechat */
+import _ from 'underscore';
+import s from 'underscore.string';
+import toastr from 'toastr';
+import visitor from '../../imports/client/visitor';
+
+this.ChatMessages = class ChatMessages {
+ init(node) {
+ this.editing = {};
+
+ // this.messageMaxSize = RocketChat.settings.get('Message_MaxAllowedSize')
+ this.wrapper = $(node).find('.wrapper');
+ this.input = $(node).find('.input-message').get(0);
+ // this.bindEvents()
+ return;
+ }
+
+ resize() {
+ const dif = 60 + $('.messages-container').find('footer').outerHeight();
+ return $('.messages-box').css({
+ height: `calc(100% - ${ dif }px)`
+ });
+ }
+
+ toPrevMessage() {
+ const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)');
+ if (msgs.length) {
+ if (this.editing.element) {
+ if (msgs[this.editing.index - 1]) {
+ this.edit(msgs[this.editing.index - 1], this.editing.index - 1);
+ }
+ } else {
+ this.edit(msgs[msgs.length - 1], msgs.length - 1);
+ }
+ }
+ }
+
+ toNextMessage() {
+ if (this.editing.element) {
+ const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)');
+ if (msgs[this.editing.index + 1]) {
+ this.edit(msgs[this.editing.index + 1], this.editing.index + 1);
+ } else {
+ this.clearEditing();
+ }
+ }
+ }
+
+ getEditingIndex(element) {
+ const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)');
+ let index = 0;
+ for (const msg of Array.from(msgs)) {
+ if (msg === element) {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
+
+ edit(element, index) {
+ if (element.classList.contains('system')) {
+ return;
+ }
+ this.clearEditing();
+ const id = element.getAttribute('id');
+ const message = ChatMessage.findOne({ _id: id, 'u._id': visitor.getId() });
+ this.input.value = message.msg;
+ this.editing.element = element;
+ this.editing.index = index || this.getEditingIndex(element);
+ this.editing.id = id;
+ element.classList.add('editing');
+ this.input.classList.add('editing');
+ setTimeout(() => {
+ this.input.focus();
+ }, 5);
+ }
+
+ clearEditing() {
+ if (this.editing.element) {
+ this.editing.element.classList.remove('editing');
+ this.input.classList.remove('editing');
+ this.editing.id = null;
+ this.editing.element = null;
+ this.editing.index = null;
+ this.input.value = this.editing.saved || '';
+ } else {
+ this.editing.saved = this.input.value;
+ }
+ }
+
+ send(rid, input) {
+ if (s.trim(input.value) === '') {
+ return;
+ }
+ if (this.isMessageTooLong(input)) {
+ return toastr.error(t('Message_too_long'));
+ }
+ // KonchatNotification.removeRoomNotification(rid)
+ const msg = input.value;
+ input.value = '';
+ if (!rid) {
+ rid = visitor.getRoom(true);
+ }
+
+ const sendMessage = () => {
+ const msgObject = {
+ _id: Random.id(),
+ rid,
+ msg,
+ token: visitor.getToken()
+ };
+ MsgTyping.stop(rid);
+
+ let agent;
+ const currentAgent = !visitor.roomSubscribed && Livechat.agent;
+ if (currentAgent) {
+ agent = {
+ agentId: currentAgent._id,
+ username: currentAgent.username
+ };
+ }
+
+ Meteor.call('sendMessageLivechat', msgObject, agent, (error, result) => {
+ if (error) {
+ ChatMessage.update(msgObject._id, { $set: { error: true } });
+ showError(error.reason);
+ }
+
+ if (result && result.rid && !visitor.isSubscribed(result.rid)) {
+ Livechat.connecting = result.showConnecting;
+ ChatMessage.update(result._id, _.omit(result, '_id'));
+ Livechat.room = result.rid;
+
+ visitor.setConnected();
+
+ parentCall('callback', 'chat-started');
+ }
+ });
+ };
+
+ if (!visitor.getId()) {
+ const guest = {
+ token: visitor.getToken()
+ };
+
+ if (Livechat.department) {
+ guest.department = Livechat.department;
+ }
+
+ Meteor.call('livechat:registerGuest', guest, (error, result) => {
+ if (error) {
+ return showError(error.reason);
+ }
+
+ visitor.setId(result.userId);
+ sendMessage();
+ });
+ } else {
+ sendMessage();
+ }
+ }
+
+ deleteMsg(message) {
+ Meteor.call('deleteMessage', message, (error) => {
+ if (error) {
+ return handleError(error);
+ }
+ });
+ }
+
+ update(id, rid, input) {
+ if (s.trim(input.value) !== '') {
+ const msg = input.value;
+ Meteor.call('updateMessage', { id, msg });
+ this.clearEditing();
+ MsgTyping.stop(rid);
+ }
+ }
+
+ startTyping(rid, input) {
+ if (s.trim(input.value) !== '') {
+ MsgTyping.start(rid);
+ } else {
+ MsgTyping.stop(rid);
+ }
+ }
+
+ bindEvents() {
+ if (this.wrapper && this.wrapper.length) {
+ $('.input-message').autogrow({
+ postGrowCallback: () => {
+ this.resize();
+ }
+ });
+ }
+ }
+
+ keyup(rid, event) {
+ let i;
+ const input = event.currentTarget;
+ const k = event.which;
+ const keyCodes = [
+ 13, // Enter
+ 20, // Caps lock
+ 16, // Shift
+ 9, // Tab
+ 27, // Escape Key
+ 17, // Control Key
+ 91, // Windows Command Key
+ 19, // Pause Break
+ 18, // Alt Key
+ 93, // Right Click Point Key
+ 45, // Insert Key
+ 34, // Page Down
+ 35, // Page Up
+ 144, // Num Lock
+ 145 // Scroll Lock
+ ];
+ for (i = 35; i <= 40; i++) { keyCodes.push(i); } // Home, End, Arrow Keys
+ for (i = 112; i <= 123; i++) { keyCodes.push(i); } // F1 - F12
+
+ if (!Array.from(keyCodes).includes(k)) {
+ this.startTyping(rid, input);
+ }
+ }
+
+ keydown(rid, event) {
+ const input = event.currentTarget;
+ const k = event.which;
+ this.resize(input);
+ if (k === 13 && !event.shiftKey && !event.ctrlKey && !event.altKey) { // Enter without shift/ctrl/alt
+ event.preventDefault();
+ event.stopPropagation();
+ if (this.editing.id) {
+ this.update(this.editing.id, rid, input);
+ } else {
+ this.send(rid, input);
+ }
+ return;
+ }
+
+ if (k === 27) {
+ if (this.editing.id) {
+ event.preventDefault();
+ event.stopPropagation();
+ this.clearEditing();
+ return;
+ }
+ // else if k is 38 or k is 40 # Arrow Up or down
+ // if k is 38
+ // return if input.value.slice(0, input.selectionStart).match(/[\n]/) isnt null
+ // this.toPrevMessage()
+ // else
+ // return if input.value.slice(input.selectionEnd, input.value.length).match(/[\n]/) isnt null
+ // this.toNextMessage()
+
+ // event.preventDefault()
+ // event.stopPropagation()
+
+ // ctrl (command) + shift + k -> clear room messages
+ } else if (k === 75 && ((navigator.platform.indexOf('Mac') !== -1 && event.metaKey && event.shiftKey) || (navigator.platform.indexOf('Mac') === -1 && event.ctrlKey && event.shiftKey))) {
+ RoomHistoryManager.clear(rid);
+ }
+ }
+
+ isMessageTooLong(input) {
+ return input && input.value.length > this.messageMaxSize;
+ }
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/collections.js b/packages/rocketchat-livechat/.app/client/lib/collections.js
new file mode 100644
index 0000000000000..1feb9caace84c
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/collections.js
@@ -0,0 +1,2 @@
+this.ChatMessage = new Mongo.Collection(null);
+this.Department = new Mongo.Collection(null);
diff --git a/packages/rocketchat-livechat/.app/client/lib/commands.js b/packages/rocketchat-livechat/.app/client/lib/commands.js
new file mode 100644
index 0000000000000..e63bc3d10bf2b
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/commands.js
@@ -0,0 +1,70 @@
+/* globals LivechatVideoCall, Livechat, swal */
+import visitor from '../../imports/client/visitor';
+
+// Functions to call on messages of type 'command'
+this.Commands = {
+ survey() {
+ if (!($('body #survey').length)) {
+ Blaze.render(Template.survey, $('body').get(0));
+ }
+ },
+
+ endCall() {
+ LivechatVideoCall.finish();
+ },
+
+ promptTranscript() {
+ if (Livechat.transcript) {
+ const visitorData = visitor.getData();
+ const email = visitorData && visitorData.visitorEmails && visitorData.visitorEmails.length > 0 ? visitorData.visitorEmails[0].address : '';
+
+ swal({
+ title: t('Chat_ended'),
+ text: Livechat.transcriptMessage,
+ type: 'input',
+ inputValue: email,
+ showCancelButton: true,
+ cancelButtonText: t('no'),
+ confirmButtonText: t('yes'),
+ closeOnCancel: true,
+ closeOnConfirm: false
+ }, (response) => {
+ if ((typeof response === 'boolean') && !response) {
+ return true;
+ } else {
+ if (!response) {
+ swal.showInputError(t('please enter your email'));
+ return false;
+ }
+ if (response.trim() === '') {
+ swal.showInputError(t('please enter your email'));
+ return false;
+ } else {
+ Meteor.call('livechat:sendTranscript', visitor.getToken(), visitor.getRoom(), response, (err) => {
+ if (err) {
+ console.error(err);
+ }
+ swal({
+ title: t('transcript_sent'),
+ type: 'success',
+ timer: 1000,
+ showConfirmButton: false
+ });
+ });
+ }
+ }
+ });
+ } else {
+ swal({
+ title: t('Chat_ended'),
+ type: 'success',
+ timer: 1000,
+ showConfirmButton: false
+ });
+ }
+ },
+
+ connected() {
+ Livechat.connecting = false;
+ }
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/error.js b/packages/rocketchat-livechat/.app/client/lib/error.js
new file mode 100644
index 0000000000000..7fd5501fc2a10
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/error.js
@@ -0,0 +1,3 @@
+this.showError = msg => {
+ $('.error').addClass('show').find('span').html(msg);
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js b/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js
new file mode 100644
index 0000000000000..8acbe3d5da126
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js
@@ -0,0 +1,81 @@
+import visitor from '../../../imports/client/visitor';
+
+this.Notifications = new class {
+ constructor() {
+ this.logged = visitor.getId() !== null;
+ this.loginCb = [];
+ Tracker.autorun(() => {
+ if (visitor.getId() !== null && this.logged === false) {
+ this.loginCb.forEach(cb => cb());
+ }
+ return this.logged = visitor.getId() !== null;
+ });
+ this.debug = false;
+ this.streamAll = new Meteor.Streamer('notify-all');
+ this.streamLogged = new Meteor.Streamer('notify-logged');
+ this.streamRoom = new Meteor.Streamer('notify-room');
+ this.streamRoomUsers = new Meteor.Streamer('notify-room-users');
+ this.streamUser = new Meteor.Streamer('notify-user');
+ if (this.debug === true) {
+ this.onAll(function() {
+ return console.log('RocketChat.Notifications: onAll', arguments);
+ });
+ this.onUser(function() {
+ return console.log('RocketChat.Notifications: onAll', arguments);
+ });
+ }
+ }
+
+ onLogin(cb) {
+ this.loginCb.push(cb);
+ if (this.logged) {
+ return cb();
+ }
+ }
+ notifyRoom(room, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('RocketChat.Notifications: notifyRoom', arguments);
+ }
+ args.unshift(`${ room }/${ eventName }`);
+ return this.streamRoom.emit.apply(this.streamRoom, args);
+ }
+ notifyUser(userId, eventName, ...args) {
+ if (this.debug === true) {
+ console.log('RocketChat.Notifications: notifyUser', arguments);
+ }
+ args.unshift(`${ userId }/${ eventName }`);
+ return this.streamUser.emit.apply(this.streamUser, args);
+ }
+ onAll(eventName, callback) {
+ return this.streamAll.on(eventName, { token: visitor.getToken() }, callback);
+ }
+ onLogged(eventName, callback) {
+ return this.onLogin(() => {
+ return this.streamLogged.on(eventName, { token: visitor.getToken() }, callback);
+ });
+ }
+ onRoom(room, eventName, callback) {
+ if (this.debug === true) {
+ this.streamRoom.on(room, { token: visitor.getToken() }, function() {
+ return console.log(`RocketChat.Notifications: onRoom ${ room }`, arguments);
+ });
+ }
+ return this.streamRoom.on(`${ room }/${ eventName }`, { token: visitor.getToken() }, callback);
+ }
+ onUser(eventName, callback) {
+ return this.streamUser.on(`${ visitor.getId() }/${ eventName }`, { token: visitor.getToken() }, callback);
+ }
+ unAll(callback) {
+ return this.streamAll.removeListener('notify', callback);
+ }
+ unLogged(callback) {
+ return this.streamLogged.removeListener('notify', callback);
+ }
+ unRoom(room, eventName, callback) {
+ return this.streamRoom.removeListener(`${ room }/${ eventName }`, callback);
+ }
+ unUser(eventName, callback) {
+ return this.streamUser.removeListener(`${ visitor.getId() }/${ eventName }`, callback);
+ }
+
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js b/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js
new file mode 100644
index 0000000000000..2d6ab8f924412
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js
@@ -0,0 +1,234 @@
+/* globals readMessage UserRoles RoomRoles*/
+
+import visitor from '../../../imports/client/visitor';
+import _ from 'underscore';
+
+export const RoomHistoryManager = new class {
+ constructor() {
+ this.defaultLimit = 50;
+ this.histories = {};
+ }
+ getRoom(rid) {
+ if ((this.histories[rid] == null)) {
+ this.histories[rid] = {
+ hasMore: new ReactiveVar(true),
+ hasMoreNext: new ReactiveVar(false),
+ isLoading: new ReactiveVar(false),
+ unreadNotLoaded: new ReactiveVar(0),
+ firstUnread: new ReactiveVar,
+ loaded: undefined
+ };
+ }
+
+ return this.histories[rid];
+ }
+
+ getMore(rid, limit) {
+ if (limit == null) { limit = this.defaultLimit; }
+ const room = this.getRoom(rid);
+ if (room.hasMore.curValue !== true) {
+ return;
+ }
+
+ room.isLoading.set(true);
+
+ //$('.messages-box .wrapper').data('previous-height', $('.messages-box .wrapper').get(0)?.scrollHeight - $('.messages-box .wrapper').get(0)?.scrollTop)
+ // ScrollListener.setLoader true
+ const lastMessage = ChatMessage.findOne({rid}, { fields: { ts: 1 }, sort: { ts: 1 }});
+ // lastMessage ?= ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
+
+ let ts;
+ if (lastMessage) {
+ ts = lastMessage.ts;
+ } else {
+ ts = new Date();
+ }
+
+ Meteor.call('livechat:loadHistory', { token: visitor.getToken(), rid, ts, limit }, (err, result) => {
+ if (err) {
+ return;
+ }
+
+ if (result && result.messages) {
+ result.messages.forEach((item) => {
+ if (item.t !== 'command') {
+ ChatMessage.upsert({_id: item._id}, item);
+ }
+ });
+ room.isLoading.set(false);
+ room.loaded += result.messages.length;
+ if (result.messages.length < limit) {
+ room.hasMore.set(false);
+ }
+ }
+ });
+ }
+
+ getMoreNext(rid, limit) {
+ if (limit == null) { limit = this.defaultLimit; }
+ const room = this.getRoom(rid);
+ if (room.hasMoreNext.curValue !== true) {
+ return;
+ }
+
+ const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance();
+ instance.atBottom = false;
+
+ room.isLoading.set(true);
+
+ const lastMessage = ChatMessage.findOne({rid}, {sort: {ts: -1}});
+
+ let typeName = undefined;
+
+ const subscription = ChatSubscription.findOne({rid});
+ if (subscription != null) {
+ // const { ls } = subscription;
+ typeName = subscription.t + subscription.name;
+ } else {
+ const curRoomDoc = ChatRoom.findOne({_id: rid});
+ typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined);
+ }
+
+ const { ts } = lastMessage;
+
+ if (ts) {
+ return Meteor.call('loadNextMessages', rid, ts, limit, function(err, result) {
+ for (const item of Array.from((result != null ? result.messages : undefined) || [])) {
+ if (item.t !== 'command') {
+ const roles = [
+ (item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 }})) || {},
+ (item.u && item.u._id && RoomRoles.findOne({rid: item.rid, 'u._id': item.u._id})) || {}
+ ].map(e => e.roles);
+ item.roles = _.union.apply(_.union, roles);
+ ChatMessage.upsert({_id: item._id}, item);
+ }
+ }
+
+ Meteor.defer(() => RoomManager.updateMentionsMarksOfRoom(typeName));
+
+ room.isLoading.set(false);
+ if (room.loaded == null) { room.loaded = 0; }
+
+ room.loaded += result.messages.length;
+ if (result.messages.length < limit) {
+ room.hasMoreNext.set(false);
+ }
+ });
+ }
+ }
+
+ getSurroundingMessages(message, limit) {
+ if (limit == null) { limit = this.defaultLimit; }
+ if (!(message != null ? message.rid : undefined)) {
+ return;
+ }
+
+ const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance();
+
+ if (ChatMessage.findOne(message._id)) {
+ const wrapper = $('.messages-box .wrapper');
+ const msgElement = $(`#${ message._id }`, wrapper);
+ const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height()/2);
+ wrapper.animate({
+ scrollTop: pos
+ }, 500);
+ msgElement.addClass('highlight');
+
+ setTimeout(function() {
+ const messages = wrapper[0];
+ return instance.atBottom = messages.scrollTop >= (messages.scrollHeight - messages.clientHeight);
+ });
+
+ return setTimeout(() => msgElement.removeClass('highlight'), 500);
+ } else {
+ const room = this.getRoom(message.rid);
+ room.isLoading.set(true);
+ ChatMessage.remove({ rid: message.rid });
+
+ let typeName = undefined;
+
+ const subscription = ChatSubscription.findOne({rid: message.rid});
+ if (subscription) {
+ // const { ls } = subscription;
+ typeName = subscription.t + subscription.name;
+ } else {
+ const curRoomDoc = ChatRoom.findOne({_id: message.rid});
+ typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined);
+ }
+
+ return Meteor.call('loadSurroundingMessages', message, limit, function(err, result) {
+ for (const item of Array.from((result != null ? result.messages : undefined) || [])) {
+ if (item.t !== 'command') {
+ const roles = [
+ (item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 }})) || {},
+ (item.u && item.u._id && RoomRoles.findOne({rid: item.rid, 'u._id': item.u._id})) || {}
+ ].map(e => e.roles);
+ item.roles = _.union.apply(_.union, roles);
+ ChatMessage.upsert({_id: item._id}, item);
+ }
+ }
+
+ Meteor.defer(function() {
+ readMessage.refreshUnreadMark(message.rid, true);
+ RoomManager.updateMentionsMarksOfRoom(typeName);
+ const wrapper = $('.messages-box .wrapper');
+ const msgElement = $(`#${ message._id }`, wrapper);
+ const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height()/2);
+ wrapper.animate({
+ scrollTop: pos
+ }, 500);
+
+ msgElement.addClass('highlight');
+
+ setTimeout(function() {
+ room.isLoading.set(false);
+ const messages = wrapper[0];
+ instance.atBottom = !result.moreAfter && (messages.scrollTop >= (messages.scrollHeight - messages.clientHeight));
+ return 500;
+ });
+
+ return setTimeout(() => msgElement.removeClass('highlight'), 500);
+ });
+ if (room.loaded == null) { room.loaded = 0; }
+ room.loaded += result.messages.length;
+ room.hasMore.set(result.moreBefore);
+ return room.hasMoreNext.set(result.moreAfter);
+ });
+ }
+ }
+
+ hasMore(rid) {
+ const room = this.getRoom(rid);
+ return room.hasMore.get();
+ }
+
+ hasMoreNext(rid) {
+ const room = this.getRoom(rid);
+ return room.hasMoreNext.get();
+ }
+
+
+ getMoreIfIsEmpty(rid) {
+ const room = this.getRoom(rid);
+
+ if (room.loaded === undefined) {
+ return this.getMore(rid);
+ }
+ }
+
+
+ isLoading(rid) {
+ const room = this.getRoom(rid);
+ return room.isLoading.get();
+ }
+
+ clear(rid) {
+ ChatMessage.remove({ rid });
+ if (this.histories[rid] != null) {
+ this.histories[rid].hasMore.set(true);
+ this.histories[rid].isLoading.set(false);
+ return this.histories[rid].loaded = undefined;
+ }
+ }
+};
+this.RoomHistoryManager = RoomHistoryManager;
diff --git a/packages/rocketchat-livechat/.app/client/lib/fromApp/avatar.js b/packages/rocketchat-livechat/.app/client/lib/fromApp/avatar.js
new file mode 100644
index 0000000000000..07aad70c42cae
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/fromApp/avatar.js
@@ -0,0 +1,21 @@
+this.getAvatarUrlFromUsername = username => {
+ const key = `avatar_random_${ username }`;
+ const random = Session.keys[key] || 0;
+ if (!username) {
+ return;
+ }
+
+ return `${ Meteor.absoluteUrl() }avatar/${ username }.jpg?_dc=${ random }`;
+};
+
+this.updateAvatarOfUsername = username => {
+ const key = `avatar_random_${ username }`;
+ Session.set(key, Math.round(Math.random() * 1000));
+
+ Object.keys(RoomManager.openedRooms).forEach((key) => {
+ const room = RoomManager.openedRooms[key];
+ const url = getAvatarUrlFromUsername(username);
+ $(room.dom).find(`.message[data-username='${ username }'] .avatar-image`).css('background-image', `url(${ url })`);
+ });
+ return true;
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/hooks.js b/packages/rocketchat-livechat/.app/client/lib/hooks.js
new file mode 100644
index 0000000000000..3a525c34cf5db
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/hooks.js
@@ -0,0 +1,60 @@
+/* globals CustomFields, Livechat */
+import visitor from '../../imports/client/visitor';
+
+const api = {
+ pageVisited(info) {
+ if (info.change === 'url') {
+ Triggers.processRequest(info);
+ }
+
+ Meteor.call('livechat:pageVisited', visitor.getToken(), info);
+ },
+
+ setCustomField(key, value, overwrite = true) {
+ CustomFields.setCustomField(visitor.getToken(), key, value, overwrite);
+ },
+
+ setTheme(theme) {
+ if (theme.color) {
+ Livechat.customColor = theme.color;
+ }
+ if (theme.fontColor) {
+ Livechat.customFontColor = theme.fontColor;
+ }
+ },
+
+ setDepartment(department) {
+ Livechat.department = department;
+ },
+
+ clearDepartment() {
+ Livechat.department = null;
+ },
+
+ widgetOpened() {
+ Livechat.setWidgetOpened();
+ },
+
+ widgetClosed() {
+ Livechat.setWidgetClosed();
+ }
+};
+
+window.addEventListener('message', function(msg) {
+ if (typeof msg.data === 'object' && msg.data.src !== undefined && msg.data.src === 'rocketchat') {
+ if (api[msg.data.fn] !== undefined && typeof api[msg.data.fn] === 'function') {
+ const args = [].concat(msg.data.args || []);
+ api[msg.data.fn].apply(null, args);
+ }
+ }
+}, false);
+
+// tell parent window that we are ready
+Meteor.startup(function() {
+ Tracker.autorun((c) => {
+ if (Livechat.isReady()) {
+ parentCall('ready');
+ c.stop();
+ }
+ });
+});
diff --git a/packages/rocketchat-livechat/.app/client/lib/msgTyping.js b/packages/rocketchat-livechat/.app/client/lib/msgTyping.js
new file mode 100644
index 0000000000000..378af82a34aa5
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/msgTyping.js
@@ -0,0 +1,80 @@
+/* globals Notifications */
+import visitor from '../../imports/client/visitor';
+import _ from 'underscore';
+
+export const MsgTyping = (function() {
+ const timeout = 15000;
+ const timeouts = {};
+ let renew = true;
+ const renewTimeout = 10000;
+ const selfTyping = new ReactiveVar(false);
+ const usersTyping = {};
+ const dep = new Tracker.Dependency;
+
+ const addStream = function(room) {
+ if (!_.isEmpty(usersTyping[room] && usersTyping[room].users)) {
+ return;
+ }
+ usersTyping[room] = { users: {} };
+ return Notifications.onRoom(room, 'typing', function(username, typing, extraData) {
+ const user = Meteor.user();
+ if (username === (user && user.username)) {
+ return;
+ }
+ const { users } = usersTyping[room];
+ if (typing === true) {
+ users[username] = Meteor.setTimeout(function() {
+ delete users[username];
+ usersTyping[room].users = users;
+ return dep.changed();
+ }, timeout);
+ } else {
+ delete users[username];
+ }
+ usersTyping[room].users = users;
+ return dep.changed();
+ });
+ };
+
+ Tracker.autorun(() => {
+ if (visitor.getRoom() && visitor.getId()) {
+ addStream(visitor.getRoom());
+ }
+ });
+
+ const stop = function(room) {
+ renew = true;
+ selfTyping.set(false);
+ if (timeouts && timeouts[room]) {
+ clearTimeout(timeouts[room]);
+ timeouts[room] = null;
+ }
+ const visitorData = visitor.getData();
+ return Notifications.notifyRoom(room, 'typing', visitorData && visitorData.username, false, { token: visitor.getToken() });
+ };
+ const start = function(room) {
+ if (!renew) { return; }
+
+ setTimeout(() => renew = true, renewTimeout);
+
+ renew = false;
+ selfTyping.set(true);
+ const visitorData = visitor.getData();
+ Notifications.notifyRoom(room, 'typing', visitorData && visitorData.username, true, { token: visitor.getToken() });
+ clearTimeout(timeouts[room]);
+ return timeouts[room] = Meteor.setTimeout(() => stop(room), timeout);
+ };
+
+ const get = function(room) {
+ dep.depend();
+ if (!usersTyping[room]) {
+ usersTyping[room] = { users: {} };
+ }
+ const { users } = usersTyping[room];
+ return _.keys(users) || [];
+ };
+
+ return { start, stop, get, selfTyping };
+}());
+
+this.MsgTyping = MsgTyping;
diff --git a/packages/rocketchat-livechat/.app/client/lib/parentCall.js b/packages/rocketchat-livechat/.app/client/lib/parentCall.js
new file mode 100644
index 0000000000000..ae705ec7618f3
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/parentCall.js
@@ -0,0 +1,9 @@
+this.parentCall = (method, args = []) => {
+ const data = {
+ src: 'rocketchat',
+ fn: method,
+ args
+ };
+
+ window.parent.postMessage(data, '*');
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/tapi18n.js b/packages/rocketchat-livechat/.app/client/lib/tapi18n.js
new file mode 100644
index 0000000000000..c1ded6b860504
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/tapi18n.js
@@ -0,0 +1,28 @@
+import _ from 'underscore';
+
+this.t = function(key, ...replaces) {
+ if (_.isObject(replaces[0])) {
+ return TAPi18n.__(key, replaces);
+ } else {
+ return TAPi18n.__(key, {
+ postProcess: 'sprintf',
+ sprintf: replaces
+ });
+ }
+};
+
+this.tr = function(key, options, ...replaces) {
+ if (_.isObject(replaces[0])) {
+ return TAPi18n.__(key, options, replaces);
+ } else {
+ return TAPi18n.__(key, options, {
+ postProcess: 'sprintf',
+ sprintf: replaces
+ });
+ }
+};
+
+this.isRtl = (lang) => {
+ const language = lang ? lang : localStorage.getItem('userLanguage') ? localStorage.getItem('userLanguage') : 'en-US';
+ return ['ar', 'dv', 'fa', 'he', 'ku', 'ps', 'sd', 'ug', 'ur', 'yi'].includes(language.split('-').shift().toLowerCase());
+};
diff --git a/packages/rocketchat-livechat/.app/client/lib/triggers.js b/packages/rocketchat-livechat/.app/client/lib/triggers.js
new file mode 100644
index 0000000000000..3f958c47b97d8
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/lib/triggers.js
@@ -0,0 +1,142 @@
+/* globals Livechat */
+import visitor from '../../imports/client/visitor';
+
+function getAgent(triggerAction) {
+ return new Promise((resolve, reject) => {
+ const { params } = triggerAction;
+ if (params.sender === 'queue') {
+ const cache = localStorage.getItem('triggerAgent');
+ if (cache) {
+ const cacheAgent = JSON.parse(cache);
+
+ // cache valid for 1h
+ if (cacheAgent.ts && Date.now() - cacheAgent.ts < 3600000) {
+ return resolve(cacheAgent.agent);
+ }
+ }
+
+ Meteor.call('livechat:getNextAgent', {
+ token: visitor.getToken(),
+ department: Livechat.department
+ }, (error, result) => {
+ if (error) {
+ return reject(error);
+ }
+ localStorage.setItem('triggerAgent', JSON.stringify({
+ agent: result,
+ ts: Date.now()
+ }));
+
+ resolve(result);
+ });
+ } else if (params.sender === 'custom') {
+ resolve({
+ username: params.name
+ });
+ } else {
+ reject('Unknown sender');
+ }
+ });
+}
+
+this.Triggers = (function() {
+ let triggers = [];
+ let initiated = false;
+ let requests = [];
+ let enabled = true;
+
+ const fire = function(trigger) {
+ if (!enabled || visitor.getId()) {
+ return;
+ }
+ trigger.actions.forEach(function(action) {
+ if (action.name === 'send-message') {
+ // flag to skip the trigger if the action is 'send-message'
+ trigger.skip = true;
+
+ getAgent(action).then((agent) => {
+ let roomId = visitor.getRoom();
+
+ if (!roomId) {
+ roomId = Random.id();
+ visitor.setRoom(roomId);
+ }
+
+ Session.set('triggered', true);
+ ChatMessage.insert({
+ msg: action.params.msg,
+ rid: roomId,
+ u: agent
+ });
+
+ if (agent._id) {
+ Livechat.agent = agent;
+ }
+
+ parentCall('openWidget');
+ });
+ }
+ });
+ };
+
+ const processRequest = function(request) {
+ if (!initiated) {
+ return requests.push(request);
+ }
+ triggers.forEach(function(trigger) {
+ if (trigger.skip) {
+ return;
+ }
+ trigger.conditions.forEach(function(condition) {
+ switch (condition.name) {
+ case 'page-url':
+ if (request.location.href.match(new RegExp(condition.value))) {
+ fire(trigger);
+ }
+ break;
+
+ case 'time-on-site':
+ if (trigger.timeout) {
+ clearTimeout(trigger.timeout);
+ }
+ trigger.timeout = setTimeout(function() {
+ fire(trigger);
+ }, parseInt(condition.value) * 1000);
+ break;
+ }
+ });
+ });
+ };
+
+ const setTriggers = function(newTriggers) {
+ triggers = newTriggers;
+ };
+
+ const init = function() {
+ initiated = true;
+
+ if (requests.length > 0 && triggers.length > 0) {
+ requests.forEach(function(request) {
+ processRequest(request);
+ });
+
+ requests = [];
+ }
+ };
+
+ const setDisabled = function() {
+ enabled = false;
+ };
+
+ const setEnabled = function() {
+ enabled = true;
+ };
+
+ return {
+ init,
+ processRequest,
+ setTriggers,
+ setDisabled,
+ setEnabled
+ };
+}());
diff --git a/packages/rocketchat-livechat/.app/client/methods/sendMessageExternal.js b/packages/rocketchat-livechat/.app/client/methods/sendMessageExternal.js
new file mode 100644
index 0000000000000..8a2bdaebf2a7b
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/methods/sendMessageExternal.js
@@ -0,0 +1,27 @@
+import visitor from '../../imports/client/visitor';
+import s from 'underscore.string';
+
+Meteor.methods({
+ sendMessageLivechat(message) {
+ if (s.trim(message.msg) !== '') {
+ if (isNaN(TimeSync.serverOffset())) {
+ message.ts = new Date();
+ } else {
+ message.ts = new Date(Date.now() + TimeSync.serverOffset());
+ }
+
+ const user = Meteor.user();
+
+ message.u = {
+ _id: visitor.getId(),
+ username: user && user.username || 'visitor'
+ };
+
+ message.temp = true;
+
+ // message = RocketChat.callbacks.run 'beforeSaveMessage', message
+
+ ChatMessage.insert(message);
+ }
+ }
+});
diff --git a/packages/rocketchat-livechat/.app/client/routes/router.js b/packages/rocketchat-livechat/.app/client/routes/router.js
new file mode 100644
index 0000000000000..9b6e69af2952b
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/routes/router.js
@@ -0,0 +1,13 @@
+import visitor from '../../imports/client/visitor';
+
+BlazeLayout.setRoot('body');
+
+FlowRouter.route('/livechat', {
+ name: 'index',
+ triggersEnter: [
+ () => visitor.register()
+ ],
+ action() {
+ BlazeLayout.render('main', { center: 'livechatWindow' });
+ }
+});
diff --git a/packages/rocketchat-livechat/app/client/startup/customFields.js b/packages/rocketchat-livechat/.app/client/startup/customFields.js
similarity index 100%
rename from packages/rocketchat-livechat/app/client/startup/customFields.js
rename to packages/rocketchat-livechat/.app/client/startup/customFields.js
diff --git a/packages/rocketchat-livechat/.app/client/startup/visitor.js b/packages/rocketchat-livechat/.app/client/startup/visitor.js
new file mode 100644
index 0000000000000..92b723bc05fa6
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/startup/visitor.js
@@ -0,0 +1,29 @@
+import visitor from '../../imports/client/visitor';
+
+Meteor.startup(() => {
+ if (!localStorage.getItem('rocketChatLivechat')) {
+ localStorage.setItem('rocketChatLivechat', Random.id());
+ } else {
+ Tracker.autorun(c => {
+ if (!visitor.getId() && visitor.getToken()) {
+ Meteor.call('livechat:loginByToken', visitor.getToken(), (err, result) => {
+ if (result && result._id) {
+ visitor.setId(result._id);
+ c.stop();
+ }
+ });
+ }
+ });
+ }
+});
+
+Meteor.startup(() => {
+ let connected = false;
+ Tracker.autorun(function() {
+ var connectionStatus = Meteor.status();
+ if (visitor.getRoom() && visitor.getToken() && connectionStatus.connected && !connected) {
+ connected = connectionStatus.connected;
+ visitor.setConnected();
+ }
+ });
+});
diff --git a/packages/rocketchat-livechat/.app/client/stylesheets/main.less b/packages/rocketchat-livechat/.app/client/stylesheets/main.less
new file mode 100644
index 0000000000000..695ebb332081f
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/stylesheets/main.less
@@ -0,0 +1,880 @@
+@import "utils/_reset.import.less";
+@import "utils/_variables.import.less";
+@import "utils/_keyframes.import.less";
+@import "utils/_loading.import.less";
+
+* {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+}
+
+html,
+body {
+ height: 100%;
+}
+
+body {
+ margin: 0;
+ font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI";
+ font-size: 0.8rem;
+ color: @primary-font-color;
+ height: 100%;
+ width: 100%;
+ -webkit-font-smoothing: antialiased;
+ line-height: 1rem;
+ padding: 0;
+ overflow: hidden;
+ position: relative;
+ border-top-right-radius: 5px;
+ border-top-left-radius: 5px;
+}
+
+input,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ padding: 5px;
+ margin: 5px 0;
+ border: 1px solid #e7e7e7;
+ border-radius: 5px;
+ outline: none;
+}
+
+button {
+ background: none;
+ border: none;
+ padding: 0;
+ text-align: left;
+ cursor: pointer;
+ text-transform: inherit;
+ color: inherit;
+ font-style: inherit;
+}
+
+input:focus {
+ outline: none;
+ box-shadow: 0 0 0;
+}
+
+.button {
+ &:extend(.unselectable);
+ display: inline-block;
+ padding: 9px 12px;
+ font-weight: 500;
+ font-size: 13px;
+ margin: 4px;
+ text-transform: uppercase;
+ word-spacing: 0;
+ box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.125);
+ border: none;
+ border-radius: 0;
+ line-height: 16px;
+ position: relative;
+ cursor: pointer;
+ color: rgba(255, 255, 255, 0.85);
+ background-color: lighten(desaturate(@primary-background-color, 15%), 12.5%);
+
+ span {
+ position: relative;
+ z-index: 2;
+ }
+
+ &::before {
+ background-color: rgba(0, 0, 0, 0.1);
+ content: " ";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ z-index: 1;
+ transition: opacity 0.1s ease-out;
+ }
+
+ &:hover {
+ text-decoration: none;
+ color: #ffffff;
+
+ &::before {
+ opacity: 1;
+ }
+ }
+
+ &.secondary {
+ background-color: @tertiary-background-color;
+ color: @primary-font-color;
+
+ &::before {
+ background-color: rgba(0, 0, 0, 0.045);
+ }
+ }
+
+ &.clean {
+ font-size: 14px;
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.08);
+
+ &.primary {
+ font-weight: 600;
+ }
+ }
+
+ &.button-block {
+ display: block;
+ width: 100%;
+ }
+}
+
+.field-error {
+ border: 1px solid red;
+}
+
+.livechat-room {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ border-top-right-radius: inherit;
+ border-top-left-radius: inherit;
+
+ &.popout {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+
+ .title {
+ cursor: default;
+ }
+ }
+
+ .title {
+ flex: 1 0 @header-min-height;
+ line-height: @header-min-height;
+ border-top-right-radius: inherit;
+ border-top-left-radius: inherit;
+ color: #ffffff;
+ z-index: 10;
+ cursor: pointer;
+ padding: 0 10px;
+
+ h1 {
+ margin: 0;
+ font-size: 10pt;
+ display: inline-block;
+ }
+
+ .toolbar {
+ display: inline-block;
+ float: right;
+
+ svg {
+ cursor: pointer;
+ fill: currentColor;
+ width: 14px;
+ margin: 0 5px;
+ vertical-align: middle;
+
+ &:last-of-type {
+ margin-right: 0;
+ }
+ }
+ }
+ }
+
+ .header {
+ flex: 1 0 60px;
+ display: flex;
+ box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2);
+ background-color: #fcfcfc;
+ color: @secondary-font-color;
+ z-index: 2;
+
+ .picture {
+ flex: 0 1 60px;
+ padding: 5px 10px;
+
+ img {
+ width: 50px;
+ height: 50px;
+ border-radius: 6px;
+ border: 1px solid @window-border-color;
+ }
+ }
+
+ .info {
+ flex: 1;
+ padding: 5px 0;
+
+ h2 {
+ color: @primary-font-color;
+ font-size: 14px;
+ }
+
+ li {
+ font-size: 11px;
+ }
+ }
+ }
+
+ .messages {
+ flex: 1 1 100%;
+ background-color: #ffffff;
+ border-left: 1px solid @window-border-color;
+ border-right: 1px solid @window-border-color;
+ overflow-y: auto;
+
+ .wrapper {
+ padding-bottom: 6px;
+
+ ul {
+ list-style-type: none;
+ padding: 0;
+
+ li {
+ padding: 0;
+ }
+ }
+
+ .message {
+ font-size: 12px;
+ padding: 8px 10px 0;
+ position: relative;
+ line-height: 18px;
+ min-height: 36px;
+
+ &::after {
+ content: '';
+ display: block;
+ clear: both;
+ }
+
+ .content {
+ width: 75%;
+ background-color: #f3f3f3;
+ border: 1px solid desaturate(darken(#f3f3f3, 10%), 40%);
+ margin-left: 38px;
+ border-radius: 6px;
+ padding: 5px;
+ float: left;
+ word-wrap: break-word;
+ word-break: break-word;
+ -ms-hyphens: auto;
+ -moz-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+
+ &::before {
+ border-style: solid;
+ border-color: transparent desaturate(darken(#f3f3f3, 10%), 40%) transparent transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ font-size: 0;
+ pointer-events: none;
+ border-width: 5px;
+ position: absolute;
+ left: 38px;
+ }
+ }
+
+ &:nth-child(1) {
+ margin-top: 0;
+ }
+
+ &.new-day {
+ margin-top: 60px;
+
+ &::before {
+ content: attr(data-date);
+ display: block;
+ position: absolute;
+ top: -30px;
+ left: calc(~'50% - 70px');
+ font-size: 10px;
+ font-weight: 600;
+ text-align: center;
+ color: @secondary-font-color;
+ z-index: 1;
+ padding: 0 10px;
+ background-color: #ffffff;
+ min-width: 120px;
+ }
+
+ .content {
+ &::after {
+ content: " ";
+ display: block;
+ position: absolute;
+ top: -20px;
+ left: 0;
+ width: 100%;
+ border-top: 1px solid #dddddd;
+ }
+ }
+ }
+
+ .edit-message {
+ display: none;
+ cursor: pointer;
+ }
+
+ &.own {
+ .content {
+ background-color: #feffd7;
+ border: 1px solid desaturate(darken(#feffd7, 10%), 40%);
+ float: right;
+ margin-right: 3px;
+
+ &::before {
+ border-style: solid;
+ border-color: transparent transparent transparent desaturate(darken(#feffd7, 10%), 40%);
+ content: " ";
+ height: 0;
+ width: 0;
+ font-size: 0;
+ pointer-events: none;
+ border-width: 5px;
+ position: absolute;
+ right: 3px;
+ left: inherit;
+ }
+ }
+
+ .thumb {
+ display: none;
+ }
+ }
+
+ .delete-message {
+ display: none;
+ cursor: pointer;
+ }
+
+ .user {
+ display: inline-block;
+ font-weight: 600;
+ color: #444444;
+ margin-right: 5px;
+ outline: none;
+
+ &:hover {
+ color: #333333;
+ }
+ }
+
+ .thumb {
+ position: absolute;
+ left: 10px;
+ top: 6px;
+ display: block;
+ width: 30px;
+ height: 30px;
+ }
+
+ .info {
+ color: @info-font-color;
+ display: inline-block;
+ float: right;
+ margin: 9px -1px -5px 9px;
+ font-size: 9px;
+ text-align: right;
+ left: -10px;
+ width: 55px;
+
+ .edited {
+ display: inline-block;
+ }
+
+ .edit-message {
+ float: left;
+ margin-left: 1px;
+ }
+
+ .delete-message {
+ float: left;
+ }
+ }
+
+ &.sequential {
+ padding-top: 2px;
+ min-height: 20px;
+
+ .user {
+ display: none;
+ }
+
+ .thumb {
+ display: none;
+ }
+ }
+
+ &.system {
+ .body {
+ color: @info-font-color;
+ font-style: italic;
+
+ em {
+ font-weight: 600;
+ }
+ }
+ }
+
+ .avatar-initials {
+ line-height: 40px;
+ }
+
+ a {
+ color: @link-font-color;
+ font-weight: 400;
+
+ &:hover {
+ color: darken(@link-font-color, 10%);
+ text-decoration: underline;
+ }
+ }
+
+ .body {
+ opacity: 1;
+ transition: opacity 1s linear;
+ }
+
+ &.temp .body {
+ opacity: 0.5;
+ }
+
+ &.msg-error .body {
+ text-decoration: line-through;
+ }
+
+ .avatar {
+ height: 100%;
+ width: 100%;
+
+ .avatar-image {
+ height: 100%;
+ width: 100%;
+ min-height: 20px;
+ min-width: 20px;
+ display: block;
+ position: relative;
+ background-color: transparent;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ border-radius: 4px;
+ }
+ }
+ }
+ }
+
+ .new-message {
+ margin: 0 -65px;
+ position: absolute;
+ background: #428bca;
+ border-radius: 20px;
+ width: 130px;
+ height: 30px;
+ text-align: center;
+ color: #ffffff;
+ line-height: 30px;
+ font-size: 0.8em;
+ cursor: pointer;
+ bottom: 8px;
+ left: 50%;
+ z-index: 5;
+ transition: transform 0.3s ease-out;
+ transform: translateY(-40px);
+
+ &.not {
+ transform: translateY(100%);
+ }
+ }
+
+ .error {
+ bottom: @footer-min-height;
+ position: fixed;
+ width: 100%;
+ background-color: #f7d799;
+ padding: 5px;
+ z-index: 8;
+ transition: transform 0.2s ease-out;
+ transform: translateY(100%);
+
+ &.show {
+ transform: translateY(0);
+ }
+ }
+ }
+
+ .footer {
+ flex: 1 0 @footer-min-height;
+ z-index: 10;
+ background-color: #fcfcfc;
+ border-top: 1px solid @window-border-color;
+ border-left: 1px solid @window-border-color;
+ border-right: 1px solid @window-border-color;
+
+ .message-bar {
+ display: flex;
+ flex-direction: row;
+ padding-top: 6px;
+
+ .input-wrapper {
+ flex-grow: 1;
+ padding-left: 6px;
+
+ textarea {
+ display: block;
+ padding: 6px 8px;
+ padding-right: 38px;
+ overflow-y: auto;
+ resize: none;
+ margin: 0;
+ max-height: 200px;
+ width: 100%;
+ font-size: 12px;
+ -webkit-appearance: none;
+ height: 28px;
+ line-height: normal;
+ background-color: #ffffff;
+ position: relative;
+ }
+ }
+
+ .buttons {
+ color: @secondary-font-color;
+ fill: @secondary-font-color;
+ display: flex;
+ align-items: center;
+ padding: 0 5px;
+
+ svg {
+ width: 15px;
+ height: 15px;
+ margin: 0 4px;
+ cursor: pointer;
+ transition: fill 0.15s ease-out;
+
+ &:hover {
+ fill: @primary-font-color;
+ }
+ }
+ }
+ }
+
+ .toggle-options {
+ clear: both;
+ color: @secondary-font-color;
+ margin-left: 6px;
+ outline: none;
+ margin-top: 5px;
+ font-size: 0.65rem;
+ }
+
+ .typing {
+ clear: both;
+ color: @secondary-font-color;
+ margin-left: 8px;
+ outline: none;
+ margin-top: 2px;
+ font-size: 0.65rem;
+ }
+
+ .options-menu {
+ min-width: 100px;
+ bottom: 21px;
+ left: 6px;
+ border-radius: 2px;
+ padding: 6px 0;
+ background-color: #ffffff;
+ color: @secondary-font-color;
+ box-shadow:
+ 0 1px 1px 0 rgba(0, 0, 0, 0.2),
+ 0 2px 10px 0 rgba(0, 0, 0, 0.16);
+ position: absolute;
+ z-index: 200;
+ transition: transform 0.15s ease, visibility 0.15s ease, opacity 0.15s ease;
+ transform: translateY(30px);
+ opacity: 0;
+ visibility: hidden;
+
+ &.show {
+ transform: translateY(0);
+ opacity: 1;
+ display: block;
+ visibility: visible;
+ }
+
+ ul {
+ li {
+ padding: 0 13px 0 8px;
+
+ &:hover {
+ background-color: #eeeeee;
+ }
+
+ button {
+ display: block;
+ padding: 4px 2px;
+ outline: none;
+ }
+ }
+ }
+ }
+ }
+
+ .offline {
+ flex: 1 1 100%;
+ background-color: white;
+ padding: 1em 10px;
+ border-left: 1px solid @window-border-color;
+ border-right: 1px solid @window-border-color;
+
+ .offline-message {
+ padding: 1em 0;
+ }
+
+ .message-sent {
+ text-align: center;
+ }
+
+ form {
+ input,
+ textarea {
+ display: block;
+ width: 100%;
+ }
+
+ .buttons {
+ text-align: center;
+ }
+
+ .error {
+ display: none;
+ background-color: #f7d799;
+ padding: 5px;
+
+ &.show {
+ display: block;
+ }
+ }
+ }
+ }
+}
+
+.livechat-form {
+ flex: 1 1 100%;
+ display: block;
+ background-color: #ffffff;
+ border-left: 1px solid @window-border-color;
+ border-right: 1px solid @window-border-color;
+ padding: 5px;
+
+ input,
+ select {
+ display: block;
+ background-color: #ffffff;
+ }
+
+ .error {
+ display: none;
+ background-color: #f7d799;
+ padding: 5px;
+
+ &.show {
+ display: block;
+ }
+ }
+
+ form {
+ padding: 0 1em;
+ text-align: center;
+
+ input,
+ select {
+ width: 100%;
+ }
+ }
+}
+
+.modal {
+ border-top-right-radius: inherit;
+ border-top-left-radius: inherit;
+
+ .overlay {
+ border-top-right-radius: inherit;
+ border-top-left-radius: inherit;
+ background-color: rgba(0, 0, 0, 0.5);
+ position: fixed;
+ height: 100%;
+ width: 100%;
+ z-index: 9990;
+ top: 0;
+ left: 0;
+ }
+
+ .wrapper {
+ z-index: 9999;
+ background: white;
+ position: fixed;
+ height: 80%;
+ width: 80%;
+ top: 15%;
+ left: 10%;
+ border-radius: 6px;
+ display: flex;
+ flex-direction: column;
+
+ header {
+ flex: 1 0 40px;
+ padding: 0 15px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ line-height: 40px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+ .content {
+ overflow-y: auto;
+ padding: 10px;
+ flex: 1 1 100%;
+
+ .instructions {
+ margin-top: 5px;
+ }
+
+ .survey-item {
+ margin-top: 20px;
+
+ .question {
+ display: block;
+ }
+
+ .answer {
+ margin-right: 5px;
+ display: inline-block;
+ text-align: center;
+ }
+ }
+ }
+
+ footer {
+ flex: 1 0 60px;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ line-height: 60px;
+ text-align: right;
+ padding-right: 20px;
+ }
+ }
+}
+
+.powered-by {
+ margin-top: -20px;
+ line-height: 20px;
+ right: 0;
+ z-index: 10;
+ text-align: right;
+ font-size: 0.65rem;
+ height: 20px;
+ color: #666666;
+ padding: 0 1em;
+ opacity: 0.5;
+ align-self: flex-end;
+ transition: opacity 0.15s ease-out;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ a {
+ text-decoration: none;
+ margin-left: 1px;
+
+ img {
+ height: 14px;
+ vertical-align: middle;
+ }
+ }
+}
+
+.sweet-overlay {
+ border-top-right-radius: inherit;
+ border-top-left-radius: inherit;
+}
+
+.video-call {
+ position: fixed;
+ top: @header-min-height;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: #000000;
+ z-index: 11;
+
+ .video-overlay {
+ position: fixed;
+ top: @header-min-height;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 13;
+
+ .toolbar {
+ position: absolute;
+ bottom: 40px;
+ width: 100%;
+ text-align: center;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(50px);
+ transition: opacity 0.175s ease-out, transform 0.175s ease-out, visibility 0.175s ease-out;
+
+ &.visible {
+ opacity: 1;
+ visibility: visible;
+ transform: translateY(0);
+ }
+
+ .end-call {
+ background-color: red;
+ fill: white;
+ border-radius: 50%;
+ height: 60px;
+ width: 60px;
+ text-align: center;
+ outline: none;
+
+ svg {
+ width: 30px;
+ height: 30px;
+ }
+ }
+ }
+ }
+
+ .container {
+ z-index: 12;
+ }
+}
+
+@media all and(max-height: 200px) {
+ .livechat-room {
+ .title {
+ height: 100%;
+ }
+
+ .footer {
+ display: none;
+ }
+
+ .messages {
+ display: none;
+ }
+
+ .powered-by {
+ display: none;
+ }
+ }
+}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_keyframes.import.less
similarity index 95%
rename from packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less
rename to packages/rocketchat-livechat/.app/client/stylesheets/utils/_keyframes.import.less
index 8aa3df96f1da3..04261b859690e 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less
+++ b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_keyframes.import.less
@@ -117,13 +117,13 @@
1% {
opacity: 0;
visibility: visible;
- .transform(translateY(-150px));
+ transform: translateY(-150px);
}
100% {
opacity: 1;
visibility: visible;
- .transform(translateY(0));
+ transform: translateY(0);
}
}
@@ -155,7 +155,7 @@
99% {
opacity: 0;
visibility: visible;
- .transform(translateY(150px));
+ transform: translateY(150px);
}
100% {
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_loading.import.less b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_loading.import.less
similarity index 100%
rename from packages/rocketchat-livechat/app/client/stylesheets/utils/_loading.import.less
rename to packages/rocketchat-livechat/.app/client/stylesheets/utils/_loading.import.less
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_reset.import.less
similarity index 100%
rename from packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less
rename to packages/rocketchat-livechat/.app/client/stylesheets/utils/_reset.import.less
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_variables.import.less
similarity index 96%
rename from packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less
rename to packages/rocketchat-livechat/.app/client/stylesheets/utils/_variables.import.less
index a8aa9a3b06f32..27e8fd7c61c73 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less
+++ b/packages/rocketchat-livechat/.app/client/stylesheets/utils/_variables.import.less
@@ -24,7 +24,7 @@
@quaternary-font-color: rgba(255, 255, 255, 0.85);
@info-font-color: #aaaaaa;
-@status-online: #35ac19;
+@status-online: #4dff4d;
@status-offline: rgba(150, 150, 150, 0.5);
@status-busy: #d30230;
@status-away: #fcb316;
diff --git a/packages/rocketchat-livechat/app/client/views/avatar.html b/packages/rocketchat-livechat/.app/client/views/avatar.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/avatar.html
rename to packages/rocketchat-livechat/.app/client/views/avatar.html
diff --git a/packages/rocketchat-livechat/.app/client/views/avatar.js b/packages/rocketchat-livechat/.app/client/views/avatar.js
new file mode 100644
index 0000000000000..62443cf499121
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/avatar.js
@@ -0,0 +1,20 @@
+import visitor from '../../imports/client/visitor';
+
+Template.avatar.helpers({
+ imageUrl() {
+ let username = this.username;
+ if (!username && this.userId) {
+ const user = Meteor.users.findOne(this.userId, { fields: { username: 1 }});
+ username = user && user.username;
+ }
+
+ const currentUser = visitor.getData();
+ if (!username || (currentUser && currentUser.username === username)) {
+ return;
+ }
+
+ Session.get(`avatar_random_${ username }`);
+
+ return `background-image:url(${ getAvatarUrlFromUsername(username) });`;
+ }
+});
diff --git a/packages/rocketchat-livechat/.app/client/views/livechatWindow.html b/packages/rocketchat-livechat/.app/client/views/livechatWindow.html
new file mode 100644
index 0000000000000..5946a7eca43a0
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/livechatWindow.html
@@ -0,0 +1,57 @@
+
+ {{#if livechatStarted}}
+ {{#if showWidget}}
+
+
+ {{#if livechatOnline}}
+ {{#if showRegisterForm}}
+ {{> register}}
+ {{else}}
+ {{> messages}}
+ {{#if showSwitchDepartmentForm}}
+ {{> switchDepartment}}
+ {{/if}}
+ {{/if}}
+ {{else}}
+
+ {{> offlineForm (offlineData)}}
+
+ {{/if}}
+ {{> poweredBy }}
+
+ {{/if}}
+ {{/if}}
+ {{#if videoCalling}}
+ {{> videoCall}}
+ {{/if}}
+
diff --git a/packages/rocketchat-livechat/app/client/views/livechatWindow.js b/packages/rocketchat-livechat/.app/client/views/livechatWindow.js
similarity index 80%
rename from packages/rocketchat-livechat/app/client/views/livechatWindow.js
rename to packages/rocketchat-livechat/.app/client/views/livechatWindow.js
index 0fe40f00f572c..c0fdf8f2d18f1 100644
--- a/packages/rocketchat-livechat/app/client/views/livechatWindow.js
+++ b/packages/rocketchat-livechat/.app/client/views/livechatWindow.js
@@ -1,4 +1,5 @@
/* globals Department, Livechat, LivechatVideoCall */
+import visitor from '../../imports/client/visitor';
Template.livechatWindow.helpers({
title() {
@@ -17,11 +18,14 @@ Template.livechatWindow.helpers({
return Session.get('sound');
},
showRegisterForm() {
- if (Session.get('triggered') || Meteor.userId()) {
+ if (Session.get('triggered') || visitor.getId()) {
return false;
}
return Livechat.registrationForm;
},
+ showSwitchDepartmentForm() {
+ return Livechat.showSwitchDepartmentForm;
+ },
livechatStarted() {
return Livechat.online !== null;
},
@@ -44,6 +48,9 @@ Template.livechatWindow.helpers({
},
isOpened() {
return Livechat.isWidgetOpened();
+ },
+ showWidget() {
+ return Livechat.online || Livechat.displayOfflineForm;
}
});
@@ -64,9 +71,13 @@ Template.livechatWindow.events({
Template.livechatWindow.onCreated(function() {
Session.set({sound: true});
+ TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
+
+ const availableLanguages = TAPi18n.getLanguages();
+
const defaultAppLanguage = () => {
let lng = window.navigator.userLanguage || window.navigator.language || 'en';
- let regexp = /([a-z]{2}-)([a-z]{2})/;
+ const regexp = /([a-z]{2}-)([a-z]{2})/;
if (regexp.test(lng)) {
lng = lng.replace(regexp, function(match, ...parts) {
return parts[0] + parts[1].toUpperCase();
@@ -106,13 +117,25 @@ Template.livechatWindow.onCreated(function() {
if (result.room) {
Livechat.room = result.room._id;
+
+ visitor.setConnected();
+ }
+
+ if (result.visitor) {
+ visitor.setData(result.visitor);
}
if (result.agentData) {
Livechat.agent = result.agentData;
}
- TAPi18n.setLanguage((result.language || defaultAppLanguage()).split('-').shift());
+ let language = result.language || defaultAppLanguage();
+
+ if (!availableLanguages[language]) {
+ language = language.split('-').shift();
+ }
+
+ TAPi18n.setLanguage(language);
Triggers.setTriggers(result.triggers);
Triggers.init();
@@ -120,7 +143,7 @@ Template.livechatWindow.onCreated(function() {
result.departments.forEach((department) => {
Department.insert(department);
});
-
+ Livechat.allowSwitchingDepartments = result.allowSwitchingDepartments;
Livechat.ready();
}
});
diff --git a/packages/rocketchat-livechat/app/client/views/loading.html b/packages/rocketchat-livechat/.app/client/views/loading.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/loading.html
rename to packages/rocketchat-livechat/.app/client/views/loading.html
diff --git a/packages/rocketchat-livechat/.app/client/views/main.html b/packages/rocketchat-livechat/.app/client/views/main.html
new file mode 100644
index 0000000000000..5b65e57c29cee
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/main.html
@@ -0,0 +1,21 @@
+
+ Rocket.Chat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{> Template.dynamic template=center}}
+
diff --git a/packages/rocketchat-livechat/app/client/views/message.html b/packages/rocketchat-livechat/.app/client/views/message.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/message.html
rename to packages/rocketchat-livechat/.app/client/views/message.html
diff --git a/packages/rocketchat-livechat/.app/client/views/message.js b/packages/rocketchat-livechat/.app/client/views/message.js
new file mode 100644
index 0000000000000..9dc31af875b10
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/message.js
@@ -0,0 +1,116 @@
+/* globals Livechat, t, tr, livechatAutolinker */
+import moment from 'moment';
+import visitor from '../../imports/client/visitor';
+import s from 'underscore.string';
+
+Template.message.helpers({
+ own() {
+ if (this.u && this.u._id === visitor.getId()) {
+ return 'own';
+ }
+ },
+ time() {
+ return moment(this.ts).format('LT');
+ },
+ date() {
+ return moment(this.ts).format('LL');
+ },
+ isTemp() {
+ if (this.temp === true) {
+ return 'temp';
+ }
+ },
+ error() {
+ if (this.error) {
+ return 'msg-error';
+ }
+ },
+ body() {
+ switch (this.t) {
+ case 'r':
+ return t('Room_name_changed', { room_name: this.msg, user_by: this.u.username });
+ case 'au':
+ return t('User_added_by', { user_added: this.msg, user_by: this.u.username });
+ case 'ru':
+ return t('User_removed_by', { user_removed: this.msg, user_by: this.u.username });
+ case 'ul':
+ return tr('User_left', { context: this.u.gender }, { user_left: this.u.username });
+ case 'uj':
+ return tr('User_joined', { context: this.u.gender }, { user: this.u.username });
+ case 'wm':
+ return t('Welcome', { user: this.u.username });
+ case 'livechat-close':
+ return t('Conversation_finished');
+ // case 'rtc': return RocketChat.callbacks.run('renderRtcMessage', this);
+ default:
+ this.html = this.msg;
+ if (s.trim(this.html) !== '') {
+ this.html = s.escapeHTML(this.html);
+ }
+ // message = RocketChat.callbacks.run 'renderMessage', this
+ const message = this;
+ this.html = message.html.replace(/\n/gm, ' ');
+ return livechatAutolinker.link(this.html);
+ }
+ },
+
+ system() {
+ if (['s', 'p', 'f', 'r', 'au', 'ru', 'ul', 'wm', 'uj', 'livechat-close'].includes(this.t)) {
+ return 'system';
+ }
+ },
+
+ sender() {
+ const agent = Livechat.agent;
+ if (agent && this.u.username === agent.username) {
+ return agent.name || agent.username;
+ }
+ return this.u.username;
+ }
+});
+
+Template.message.onViewRendered = function(context) {
+ const view = this;
+ this._domrange.onAttached(function(domRange) {
+ const lastNode = domRange.lastNode();
+ const previousNode = lastNode.previousElementSibling;
+ const nextNode = lastNode.nextElementSibling;
+
+ if (!previousNode || previousNode.dataset.date !== lastNode.dataset.date) {
+ $(lastNode).addClass('new-day');
+ $(lastNode).removeClass('sequential');
+ } else if (previousNode.dataset.username !== lastNode.dataset.username) {
+ $(lastNode).removeClass('sequential');
+ }
+
+ if (nextNode && nextNode.dataset.date === lastNode.dataset.date) {
+ $(nextNode).removeClass('new-day');
+ $(nextNode).addClass('sequential');
+ } else {
+ $(nextNode).addClass('new-day');
+ $(nextNode).removeClass('sequential');
+ }
+
+ if (!nextNode || nextNode.dataset.username !== lastNode.dataset.username) {
+ $(nextNode).removeClass('sequential');
+ }
+
+ if (context.urls && context.urls.length > 0 && Template.oembedBaseWidget) {
+ context.urls.forEach(item => {
+ const urlNode = lastNode.querySelector(`.body a[href="${ item.url }"]`);
+ if (urlNode) {
+ $(urlNode).replaceWith(Blaze.toHTMLWithData(Template.oembedBaseWidget, item));
+ }
+ });
+ }
+
+ if (!nextNode) {
+ if (lastNode.classList.contains('own')) {
+ view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom = true;
+ } else if (view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom !== true) {
+ const newMessage = document.querySelector('.new-message');
+ newMessage.className = 'new-message';
+ }
+ }
+ });
+};
diff --git a/packages/rocketchat-livechat/app/client/views/messages.html b/packages/rocketchat-livechat/.app/client/views/messages.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/messages.html
rename to packages/rocketchat-livechat/.app/client/views/messages.html
diff --git a/packages/rocketchat-livechat/.app/client/views/messages.js b/packages/rocketchat-livechat/.app/client/views/messages.js
new file mode 100644
index 0000000000000..9d298fa207cfc
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/messages.js
@@ -0,0 +1,201 @@
+/* globals Livechat, LivechatVideoCall, MsgTyping */
+import visitor from '../../imports/client/visitor';
+import _ from 'underscore';
+
+Template.messages.helpers({
+ messages() {
+ return ChatMessage.find({
+ rid: visitor.getRoom(),
+ t: {
+ '$ne': 't'
+ }
+ }, {
+ sort: {
+ ts: 1
+ }
+ });
+ },
+ showOptions() {
+ if (Template.instance().showOptions.get()) {
+ return 'show';
+ } else {
+ return '';
+ }
+ },
+ optionsLink() {
+ if (Template.instance().showOptions.get()) {
+ return t('Close_menu');
+ } else {
+ return t('Options');
+ }
+ },
+ videoCallEnabled() {
+ return Livechat.videoCall;
+ },
+ showConnecting() {
+ return Livechat.connecting;
+ },
+ usersTyping() {
+ const users = MsgTyping.get(visitor.getRoom());
+ if (users.length === 0) {
+ return;
+ }
+ if (users.length === 1) {
+ return {
+ multi: false,
+ selfTyping: MsgTyping.selfTyping.get(),
+ users: users[0]
+ };
+ }
+ // usernames = _.map messages, (message) -> return message.u.username
+ let last = users.pop();
+ if (users.length > 4) {
+ last = t('others');
+ }
+ // else
+ let usernames = users.join(', ');
+ usernames = [usernames, last];
+ return {
+ multi: true,
+ selfTyping: MsgTyping.selfTyping.get(),
+ users: usernames.join(` ${ t('and') } `)
+ };
+ },
+ agentData() {
+ const agent = Livechat.agent;
+ if (!agent) {
+ return null;
+ }
+
+ const agentData = {
+ avatar: getAvatarUrlFromUsername(agent.username)
+ };
+
+ if (agent.name) {
+ agentData.name = agent.name;
+ }
+
+ if (agent.emails && agent.emails[0] && agent.emails[0].address) {
+ agentData.email = agent.emails[0].address;
+ }
+
+ if (agent.customFields && agent.customFields.phone) {
+ agentData.phone = agent.customFields.phone;
+ }
+
+ return agentData;
+ }
+});
+
+Template.messages.events({
+ 'keyup .input-message'(event, instance) {
+ instance.chatMessages.keyup(visitor.getRoom(), event, instance);
+ instance.updateMessageInputHeight(event.currentTarget);
+ },
+ 'keydown .input-message'(event, instance) {
+ return instance.chatMessages.keydown(visitor.getRoom(), event, instance);
+ },
+ 'click .send-button'(event, instance) {
+ const input = instance.find('.input-message');
+ const sent = instance.chatMessages.send(visitor.getRoom(), input);
+ input.focus();
+ instance.updateMessageInputHeight(input);
+
+ return sent;
+ },
+ 'click .new-message'(event, instance) {
+ instance.atBottom = true;
+ return instance.find('.input-message').focus();
+ },
+ 'click .error'(event) {
+ return $(event.currentTarget).removeClass('show');
+ },
+ 'click .toggle-options'(event, instance) {
+ instance.showOptions.set(!instance.showOptions.get());
+ },
+ 'click .video-button'(event) {
+ event.preventDefault();
+
+ if (!visitor.getId()) {
+ Meteor.call('livechat:registerGuest', { token: visitor.getToken() }, (error, result) => {
+ if (error) {
+ return console.log(error.reason);
+ }
+
+ visitor.setId(result.userId);
+ LivechatVideoCall.request();
+ });
+ } else {
+ LivechatVideoCall.request();
+ }
+ }
+});
+
+Template.messages.onCreated(function() {
+ this.atBottom = true;
+
+ this.showOptions = new ReactiveVar(false);
+
+ this.updateMessageInputHeight = function(input) {
+ // Inital height is 28. If the scrollHeight is greater than that( we have more text than area ),
+ // increase the size of the textarea. The max-height is set at 200
+ // even if the scrollHeight become bigger than that it should never exceed that.
+ // Account for no text in the textarea when increasing the height.
+ // If there is no text, reset the height.
+ const inputScrollHeight = $(input).prop('scrollHeight');
+ if (inputScrollHeight > 28) {
+ return $(input).height($(input).val() === '' ? '15px' : (inputScrollHeight >= 200 ? inputScrollHeight - 50 : inputScrollHeight - 20));
+ }
+ };
+
+ $(document).click((/*event*/) => {
+ if (!this.showOptions.get()) {
+ return;
+ }
+ const target = $(event.target);
+ if (!target.closest('.options-menu').length && !target.is('.options-menu') && !target.closest('.toggle-options').length && !target.is('.toggle-options')) {
+ this.showOptions.set(false);
+ }
+ });
+});
+
+Template.messages.onRendered(function() {
+ this.chatMessages = new ChatMessages();
+ this.chatMessages.init(this.firstNode);
+});
+
+Template.messages.onRendered(function() {
+ const messages = this.find('.messages');
+ const newMessage = this.find('.new-message');
+ const template = this;
+
+ if (messages) {
+ const onscroll = _.throttle(function() {
+ template.atBottom = messages.scrollTop >= messages.scrollHeight - messages.clientHeight;
+ }, 200);
+ Meteor.setInterval(function() {
+ if (template.atBottom) {
+ messages.scrollTop = messages.scrollHeight - messages.clientHeight;
+ newMessage.className = 'new-message not';
+ }
+ }, 100);
+ messages.addEventListener('touchstart', function() {
+ template.atBottom = false;
+ });
+ messages.addEventListener('touchend', function() {
+ onscroll();
+ });
+ messages.addEventListener('scroll', function() {
+ template.atBottom = false;
+ onscroll();
+ });
+ messages.addEventListener('mousewheel', function() {
+ template.atBottom = false;
+ onscroll();
+ });
+ messages.addEventListener('wheel', function() {
+ template.atBottom = false;
+ onscroll();
+ });
+ }
+});
diff --git a/packages/rocketchat-livechat/app/client/views/offlineForm.html b/packages/rocketchat-livechat/.app/client/views/offlineForm.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/offlineForm.html
rename to packages/rocketchat-livechat/.app/client/views/offlineForm.html
diff --git a/packages/rocketchat-livechat/app/client/views/offlineForm.js b/packages/rocketchat-livechat/.app/client/views/offlineForm.js
similarity index 92%
rename from packages/rocketchat-livechat/app/client/views/offlineForm.js
rename to packages/rocketchat-livechat/.app/client/views/offlineForm.js
index 730297f087bde..d834cf58d406f 100644
--- a/packages/rocketchat-livechat/app/client/views/offlineForm.js
+++ b/packages/rocketchat-livechat/.app/client/views/offlineForm.js
@@ -1,3 +1,6 @@
+import _ from 'underscore';
+import s from 'underscore.string';
+
Template.offlineForm.helpers({
error() {
return Template.instance().error.get();
@@ -20,7 +23,7 @@ Template.offlineForm.events({
const form = event.currentTarget;
- let data = {
+ const data = {
name: form.elements['name'].value,
email: form.elements['email'].value,
message: form.elements['message'].value
@@ -40,6 +43,7 @@ Template.offlineForm.events({
return instance.showError(error.reason);
} else {
instance.messageSent.set(true);
+ parentCall('callback', ['offline-form-submit', data]);
}
});
}
diff --git a/packages/rocketchat-livechat/.app/client/views/options.html b/packages/rocketchat-livechat/.app/client/views/options.html
new file mode 100644
index 0000000000000..605111d3fce22
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/options.html
@@ -0,0 +1,10 @@
+
+
+
diff --git a/packages/rocketchat-livechat/.app/client/views/options.js b/packages/rocketchat-livechat/.app/client/views/options.js
new file mode 100644
index 0000000000000..c6c38c864c771
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/options.js
@@ -0,0 +1,44 @@
+/* globals Department, Livechat, swal */
+import visitor from '../../imports/client/visitor';
+
+Template.options.helpers({
+ showDepartments() {
+ return Livechat.allowSwitchingDepartments && Department.find({ showOnRegistration: true }).count() > 1;
+ },
+ departments() {
+ return Department.find({ showOnRegistration: true });
+ },
+ selectedDepartment() {
+ return this._id === Livechat.department;
+ }
+});
+
+Template.options.events({
+ 'click .end-chat'() {
+ swal({
+ text: t('Are_you_sure_do_you_want_end_this_chat'),
+ title: '',
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('No'),
+ closeOnConfirm: true,
+ html: false
+ }, () => {
+ Meteor.call('livechat:closeByVisitor', { roomId: visitor.getRoom(), token: visitor.getToken() }, (error) => {
+ if (error) {
+ return console.log('Error ->', error);
+ }
+ swal({
+ title: t('Chat_ended'),
+ type: 'success',
+ timer: 2000
+ });
+ });
+ });
+ },
+ 'click .switch-department'() {
+ Livechat.showSwitchDepartmentForm = true;
+ }
+});
diff --git a/packages/rocketchat-livechat/.app/client/views/poweredBy.html b/packages/rocketchat-livechat/.app/client/views/poweredBy.html
new file mode 100644
index 0000000000000..f327d98cecbe1
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/poweredBy.html
@@ -0,0 +1,8 @@
+
+
+ {{_ "Powered_by"}}
+
+
+
+
+
diff --git a/packages/rocketchat-livechat/app/client/views/register.html b/packages/rocketchat-livechat/.app/client/views/register.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/register.html
rename to packages/rocketchat-livechat/.app/client/views/register.html
diff --git a/packages/rocketchat-livechat/app/client/views/register.js b/packages/rocketchat-livechat/.app/client/views/register.js
similarity index 75%
rename from packages/rocketchat-livechat/app/client/views/register.js
rename to packages/rocketchat-livechat/.app/client/views/register.js
index f1119080040c0..19a6ffa8e5c9a 100644
--- a/packages/rocketchat-livechat/app/client/views/register.js
+++ b/packages/rocketchat-livechat/.app/client/views/register.js
@@ -1,4 +1,6 @@
/* globals Department, Livechat, LivechatVideoCall */
+import visitor from '../../imports/client/visitor';
+import _ from 'underscore';
Template.register.helpers({
error() {
@@ -23,45 +25,41 @@ Template.register.helpers({
Template.register.events({
'submit #livechat-registration'(e, instance) {
- var $email, $name;
e.preventDefault();
- let start = () => {
+ const start = () => {
instance.hideError();
if (instance.request === 'video') {
LivechatVideoCall.request();
}
};
- $name = instance.$('input[name=name]');
- $email = instance.$('input[name=email]');
+ const $name = instance.$('input[name=name]');
+ const $email = instance.$('input[name=email]');
if (!($name.val().trim() && $email.val().trim())) {
return instance.showError(TAPi18n.__('Please_fill_name_and_email'));
} else {
- var departmentId = instance.$('select[name=department]').val();
+ let departmentId = instance.$('select[name=department]').val();
if (!departmentId) {
- var department = Department.findOne({ showOnRegistration: true });
+ const department = Department.findOne({ showOnRegistration: true });
if (department) {
departmentId = department._id;
}
}
- var guest = {
+ const guest = {
token: visitor.getToken(),
name: $name.val(),
email: $email.val(),
- department: Livechat.deparment || departmentId
+ department: Livechat.department || departmentId
};
Meteor.call('livechat:registerGuest', guest, function(error, result) {
if (error != null) {
return instance.showError(error.reason);
}
- Meteor.loginWithToken(result.token, function(error) {
- if (error) {
- return instance.showError(error.reason);
- }
- start();
- });
+ parentCall('callback', ['pre-chat-form-submit', _.omit(guest, 'token')]);
+ visitor.setId(result.userId);
+ start();
});
}
},
diff --git a/packages/rocketchat-livechat/app/client/views/survey.html b/packages/rocketchat-livechat/.app/client/views/survey.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/survey.html
rename to packages/rocketchat-livechat/.app/client/views/survey.html
diff --git a/packages/rocketchat-livechat/.app/client/views/survey.js b/packages/rocketchat-livechat/.app/client/views/survey.js
new file mode 100644
index 0000000000000..c9c66add13a79
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/survey.js
@@ -0,0 +1,20 @@
+/* globals swal */
+import visitor from '../../imports/client/visitor';
+
+Template.survey.events({
+ 'click button.skip'(e, instance) {
+ instance.$('#survey').remove();
+ },
+
+ 'click button.send'(e, instance) {
+ const formData = instance.$('form').serializeArray();
+ Meteor.call('livechat:saveSurveyFeedback', visitor.getToken(), visitor.getRoom(), formData, function(/*err, results*/) {
+ instance.$('#survey').remove();
+ swal({
+ title: t('Thank_you_for_your_feedback'),
+ type: 'success',
+ timer: 2000
+ });
+ });
+ }
+});
diff --git a/packages/rocketchat-livechat/.app/client/views/switchDepartment.html b/packages/rocketchat-livechat/.app/client/views/switchDepartment.html
new file mode 100644
index 0000000000000..ee56767bd2a86
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/switchDepartment.html
@@ -0,0 +1,21 @@
+
+ {{#modal}}
+
+ {{/modal}}
+
diff --git a/packages/rocketchat-livechat/.app/client/views/switchDepartment.js b/packages/rocketchat-livechat/.app/client/views/switchDepartment.js
new file mode 100644
index 0000000000000..e6288ed920dd6
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/client/views/switchDepartment.js
@@ -0,0 +1,76 @@
+/* globals Department, Livechat, swal */
+import visitor from '../../imports/client/visitor';
+
+Template.switchDepartment.helpers({
+ departments() {
+ return Department.find({
+ showOnRegistration: true,
+ _id: {
+ $ne: Livechat.department
+ }
+ });
+ },
+ error() {
+ return Template.instance().error.get();
+ },
+ showError() {
+ return Template.instance().error.get() ? 'show' : '';
+ }
+});
+
+Template.switchDepartment.onCreated(function() {
+ this.error = new ReactiveVar();
+});
+
+Template.switchDepartment.events({
+ 'submit form'(e, instance) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ const departmentId = instance.$('.switch-department-select').val();
+ if (!departmentId) {
+ instance.error.set(t('Please_choose_a_department'));
+ return;
+ }
+
+ instance.error.set();
+ swal({
+ text: t('Are_you_sure_do_you_want_end_this_chat_and_switch_department'),
+ title: '',
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('No'),
+ closeOnConfirm: true,
+ html: false
+ }, () => {
+ Meteor.call('livechat:closeByVisitor', { roomId: visitor.getRoom(), token: visitor.getToken() }, (error) => {
+ if (error) {
+ return console.log('Error ->', error);
+ }
+
+ const guestData = {
+ token: visitor.getToken(),
+ department: departmentId
+ };
+ Meteor.call('livechat:setDepartmentForVisitor', guestData, (error) => {
+ if (error) {
+ return console.log('Error ->', error);
+ }
+ Livechat.department = departmentId;
+ Livechat.showSwitchDepartmentForm = false;
+ swal({
+ title: t('Department_switched'),
+ type: 'success',
+ timer: 2000
+ });
+ });
+ });
+ });
+ },
+
+ 'click #btnCancel'() {
+ Livechat.showSwitchDepartmentForm = false;
+ }
+});
diff --git a/packages/rocketchat-livechat/app/client/views/videoCall.html b/packages/rocketchat-livechat/.app/client/views/videoCall.html
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/videoCall.html
rename to packages/rocketchat-livechat/.app/client/views/videoCall.html
diff --git a/packages/rocketchat-livechat/app/client/views/videoCall.js b/packages/rocketchat-livechat/.app/client/views/videoCall.js
similarity index 100%
rename from packages/rocketchat-livechat/app/client/views/videoCall.js
rename to packages/rocketchat-livechat/.app/client/views/videoCall.js
diff --git a/packages/rocketchat-livechat/.app/i18n/ar.i18n.json b/packages/rocketchat-livechat/.app/i18n/ar.i18n.json
new file mode 100644
index 0000000000000..f8393f74f959d
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/ar.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "ملاحظات إضافية",
+ "Appearance": "المظهر",
+ "Are_you_sure_do_you_want_end_this_chat": "هل تُؤكّد إنهاء هذه الدردشة؟",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "هل تُؤكّد إنهاء هذه الدردشة وتغيير الفرع؟",
+ "Cancel": "إلغاء",
+ "Change": "تغيير",
+ "Chat_ended": "تم إنهاء الدردشة!",
+ "Choose_a_new_department": "اختيار فرع جديد",
+ "Close_menu": "إغلاق القائمة",
+ "Conversation_finished": "تم إنهاء المحادثة",
+ "End_chat": "إنهاء الدردشة",
+ "How_friendly_was_the_chat_agent": "كيف ودية وكان وكيل الدردشة؟",
+ "How_knowledgeable_was_the_chat_agent": "معرفة كيف كان وكيل الدردشة؟",
+ "How_responsive_was_the_chat_agent": "كيف تستجيب كان وكيل الدردشة؟",
+ "How_satisfied_were_you_with_this_chat": "ما مدى رضاك مع هذه الدردشة؟",
+ "Installation": "تنصيب",
+ "New_messages": "رسائل جديدة",
+ "No": "لا",
+ "Options": "خيارات",
+ "Please_answer_survey": "يرجى ان نتوقف لحظة للرد على مسح سريع حول هذه الدردشة",
+ "Please_choose_a_department": "الرجاء اختيار فرع",
+ "Please_fill_name_and_email": "الرجاء إدخال الإسم والبريد الإلكتروني",
+ "Powered_by": "مشغل بواسطة",
+ "Request_video_chat": "طلب دردشة عبر الفيديو",
+ "Select_a_department": "حدد القسم",
+ "Switch_department": "تغيير الفرع",
+ "Department_switched": "تم تغيير الفرع",
+ "Send": "إرسال",
+ "Skip": "تخطي",
+ "Start_Chat": "بدأ الدردشة",
+ "Survey": "الدراسة الاستقصائية",
+ "Survey_instructions": "معدل كل سؤال وفقا لالارتياح الخاص بك، 1 وهذا يعني أنك غير راضي تماما و 5 يعني كنت راضيا تماما.",
+ "Thank_you_for_your_feedback": "شكرا لأفادتك",
+ "Thanks_We_ll_get_back_to_you_soon": "شكر! سوف نعود إليك قريبا.",
+ "transcript_sent": "تم إرسال رسالة النسخ السماعي",
+ "Type_your_email": "اكتب بريدك الالكتروني",
+ "Type_your_message": "اكتب رسالتك",
+ "Type_your_name": "اكتب اسمك",
+ "User_joined": "العضو انضم",
+ "User_left": "اليسار المستخدم",
+ "We_are_offline_Sorry_for_the_inconvenience": "نحن حاليا. آسف للإزعاج.",
+ "Yes": "نعم",
+ "You": "أنت",
+ "You_must_complete_all_fields": "يجب عليك إكمال جميع الحقول"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/.app/i18n/az.i18n.json b/packages/rocketchat-livechat/.app/i18n/az.i18n.json
new file mode 100644
index 0000000000000..4d1f06b96d0c8
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/az.i18n.json
@@ -0,0 +1,3 @@
+{
+ "Additional_Feedback": "əlavə Əlaqə"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/bg.i18n.json b/packages/rocketchat-livechat/.app/i18n/bg.i18n.json
similarity index 97%
rename from packages/rocketchat-livechat/app/i18n/bg.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/bg.i18n.json
index 060a3ee278801..2a6ec769e46c9 100644
--- a/packages/rocketchat-livechat/app/i18n/bg.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/bg.i18n.json
@@ -1,6 +1,7 @@
{
"Are_you_sure_do_you_want_end_this_chat": "Сигурен ли си че искаш да прекратиш този чат?",
"Cancel": "Отказ",
+ "Change": "Промени",
"Chat_ended": "Край на чата",
"Close_menu": "Затваряне на менюто",
"Conversation_finished": "Разговорът завърши",
diff --git a/packages/rocketchat-livechat/app/i18n/ca.i18n.json b/packages/rocketchat-livechat/.app/i18n/ca.i18n.json
similarity index 83%
rename from packages/rocketchat-livechat/app/i18n/ca.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ca.i18n.json
index b076d4e9369b1..acc4e053f77f6 100644
--- a/packages/rocketchat-livechat/app/i18n/ca.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/ca.i18n.json
@@ -2,8 +2,11 @@
"Additional_Feedback": "Comentaris addicionals",
"Appearance": "Aparença",
"Are_you_sure_do_you_want_end_this_chat": "Segur que voleu finalitzar aquest xat?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Esteu segurs de finalitzar aquest xat i canviar de departament?",
"Cancel": "Cancel·la",
+ "Change": "Canvia",
"Chat_ended": "Xat finalitzat!",
+ "Choose_a_new_department": "Tria un nou departament",
"Close_menu": "Tanca el menú",
"Conversation_finished": "Conversa acabada",
"End_chat": "Finalitza xat",
@@ -16,10 +19,13 @@
"No": "No",
"Options": "Opcions",
"Please_answer_survey": "Si us plau, permeti'ns un moment per a una breu enquesta sobre aquest xat",
+ "Please_choose_a_department": "Si us plau, tria un departament",
"Please_fill_name_and_email": "Si us plau, omple el nom i l'adreça electrònica.",
"Powered_by": "Funciona amb",
"Request_video_chat": "Demana vídeo xat",
"Select_a_department": "Selecciona un departament",
+ "Switch_department": "Canvia departament",
+ "Department_switched": "Departament canviat",
"Send": "Envia",
"Skip": "Salta",
"Start_Chat": "Inicia xat",
diff --git a/packages/rocketchat-livechat/app/i18n/cs.i18n.json b/packages/rocketchat-livechat/.app/i18n/cs.i18n.json
similarity index 83%
rename from packages/rocketchat-livechat/app/i18n/cs.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/cs.i18n.json
index 96a789d1b1cb5..c0713304800a9 100644
--- a/packages/rocketchat-livechat/app/i18n/cs.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/cs.i18n.json
@@ -2,8 +2,11 @@
"Additional_Feedback": "Dodatečný Feedback",
"Appearance": "Vzhled",
"Are_you_sure_do_you_want_end_this_chat": "Opravdu chcete ukončit tuto konverzaci?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Opravdu ukončit tento chat a změnit oddělení?",
"Cancel": "Storno",
+ "Change": "Změnit",
"Chat_ended": "Konverzace ukončena",
+ "Choose_a_new_department": "Vyberte nové oddělení",
"Close_menu": "Zavřít menu",
"Conversation_finished": "Rozhovor skončil",
"End_chat": "Ukončit konverzaci",
@@ -16,10 +19,13 @@
"No": "Ne",
"Options": "Volby",
"Please_answer_survey": "Věnujte prosím chvilku času ohodnocení chatu.",
+ "Please_choose_a_department": "Prosím vyberte oddělení",
"Please_fill_name_and_email": "Prosím vyplňte jméno a e-mail",
"Powered_by": "Používá technologii",
"Request_video_chat": "Zažádat o video chat",
"Select_a_department": "Vyberte oddělení",
+ "Switch_department": "Změnit oddělení",
+ "Department_switched": "Oddělení změněno",
"Send": "Poslat",
"Skip": "Přeskočit",
"Start_Chat": "Spustit chat",
diff --git a/packages/rocketchat-livechat/app/i18n/da.i18n.json b/packages/rocketchat-livechat/.app/i18n/da.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/da.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/da.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/de-AT.i18n.json b/packages/rocketchat-livechat/.app/i18n/de-AT.i18n.json
similarity index 95%
rename from packages/rocketchat-livechat/app/i18n/de-AT.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/de-AT.i18n.json
index 2ef18fad73fd7..0b6040e974fc4 100644
--- a/packages/rocketchat-livechat/app/i18n/de-AT.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/de-AT.i18n.json
@@ -19,6 +19,8 @@
"Please_fill_name_and_email": "Bitte geben Sie einen Namen und eine E-Mail-Adresse ein.",
"Request_video_chat": "Video Chat anfragen",
"Select_a_department": "Abteilung auswählen",
+ "Switch_department": "Abteilung wechseln",
+ "Department_switched": "Abteilung gewechselt",
"Send": "Senden",
"Skip": "Überspringen",
"Start_Chat": "Chat beginnen",
diff --git a/packages/rocketchat-livechat/.app/i18n/de.i18n.json b/packages/rocketchat-livechat/.app/i18n/de.i18n.json
new file mode 100644
index 0000000000000..a6cffab45d7e8
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/de.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "Zusätzliches Feedback",
+ "Appearance": "Erscheinungsbild",
+ "Are_you_sure_do_you_want_end_this_chat": "Sind Sie sich sicher, dass Sie diesen Chat beenden wollen?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Sind Sie sich sicher, dass Sie diesen Chat beenden und die Abteilung wechseln wollen",
+ "Cancel": "Abbrechen",
+ "Change": "Ändern",
+ "Chat_ended": "Chat beendet!",
+ "Choose_a_new_department": "Wählen Sie eine neue Abteilung",
+ "Close_menu": "Menü schließen",
+ "Conversation_finished": "Gespräch beendet",
+ "End_chat": "Chat beenden",
+ "How_friendly_was_the_chat_agent": "Wie freundlich war der Chat-Agent?",
+ "How_knowledgeable_was_the_chat_agent": "Wie sachkundig war der Chat-Agent?",
+ "How_responsive_was_the_chat_agent": "Wie reaktionsschnell war der Chat-Agent?",
+ "How_satisfied_were_you_with_this_chat": "Wie zufrieden sind Sie mit diesem Gespräch?",
+ "Installation": "Installation",
+ "New_messages": "Neue Nachrichten",
+ "No": "Nein",
+ "Options": "Optionen",
+ "Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Gespräch zu beantworten.",
+ "Please_choose_a_department": "Wähle eine Abteilung",
+ "Please_fill_name_and_email": "Bitte gib einen Namen und eine E-Mail-Adresse ein",
+ "Powered_by": "Powered by",
+ "Request_video_chat": "Video-Chat anfragen",
+ "Select_a_department": "Abteilung auswählen",
+ "Switch_department": "Abteilung wechseln",
+ "Department_switched": "Abteilung wurde gewechselt",
+ "Send": "Senden",
+ "Skip": "Überspringen",
+ "Start_Chat": "Chat beginnen",
+ "Survey": "Umfrage",
+ "Survey_instructions": "Bewerte jede Frage: 1 bedeutet, \"total unzufrieden\", 5 \"vollständig zufrieden\".",
+ "Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung.",
+ "Thanks_We_ll_get_back_to_you_soon": "Vielen Dank! Wir kommen auf Sie zeitnah zurück.",
+ "transcript_sent": "Transkript versendet",
+ "Type_your_email": "Geben Sie Ihre E-Mail-Adresse an",
+ "Type_your_message": "Geben Sie Ihre Nachricht ein.",
+ "Type_your_name": "Geben Sie Ihren Namen ein",
+ "User_joined": "Benutzer.in wurde Mitglied",
+ "User_left": "Benutzer.in abgemeldet",
+ "We_are_offline_Sorry_for_the_inconvenience": "Tut uns leid, aber wir sind offline.",
+ "Yes": "Ja",
+ "You": "Sie",
+ "You_must_complete_all_fields": "Sie müssen alle Felder ausfüllen"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/el.i18n.json b/packages/rocketchat-livechat/.app/i18n/el.i18n.json
similarity index 81%
rename from packages/rocketchat-livechat/app/i18n/el.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/el.i18n.json
index 724ee91211ea0..d6cb296fd414a 100644
--- a/packages/rocketchat-livechat/app/i18n/el.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/el.i18n.json
@@ -1,13 +1,21 @@
{
"Additional_Feedback": "Πρόσθετα Σχόλια",
"Appearance": "Εμφάνιση",
+ "Are_you_sure_do_you_want_end_this_chat": "Είσαι σίγουρος ότι θες να τερματίσεις τη συνομιλία;",
+ "Cancel": "Ακύρωση",
+ "Change": "Αλλαγή",
+ "Chat_ended": "Η συνομιλία τελείωσε!",
+ "Close_menu": "Κλείσιμο μενού",
"Conversation_finished": "Η συνομιλία τελείωσε",
+ "End_chat": "Τερματισμός συνομιλίας",
"How_friendly_was_the_chat_agent": "Πόσο φιλικός ήταν ο εκπρόσωπος μας;",
"How_knowledgeable_was_the_chat_agent": "Πώς γνώστης ήταν ο εκπρόσωπος μας;",
"How_responsive_was_the_chat_agent": "Πώς ανταποκρίσιμος ήταν ο εκπρόσωπος μας;",
"How_satisfied_were_you_with_this_chat": "Πόσο ικανοποιημένοι είστε με αυτήν την συνομιλία;",
"Installation": "Εγκατάσταση",
"New_messages": "Νέα μηνύματα",
+ "No": "Όχι",
+ "Options": "Επιλογές",
"Please_answer_survey": "Αφιερώστε λίγο χρόνο για να απαντήσετε σε μια σύντομη έρευνα σχετικά με αυτή τη συνομιλία",
"Please_fill_name_and_email": "Παρακαλούμε συμπληρώστε το όνομα και το e-mail",
"Powered_by": "Powered by",
@@ -19,11 +27,14 @@
"Survey_instructions": "Βαθμολογήστε κάθε ερώτηση, σύμφωνα με την ικανοποίησή σας, 1 που σημαίνει ότι θα είναι εντελώς ανικανοποίητοι και 5 σημαίνει ότι είστε απόλυτα ικανοποιημένοι.",
"Thank_you_for_your_feedback": "Ευχαριστούμε για την ανταπόκρισή σας",
"Thanks_We_ll_get_back_to_you_soon": "Ευχαριστώ! Θα επικοινωνήσουμε μαζί σας σύντομα.",
+ "transcript_sent": "Το αντίγραφο της συνομιλίας στάλθηκε",
"Type_your_email": "Πληκτρολογήστε το email σας",
"Type_your_message": "Πληκτρολογήστε το μήνυμά σας",
"Type_your_name": "Πληκτρολογήστε το όνομά σας",
"User_joined": "εντάχθηκε χρήστη",
"User_left": "αριστερή χρήστη",
"We_are_offline_Sorry_for_the_inconvenience": "Είμαστε εκτός σύνδεσης. Συγγνώμη για την ταλαιπωρία.",
+ "Yes": "Ναι",
+ "You": "Εσύ",
"You_must_complete_all_fields": "Πρέπει να συμπληρώσετε όλα τα πεδία"
}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/en.i18n.json b/packages/rocketchat-livechat/.app/i18n/en.i18n.json
similarity index 79%
rename from packages/rocketchat-livechat/app/i18n/en.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/en.i18n.json
index 9e1e2c9e7360f..f7d5ffa4aa20e 100644
--- a/packages/rocketchat-livechat/app/i18n/en.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/en.i18n.json
@@ -1,9 +1,12 @@
{
"Additional_Feedback": "Additional Feedback",
"Appearance": "Appearance",
- "Are_you_sure_do_you_want_end_this_chat": "Are you sure do you want to end this chat?",
+ "Are_you_sure_do_you_want_end_this_chat": "Are you sure you want to end this chat?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Are you sure you want to end this chat and switch department?",
"Cancel": "Cancel",
+ "Change": "Change",
"Chat_ended": "Chat ended!",
+ "Choose_a_new_department": "Choose a new department",
"Close_menu": "Close menu",
"Conversation_finished": "Conversation finished",
"End_chat": "End chat",
@@ -16,10 +19,13 @@
"No": "No",
"Options": "Options",
"Please_answer_survey": "Please take a moment to answer a quick survey about this chat",
+ "Please_choose_a_department": "Please choose a department",
"Please_fill_name_and_email": "Please fill name and email",
"Powered_by": "Powered by",
"Request_video_chat": "Request video chat",
"Select_a_department": "Select a department",
+ "Switch_department": "Switch department",
+ "Department_switched": "Department switched",
"Send": "Send",
"Skip": "Skip",
"Start_Chat": "Start Chat",
diff --git a/packages/rocketchat-livechat/.app/i18n/eo.i18n.json b/packages/rocketchat-livechat/.app/i18n/eo.i18n.json
new file mode 100644
index 0000000000000..0830e1885e4fe
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/eo.i18n.json
@@ -0,0 +1,3 @@
+{
+ "Additional_Feedback": "Kromaj Rimarkojn"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/es.i18n.json b/packages/rocketchat-livechat/.app/i18n/es.i18n.json
similarity index 76%
rename from packages/rocketchat-livechat/app/i18n/es.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/es.i18n.json
index ecdcb5cefae6f..aaa06118e1418 100644
--- a/packages/rocketchat-livechat/app/i18n/es.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/es.i18n.json
@@ -2,24 +2,30 @@
"Additional_Feedback": "Comentarios adicionales",
"Appearance": "Apariencia",
"Are_you_sure_do_you_want_end_this_chat": "¿Estás seguro de que quieres finalizar este chat?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "¿Estás seguro de querer terminar este chat y cambiar de departamento?",
"Cancel": "Cancelar",
+ "Change": "Cambiar",
"Chat_ended": "Chat finalizado!",
+ "Choose_a_new_department": "Selecciona un nuevo departamento",
"Close_menu": "Cerrar menú",
"Conversation_finished": "Conversación terminada",
"End_chat": "Finalizar chat",
"How_friendly_was_the_chat_agent": "Que tan amigable fue nuestro agente de chat?",
- "How_knowledgeable_was_the_chat_agent": "Nuestro agente de chat mostró dominio sobre el tema?",
- "How_responsive_was_the_chat_agent": "Que tan eficiente al responder sus preguntas fue nuestro agente de chat?",
+ "How_knowledgeable_was_the_chat_agent": "¿Qué tan conocedor era el agente de chat?",
+ "How_responsive_was_the_chat_agent": "¿Qué tan receptivo fue el agente de chat?",
"How_satisfied_were_you_with_this_chat": "Que tan satisfecho quedo después de esta sesión de chat?",
"Installation": "Instalación ",
"New_messages": "Nuevos mensajes",
"No": "No",
"Options": "Opciones",
"Please_answer_survey": "Por favor, tómese un momento para responder una encuesta rápida sobre este chat",
+ "Please_choose_a_department": "Por favor selecciona un departamento",
"Please_fill_name_and_email": "Por favor introduzca su nombre y correo electrónico.",
"Powered_by": "Impulsado por",
"Request_video_chat": "Solicitar videochat",
"Select_a_department": "Seleccionar un departamento",
+ "Switch_department": "Cambiar de departamento",
+ "Department_switched": "Departamento cambiado",
"Send": "Enviar",
"Skip": "Saltar",
"Start_Chat": "Iniciar chat",
diff --git a/packages/rocketchat-livechat/.app/i18n/fa.i18n.json b/packages/rocketchat-livechat/.app/i18n/fa.i18n.json
new file mode 100644
index 0000000000000..d2b17a2e44ec9
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/fa.i18n.json
@@ -0,0 +1,41 @@
+{
+ "Additional_Feedback": "بازخورد اضافی",
+ "Appearance": "ظاهر",
+ "Are_you_sure_do_you_want_end_this_chat": "آیا مطمئن هستید که میخواهید این چت را پایان دهید؟",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "آیا مطمئن هستید که میخواهید این چت را پایان دهید و بخش را عوض کنید؟",
+ "Cancel": "لغو",
+ "Change": "تغییر",
+ "Chat_ended": "چت پایان یافت!",
+ "Choose_a_new_department": "یک بخش جدید را انتخاب کنید",
+ "Close_menu": "بستن منو",
+ "Conversation_finished": "مکالمه به پایان رسید",
+ "End_chat": "پایان دادن چت",
+ "How_friendly_was_the_chat_agent": "عامل چت چقدر دوستانه بود؟",
+ "How_knowledgeable_was_the_chat_agent": "عامل چت چقدر آگاه بود؟",
+ "How_responsive_was_the_chat_agent": "عامل چت چه میزان انعطاف پذیر بود؟",
+ "How_satisfied_were_you_with_this_chat": "چقدر از این چت راضی بودید؟",
+ "Installation": "نصب و راه اندازی",
+ "New_messages": "پیامهای جدید",
+ "No": "خیر",
+ "Options": "گزینهها",
+ "Please_answer_survey": "لطفا به نظرسنجی در مورد این چت پاسخ دهید",
+ "Please_choose_a_department": "لطفا یک بخش انتخاب کنید",
+ "Please_fill_name_and_email": "لطفا نام و ایمیل را پر کنید",
+ "Powered_by": "طراحی شده توسط",
+ "Request_video_chat": "درخواست چت ویدیویی",
+ "Select_a_department": "انتخاب بخش",
+ "Send": "ارسال",
+ "Skip": "پرش",
+ "Start_Chat": "شروع چت",
+ "Survey": "نظرسنجی",
+ "Survey_instructions": "به هر سوال بر اساس رضایتتان نمره دهید. ۱ به معنای عدم رضایت کامل و ۵ به معنای رضایت کامل است.",
+ "Thank_you_for_your_feedback": "تشکر به خاطر انعکاس نظرات",
+ "Thanks_We_ll_get_back_to_you_soon": "تشکر! به زودی باز خواهیم گشت.",
+ "Type_your_email": "ایمیل خود را بنویسید",
+ "Type_your_message": "پیام خود را بنویسید",
+ "Type_your_name": "نامتان را بنویسید",
+ "User_joined": "تاریخ عضویت کاربر",
+ "User_left": "تاریخ ترک کاربر",
+ "We_are_offline_Sorry_for_the_inconvenience": "متأسفانه در حال حاضر آفلاین هستیم.",
+ "You_must_complete_all_fields": "باید همه موارد را کامل کنید"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/fi.i18n.json b/packages/rocketchat-livechat/.app/i18n/fi.i18n.json
similarity index 81%
rename from packages/rocketchat-livechat/app/i18n/fi.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/fi.i18n.json
index d9797d678dff3..4d231cc093dc3 100644
--- a/packages/rocketchat-livechat/app/i18n/fi.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/fi.i18n.json
@@ -2,8 +2,11 @@
"Additional_Feedback": "Lisäpalaute",
"Appearance": "Ulkoasu",
"Are_you_sure_do_you_want_end_this_chat": "Haluatko lopettaa tämän keskustelun?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Oletko varma että haluat lopettaa tämän keskustelun ja vaihtaa osastoa?",
"Cancel": "Peruuta",
+ "Change": "Muuta",
"Chat_ended": "Keskustelu lopetettu!",
+ "Choose_a_new_department": "Valitse uusi osasto",
"Close_menu": "Sulje valikko",
"Conversation_finished": "Keskustelu päättynyt",
"End_chat": "Lopeta keskustelu",
@@ -16,9 +19,13 @@
"No": "Ei",
"Options": "Valinnat",
"Please_answer_survey": "Käytä hetki vastataksesi pikakyselyyn tästä chatista",
+ "Please_choose_a_department": "Ole hyvä ja valitse uusi osasto",
"Please_fill_name_and_email": "Täytä nimi ja sähköpostiosoite",
"Powered_by": "Palvelun tarjoaa",
+ "Request_video_chat": "Pyydä videochattia",
"Select_a_department": "Valitse osasto",
+ "Switch_department": "Vaihda osastoa",
+ "Department_switched": "Osasto vaihdettu",
"Send": "Lähetä",
"Skip": "Ohita",
"Start_Chat": "Aloita Chat",
diff --git a/packages/rocketchat-livechat/.app/i18n/fr.i18n.json b/packages/rocketchat-livechat/.app/i18n/fr.i18n.json
new file mode 100644
index 0000000000000..0b1aa6ba8f8fa
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/fr.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "Commentaires supplémentaires",
+ "Appearance": "Apparence",
+ "Are_you_sure_do_you_want_end_this_chat": "Êtes-vous sûr de vouloir mettre fin à cette conversation ?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Êtes vous sûr de vouloir terminer ce tchat en direct et changer de service ?",
+ "Cancel": "Annuler",
+ "Change": "Changer",
+ "Chat_ended": "Conversation terminée !",
+ "Choose_a_new_department": "Choisir un nouveau service",
+ "Close_menu": "Fermer le menu",
+ "Conversation_finished": "Conversation terminée",
+ "End_chat": "Mettre fin à la conversation",
+ "How_friendly_was_the_chat_agent": "Votre interlocuteur était-il sympathique ?",
+ "How_knowledgeable_was_the_chat_agent": "Les réponses de votre interlocuteur étaient-elles adaptées ?",
+ "How_responsive_was_the_chat_agent": "Votre interlocuteur a-t-il répondu à vos questions ?",
+ "How_satisfied_were_you_with_this_chat": "Êtes-vous satisfait de ce chat?",
+ "Installation": "Installation",
+ "New_messages": "Nouveaux messages",
+ "No": "Non",
+ "Options": "Options",
+ "Please_answer_survey": "Merci de prendre un moment pour répondre à un sondage rapide à propos de ce chat ",
+ "Please_choose_a_department": "Merci de choisir un service",
+ "Please_fill_name_and_email": "Veuillez saisir votre nom et votre adresse e-mail",
+ "Powered_by": "Propulsé par",
+ "Request_video_chat": "Demander un chat vidéo",
+ "Select_a_department": "Sélectionner un service",
+ "Switch_department": "Changer de service",
+ "Department_switched": "Changement de service effectué",
+ "Send": "Envoyer",
+ "Skip": "Passer",
+ "Start_Chat": "Démarrer un chat",
+ "Survey": "Sondage",
+ "Survey_instructions": "Notez chaque question en fonction de votre satisfaction, 1 signifiant que vous êtes très insatisfait et 5 que vous êtes entièrement satisfait.",
+ "Thank_you_for_your_feedback": "Merci pour votre retour",
+ "Thanks_We_ll_get_back_to_you_soon": "Merci ! Nous regarderons cela dès que possible.",
+ "transcript_sent": "Transcription envoyée",
+ "Type_your_email": "Entrez votre e-mail",
+ "Type_your_message": "Entrez votre message",
+ "Type_your_name": "Entrez votre nom",
+ "User_joined": "L'utilisateur a rejoint",
+ "User_left": "L'utilisateur est parti",
+ "We_are_offline_Sorry_for_the_inconvenience": "Nous sommes hors-ligne. Désolé pour le désagrément.",
+ "Yes": "Oui",
+ "You": "Vous",
+ "You_must_complete_all_fields": "Vous devez remplir tous les champs"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/he.i18n.json b/packages/rocketchat-livechat/.app/i18n/he.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/he.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/he.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/hr.i18n.json b/packages/rocketchat-livechat/.app/i18n/hr.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/hr.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/hr.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/hu.i18n.json b/packages/rocketchat-livechat/.app/i18n/hu.i18n.json
similarity index 81%
rename from packages/rocketchat-livechat/app/i18n/hu.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/hu.i18n.json
index 5d99b90e02324..dba580f17138a 100644
--- a/packages/rocketchat-livechat/app/i18n/hu.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/hu.i18n.json
@@ -3,19 +3,19 @@
"Appearance": "Megjelenés",
"Are_you_sure_do_you_want_end_this_chat": "Biztosan befejezi a beszélgetést?",
"Cancel": "Mégse",
- "Chat_ended": "Beszélgetés befejeződött!",
+ "Chat_ended": "A beszélgetés befejeződött!",
"Close_menu": "Menü bezárása",
"Conversation_finished": "Beszélgetés befejeződött",
"End_chat": "Beszélgetés befejezése",
- "How_friendly_was_the_chat_agent": "Hogyan barátságos volt a chat ügynök?",
+ "How_friendly_was_the_chat_agent": "Mennyire volt barátságos a chat ügynök?",
"How_knowledgeable_was_the_chat_agent": "Mennyire értett a chat ügynök?",
- "How_responsive_was_the_chat_agent": "Hogyan reagálnak volt a chat ügynök?",
- "How_satisfied_were_you_with_this_chat": "Mennyire volt elégedett ezzel a beszélgetés?",
+ "How_responsive_was_the_chat_agent": "Hogyan reagált a chat ügynök?",
+ "How_satisfied_were_you_with_this_chat": "Mennyire volt elégedett ezzel a beszélgetéssel?",
"Installation": "Telepítés",
"New_messages": "Új üzenetek",
"No": "Nem",
- "Options": "Lehetőségek",
- "Please_answer_survey": "Kérjük, szánjon egy kis választ egy gyors felmérést erről csevegés",
+ "Options": "Beállítások",
+ "Please_answer_survey": "Kérjük szánjon pár percet egy felmérésre, erről a beszélgetésről",
"Please_fill_name_and_email": "Kérjük töltse ki a nevét és e-mail címét",
"Powered_by": "Powered by",
"Request_video_chat": "Videó beszélgetés indítása",
diff --git a/packages/rocketchat-livechat/app/i18n/id.i18n.json b/packages/rocketchat-livechat/.app/i18n/id.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/id.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/id.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/it.i18n.json b/packages/rocketchat-livechat/.app/i18n/it.i18n.json
new file mode 100644
index 0000000000000..3070e876bd30a
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/it.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "Feedback Aggiuntivi",
+ "Appearance": "Aspetto",
+ "Are_you_sure_do_you_want_end_this_chat": "Sei sicuro di voler terminare questa chat?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Sei sicuro di voler terminare la chat e cambiare dipartimento?",
+ "Cancel": "Annulla",
+ "Change": "Cambia",
+ "Chat_ended": "Chat terminata!",
+ "Choose_a_new_department": "Seleziona un nuovo dipartimento",
+ "Close_menu": "Chiudi menu",
+ "Conversation_finished": "Conversazione terminata",
+ "End_chat": "Termina chat",
+ "How_friendly_was_the_chat_agent": "Quanto amichevole era l'operatore?",
+ "How_knowledgeable_was_the_chat_agent": "Quanto ben informato era l'operatore?",
+ "How_responsive_was_the_chat_agent": "Quanto efficiente era l'operatore?",
+ "How_satisfied_were_you_with_this_chat": "Quanto sei soddisfatto di questa chat?",
+ "Installation": "Installazione",
+ "New_messages": "Nuovi messaggi",
+ "No": "No",
+ "Options": "Opzioni",
+ "Please_answer_survey": "Hai un momento per rispondere a un rapido sondaggio su questa chat?",
+ "Please_choose_a_department": "Si prega di scegliere un dipartimento",
+ "Please_fill_name_and_email": "Si prega di compilare il nome e l'email",
+ "Powered_by": "Tecnologia di",
+ "Request_video_chat": "Richiedi video chat",
+ "Select_a_department": "Seleziona un reparto",
+ "Switch_department": "Cambia dipartimento",
+ "Department_switched": "Dipartimento cambiato",
+ "Send": "Invia",
+ "Skip": "Salta",
+ "Start_Chat": "Avvia chat",
+ "Survey": "Sondaggio",
+ "Survey_instructions": "Vota ogni domanda secondo il tuo senso di soddisfazione, 1 significa che sei completamente insoddisfatto e 5 significa che sei completamente soddisfatto.",
+ "Thank_you_for_your_feedback": "Grazie per il tuo feedback",
+ "Thanks_We_ll_get_back_to_you_soon": "Grazie! Torneremo al più presto.",
+ "transcript_sent": "Trascrizione inviata",
+ "Type_your_email": "Inserisci la tua email",
+ "Type_your_message": "Inserisci il tuo messaggio",
+ "Type_your_name": "Inserisci il tuo nome",
+ "User_joined": "L'utente si è unito",
+ "User_left": "L'utente ha abbandonato",
+ "We_are_offline_Sorry_for_the_inconvenience": "Siamo offline. Ci dispiace per l'inconveniente.",
+ "Yes": "Si",
+ "You": "Tu",
+ "You_must_complete_all_fields": "È necessario completare tutti i campi"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ja.i18n.json b/packages/rocketchat-livechat/.app/i18n/ja.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ja.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ja.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/km.i18n.json b/packages/rocketchat-livechat/.app/i18n/km.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/km.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/km.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/ko.i18n.json b/packages/rocketchat-livechat/.app/i18n/ko.i18n.json
new file mode 100644
index 0000000000000..4b8d8bc0aaa2d
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/ko.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "추가 의견",
+ "Appearance": "보기",
+ "Are_you_sure_do_you_want_end_this_chat": "이 채팅을 정말 끝내시겠습니까?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "현재 진행중인 채팅을 종료하고 부서를 변경하시겠습니까?",
+ "Cancel": "취소",
+ "Change": "변경",
+ "Chat_ended": "채팅이 종료되었습니다. ",
+ "Choose_a_new_department": "새 부서를 선택해주세요",
+ "Close_menu": "메뉴 닫기",
+ "Conversation_finished": "대화 종료됨",
+ "End_chat": "채팅 끝남",
+ "How_friendly_was_the_chat_agent": "상담사가 친절했나요?",
+ "How_knowledgeable_was_the_chat_agent": "상담사의 관련 업무 지식이 충분했나요?",
+ "How_responsive_was_the_chat_agent": "삼담사가 빠르게 응답했나요?",
+ "How_satisfied_were_you_with_this_chat": "채팅 내용에 얼마나 만족 하였나요?",
+ "Installation": "설치",
+ "New_messages": "새 메시지",
+ "No": "아니오",
+ "Options": "옵션",
+ "Please_answer_survey": "이 채팅에 대한 간단한 설문 조사에 응답하기 위해 잠시 시간을내어 주시기 바랍니다",
+ "Please_choose_a_department": "부서를 선택해주세요",
+ "Please_fill_name_and_email": "이름과 이메일을 입력하세요",
+ "Powered_by": "지원을받는",
+ "Request_video_chat": "비디오채팅 요청",
+ "Select_a_department": "부서를 선택해주세요",
+ "Switch_department": "부서 변경",
+ "Department_switched": "부서가 변경되었습니다",
+ "Send": "전송",
+ "Skip": "건너뛰기",
+ "Start_Chat": "채팅 시작",
+ "Survey": "설문",
+ "Survey_instructions": "당신의 만족도를 평가해 주세요. 매우불만은 1, 매우 만족은 5 입니다.",
+ "Thank_you_for_your_feedback": "의견을 보내 주셔서 감사합니다",
+ "Thanks_We_ll_get_back_to_you_soon": "감사합니다! 곧 다시 연락드리겠습니다",
+ "transcript_sent": "채팅 내용을 발송했습니다",
+ "Type_your_email": "이메일을 입력해주세요",
+ "Type_your_message": "메시지를 입력해주세요",
+ "Type_your_name": "이름을 입력해주세요",
+ "User_joined": "사용자가 참여하였습니다",
+ "User_left": "사용자가 떠났습니다",
+ "We_are_offline_Sorry_for_the_inconvenience": "현재 오프라인 상태입니다. 불편을 드려 죄송합니다",
+ "Yes": "예",
+ "You": "당신",
+ "You_must_complete_all_fields": "모든 필드를 작성해야합니다"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ku.i18n.json b/packages/rocketchat-livechat/.app/i18n/ku.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ku.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ku.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/lo.i18n.json b/packages/rocketchat-livechat/.app/i18n/lo.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/lo.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/lo.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/lt.i18n.json b/packages/rocketchat-livechat/.app/i18n/lt.i18n.json
new file mode 100644
index 0000000000000..455f614975a19
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/lt.i18n.json
@@ -0,0 +1,10 @@
+{
+ "Additional_Feedback": "Papildomi Atsiliepimai",
+ "Appearance": "Išvaizda",
+ "Are_you_sure_do_you_want_end_this_chat": "Ar tikrai norite užbaigti pokalbį?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Ar tikrai norite užbaigti pokalbi ir pakeisti skyrių.",
+ "Cancel": "Atšaukti",
+ "Change": "Keisti",
+ "Chat_ended": "Pokalbis užbaigtas!",
+ "Choose_a_new_department": "Pasirinkite naują skyrių"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ms-MY.i18n.json b/packages/rocketchat-livechat/.app/i18n/ms-MY.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ms-MY.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ms-MY.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/nl.i18n.json b/packages/rocketchat-livechat/.app/i18n/nl.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/nl.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/nl.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/no.i18n.json b/packages/rocketchat-livechat/.app/i18n/no.i18n.json
new file mode 100644
index 0000000000000..539088fa6dc64
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/no.i18n.json
@@ -0,0 +1,29 @@
+{
+ "Additional_Feedback": "Tilleggs Tilbakemelding",
+ "Appearance": "Utseende",
+ "Are_you_sure_do_you_want_end_this_chat": "Er du sikker på at du vil avslutte denne samtalen?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Er du sikker på at du vil avslutte denne samtalen og bytte avdeling?",
+ "Cancel": "Avbryt",
+ "Change": "Endre",
+ "Chat_ended": "Samtalen er avsluttet!",
+ "Choose_a_new_department": "Velg ny avdeling",
+ "Close_menu": "Lukk meny",
+ "Conversation_finished": "Samtalen er avsluttet",
+ "End_chat": "Avslutt samtale",
+ "How_friendly_was_the_chat_agent": "Hvor vennlig var personen du pratet med?",
+ "How_responsive_was_the_chat_agent": "Hvor raskt svarte personen du pratet med?",
+ "How_satisfied_were_you_with_this_chat": "Er du fornøyd med samtalen?",
+ "Installation": "Installasjon",
+ "New_messages": "Ny melding",
+ "No": "Nei",
+ "Options": "Egenskaper",
+ "Send": "Send",
+ "Skip": "Hopp over",
+ "Start_Chat": "Start samtale",
+ "Survey": "Undersøkelse",
+ "Type_your_message": "Skriv inn din beskjed",
+ "Type_your_name": "Skriv inn ditt navn",
+ "Yes": "Ja",
+ "You": "Deg",
+ "You_must_complete_all_fields": "Du må fylle inn alle feltene"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/pl.i18n.json b/packages/rocketchat-livechat/.app/i18n/pl.i18n.json
similarity index 81%
rename from packages/rocketchat-livechat/app/i18n/pl.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/pl.i18n.json
index 63efe4084e688..2ecea65228ec5 100644
--- a/packages/rocketchat-livechat/app/i18n/pl.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/pl.i18n.json
@@ -1,9 +1,12 @@
{
- "Additional_Feedback": "dodatkowy komentarz",
+ "Additional_Feedback": "Dodatkowy Komentarz",
"Appearance": "Wygląd",
"Are_you_sure_do_you_want_end_this_chat": "Czy jesteś pewny że chcesz zakończyć rozmowę?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Czy jesteś pewny że chcesz zakończyć ten czat i zmienić departament?",
"Cancel": "Anuluj",
+ "Change": "Zmień",
"Chat_ended": "Rozmowa zakończona!",
+ "Choose_a_new_department": "Wybierz nowy departament",
"Close_menu": "Zamknij menu",
"Conversation_finished": "Rozmowa zakończona",
"End_chat": "Zakończ rozmowę",
@@ -16,10 +19,13 @@
"No": "Nie",
"Options": "Opcje",
"Please_answer_survey": "Proszę poświęć chwilę, aby odpowiedzieć na krótką ankietę na temat tej rozmowy",
+ "Please_choose_a_department": "Proszę wybierz departament",
"Please_fill_name_and_email": "Proszę wypełnić nazwisko i adres e-mail",
"Powered_by": "Dostarczane przez",
"Request_video_chat": "Zaproponuj rozmowę video",
"Select_a_department": "Wybierz oddział",
+ "Switch_department": "Zmień departament",
+ "Department_switched": "Zmieniono departament",
"Send": "Wyślij",
"Skip": "Pomiń",
"Start_Chat": "Rozpocznij czat",
diff --git a/packages/rocketchat-livechat/.app/i18n/pt-BR.i18n.json b/packages/rocketchat-livechat/.app/i18n/pt-BR.i18n.json
new file mode 100644
index 0000000000000..3092aaa20e3d9
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/pt-BR.i18n.json
@@ -0,0 +1,40 @@
+{
+ "Additional_Feedback": "Feedback Adicional",
+ "Appearance": "Aparência",
+ "Are_you_sure_do_you_want_end_this_chat": "Você tem certeza que deseja encerrar?",
+ "Cancel": "Cancelar",
+ "Chat_ended": "Chat encerrado!",
+ "Close_menu": "Fechar menu",
+ "Conversation_finished": "Chat encerrado",
+ "End_chat": "Encerrar chat",
+ "How_friendly_was_the_chat_agent": "Quão amigável foi o agente de bate-papo?",
+ "How_knowledgeable_was_the_chat_agent": "Quão bem informado foi o agente bate-papo?",
+ "How_responsive_was_the_chat_agent": "Quão responsivo foi o agente de bate-papo?",
+ "How_satisfied_were_you_with_this_chat": "Você ficou satisfeito com este bate-papo?",
+ "Installation": "Instalação",
+ "New_messages": "Novas mensagens",
+ "No": "Não",
+ "Options": "Opções",
+ "Please_answer_survey": "Por favor, nos dê um momento para responder uma rápida pesquisa sobre este chat",
+ "Please_fill_name_and_email": "Por favor, preencha nome e email",
+ "Powered_by": "Distribuído por",
+ "Request_video_chat": "Solicitar vídeoconferência",
+ "Select_a_department": "Selecione um departamento",
+ "Send": "Enviar",
+ "Skip": "Pular",
+ "Start_Chat": "Iniciar bate-papo",
+ "Survey": "Pesquisa",
+ "Survey_instructions": "Classifique cada questão de acordo com a sua satisfação, 1 significa que você está completamente insatisfeito e 5 significa que você está completamente satisfeito.",
+ "Thank_you_for_your_feedback": "Obrigado pelo seu feedback",
+ "Thanks_We_ll_get_back_to_you_soon": "Obrigado! Nós entraremos em contato com você em breve.",
+ "transcript_sent": "Transcrição enviada",
+ "Type_your_email": "Digite seu e-mail",
+ "Type_your_message": "Digite sua mensagem",
+ "Type_your_name": "Digite seu nome",
+ "User_joined": "Usuário entrou",
+ "User_left": "Usuário saiu",
+ "We_are_offline_Sorry_for_the_inconvenience": "Nós estamos offline. Desculpe pelo inconveniente.",
+ "Yes": "Sim",
+ "You": "Você",
+ "You_must_complete_all_fields": "Você deve preencher todos os campos"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/pt.i18n.json b/packages/rocketchat-livechat/.app/i18n/pt.i18n.json
similarity index 84%
rename from packages/rocketchat-livechat/app/i18n/pt.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/pt.i18n.json
index 0c533fac233c8..aade2c0e02147 100644
--- a/packages/rocketchat-livechat/app/i18n/pt.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/pt.i18n.json
@@ -2,8 +2,11 @@
"Additional_Feedback": "Feedback Adicional",
"Appearance": "Aparência",
"Are_you_sure_do_you_want_end_this_chat": "Você tem certeza que deseja encerrar?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Tem a certeza que deseja terminar este chat e mudar o departamento?",
"Cancel": "Cancelar",
+ "Change": "Alterar",
"Chat_ended": "Chat encerrado!",
+ "Choose_a_new_department": "Escolha um novo departamento",
"Close_menu": "Fechar menu",
"Conversation_finished": "Chat encerrado",
"End_chat": "Encerrar chat",
@@ -16,10 +19,13 @@
"No": "Não",
"Options": "Opções",
"Please_answer_survey": "Por favor nos dê um momento para responder uma rápida pesquisa sobre este chat",
+ "Please_choose_a_department": "Por favor escolha um departamento",
"Please_fill_name_and_email": "Por favor preencha nome e email",
"Powered_by": "Distribuído por",
"Request_video_chat": "Solicitar vídeoconferência",
"Select_a_department": "Selecione um departamento",
+ "Switch_department": "Mudar departamento",
+ "Department_switched": "Departamento alterado",
"Send": "Enviar",
"Skip": "Pular",
"Start_Chat": "Iniciar bate-papo",
diff --git a/packages/rocketchat-livechat/app/i18n/ro.i18n.json b/packages/rocketchat-livechat/.app/i18n/ro.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ro.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ro.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/ru.i18n.json b/packages/rocketchat-livechat/.app/i18n/ru.i18n.json
new file mode 100644
index 0000000000000..a4c38d477cf79
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/ru.i18n.json
@@ -0,0 +1,46 @@
+{
+ "Additional_Feedback": "Дополнительная обратная связь",
+ "Appearance": "Внешний вид",
+ "Are_you_sure_do_you_want_end_this_chat": "Вы уверены, что хотите завершить этот чат?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Вы действительно хотите завершить этот чат и сменить отдел?",
+ "Cancel": "Отмена",
+ "Change": "Изменить",
+ "Chat_ended": "Чат закончен!",
+ "Choose_a_new_department": "Выберите новый отдел",
+ "Close_menu": "Закрыть меню",
+ "Conversation_finished": "Беседа закончена",
+ "End_chat": "Закончить чат",
+ "How_friendly_was_the_chat_agent": "Насколько дружелюбен был сотрудник чата?",
+ "How_knowledgeable_was_the_chat_agent": "Насколько компетентен был сотрудник чата?",
+ "How_responsive_was_the_chat_agent": "Насколько отзывчив был сотрудник чата?",
+ "How_satisfied_were_you_with_this_chat": "Насколько Вы удовлетворены использованием этого чата?",
+ "Installation": "Установка",
+ "New_messages": "Новые сообщения",
+ "No": "Нет",
+ "Options": "Параметры",
+ "Please_answer_survey": "Пожалуйста, уделите время, чтобы ответить на несколько вопросов об этом чате",
+ "Please_choose_a_department": "Пожалуйста, выберете отдел",
+ "Please_fill_name_and_email": "Введите имя и адрес электронной почты",
+ "Powered_by": "Представлен",
+ "Request_video_chat": "Запрос чата с видео",
+ "Select_a_department": "Выберите отдел",
+ "Switch_department": "Сменить отдел",
+ "Department_switched": "Отдел сменён",
+ "Send": "Отправить",
+ "Skip": "Пропустить",
+ "Start_Chat": "Начать чат",
+ "Survey": "Опрос",
+ "Survey_instructions": "Оцените каждый вопрос по 5-балльной шкале, где 1 означает, что Вы совсем недовольны, и 5 - полностью довольны.",
+ "Thank_you_for_your_feedback": "Спасибо за Ваш отзыв",
+ "Thanks_We_ll_get_back_to_you_soon": "Спасибо! Мы свяжемся с вами в ближайшее время.",
+ "transcript_sent": "Переписка отправлена",
+ "Type_your_email": "Введите адрес электронной почты",
+ "Type_your_message": "Введите своё сообщение",
+ "Type_your_name": "Введите свое имя",
+ "User_joined": "Пользователь присоединился",
+ "User_left": "Пользователь вышел",
+ "We_are_offline_Sorry_for_the_inconvenience": "Мы не в сети. Извините за доставленные неудобства.",
+ "Yes": "Да",
+ "You": "Вы",
+ "You_must_complete_all_fields": "Вы должны заполнить все поля"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/sq.i18n.json b/packages/rocketchat-livechat/.app/i18n/sq.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/sq.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/sq.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/sr.i18n.json b/packages/rocketchat-livechat/.app/i18n/sr.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/sr.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/sr.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/sv.i18n.json b/packages/rocketchat-livechat/.app/i18n/sv.i18n.json
new file mode 100644
index 0000000000000..f3585ed320910
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/sv.i18n.json
@@ -0,0 +1,45 @@
+{
+ "Additional_Feedback": "Ytterligare Feedback",
+ "Appearance": "Utseende",
+ "Are_you_sure_do_you_want_end_this_chat": "Är du säker på att du vill avsluta denna chatt?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Är du säker på att du vill avsluta denna chatt och byta avdelning?",
+ "Cancel": "Avbryt",
+ "Change": "Ändra",
+ "Chat_ended": "Chatt avslutad!",
+ "Choose_a_new_department": "Välj en ny avdelning",
+ "Close_menu": "Stäng meny",
+ "Conversation_finished": "Konversation avslutad",
+ "End_chat": "Avsluta chatt",
+ "How_friendly_was_the_chat_agent": "Hur vänlig var chattagenten?",
+ "How_knowledgeable_was_the_chat_agent": "Hur kunnig var chattagenten?",
+ "How_responsive_was_the_chat_agent": "Hur mottaglig var chattagenten?",
+ "How_satisfied_were_you_with_this_chat": "Hur nöjd blev du med denna chatt?",
+ "Installation": "Installation",
+ "New_messages": "Nya meddelanden",
+ "No": "Nej",
+ "Options": "Inställningar",
+ "Please_answer_survey": "Vänligen ta en stund för att svara på en snabb enkät om chatten.",
+ "Please_choose_a_department": "Vänligen välj en avdelning",
+ "Please_fill_name_and_email": "Vänligen fyll i namn och e-postadress",
+ "Powered_by": "Drivs med hjälp av",
+ "Request_video_chat": "Begär videochatt",
+ "Select_a_department": "Välj en avdelning",
+ "Switch_department": "Byt avdelning",
+ "Send": "Skicka",
+ "Skip": "Hoppa över",
+ "Start_Chat": "Starta chatt",
+ "Survey": "Enkät",
+ "Survey_instructions": "Betygsätt varje fråga efter hur nöjd du är med svaret, 1 betyder att du inte alls är nöjd och 5 betyder att du är helt nöjd.\n",
+ "Thank_you_for_your_feedback": "Tack för din feedback",
+ "Thanks_We_ll_get_back_to_you_soon": "Tack! Vi återkommer till dig så snart vi kan.",
+ "transcript_sent": "Kopia är skickad",
+ "Type_your_email": "Skriv din e-post",
+ "Type_your_message": "Skriv in ditt meddelande",
+ "Type_your_name": "Skriv in ditt namn",
+ "User_joined": "Användare ansluter",
+ "User_left": "Användare lämnade",
+ "We_are_offline_Sorry_for_the_inconvenience": "Vi är offline. Vi beklagar olägenheten.",
+ "Yes": "Ja",
+ "You": "Du",
+ "You_must_complete_all_fields": "Du måste fylla i alla fält"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ta-IN.i18n.json b/packages/rocketchat-livechat/.app/i18n/ta-IN.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ta-IN.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ta-IN.i18n.json
diff --git a/packages/rocketchat-livechat/app/i18n/tr.i18n.json b/packages/rocketchat-livechat/.app/i18n/tr.i18n.json
similarity index 75%
rename from packages/rocketchat-livechat/app/i18n/tr.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/tr.i18n.json
index 8502da1199947..27c561623dc53 100644
--- a/packages/rocketchat-livechat/app/i18n/tr.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/tr.i18n.json
@@ -1,25 +1,31 @@
{
"Additional_Feedback": "Ek Geri Bildirim",
"Appearance": "Görünüm",
- "Are_you_sure_do_you_want_end_this_chat": "Bu sohbeti bitirmek istediğinize emin misiniz?",
+ "Are_you_sure_do_you_want_end_this_chat": "Bu sohbeti kapatmak istediğinize emin misiniz?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Bu sohbeti kapatıp bölüm değiştirmek istediğinize emin misiniz?",
"Cancel": "Vazgeç",
+ "Change": "Değiştir",
"Chat_ended": "Sohbet bitti!",
+ "Choose_a_new_department": "Yeni bölüm seç",
"Close_menu": "Menüyü Kapat",
"Conversation_finished": "Konuşma bitti",
"End_chat": "Sohbeti bitir",
"How_friendly_was_the_chat_agent": "Müşteri temsilcisi ne kadar dost canlısıydı?",
"How_knowledgeable_was_the_chat_agent": "Müşteri temsilcisi ne kadar bilgiliydi?",
- "How_responsive_was_the_chat_agent": "Müşteri temsilcisi ne kadar uyumluydu?",
+ "How_responsive_was_the_chat_agent": "Müşteri temsilcisi sorularınıza ne kadar cevap verdi?",
"How_satisfied_were_you_with_this_chat": "Bu sohbetten ne kadar memnun kaldınız?",
"Installation": "Kurulum",
"New_messages": "Yeni Mesajlar",
"No": "Hayır",
"Options": "Seçenekler",
"Please_answer_survey": "Lütfen bu sohbet hakkında hızlı bir anket yapmak için bir dakikanızı ayırın",
+ "Please_choose_a_department": "Lütfen bir bölüm seçin",
"Please_fill_name_and_email": "Lütfen isim ve e-posta alanlarını doldurunuz",
"Powered_by": "Tarafından Desteklenmektedir",
"Request_video_chat": "Görüntülü sohbet isteği gönder",
- "Select_a_department": "Bir bölüm seçin",
+ "Select_a_department": "Bölüm seç",
+ "Switch_department": "Bölüm değiştir",
+ "Department_switched": "Bölüm değiştirildi",
"Send": "Gönder",
"Skip": "Atla",
"Start_Chat": "Sohbete Başla",
diff --git a/packages/rocketchat-livechat/app/i18n/ug.i18n.json b/packages/rocketchat-livechat/.app/i18n/ug.i18n.json
similarity index 100%
rename from packages/rocketchat-livechat/app/i18n/ug.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/ug.i18n.json
diff --git a/packages/rocketchat-livechat/.app/i18n/uk.i18n.json b/packages/rocketchat-livechat/.app/i18n/uk.i18n.json
new file mode 100644
index 0000000000000..b6a37e53980a2
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/uk.i18n.json
@@ -0,0 +1,40 @@
+{
+ "Additional_Feedback": "Додатковий зворотній зв'язок",
+ "Appearance": "Зовнішній вигляд",
+ "Are_you_sure_do_you_want_end_this_chat": "Ви дійсно бажаєте закінчити чат? ",
+ "Cancel": "Скасувати",
+ "Chat_ended": "Чат закінчено!",
+ "Close_menu": "Закрити меню",
+ "Conversation_finished": "Розмову закінчено",
+ "End_chat": "Закінчити чат",
+ "How_friendly_was_the_chat_agent": "Чи дружній був співробітник?",
+ "How_knowledgeable_was_the_chat_agent": "Наскільки обізнаним був співробітник чату?",
+ "How_responsive_was_the_chat_agent": "Наскільки чуйний був співробітник чату?",
+ "How_satisfied_were_you_with_this_chat": "Наскільки ви задоволені використанням цього чату?",
+ "Installation": "Встановлення",
+ "New_messages": "Нові повідомлення",
+ "No": "Ні",
+ "Options": "Параметри",
+ "Please_answer_survey": "Будь ласка, знайдіть час, щоб відповісти на декілька питань щодо цього чату",
+ "Please_fill_name_and_email": "Заповніть, будь ласка, ім'я та адресу електронної пошти",
+ "Powered_by": "За підтримки",
+ "Request_video_chat": "Запит чату з відео",
+ "Select_a_department": "Виберіть відділ",
+ "Send": "Надіслати",
+ "Skip": "Пропустити",
+ "Start_Chat": "Розпочати чат",
+ "Survey": "Опитування",
+ "Survey_instructions": "Оцінити кожне питання відповідно до ваших задоволення, 1 означає, що ви повністю незадоволеним і 5 означає, що ви повністю задоволені.",
+ "Thank_you_for_your_feedback": "Спасибі за ваш відгук",
+ "Thanks_We_ll_get_back_to_you_soon": "Дякую! Ми зв'яжемося з вами найближчим часом.",
+ "transcript_sent": "Транскрипцію відправлено",
+ "Type_your_email": "Введіть адресу електронної пошти",
+ "Type_your_message": "текст повідомлення",
+ "Type_your_name": "Введіть ваше ім'я",
+ "User_joined": "Користувач приєднався",
+ "User_left": "Користувач вийшов",
+ "We_are_offline_Sorry_for_the_inconvenience": "Ми в автономному режимі. Вибачте за незручності.",
+ "Yes": "Так",
+ "You": "Ви",
+ "You_must_complete_all_fields": "Ви повинні заповнити всі поля"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/.app/i18n/zh-HK.i18n.json b/packages/rocketchat-livechat/.app/i18n/zh-HK.i18n.json
new file mode 100644
index 0000000000000..b1e15ecd28c05
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/i18n/zh-HK.i18n.json
@@ -0,0 +1,23 @@
+{
+ "Additional_Feedback": "其他意見",
+ "Appearance": "外觀",
+ "Cancel": "取消",
+ "Change": "變更",
+ "Chat_ended": "聊天已結束!",
+ "Close_menu": "關閉選單",
+ "Conversation_finished": "對話已結束",
+ "End_chat": "結束聊天",
+ "Installation": "安裝",
+ "New_messages": "新訊息",
+ "Options": "選項",
+ "Please_choose_a_department": "請選擇一個部門",
+ "Please_fill_name_and_email": "請輸入姓名及 Email",
+ "Powered_by": "Powered by",
+ "Request_video_chat": "請求視像通訊",
+ "Select_a_department": "選擇一個部門",
+ "Send": "傳送",
+ "Skip": "略過",
+ "Start_Chat": "开始聊天",
+ "Survey": "問卷",
+ "You_must_complete_all_fields": "您必須填寫所有欄位"
+}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/zh-TW.i18n.json b/packages/rocketchat-livechat/.app/i18n/zh-TW.i18n.json
similarity index 98%
rename from packages/rocketchat-livechat/app/i18n/zh-TW.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/zh-TW.i18n.json
index 19e4cac78d16a..8d34d993e4ba0 100644
--- a/packages/rocketchat-livechat/app/i18n/zh-TW.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/zh-TW.i18n.json
@@ -3,6 +3,7 @@
"Appearance": "外觀",
"Are_you_sure_do_you_want_end_this_chat": "你確定要結束聊天嗎?",
"Cancel": "取消",
+ "Change": "變更",
"Chat_ended": "聊天已結束!",
"Close_menu": "關閉選單",
"Conversation_finished": "對話已結束",
diff --git a/packages/rocketchat-livechat/app/i18n/zh.i18n.json b/packages/rocketchat-livechat/.app/i18n/zh.i18n.json
similarity index 78%
rename from packages/rocketchat-livechat/app/i18n/zh.i18n.json
rename to packages/rocketchat-livechat/.app/i18n/zh.i18n.json
index 72e63ec923461..ba7fcdc4a50bd 100644
--- a/packages/rocketchat-livechat/app/i18n/zh.i18n.json
+++ b/packages/rocketchat-livechat/.app/i18n/zh.i18n.json
@@ -1,9 +1,12 @@
{
"Additional_Feedback": "额外反馈",
"Appearance": "外观",
- "Are_you_sure_do_you_want_end_this_chat": "你确定你想要结束这个聊天?",
+ "Are_you_sure_do_you_want_end_this_chat": "你确定要结束这个聊天?",
+ "Are_you_sure_do_you_want_end_this_chat_and_switch_department": "你确定你要结束这个聊天并且切换部门?",
"Cancel": "取消",
+ "Change": "改变",
"Chat_ended": "对话已结束!",
+ "Choose_a_new_department": "选择一个新部门",
"Close_menu": "关闭菜单",
"Conversation_finished": "对话已结束",
"End_chat": "结束对话",
@@ -16,8 +19,10 @@
"No": "否",
"Options": "选项",
"Please_answer_survey": "请花几分钟来反馈这次交谈的体验",
+ "Please_choose_a_department": "请选择一个新部门",
"Please_fill_name_and_email": "请填写姓名和电子邮箱地址",
"Powered_by": "提供:",
+ "Request_video_chat": "请求视频聊天",
"Select_a_department": "请选择一个部门",
"Send": "发送",
"Skip": "跳过",
@@ -26,6 +31,7 @@
"Survey_instructions": "请根据您的满意程度给每个问题打分,1 代表非常不满意,5 代表非常满意。",
"Thank_you_for_your_feedback": "感谢您的反馈",
"Thanks_We_ll_get_back_to_you_soon": "谢谢!我们会尽快回复您。",
+ "transcript_sent": "录音发送",
"Type_your_email": "输入您的电子邮箱地址",
"Type_your_message": "输入您的留言",
"Type_your_name": "输入您的姓名",
@@ -33,5 +39,6 @@
"User_left": "用户已离开",
"We_are_offline_Sorry_for_the_inconvenience": "我们正处在离线状态。带来不便请您谅解。",
"Yes": "是",
+ "You": "你",
"You_must_complete_all_fields": "您必须填写所有字段"
}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/.app/imports/client/visitor.js b/packages/rocketchat-livechat/.app/imports/client/visitor.js
new file mode 100644
index 0000000000000..bb0613cb92e0e
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/imports/client/visitor.js
@@ -0,0 +1,99 @@
+/* globals Commands */
+const msgStream = new Meteor.Streamer('room-messages');
+
+export default {
+ id: new ReactiveVar(null),
+ token: new ReactiveVar(null),
+ room: new ReactiveVar(null),
+ data: new ReactiveVar(null),
+ roomToSubscribe: new ReactiveVar(null),
+ roomSubscribed: null,
+ connected: null,
+
+ register() {
+ if (!localStorage.getItem('visitorToken')) {
+ localStorage.setItem('visitorToken', Random.id());
+ }
+
+ this.token.set(localStorage.getItem('visitorToken'));
+ },
+
+ getId() {
+ return this.id.get();
+ },
+
+ setId(id) {
+ return this.id.set(id);
+ },
+
+ getData() {
+ return this.data.get();
+ },
+
+ setData(data) {
+ this.data.set(data);
+ },
+
+ getToken() {
+ return this.token.get();
+ },
+
+ setRoom(rid) {
+ this.room.set(rid);
+ },
+
+ getRoom(createOnEmpty = false) {
+ let roomId = this.room.get();
+ if (!roomId && createOnEmpty) {
+ roomId = Random.id();
+ this.room.set(roomId);
+ }
+
+ return roomId;
+ },
+
+ isSubscribed(roomId) {
+ return this.roomSubscribed === roomId;
+ },
+
+ subscribeToRoom(roomId) {
+ if (this.roomSubscribed && this.roomSubscribed === roomId) {
+ return;
+ }
+
+ this.roomSubscribed = roomId;
+
+ msgStream.on(roomId, { token: this.getToken() }, (msg) => {
+ if (msg.t === 'command') {
+ Commands[msg.msg] && Commands[msg.msg]();
+ } else if (msg.t !== 'livechat_video_call') {
+ ChatMessage.upsert({ _id: msg._id }, msg);
+
+ if (msg.t === 'livechat-close') {
+ parentCall('callback', 'chat-ended');
+ }
+
+ // notification sound
+ if (Session.equals('sound', true) && msg.u._id !== this.getId()) {
+ const audio = document.getElementById('chatAudioNotification');
+ audio.play();
+ }
+ }
+ });
+ },
+
+ setConnected() {
+ if (this.connected) {
+ return;
+ }
+ const token = this.getToken();
+
+ this.connected = true;
+ Meteor.call('UserPresence:connect', token, { visitor: token });
+
+ Meteor.startup(function() {
+ UserPresence.awayTime = 300000; // 5 minutes
+ UserPresence.start(token);
+ });
+ }
+};
diff --git a/packages/rocketchat-livechat/.app/package.json b/packages/rocketchat-livechat/.app/package.json
new file mode 100644
index 0000000000000..9b02fe8f32e5d
--- /dev/null
+++ b/packages/rocketchat-livechat/.app/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "rocketchat-livechat",
+ "version": "1.0.0",
+ "description": "Livechat app from Rocket.Chat",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": {
+ "name": "Rocket.Chat",
+ "url": "https://rocket.chat/"
+ },
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/RocketChat/Rocket.Chat.git"
+ },
+ "bugs": {
+ "url": "https://github.com/RocketChat/Rocket.Chat/issues",
+ "email": "support@rocket.chat"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.0.0-beta.40",
+ "autolinker": "^1.6.2",
+ "bcrypt": "^1.0.3",
+ "core-js": "^2.5.3",
+ "jquery": "^3.3.1",
+ "moment": "^2.20.1",
+ "toastr": "^2.1.4",
+ "underscore": "^1.8.3",
+ "underscore.string": "^3.3.4"
+ }
+}
diff --git a/packages/rocketchat-livechat/app/run.sh b/packages/rocketchat-livechat/.app/run.sh
similarity index 100%
rename from packages/rocketchat-livechat/app/run.sh
rename to packages/rocketchat-livechat/.app/run.sh
diff --git a/packages/rocketchat-livechat/app/.meteor/packages b/packages/rocketchat-livechat/app/.meteor/packages
deleted file mode 100644
index 766b44b83c902..0000000000000
--- a/packages/rocketchat-livechat/app/.meteor/packages
+++ /dev/null
@@ -1,43 +0,0 @@
-# Meteor packages used by this project, one per line.
-# Check this file (and the other files in this directory) into your repository.
-#
-# 'meteor add' and 'meteor remove' will edit this file for you,
-# but you can also edit it by hand.
-
-meteor@1.6.0
-webapp@1.3.12
-logging@1.1.16
-tracker@1.1.1
-deps@1.0.12
-session@1.1.7
-ddp@1.2.5
-livedata@1.0.18
-mongo@1.1.14
-blaze@2.1.8
-ui@1.0.11
-spacebars@1.0.12
-templating@1.2.14_1
-check@1.2.4
-underscore@1.0.10
-jquery@1.11.10
-random@1.0.10
-ejson@1.0.13
-coffeescript@1.11.1_4
-rocketchat:streamer
-kadira:flow-router
-kadira:blaze-layout
-konecty:nrr
-less@2.7.8
-underscorestring:underscore.string
-momentjs:moment
-mizzao:timesync
-reactive-var@1.0.11
-accounts-password@1.3.3
-tap:i18n
-# kevohagan:sweetalert
-smoral:sweetalert
-ecmascript@0.6.1
-es5-shim@4.6.15
-standard-minifier-css@1.3.2
-standard-minifier-js@1.2.1
-shell-server@0.2.1
diff --git a/packages/rocketchat-livechat/app/.meteor/release b/packages/rocketchat-livechat/app/.meteor/release
deleted file mode 100644
index 61f6c675b193f..0000000000000
--- a/packages/rocketchat-livechat/app/.meteor/release
+++ /dev/null
@@ -1 +0,0 @@
-METEOR@1.4.2.3
diff --git a/packages/rocketchat-livechat/app/.meteor/versions b/packages/rocketchat-livechat/app/.meteor/versions
deleted file mode 100644
index c79b27716db91..0000000000000
--- a/packages/rocketchat-livechat/app/.meteor/versions
+++ /dev/null
@@ -1,89 +0,0 @@
-accounts-base@1.2.14
-accounts-password@1.3.3
-aldeed:simple-schema@1.5.3
-allow-deny@1.0.5
-babel-compiler@6.13.0
-babel-runtime@1.0.1
-base64@1.0.10
-binary-heap@1.0.10
-blaze@2.3.0
-blaze-tools@1.0.10
-boilerplate-generator@1.0.11
-caching-compiler@1.1.9
-caching-html-compiler@1.1.0
-callback-hook@1.0.10
-cfs:http-methods@0.0.32
-check@1.2.4
-coffeescript@1.11.1_4
-ddp@1.2.5
-ddp-client@1.3.2
-ddp-common@1.2.8
-ddp-rate-limiter@1.0.6
-ddp-server@1.3.12
-deps@1.0.12
-diff-sequence@1.0.7
-ecmascript@0.6.1
-ecmascript-runtime@0.3.15
-ejson@1.0.13
-email@1.1.18
-es5-shim@4.6.15
-geojson-utils@1.0.10
-html-tools@1.0.11
-htmljs@1.0.11
-http@1.2.10
-id-map@1.0.9
-jquery@1.11.10
-kadira:blaze-layout@2.3.0
-kadira:flow-router@2.12.1
-konecty:nrr@2.0.2
-less@2.7.8
-livedata@1.0.18
-localstorage@1.0.12
-logging@1.1.16
-mdg:validation-error@0.5.1
-meteor@1.6.0
-meteorspark:util@0.2.0
-minifier-css@1.2.15
-minifier-js@1.2.15
-minimongo@1.0.19
-mizzao:timesync@0.4.0
-modules@0.7.7
-modules-runtime@0.7.8
-momentjs:moment@2.17.1
-mongo@1.1.14
-mongo-id@1.0.6
-npm-bcrypt@0.9.2
-npm-mongo@2.2.16_1
-observe-sequence@1.0.14
-ordered-dict@1.0.9
-promise@0.8.8
-raix:eventemitter@0.1.3
-random@1.0.10
-rate-limit@1.0.6
-reactive-dict@1.1.8
-reactive-var@1.0.11
-retry@1.0.9
-rocketchat:streamer@0.5.0
-routepolicy@1.0.12
-service-configuration@1.0.11
-session@1.1.7
-sha@1.0.9
-shell-server@0.2.1
-smoral:sweetalert@1.1.1
-spacebars@1.0.13
-spacebars-compiler@1.1.0
-srp@1.0.10
-standard-minifier-css@1.3.2
-standard-minifier-js@1.2.1
-tap:i18n@1.8.2
-templating@1.3.0
-templating-compiler@1.3.0
-templating-runtime@1.3.0
-templating-tools@1.1.0
-tracker@1.1.1
-ui@1.0.12
-underscore@1.0.10
-underscorestring:underscore.string@3.3.4
-url@1.0.11
-webapp@1.3.12
-webapp-hashing@1.0.9
diff --git a/packages/rocketchat-livechat/app/client/lib/CustomFields.js b/packages/rocketchat-livechat/app/client/lib/CustomFields.js
deleted file mode 100644
index af1b9fbce13f8..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/CustomFields.js
+++ /dev/null
@@ -1,32 +0,0 @@
-this.CustomFields = (function() {
- var queue = {};
- var initiated = false;
-
- var setCustomField = function(token, key, value) {
- if (!initiated) {
- // queue by key
- queue[key] = { token, value };
- return;
- }
- Meteor.call('livechat:setCustomField', token, key, value);
- };
-
- var init = function() {
- Tracker.autorun(function() {
- if (Meteor.userId()) {
- initiated = true;
- Object.keys(queue).forEach((key) => {
- setCustomField.call(this, queue[key].token, key, queue[key].value);
- });
- queue = {};
- } else {
- initiated = false;
- }
- });
- };
-
- return {
- init: init,
- setCustomField: setCustomField
- };
-}());
diff --git a/packages/rocketchat-livechat/app/client/lib/_visitor.coffee b/packages/rocketchat-livechat/app/client/lib/_visitor.coffee
deleted file mode 100644
index d3754eb0b5493..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/_visitor.coffee
+++ /dev/null
@@ -1,54 +0,0 @@
-msgStream = new Meteor.Streamer 'room-messages'
-
-@visitor = new class
- token = new ReactiveVar null
- room = new ReactiveVar null
- roomToSubscribe = new ReactiveVar null
- roomSubscribed = null
-
- register = ->
- if not localStorage.getItem 'visitorToken'
- localStorage.setItem 'visitorToken', Random.id()
-
- token.set localStorage.getItem 'visitorToken'
-
- getToken = ->
- return token.get()
-
- setRoom = (rid) ->
- room.set rid
-
- getRoom = (createOnEmpty = false) ->
- roomId = room.get()
- if not roomId? and createOnEmpty
- roomId = Random.id()
- room.set roomId
-
- return roomId
-
- isSubscribed = (roomId) ->
- return roomSubscribed is roomId
-
- subscribeToRoom = (roomId) ->
- if roomSubscribed?
- return if roomSubscribed is roomId
-
- roomSubscribed = roomId
-
- msgStream.on roomId, (msg) ->
- if msg.t is 'command'
- Commands[msg.msg]?()
- else if msg.t isnt 'livechat_video_call'
- ChatMessage.upsert { _id: msg._id }, msg
-
- # notification sound
- if Session.equals('sound', true)
- if msg.u._id isnt Meteor.user()._id
- $('#chatAudioNotification')[0].play();
-
- register: register
- getToken: getToken
- setRoom: setRoom
- getRoom: getRoom
- subscribeToRoom: subscribeToRoom
- isSubscribed: isSubscribed
diff --git a/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee b/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee
deleted file mode 100644
index 4b6eecccf0e35..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee
+++ /dev/null
@@ -1,218 +0,0 @@
-import toastr from 'toastr'
-class @ChatMessages
- init: (node) ->
- this.editing = {}
-
- # this.messageMaxSize = RocketChat.settings.get('Message_MaxAllowedSize')
- this.wrapper = $(node).find(".wrapper")
- this.input = $(node).find(".input-message").get(0)
- # this.bindEvents()
- return
-
- resize: ->
- dif = 60 + $(".messages-container").find("footer").outerHeight()
- $(".messages-box").css
- height: "calc(100% - #{dif}px)"
-
- toPrevMessage: ->
- msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
- if msgs.length
- if this.editing.element
- if msgs[this.editing.index - 1]
- this.edit msgs[this.editing.index - 1], this.editing.index - 1
- else
- this.edit msgs[msgs.length - 1], msgs.length - 1
-
- toNextMessage: ->
- if this.editing.element
- msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
- if msgs[this.editing.index + 1]
- this.edit msgs[this.editing.index + 1], this.editing.index + 1
- else
- this.clearEditing()
-
- getEditingIndex: (element) ->
- msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
- index = 0
- for msg in msgs
- if msg is element
- return index
- index++
- return -1
-
- edit: (element, index) ->
- return if element.classList.contains("system")
- this.clearEditing()
- id = element.getAttribute("id")
- message = ChatMessage.findOne { _id: id, 'u._id': Meteor.userId() }
- this.input.value = message.msg
- this.editing.element = element
- this.editing.index = index or this.getEditingIndex(element)
- this.editing.id = id
- element.classList.add("editing")
- this.input.classList.add("editing")
- setTimeout =>
- this.input.focus()
- , 5
-
- clearEditing: ->
- if this.editing.element
- this.editing.element.classList.remove("editing")
- this.input.classList.remove("editing")
- this.editing.id = null
- this.editing.element = null
- this.editing.index = null
- this.input.value = this.editing.saved or ""
- else
- this.editing.saved = this.input.value
-
- send: (rid, input) ->
- if s.trim(input.value) isnt ''
- if this.isMessageTooLong(input)
- return toastr.error t('Message_too_long')
- # KonchatNotification.removeRoomNotification(rid)
- msg = input.value
- input.value = ''
- rid ?= visitor.getRoom(true)
-
- sendMessage = (callback) ->
- msgObject = {
- _id: Random.id(),
- rid: rid,
- msg: msg,
- token: visitor.getToken()
- }
- MsgTyping.stop(rid)
-
- Meteor.call 'sendMessageLivechat', msgObject, (error, result) ->
- if error
- ChatMessage.update msgObject._id, { $set: { error: true } }
- showError error.reason
-
- if result?.rid? and not visitor.isSubscribed(result.rid)
- Livechat.connecting = result.showConnecting
- ChatMessage.update result._id, _.omit(result, '_id')
- Livechat.room = result.rid
-
- if not Meteor.userId()
- guest = {
- token: visitor.getToken()
- }
-
- if Livechat.department
- guest.department = Livechat.department
-
- Meteor.call 'livechat:registerGuest', guest, (error, result) ->
- if error?
- return showError error.reason
-
- Meteor.loginWithToken result.token, (error) ->
- if error
- return showError error.reason
-
- sendMessage()
- else
- sendMessage()
-
- deleteMsg: (message) ->
- Meteor.call 'deleteMessage', message, (error, result) ->
- if error
- return handleError(error)
-
- update: (id, rid, input) ->
- if s.trim(input.value) isnt ''
- msg = input.value
- Meteor.call 'updateMessage', { id: id, msg: msg }
- this.clearEditing()
- MsgTyping.stop(rid)
-
- startTyping: (rid, input) ->
- if s.trim(input.value) isnt ''
- MsgTyping.start(rid)
- else
- MsgTyping.stop(rid)
-
- bindEvents: ->
- if this.wrapper?.length
- $(".input-message").autogrow
- postGrowCallback: =>
- this.resize()
-
- tryCompletion: (input) ->
- value = input.value.match(/[^\s]+$/)
- if value?.length > 0
- value = value[0]
-
- re = new RegExp value, 'i'
-
- user = Meteor.users.findOne username: re
- if user?
- input.value = input.value.replace value, "@#{user.username} "
-
- keyup: (rid, event) ->
- input = event.currentTarget
- k = event.which
- keyCodes = [
- 13, # Enter
- 20, # Caps lock
- 16, # Shift
- 9, # Tab
- 27, # Escape Key
- 17, # Control Key
- 91, # Windows Command Key
- 19, # Pause Break
- 18, # Alt Key
- 93, # Right Click Point Key
- 45, # Insert Key
- 34, # Page Down
- 35, # Page Up
- 144, # Num Lock
- 145 # Scroll Lock
- ]
- keyCodes.push i for i in [35..40] # Home, End, Arrow Keys
- keyCodes.push i for i in [112..123] # F1 - F12
-
- unless k in keyCodes
- this.startTyping(rid, input)
-
- keydown: (rid, event) ->
- input = event.currentTarget
- k = event.which
- this.resize(input)
- if k is 13 and not event.shiftKey and not event.ctrlKey and not event.altKey # Enter without shift/ctrl/alt
- event.preventDefault()
- event.stopPropagation()
- if this.editing.id
- this.update(this.editing.id, rid, input)
- else
- this.send(rid, input)
- return
-
- if k is 9
- event.preventDefault()
- event.stopPropagation()
- @tryCompletion input
-
- if k is 27
- if this.editing.id
- event.preventDefault()
- event.stopPropagation()
- this.clearEditing()
- return
- # else if k is 38 or k is 40 # Arrow Up or down
- # if k is 38
- # return if input.value.slice(0, input.selectionStart).match(/[\n]/) isnt null
- # this.toPrevMessage()
- # else
- # return if input.value.slice(input.selectionEnd, input.value.length).match(/[\n]/) isnt null
- # this.toNextMessage()
-
- # event.preventDefault()
- # event.stopPropagation()
-
- # ctrl (command) + shift + k -> clear room messages
- else if k is 75 and ((navigator?.platform?.indexOf('Mac') isnt -1 and event.metaKey and event.shiftKey) or (navigator?.platform?.indexOf('Mac') is -1 and event.ctrlKey and event.shiftKey))
- RoomHistoryManager.clear rid
-
- isMessageTooLong: (input) ->
- input?.value.length > this.messageMaxSize
diff --git a/packages/rocketchat-livechat/app/client/lib/collections.coffee b/packages/rocketchat-livechat/app/client/lib/collections.coffee
deleted file mode 100644
index ea4c90291bd84..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/collections.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-@ChatMessage = new Meteor.Collection null
-@Department = new Meteor.Collection null
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/client/lib/commands.js b/packages/rocketchat-livechat/app/client/lib/commands.js
deleted file mode 100644
index 52d9b8801231e..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/commands.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* globals LivechatVideoCall, Livechat */
-// Functions to call on messages of type 'command'
-this.Commands = {
- survey: function() {
- if (!($('body #survey').length)) {
- Blaze.render(Template.survey, $('body').get(0));
- }
- },
-
- endCall: function() {
- LivechatVideoCall.finish();
- },
-
- promptTranscript: function() {
- if (Livechat.transcript) {
- const user = Meteor.user();
- let email = user.visitorEmails && user.visitorEmails.length > 0 ? user.visitorEmails[0].address : '';
-
- swal({
- title: t('Chat_ended'),
- text: Livechat.transcriptMessage,
- type: 'input',
- inputValue: email,
- showCancelButton: true,
- cancelButtonText: t('no'),
- confirmButtonText: t('yes'),
- closeOnCancel: true,
- closeOnConfirm: false
- }, (response) => {
- if ((typeof response === 'boolean') && !response) {
- return true;
- } else {
- if (!response) {
- swal.showInputError(t('please enter your email'));
- return false;
- }
- if (response.trim() === '') {
- swal.showInputError(t('please enter your email'));
- return false;
- } else {
- Meteor.call('livechat:sendTranscript', visitor.getRoom(), response, (err) => {
- if (err) {
- console.error(err);
- }
- swal({
- title: t('transcript_sent'),
- type: 'success',
- timer: 1000,
- showConfirmButton: false
- });
- });
- }
- }
- });
- } else {
- swal({
- title: t('Chat_ended'),
- type: 'success',
- timer: 1000,
- showConfirmButton: false
- });
- }
- },
-
- connected: function() {
- Livechat.connecting = false;
- }
-};
diff --git a/packages/rocketchat-livechat/app/client/lib/error.coffee b/packages/rocketchat-livechat/app/client/lib/error.coffee
deleted file mode 100644
index 0b3058978b731..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/error.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-@showError = (msg) ->
- $('.error').addClass('show').find('span').html(msg)
diff --git a/packages/rocketchat-livechat/app/client/lib/fromApp/Notifications.coffee b/packages/rocketchat-livechat/app/client/lib/fromApp/Notifications.coffee
deleted file mode 100644
index 9fd588378e23c..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/fromApp/Notifications.coffee
+++ /dev/null
@@ -1,45 +0,0 @@
-@Notifications = new class
- constructor: ->
- @debug = false
- @streamAll = new Meteor.Streamer 'notify-all'
- @streamRoom = new Meteor.Streamer 'notify-room'
- @streamUser = new Meteor.Streamer 'notify-user'
-
- if @debug is true
- @onAll -> console.log "RocketChat.Notifications: onAll", arguments
- @onUser -> console.log "RocketChat.Notifications: onAll", arguments
-
-
- notifyRoom: (room, eventName, args...) ->
- console.log "RocketChat.Notifications: notifyRoom", arguments if @debug is true
-
- args.unshift "#{room}/#{eventName}"
- @streamRoom.emit.apply @streamRoom, args
-
- notifyUser: (userId, eventName, args...) ->
- console.log "RocketChat.Notifications: notifyUser", arguments if @debug is true
-
- args.unshift "#{userId}/#{eventName}"
- @streamUser.emit.apply @streamUser, args
-
- onAll: (eventName, callback) ->
- @streamAll.on eventName, callback
-
- onRoom: (room, eventName, callback) ->
- if @debug is true
- @streamRoom.on room, -> console.log "RocketChat.Notifications: onRoom #{room}", arguments
-
- @streamRoom.on "#{room}/#{eventName}", callback
-
- onUser: (eventName, callback) ->
- @streamUser.on "#{Meteor.userId()}/#{eventName}", callback
-
-
- unAll: (callback) ->
- @streamAll.removeListener 'notify', callback
-
- unRoom: (room, eventName, callback) ->
- @streamRoom.removeListener "#{room}/#{eventName}", callback
-
- unUser: (callback) ->
- @streamUser.removeListener Meteor.userId(), callback
diff --git a/packages/rocketchat-livechat/app/client/lib/fromApp/RoomHistoryManager.coffee b/packages/rocketchat-livechat/app/client/lib/fromApp/RoomHistoryManager.coffee
deleted file mode 100644
index d21a2a296144c..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/fromApp/RoomHistoryManager.coffee
+++ /dev/null
@@ -1,70 +0,0 @@
-@RoomHistoryManager = new class
- defaultLimit = 50
-
- histories = {}
-
- getRoom = (rid) ->
- if not histories[rid]?
- histories[rid] =
- hasMore: ReactiveVar true
- isLoading: ReactiveVar false
- loaded: 0
-
- return histories[rid]
-
- getMore = (rid, limit=defaultLimit) ->
- room = getRoom rid
- if room.hasMore.curValue isnt true
- return
-
- room.isLoading.set true
-
- #$('.messages-box .wrapper').data('previous-height', $('.messages-box .wrapper').get(0)?.scrollHeight - $('.messages-box .wrapper').get(0)?.scrollTop)
- # ScrollListener.setLoader true
- lastMessage = ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
- # lastMessage ?= ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
-
- if lastMessage?
- ts = lastMessage.ts
- else
- ts = new Date
-
- Meteor.call 'loadHistory', rid, ts, limit, undefined, (err, result) ->
- return if err?
-
- for item in result?.messages or []
- if item.t isnt 'command'
- ChatMessage.upsert {_id: item._id}, item
- room.isLoading.set false
- room.loaded += result.messages.length
- if result.messages.length < limit
- room.hasMore.set false
-
- hasMore = (rid) ->
- room = getRoom rid
-
- return room.hasMore.get()
-
- getMoreIfIsEmpty = (rid) ->
- room = getRoom rid
-
- if room.loaded is 0
- getMore rid
-
- isLoading = (rid) ->
- room = getRoom rid
-
- return room.isLoading.get()
-
- clear = (rid) ->
- ChatMessage.remove({ rid: rid })
- if histories[rid]?
- histories[rid].hasMore.set true
- histories[rid].isLoading.set false
- histories[rid].loaded = 0
-
- getMore: getMore
- getMoreIfIsEmpty: getMoreIfIsEmpty
- hasMore: hasMore
- isLoading: isLoading
- clear: clear
diff --git a/packages/rocketchat-livechat/app/client/lib/fromApp/avatar.coffee b/packages/rocketchat-livechat/app/client/lib/fromApp/avatar.coffee
deleted file mode 100644
index 7988062501b20..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/fromApp/avatar.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-@getAvatarUrlFromUsername = (username) ->
- key = "avatar_random_#{username}"
- random = Session.keys[key] or 0
- if not username?
- return
-
- return "#{Meteor.absoluteUrl()}avatar/#{username}.jpg?_dc=#{random}"
-
-@updateAvatarOfUsername = (username) ->
- key = "avatar_random_#{username}"
- Session.set key, Math.round(Math.random() * 1000)
-
- for key, room of RoomManager.openedRooms
- url = getAvatarUrlFromUsername username
-
- $(room.dom).find(".message[data-username='#{username}'] .avatar-image").css('background-image', "url(#{url})");
-
- return true
diff --git a/packages/rocketchat-livechat/app/client/lib/hooks.js b/packages/rocketchat-livechat/app/client/lib/hooks.js
deleted file mode 100644
index 2739bed6f9fe4..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/hooks.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* globals CustomFields, Livechat */
-var api = {
- pageVisited: function(info) {
- if (info.change === 'url') {
- Triggers.processRequest(info);
- }
-
- Meteor.call('livechat:pageVisited', visitor.getToken(), info);
- },
-
- setCustomField: function(key, value) {
- CustomFields.setCustomField(visitor.getToken(), key, value);
- },
-
- setTheme: function(theme) {
- if (theme.color) {
- Livechat.customColor = theme.color;
- }
- if (theme.fontColor) {
- Livechat.customFontColor = theme.fontColor;
- }
- },
-
- setDepartment: function(department) {
- Livechat.department = department;
- },
-
- clearDepartment: function() {
- Livechat.department = null;
- },
-
- widgetOpened: function() {
- Livechat.setWidgetOpened();
- },
-
- widgetClosed: function() {
- Livechat.setWidgetClosed();
- }
-};
-
-window.addEventListener('message', function(msg) {
- if (typeof msg.data === 'object' && msg.data.src !== undefined && msg.data.src === 'rocketchat') {
- if (api[msg.data.fn] !== undefined && typeof api[msg.data.fn] === 'function') {
- var args = [].concat(msg.data.args || []);
- api[msg.data.fn].apply(null, args);
- }
- }
-}, false);
-
-// tell parent window that we are ready
-Meteor.startup(function() {
- Tracker.autorun((c) => {
- if (Livechat.isReady()) {
- parentCall('ready');
- c.stop();
- }
- });
-});
diff --git a/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee b/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee
deleted file mode 100644
index ac6bd5b72269e..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee
+++ /dev/null
@@ -1,69 +0,0 @@
-@MsgTyping = do ->
- timeout = 15000
- timeouts = {}
- renew = true
- renewTimeout = 10000
- selfTyping = new ReactiveVar false
- usersTyping = {}
- dep = new Tracker.Dependency
-
- addStream = (room) ->
- if _.isEmpty usersTyping[room]?.users
- usersTyping[room] = { users: {} }
- Notifications.onRoom room, 'typing', (username, typing) ->
- unless username is Meteor.user()?.username
- if typing is true
- users = usersTyping[room].users
- users[username] = Meteor.setTimeout ->
- delete users[username]
- usersTyping[room].users = users
- dep.changed()
- , timeout
- usersTyping[room].users = users
- dep.changed()
- else
- users = usersTyping[room].users
- delete users[username]
- usersTyping[room].users = users
- dep.changed()
-
- Tracker.autorun ->
- if visitor.getRoom() and Meteor.userId()
- addStream visitor.getRoom()
-
- start = (room) ->
- return unless renew
-
- setTimeout ->
- renew = true
- , renewTimeout
-
- renew = false
- selfTyping.set true
- Notifications.notifyRoom room, 'typing', Meteor.user()?.username, true
- clearTimeout timeouts[room]
- timeouts[room] = Meteor.setTimeout ->
- stop(room)
- , timeout
-
- stop = (room) ->
- renew = true
- selfTyping.set false
- if timeouts?[room]?
- clearTimeout(timeouts[room])
- timeouts[room] = null
- Notifications.notifyRoom room, 'typing', Meteor.user()?.username, false
-
- get = (room) ->
- dep.depend()
- unless usersTyping[room]
- usersTyping[room] = { users: {} }
- users = usersTyping[room].users
- return _.keys(users) or []
-
- return {
- start: start
- stop: stop
- get: get
- selfTyping: selfTyping
- }
diff --git a/packages/rocketchat-livechat/app/client/lib/parentCall.coffee b/packages/rocketchat-livechat/app/client/lib/parentCall.coffee
deleted file mode 100644
index e09e1103c95f3..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/parentCall.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-@parentCall = (method, args = []) ->
- data =
- src: 'rocketchat'
- fn: method
- args: args
-
- window.parent.postMessage data, '*'
diff --git a/packages/rocketchat-livechat/app/client/lib/tapi18n.coffee b/packages/rocketchat-livechat/app/client/lib/tapi18n.coffee
deleted file mode 100644
index 1cf705e3952ea..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/tapi18n.coffee
+++ /dev/null
@@ -1,15 +0,0 @@
-@t = (key, replaces...) ->
- if _.isObject replaces[0]
- return TAPi18n.__ key, replaces
- else
- return TAPi18n.__ key, { postProcess: 'sprintf', sprintf: replaces }
-
-@tr = (key, options, replaces...) ->
- if _.isObject replaces[0]
- return TAPi18n.__ key, options, replaces
- else
- return TAPi18n.__ key, options, { postProcess: 'sprintf', sprintf: replaces }
-
-@isRtl = (language) ->
- # https://en.wikipedia.org/wiki/Right-to-left#cite_note-2
- return language?.split('-').shift().toLowerCase() in ['ar', 'dv', 'fa', 'he', 'ku', 'ps', 'sd', 'ug', 'ur', 'yi']
diff --git a/packages/rocketchat-livechat/app/client/lib/triggers.js b/packages/rocketchat-livechat/app/client/lib/triggers.js
deleted file mode 100644
index 39f43afdd257c..0000000000000
--- a/packages/rocketchat-livechat/app/client/lib/triggers.js
+++ /dev/null
@@ -1,97 +0,0 @@
-this.Triggers = (function() {
- var triggers = [];
- var initiated = false;
- var requests = [];
- var enabled = true;
-
- var fire = function(trigger) {
- if (!enabled || Meteor.userId()) {
- return;
- }
- trigger.actions.forEach(function(action) {
- if (action.name === 'send-message') {
- // flag to skip the trigger if the action is 'send-message'
- trigger.skip = true;
-
- var roomId = visitor.getRoom();
-
- if (!roomId) {
- roomId = Random.id();
- visitor.setRoom(roomId);
- }
-
- Session.set('triggered', true);
- ChatMessage.insert({
- msg: action.params.msg,
- rid: roomId,
- u: {
- username: action.params.name
- }
- });
-
- parentCall('openWidget');
- }
- });
- };
-
- var processRequest = function(request) {
- if (!initiated) {
- return requests.push(request);
- }
- triggers.forEach(function(trigger) {
- if (trigger.skip) {
- return;
- }
- trigger.conditions.forEach(function(condition) {
- switch (condition.name) {
- case 'page-url':
- if (request.location.href.match(new RegExp(condition.value))) {
- fire(trigger);
- }
- break;
-
- case 'time-on-site':
- if (trigger.timeout) {
- clearTimeout(trigger.timeout);
- }
- trigger.timeout = setTimeout(function() {
- fire(trigger);
- }, parseInt(condition.value) * 1000);
- break;
- }
- });
- });
- };
-
- var setTriggers = function(newTriggers) {
- triggers = newTriggers;
- };
-
- var init = function() {
- initiated = true;
-
- if (requests.length > 0 && triggers.length > 0) {
- requests.forEach(function(request) {
- processRequest(request);
- });
-
- requests = [];
- }
- };
-
- var setDisabled = function() {
- enabled = false;
- };
-
- var setEnabled = function() {
- enabled = true;
- };
-
- return {
- init: init,
- processRequest: processRequest,
- setTriggers: setTriggers,
- setDisabled: setDisabled,
- setEnabled: setEnabled
- };
-}());
diff --git a/packages/rocketchat-livechat/app/client/methods/sendMessageExternal.coffee b/packages/rocketchat-livechat/app/client/methods/sendMessageExternal.coffee
deleted file mode 100644
index 24e493f8913ca..0000000000000
--- a/packages/rocketchat-livechat/app/client/methods/sendMessageExternal.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-Meteor.methods
- sendMessageLivechat: (message) ->
- if s.trim(message.msg) isnt ''
-
- if isNaN(TimeSync.serverOffset())
- message.ts = new Date()
- else
- message.ts = new Date(Date.now() + TimeSync.serverOffset())
-
- message.u =
- _id: Meteor.userId()
- username: Meteor.user()?.username || 'visitor'
-
- message.temp = true
-
- # message = RocketChat.callbacks.run 'beforeSaveMessage', message
-
- ChatMessage.insert message
diff --git a/packages/rocketchat-livechat/app/client/routes/router.coffee b/packages/rocketchat-livechat/app/client/routes/router.coffee
deleted file mode 100644
index 6b1712849214f..0000000000000
--- a/packages/rocketchat-livechat/app/client/routes/router.coffee
+++ /dev/null
@@ -1,12 +0,0 @@
-BlazeLayout.setRoot('body');
-
-FlowRouter.route '/livechat',
- name: 'index'
-
- triggersEnter: [
- ->
- visitor.register()
- ]
-
- action: ->
- BlazeLayout.render 'main', {center: 'livechatWindow'}
diff --git a/packages/rocketchat-livechat/app/client/startup/visitor.coffee b/packages/rocketchat-livechat/app/client/startup/visitor.coffee
deleted file mode 100644
index ddacd7c4134a3..0000000000000
--- a/packages/rocketchat-livechat/app/client/startup/visitor.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
-@visitorId = new ReactiveVar null
-
-Meteor.startup ->
- if not localStorage.getItem('rocketChatLivechat')?
- localStorage.setItem('rocketChatLivechat', Random.id())
- else
- Tracker.autorun (c) ->
- if not Meteor.userId() and visitor.getToken()
- Meteor.call 'livechat:loginByToken', visitor.getToken(), (err, result) ->
- if result?.token
- Meteor.loginWithToken result.token, (err, result) ->
- c.stop()
-
- visitorId.set localStorage.getItem('rocketChatLivechat')
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/main.less b/packages/rocketchat-livechat/app/client/stylesheets/main.less
deleted file mode 100644
index a92b5a0a4e029..0000000000000
--- a/packages/rocketchat-livechat/app/client/stylesheets/main.less
+++ /dev/null
@@ -1,867 +0,0 @@
-@import "utils/_reset.import.less";
-@import "utils/_lesshat.import.less";
-@import "utils/_variables.import.less";
-@import "utils/_keyframes.import.less";
-@import "utils/_loading.import.less";
-
-* {
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
-}
-
-html,
-body {
- height: 100%;
-}
-
-body {
- margin: 0;
- font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI";
- font-size: 0.8rem;
- color: @primary-font-color;
- height: 100%;
- width: 100%;
- -webkit-font-smoothing: antialiased;
- line-height: 1rem;
- padding: 0;
- overflow: hidden;
- position: relative;
- border-top-right-radius: 5px;
- border-top-left-radius: 5px;
-}
-
-input,
-select,
-textarea {
- font-family: inherit;
- font-size: inherit;
- line-height: inherit;
- padding: 5px;
- margin: 5px 0;
- border: 1px solid #e7e7e7;
- border-radius: 5px;
- outline: none;
-}
-
-button {
- background: none;
- border: none;
- padding: 0;
- text-align: left;
- cursor: pointer;
- text-transform: inherit;
- color: inherit;
- font-style: inherit;
-}
-
-input:focus {
- outline: none;
- box-shadow: 0 0 0;
-}
-
-.button {
- &:extend(.unselectable);
- display: inline-block;
- padding: 9px 12px;
- font-weight: 500;
- font-size: 13px;
- margin: 4px;
- text-transform: uppercase;
- word-spacing: 0;
- box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.125);
- border: none;
- border-radius: 0;
- line-height: 16px;
- position: relative;
- cursor: pointer;
- color: rgba(255, 255, 255, 0.85);
- background-color: lighten(desaturate(@primary-background-color, 15%), 12.5%);
-
- span {
- position: relative;
- z-index: 2;
- }
-
- &::before {
- background-color: rgba(0, 0, 0, 0.1);
- content: " ";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- opacity: 0;
- z-index: 1;
- transition: opacity 0.1s ease-out;
- }
-
- &:hover {
- text-decoration: none;
- color: #ffffff;
-
- &::before {
- opacity: 1;
- }
- }
-
- &.secondary {
- background-color: @tertiary-background-color;
- color: @primary-font-color;
-
- &::before {
- background-color: rgba(0, 0, 0, 0.045);
- }
- }
-
- &.clean {
- font-size: 14px;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.08);
-
- &.primary {
- font-weight: 600;
- }
- }
-
- &.button-block {
- display: block;
- width: 100%;
- }
-}
-
-.field-error {
- border: 1px solid red;
-}
-
-.livechat-room {
- display: flex;
- flex-direction: column;
- height: 100%;
- border-top-right-radius: inherit;
- border-top-left-radius: inherit;
-
- &.popout {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-
- .title {
- cursor: default;
- }
- }
-
- .title {
- flex: 1 0 @header-min-height;
- line-height: @header-min-height;
- border-top-right-radius: inherit;
- border-top-left-radius: inherit;
- color: #ffffff;
- z-index: 10;
- cursor: pointer;
- padding: 0 10px;
-
- h1 {
- margin: 0;
- font-size: 10pt;
- display: inline-block;
- }
-
- .toolbar {
- display: inline-block;
- float: right;
-
- svg {
- cursor: pointer;
- fill: currentColor;
- width: 14px;
- margin: 0 5px;
- vertical-align: middle;
-
- &:last-of-type {
- margin-right: 0;
- }
- }
- }
- }
-
- .header {
- flex: 1 0 60px;
- display: flex;
- box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2);
- background-color: #fcfcfc;
- color: @secondary-font-color;
- z-index: 2;
-
- .picture {
- flex: 0 1 60px;
- padding: 5px 10px;
-
- img {
- width: 50px;
- height: 50px;
- border-radius: 6px;
- border: 1px solid @window-border-color;
- }
- }
-
- .info {
- flex: 1;
- padding: 5px 0;
-
- h2 {
- color: @primary-font-color;
- font-size: 14px;
- }
-
- li {
- font-size: 11px;
- }
- }
- }
-
- .messages {
- flex: 1 1 100%;
- background-color: #ffffff;
- border-left: 1px solid @window-border-color;
- border-right: 1px solid @window-border-color;
- overflow-y: auto;
-
- .wrapper {
- padding-bottom: 6px;
-
- ul {
- list-style-type: none;
- padding: 0;
-
- li {
- padding: 0;
- }
- }
-
- .message {
- font-size: 12px;
- padding: 8px 10px 0;
- position: relative;
- line-height: 18px;
- min-height: 36px;
-
- &::after {
- content: '';
- display: block;
- clear: both;
- }
-
- .content {
- width: 75%;
- background-color: #f3f3f3;
- border: 1px solid desaturate(darken(#f3f3f3, 10%), 40%);
- margin-left: 38px;
- border-radius: 6px;
- padding: 5px;
- float: left;
-
- &::before {
- border-style: solid;
- border-color: transparent desaturate(darken(#f3f3f3, 10%), 40%) transparent transparent;
- content: " ";
- height: 0;
- width: 0;
- font-size: 0;
- pointer-events: none;
- border-width: 5px;
- position: absolute;
- left: 38px;
- }
- }
-
- &:nth-child(1) {
- margin-top: 0;
- }
-
- &.new-day {
- margin-top: 60px;
-
- &::before {
- content: attr(data-date);
- display: block;
- position: absolute;
- top: -30px;
- left: 0;
- font-size: 10px;
- font-weight: 600;
- text-align: center;
- .calc(left, ~'50% - 70px');
- color: @secondary-font-color;
- z-index: 1;
- padding: 0 10px;
- background-color: #ffffff;
- min-width: 120px;
- }
-
- .content {
- &::after {
- content: " ";
- display: block;
- position: absolute;
- top: -20px;
- left: 0;
- width: 100%;
- border-top: 1px solid #dddddd;
- }
- }
- }
-
- .edit-message {
- display: none;
- cursor: pointer;
- }
-
- &.own {
- .content {
- background-color: #feffd7;
- border: 1px solid desaturate(darken(#feffd7, 10%), 40%);
- float: right;
- margin-right: 3px;
-
- &::before {
- border-style: solid;
- border-color: transparent transparent transparent desaturate(darken(#feffd7, 10%), 40%);
- content: " ";
- height: 0;
- width: 0;
- font-size: 0;
- pointer-events: none;
- border-width: 5px;
- position: absolute;
- right: 3px;
- left: inherit;
- }
- }
- }
-
- .delete-message {
- display: none;
- cursor: pointer;
- }
-
- .user {
- display: inline-block;
- font-weight: 600;
- color: #444444;
- margin-right: 5px;
- outline: none;
-
- &:hover {
- color: #333333;
- }
- }
-
- .thumb {
- position: absolute;
- left: 10px;
- top: 6px;
- display: block;
- width: 30px;
- height: 30px;
- }
-
- .info {
- color: @info-font-color;
- display: inline-block;
- float: right;
- margin: 9px -1px -5px 9px;
- font-size: 9px;
- text-align: right;
- left: -10px;
- width: 55px;
-
- .edited {
- display: inline-block;
- }
-
- .edit-message {
- float: left;
- margin-left: 1px;
- }
-
- .delete-message {
- float: left;
- }
- }
-
- &.sequential {
- padding-top: 2px;
- min-height: 20px;
-
- .user {
- display: none;
- }
-
- .thumb {
- display: none;
- }
- }
-
- &.system {
- .body {
- color: @info-font-color;
- font-style: italic;
-
- em {
- font-weight: 600;
- }
- }
- }
-
- .avatar-initials {
- line-height: 40px;
- }
-
- a {
- color: @link-font-color;
- font-weight: 400;
-
- &:hover {
- color: darken(@link-font-color, 10%);
- text-decoration: underline;
- }
- }
-
- .body {
- opacity: 1;
- transition: opacity 1s linear;
- }
-
- &.temp .body {
- opacity: 0.5;
- }
-
- &.msg-error .body {
- text-decoration: line-through;
- }
-
- .avatar .avatar-image {
- height: 100%;
- width: 100%;
- min-height: 20px;
- min-width: 20px;
- display: block;
- position: relative;
- background-color: transparent;
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center;
- border-radius: 4px;
- }
- }
- }
-
- .new-message {
- margin: 0 -65px;
- position: absolute;
- background: #428bca;
- border-radius: 20px;
- width: 130px;
- height: 30px;
- text-align: center;
- color: #ffffff;
- line-height: 30px;
- font-size: 0.8em;
- cursor: pointer;
- bottom: 8px;
- left: 50%;
- z-index: 5;
- transition: transform 0.3s ease-out;
- .transform(translateY(-40px));
-
- &.not {
- .transform(translateY(100%));
- }
- }
-
- .error {
- bottom: @footer-min-height;
- position: fixed;
- width: 100%;
- background-color: #f7d799;
- padding: 5px;
- z-index: 8;
- transition: transform 0.2s ease-out;
- .transform(translateY(100%));
-
- &.show {
- .transform(translateY(0));
- }
- }
- }
-
- .footer {
- flex: 1 0 @footer-min-height;
- z-index: 10;
- background-color: #fcfcfc;
- border-top: 1px solid @window-border-color;
- border-left: 1px solid @window-border-color;
- border-right: 1px solid @window-border-color;
-
- .message-bar {
- display: flex;
- flex-direction: row;
- padding-top: 6px;
-
- .input-wrapper {
- flex-grow: 1;
- padding-left: 6px;
-
- textarea {
- display: block;
- padding: 6px 8px;
- padding-right: 38px;
- overflow-y: auto;
- resize: none;
- margin: 0;
- max-height: 200px;
- width: 100%;
- font-size: 12px;
- -webkit-appearance: none;
- height: 28px;
- line-height: normal;
- background-color: #ffffff;
- position: relative;
- }
- }
-
- .buttons {
- color: @secondary-font-color;
- fill: @secondary-font-color;
- display: flex;
- align-items: center;
- padding: 0 5px;
-
- svg {
- width: 15px;
- height: 15px;
- margin: 0 4px;
- cursor: pointer;
- transition: fill 0.15s ease-out;
-
- &:hover {
- fill: @primary-font-color;
- }
- }
- }
- }
-
- .toggle-options {
- clear: both;
- color: @secondary-font-color;
- margin-left: 6px;
- outline: none;
- margin-top: 5px;
- font-size: 0.65rem;
- }
-
- .typing {
- clear: both;
- color: @secondary-font-color;
- margin-left: 8px;
- outline: none;
- margin-top: 2px;
- font-size: 0.65rem;
- }
-
- .options-menu {
- min-width: 100px;
- bottom: 21px;
- left: 6px;
- border-radius: 2px;
- padding: 6px 0;
- background-color: #ffffff;
- color: @secondary-font-color;
- box-shadow:
- 0 1px 1px 0 rgba(0, 0, 0, 0.2),
- 0 2px 10px 0 rgba(0, 0, 0, 0.16);
- position: absolute;
- z-index: 200;
- transition: transform 0.15s ease, visibility 0.15s ease, opacity 0.15s ease;
- .transform(translateY(30px));
- opacity: 0;
- visibility: hidden;
-
- &.show {
- .transform(translateY(0px));
- opacity: 1;
- display: block;
- visibility: visible;
- }
-
- ul {
- li {
- padding: 0 13px 0 8px;
-
- &:hover {
- background-color: #eeeeee;
- }
-
- button {
- display: block;
- padding: 4px 2px;
- outline: none;
- }
- }
- }
- }
- }
-
- .offline {
- flex: 1 1 100%;
- background-color: white;
- padding: 1em 10px;
- border-left: 1px solid @window-border-color;
- border-right: 1px solid @window-border-color;
-
- .offline-message {
- padding: 1em 0;
- }
-
- .message-sent {
- text-align: center;
- }
-
- form {
- input,
- textarea {
- display: block;
- width: 100%;
- }
-
- .buttons {
- text-align: center;
- }
-
- .error {
- display: none;
- background-color: #f7d799;
- padding: 5px;
-
- &.show {
- display: block;
- }
- }
- }
- }
-}
-
-.livechat-form {
- flex: 1 1 100%;
- display: block;
- background-color: #ffffff;
- border-left: 1px solid @window-border-color;
- border-right: 1px solid @window-border-color;
- padding: 5px;
-
- input,
- select {
- display: block;
- background-color: #ffffff;
- }
-
- .error {
- display: none;
- background-color: #f7d799;
- padding: 5px;
-
- &.show {
- display: block;
- }
- }
-
- form {
- padding: 0 1em;
- text-align: center;
-
- input,
- select {
- width: 100%;
- }
- }
-}
-
-.modal {
- border-top-right-radius: inherit;
- border-top-left-radius: inherit;
-
- .overlay {
- border-top-right-radius: inherit;
- border-top-left-radius: inherit;
- background-color: rgba(0, 0, 0, 0.5);
- position: fixed;
- height: 100%;
- width: 100%;
- z-index: 9990;
- top: 0;
- left: 0;
- }
-
- .wrapper {
- z-index: 9999;
- background: white;
- position: fixed;
- height: 80%;
- width: 80%;
- top: 15%;
- left: 10%;
- border-radius: 6px;
- display: flex;
- flex-direction: column;
-
- header {
- flex: 1 0 40px;
- padding: 0 15px;
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
- line-height: 40px;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- }
-
- .content {
- overflow-y: auto;
- padding: 10px;
- flex: 1 1 100%;
-
- .instructions {
- margin-top: 5px;
- }
-
- .survey-item {
- margin-top: 20px;
-
- .question {
- display: block;
- }
-
- .answer {
- margin-right: 5px;
- display: inline-block;
- text-align: center;
- }
- }
- }
-
- footer {
- flex: 1 0 60px;
- border-top: 1px solid rgba(0, 0, 0, 0.1);
- line-height: 60px;
- text-align: right;
- padding-right: 20px;
- }
- }
-}
-
-.powered-by {
- margin-top: -20px;
- line-height: 20px;
- right: 0;
- z-index: 10;
- text-align: right;
- font-size: 0.65rem;
- height: 20px;
- color: #666666;
- padding: 0 1em;
- opacity: 0.5;
- align-self: flex-end;
- transition: opacity 0.15s ease-out;
-
- &:hover {
- opacity: 1;
- }
-
- a {
- text-decoration: none;
- margin-left: 1px;
-
- img {
- height: 14px;
- vertical-align: middle;
- }
- }
-}
-
-.sweet-overlay {
- border-top-right-radius: inherit;
- border-top-left-radius: inherit;
-}
-
-.video-call {
- position: fixed;
- top: @header-min-height;
- bottom: 0;
- left: 0;
- right: 0;
- background-color: #000000;
- z-index: 11;
-
- .video-overlay {
- position: fixed;
- top: @header-min-height;
- bottom: 0;
- left: 0;
- right: 0;
- z-index: 13;
-
- .toolbar {
- position: absolute;
- bottom: 40px;
- width: 100%;
- text-align: center;
- opacity: 0;
- visibility: hidden;
- .transform(translateY(50px));
- transition: opacity 0.175s ease-out, transform 0.175s ease-out, visibility 0.175s ease-out;
-
- &.visible {
- opacity: 1;
- visibility: visible;
- .transform(translateY(0px));
- }
-
- .end-call {
- background-color: red;
- fill: white;
- border-radius: 50%;
- height: 60px;
- width: 60px;
- text-align: center;
- outline: none;
-
- svg {
- width: 30px;
- height: 30px;
- }
- }
- }
- }
-
- .container {
- z-index: 12;
- }
-}
-
-@media all and(max-height: 200px) {
- .livechat-room {
- .title {
- height: 100%;
- }
-
- .footer {
- display: none;
- }
-
- .messages {
- display: none;
- }
-
- .powered-by {
- display: none;
- }
- }
-}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less
deleted file mode 100644
index 0979dd5275e4c..0000000000000
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less
+++ /dev/null
@@ -1,85 +0,0 @@
-// lesshat - The best mixin library in the world
-//
-// version: v4.1.0 (2016-07-19)
-
-.animation(...) {
- @process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-animation: @process;
- -moz-animation: @process;
- -o-animation: @process;
- animation: @process;
-}
-
-.box-sizing(...) {
- @process: ~`(function(n){return n=n||"content-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-box-sizing: @process;
- -moz-box-sizing: @process;
- box-sizing: @process;
-}
-
-.calc(...) {
- @process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- @state: 1; -lh-property: @process;
-}
-
-.transform(...) {
- @process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: @process;
- -moz-transform: @process;
- -ms-transform: @process;
- -o-transform: @process;
- transform: @process;
-}
-
-.transform-origin(...) {
- @process: ~`(function(e){e=e||"50% 50% 0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"%"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform-origin: @process;
- -moz-transform-origin: @process;
- -ms-transform-origin: @process;
- -o-transform-origin: @process;
- transform-origin: @process;
-}
-
-.transform-style(...) {
- @process: ~`(function(n){return n=n||"flat"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform-style: @process;
- -moz-transform-style: @process;
- -ms-transform-style: @process;
- -o-transform-style: @process;
- transform-style: @process;
-}
-
-.translate(...) {
- @process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: translate(@process);
- -moz-transform: translate(@process);
- -ms-transform: translate(@process);
- -o-transform: translate(@process);
- transform: translate(@process);
-}
-
-.translateX(...) {
- @process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: translateX(@process);
- -moz-transform: translateX(@process);
- -ms-transform: translateX(@process);
- -o-transform: translateX(@process);
- transform: translateX(@process);
-}
-
-.translateY(...) {
- @process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: translateY(@process);
- -moz-transform: translateY(@process);
- -ms-transform: translateY(@process);
- -o-transform: translateY(@process);
- transform: translateY(@process);
-}
-
-.user-select(...) {
- @process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-user-select: @process;
- -moz-user-select: @process;
- -ms-user-select: @process;
- user-select: @process;
-}
diff --git a/packages/rocketchat-livechat/app/client/views/avatar.coffee b/packages/rocketchat-livechat/app/client/views/avatar.coffee
deleted file mode 100644
index 5e2e62ab9ef3d..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/avatar.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
-Template.avatar.helpers
- imageUrl: ->
- username = this.username
- if not username? and this.userId?
- username = Meteor.users.findOne(this.userId)?.username
-
- if not username? or Meteor.user()?.username is username
- return
-
- Session.get "avatar_random_#{username}"
-
- url = getAvatarUrlFromUsername(username)
-
- return "background-image:url(#{url});"
diff --git a/packages/rocketchat-livechat/app/client/views/livechatWindow.html b/packages/rocketchat-livechat/app/client/views/livechatWindow.html
deleted file mode 100644
index f84029593a03a..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/livechatWindow.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
- {{#if livechatStarted}}
-
-
- {{#if livechatOnline}}
- {{#if showRegisterForm}}
- {{> register}}
- {{else}}
- {{> messages}}
- {{/if}}
- {{else}}
-
- {{> offlineForm (offlineData)}}
-
- {{/if}}
- {{> poweredBy }}
-
- {{/if}}
- {{#if videoCalling}}
- {{> videoCall}}
- {{/if}}
-
diff --git a/packages/rocketchat-livechat/app/client/views/main.html b/packages/rocketchat-livechat/app/client/views/main.html
deleted file mode 100644
index fa39318af8be3..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/main.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
- Rocket.Chat
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{> Template.dynamic template=center}}
-
diff --git a/packages/rocketchat-livechat/app/client/views/message.coffee b/packages/rocketchat-livechat/app/client/views/message.coffee
deleted file mode 100644
index ebe1b3b017a57..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/message.coffee
+++ /dev/null
@@ -1,86 +0,0 @@
-import moment from 'moment'
-
-Template.message.helpers
- own: ->
- return 'own' if this.u?._id is Meteor.userId()
-
- time: ->
- return moment(this.ts).format('LT')
-
- date: ->
- return moment(this.ts).format('LL')
-
- isTemp: ->
- if @temp is true
- return 'temp'
- return
-
- error: ->
- return 'msg-error' if @error
-
- body: ->
- switch this.t
- when 'r' then t('Room_name_changed', { room_name: this.msg, user_by: this.u.username })
- when 'au' then t('User_added_by', { user_added: this.msg, user_by: this.u.username })
- when 'ru' then t('User_removed_by', { user_removed: this.msg, user_by: this.u.username })
- when 'ul' then tr('User_left', { context: this.u.gender }, { user_left: this.u.username })
- when 'uj' then tr('User_joined', { context: this.u.gender }, { user: this.u.username })
- when 'wm' then t('Welcome', { user: this.u.username })
- when 'livechat-close' then t('Conversation_finished')
- # when 'rtc' then RocketChat.callbacks.run 'renderRtcMessage', this
- else
- this.html = this.msg
- if s.trim(this.html) isnt ''
- this.html = s.escapeHTML this.html
- # message = RocketChat.callbacks.run 'renderMessage', this
- message = this
- this.html = message.html.replace /\n/gm, ' '
- return livechatAutolinker.link this.html
-
- system: ->
- return 'system' if this.t in ['s', 'p', 'f', 'r', 'au', 'ru', 'ul', 'wm', 'uj', 'livechat-close']
-
- sender: ->
- agent = Livechat.agent
- if agent && @u.username is agent.username
- return agent.name or agent.username
- return @u.username
-
-
-Template.message.onViewRendered = (context) ->
- view = this
- this._domrange.onAttached (domRange) ->
- lastNode = domRange.lastNode()
- if lastNode.previousElementSibling?.dataset?.date isnt lastNode.dataset.date
- $(lastNode).addClass('new-day')
- $(lastNode).removeClass('sequential')
- else if lastNode.previousElementSibling?.dataset?.username isnt lastNode.dataset.username
- $(lastNode).removeClass('sequential')
-
- if lastNode.nextElementSibling?.dataset?.date is lastNode.dataset.date
- $(lastNode.nextElementSibling).removeClass('new-day')
- $(lastNode.nextElementSibling).addClass('sequential')
- else
- $(lastNode.nextElementSibling).addClass('new-day')
- $(lastNode.nextElementSibling).removeClass('sequential')
-
- if lastNode.nextElementSibling?.dataset?.username isnt lastNode.dataset.username
- $(lastNode.nextElementSibling).removeClass('sequential')
-
- ul = lastNode.parentElement
- wrapper = ul.parentElement
-
- if context.urls?.length > 0 and Template.oembedBaseWidget?
- for item in context.urls
- do (item) ->
- urlNode = lastNode.querySelector('.body a[href="'+item.url+'"]')
- if urlNode?
- $(urlNode).replaceWith Blaze.toHTMLWithData Template.oembedBaseWidget, item
-
- if not lastNode.nextElementSibling?
- if lastNode.classList.contains('own') is true
- view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom = true
- else
- if view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom isnt true
- newMessage = document.querySelector(".new-message")
- newMessage.className = "new-message"
diff --git a/packages/rocketchat-livechat/app/client/views/messages.js b/packages/rocketchat-livechat/app/client/views/messages.js
deleted file mode 100644
index 5bda8a026ac7d..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/messages.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/* globals Livechat, LivechatVideoCall, MsgTyping */
-
-Template.messages.helpers({
- messages() {
- return ChatMessage.find({
- rid: visitor.getRoom(),
- t: {
- '$ne': 't'
- }
- }, {
- sort: {
- ts: 1
- }
- });
- },
- showOptions() {
- if (Template.instance().showOptions.get()) {
- return 'show';
- } else {
- return '';
- }
- },
- optionsLink() {
- if (Template.instance().showOptions.get()) {
- return t('Close_menu');
- } else {
- return t('Options');
- }
- },
- videoCallEnabled() {
- return Livechat.videoCall;
- },
- showConnecting() {
- return Livechat.connecting;
- },
- usersTyping() {
- const users = MsgTyping.get(visitor.getRoom());
- if (users.length === 0) {
- return;
- }
- if (users.length === 1) {
- return {
- multi: false,
- selfTyping: MsgTyping.selfTyping.get(),
- users: users[0]
- };
- }
- // usernames = _.map messages, (message) -> return message.u.username
- let last = users.pop();
- if (users.length > 4) {
- last = t('others');
- }
- // else
- let usernames = users.join(', ');
- usernames = [usernames, last];
- return {
- multi: true,
- selfTyping: MsgTyping.selfTyping.get(),
- users: usernames.join(` ${t('and')} `)
- };
- },
- agentData() {
- const agent = Livechat.agent;
- if (!agent) {
- return null;
- }
-
- const agentData = {
- avatar: getAvatarUrlFromUsername(agent.username)
- };
-
- if (agent.name) {
- agentData.name = agent.name;
- }
-
- if (agent.emails && agent.emails[0] && agent.emails[0].address) {
- agentData.email = agent.emails[0].address;
- }
-
- if (agent.customFields && agent.customFields.phone) {
- agentData.phone = agent.customFields.phone;
- }
-
- return agentData;
- }
-});
-
-Template.messages.events({
- 'keyup .input-message': function(event, instance) {
- instance.chatMessages.keyup(visitor.getRoom(), event, instance);
- instance.updateMessageInputHeight(event.currentTarget);
- },
- 'keydown .input-message': function(event, instance) {
- return instance.chatMessages.keydown(visitor.getRoom(), event, instance);
- },
- 'click .send-button': function(event, instance) {
- let input = instance.find('.input-message');
- let sent = instance.chatMessages.send(visitor.getRoom(), input);
- input.focus();
- instance.updateMessageInputHeight(input);
-
- return sent;
- },
- 'click .new-message': function(event, instance) {
- instance.atBottom = true;
- return instance.find('.input-message').focus();
- },
- 'click .error': function(event) {
- return $(event.currentTarget).removeClass('show');
- },
- 'click .toggle-options': function(event, instance) {
- instance.showOptions.set(!instance.showOptions.get());
- },
- 'click .video-button': function(event) {
- event.preventDefault();
-
- if (!Meteor.userId()) {
- Meteor.call('livechat:registerGuest', { token: visitor.getToken() }, (error, result) => {
- if (error) {
- return console.log(error.reason);
- }
-
- Meteor.loginWithToken(result.token, (error) => {
- if (error) {
- return console.log(error.reason);
- }
-
- LivechatVideoCall.request();
- });
- });
- } else {
- LivechatVideoCall.request();
- }
- }
-});
-
-Template.messages.onCreated(function() {
- this.atBottom = true;
-
- this.showOptions = new ReactiveVar(false);
-
- this.updateMessageInputHeight = function(input) {
- // Inital height is 28. If the scrollHeight is greater than that( we have more text than area ),
- // increase the size of the textarea. The max-height is set at 200
- // even if the scrollHeight become bigger than that it should never exceed that.
- // Account for no text in the textarea when increasing the height.
- // If there is no text, reset the height.
- let inputScrollHeight;
- inputScrollHeight = $(input).prop('scrollHeight');
- if (inputScrollHeight > 28) {
- return $(input).height($(input).val() === '' ? '15px' : (inputScrollHeight >= 200 ? inputScrollHeight - 50 : inputScrollHeight - 20));
- }
- };
-
- $(document).click((/*event*/) => {
- if (!this.showOptions.get()) {
- return;
- }
- let target = $(event.target);
- if (!target.closest('.options-menu').length && !target.is('.options-menu') && !target.closest('.toggle-options').length && !target.is('.toggle-options')) {
- this.showOptions.set(false);
- }
- });
-});
-
-Template.messages.onRendered(function() {
- this.chatMessages = new ChatMessages();
- this.chatMessages.init(this.firstNode);
-});
-
-Template.messages.onRendered(function() {
- var messages, newMessage, onscroll, template;
- messages = this.find('.messages');
- newMessage = this.find('.new-message');
- template = this;
- if (messages) {
- onscroll = _.throttle(function() {
- template.atBottom = messages.scrollTop >= messages.scrollHeight - messages.clientHeight;
- }, 200);
- Meteor.setInterval(function() {
- if (template.atBottom) {
- messages.scrollTop = messages.scrollHeight - messages.clientHeight;
- newMessage.className = 'new-message not';
- }
- }, 100);
- messages.addEventListener('touchstart', function() {
- template.atBottom = false;
- });
- messages.addEventListener('touchend', function() {
- onscroll();
- });
- messages.addEventListener('scroll', function() {
- template.atBottom = false;
- onscroll();
- });
- messages.addEventListener('mousewheel', function() {
- template.atBottom = false;
- onscroll();
- });
- messages.addEventListener('wheel', function() {
- template.atBottom = false;
- onscroll();
- });
- }
-});
diff --git a/packages/rocketchat-livechat/app/client/views/options.html b/packages/rocketchat-livechat/app/client/views/options.html
deleted file mode 100644
index 50bc5217f78d4..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/options.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
diff --git a/packages/rocketchat-livechat/app/client/views/options.js b/packages/rocketchat-livechat/app/client/views/options.js
deleted file mode 100644
index e23857cc8311e..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/options.js
+++ /dev/null
@@ -1,21 +0,0 @@
-Template.options.events({
- 'click .end-chat'() {
- swal({
- text: t('Are_you_sure_do_you_want_end_this_chat'),
- title: '',
- type: 'warning',
- showCancelButton: true,
- confirmButtonColor: '#DD6B55',
- confirmButtonText: t('Yes'),
- cancelButtonText: t('No'),
- closeOnConfirm: false,
- html: false
- }, () => {
- Meteor.call('livechat:closeByVisitor', (error) => {
- if (error) {
- return console.log('Error ->', error);
- }
- });
- });
- }
-});
diff --git a/packages/rocketchat-livechat/app/client/views/poweredBy.html b/packages/rocketchat-livechat/app/client/views/poweredBy.html
deleted file mode 100644
index 7e3e337a34a61..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/poweredBy.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- {{_ "Powered_by"}}
-
-
-
-
-
diff --git a/packages/rocketchat-livechat/app/client/views/survey.js b/packages/rocketchat-livechat/app/client/views/survey.js
deleted file mode 100644
index 2a51aad82c65a..0000000000000
--- a/packages/rocketchat-livechat/app/client/views/survey.js
+++ /dev/null
@@ -1,17 +0,0 @@
-Template.survey.events({
- 'click button.skip': function(e, instance) {
- instance.$('#survey').remove();
- },
-
- 'click button.send': function(e, instance) {
- const formData = instance.$('form').serializeArray();
- Meteor.call('livechat:saveSurveyFeedback', visitor.getToken(), visitor.getRoom(), formData, function(/*err, results*/) {
- instance.$('#survey').remove();
- swal({
- title: t('Thank_you_for_your_feedback'),
- type: 'success',
- timer: 2000
- });
- });
- }
-});
diff --git a/packages/rocketchat-livechat/app/i18n/ar.i18n.json b/packages/rocketchat-livechat/app/i18n/ar.i18n.json
deleted file mode 100644
index 63ff96f74b71a..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/ar.i18n.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "Additional_Feedback": "ملاحظات إضافية",
- "Appearance": "المظهر",
- "Conversation_finished": "المحادثة الانتهاء",
- "How_friendly_was_the_chat_agent": "كيف ودية وكان وكيل الدردشة؟",
- "How_knowledgeable_was_the_chat_agent": "معرفة كيف كان وكيل الدردشة؟",
- "How_responsive_was_the_chat_agent": "كيف تستجيب كان وكيل الدردشة؟",
- "How_satisfied_were_you_with_this_chat": "ما مدى رضاك مع هذه الدردشة؟",
- "Installation": "تركيب",
- "New_messages": "رسائل جديدة",
- "Please_answer_survey": "يرجى ان نتوقف لحظة للرد على مسح سريع حول هذه الدردشة",
- "Please_fill_name_and_email": "الرجاء إدخال الإسم والبريد الإلكتروني",
- "Powered_by": "مشغل بواسطة",
- "Select_a_department": "حدد القسم",
- "Send": "إرسال",
- "Skip": "تخطي",
- "Start_Chat": "بدأ الدردشة",
- "Survey": "الدراسة الاستقصائية",
- "Survey_instructions": "معدل كل سؤال وفقا لالارتياح الخاص بك، 1 وهذا يعني أنك غير راضي تماما و 5 يعني كنت راضيا تماما.",
- "Thank_you_for_your_feedback": "شكرا لأفادتك",
- "Thanks_We_ll_get_back_to_you_soon": "شكر! سوف نعود إليك قريبا.",
- "Type_your_email": "اكتب بريدك الالكتروني",
- "Type_your_message": "اكتب رسالتك",
- "Type_your_name": "اكتب اسمك",
- "User_joined": "العضو انضم",
- "User_left": "اليسار المستخدم",
- "We_are_offline_Sorry_for_the_inconvenience": "نحن حاليا. آسف للإزعاج.",
- "You_must_complete_all_fields": "يجب عليك إكمال جميع الحقول"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/de.i18n.json b/packages/rocketchat-livechat/app/i18n/de.i18n.json
deleted file mode 100644
index 645e8cf8808b6..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/de.i18n.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "Additional_Feedback": "Zusätzliches Feedback",
- "Appearance": "Erscheinungsbild",
- "Are_you_sure_do_you_want_end_this_chat": "Sind Sie sich sicher diesen Chat zu beenden?",
- "Cancel": "Abbrechen",
- "Chat_ended": "Chat beendet!",
- "Close_menu": "Menü schließen",
- "Conversation_finished": "Gespräch beendet",
- "End_chat": "Chat beenden",
- "How_friendly_was_the_chat_agent": "Wie freundlich war der Chat-Agent?",
- "How_knowledgeable_was_the_chat_agent": "Wie sachkundig war der Chat-Agent?",
- "How_responsive_was_the_chat_agent": "Wie reaktionsschnell war der Chat-Agent?",
- "How_satisfied_were_you_with_this_chat": "Wie zufrieden sind Sie mit diesem Gespräch?",
- "Installation": "Installation",
- "New_messages": "Neue Nachrichten",
- "No": "Nein",
- "Options": "Optionen",
- "Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Gespräch zu beantworten.",
- "Please_fill_name_and_email": "Bitte geben Sie einen Namen und eine E-Mail-Adresse ein.",
- "Powered_by": "Unterstützt von",
- "Request_video_chat": "Video Chat anfragen",
- "Select_a_department": "Abteilung auswählen",
- "Send": "Senden",
- "Skip": "Überspringen",
- "Start_Chat": "Chat beginnen",
- "Survey": "Umfrage",
- "Survey_instructions": "Bewerten Sie jede Frage nach Ihrer Zufriedenheit. 1 bedeutet, dass Sie völlig unzufrieden sind und 5 bedeutet, dass Sie vollständig zufrieden sind.",
- "Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung.",
- "Thanks_We_ll_get_back_to_you_soon": "Vielen Dank! Wir kommen auf Sie zeitnah zurück.",
- "transcript_sent": "Transkript versendet",
- "Type_your_email": "Geben Sie Ihre E-Mail-Adresse an",
- "Type_your_message": "Geben Sie Ihre Nachricht ein.",
- "Type_your_name": "Geben Sie Ihren Namen ein",
- "User_joined": "Benutzer.in wurde Mitglied",
- "User_left": "Benutzer.in abgemeldet",
- "We_are_offline_Sorry_for_the_inconvenience": "Wir sind offline. Entschuldigen Sie die Unannehmlichkeiten.",
- "Yes": "Ja",
- "You": "Sie",
- "You_must_complete_all_fields": "Sie müssen alle Felder ausfüllen"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/fa.i18n.json b/packages/rocketchat-livechat/app/i18n/fa.i18n.json
deleted file mode 100644
index 074012b085179..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/fa.i18n.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "Additional_Feedback": "بازخورد اضافی",
- "Appearance": "ظاهر",
- "Conversation_finished": "مکالمه به پایان رسید",
- "How_friendly_was_the_chat_agent": "عامل چت چگونه دوستانه بود؟",
- "How_knowledgeable_was_the_chat_agent": "عامل چت چگونه آگاه بود؟",
- "How_responsive_was_the_chat_agent": "عامل چت چگونه پاسخگو بود؟",
- "How_satisfied_were_you_with_this_chat": "چگونه رضایت شما را با این چت بود؟",
- "Installation": "نصب و راه اندازی",
- "New_messages": "پیام های جدید",
- "Please_answer_survey": "لطفا یک لحظه به پاسخ به یک نظرسنجی در مورد این چت",
- "Please_fill_name_and_email": "لطفا نام و ایمیل را پر کنید",
- "Powered_by": "طراحی شده توسط",
- "Select_a_department": "انتخاب بخش",
- "Send": "ارسال",
- "Skip": "رفتن",
- "Start_Chat": "شروع چت",
- "Survey": "نظرسنجی",
- "Survey_instructions": "رای هر سوال با توجه به جلب رضایت شما، 1 معنی که شما ناراضی هستند به طور کامل و 5 این معنی که شما به طور کامل راضی هستند.",
- "Thank_you_for_your_feedback": "با تشکر از شما برای نظرات شما",
- "Thanks_We_ll_get_back_to_you_soon": "با تشکر! ما به شما به زودی.",
- "Type_your_email": "نوع ایمیل خود را",
- "Type_your_message": "نوع پیام خود را",
- "Type_your_name": "نامتان را بنویسید",
- "User_joined": "کاربر تاریخ عضویت",
- "User_left": "سمت چپ کاربر",
- "We_are_offline_Sorry_for_the_inconvenience": "ما آنلاین نیست. با عرض پوزش برای ناراحتی.",
- "You_must_complete_all_fields": "شما باید تمام زمینه ها کامل"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/fr.i18n.json b/packages/rocketchat-livechat/app/i18n/fr.i18n.json
deleted file mode 100644
index 6a58f9c447770..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/fr.i18n.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "Additional_Feedback": "Commentaires supplémentaires",
- "Appearance": "Apparence",
- "Are_you_sure_do_you_want_end_this_chat": "Êtes-vous sûr de vouloir mettre fin à cette conversation ?",
- "Cancel": "Annuler",
- "Chat_ended": "Conversation terminée !",
- "Close_menu": "Fermer le menu",
- "Conversation_finished": "Conversation terminée",
- "End_chat": "Mettre fin à la conversation",
- "How_friendly_was_the_chat_agent": "L'assistant du chat était-il sympathique ?",
- "How_knowledgeable_was_the_chat_agent": "Les réponses de l'assistant du chat était-elles adaptées ?",
- "How_responsive_was_the_chat_agent": "L'assistant du chat a-t-il répondu à vos questions ?",
- "How_satisfied_were_you_with_this_chat": "Êtes-vous satisfait de ce chat?",
- "Installation": "Installation",
- "New_messages": "Nouveaux messages",
- "No": "Non",
- "Options": "Options",
- "Please_answer_survey": "Merci de prendre un moment pour répondre à un sondage rapide à propos de ce chat ",
- "Please_fill_name_and_email": "Veuillez remplir votre nom et votre adresse e-mail",
- "Powered_by": "Propulsé par",
- "Request_video_chat": "Demander un chat vidéo",
- "Select_a_department": "Sélectionner un département",
- "Send": "Envoyer",
- "Skip": "Passer",
- "Start_Chat": "Démarrer un chat",
- "Survey": "Sondage",
- "Survey_instructions": "Notez chaque question en fonction de votre satisfaction, 1 signifiant que vous êtes très insatisfait et 5 que vous êtes entièrement satisfait.",
- "Thank_you_for_your_feedback": "Merci pour votre retour",
- "Thanks_We_ll_get_back_to_you_soon": "Merci ! Nous regarderons cela dès que possible.",
- "transcript_sent": "Transcription envoyée",
- "Type_your_email": "Entrez votre e-mail",
- "Type_your_message": "Entrez votre message",
- "Type_your_name": "Entrez votre nom",
- "User_joined": "L'utilisateur a rejoint",
- "User_left": "L'utilisateur est parti",
- "We_are_offline_Sorry_for_the_inconvenience": "Nous sommes hors-ligne. Désolé pour le désagrément.",
- "Yes": "Oui",
- "You": "Vous",
- "You_must_complete_all_fields": "Vous devez remplir tous les champs"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/it.i18n.json b/packages/rocketchat-livechat/app/i18n/it.i18n.json
deleted file mode 100644
index 1cb1fb1209598..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/it.i18n.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "Additional_Feedback": "Feedback aggiuntivi",
- "Appearance": "Aspetto",
- "Are_you_sure_do_you_want_end_this_chat": "Sei sicuro di voler chiudere questa chat?",
- "Cancel": "Cancella",
- "Chat_ended": "Chat chiusa!",
- "Close_menu": "Chiudi menu",
- "Conversation_finished": "conversazione finito",
- "End_chat": "Chiusura chat",
- "How_friendly_was_the_chat_agent": "Il servizio chat é stato funzionale?",
- "How_knowledgeable_was_the_chat_agent": "Quanto é stato semplice il servizio chat?",
- "How_responsive_was_the_chat_agent": "Quanto é stato reattivo il servizio chat?",
- "How_satisfied_were_you_with_this_chat": "Quanto sei soddisfatto con questa chat?",
- "Installation": "Installazione",
- "New_messages": "Nuovi messaggi",
- "No": "No",
- "Options": "Opzioni",
- "Please_answer_survey": "Hai un momento per rispondere a un rapido sondaggio su questa chat?",
- "Please_fill_name_and_email": "Compila nome e indirizzo e-mail",
- "Powered_by": "Powered by",
- "Select_a_department": "Seleziona un reparto",
- "Send": "Invia",
- "Skip": "Salta",
- "Start_Chat": "Avvia chat",
- "Survey": "Sondaggio",
- "Survey_instructions": "Vota ogni domanda secondo la tua soddisfazione, 1 significa che sei completamente insoddisfatto e 5 significa che sei completamente soddisfatto.",
- "Thank_you_for_your_feedback": "Grazie per il tuo feedback",
- "Thanks_We_ll_get_back_to_you_soon": "Grazie! Torneremo al più presto.",
- "Type_your_email": "Inserisci la tua e-mail",
- "Type_your_message": "Inserisci il tuo messaggio",
- "Type_your_name": "Scrivi il tuo nome",
- "User_joined": "é entrato",
- "User_left": "Utente ha lasciato",
- "We_are_offline_Sorry_for_the_inconvenience": "Non siamo in linea. Ci dispiace per l'inconveniente.",
- "Yes": "Si",
- "You": "Tu",
- "You_must_complete_all_fields": "È necessario completare tutti i campi"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ko.i18n.json b/packages/rocketchat-livechat/app/i18n/ko.i18n.json
deleted file mode 100644
index ba628fdff090b..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/ko.i18n.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "Additional_Feedback": "추가 의견",
- "Appearance": "모양",
- "Are_you_sure_do_you_want_end_this_chat": "이 채팅을 정말 끝내시겠습니까?",
- "Cancel": "취소",
- "Chat_ended": "채팅 끝남!",
- "Close_menu": "메뉴 닫기",
- "Conversation_finished": "대화 종료됨",
- "End_chat": "채팅 끝남",
- "How_friendly_was_the_chat_agent": "채팅 에이전트는 어떻게 친했다?",
- "How_knowledgeable_was_the_chat_agent": "채팅 에이전트는 어떻게 지식인가?",
- "How_responsive_was_the_chat_agent": "채팅 에이전트는 어떻게 반응이었다?",
- "How_satisfied_were_you_with_this_chat": "이 채팅에 당신을 어떻게 만족?",
- "Installation": "설치",
- "New_messages": "새 메시지",
- "Options": "옵션",
- "Please_answer_survey": "이 채팅에 대한 간단한 설문 조사에 응답하기 위해 잠시 시간을내어 주시기 바랍니다",
- "Please_fill_name_and_email": "이름과 이메일을 입력하세요",
- "Powered_by": "에 의해 구동",
- "Request_video_chat": "비디오채팅 요청",
- "Select_a_department": "부서를 선택해주세요",
- "Send": "전송",
- "Skip": "건너뛰기",
- "Start_Chat": "채팅 시작",
- "Survey": "설문",
- "Survey_instructions": "당신이 완전히 만족하는 의미를 완전히 만족하지 의미에 대한 만족도에 따라 1 각 질문에 평가 5.",
- "Thank_you_for_your_feedback": "의견을 보내 주셔서 감사합니다",
- "Thanks_We_ll_get_back_to_you_soon": "감사합니다! 곧 다시 연락드리겠습니다",
- "Type_your_email": "이메일을 입력",
- "Type_your_message": "메시지를 입력",
- "Type_your_name": "당신의 이름을 입력",
- "User_joined": "사용자 가입",
- "User_left": "사용자 왼쪽",
- "We_are_offline_Sorry_for_the_inconvenience": "우리는 오프라인 상태입니다. 불편을 드려 죄송합니다.",
- "You_must_complete_all_fields": "모든 필드를 작성해야합니다"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/lt.i18n.json b/packages/rocketchat-livechat/app/i18n/lt.i18n.json
deleted file mode 100644
index 1b5b400f98806..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/lt.i18n.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Additional_Feedback": "Papildoma Atsiliepimai"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/ru.i18n.json b/packages/rocketchat-livechat/app/i18n/ru.i18n.json
deleted file mode 100644
index 374c766b0a89d..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/ru.i18n.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "Additional_Feedback": "Дополнительная обратная связь",
- "Appearance": "Внешний вид",
- "Conversation_finished": "Разговор закончен",
- "How_friendly_was_the_chat_agent": "Насколько дружелюбен был сотрудник чата?",
- "How_knowledgeable_was_the_chat_agent": "Насколько информативен был сотрудник чата?",
- "How_responsive_was_the_chat_agent": "Насколько отзывчив был сотрудник чата?",
- "How_satisfied_were_you_with_this_chat": "Насколько Вы удовлетворены использованием этого чата?",
- "Installation": "Установка",
- "New_messages": "Новые сообщения",
- "Please_answer_survey": "Пожалуйста, уделите минуту для того, чтобы ответить на несколько вопросов об этом чате",
- "Please_fill_name_and_email": "Введите имя и электронный адрес",
- "Powered_by": "Представлен",
- "Select_a_department": "Выберите группу",
- "Send": "Отправить",
- "Skip": "Пропустить",
- "Start_Chat": "Начать чат",
- "Survey": "Опрос",
- "Survey_instructions": "Оцените каждый вопрос по 5-балльной шкале, где 1 означает, что Вы совсем недовольны, и 5 - полностью довольны.",
- "Thank_you_for_your_feedback": "Спасибо за Ваш отзыв",
- "Thanks_We_ll_get_back_to_you_soon": "Спасибо! Мы свяжемся с вами в ближайшее время.",
- "Type_your_email": "Введите адрес электронной почты",
- "Type_your_message": "Текст сообщения",
- "Type_your_name": "Введите свое имя",
- "User_joined": "Пользователь присоединился",
- "User_left": "слева Пользователь",
- "We_are_offline_Sorry_for_the_inconvenience": "Мы не в сети. Извините за доставленные неудобства.",
- "You_must_complete_all_fields": "Вы должны заполнить все поля"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/sv.i18n.json b/packages/rocketchat-livechat/app/i18n/sv.i18n.json
deleted file mode 100644
index e1aacc1dfac4e..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/sv.i18n.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "Additional_Feedback": "Ytterligare feedback",
- "Appearance": "Utseende",
- "Cancel": "Avbryt",
- "Close_menu": "Stäng meny",
- "Conversation_finished": "konversation klar",
- "End_chat": "Avsluta chatt",
- "How_friendly_was_the_chat_agent": "Hur vänlig var chattagenten?",
- "How_knowledgeable_was_the_chat_agent": "Hur kunnig var chattagenten?",
- "How_responsive_was_the_chat_agent": "Hur reagerar var chattagenten?",
- "How_satisfied_were_you_with_this_chat": "Hur nöjd var du med chatten?",
- "Installation": "Installation",
- "New_messages": "Nya meddelanden",
- "No": "Nej",
- "Please_answer_survey": "Vänligen ta en stund för att svara på en snabb enkät om chatten.",
- "Please_fill_name_and_email": "Vänligen fyll i namn och e-postadress",
- "Powered_by": "powered by",
- "Select_a_department": "Välj en avdelning",
- "Send": "Skicka",
- "Skip": "Hoppa över",
- "Start_Chat": "Starta chatt",
- "Survey": "Enkät",
- "Survey_instructions": "Betygsätt varje fråga efter hur nöjd du är, 1 betyder att du inte alls är nöjd och 5 betyder att du är helt nöjd.\n",
- "Thank_you_for_your_feedback": "Tack för din feedback",
- "Thanks_We_ll_get_back_to_you_soon": "Tack! Vi återkommer till dig snart.",
- "Type_your_email": "Skriv din e-post",
- "Type_your_message": "Skriv in ditt meddelande",
- "Type_your_name": "Skriv in ditt namn",
- "User_joined": "user gick",
- "User_left": "användaren vänster",
- "We_are_offline_Sorry_for_the_inconvenience": "Vi är offline. Vi beklagar olägenheten. ",
- "You_must_complete_all_fields": "Du måste fylla i alla fält"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/uk.i18n.json b/packages/rocketchat-livechat/app/i18n/uk.i18n.json
deleted file mode 100644
index 06ec3a3e2883c..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/uk.i18n.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "Additional_Feedback": "Додаткова зв'язок",
- "Appearance": "зовнішній вигляд",
- "Conversation_finished": "розмова закінчена",
- "How_friendly_was_the_chat_agent": "Як дружній був чат агент?",
- "How_knowledgeable_was_the_chat_agent": "Наскільки добре був чат агент?",
- "How_responsive_was_the_chat_agent": "Як реагувати був чат агент?",
- "How_satisfied_were_you_with_this_chat": "Як ви задоволені цей чат?",
- "Installation": "установка",
- "New_messages": "нові повідомлення",
- "Please_answer_survey": "Будь ласка, знайдіть час, щоб відповісти на швидкий огляд про це чаті",
- "Please_fill_name_and_email": "Заповніть, будь ласка, ім'я та адресу електронної пошти",
- "Powered_by": "працює на",
- "Select_a_department": "Виберіть відділ",
- "Send": "послати",
- "Skip": "скакати",
- "Start_Chat": "Почати Чат",
- "Survey": "обстеження",
- "Survey_instructions": "Оцінити кожне питання відповідно до ваших задоволення, 1 означає, що ви повністю незадоволеним і 5 означає, що ви повністю задоволені.",
- "Thank_you_for_your_feedback": "Спасибі за ваш відгук",
- "Thanks_We_ll_get_back_to_you_soon": "Дякую! Ми зв'яжемося з вами найближчим часом.",
- "Type_your_email": "Введіть адресу електронної пошти",
- "Type_your_message": "текст повідомлення",
- "Type_your_name": "Введіть ваше ім'я",
- "User_joined": "Користувач приєднався",
- "User_left": "зліва Користувач",
- "We_are_offline_Sorry_for_the_inconvenience": "Ми в автономному режимі. Вибачте за незручності.",
- "You_must_complete_all_fields": "Ви повинні заповнити всі поля"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/i18n/zh-HK.i18n.json b/packages/rocketchat-livechat/app/i18n/zh-HK.i18n.json
deleted file mode 100644
index f7ea94348cb2c..0000000000000
--- a/packages/rocketchat-livechat/app/i18n/zh-HK.i18n.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Start_Chat": "开始聊天"
-}
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/package.json b/packages/rocketchat-livechat/app/package.json
deleted file mode 100644
index 5a10e8c08dade..0000000000000
--- a/packages/rocketchat-livechat/app/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "rocketchat-livechat",
- "version": "1.0.0",
- "description": "Livechat app from Rocket.Chat",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": {
- "name": "Rocket.Chat",
- "url": "https://rocket.chat/"
- },
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "https://github.com/RocketChat/Rocket.Chat.git"
- },
- "bugs": {
- "url": "https://github.com/RocketChat/Rocket.Chat/issues",
- "email": "support@rocket.chat"
- },
- "dependencies": {
- "autolinker": "^1.4.0",
- "jquery": "^3.1.1",
- "babel-runtime": "^6.22.0",
- "bcrypt": "^1.0.2",
- "moment": "^2.17.1",
- "toastr": "^2.1.2"
- }
-}
diff --git a/packages/rocketchat-livechat/assets/demo.html b/packages/rocketchat-livechat/assets/demo.html
index 2071ee08861a5..a8269484df63d 100644
--- a/packages/rocketchat-livechat/assets/demo.html
+++ b/packages/rocketchat-livechat/assets/demo.html
@@ -10,7 +10,7 @@
var h = d.getElementsByTagName(s)[0],
j = d.createElement(s);
j.async = true;
- j.src = '/packages/rocketchat_livechat/assets/rocket-livechat.js';
+ j.src = '/packages/rocketchat_livechat/assets/rocketchat-livechat.min.js?_=201702160944';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', '/livechat');
diff --git a/packages/rocketchat-livechat/assets/rocket-livechat.js b/packages/rocketchat-livechat/assets/rocket-livechat.js
index 0fcac2ce9ffdd..d81d0ae304c6c 100644
--- a/packages/rocketchat-livechat/assets/rocket-livechat.js
+++ b/packages/rocketchat-livechat/assets/rocket-livechat.js
@@ -1,3 +1,479 @@
+/*!
+ * EventEmitter v5.1.0 - git.io/ee
+ * Unlicense - http://unlicense.org/
+ * Oliver Caldwell - http://oli.me.uk/
+ * @preserve
+ */
+(function(exports) {
+ 'use strict';
+
+ /**
+ * Class for managing events.
+ * Can be extended to provide event functionality in other classes.
+ *
+ * @class EventEmitter Manages event registering and emitting.
+ */
+ function EventEmitter() {}
+
+ // Shortcuts to improve speed and size
+ var proto = EventEmitter.prototype;
+ var originalGlobalValue = exports.EventEmitter;
+
+ /**
+ * Finds the index of the listener for the event in its storage array.
+ *
+ * @param {Function[]} listeners Array of listeners to search through.
+ * @param {Function} listener Method to look for.
+ * @return {Number} Index of the specified listener, -1 if not found
+ * @api private
+ */
+ function indexOfListener(listeners, listener) {
+ var i = listeners.length;
+ while (i--) {
+ if (listeners[i].listener === listener) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
+ *
+ * @param {String} name The name of the target method.
+ * @return {Function} The aliased method
+ * @api private
+ */
+ function alias(name) {
+ return function aliasClosure() {
+ return this[name].apply(this, arguments);
+ };
+ }
+
+ /**
+ * Returns the listener array for the specified event.
+ * Will initialise the event object and listener arrays if required.
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
+ * Each property in the object response is an array of listener functions.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Function[]|Object} All listener functions for the event.
+ */
+ proto.getListeners = function getListeners(evt) {
+ var events = this._getEvents();
+ var response;
+ var key;
+
+ // Return a concatenated array of all matching events if
+ // the selector is a regular expression.
+ if (evt instanceof RegExp) {
+ response = {};
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ response[key] = events[key];
+ }
+ }
+ } else {
+ response = events[evt] || (events[evt] = []);
+ }
+
+ return response;
+ };
+
+ /**
+ * Takes a list of listener objects and flattens it into a list of listener functions.
+ *
+ * @param {Object[]} listeners Raw listener objects.
+ * @return {Function[]} Just the listener functions.
+ */
+ proto.flattenListeners = function flattenListeners(listeners) {
+ var flatListeners = [];
+ var i;
+
+ for (i = 0; i < listeners.length; i += 1) {
+ flatListeners.push(listeners[i].listener);
+ }
+
+ return flatListeners;
+ };
+
+ /**
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
+ *
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
+ * @return {Object} All listener functions for an event in an object.
+ */
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
+ var listeners = this.getListeners(evt);
+ var response;
+
+ if (listeners instanceof Array) {
+ response = {};
+ response[evt] = listeners;
+ }
+
+ return response || listeners;
+ };
+
+ function isValidListener(listener) {
+ if (typeof listener === 'function' || listener instanceof RegExp) {
+ return true;
+ } else if (listener && typeof listener === 'object') {
+ return isValidListener(listener.listener);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds a listener function to the specified event.
+ * The listener will not be added if it is a duplicate.
+ * If the listener returns true then it will be removed after it is called.
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListener = function addListener(evt, listener) {
+ if (!isValidListener(listener)) {
+ throw new TypeError('listener must be a function');
+ }
+
+ var listeners = this.getListenersAsObject(evt);
+ var listenerIsWrapped = typeof listener === 'object';
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
+ listeners[key].push(listenerIsWrapped ? listener : {
+ listener: listener,
+ once: false
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of addListener
+ */
+ proto.on = alias('addListener');
+
+ /**
+ * Semi-alias of addListener. It will add a listener that will be
+ * automatically removed after its first execution.
+ *
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addOnceListener = function addOnceListener(evt, listener) {
+ return this.addListener(evt, {
+ listener: listener,
+ once: true
+ });
+ };
+
+ /**
+ * Alias of addOnceListener.
+ */
+ proto.once = alias('addOnceListener');
+
+ /**
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
+ * You need to tell it what event names should be matched by a regex.
+ *
+ * @param {String} evt Name of the event to create.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvent = function defineEvent(evt) {
+ this.getListeners(evt);
+ return this;
+ };
+
+ /**
+ * Uses defineEvent to define multiple events.
+ *
+ * @param {String[]} evts An array of event names to define.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.defineEvents = function defineEvents(evts) {
+ for (var i = 0; i < evts.length; i += 1) {
+ this.defineEvent(evts[i]);
+ }
+ return this;
+ };
+
+ /**
+ * Removes a listener function from the specified event.
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
+ * @param {Function} listener Method to remove from the event.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListener = function removeListener(evt, listener) {
+ var listeners = this.getListenersAsObject(evt);
+ var index;
+ var key;
+
+ for (key in listeners) {
+ if (listeners.hasOwnProperty(key)) {
+ index = indexOfListener(listeners[key], listener);
+
+ if (index !== -1) {
+ listeners[key].splice(index, 1);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeListener
+ */
+ proto.off = alias('removeListener');
+
+ /**
+ * Adds listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
+ * Yeah, this function does quite a bit. That's probably a bad thing.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.addListeners = function addListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(false, evt, listeners);
+ };
+
+ /**
+ * Removes listeners in bulk using the manipulateListeners method.
+ * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be removed.
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
+ *
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeListeners = function removeListeners(evt, listeners) {
+ // Pass through to manipulateListeners
+ return this.manipulateListeners(true, evt, listeners);
+ };
+
+ /**
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
+ * The first argument will determine if the listeners are removed (true) or added (false).
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
+ * You can also pass it an event name and an array of listeners to be added/removed.
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
+ *
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
+ var i;
+ var value;
+ var single = remove ? this.removeListener : this.addListener;
+ var multiple = remove ? this.removeListeners : this.addListeners;
+
+ // If evt is an object then pass each of its properties to this method
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
+ for (i in evt) {
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
+ // Pass the single listener straight through to the singular method
+ if (typeof value === 'function') {
+ single.call(this, i, value);
+ } else {
+ // Otherwise pass back to the multiple function
+ multiple.call(this, i, value);
+ }
+ }
+ }
+ } else {
+ // So evt must be a string
+ // And listeners must be an array of listeners
+ // Loop over it and pass each one to the multiple method
+ i = listeners.length;
+ while (i--) {
+ single.call(this, evt, listeners[i]);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Removes all listeners from a specified event.
+ * If you do not specify an event then all listeners will be removed.
+ * That means every event will be emptied.
+ * You can also pass a regex to remove all events that match it.
+ *
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.removeEvent = function removeEvent(evt) {
+ var type = typeof evt;
+ var events = this._getEvents();
+ var key;
+
+ // Remove different things depending on the state of evt
+ if (type === 'string') {
+ // Remove all listeners for the specified event
+ delete events[evt];
+ } else if (evt instanceof RegExp) {
+ // Remove all events matching the regex.
+ for (key in events) {
+ if (events.hasOwnProperty(key) && evt.test(key)) {
+ delete events[key];
+ }
+ }
+ } else {
+ // Remove all listeners in all events
+ delete this._events;
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of removeEvent.
+ *
+ * Added to mirror the node API.
+ */
+ proto.removeAllListeners = alias('removeEvent');
+
+ /**
+ * Emits an event of your choice.
+ * When emitted, every listener attached to that event will be executed.
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
+ * So they will not arrive within the array on the other side, they will be separate.
+ * You can also pass a regular expression to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emitEvent = function emitEvent(evt, args) {
+ var listenersMap = this.getListenersAsObject(evt);
+ var listeners;
+ var listener;
+ var i;
+ var key;
+ var response;
+
+ for (key in listenersMap) {
+ if (listenersMap.hasOwnProperty(key)) {
+ listeners = listenersMap[key].slice(0);
+
+ for (i = 0; i < listeners.length; i++) {
+ // If the listener returns true then it shall be removed from the event
+ // The function is executed either with a basic call or an apply if there is an args array
+ listener = listeners[i];
+
+ if (listener.once === true) {
+ this.removeListener(evt, listener.listener);
+ }
+
+ response = listener.listener.apply(this, args || []);
+
+ if (response === this._getOnceReturnValue()) {
+ this.removeListener(evt, listener.listener);
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Alias of emitEvent
+ */
+ proto.trigger = alias('emitEvent');
+
+ /**
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
+ *
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
+ * @param {...*} Optional additional arguments to be passed to each listener.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.emit = function emit(evt) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return this.emitEvent(evt, args);
+ };
+
+ /**
+ * Sets the current value to check against when executing listeners. If a
+ * listeners return value matches the one set here then it will be removed
+ * after execution. This value defaults to true.
+ *
+ * @param {*} value The new value to check for when executing listeners.
+ * @return {Object} Current instance of EventEmitter for chaining.
+ */
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
+ this._onceReturnValue = value;
+ return this;
+ };
+
+ /**
+ * Fetches the current value to check against when executing listeners. If
+ * the listeners return value matches this one then it should be removed
+ * automatically. It will return true by default.
+ *
+ * @return {*|Boolean} The current value to check for or the default, true.
+ * @api private
+ */
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
+ if (this.hasOwnProperty('_onceReturnValue')) {
+ return this._onceReturnValue;
+ } else {
+ return true;
+ }
+ };
+
+ /**
+ * Fetches the events object and creates one if required.
+ *
+ * @return {Object} The events storage object.
+ * @api private
+ */
+ proto._getEvents = function _getEvents() {
+ return this._events || (this._events = {});
+ };
+
+ /**
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
+ *
+ * @return {Function} Non conflicting EventEmitter class.
+ */
+ EventEmitter.noConflict = function noConflict() {
+ exports.EventEmitter = originalGlobalValue;
+ return EventEmitter;
+ };
+
+ // Expose the class either via AMD, CommonJS or the global object
+ if (typeof module === 'object' && module.exports) {
+ module.exports = EventEmitter;
+ } else {
+ exports.EventEmitter = EventEmitter;
+ }
+}(this || {}));
+
+/* globals EventEmitter */
+
(function(w) {
w.RocketChat = w.RocketChat || { _: [] };
var config = {};
@@ -5,11 +481,40 @@
var iframe;
var hookQueue = [];
var ready = false;
+ var smallScreen = false;
+ var bodyStyle;
+ var scrollPosition;
var widgetWidth = '320px';
var widgetHeightOpened = '350px';
var widgetHeightClosed = '30px';
+ var validCallbacks = [
+ 'chat-maximized',
+ 'chat-minimized',
+ 'chat-started',
+ 'chat-ended',
+ 'pre-chat-form-submit',
+ 'offline-form-submit'
+ ];
+ var callbacks = new EventEmitter();
+
+ var registerCallback = function(eventName, fn) {
+ if (validCallbacks.indexOf(eventName) === -1) {
+ return false;
+ }
+
+ return callbacks.on(eventName, fn);
+ };
+
+ var emitCallback = function(eventName, data) {
+ if (typeof data !== 'undefined') {
+ callbacks.emit(eventName, data);
+ } else {
+ callbacks.emit(eventName);
+ }
+ };
+
// hooks
var callHook = function(action, params) {
if (!ready) {
@@ -24,16 +529,39 @@
};
var closeWidget = function() {
+ if (widget.dataset.state === 'closed') {
+ return;
+ }
+
+ if (smallScreen) {
+ document.body.style.cssText = bodyStyle;
+ document.body.scrollTop = scrollPosition;
+ }
+
widget.dataset.state = 'closed';
widget.style.height = widgetHeightClosed;
callHook('widgetClosed');
+
+ emitCallback('chat-minimized');
};
var openWidget = function() {
+ if (widget.dataset.state === 'opened') {
+ return;
+ }
+
+ if (smallScreen) {
+ scrollPosition = document.body.scrollTop;
+ bodyStyle = document.body.style.cssText;
+ document.body.style.cssText += 'overflow: hidden; height: 100%; width: 100%; position: fixed; top:' + scrollPosition + 'px;';
+ }
+
widget.dataset.state = 'opened';
widget.style.height = widgetHeightOpened;
callHook('widgetOpened');
document.querySelector('.rocketchat-widget iframe').focus();
+
+ emitCallback('chat-maximized');
};
var api = {
@@ -63,6 +591,9 @@
},
removeWidget: function() {
document.getElementsByTagName('body')[0].removeChild(widget);
+ },
+ callback: function(eventName, data) {
+ emitCallback(eventName, data);
}
};
@@ -74,8 +605,11 @@
});
};
- var setCustomField = function(key, value) {
- callHook('setCustomField', [ key, value ]);
+ var setCustomField = function(key, value, overwrite) {
+ if (typeof overwrite === 'undefined') {
+ overwrite = true;
+ }
+ callHook('setCustomField', [key, value, overwrite]);
};
var setTheme = function(theme) {
@@ -118,8 +652,8 @@
chatWidget.dataset.state = 'closed';
chatWidget.className = 'rocketchat-widget';
chatWidget.innerHTML = '' +
- ' '+
- '
';
+ ' ' +
+ '
';
chatWidget.style.position = 'fixed';
chatWidget.style.width = widgetWidth;
@@ -146,6 +680,7 @@
var mediaqueryresponse = function(mql) {
if (mql.matches) {
+ smallScreen = true;
chatWidget.style.left = '0';
chatWidget.style.right = '0';
chatWidget.style.width = '100%';
@@ -156,7 +691,7 @@
}
};
- var mql = window.matchMedia('screen and (max-device-width: 480px) and (orientation: portrait)');
+ var mql = window.matchMedia('screen and (max-device-width: 480px)');
mediaqueryresponse(mql);
mql.addListener(mediaqueryresponse);
@@ -181,11 +716,20 @@
// exports
w.RocketChat.livechat = {
+ // methods
pageVisited: pageVisited,
setCustomField: setCustomField,
setTheme: setTheme,
setDepartment: setDepartment,
- clearDepartment: clearDepartment
+ clearDepartment: clearDepartment,
+
+ // callbacks
+ onChatMaximized: function(fn) { registerCallback('chat-maximized', fn); },
+ onChatMinimized: function(fn) { registerCallback('chat-minimized', fn); },
+ onChatStarted: function(fn) { registerCallback('chat-started', fn); },
+ onChatEnded: function(fn) { registerCallback('chat-ended', fn); },
+ onPrechatFormSubmit: function(fn) { registerCallback('pre-chat-form-submit', fn); },
+ onOfflineFormSubmit: function(fn) { registerCallback('offline-form-submit', fn); }
};
// proccess queue
diff --git a/packages/rocketchat-livechat/client/collections/LivechatVisitor.js b/packages/rocketchat-livechat/client/collections/LivechatVisitor.js
new file mode 100644
index 0000000000000..e2b44ef3f14fa
--- /dev/null
+++ b/packages/rocketchat-livechat/client/collections/LivechatVisitor.js
@@ -0,0 +1 @@
+this.LivechatVisitor = new Mongo.Collection('rocketchat_livechat_visitor');
diff --git a/packages/rocketchat-livechat/client/collections/livechatOfficeHour.js b/packages/rocketchat-livechat/client/collections/livechatOfficeHour.js
index a741186d23577..0cb4a81530eeb 100644
--- a/packages/rocketchat-livechat/client/collections/livechatOfficeHour.js
+++ b/packages/rocketchat-livechat/client/collections/livechatOfficeHour.js
@@ -1 +1 @@
-this.LivechatOfficeHour = new Mongo.Collection('rocketchat_livechat_office_hour');
\ No newline at end of file
+this.LivechatOfficeHour = new Mongo.Collection('rocketchat_livechat_office_hour');
diff --git a/packages/rocketchat-livechat/client/methods/changeLivechatStatus.js b/packages/rocketchat-livechat/client/methods/changeLivechatStatus.js
index 8462ced931590..076dc45fccd95 100644
--- a/packages/rocketchat-livechat/client/methods/changeLivechatStatus.js
+++ b/packages/rocketchat-livechat/client/methods/changeLivechatStatus.js
@@ -6,7 +6,7 @@ Meteor.methods({
const user = Meteor.user();
- let newStatus = user.statusLivechat === 'available' ? 'not-available' : 'available';
+ const newStatus = user.statusLivechat === 'available' ? 'not-available' : 'available';
Meteor.users.update(user._id, { $set: { statusLivechat: newStatus }});
}
diff --git a/packages/rocketchat-livechat/client/route.js b/packages/rocketchat-livechat/client/route.js
index 887ca7750d214..afde8beff00c1 100644
--- a/packages/rocketchat-livechat/client/route.js
+++ b/packages/rocketchat-livechat/client/route.js
@@ -124,11 +124,19 @@ AccountBox.addRoute({
}, livechatManagerRoutes);
AccountBox.addRoute({
- name: 'livechat-integrations',
- path: '/integrations',
+ name: 'livechat-webhooks',
+ path: '/webhooks',
sideNav: 'livechatFlex',
- i18nPageTitle: 'Integrations',
- pageTemplate: 'livechatIntegrations'
+ i18nPageTitle: 'Webhooks',
+ pageTemplate: 'livechatIntegrationWebhook'
+}, livechatManagerRoutes);
+
+AccountBox.addRoute({
+ name: 'livechat-facebook',
+ path: '/facebook',
+ sideNav: 'livechatFlex',
+ i18nPageTitle: 'Facebook Messenger',
+ pageTemplate: 'livechatIntegrationFacebook'
}, livechatManagerRoutes);
AccountBox.addRoute({
diff --git a/packages/rocketchat-livechat/client/stylesheets/lesshat.less b/packages/rocketchat-livechat/client/stylesheets/lesshat.less
deleted file mode 100644
index 7c9f0ae86a267..0000000000000
--- a/packages/rocketchat-livechat/client/stylesheets/lesshat.less
+++ /dev/null
@@ -1,17 +0,0 @@
-// lesshat - The best mixin library in the world
-//
-// version: v4.1.0 (2016-07-19)
-
-.calc(...) {
- @process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- @state: 1; -lh-property: @process;
-}
-
-.transform(...) {
- @process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
- -webkit-transform: @process;
- -moz-transform: @process;
- -ms-transform: @process;
- -o-transform: @process;
- transform: @process;
-}
diff --git a/packages/rocketchat-livechat/client/stylesheets/livechat.less b/packages/rocketchat-livechat/client/stylesheets/livechat.less
index 7e268decb3fce..626d12b3cead8 100644
--- a/packages/rocketchat-livechat/client/stylesheets/livechat.less
+++ b/packages/rocketchat-livechat/client/stylesheets/livechat.less
@@ -1,5 +1,3 @@
-@import "lesshat.less";
-
@header-min-height: 30px;
@footer-min-height: 55px;
@link-font-color: #008ce3;
@@ -28,9 +26,11 @@
.trigger-value {
width: 70%;
- input {
- display: inline-block !important;
+ textarea, input, select {
+ display: block !important;
width: auto !important;
+ margin-bottom: 4px;
+ min-width: 50%;
}
}
@@ -237,11 +237,10 @@
display: block;
position: absolute;
top: -30px;
- left: 0;
+ left: calc(~'50% - 70px');
font-size: 10px;
font-weight: 600;
text-align: center;
- .calc(left, ~'50% - 70px');
color: @secondary-font-color;
z-index: 10;
padding: 0 10px;
@@ -424,10 +423,10 @@
left: 50%;
z-index: 5;
transition: transform 0.3s ease-out;
- .transform(translateY(-40px));
+ transform: translateY(-40px);
&.not {
- .transform(translateY(100%));
+ transform: translateY(100%);
}
}
@@ -439,10 +438,10 @@
padding: 5px;
z-index: 8;
transition: transform 0.2s ease-out;
- .transform(translateY(100%));
+ transform: translateY(100%);
&.show {
- .transform(translateY(0));
+ transform: translateY(0);
}
}
}
@@ -624,18 +623,13 @@
}
.livechat-section {
- opacity: 0.5;
- transition: opacity 0.4s ease;
-
- &.available {
- opacity: 1;
- }
+ margin-bottom: 22px;
}
.livechat-status {
- float: right;
- margin-right: 10px;
font-size: 20px;
+ line-height: 18px;
+ color: #9d9fa3;
}
.external-message {
diff --git a/packages/rocketchat-livechat/client/ui.js b/packages/rocketchat-livechat/client/ui.js
index 9842f10c2afb8..a2f95eb9c7054 100644
--- a/packages/rocketchat-livechat/client/ui.js
+++ b/packages/rocketchat-livechat/client/ui.js
@@ -1,6 +1,6 @@
AccountBox.addItem({
name: 'Livechat',
- icon: 'icon-chat-empty',
+ icon: 'livechat',
href: 'livechat-current-chats',
sideNav: 'livechatFlex',
condition: () => {
@@ -12,25 +12,16 @@ RocketChat.TabBar.addButton({
groups: ['live'],
id: 'visitor-info',
i18nTitle: 'Visitor_Info',
- icon: 'icon-info-circled',
+ icon: 'info-circled',
template: 'visitorInfo',
order: 0
});
-// RocketChat.TabBar.addButton({
-// groups: ['livechat'],
-// id: 'visitor-navigation',
-// i18nTitle: 'Visitor_Navigation',
-// icon: 'icon-history',
-// template: 'visitorNavigation',
-// order: 10
-// });
-
RocketChat.TabBar.addButton({
groups: ['live'],
id: 'visitor-history',
i18nTitle: 'Past_Chats',
- icon: 'icon-chat',
+ icon: 'chat',
template: 'visitorHistory',
order: 11
});
@@ -45,7 +36,7 @@ RocketChat.TabBar.addButton({
groups: ['live'],
id: 'external-search',
i18nTitle: 'Knowledge_Base',
- icon: 'icon-lightbulb',
+ icon: 'lightbulb',
template: 'externalSearch',
order: 10
});
diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.html b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.html
new file mode 100644
index 0000000000000..37e78533ca7ed
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.html
@@ -0,0 +1,39 @@
+
+
+
diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.js b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.js
new file mode 100644
index 0000000000000..1adf15706c3ee
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationFacebook.js
@@ -0,0 +1,151 @@
+Template.livechatIntegrationFacebook.helpers({
+ pages() {
+ return Template.instance().pages.get();
+ },
+ subscribed() {
+ return this.subscribed ? 'checked' : '';
+ },
+ enabled() {
+ return Template.instance().enabled.get();
+ },
+ hasToken() {
+ return Template.instance().hasToken.get();
+ },
+ enableButtonDisabled() {
+ return !Template.instance().hasToken.get() ? 'disabled' : '';
+ },
+ isLoading() {
+ return Template.instance().loading.get();
+ }
+});
+
+Template.livechatIntegrationFacebook.onCreated(function() {
+ this.enabled = new ReactiveVar(false);
+ this.hasToken = new ReactiveVar(false);
+ this.pages = new ReactiveVar([]);
+ this.loading = new ReactiveVar(false);
+
+ this.autorun(() => {
+ if (this.enabled.get()) {
+ this.loadPages();
+ }
+ });
+
+ this.result = (successFn, errorFn = () => {}) => {
+ return (error, result) => {
+ // fix the state where user it was enabled on admin
+ if (error && error.error) {
+ switch (error.error) {
+ case 'invalid-facebook-token':
+ case 'invalid-instance-url':
+ case 'integration-disabled':
+ return Meteor.call('livechat:facebook', { action: 'enable' }, this.result(() => {
+ this.enabled.set(true);
+ this.loadPages();
+ }, () => this.loadPages()));
+ }
+ }
+
+ if (result && result.success === false && (result.type === 'OAuthException' || typeof result.url !== 'undefined')) {
+ const oauthWindow = window.open(result.url, 'facebook-integration-oauth', 'width=600,height=400');
+
+ const checkInterval = setInterval(() => {
+ if (oauthWindow.closed) {
+ clearInterval(checkInterval);
+ errorFn(error);
+ }
+ }, 300);
+ return;
+ }
+ if (error) {
+ errorFn(error);
+ return modal.open({
+ title: t('Error_loading_pages'),
+ text: error.reason,
+ type: 'error'
+ });
+ }
+ successFn(result);
+ };
+ };
+
+ this.loadPages = () => {
+ this.pages.set([]);
+ this.loading.set(true);
+ Meteor.call('livechat:facebook', { action: 'list-pages' }, this.result((result) => {
+ this.pages.set(result.pages);
+ this.loading.set(false);
+ }, () => this.loading.set(false)));
+ };
+});
+
+Template.livechatIntegrationFacebook.onRendered(function() {
+ this.loading.set(true);
+ Meteor.call('livechat:facebook', { action: 'initialState' }, this.result((result) => {
+ this.enabled.set(result.enabled);
+ this.hasToken.set(result.hasToken);
+ this.loading.set(false);
+ }));
+});
+
+Template.livechatIntegrationFacebook.events({
+ 'click .reload'(event, instance) {
+ event.preventDefault();
+
+ instance.loadPages();
+ },
+ 'click .enable'(event, instance) {
+ event.preventDefault();
+
+ Meteor.call('livechat:facebook', { action: 'enable' }, instance.result(() => {
+ instance.enabled.set(true);
+ }, () => instance.enabled.set(true)));
+ },
+ 'click .disable'(event, instance) {
+ event.preventDefault();
+
+ modal.open({
+ title: t('Disable_Facebook_integration'),
+ text: t('Are_you_sure_you_want_to_disable_Facebook_integration'),
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#DD6B55',
+ confirmButtonText: t('Yes'),
+ cancelButtonText: t('Cancel'),
+ closeOnConfirm: false,
+ html: false
+ }, () => {
+ Meteor.call('livechat:facebook', { action: 'disable' }, (err) => {
+ if (err) {
+ return handleError(err);
+ }
+ instance.enabled.set(false);
+ instance.pages.set([]);
+
+ modal.open({
+ title: t('Disabled'),
+ text: t('Integration_disabled'),
+ type: 'success',
+ timer: 2000,
+ showConfirmButton: false
+ });
+ });
+ });
+ },
+ 'change [name=subscribe]'(event, instance) {
+ Meteor.call('livechat:facebook', {
+ action: !event.currentTarget.checked ? 'unsubscribe' : 'subscribe',
+ page: this.id
+ }, (err, result) => {
+ if (result.success) {
+ const pages = instance.pages.get();
+ pages.forEach(page => {
+ if (page.id === this.id) {
+ page.subscribed = event.currentTarget.checked;
+ }
+ });
+ instance.pages.set(pages);
+ }
+ });
+ }
+});
diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html
new file mode 100644
index 0000000000000..04bb8832d1ff9
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html
@@ -0,0 +1,43 @@
+
+ {{#requiresPermission 'view-livechat-manager'}}
+
+ {{/requiresPermission}}
+
diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js
new file mode 100644
index 0000000000000..2a56023283642
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js
@@ -0,0 +1,89 @@
+/* globals LivechatIntegration */
+import _ from 'underscore';
+import s from 'underscore.string';
+import toastr from 'toastr';
+
+Template.livechatIntegrationWebhook.helpers({
+ webhookUrl() {
+ const setting = LivechatIntegration.findOne('Livechat_webhookUrl');
+ return setting && setting.value;
+ },
+ secretToken() {
+ const setting = LivechatIntegration.findOne('Livechat_secret_token');
+ return setting && setting.value;
+ },
+ disableTest() {
+ return Template.instance().disableTest.get();
+ },
+ sendOnCloseChecked() {
+ const setting = LivechatIntegration.findOne('Livechat_webhook_on_close');
+ return setting && setting.value;
+ },
+ sendOnOfflineChecked() {
+ const setting = LivechatIntegration.findOne('Livechat_webhook_on_offline_msg');
+ return setting && setting.value;
+ }
+});
+
+Template.livechatIntegrationWebhook.onCreated(function() {
+ this.disableTest = new ReactiveVar(true);
+
+ this.autorun(() => {
+ const webhook = LivechatIntegration.findOne('Livechat_webhookUrl');
+ this.disableTest.set(!webhook || _.isEmpty(webhook.value));
+ });
+
+ this.subscribe('livechat:integration');
+});
+
+Template.livechatIntegrationWebhook.events({
+ 'change #webhookUrl, blur #webhookUrl'(e, instance) {
+ const setting = LivechatIntegration.findOne('Livechat_webhookUrl');
+ instance.disableTest.set(!setting || e.currentTarget.value !== setting.value);
+ },
+ 'click .test'(e, instance) {
+ if (!instance.disableTest.get()) {
+ Meteor.call('livechat:webhookTest', (err) => {
+ if (err) {
+ return handleError(err);
+ }
+ modal.open({
+ title: t('It_works'),
+ type: 'success',
+ timer: 2000
+ });
+ });
+ }
+ },
+ 'click .reset-settings'(e, instance) {
+ e.preventDefault();
+
+ const webhookUrl = LivechatIntegration.findOne('Livechat_webhookUrl');
+ const secretToken = LivechatIntegration.findOne('Livechat_secret_token');
+ const webhookOnClose = LivechatIntegration.findOne('Livechat_webhook_on_close');
+ const webhookOnOfflineMsg = LivechatIntegration.findOne('Livechat_webhook_on_offline_msg');
+
+ instance.$('#webhookUrl').val(webhookUrl && webhookUrl.value);
+ instance.$('#secretToken').val(secretToken && secretToken.value);
+ instance.$('#sendOnClose').get(0).checked = webhookOnClose && webhookOnClose.value;
+ instance.$('#sendOnOffline').get(0).checked = webhookOnOfflineMsg && webhookOnOfflineMsg.value;
+
+ instance.disableTest.set(!webhookUrl || _.isEmpty(webhookUrl.value));
+ },
+ 'submit .rocket-form'(e, instance) {
+ e.preventDefault();
+
+ const settings = {
+ 'Livechat_webhookUrl': s.trim(instance.$('#webhookUrl').val()),
+ 'Livechat_secret_token': s.trim(instance.$('#secretToken').val()),
+ 'Livechat_webhook_on_close': instance.$('#sendOnClose').get(0).checked,
+ 'Livechat_webhook_on_offline_msg': instance.$('#sendOnOffline').get(0).checked
+ };
+ Meteor.call('livechat:saveIntegration', settings, (err) => {
+ if (err) {
+ return handleError(err);
+ }
+ toastr.success(t('Saved'));
+ });
+ }
+});
diff --git a/packages/rocketchat-livechat/client/views/app/livechatAppearance.html b/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
index 5003b79a96049..03fdaf1731f74 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
@@ -8,15 +8,24 @@ {{_ "Settings"}}
{{_ "Livechat_online"}}
{{_ "Title"}}
-
+
+
{{_ "Livechat_offline"}}
@@ -31,30 +40,30 @@ {{_ "Settings"}}
{{_ "Offline_form_unavailable_message"}}
-
+
{{_ "Offline_message"}}
-
+
{{_ "Title_offline"}}
-
+
{{_ "Email_address_to_send_offline_messages"}}
-
+
{{_ "Offline_success_message"}}
-
+
@@ -112,7 +121,7 @@
{{sampleTitle}}
@@ -123,11 +132,11 @@ {{sampleTitle}}
{{{sampleOfflineMessage}}}