Port 7.7 - WIP
This commit is contained in:
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
root=true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
|
||||
indent_size = 4
|
||||
@@ -15,6 +15,7 @@
|
||||
<section name="BaseRestExtensions" type="Umbraco.Core.Configuration.BaseRest.BaseRestSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="FileSystemProviders" type="Umbraco.Core.Configuration.FileSystemProvidersSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="dashBoard" type="Umbraco.Core.Configuration.Dashboard.DashboardSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
@@ -30,6 +31,7 @@
|
||||
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<FileSystemProviders configSource="config\FileSystemProviders.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<dashBoard configSource="config\Dashboard.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<HealthChecks configSource="config\HealthChecks.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
</umbracoConfiguration>
|
||||
|
||||
<FileSystemProviders xdt:Transform="Remove" />
|
||||
@@ -366,19 +368,19 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
|
||||
@@ -92,15 +92,16 @@
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
<!--Users-->
|
||||
<add application="users" alias="users" title="Users" type="umbraco.loadUsers, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0"
|
||||
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="users" alias="userTypes"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="users" alias="userTypes" title="User Types" type="umbraco.cms.presentation.Trees.UserTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1"
|
||||
xdt:Transform="Remove" />
|
||||
<add application="users" alias="userPermissions"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="users" alias="userPermissions" title="User Permissions" type="umbraco.cms.presentation.Trees.UserPermissions, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
<!--Members-->
|
||||
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco"
|
||||
|
||||
@@ -53,7 +53,9 @@ namespace Umbraco.Core.Cache
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserCacheKey = "UmbracoUser";
|
||||
|
||||
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string ContentTypeCacheKey = "UmbracoContentType";
|
||||
@@ -85,7 +87,7 @@ namespace Umbraco.Core.Cache
|
||||
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
|
||||
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
|
||||
|
||||
public const string IdToKeyCacheKey = "UI2K";
|
||||
public const string KeyToIdCacheKey = "UK2I";
|
||||
public const string IdToKeyCacheKey = "UI2K__";
|
||||
public const string KeyToIdCacheKey = "UK2I__";
|
||||
}
|
||||
}
|
||||
|
||||
35
src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs
Normal file
35
src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal class ActionMetadataAttribute : Attribute
|
||||
{
|
||||
public string Category { get; }
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign a Category, since no name is assigned it will try to be translated from the language files based on the action's alias
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
public ActionMetadataAttribute(string category)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
|
||||
Category = category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign an explicit name and category
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="name"></param>
|
||||
public ActionMetadataAttribute(string category, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
Category = category;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net.Configuration;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
@@ -44,7 +45,6 @@ namespace Umbraco.Core.Configuration
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
private const string StaticReservedPaths = "~/app_plugins/,~/install/,";
|
||||
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -55,6 +55,7 @@ namespace Umbraco.Core.Configuration
|
||||
_reservedUrlsCache = null;
|
||||
_reservedPaths = null;
|
||||
_reservedUrls = null;
|
||||
HasSmtpServer = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,6 +67,25 @@ namespace Umbraco.Core.Configuration
|
||||
ResetInternal();
|
||||
}
|
||||
|
||||
public static bool HasSmtpServerConfigured(string appPath)
|
||||
{
|
||||
if (HasSmtpServer.HasValue) return HasSmtpServer.Value;
|
||||
|
||||
var config = WebConfigurationManager.OpenWebConfiguration(appPath);
|
||||
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
|
||||
if (settings == null || settings.Smtp == null) return false;
|
||||
if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false)
|
||||
return true;
|
||||
if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For testing only
|
||||
/// </summary>
|
||||
internal static bool? HasSmtpServer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reserved urls from web.config.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class DisabledHealthCheckElement : ConfigurationElement, IDisabledHealthCheck
|
||||
{
|
||||
private const string IdKey = "id";
|
||||
private const string DisabledOnKey = "disabledOn";
|
||||
private const string DisabledByKey = "disabledBy";
|
||||
|
||||
[ConfigurationProperty(IdKey, IsKey = true, IsRequired = true)]
|
||||
public Guid Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((Guid)(base[IdKey]));
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledOnKey, IsKey = false, IsRequired = false)]
|
||||
public DateTime DisabledOn
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((DateTime)(base[DisabledOnKey]));
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledByKey, IsKey = false, IsRequired = false)]
|
||||
public int DisabledBy
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((int)(base[DisabledByKey]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(DisabledHealthCheckElement), AddItemName = "check")]
|
||||
public class DisabledHealthChecksElementCollection : ConfigurationElementCollection, IEnumerable<IDisabledHealthCheck>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new DisabledHealthCheckElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((DisabledHealthCheckElement)(element)).Id;
|
||||
}
|
||||
|
||||
public new DisabledHealthCheckElement this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DisabledHealthCheckElement)BaseGet(key);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<IDisabledHealthCheck> IEnumerable<IDisabledHealthCheck>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as DisabledHealthCheckElement;
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class HealthCheckNotificationSettingsElement : ConfigurationElement, IHealthCheckNotificationSettings
|
||||
{
|
||||
private const string EnabledKey = "enabled";
|
||||
private const string FirstRunTimeKey = "firstRunTime";
|
||||
private const string PeriodKey = "periodInHours";
|
||||
private const string NotificationMethodsKey = "notificationMethods";
|
||||
private const string DisabledChecksKey = "disabledChecks";
|
||||
|
||||
[ConfigurationProperty(EnabledKey, IsRequired = true)]
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[EnabledKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(FirstRunTimeKey, IsRequired = false)]
|
||||
public string FirstRunTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[FirstRunTimeKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(PeriodKey, IsRequired = true)]
|
||||
public int PeriodInHours
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)base[PeriodKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(NotificationMethodsKey, IsDefaultCollection = true, IsRequired = false)]
|
||||
public NotificationMethodsElementCollection NotificationMethods
|
||||
{
|
||||
get
|
||||
{
|
||||
return (NotificationMethodsElementCollection)base[NotificationMethodsKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledChecksKey, IsDefaultCollection = false, IsRequired = false)]
|
||||
public DisabledHealthChecksElementCollection DisabledChecks
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DisabledHealthChecksElementCollection)base[DisabledChecksKey];
|
||||
}
|
||||
}
|
||||
|
||||
bool IHealthCheckNotificationSettings.Enabled
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
string IHealthCheckNotificationSettings.FirstRunTime
|
||||
{
|
||||
get { return FirstRunTime; }
|
||||
}
|
||||
|
||||
int IHealthCheckNotificationSettings.PeriodInHours
|
||||
{
|
||||
get { return PeriodInHours; }
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, INotificationMethod> IHealthCheckNotificationSettings.NotificationMethods
|
||||
{
|
||||
get { return NotificationMethods; }
|
||||
}
|
||||
|
||||
IEnumerable<IDisabledHealthCheck> IHealthCheckNotificationSettings.DisabledChecks
|
||||
{
|
||||
get { return DisabledChecks; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public enum HealthCheckNotificationVerbosity
|
||||
{
|
||||
Summary,
|
||||
Detailed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class HealthChecksSection : ConfigurationSection, IHealthChecks
|
||||
{
|
||||
private const string DisabledChecksKey = "disabledChecks";
|
||||
private const string NotificationSettingsKey = "notificationSettings";
|
||||
|
||||
[ConfigurationProperty(DisabledChecksKey)]
|
||||
public DisabledHealthChecksElementCollection DisabledChecks
|
||||
{
|
||||
get { return ((DisabledHealthChecksElementCollection)(base[DisabledChecksKey])); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty(NotificationSettingsKey, IsRequired = true)]
|
||||
public HealthCheckNotificationSettingsElement NotificationSettings
|
||||
{
|
||||
get { return ((HealthCheckNotificationSettingsElement)(base[NotificationSettingsKey])); }
|
||||
}
|
||||
|
||||
IEnumerable<IDisabledHealthCheck> IHealthChecks.DisabledChecks
|
||||
{
|
||||
get { return DisabledChecks; }
|
||||
}
|
||||
|
||||
IHealthCheckNotificationSettings IHealthChecks.NotificationSettings
|
||||
{
|
||||
get { return NotificationSettings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IDisabledHealthCheck
|
||||
{
|
||||
Guid Id { get; }
|
||||
DateTime DisabledOn { get; }
|
||||
int DisabledBy { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IHealthCheckNotificationSettings
|
||||
{
|
||||
bool Enabled { get; }
|
||||
string FirstRunTime { get; }
|
||||
int PeriodInHours { get; }
|
||||
IReadOnlyDictionary<string, INotificationMethod> NotificationMethods { get; }
|
||||
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs
Normal file
10
src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IHealthChecks
|
||||
{
|
||||
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
|
||||
IHealthCheckNotificationSettings NotificationSettings { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface INotificationMethod
|
||||
{
|
||||
string Alias { get; }
|
||||
bool Enabled { get; }
|
||||
HealthCheckNotificationVerbosity Verbosity { get; }
|
||||
bool FailureOnly { get; }
|
||||
IReadOnlyDictionary<string, INotificationMethodSettings> Settings { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface INotificationMethodSettings
|
||||
{
|
||||
string Key { get; }
|
||||
string Value { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class NotificationMethodElement : ConfigurationElement, INotificationMethod
|
||||
{
|
||||
private const string AliasKey = "alias";
|
||||
private const string EnabledKey = "enabled";
|
||||
private const string VerbosityKey = "verbosity";
|
||||
private const string FailureonlyKey = "failureOnly";
|
||||
private const string SettingsKey = "settings";
|
||||
|
||||
[ConfigurationProperty(AliasKey, IsKey = true, IsRequired = true)]
|
||||
public string Alias
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[AliasKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(EnabledKey, IsKey = true, IsRequired = true)]
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[EnabledKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(VerbosityKey, IsRequired = true)]
|
||||
public HealthCheckNotificationVerbosity Verbosity
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HealthCheckNotificationVerbosity)base[VerbosityKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(FailureonlyKey, IsRequired = false)]
|
||||
public bool FailureOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[FailureonlyKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(SettingsKey, IsDefaultCollection = true, IsRequired = false)]
|
||||
public NotificationMethodSettingsElementCollection Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
return (NotificationMethodSettingsElementCollection)base[SettingsKey];
|
||||
}
|
||||
}
|
||||
|
||||
string INotificationMethod.Alias
|
||||
{
|
||||
get { return Alias; }
|
||||
}
|
||||
|
||||
bool INotificationMethod.Enabled
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
HealthCheckNotificationVerbosity INotificationMethod.Verbosity
|
||||
{
|
||||
get { return Verbosity; }
|
||||
}
|
||||
|
||||
bool INotificationMethod.FailureOnly
|
||||
{
|
||||
get { return FailureOnly; }
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, INotificationMethodSettings> INotificationMethod.Settings
|
||||
{
|
||||
get { return Settings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class NotificationMethodSettingsElement : ConfigurationElement, INotificationMethodSettings
|
||||
{
|
||||
private const string KeyKey = "key";
|
||||
private const string ValueKey = "value";
|
||||
|
||||
[ConfigurationProperty(KeyKey, IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[KeyKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(ValueKey, IsRequired = true)]
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[ValueKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(NotificationMethodSettingsElement), AddItemName = "add")]
|
||||
public class NotificationMethodSettingsElementCollection : ConfigurationElementCollection, IEnumerable<INotificationMethodSettings>, IReadOnlyDictionary<string, INotificationMethodSettings>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new NotificationMethodSettingsElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((NotificationMethodSettingsElement)(element)).Key;
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, INotificationMethodSettings>> IEnumerable<KeyValuePair<string, INotificationMethodSettings>>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var val = (NotificationMethodSettingsElement)BaseGet(i);
|
||||
var key = (string)BaseGetKey(i);
|
||||
yield return new KeyValuePair<string, INotificationMethodSettings>(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<INotificationMethodSettings> IEnumerable<INotificationMethodSettings>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodSettingsElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethodSettings>.ContainsKey(string key)
|
||||
{
|
||||
return ((IReadOnlyDictionary<string, INotificationMethodSettings>)this).Keys.Any(x => x == key);
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethodSettings>.TryGetValue(string key, out INotificationMethodSettings value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = (NotificationMethodSettingsElement)BaseGet(key);
|
||||
value = val;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INotificationMethodSettings IReadOnlyDictionary<string, INotificationMethodSettings>.this[string key]
|
||||
{
|
||||
get { return (NotificationMethodSettingsElement)BaseGet(key); }
|
||||
}
|
||||
|
||||
IEnumerable<string> IReadOnlyDictionary<string, INotificationMethodSettings>.Keys
|
||||
{
|
||||
get { return BaseGetAllKeys().Cast<string>(); }
|
||||
}
|
||||
|
||||
IEnumerable<INotificationMethodSettings> IReadOnlyDictionary<string, INotificationMethodSettings>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodSettingsElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(NotificationMethodElement), AddItemName = "notificationMethod")]
|
||||
public class NotificationMethodsElementCollection : ConfigurationElementCollection, IEnumerable<INotificationMethod>, IReadOnlyDictionary<string, INotificationMethod>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new NotificationMethodElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((NotificationMethodElement)(element)).Alias;
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, INotificationMethod>> IEnumerable<KeyValuePair<string, INotificationMethod>>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var val = (NotificationMethodElement)BaseGet(i);
|
||||
var key = (string)BaseGetKey(i);
|
||||
yield return new KeyValuePair<string, INotificationMethod>(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<INotificationMethod> IEnumerable<INotificationMethod>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethod>.ContainsKey(string key)
|
||||
{
|
||||
return ((IReadOnlyDictionary<string, INotificationMethod>) this).Keys.Any(x => x == key);
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethod>.TryGetValue(string key, out INotificationMethod value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = (NotificationMethodElement)BaseGet(key);
|
||||
value = val;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INotificationMethod IReadOnlyDictionary<string, INotificationMethod>.this[string key]
|
||||
{
|
||||
get { return (NotificationMethodElement)BaseGet(key); }
|
||||
}
|
||||
|
||||
IEnumerable<string> IReadOnlyDictionary<string, INotificationMethod>.Keys
|
||||
{
|
||||
get { return BaseGetAllKeys().Cast<string>(); }
|
||||
}
|
||||
|
||||
IEnumerable<INotificationMethod> IReadOnlyDictionary<string, INotificationMethod>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.Dashboard;
|
||||
using Umbraco.Core.Configuration.Grid;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -53,6 +54,12 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
SetDashboardSettings(dashboardConfig);
|
||||
}
|
||||
|
||||
if (_healthChecks == null)
|
||||
{
|
||||
var healthCheckConfig = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as IHealthChecks;
|
||||
SetHealthCheckSettings(healthCheckConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,16 +67,34 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
/// <param name="umbracoSettings"></param>
|
||||
/// <param name="dashboardSettings"></param>
|
||||
public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IDashboardSection dashboardSettings)
|
||||
/// <param name="healthChecks"></param>
|
||||
public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IDashboardSection dashboardSettings, IHealthChecks healthChecks)
|
||||
{
|
||||
SetHealthCheckSettings(healthChecks);
|
||||
SetUmbracoSettings(umbracoSettings);
|
||||
SetDashboardSettings(dashboardSettings);
|
||||
}
|
||||
|
||||
private IHealthChecks _healthChecks;
|
||||
private IDashboardSection _dashboardSection;
|
||||
private IUmbracoSettingsSection _umbracoSettings;
|
||||
private IGridConfig _gridConfig;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IHealthCheck config
|
||||
/// </summary>
|
||||
public IHealthChecks HealthCheck()
|
||||
{
|
||||
if (_healthChecks == null)
|
||||
{
|
||||
var ex = new ConfigurationErrorsException("Could not load the " + typeof(IHealthChecks) + " from config file, ensure the web.config and healthchecks.config files are formatted correctly");
|
||||
LogHelper.Error<UmbracoConfig>("Config error", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return _healthChecks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IDashboardSection
|
||||
/// </summary>
|
||||
@@ -89,11 +114,20 @@ namespace Umbraco.Core.Configuration
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
internal void SetDashboardSettings(IDashboardSection value)
|
||||
public void SetDashboardSettings(IDashboardSection value)
|
||||
{
|
||||
_dashboardSection = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetHealthCheckSettings(IHealthChecks value)
|
||||
{
|
||||
_healthChecks = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
public interface ILink
|
||||
{
|
||||
string Application { get; }
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool ConvertUrlsToAscii { get; }
|
||||
|
||||
bool TryConvertUrlsToAscii { get; }
|
||||
|
||||
IEnumerable<IChar> CharCollection { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
|
||||
{
|
||||
|
||||
@@ -111,7 +111,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool IRequestHandlerSection.ConvertUrlsToAscii
|
||||
{
|
||||
get { return UrlReplacing.ConvertUrlsToAscii; }
|
||||
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); }
|
||||
}
|
||||
|
||||
bool IRequestHandlerSection.TryConvertUrlsToAscii
|
||||
{
|
||||
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); }
|
||||
}
|
||||
|
||||
IEnumerable<IChar> IRequestHandlerSection.CharCollection
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return (bool) base["removeDoubleDashes"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("toAscii", DefaultValue = false)]
|
||||
internal bool ConvertUrlsToAscii
|
||||
[ConfigurationProperty("toAscii", DefaultValue = "false")]
|
||||
internal string ConvertUrlsToAscii
|
||||
{
|
||||
get { return (bool)base["toAscii"]; }
|
||||
get { return (string) base["toAscii"]; }
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(CharCollection), AddItemName = "char")]
|
||||
|
||||
@@ -4,7 +4,7 @@ using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
{
|
||||
private readonly MetaData _packageMetaData;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
public class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
public UninstallPackageEventArgs(TEntity eventObject, bool canCancel)
|
||||
: base(new[] { eventObject }, canCancel)
|
||||
|
||||
@@ -109,6 +109,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string MapPath(string path, bool useHttpContext)
|
||||
{
|
||||
if (path == null) throw new ArgumentNullException("path");
|
||||
|
||||
// Check if the path is already mapped
|
||||
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
|
||||
|| path.StartsWith(@"\\")) //UNC Paths start with "\\". If the site is running off a network drive mapped paths will look like "\\Whatever\Boo\Bar"
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
if (IsPropertyDirty("CreateDate") == false || _createDate == default(DateTime))
|
||||
CreateDate = DateTime.Now;
|
||||
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
|
||||
UpdateDate = CreateDate;
|
||||
UpdateDate = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -127,6 +127,10 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
|
||||
UpdateDate = DateTime.Now;
|
||||
|
||||
//this is just in case
|
||||
if (_createDate == default(DateTime))
|
||||
CreateDate = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
8
src/Umbraco.Core/Models/EntityBase/EntityPath.cs
Normal file
8
src/Umbraco.Core/Models/EntityBase/EntityPath.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
public class EntityPath
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,67 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class BackOfficeIdentityUser : IdentityUser<int, IIdentityUserLogin, IdentityUserRole<string>, IdentityUserClaim<int>>
|
||||
public class BackOfficeIdentityUser : IdentityUser<int, IIdentityUserLogin, IdentityUserRole<string>, IdentityUserClaim<int>>, IRememberBeingDirty
|
||||
{
|
||||
|
||||
public BackOfficeIdentityUser()
|
||||
/// <summary>
|
||||
/// Used to construct a new instance without an identity
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="email">This is allowed to be null (but would need to be filled in if trying to persist this instance)</param>
|
||||
/// <param name="culture"></param>
|
||||
/// <returns></returns>
|
||||
public static BackOfficeIdentityUser CreateNew(string username, string email, string culture)
|
||||
{
|
||||
StartMediaId = -1;
|
||||
StartContentId = -1;
|
||||
Culture = Configuration.GlobalSettings.DefaultUILanguage;
|
||||
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username");
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", "culture");
|
||||
|
||||
var user = new BackOfficeIdentityUser();
|
||||
user.DisableChangeTracking();
|
||||
user._userName = username;
|
||||
user._email = email;
|
||||
//we are setting minvalue here because the default is "0" which is the id of the admin user
|
||||
//which we cannot allow because the admin user will always exist
|
||||
user._id = int.MinValue;
|
||||
user._hasIdentity = false;
|
||||
user._culture = culture;
|
||||
user.EnableChangeTracking();
|
||||
return user;
|
||||
}
|
||||
|
||||
private BackOfficeIdentityUser()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an existing user with the specified groups
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groups"></param>
|
||||
public BackOfficeIdentityUser(int userId, IEnumerable<IReadOnlyUserGroup> groups)
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_culture = Configuration.GlobalSettings.DefaultUILanguage;
|
||||
_groups = groups.ToArray();
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>(_groups.Select(x => new IdentityUserRole<string>
|
||||
{
|
||||
RoleId = x.Alias,
|
||||
UserId = userId.ToString()
|
||||
}));
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
}
|
||||
|
||||
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
|
||||
@@ -27,16 +73,155 @@ namespace Umbraco.Core.Models.Identity
|
||||
return userIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if an Id has been set on this object this will be false if the object is new and not peristed to the database
|
||||
/// </summary>
|
||||
public bool HasIdentity
|
||||
{
|
||||
get { return _hasIdentity; }
|
||||
}
|
||||
|
||||
public int[] CalculatedMediaStartNodeIds { get; internal set; }
|
||||
public int[] CalculatedContentStartNodeIds { get; internal set; }
|
||||
|
||||
public override int Id
|
||||
{
|
||||
get { return _id; }
|
||||
set
|
||||
{
|
||||
_id = value;
|
||||
_hasIdentity = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override Email so we can track changes to it
|
||||
/// </summary>
|
||||
public override string Email
|
||||
{
|
||||
get { return _email; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _email, Ps.Value.EmailSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override UserName so we can track changes to it
|
||||
/// </summary>
|
||||
public override string UserName
|
||||
{
|
||||
get { return _userName; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _userName, Ps.Value.UserNameSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override LastLoginDateUtc so we can track changes to it
|
||||
/// </summary>
|
||||
public override DateTime? LastLoginDateUtc
|
||||
{
|
||||
get { return _lastLoginDateUtc; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _lastLoginDateUtc, Ps.Value.LastLoginDateUtcSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override EmailConfirmed so we can track changes to it
|
||||
/// </summary>
|
||||
public override bool EmailConfirmed
|
||||
{
|
||||
get { return _emailConfirmed; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _emailConfirmed, Ps.Value.EmailConfirmedSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the user's real name
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
public int StartContentId { get; set; }
|
||||
public int StartMediaId { get; set; }
|
||||
public string[] AllowedSections { get; set; }
|
||||
public string Culture { get; set; }
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
|
||||
}
|
||||
|
||||
public string UserTypeAlias { get; set; }
|
||||
/// <summary>
|
||||
/// Override AccessFailedCount so we can track changes to it
|
||||
/// </summary>
|
||||
public override int AccessFailedCount
|
||||
{
|
||||
get { return _accessFailedCount; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _accessFailedCount, Ps.Value.AccessFailedCountSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override PasswordHash so we can track changes to it
|
||||
/// </summary>
|
||||
public override string PasswordHash
|
||||
{
|
||||
get { return _passwordHash; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _passwordHash, Ps.Value.PasswordHashSelector); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Content start nodes assigned to the User (not ones assigned to the user's groups)
|
||||
/// </summary>
|
||||
public int[] StartContentIds
|
||||
{
|
||||
get { return _startContentIds; }
|
||||
set
|
||||
{
|
||||
if (value == null) value = new int[0];
|
||||
_tracker.SetPropertyValueAndDetectChanges(value, ref _startContentIds, Ps.Value.StartContentIdsSelector, Ps.Value.StartIdsComparer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Media start nodes assigned to the User (not ones assigned to the user's groups)
|
||||
/// </summary>
|
||||
public int[] StartMediaIds
|
||||
{
|
||||
get { return _startMediaIds; }
|
||||
set
|
||||
{
|
||||
if (value == null) value = new int[0];
|
||||
_tracker.SetPropertyValueAndDetectChanges(value, ref _startMediaIds, Ps.Value.StartMediaIdsSelector, Ps.Value.StartIdsComparer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a readonly list of the user's allowed sections which are based on it's user groups
|
||||
/// </summary>
|
||||
public string[] AllowedSections
|
||||
{
|
||||
get { return _allowedSections ?? (_allowedSections = _groups.SelectMany(x => x.AllowedSections).Distinct().ToArray()); }
|
||||
}
|
||||
|
||||
public string Culture
|
||||
{
|
||||
get { return _culture; }
|
||||
set { _tracker.SetPropertyValueAndDetectChanges(value, ref _culture, Ps.Value.CultureSelector); }
|
||||
}
|
||||
|
||||
public IReadOnlyUserGroup[] Groups
|
||||
{
|
||||
get { return _groups; }
|
||||
set
|
||||
{
|
||||
//so they recalculate
|
||||
_allowedSections = null;
|
||||
|
||||
//now clear all roles and re-add them
|
||||
_roles.CollectionChanged -= _roles_CollectionChanged;
|
||||
_roles.Clear();
|
||||
foreach (var identityUserRole in _groups.Select(x => new IdentityUserRole<string>
|
||||
{
|
||||
RoleId = x.Alias,
|
||||
UserId = Id.ToString()
|
||||
}))
|
||||
{
|
||||
_roles.Add(identityUserRole);
|
||||
}
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
|
||||
_tracker.SetPropertyValueAndDetectChanges(value, ref _groups, Ps.Value.GroupsSelector, Ps.Value.GroupsComparer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is always enabled
|
||||
@@ -83,15 +268,41 @@ namespace Umbraco.Core.Models.Identity
|
||||
}
|
||||
}
|
||||
|
||||
public bool LoginsChanged { get; private set; }
|
||||
|
||||
void Logins_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
LoginsChanged = true;
|
||||
_tracker.OnPropertyChanged(Ps.Value.LoginsSelector);
|
||||
}
|
||||
|
||||
private ObservableCollection<IIdentityUserLogin> _logins;
|
||||
private Lazy<IEnumerable<IIdentityUserLogin>> _getLogins;
|
||||
private void _roles_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
_tracker.OnPropertyChanged(Ps.Value.RolesSelector);
|
||||
}
|
||||
|
||||
private readonly ObservableCollection<IdentityUserRole<string>> _roles;
|
||||
|
||||
/// <summary>
|
||||
/// helper method to easily add a role without having to deal with IdentityUserRole{T}
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <remarks>
|
||||
/// Adding a role this way will not reflect on the user's group's collection or it's allowed sections until the user is persisted
|
||||
/// </remarks>
|
||||
public void AddRole(string role)
|
||||
{
|
||||
Roles.Add(new IdentityUserRole<string>
|
||||
{
|
||||
UserId = this.Id.ToString(),
|
||||
RoleId = role
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override Roles because the value of these are the user's group aliases
|
||||
/// </summary>
|
||||
public override ICollection<IdentityUserRole<string>> Roles
|
||||
{
|
||||
get { return _roles; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to set a lazy call back to populate the user's Login list
|
||||
@@ -102,5 +313,127 @@ namespace Umbraco.Core.Models.Identity
|
||||
if (callback == null) throw new ArgumentNullException("callback");
|
||||
_getLogins = callback;
|
||||
}
|
||||
|
||||
#region Change tracking
|
||||
|
||||
public void DisableChangeTracking()
|
||||
{
|
||||
_tracker.DisableChangeTracking();
|
||||
}
|
||||
|
||||
public void EnableChangeTracking()
|
||||
{
|
||||
_tracker.EnableChangeTracking();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Since this class only has change tracking turned on for Email/Username this will return true if either of those have changed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsDirty()
|
||||
{
|
||||
return _tracker.IsDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified property is dirty
|
||||
/// </summary>
|
||||
/// <param name="propName"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsPropertyDirty(string propName)
|
||||
{
|
||||
return _tracker.IsPropertyDirty(propName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets dirty properties
|
||||
/// </summary>
|
||||
void ICanBeDirty.ResetDirtyProperties()
|
||||
{
|
||||
_tracker.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
bool IRememberBeingDirty.WasDirty()
|
||||
{
|
||||
return _tracker.WasDirty();
|
||||
}
|
||||
|
||||
bool IRememberBeingDirty.WasPropertyDirty(string propertyName)
|
||||
{
|
||||
return _tracker.WasPropertyDirty(propertyName);
|
||||
}
|
||||
|
||||
void IRememberBeingDirty.ForgetPreviouslyDirtyProperties()
|
||||
{
|
||||
_tracker.ForgetPreviouslyDirtyProperties();
|
||||
}
|
||||
|
||||
public void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
_tracker.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
private class PropertySelectors
|
||||
{
|
||||
public readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, string>(x => x.Email);
|
||||
public readonly PropertyInfo UserNameSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, string>(x => x.UserName);
|
||||
public readonly PropertyInfo LastLoginDateUtcSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, DateTime?>(x => x.LastLoginDateUtc);
|
||||
public readonly PropertyInfo EmailConfirmedSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, bool>(x => x.EmailConfirmed);
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, string>(x => x.Name);
|
||||
public readonly PropertyInfo AccessFailedCountSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, int>(x => x.AccessFailedCount);
|
||||
public readonly PropertyInfo PasswordHashSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, string>(x => x.PasswordHash);
|
||||
public readonly PropertyInfo CultureSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, string>(x => x.Culture);
|
||||
public readonly PropertyInfo StartMediaIdsSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, int[]>(x => x.StartMediaIds);
|
||||
public readonly PropertyInfo StartContentIdsSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, int[]>(x => x.StartContentIds);
|
||||
public readonly PropertyInfo GroupsSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, IReadOnlyUserGroup[]>(x => x.Groups);
|
||||
public readonly PropertyInfo LoginsSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, IEnumerable<IIdentityUserLogin>>(x => x.Logins);
|
||||
public readonly PropertyInfo RolesSelector = ExpressionHelper.GetPropertyInfo<BackOfficeIdentityUser, IEnumerable<IdentityUserRole<string>>>(x => x.Roles);
|
||||
|
||||
//Custom comparer for enumerables
|
||||
public readonly DelegateEqualityComparer<IReadOnlyUserGroup[]> GroupsComparer = new DelegateEqualityComparer<IReadOnlyUserGroup[]>(
|
||||
(groups, enumerable) => groups.Select(x => x.Alias).UnsortedSequenceEqual(enumerable.Select(x => x.Alias)),
|
||||
groups => groups.GetHashCode());
|
||||
public readonly DelegateEqualityComparer<int[]> StartIdsComparer = new DelegateEqualityComparer<int[]>(
|
||||
(groups, enumerable) => groups.UnsortedSequenceEqual(enumerable),
|
||||
groups => groups.GetHashCode());
|
||||
|
||||
}
|
||||
|
||||
private readonly ChangeTracker _tracker = new ChangeTracker();
|
||||
private string _email;
|
||||
private string _userName;
|
||||
private int _id;
|
||||
private bool _hasIdentity = false;
|
||||
private DateTime? _lastLoginDateUtc;
|
||||
private bool _emailConfirmed;
|
||||
private string _name;
|
||||
private int _accessFailedCount;
|
||||
private string _passwordHash;
|
||||
private string _culture;
|
||||
private ObservableCollection<IIdentityUserLogin> _logins;
|
||||
private Lazy<IEnumerable<IIdentityUserLogin>> _getLogins;
|
||||
private IReadOnlyUserGroup[] _groups;
|
||||
private string[] _allowedSections;
|
||||
private int[] _startMediaIds;
|
||||
private int[] _startContentIds;
|
||||
|
||||
/// <summary>
|
||||
/// internal class used to track changes for properties that have it enabled
|
||||
/// </summary>
|
||||
private class ChangeTracker : TracksChangesEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Make this public so that it's usable
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo"></param>
|
||||
public new void OnPropertyChanged(PropertyInfo propertyInfo)
|
||||
{
|
||||
base.OnPropertyChanged(propertyInfo);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class IdentityProfile : Profile
|
||||
{
|
||||
public IdentityProfile(ILocalizedTextService textService)
|
||||
public IdentityProfile(ILocalizedTextService textService, IEntityService entityService)
|
||||
{
|
||||
CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.BeforeMap((src, dest) =>
|
||||
{
|
||||
dest.DisableChangeTracking();
|
||||
})
|
||||
.ConstructUsing(src => new BackOfficeIdentityUser(src.Id, src.Groups))
|
||||
.ForMember(dest => dest.LastLoginDateUtc, opt => opt.MapFrom(src => src.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
|
||||
.ForMember(dest => dest.EmailConfirmed, opt => opt.MapFrom(src => src.EmailConfirmedDate.HasValue))
|
||||
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
|
||||
.ForMember(dest => dest.LockoutEndDateUtc, opt => opt.MapFrom(src => src.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null))
|
||||
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Username))
|
||||
.ForMember(dest => dest.PasswordHash, opt => opt.MapFrom(user => GetPasswordHash(user.RawPasswordValue)))
|
||||
.ForMember(dest => dest.Culture, opt => opt.MapFrom(src => src.GetUserCulture(textService)))
|
||||
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
|
||||
.ForMember(dest => dest.StartMediaId, opt => opt.MapFrom(src => src.StartMediaId))
|
||||
.ForMember(dest => dest.StartContentId, opt => opt.MapFrom(src => src.StartContentId))
|
||||
.ForMember(dest => dest.UserTypeAlias, opt => opt.MapFrom(src => src.UserType.Alias))
|
||||
.ForMember(dest => dest.StartMediaIds, opt => opt.MapFrom(src => src.StartMediaIds))
|
||||
.ForMember(dest => dest.StartContentIds, opt => opt.MapFrom(src => src.StartContentIds))
|
||||
.ForMember(dest => dest.AccessFailedCount, opt => opt.MapFrom(src => src.FailedPasswordAttempts))
|
||||
.ForMember(dest => dest.CalculatedContentStartNodeIds, opt => opt.MapFrom(src => src.CalculateContentStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.CalculatedMediaStartNodeIds, opt => opt.MapFrom(src => src.CalculateMediaStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.AllowedSections, opt => opt.MapFrom(src => src.AllowedSections.ToArray()))
|
||||
.ForMember(dest => dest.LockoutEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Logins, opt => opt.Ignore())
|
||||
@@ -33,12 +42,21 @@ namespace Umbraco.Core.Models.Identity
|
||||
.ForMember(dest => dest.PhoneNumberConfirmed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.TwoFactorEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Roles, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Claims, opt => opt.Ignore());
|
||||
.ForMember(dest => dest.Claims, opt => opt.Ignore())
|
||||
.AfterMap((src, dest) =>
|
||||
{
|
||||
dest.ResetDirtyProperties(true);
|
||||
dest.EnableChangeTracking();
|
||||
});
|
||||
|
||||
CreateMap<BackOfficeIdentityUser, UserData>()
|
||||
.ConstructUsing(source => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id'
|
||||
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
|
||||
.ForMember(dest => dest.AllowedApplications, opt => opt.MapFrom(src => src.AllowedSections))
|
||||
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
|
||||
.ForMember(dest => dest.StartContentNodes, opt => opt.MapFrom(src => src.CalculatedContentStartNodeIds))
|
||||
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
|
||||
.ForMember(dest => dest.StartMediaNodes, opt => opt.MapFrom(src => src.CalculatedMediaStartNodeIds))
|
||||
.ForMember(dest => dest.RealName, opt => opt.MapFrom(src => src.Name))
|
||||
.ForMember(dest => dest.Roles, opt => opt.MapFrom(user => new[] { user.UserTypeAlias }))
|
||||
.ForMember(dest => dest.StartContentNode, opt => opt.MapFrom(src => src.StartContentId))
|
||||
@@ -50,7 +68,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
|
||||
private static string GetPasswordHash(string storedPass)
|
||||
{
|
||||
return storedPass.StartsWith("___UIDEMPTYPWORD__") ? null : storedPass;
|
||||
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs
Normal file
54
src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an <see cref="IContent"/> -> user group & permission key value pair collection
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implements <see cref="IAggregateRoot"/> purely so it can be used with the repository layer which is why it's explicitly implemented.
|
||||
/// </remarks>
|
||||
public class ContentPermissionSet : EntityPermissionSet, IAggregateRoot
|
||||
{
|
||||
private readonly IContent _content;
|
||||
|
||||
public ContentPermissionSet(IContent content, EntityPermissionCollection permissionsSet)
|
||||
: base(content.Id, permissionsSet)
|
||||
{
|
||||
_content = content;
|
||||
}
|
||||
|
||||
public override int EntityId
|
||||
{
|
||||
get { return _content.Id; }
|
||||
}
|
||||
|
||||
#region Explicit implementation of IAggregateRoot
|
||||
int IEntity.Id
|
||||
{
|
||||
get { return EntityId; }
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
bool IEntity.HasIdentity
|
||||
{
|
||||
get { return EntityId > 0; }
|
||||
}
|
||||
|
||||
Guid IEntity.Key { get; set; }
|
||||
|
||||
DateTime IEntity.CreateDate { get; set; }
|
||||
|
||||
DateTime IEntity.UpdateDate { get; set; }
|
||||
|
||||
DateTime? IDeletableEntity.DeletedDate { get; set; }
|
||||
|
||||
object IDeepCloneable.DeepClone()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,66 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user -> entity permission
|
||||
/// Represents an entity permission (defined on the user group and derived to retrieve permissions for a given user)
|
||||
/// </summary>
|
||||
public class EntityPermission
|
||||
public class EntityPermission : IEquatable<EntityPermission>
|
||||
{
|
||||
public EntityPermission(int userId, int entityId, string[] assignedPermissions)
|
||||
public EntityPermission(int groupId, int entityId, string[] assignedPermissions)
|
||||
{
|
||||
UserId = userId;
|
||||
UserGroupId = groupId;
|
||||
EntityId = entityId;
|
||||
AssignedPermissions = assignedPermissions;
|
||||
IsDefaultPermissions = false;
|
||||
}
|
||||
|
||||
public EntityPermission(int groupId, int entityId, string[] assignedPermissions, bool isDefaultPermissions)
|
||||
{
|
||||
UserGroupId = groupId;
|
||||
EntityId = entityId;
|
||||
AssignedPermissions = assignedPermissions;
|
||||
IsDefaultPermissions = isDefaultPermissions;
|
||||
}
|
||||
|
||||
public int UserId { get; private set; }
|
||||
public int EntityId { get; private set; }
|
||||
public int UserGroupId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The assigned permissions for the user/entity combo
|
||||
/// </summary>
|
||||
public string[] AssignedPermissions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the permissions assigned to this object are the group's default permissions and not explicitly defined permissions
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be the case when looking up entity permissions and falling back to the default permissions
|
||||
/// </remarks>
|
||||
public bool IsDefaultPermissions { get; private set; }
|
||||
|
||||
public bool Equals(EntityPermission other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return EntityId == other.EntityId && UserGroupId == other.UserGroupId;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((EntityPermission) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (EntityId * 397) ^ UserGroupId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="HashSet{T}"/> of <see cref="EntityPermission"/>
|
||||
/// </summary>
|
||||
public class EntityPermissionCollection : HashSet<EntityPermission>
|
||||
{
|
||||
public EntityPermissionCollection()
|
||||
{
|
||||
}
|
||||
|
||||
public EntityPermissionCollection(IEnumerable<EntityPermission> collection) : base(collection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aggregate permissions in the permission set
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This value is only calculated once
|
||||
/// </remarks>
|
||||
public IEnumerable<string> GetAllPermissions()
|
||||
{
|
||||
return _aggregatePermissions ?? (_aggregatePermissions =
|
||||
this.SelectMany(x => x.AssignedPermissions).Distinct().ToArray());
|
||||
}
|
||||
|
||||
private string[] _aggregatePermissions;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entity -> user & permission key value pair collection
|
||||
/// Represents an entity -> user group & permission key value pair collection
|
||||
/// </summary>
|
||||
public class EntityPermissionSet
|
||||
{
|
||||
private static readonly Lazy<EntityPermissionSet> EmptyInstance = new Lazy<EntityPermissionSet>(() => new EntityPermissionSet(-1, new EntityPermissionCollection()));
|
||||
/// <summary>
|
||||
/// Returns an empty permission set
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static EntityPermissionSet Empty()
|
||||
{
|
||||
return EmptyInstance.Value;
|
||||
}
|
||||
|
||||
public EntityPermissionSet(int entityId, EntityPermissionCollection permissionsSet)
|
||||
{
|
||||
EntityId = entityId;
|
||||
PermissionsSet = permissionsSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The entity id with permissions assigned
|
||||
/// </summary>
|
||||
public int EntityId { get; private set; }
|
||||
public virtual int EntityId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The key/value pairs of user id & single permission
|
||||
/// The key/value pairs of user group id & single permission
|
||||
/// </summary>
|
||||
public IEnumerable<UserPermission> UserPermissionsSet { get; private set; }
|
||||
public EntityPermissionCollection PermissionsSet { get; private set; }
|
||||
|
||||
public EntityPermissionSet(int entityId, IEnumerable<UserPermission> userPermissionsSet)
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aggregate permissions in the permission set
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This value is only calculated once
|
||||
/// </remarks>
|
||||
public IEnumerable<string> GetAllPermissions()
|
||||
{
|
||||
EntityId = entityId;
|
||||
UserPermissionsSet = userPermissionsSet;
|
||||
return PermissionsSet.GetAllPermissions();
|
||||
}
|
||||
|
||||
public class UserPermission
|
||||
{
|
||||
public UserPermission(int userId, string permission)
|
||||
{
|
||||
UserId = userId;
|
||||
Permission = permission;
|
||||
}
|
||||
|
||||
public int UserId { get; private set; }
|
||||
public string Permission { get; private set; }
|
||||
|
||||
protected bool Equals(UserPermission other)
|
||||
{
|
||||
return UserId == other.UserId && string.Equals(Permission, other.Permission);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((UserPermission) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (UserId*397) ^ Permission.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the the Profile interface
|
||||
/// Defines the the User Profile interface
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This interface is pretty useless but has been exposed publicly from 6.x so we're stuck with it. It would make more sense
|
||||
/// if the Id was an int but since it's not people have to cast it to int all of the time!
|
||||
/// </remarks>
|
||||
public interface IProfile
|
||||
{
|
||||
object Id { get; set; }
|
||||
string Name { get; set; }
|
||||
int Id { get; }
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
||||
|
||||
31
src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs
Normal file
31
src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// A readonly user group providing basic information
|
||||
/// </summary>
|
||||
public interface IReadOnlyUserGroup
|
||||
{
|
||||
string Name { get; }
|
||||
string Icon { get; }
|
||||
int Id { get; }
|
||||
int? StartContentId { get; }
|
||||
int? StartMediaId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The alias
|
||||
/// </summary>
|
||||
string Alias { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
IEnumerable<string> Permissions { get; set; }
|
||||
|
||||
IEnumerable<string> AllowedSections { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
@@ -10,28 +11,38 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// <remarks>Will be left internal until a proper Membership implementation is part of the roadmap</remarks>
|
||||
public interface IUser : IMembershipUser, IRememberBeingDirty, ICanBeDirty
|
||||
{
|
||||
UserState UserState { get; }
|
||||
|
||||
string Name { get; set; }
|
||||
int SessionTimeout { get; set; }
|
||||
int StartContentId { get; set; }
|
||||
int StartMediaId { get; set; }
|
||||
int[] StartContentIds { get; set; }
|
||||
int[] StartMediaIds { get; set; }
|
||||
string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the user type for the user
|
||||
/// </summary>
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUserType UserType { get; set; }
|
||||
|
||||
//TODO: This should be a private set
|
||||
DateTime? EmailConfirmedDate { get; set; }
|
||||
DateTime? InvitedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default permission set for the user
|
||||
/// Gets the groups that user is part of
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently in umbraco each permission is a single char but with an Enumerable{string} collection this allows for flexible changes to this in the future
|
||||
/// </remarks>
|
||||
IEnumerable<string> DefaultPermissions { get; set; }
|
||||
IEnumerable<IReadOnlyUserGroup> Groups { get; }
|
||||
|
||||
void RemoveGroup(string group);
|
||||
void ClearGroups();
|
||||
void AddGroup(IReadOnlyUserGroup group);
|
||||
|
||||
IEnumerable<string> AllowedSections { get; }
|
||||
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
void RemoveAllowedSection(string sectionAlias);
|
||||
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
void AddAllowedSection(string sectionAlias);
|
||||
|
||||
/// <summary>
|
||||
@@ -43,5 +54,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The security stamp used by ASP.Net identity
|
||||
/// </summary>
|
||||
string SecurityStamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
|
||||
/// </summary>
|
||||
string Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
44
src/Umbraco.Core/Models/Membership/IUserGroup.cs
Normal file
44
src/Umbraco.Core/Models/Membership/IUserGroup.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
public interface IUserGroup : IAggregateRoot
|
||||
{
|
||||
string Alias { get; set; }
|
||||
|
||||
int? StartContentId { get; set; }
|
||||
int? StartMediaId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The icon
|
||||
/// </summary>
|
||||
string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
IEnumerable<string> Permissions { get; set; }
|
||||
|
||||
IEnumerable<string> AllowedSections { get; }
|
||||
|
||||
void RemoveAllowedSection(string sectionAlias);
|
||||
|
||||
void AddAllowedSection(string sectionAlias);
|
||||
|
||||
void ClearAllowedSections();
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the number of users assigned to this group
|
||||
/// </summary>
|
||||
int UserCount { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public interface IUserType : IAggregateRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// The user type alias
|
||||
/// </summary>
|
||||
string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user type name
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions for the user type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
IEnumerable<string> Permissions { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
70
src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs
Normal file
70
src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
public class ReadOnlyUserGroup : IReadOnlyUserGroup, IEquatable<ReadOnlyUserGroup>
|
||||
{
|
||||
public ReadOnlyUserGroup(int id, string name, string icon, int? startContentId, int? startMediaId, string @alias,
|
||||
IEnumerable<string> allowedSections, IEnumerable<string> permissions)
|
||||
{
|
||||
Name = name;
|
||||
Icon = icon;
|
||||
Id = id;
|
||||
Alias = alias;
|
||||
AllowedSections = allowedSections.ToArray();
|
||||
Permissions = permissions.ToArray();
|
||||
|
||||
//Zero is invalid and will be treated as Null
|
||||
StartContentId = startContentId == 0 ? null : startContentId;
|
||||
StartMediaId = startMediaId == 0 ? null : startMediaId;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string Icon { get; private set; }
|
||||
public int? StartContentId { get; private set; }
|
||||
public int? StartMediaId { get; private set; }
|
||||
public string Alias { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
public IEnumerable<string> Permissions { get; set; }
|
||||
public IEnumerable<string> AllowedSections { get; private set; }
|
||||
|
||||
public bool Equals(ReadOnlyUserGroup other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return string.Equals(Alias, other.Alias);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((ReadOnlyUserGroup) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Alias.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(ReadOnlyUserGroup left, ReadOnlyUserGroup right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(ReadOnlyUserGroup left, ReadOnlyUserGroup right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
@@ -18,64 +19,107 @@ namespace Umbraco.Core.Models.Membership
|
||||
[DataContract(IsReference = true)]
|
||||
public class User : Entity, IUser
|
||||
{
|
||||
public User(IUserType userType)
|
||||
/// <summary>
|
||||
/// Constructor for creating a new/empty user
|
||||
/// </summary>
|
||||
public User()
|
||||
{
|
||||
if (userType == null) throw new ArgumentNullException("userType");
|
||||
|
||||
_userType = userType;
|
||||
_defaultPermissions = _userType.Permissions == null ? Enumerable.Empty<string>() : new List<string>(_userType.Permissions);
|
||||
//Groups = new List<object> { userType };
|
||||
SessionTimeout = 60;
|
||||
_sectionCollection = new ObservableCollection<string>();
|
||||
_addedSections = new List<string>();
|
||||
_removedSections = new List<string>();
|
||||
_userGroups = new HashSet<IReadOnlyUserGroup>();
|
||||
_language = GlobalSettings.DefaultUILanguage;
|
||||
_sectionCollection.CollectionChanged += SectionCollectionChanged;
|
||||
_isApproved = true;
|
||||
_isLockedOut = false;
|
||||
_startContentId = -1;
|
||||
_startMediaId = -1;
|
||||
_startContentIds = new int[] { };
|
||||
_startMediaIds = new int[] { };
|
||||
//cannot be null
|
||||
_rawPasswordValue = "";
|
||||
}
|
||||
|
||||
public User(string name, string email, string username, string rawPasswordValue, IUserType userType)
|
||||
: this(userType)
|
||||
/// <summary>
|
||||
/// Constructor for creating a new/empty user
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="rawPasswordValue"></param>
|
||||
public User(string name, string email, string username, string rawPasswordValue)
|
||||
: this()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name");
|
||||
if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Value cannot be null or whitespace.", "email");
|
||||
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username");
|
||||
if (string.IsNullOrEmpty(rawPasswordValue)) throw new ArgumentException("Value cannot be null or empty.", "rawPasswordValue");
|
||||
|
||||
_name = name;
|
||||
_email = email;
|
||||
_username = username;
|
||||
_rawPasswordValue = rawPasswordValue;
|
||||
_userGroups = new HashSet<IReadOnlyUserGroup>();
|
||||
_isApproved = true;
|
||||
_isLockedOut = false;
|
||||
_startContentId = -1;
|
||||
_startMediaId = -1;
|
||||
_startContentIds = new int[] { };
|
||||
_startMediaIds = new int[] { };
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for creating a new User instance for an existing user
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="rawPasswordValue"></param>
|
||||
/// <param name="userGroups"></param>
|
||||
/// <param name="startContentIds"></param>
|
||||
/// <param name="startMediaIds"></param>
|
||||
public User(int id, string name, string email, string username, string rawPasswordValue, IEnumerable<IReadOnlyUserGroup> userGroups, int[] startContentIds, int[] startMediaIds)
|
||||
: this()
|
||||
{
|
||||
//we allow whitespace for this value so just check null
|
||||
if (rawPasswordValue == null) throw new ArgumentNullException("rawPasswordValue");
|
||||
if (userGroups == null) throw new ArgumentNullException("userGroups");
|
||||
if (startContentIds == null) throw new ArgumentNullException("startContentIds");
|
||||
if (startMediaIds == null) throw new ArgumentNullException("startMediaIds");
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name");
|
||||
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username");
|
||||
|
||||
Id = id;
|
||||
_name = name;
|
||||
_email = email;
|
||||
_username = username;
|
||||
_rawPasswordValue = rawPasswordValue;
|
||||
_userGroups = new HashSet<IReadOnlyUserGroup>(userGroups);
|
||||
_isApproved = true;
|
||||
_isLockedOut = false;
|
||||
_startContentIds = startContentIds;
|
||||
_startMediaIds = startMediaIds;
|
||||
}
|
||||
|
||||
private IUserType _userType;
|
||||
private string _name;
|
||||
private string _securityStamp;
|
||||
private List<string> _addedSections;
|
||||
private List<string> _removedSections;
|
||||
private ObservableCollection<string> _sectionCollection;
|
||||
private string _avatar;
|
||||
private int _sessionTimeout;
|
||||
private int _startContentId;
|
||||
private int _startMediaId;
|
||||
private int[] _startContentIds;
|
||||
private int[] _startMediaIds;
|
||||
private int _failedLoginAttempts;
|
||||
|
||||
private string _username;
|
||||
private DateTime? _emailConfirmedDate;
|
||||
private DateTime? _invitedDate;
|
||||
private string _email;
|
||||
private string _rawPasswordValue;
|
||||
private IEnumerable<string> _allowedSections;
|
||||
private HashSet<IReadOnlyUserGroup> _userGroups;
|
||||
private bool _isApproved;
|
||||
private bool _isLockedOut;
|
||||
private string _language;
|
||||
private DateTime _lastPasswordChangedDate;
|
||||
private DateTime _lastLoginDate;
|
||||
private DateTime _lastLockoutDate;
|
||||
|
||||
private IEnumerable<string> _defaultPermissions;
|
||||
|
||||
private bool _defaultToLiveEditing;
|
||||
private IDictionary<string, object> _additionalData;
|
||||
private object _additionalDataLock = new object();
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
|
||||
@@ -87,10 +131,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
public readonly PropertyInfo LastPasswordChangeDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastPasswordChangeDate);
|
||||
|
||||
public readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
|
||||
public readonly PropertyInfo AvatarSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Avatar);
|
||||
public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
|
||||
public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
|
||||
public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
public readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
|
||||
public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartContentIds);
|
||||
public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartMediaIds);
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
|
||||
|
||||
public readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
|
||||
@@ -99,9 +143,18 @@ namespace Umbraco.Core.Models.Membership
|
||||
public readonly PropertyInfo IsLockedOutSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsLockedOut);
|
||||
public readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsApproved);
|
||||
public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
|
||||
public readonly PropertyInfo EmailConfirmedDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime?>(x => x.EmailConfirmedDate);
|
||||
public readonly PropertyInfo InvitedDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime?>(x => x.InvitedDate);
|
||||
|
||||
public readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
|
||||
public readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo<User, IUserType>(x => x.UserType);
|
||||
|
||||
public readonly PropertyInfo UserGroupsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<IReadOnlyUserGroup>>(x => x.Groups);
|
||||
|
||||
//Custom comparer for enumerable
|
||||
public readonly DelegateEqualityComparer<IEnumerable<int>> IntegerEnumerableComparer =
|
||||
new DelegateEqualityComparer<IEnumerable<int>>(
|
||||
(enum1, enum2) => enum1.UnsortedSequenceEqual(enum2),
|
||||
enum1 => enum1.GetHashCode());
|
||||
}
|
||||
|
||||
#region Implementation of IMembershipUser
|
||||
@@ -113,7 +166,18 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { throw new NotSupportedException("Cannot set the provider user key for a user"); }
|
||||
}
|
||||
|
||||
|
||||
[DataMember]
|
||||
public DateTime? EmailConfirmedDate
|
||||
{
|
||||
get { return _emailConfirmedDate; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _emailConfirmedDate, Ps.Value.EmailConfirmedDateSelector); }
|
||||
}
|
||||
[DataMember]
|
||||
public DateTime? InvitedDate
|
||||
{
|
||||
get { return _invitedDate; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _invitedDate, Ps.Value.InvitedDateSelector); }
|
||||
}
|
||||
[DataMember]
|
||||
public string Username
|
||||
{
|
||||
@@ -189,6 +253,22 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
#region Implementation of IUser
|
||||
|
||||
public UserState UserState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
|
||||
return UserState.Invited;
|
||||
|
||||
if (IsLockedOut)
|
||||
return UserState.LockedOut;
|
||||
if (IsApproved == false)
|
||||
return UserState.Disabled;
|
||||
|
||||
return UserState.Active;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
@@ -198,28 +278,171 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
public IEnumerable<string> AllowedSections
|
||||
{
|
||||
get { return _sectionCollection; }
|
||||
get { return _allowedSections ?? (_allowedSections = new List<string>(_userGroups.SelectMany(x => x.AllowedSections).Distinct())); }
|
||||
}
|
||||
|
||||
public void RemoveAllowedSection(string sectionAlias)
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUserType IUser.UserType
|
||||
{
|
||||
if (_sectionCollection.Contains(sectionAlias))
|
||||
get
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
//the best we can do here is to return the user's first user group as a IUserType object
|
||||
//but we should attempt to return any group that is the built in ones first
|
||||
var groups = Groups.ToArray();
|
||||
if (groups.Length == 0)
|
||||
{
|
||||
//In backwards compatibility land, a user type cannot be null! so we need to return a fake one.
|
||||
return new UserType
|
||||
{
|
||||
Alias = "temp",
|
||||
Id = int.MinValue,
|
||||
Key = Guid.Empty,
|
||||
CreateDate = default(DateTime),
|
||||
DeletedDate = null,
|
||||
Name = "Temp",
|
||||
Permissions = new List<string>(),
|
||||
UpdateDate = default(DateTime)
|
||||
};
|
||||
}
|
||||
var builtIns = new[] { Constants.Security.AdminGroupAlias, "writer", "editor", "translator" };
|
||||
var foundBuiltIn = groups.FirstOrDefault(x => builtIns.Contains(x.Alias));
|
||||
IUserGroup realGroup;
|
||||
if (foundBuiltIn != null)
|
||||
{
|
||||
//if the group isn't IUserGroup we'll need to look it up
|
||||
realGroup = foundBuiltIn as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(foundBuiltIn.Id);
|
||||
|
||||
//return a mapped version of the group
|
||||
return new UserType
|
||||
{
|
||||
Alias = realGroup.Alias,
|
||||
Id = realGroup.Id,
|
||||
Key = realGroup.Key,
|
||||
CreateDate = realGroup.CreateDate,
|
||||
DeletedDate = realGroup.DeletedDate,
|
||||
Name = realGroup.Name,
|
||||
Permissions = realGroup.Permissions,
|
||||
UpdateDate = realGroup.UpdateDate
|
||||
};
|
||||
}
|
||||
|
||||
//otherwise return the first
|
||||
//if the group isn't IUserGroup we'll need to look it up
|
||||
realGroup = groups[0] as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(groups[0].Id);
|
||||
//return a mapped version of the group
|
||||
return new UserType
|
||||
{
|
||||
Alias = realGroup.Alias,
|
||||
Id = realGroup.Id,
|
||||
Key = realGroup.Key,
|
||||
CreateDate = realGroup.CreateDate,
|
||||
DeletedDate = realGroup.DeletedDate,
|
||||
Name = realGroup.Name,
|
||||
Permissions = realGroup.Permissions,
|
||||
UpdateDate = realGroup.UpdateDate
|
||||
};
|
||||
}
|
||||
set
|
||||
{
|
||||
//if old APIs are still using this lets first check if the user is part of the user group with the alias specified
|
||||
if (Groups.Any(x => x.Alias == value.Alias))
|
||||
return;
|
||||
|
||||
//the only other option we have here is to lookup the group (and we'll need to use singletons here :( )
|
||||
var found = ApplicationContext.Current.Services.UserService.GetUserGroupByAlias(value.Alias);
|
||||
if (found == null)
|
||||
throw new InvalidOperationException("No user group was found with the alias " + value.Alias + ", this API (IUser.UserType) is obsolete, use user groups instead");
|
||||
|
||||
//if it's found, all we can do is add it, we can't really replace them
|
||||
AddGroup(found.ToReadOnlyGroup());
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAllowedSection(string sectionAlias)
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
void IUser.RemoveAllowedSection(string sectionAlias)
|
||||
{
|
||||
if (_sectionCollection.Contains(sectionAlias) == false)
|
||||
//don't do anything if they aren't allowed it already
|
||||
if (AllowedSections.Contains(sectionAlias) == false)
|
||||
return;
|
||||
|
||||
var groups = Groups.ToArray();
|
||||
//our only option here is to check if a custom group is created for this user, if so we can remove it from that group, otherwise we'll throw
|
||||
//now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade.
|
||||
//this comes in the alias form of userName + 'Group'
|
||||
var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group"));
|
||||
if (customUserGroup != null)
|
||||
{
|
||||
_sectionCollection.Add(sectionAlias);
|
||||
//if the group isn't IUserGroup we'll need to look it up
|
||||
var realGroup = customUserGroup as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(customUserGroup.Id);
|
||||
realGroup.RemoveAllowedSection(sectionAlias);
|
||||
//now we need to flag this for saving (hack!)
|
||||
GroupsToSave.Add(realGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot remove the allowed section using this obsolete API. Modify the user's groups instead");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
void IUser.AddAllowedSection(string sectionAlias)
|
||||
{
|
||||
//don't do anything if they are allowed it already
|
||||
if (AllowedSections.Contains(sectionAlias))
|
||||
return;
|
||||
|
||||
//This is here for backwards compat only.
|
||||
//First we'll check if the user is part of the 'admin' group. If so then we can ensure that the admin group has this section available to it.
|
||||
//otherwise, the only thing we can do is create a custom user group for this user and add this section.
|
||||
//We are checking for admin here because if the user is an admin and an allowed section is being added, then it's assumed it's to be added
|
||||
//for the whole admin group (i.e. Forms installer does this for admins)
|
||||
var groups = Groups.ToArray();
|
||||
var admin = groups.FirstOrDefault(x => x.Alias == Constants.Security.AdminGroupAlias);
|
||||
if (admin != null)
|
||||
{
|
||||
//if the group isn't IUserGroup we'll need to look it up
|
||||
var realGroup = admin as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(admin.Id);
|
||||
realGroup.AddAllowedSection(sectionAlias);
|
||||
//now we need to flag this for saving (hack!)
|
||||
GroupsToSave.Add(realGroup);
|
||||
}
|
||||
|
||||
//now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade.
|
||||
//this comes in the alias form of userName + 'Group'
|
||||
var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group"));
|
||||
if (customUserGroup != null)
|
||||
{
|
||||
//if the group isn't IUserGroup we'll need to look it up
|
||||
var realGroup = customUserGroup as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(customUserGroup.Id);
|
||||
realGroup.AddAllowedSection(sectionAlias);
|
||||
//now we need to flag this for saving (hack!)
|
||||
GroupsToSave.Add(realGroup);
|
||||
}
|
||||
|
||||
//ok, so the user doesn't have a 1:1 group, we'll need to flag it for creation
|
||||
var newUserGroup = new UserGroup
|
||||
{
|
||||
Alias = Username + "Group",
|
||||
Name = "Group for " + Username
|
||||
};
|
||||
newUserGroup.AddAllowedSection(sectionAlias);
|
||||
GroupsToSave.Add(newUserGroup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This used purely for hacking backwards compatibility into this class for < 7.7 compat
|
||||
/// </summary>
|
||||
[DoNotClone]
|
||||
[IgnoreDataMember]
|
||||
internal List<IUserGroup> GroupsToSave = new List<IUserGroup>();
|
||||
|
||||
public IProfile ProfileData
|
||||
{
|
||||
get { return new UserProfile(this); }
|
||||
get { return new WrappedUserProfile(this); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -232,20 +455,11 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _securityStamp, Ps.Value.SecurityStampSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to add a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> AddedSections
|
||||
[DataMember]
|
||||
public string Avatar
|
||||
{
|
||||
get { return _addedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to remove a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> RemovedSections
|
||||
{
|
||||
get { return _removedSections; }
|
||||
get { return _avatar; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _avatar, Ps.Value.AvatarSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -268,10 +482,11 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The start content id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartContentId
|
||||
[DoNotClone]
|
||||
public int[] StartContentIds
|
||||
{
|
||||
get { return _startContentId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _startContentId, Ps.Value.StartContentIdSelector); }
|
||||
get { return _startContentIds; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _startContentIds, Ps.Value.StartContentIdSelector, Ps.Value.IntegerEnumerableComparer); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -281,10 +496,11 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The start media id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartMediaId
|
||||
[DoNotClone]
|
||||
public int[] StartMediaIds
|
||||
{
|
||||
get { return _startMediaId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _startMediaId, Ps.Value.StartMediaIdSelector); }
|
||||
get { return _startMediaIds; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _startMediaIds, Ps.Value.StartMediaIdSelector, Ps.Value.IntegerEnumerableComparer); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
@@ -294,14 +510,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _language, Ps.Value.LanguageSelector); }
|
||||
}
|
||||
|
||||
//TODO: This should be a private set
|
||||
[DataMember]
|
||||
public IEnumerable<string> DefaultPermissions
|
||||
{
|
||||
get { return _defaultPermissions;}
|
||||
set { _defaultPermissions = value; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal bool DefaultToLiveEditing
|
||||
{
|
||||
@@ -309,78 +517,107 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _defaultToLiveEditing, Ps.Value.DefaultToLiveEditingSelector); }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public IUserType UserType
|
||||
/// <summary>
|
||||
/// Gets the groups that user is part of
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public IEnumerable<IReadOnlyUserGroup> Groups
|
||||
{
|
||||
get { return _userType; }
|
||||
set
|
||||
{
|
||||
if (value.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot assign a User Type that has not been persisted");
|
||||
}
|
||||
get { return _userGroups; }
|
||||
}
|
||||
|
||||
SetPropertyValueAndDetectChanges(value, ref _userType, Ps.Value.UserTypeSelector);
|
||||
public void RemoveGroup(string group)
|
||||
{
|
||||
foreach (var userGroup in _userGroups.ToArray())
|
||||
{
|
||||
if (userGroup.Alias == group)
|
||||
{
|
||||
_userGroups.Remove(userGroup);
|
||||
//reset this flag so it's rebuilt with the assigned groups
|
||||
_allowedSections = null;
|
||||
OnPropertyChanged(Ps.Value.UserGroupsSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearGroups()
|
||||
{
|
||||
if (_userGroups.Count > 0)
|
||||
{
|
||||
_userGroups.Clear();
|
||||
//reset this flag so it's rebuilt with the assigned groups
|
||||
_allowedSections = null;
|
||||
OnPropertyChanged(Ps.Value.UserGroupsSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddGroup(IReadOnlyUserGroup group)
|
||||
{
|
||||
if (_userGroups.Add(group))
|
||||
{
|
||||
//reset this flag so it's rebuilt with the assigned groups
|
||||
_allowedSections = null;
|
||||
OnPropertyChanged(Ps.Value.UserGroupsSelector);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Whenever resetting occurs, clear the remembered add/removed collections, even if
|
||||
/// rememberPreviouslyChangedProperties is true, the AllowedSections property will still
|
||||
/// be flagged as dirty.
|
||||
/// This is used as an internal cache for this entity - specifically for calculating start nodes so we don't re-calculated all of the time
|
||||
/// </summary>
|
||||
/// <param name="rememberPreviouslyChangedProperties"></param>
|
||||
public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
internal IDictionary<string, object> AdditionalData
|
||||
{
|
||||
_addedSections.Clear();
|
||||
_removedSections.Clear();
|
||||
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the collection changed event in order for us to flag the AllowedSections property as changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(Ps.Value.AllowedSectionsSelector);
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
get
|
||||
{
|
||||
var item = e.NewItems.Cast<string>().First();
|
||||
|
||||
if (_addedSections.Contains(item) == false)
|
||||
lock (_additionalDataLock)
|
||||
{
|
||||
_addedSections.Add(item);
|
||||
return _additionalData ?? (_additionalData = new Dictionary<string, object>());
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
var item = e.OldItems.Cast<string>().First();
|
||||
|
||||
if (_removedSections.Contains(item) == false)
|
||||
{
|
||||
_removedSections.Add(item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
internal object AdditionalDataLock { get { return _additionalDataLock; } }
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (User)base.DeepClone();
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//manually clone the start node props
|
||||
clone._startContentIds = _startContentIds.ToArray();
|
||||
clone._startMediaIds = _startMediaIds.ToArray();
|
||||
|
||||
// this value has been cloned and points to the same object
|
||||
// which obviously is bad - needs to point to a new object
|
||||
clone._additionalDataLock = new object();
|
||||
|
||||
if (_additionalData != null)
|
||||
{
|
||||
// clone._additionalData points to the same dictionary, which is bad, because
|
||||
// changing one clone impacts all of them - so we need to reset it with a fresh
|
||||
// dictionary that will contain the same values - and, if some values are deep
|
||||
// cloneable, they should be deep-cloned too
|
||||
var cloneAdditionalData = clone._additionalData = new Dictionary<string, object>();
|
||||
|
||||
lock (_additionalDataLock)
|
||||
{
|
||||
foreach (var kvp in _additionalData)
|
||||
{
|
||||
var deepCloneable = kvp.Value as IDeepCloneable;
|
||||
cloneAdditionalData[kvp.Key] = deepCloneable == null ? kvp.Value : deepCloneable.DeepClone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//need to create new collections otherwise they'll get copied by ref
|
||||
clone._addedSections = new List<string>();
|
||||
clone._removedSections = new List<string>();
|
||||
clone._sectionCollection = new ObservableCollection<string>(_sectionCollection.ToList());
|
||||
clone._defaultPermissions = new List<string>(_defaultPermissions.ToList());
|
||||
clone._userGroups = new HashSet<IReadOnlyUserGroup>(_userGroups);
|
||||
clone._allowedSections = _allowedSections != null ? new List<string>(_allowedSections) : null;
|
||||
//re-create the event handler
|
||||
clone._sectionCollection.CollectionChanged += clone.SectionCollectionChanged;
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
@@ -392,28 +629,26 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// <summary>
|
||||
/// Internal class used to wrap the user in a profile
|
||||
/// </summary>
|
||||
private class UserProfile : IProfile
|
||||
private class WrappedUserProfile : IProfile
|
||||
{
|
||||
private readonly IUser _user;
|
||||
|
||||
public UserProfile(IUser user)
|
||||
public WrappedUserProfile(IUser user)
|
||||
{
|
||||
_user = user;
|
||||
}
|
||||
|
||||
public object Id
|
||||
public int Id
|
||||
{
|
||||
get { return _user.Id; }
|
||||
set { _user.Id = (int)value; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _user.Name; }
|
||||
set { _user.Name = value; }
|
||||
}
|
||||
|
||||
protected bool Equals(UserProfile other)
|
||||
private bool Equals(WrappedUserProfile other)
|
||||
{
|
||||
return _user.Equals(other._user);
|
||||
}
|
||||
@@ -423,7 +658,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((UserProfile) obj);
|
||||
return Equals((WrappedUserProfile) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
|
||||
26
src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs
Normal file
26
src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal static class UserGroupExtensions
|
||||
{
|
||||
public static IReadOnlyUserGroup ToReadOnlyGroup(this IUserGroup group)
|
||||
{
|
||||
//this will generally always be the case
|
||||
var readonlyGroup = group as IReadOnlyUserGroup;
|
||||
if (readonlyGroup != null) return readonlyGroup;
|
||||
|
||||
//otherwise create one
|
||||
return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.AllowedSections, group.Permissions);
|
||||
}
|
||||
|
||||
public static IReadOnlyUserGroup ToReadOnlyGroup(this UserGroupDto group)
|
||||
{
|
||||
return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon,
|
||||
group.StartContentId, group.StartMediaId, group.Alias,
|
||||
group.UserGroup2AppDtos.Select(x => x.AppAlias).ToArray(),
|
||||
group.DefaultPermissions == null ? Enumerable.Empty<string>() : group.DefaultPermissions.ToCharArray().Select(x => x.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/Umbraco.Core/Models/Membership/UserProfile.cs
Normal file
46
src/Umbraco.Core/Models/Membership/UserProfile.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal class UserProfile : IProfile, IEquatable<UserProfile>
|
||||
{
|
||||
public UserProfile(int id, string name)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
public bool Equals(UserProfile other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return Id == other.Id;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((UserProfile) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public static bool operator ==(UserProfile left, UserProfile right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(UserProfile left, UserProfile right)
|
||||
{
|
||||
return Equals(left, right) == false;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Umbraco.Core/Models/Membership/UserState.cs
Normal file
14
src/Umbraco.Core/Models/Membership/UserState.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// The state of a user
|
||||
/// </summary>
|
||||
public enum UserState
|
||||
{
|
||||
All = -1,
|
||||
Active = 0,
|
||||
Disabled = 1,
|
||||
LockedOut = 2,
|
||||
Invited = 3
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Type for a Backoffice User
|
||||
/// </summary>
|
||||
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class UserType : Entity, IUserType
|
||||
@@ -19,9 +17,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
private string _alias;
|
||||
private string _name;
|
||||
private IEnumerable<string> _permissions;
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
|
||||
private class PropertySelectors
|
||||
{
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<UserType, string>(x => x.Name);
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
<Compile Include="Cache\SingleItemsOnlyRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\StaticCacheProvider.cs" />
|
||||
<Compile Include="Cache\TypedCacheRefresherBase.cs" />
|
||||
<Compile Include="CodeAnnotations\ActionMetadataAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoObjectTypeAttribute.cs" />
|
||||
@@ -204,6 +205,20 @@
|
||||
<Compile Include="Configuration\Grid\IGridConfig.cs" />
|
||||
<Compile Include="Configuration\Grid\IGridEditorConfig.cs" />
|
||||
<Compile Include="Configuration\Grid\IGridEditorsConfig.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\DisabledHealthCheckElement.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\DisabledHealthChecksElementCollection.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\HealthCheckNotificationSettingsElement.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\HealthCheckNotificationVerbosity.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\HealthChecksSection.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\IDisabledHealthCheck.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\IHealthCheckNotificationSettings.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\IHealthChecks.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\INotificationMethod.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\INotificationMethodSettings.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\NotificationMethodElement.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\NotificationMethodsElementCollection.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\NotificationMethodSettingsElement.cs" />
|
||||
<Compile Include="Configuration\HealthChecks\NotificationMethodSettingsElementCollection.cs" />
|
||||
<Compile Include="Configuration\InnerTextConfigurationElement.cs" />
|
||||
<Compile Include="Configuration\OptionalCommaDelimitedConfigurationElement.cs" />
|
||||
<Compile Include="Configuration\OptionalInnerTextConfigurationElement.cs" />
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Examine.LocalStorage
|
||||
{
|
||||
public DirectoryInfo GetLocalStorageDirectory(NameValueCollection config, string configuredPath)
|
||||
{
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToMd5();
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "LuceneDir",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "Umbraco",
|
||||
"name": "umbraco",
|
||||
"version": "7",
|
||||
"homepage": "https://github.com/umbraco/Umbraco-CMS",
|
||||
"authors": [
|
||||
@@ -30,6 +30,7 @@
|
||||
"codemirror": "~5.3.0",
|
||||
"angular-local-storage": "~0.2.3",
|
||||
"moment": "~2.10.3",
|
||||
"ace-builds": "^1.2.3"
|
||||
"ace-builds": "^1.2.3",
|
||||
"clipboard": "1.7.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ module.exports = function (grunt) {
|
||||
src: ['src/installer/**/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.installer.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n angular.module('umbraco.install', []); \n",
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
@@ -382,6 +382,9 @@ module.exports = function (grunt) {
|
||||
html: {
|
||||
files: ['src/views/**/*.html', 'src/*.html'],
|
||||
tasks: ['watch-html', 'timestamp']
|
||||
},
|
||||
options: {
|
||||
interval: 500
|
||||
}
|
||||
},
|
||||
|
||||
@@ -553,6 +556,10 @@ module.exports = function (grunt) {
|
||||
|
||||
'src-min-noconflict/worker-javascript.js',
|
||||
]
|
||||
},
|
||||
'clipboard': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/clipboard.min.js']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('da',{
|
||||
"Cut": "Klip",
|
||||
"Heading 5": "Overskrift 5",
|
||||
"Header 2": "Overskrift 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Din browser underst\u00f8tter ikke direkte adgang til clipboard. Benyt Ctrl+X\/C\/ keybord shortcuts i stedet for.",
|
||||
"Heading 4": "Overskrift 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "Overskrift 2",
|
||||
"Paste": "Inds\u00e6t",
|
||||
"Close": "Luk",
|
||||
"Font Family": "Skrifttype",
|
||||
"Pre": "Pre",
|
||||
"Align right": "H\u00f8jrejusteret",
|
||||
"New document": "Nyt dokument",
|
||||
"Blockquote": "Indrykning",
|
||||
"Numbered list": "Nummerering",
|
||||
"Heading 1": "Overskrift 1",
|
||||
"Headings": "Overskrifter",
|
||||
"Increase indent": "For\u00f8g indrykning",
|
||||
"Formats": "Formater",
|
||||
"Headers": "Overskrifter",
|
||||
"Select all": "V\u00e6lg alle",
|
||||
"Header 3": "Overskrift 3",
|
||||
"Blocks": "Blokke",
|
||||
"Undo": "Fortryd",
|
||||
"Strikethrough": "Gennemstreg",
|
||||
"Bullet list": "Punkt tegn",
|
||||
"Header 1": "Overskrift 1",
|
||||
"Superscript": "H\u00e6vet",
|
||||
"Clear formatting": "Nulstil formattering",
|
||||
"Font Sizes": "Skriftst\u00f8rrelse",
|
||||
"Subscript": "S\u00e6nket",
|
||||
"Header 6": "Overskrift 6",
|
||||
"Redo": "Genopret",
|
||||
"Paragraph": "S\u00e6tning",
|
||||
"Ok": "Ok",
|
||||
"Bold": "Fed",
|
||||
"Code": "Code",
|
||||
"Italic": "Kursiv",
|
||||
"Align center": "Centreret",
|
||||
"Header 5": "Overskrift 5",
|
||||
"Heading 6": "Overskrift 6",
|
||||
"Heading 3": "Overskrift 3",
|
||||
"Decrease indent": "Formindsk indrykning",
|
||||
"Header 4": "Overskrift 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "S\u00e6t ind er indstillet til at inds\u00e6tte som ren tekst. Indhold bliver nu indsat uden formatering indtil du \u00e6ndrer indstillingen.",
|
||||
"Underline": "Understreg",
|
||||
"Cancel": "Fortryd",
|
||||
"Justify": "Justering",
|
||||
"Inline": "Inline",
|
||||
"Copy": "Kopier",
|
||||
"Align left": "Venstrejusteret",
|
||||
"Visual aids": "Visuel hj\u00e6lp",
|
||||
"Lower Greek": "Lower Gr\u00e6sk",
|
||||
"Square": "Kvadrat",
|
||||
"Default": "Standard",
|
||||
"Lower Alpha": "Lower Alpha",
|
||||
"Circle": "Cirkel",
|
||||
"Disc": "Disk",
|
||||
"Upper Alpha": "Upper Alpha",
|
||||
"Upper Roman": "Upper Roman",
|
||||
"Lower Roman": "Lower Roman",
|
||||
"Name": "Navn",
|
||||
"Anchor": "Anchor",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Du har ikke gemte \u00e6ndringer. Er du sikker p\u00e5 at du vil forts\u00e6tte?",
|
||||
"Restore last draft": "Genopret sidste kladde",
|
||||
"Special character": "Specielle tegn",
|
||||
"Source code": "Kildekode",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "Farve",
|
||||
"Right to left": "H\u00f8jre til venstre",
|
||||
"Left to right": "Venstre til h\u00f8jre",
|
||||
"Emoticons": "Emot-ikoner",
|
||||
"Robots": "Robotter",
|
||||
"Document properties": "Dokument egenskaber",
|
||||
"Title": "Titel",
|
||||
"Keywords": "S\u00f8geord",
|
||||
"Encoding": "Kodning",
|
||||
"Description": "Beskrivelse",
|
||||
"Author": "Forfatter",
|
||||
"Fullscreen": "Fuldsk\u00e6rm",
|
||||
"Horizontal line": "Vandret linie",
|
||||
"Horizontal space": "Vandret afstand",
|
||||
"Insert\/edit image": "Inds\u00e6t\/ret billede",
|
||||
"General": "Generet",
|
||||
"Advanced": "Avanceret",
|
||||
"Source": "Kilde",
|
||||
"Border": "Kant",
|
||||
"Constrain proportions": "Behold propertioner",
|
||||
"Vertical space": "Lodret afstand",
|
||||
"Image description": "Billede beskrivelse",
|
||||
"Style": "Stil",
|
||||
"Dimensions": "Dimensioner",
|
||||
"Insert image": "Inds\u00e6t billede",
|
||||
"Zoom in": "Zoom ind",
|
||||
"Contrast": "Kontrast",
|
||||
"Back": "Tilbage",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "Flip horisontalt",
|
||||
"Resize": "Skaler",
|
||||
"Sharpen": "G\u00f8r skarpere",
|
||||
"Zoom out": "Zoom ud",
|
||||
"Image options": "Billede indstillinger",
|
||||
"Apply": "Anvend",
|
||||
"Brightness": "Lysstyrke",
|
||||
"Rotate clockwise": "Drej med urets retning",
|
||||
"Rotate counterclockwise": "Drej modsat urets retning",
|
||||
"Edit image": "Rediger billede",
|
||||
"Color levels": "Farve niveauer",
|
||||
"Crop": "Besk\u00e6r",
|
||||
"Orientation": "Retning",
|
||||
"Flip vertically": "Flip vertikalt",
|
||||
"Invert": "Inverter",
|
||||
"Insert date\/time": "Inds\u00e6t dato\/klokkeslet",
|
||||
"Remove link": "Fjern link",
|
||||
"Url": "Url",
|
||||
"Text to display": "Vis tekst",
|
||||
"Anchors": "Ankre",
|
||||
"Insert link": "Inds\u00e6t link",
|
||||
"New window": "Nyt vindue",
|
||||
"None": "Ingen",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "URLen som du angav ser ud til at v\u00e6re et eksternt link. \u00d8nsker du at tilf\u00f8je det kr\u00e6vede prefiks http:\/\/ ?",
|
||||
"Target": "Target",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URLen som du angav ser ud til at v\u00e6re en email adresse. \u00d8nsker du at tilf\u00f8je det kr\u00e6vede prefiks mailto: ?",
|
||||
"Insert\/edit link": "Inds\u00e6t\/ret link",
|
||||
"Insert\/edit video": "Inds\u00e6t\/ret video",
|
||||
"Poster": "Poster",
|
||||
"Alternative source": "Alternativ kilde",
|
||||
"Paste your embed code below:": "Inds\u00e6t din embed kode herunder:",
|
||||
"Insert video": "Inds\u00e6t video",
|
||||
"Embed": "Integrer",
|
||||
"Nonbreaking space": "H\u00e5rdt mellemrum",
|
||||
"Page break": "Sideskift",
|
||||
"Paste as text": "Inds\u00e6t som ren tekst",
|
||||
"Preview": "Forh\u00e5ndsvisning",
|
||||
"Print": "Udskriv",
|
||||
"Save": "Gem",
|
||||
"Could not find the specified string.": "Kunne ikke finde s\u00f8getekst",
|
||||
"Replace": "Erstat",
|
||||
"Next": "N\u00e6ste",
|
||||
"Whole words": "Hele ord",
|
||||
"Find and replace": "Find og erstat",
|
||||
"Replace with": "Erstat med",
|
||||
"Find": "Find",
|
||||
"Replace all": "Erstat alt",
|
||||
"Match case": "STORE og sm\u00e5 bogstaver",
|
||||
"Prev": "Forrige",
|
||||
"Spellcheck": "Stavekontrol",
|
||||
"Finish": "F\u00e6rdig",
|
||||
"Ignore all": "Ignorer alt",
|
||||
"Ignore": "Ignorer",
|
||||
"Add to Dictionary": "Tilf\u00f8j til ordbog",
|
||||
"Insert row before": "Inds\u00e6t r\u00e6kke f\u00f8r",
|
||||
"Rows": "R\u00e6kker",
|
||||
"Height": "H\u00f8jde",
|
||||
"Paste row after": "Inds\u00e6t r\u00e6kke efter",
|
||||
"Alignment": "Tilpasning",
|
||||
"Border color": "Kant farve",
|
||||
"Column group": "Kolonne gruppe",
|
||||
"Row": "R\u00e6kke",
|
||||
"Insert column before": "Inds\u00e6t kolonne f\u00f8r",
|
||||
"Split cell": "Split celle",
|
||||
"Cell padding": "Celle padding",
|
||||
"Cell spacing": "Celle afstand",
|
||||
"Row type": "R\u00e6kke type",
|
||||
"Insert table": "Inds\u00e6t tabel",
|
||||
"Body": "Krop",
|
||||
"Caption": "Tekst",
|
||||
"Footer": "Sidefod",
|
||||
"Delete row": "Slet r\u00e6kke",
|
||||
"Paste row before": "Inds\u00e6t r\u00e6kke f\u00f8r",
|
||||
"Scope": "Anvendelsesomr\u00e5de",
|
||||
"Delete table": "Slet tabel",
|
||||
"H Align": "H juster",
|
||||
"Top": "Top",
|
||||
"Header cell": "Sidehoved celle",
|
||||
"Column": "Kolonne",
|
||||
"Row group": "R\u00e6kke gruppe",
|
||||
"Cell": "Celle",
|
||||
"Middle": "Midt",
|
||||
"Cell type": "Celle type",
|
||||
"Copy row": "Kopier r\u00e6kke",
|
||||
"Row properties": "R\u00e6kke egenskaber",
|
||||
"Table properties": "Tabel egenskaber",
|
||||
"Bottom": "Bund",
|
||||
"V Align": "V juster",
|
||||
"Header": "Sidehoved",
|
||||
"Right": "H\u00f8jre",
|
||||
"Insert column after": "Inds\u00e6t kolonne efter",
|
||||
"Cols": "Kolonne",
|
||||
"Insert row after": "Inds\u00e6t r\u00e6kke efter",
|
||||
"Width": "Bredde",
|
||||
"Cell properties": "Celle egenskaber",
|
||||
"Left": "Venstre",
|
||||
"Cut row": "Klip r\u00e6kke",
|
||||
"Delete column": "Slet kolonne",
|
||||
"Center": "Centrering",
|
||||
"Merge cells": "Flet celler",
|
||||
"Insert template": "Inds\u00e6t skabelon",
|
||||
"Templates": "Skabeloner",
|
||||
"Background color": "Baggrunds farve",
|
||||
"Custom...": "Brugerdefineret...",
|
||||
"Custom color": "Brugerdefineret farve",
|
||||
"No color": "Ingen farve",
|
||||
"Text color": "Tekst farve",
|
||||
"Show blocks": "Vis klokke",
|
||||
"Show invisible characters": "Vis usynlige tegn",
|
||||
"Words: {0}": "Ord: {0}",
|
||||
"Insert": "Inds\u00e6t",
|
||||
"File": "Fil",
|
||||
"Edit": "Rediger",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text omr\u00e5de. Tryk ALT-F9 for menu. Tryk ALT-F10 for toolbar. Tryk ALT-0 for hj\u00e6lp",
|
||||
"Tools": "V\u00e6rkt\u00f8j",
|
||||
"View": "Vis",
|
||||
"Table": "Tabel",
|
||||
"Format": "Format"
|
||||
});
|
||||
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('de',{
|
||||
"Cut": "Ausschneiden",
|
||||
"Heading 5": "\u00dcberschrift 5",
|
||||
"Header 2": "\u00dcberschrift 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Ihr Browser unterst\u00fctzt leider keinen direkten Zugriff auf die Zwischenablage. Bitte benutzen Sie die Strg + X \/ C \/ V Tastenkombinationen.",
|
||||
"Heading 4": "\u00dcberschrift 4",
|
||||
"Div": "Textblock",
|
||||
"Heading 2": "\u00dcberschrift 2",
|
||||
"Paste": "Einf\u00fcgen",
|
||||
"Close": "Schlie\u00dfen",
|
||||
"Font Family": "Schriftart",
|
||||
"Pre": "Vorformatierter Text",
|
||||
"Align right": "Rechtsb\u00fcndig ausrichten",
|
||||
"New document": "Neues Dokument",
|
||||
"Blockquote": "Zitat",
|
||||
"Numbered list": "Nummerierte Liste",
|
||||
"Heading 1": "\u00dcberschrift 1",
|
||||
"Headings": "\u00dcberschriften",
|
||||
"Increase indent": "Einzug vergr\u00f6\u00dfern",
|
||||
"Formats": "Formate",
|
||||
"Headers": "\u00dcberschriften",
|
||||
"Select all": "Alles ausw\u00e4hlen",
|
||||
"Header 3": "\u00dcberschrift 3",
|
||||
"Blocks": "Absatzformate",
|
||||
"Undo": "R\u00fcckg\u00e4ngig",
|
||||
"Strikethrough": "Durchgestrichen",
|
||||
"Bullet list": "Aufz\u00e4hlung",
|
||||
"Header 1": "\u00dcberschrift 1",
|
||||
"Superscript": "Hochgestellt",
|
||||
"Clear formatting": "Formatierung entfernen",
|
||||
"Font Sizes": "Schriftgr\u00f6\u00dfe",
|
||||
"Subscript": "Tiefgestellt",
|
||||
"Header 6": "\u00dcberschrift 6",
|
||||
"Redo": "Wiederholen",
|
||||
"Paragraph": "Absatz",
|
||||
"Ok": "Ok",
|
||||
"Bold": "Fett",
|
||||
"Code": "Quelltext",
|
||||
"Italic": "Kursiv",
|
||||
"Align center": "Zentriert ausrichten",
|
||||
"Header 5": "\u00dcberschrift 5",
|
||||
"Heading 6": "\u00dcberschrift 6",
|
||||
"Heading 3": "\u00dcberschrift 3",
|
||||
"Decrease indent": "Einzug verkleinern",
|
||||
"Header 4": "\u00dcberschrift 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Einf\u00fcgen ist nun im einfachen Textmodus. Inhalte werden ab jetzt als unformatierter Text eingef\u00fcgt, bis Sie diese Einstellung wieder ausschalten!",
|
||||
"Underline": "Unterstrichen",
|
||||
"Cancel": "Abbrechen",
|
||||
"Justify": "Blocksatz",
|
||||
"Inline": "Zeichenformate",
|
||||
"Copy": "Kopieren",
|
||||
"Align left": "Linksb\u00fcndig ausrichten",
|
||||
"Visual aids": "Visuelle Hilfen",
|
||||
"Lower Greek": "Griechische Kleinbuchstaben",
|
||||
"Square": "Quadrat",
|
||||
"Default": "Standard",
|
||||
"Lower Alpha": "Kleinbuchstaben",
|
||||
"Circle": "Kreis",
|
||||
"Disc": "Punkt",
|
||||
"Upper Alpha": "Gro\u00dfbuchstaben",
|
||||
"Upper Roman": "R\u00f6mische Zahlen (Gro\u00dfbuchstaben)",
|
||||
"Lower Roman": "R\u00f6mische Zahlen (Kleinbuchstaben)",
|
||||
"Name": "Name",
|
||||
"Anchor": "Textmarke",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Die \u00c4nderungen wurden noch nicht gespeichert, sind Sie sicher, dass Sie diese Seite verlassen wollen?",
|
||||
"Restore last draft": "Letzten Entwurf wiederherstellen",
|
||||
"Special character": "Sonderzeichen",
|
||||
"Source code": "Quelltext",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "Farbe",
|
||||
"Right to left": "Von rechts nach links",
|
||||
"Left to right": "Von links nach rechts",
|
||||
"Emoticons": "Emoticons",
|
||||
"Robots": "Robots",
|
||||
"Document properties": "Dokumenteigenschaften",
|
||||
"Title": "Titel",
|
||||
"Keywords": "Sch\u00fcsselw\u00f6rter",
|
||||
"Encoding": "Zeichenkodierung",
|
||||
"Description": "Beschreibung",
|
||||
"Author": "Verfasser",
|
||||
"Fullscreen": "Vollbild",
|
||||
"Horizontal line": "Horizontale Linie",
|
||||
"Horizontal space": "Horizontaler Abstand",
|
||||
"Insert\/edit image": "Bild einf\u00fcgen\/bearbeiten",
|
||||
"General": "Allgemein",
|
||||
"Advanced": "Erweitert",
|
||||
"Source": "Quelle",
|
||||
"Border": "Rahmen",
|
||||
"Constrain proportions": "Seitenverh\u00e4ltnis beibehalten",
|
||||
"Vertical space": "Vertikaler Abstand",
|
||||
"Image description": "Bildbeschreibung",
|
||||
"Style": "Stil",
|
||||
"Dimensions": "Abmessungen",
|
||||
"Insert image": "Bild einf\u00fcgen",
|
||||
"Zoom in": "Ansicht vergr\u00f6\u00dfern",
|
||||
"Contrast": "Kontrast",
|
||||
"Back": "Zur\u00fcck",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "Horizontal spiegeln",
|
||||
"Resize": "Skalieren",
|
||||
"Sharpen": "Sch\u00e4rfen",
|
||||
"Zoom out": "Ansicht verkleinern",
|
||||
"Image options": "Bildeigenschaften",
|
||||
"Apply": "Anwenden",
|
||||
"Brightness": "Helligkeit",
|
||||
"Rotate clockwise": "Im Uhrzeigersinn drehen",
|
||||
"Rotate counterclockwise": "Gegen den Uhrzeigersinn drehen",
|
||||
"Edit image": "Bild bearbeiten",
|
||||
"Color levels": "Farbwerte",
|
||||
"Crop": "Bescheiden",
|
||||
"Orientation": "Ausrichtung",
|
||||
"Flip vertically": "Vertikal spiegeln",
|
||||
"Invert": "Invertieren",
|
||||
"Insert date\/time": "Datum\/Uhrzeit einf\u00fcgen ",
|
||||
"Remove link": "Link entfernen",
|
||||
"Url": "URL",
|
||||
"Text to display": "Anzuzeigender Text",
|
||||
"Anchors": "Textmarken",
|
||||
"Insert link": "Link einf\u00fcgen",
|
||||
"New window": "Neues Fenster",
|
||||
"None": "Keine",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http:\/\/\" voranstellen?",
|
||||
"Target": "Ziel",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?",
|
||||
"Insert\/edit link": "Link einf\u00fcgen\/bearbeiten",
|
||||
"Insert\/edit video": "Video einf\u00fcgen\/bearbeiten",
|
||||
"Poster": "Poster",
|
||||
"Alternative source": "Alternative Quelle",
|
||||
"Paste your embed code below:": "F\u00fcgen Sie Ihren Einbettungscode hier ein:",
|
||||
"Insert video": "Video einf\u00fcgen",
|
||||
"Embed": "Einbetten",
|
||||
"Nonbreaking space": "Gesch\u00fctztes Leerzeichen",
|
||||
"Page break": "Seitenumbruch",
|
||||
"Paste as text": "Als Text einf\u00fcgen",
|
||||
"Preview": "Vorschau",
|
||||
"Print": "Drucken",
|
||||
"Save": "Speichern",
|
||||
"Could not find the specified string.": "Die Zeichenfolge wurde nicht gefunden.",
|
||||
"Replace": "Ersetzen",
|
||||
"Next": "Weiter",
|
||||
"Whole words": "Nur ganze W\u00f6rter",
|
||||
"Find and replace": "Suchen und ersetzen",
|
||||
"Replace with": "Ersetzen durch",
|
||||
"Find": "Suchen",
|
||||
"Replace all": "Alles ersetzen",
|
||||
"Match case": "Gro\u00df-\/Kleinschreibung beachten",
|
||||
"Prev": "Zur\u00fcck",
|
||||
"Spellcheck": "Rechtschreibpr\u00fcfung",
|
||||
"Finish": "Ende",
|
||||
"Ignore all": "Alles Ignorieren",
|
||||
"Ignore": "Ignorieren",
|
||||
"Add to Dictionary": "Zum W\u00f6rterbuch hinzuf\u00fcgen",
|
||||
"Insert row before": "Neue Zeile davor einf\u00fcgen ",
|
||||
"Rows": "Zeilen",
|
||||
"Height": "H\u00f6he",
|
||||
"Paste row after": "Zeile danach einf\u00fcgen",
|
||||
"Alignment": "Ausrichtung",
|
||||
"Border color": "Rahmenfarbe",
|
||||
"Column group": "Spaltengruppe",
|
||||
"Row": "Zeile",
|
||||
"Insert column before": "Neue Spalte davor einf\u00fcgen",
|
||||
"Split cell": "Zelle aufteilen",
|
||||
"Cell padding": "Zelleninnenabstand",
|
||||
"Cell spacing": "Zellenabstand",
|
||||
"Row type": "Zeilentyp",
|
||||
"Insert table": "Tabelle einf\u00fcgen",
|
||||
"Body": "Inhalt",
|
||||
"Caption": "Beschriftung",
|
||||
"Footer": "Fu\u00dfzeile",
|
||||
"Delete row": "Zeile l\u00f6schen",
|
||||
"Paste row before": "Zeile davor einf\u00fcgen",
|
||||
"Scope": "G\u00fcltigkeitsbereich",
|
||||
"Delete table": "Tabelle l\u00f6schen",
|
||||
"H Align": "Horizontale Ausrichtung",
|
||||
"Top": "Oben",
|
||||
"Header cell": "Kopfzelle",
|
||||
"Column": "Spalte",
|
||||
"Row group": "Zeilengruppe",
|
||||
"Cell": "Zelle",
|
||||
"Middle": "Mitte",
|
||||
"Cell type": "Zellentyp",
|
||||
"Copy row": "Zeile kopieren",
|
||||
"Row properties": "Zeileneigenschaften",
|
||||
"Table properties": "Tabelleneigenschaften",
|
||||
"Bottom": "Unten",
|
||||
"V Align": "Vertikale Ausrichtung",
|
||||
"Header": "Kopfzeile",
|
||||
"Right": "Rechtsb\u00fcndig",
|
||||
"Insert column after": "Neue Spalte danach einf\u00fcgen",
|
||||
"Cols": "Spalten",
|
||||
"Insert row after": "Neue Zeile danach einf\u00fcgen",
|
||||
"Width": "Breite",
|
||||
"Cell properties": "Zelleneigenschaften",
|
||||
"Left": "Linksb\u00fcndig",
|
||||
"Cut row": "Zeile ausschneiden",
|
||||
"Delete column": "Spalte l\u00f6schen",
|
||||
"Center": "Zentriert",
|
||||
"Merge cells": "Zellen verbinden",
|
||||
"Insert template": "Vorlage einf\u00fcgen ",
|
||||
"Templates": "Vorlagen",
|
||||
"Background color": "Hintergrundfarbe",
|
||||
"Custom...": "Benutzerdefiniert...",
|
||||
"Custom color": "Benutzerdefinierte Farbe",
|
||||
"No color": "Keine Farbe",
|
||||
"Text color": "Textfarbe",
|
||||
"Show blocks": " Bl\u00f6cke anzeigen",
|
||||
"Show invisible characters": "Unsichtbare Zeichen anzeigen",
|
||||
"Words: {0}": "W\u00f6rter: {0}",
|
||||
"Insert": "Einf\u00fcgen",
|
||||
"File": "Datei",
|
||||
"Edit": "Bearbeiten",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich-Text- Area. Dr\u00fccken Sie ALT-F9 f\u00fcr das Men\u00fc. Dr\u00fccken Sie ALT-F10 f\u00fcr Symbolleiste. Dr\u00fccken Sie ALT-0 f\u00fcr Hilfe",
|
||||
"Tools": "Werkzeuge",
|
||||
"View": "Ansicht",
|
||||
"Table": "Tabelle",
|
||||
"Format": "Format"
|
||||
});
|
||||
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js
Normal file
File diff suppressed because one or more lines are too long
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js
Normal file
File diff suppressed because one or more lines are too long
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('fi',{
|
||||
"Cut": "Leikkaa",
|
||||
"Heading 5": "Otsikko 5",
|
||||
"Header 2": "Otsikko 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Selaimesi ei tue leikep\u00f6yd\u00e4n suoraa k\u00e4ytt\u00e4mist\u00e4. Ole hyv\u00e4 ja k\u00e4yt\u00e4 n\u00e4pp\u00e4imist\u00f6n Ctrl+X\/C\/V n\u00e4pp\u00e4inyhdistelmi\u00e4.",
|
||||
"Heading 4": "Otsikko 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "Otsikko 2",
|
||||
"Paste": "Liit\u00e4",
|
||||
"Close": "Sulje",
|
||||
"Font Family": "Fontti",
|
||||
"Pre": "Esimuotoiltu",
|
||||
"Align right": "Tasaa oikealle",
|
||||
"New document": "Uusi dokumentti",
|
||||
"Blockquote": "Lainauslohko",
|
||||
"Numbered list": "J\u00e4rjestetty lista",
|
||||
"Heading 1": "Otsikko 1",
|
||||
"Headings": "Otsikot",
|
||||
"Increase indent": "Loitonna",
|
||||
"Formats": "Muotoilut",
|
||||
"Headers": "Otsikot",
|
||||
"Select all": "Valitse kaikki",
|
||||
"Header 3": "Otsikko 3",
|
||||
"Blocks": "Lohkot",
|
||||
"Undo": "Peru",
|
||||
"Strikethrough": "Yliviivaus",
|
||||
"Bullet list": "J\u00e4rjest\u00e4m\u00e4t\u00f6n lista",
|
||||
"Header 1": "Otsikko 1",
|
||||
"Superscript": "Yl\u00e4indeksi",
|
||||
"Clear formatting": "Poista muotoilu",
|
||||
"Font Sizes": "Fonttikoko",
|
||||
"Subscript": "Alaindeksi",
|
||||
"Header 6": "Otsikko 6",
|
||||
"Redo": "Tee uudelleen",
|
||||
"Paragraph": "Kappale",
|
||||
"Ok": "Ok",
|
||||
"Bold": "Lihavointi",
|
||||
"Code": "Koodi",
|
||||
"Italic": "Kursivointi",
|
||||
"Align center": "Keskit\u00e4",
|
||||
"Header 5": "Otsikko 5",
|
||||
"Heading 6": "Otsikko 6",
|
||||
"Heading 3": "Otsikko 3",
|
||||
"Decrease indent": "Sisenn\u00e4",
|
||||
"Header 4": "Otsikko 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Liitt\u00e4minen on nyt pelk\u00e4n tekstin -tilassa. Sis\u00e4ll\u00f6t liitet\u00e4\u00e4n nyt pelkk\u00e4n\u00e4 tekstin\u00e4, kunnes otat vaihtoehdon pois k\u00e4yt\u00f6st\u00e4.",
|
||||
"Underline": "Alleviivaus",
|
||||
"Cancel": "Peruuta",
|
||||
"Justify": "Tasaa",
|
||||
"Inline": "Samalla rivill\u00e4",
|
||||
"Copy": "Kopioi",
|
||||
"Align left": "Tasaa vasemmalle",
|
||||
"Visual aids": "Visuaaliset neuvot",
|
||||
"Lower Greek": "pienet kirjaimet: \u03b1, \u03b2, \u03b3",
|
||||
"Square": "Neli\u00f6",
|
||||
"Default": "Oletus",
|
||||
"Lower Alpha": "pienet kirjaimet: a, b, c",
|
||||
"Circle": "Pallo",
|
||||
"Disc": "Ympyr\u00e4",
|
||||
"Upper Alpha": "isot kirjaimet: A, B, C",
|
||||
"Upper Roman": "isot kirjaimet: I, II, III",
|
||||
"Lower Roman": "pienet kirjaimet: i, ii, iii",
|
||||
"Name": "Nimi",
|
||||
"Anchor": "Ankkuri",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Sinulla on tallentamattomia muutoksia, haluatko varmasti siirty\u00e4 toiselle sivulle?",
|
||||
"Restore last draft": "Palauta aiempi luonnos",
|
||||
"Special character": "Erikoismerkki",
|
||||
"Source code": "L\u00e4hdekoodi",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "V\u00e4ri",
|
||||
"Right to left": "Oikealta vasemmalle",
|
||||
"Left to right": "Vasemmalta oikealle",
|
||||
"Emoticons": "Hymi\u00f6t",
|
||||
"Robots": "Robotit",
|
||||
"Document properties": "Dokumentin ominaisuudet",
|
||||
"Title": "Otsikko",
|
||||
"Keywords": "Avainsanat",
|
||||
"Encoding": "Merkist\u00f6",
|
||||
"Description": "Kuvaus",
|
||||
"Author": "Tekij\u00e4",
|
||||
"Fullscreen": "Koko ruutu",
|
||||
"Horizontal line": "Vaakasuora viiva",
|
||||
"Horizontal space": "Horisontaalinen tila",
|
||||
"Insert\/edit image": "Lis\u00e4\u00e4\/muokkaa kuva",
|
||||
"General": "Yleiset",
|
||||
"Advanced": "Lis\u00e4asetukset",
|
||||
"Source": "L\u00e4hde",
|
||||
"Border": "Reunus",
|
||||
"Constrain proportions": "S\u00e4ilyt\u00e4 mittasuhteet",
|
||||
"Vertical space": "Vertikaalinen tila",
|
||||
"Image description": "Kuvaus",
|
||||
"Style": "Tyyli",
|
||||
"Dimensions": "Mittasuhteet",
|
||||
"Insert image": "Lis\u00e4\u00e4 kuva",
|
||||
"Zoom in": "L\u00e4henn\u00e4",
|
||||
"Contrast": "Kontrasti",
|
||||
"Back": "Takaisin",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "K\u00e4\u00e4nn\u00e4 vaakasuunnassa",
|
||||
"Resize": "Kuvan koon muutos",
|
||||
"Sharpen": "Ter\u00e4vyys",
|
||||
"Zoom out": "Loitonna",
|
||||
"Image options": "Kuvan asetukset",
|
||||
"Apply": "Aseta",
|
||||
"Brightness": "Kirkkaus",
|
||||
"Rotate clockwise": "Kierr\u00e4 my\u00f6t\u00e4p\u00e4iv\u00e4\u00e4n",
|
||||
"Rotate counterclockwise": "Kierr\u00e4 vastap\u00e4iv\u00e4\u00e4n",
|
||||
"Edit image": "Muokkaa kuvaa",
|
||||
"Color levels": "V\u00e4ritasot",
|
||||
"Crop": "Rajaa valintaan",
|
||||
"Orientation": "Suunta",
|
||||
"Flip vertically": "K\u00e4\u00e4nn\u00e4 pystysuunnassa",
|
||||
"Invert": "K\u00e4\u00e4nteinen",
|
||||
"Insert date\/time": "Lis\u00e4\u00e4 p\u00e4iv\u00e4m\u00e4\u00e4r\u00e4 tai aika",
|
||||
"Remove link": "Poista linkki",
|
||||
"Url": "Osoite",
|
||||
"Text to display": "N\u00e4ytett\u00e4v\u00e4 teksti",
|
||||
"Anchors": "Ankkurit",
|
||||
"Insert link": "Lis\u00e4\u00e4 linkki",
|
||||
"New window": "Uusi ikkuna",
|
||||
"None": "Ei mit\u00e4\u00e4n",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "Antamasi osoite n\u00e4ytt\u00e4\u00e4 olevan ulkoinen linkki. Haluatko lis\u00e4t\u00e4 osoitteeseen vaaditun http:\/\/ -etuliitteen?",
|
||||
"Target": "Kohde",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Antamasi osoite n\u00e4ytt\u00e4\u00e4 olevan s\u00e4hk\u00f6postiosoite. Haluatko lis\u00e4t\u00e4 osoitteeseen vaaditun mailto: -etuliitteen?",
|
||||
"Insert\/edit link": "Lis\u00e4\u00e4\/muokkaa linkki",
|
||||
"Insert\/edit video": "Lis\u00e4\u00e4\/muokkaa video",
|
||||
"Poster": "L\u00e4hett\u00e4j\u00e4",
|
||||
"Alternative source": "Vaihtoehtoinen l\u00e4hde",
|
||||
"Paste your embed code below:": "Liit\u00e4 upotuskoodisi alapuolelle:",
|
||||
"Insert video": "Lis\u00e4\u00e4 video",
|
||||
"Embed": "Upota",
|
||||
"Nonbreaking space": "Sitova v\u00e4lily\u00f6nti",
|
||||
"Page break": "Sivunvaihto",
|
||||
"Paste as text": "Liit\u00e4 tekstin\u00e4",
|
||||
"Preview": "Esikatselu",
|
||||
"Print": "Tulosta",
|
||||
"Save": "Tallenna",
|
||||
"Could not find the specified string.": "Haettua merkkijonoa ei l\u00f6ytynyt.",
|
||||
"Replace": "Korvaa",
|
||||
"Next": "Seur.",
|
||||
"Whole words": "Koko sanat",
|
||||
"Find and replace": "Etsi ja korvaa",
|
||||
"Replace with": "Korvaa",
|
||||
"Find": "Etsi",
|
||||
"Replace all": "Korvaa kaikki",
|
||||
"Match case": "Erota isot ja pienet kirjaimet",
|
||||
"Prev": "Edel.",
|
||||
"Spellcheck": "Oikolue",
|
||||
"Finish": "Lopeta",
|
||||
"Ignore all": "\u00c4l\u00e4 huomioi mit\u00e4\u00e4n",
|
||||
"Ignore": "\u00c4l\u00e4 huomioi",
|
||||
"Add to Dictionary": "Lis\u00e4\u00e4 sanakirjaan",
|
||||
"Insert row before": "Lis\u00e4\u00e4 rivi ennen",
|
||||
"Rows": "Rivit",
|
||||
"Height": "Korkeus",
|
||||
"Paste row after": "Liit\u00e4 rivi j\u00e4lkeen",
|
||||
"Alignment": "Tasaus",
|
||||
"Border color": "Reunuksen v\u00e4ri",
|
||||
"Column group": "Sarakeryhm\u00e4",
|
||||
"Row": "Rivi",
|
||||
"Insert column before": "Lis\u00e4\u00e4 rivi ennen",
|
||||
"Split cell": "Jaa solu",
|
||||
"Cell padding": "Solun tyhj\u00e4 tila",
|
||||
"Cell spacing": "Solun v\u00e4li",
|
||||
"Row type": "Rivityyppi",
|
||||
"Insert table": "Lis\u00e4\u00e4 taulukko",
|
||||
"Body": "Runko",
|
||||
"Caption": "Seloste",
|
||||
"Footer": "Alaosa",
|
||||
"Delete row": "Poista rivi",
|
||||
"Paste row before": "Liit\u00e4 rivi ennen",
|
||||
"Scope": "Laajuus",
|
||||
"Delete table": "Poista taulukko",
|
||||
"H Align": "H tasaus",
|
||||
"Top": "Yl\u00e4reuna",
|
||||
"Header cell": "Otsikkosolu",
|
||||
"Column": "Sarake",
|
||||
"Row group": "Riviryhm\u00e4",
|
||||
"Cell": "Solu",
|
||||
"Middle": "Keskikohta",
|
||||
"Cell type": "Solun tyyppi",
|
||||
"Copy row": "Kopioi rivi",
|
||||
"Row properties": "Rivin ominaisuudet",
|
||||
"Table properties": "Taulukon ominaisuudet",
|
||||
"Bottom": "Alareuna",
|
||||
"V Align": "V tasaus",
|
||||
"Header": "Otsikko",
|
||||
"Right": "Oikea",
|
||||
"Insert column after": "Lis\u00e4\u00e4 rivi j\u00e4lkeen",
|
||||
"Cols": "Sarakkeet",
|
||||
"Insert row after": "Lis\u00e4\u00e4 rivi j\u00e4lkeen",
|
||||
"Width": "Leveys",
|
||||
"Cell properties": "Solun ominaisuudet",
|
||||
"Left": "Vasen",
|
||||
"Cut row": "Leikkaa rivi",
|
||||
"Delete column": "Poista sarake",
|
||||
"Center": "Keskell\u00e4",
|
||||
"Merge cells": "Yhdist\u00e4 solut",
|
||||
"Insert template": "Lis\u00e4\u00e4 pohja",
|
||||
"Templates": "Pohjat",
|
||||
"Background color": "Taustan v\u00e4ri",
|
||||
"Custom...": "Mukauta...",
|
||||
"Custom color": "Mukautettu v\u00e4ri",
|
||||
"No color": "Ei v\u00e4ri\u00e4",
|
||||
"Text color": "Tekstin v\u00e4ri",
|
||||
"Show blocks": "N\u00e4yt\u00e4 lohkot",
|
||||
"Show invisible characters": "N\u00e4yt\u00e4 n\u00e4kym\u00e4tt\u00f6m\u00e4t merkit",
|
||||
"Words: {0}": "Sanat: {0}",
|
||||
"Insert": "Lis\u00e4\u00e4",
|
||||
"File": "Tiedosto",
|
||||
"Edit": "Muokkaa",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rikastetun tekstin alue. Paina ALT-F9 valikkoon. Paina ALT-F10 ty\u00f6kaluriviin. Paina ALT-0 ohjeeseen.",
|
||||
"Tools": "Ty\u00f6kalut",
|
||||
"View": "N\u00e4yt\u00e4",
|
||||
"Table": "Taulukko",
|
||||
"Format": "Muotoilu"
|
||||
});
|
||||
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js
Normal file
File diff suppressed because one or more lines are too long
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js
Normal file
File diff suppressed because one or more lines are too long
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('it',{
|
||||
"Cut": "Taglia",
|
||||
"Heading 5": "Intestazione 5",
|
||||
"Header 2": "Header 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Il tuo browser non supporta l'accesso diretto negli Appunti. Per favore usa i tasti di scelta rapida Ctrl+X\/C\/V.",
|
||||
"Heading 4": "Intestazione 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "Intestazione 2",
|
||||
"Paste": "Incolla",
|
||||
"Close": "Chiudi",
|
||||
"Font Family": "Famiglia font",
|
||||
"Pre": "Pre",
|
||||
"Align right": "Allinea a Destra",
|
||||
"New document": "Nuovo Documento",
|
||||
"Blockquote": "Blockquote",
|
||||
"Numbered list": "Elenchi Numerati",
|
||||
"Heading 1": "Intestazione 1",
|
||||
"Headings": "Intestazioni",
|
||||
"Increase indent": "Aumenta Rientro",
|
||||
"Formats": "Formattazioni",
|
||||
"Headers": "Intestazioni",
|
||||
"Select all": "Seleziona Tutto",
|
||||
"Header 3": "Intestazione 3",
|
||||
"Blocks": "Blocchi",
|
||||
"Undo": "Indietro",
|
||||
"Strikethrough": "Barrato",
|
||||
"Bullet list": "Elenchi Puntati",
|
||||
"Header 1": "Intestazione 1",
|
||||
"Superscript": "Apice",
|
||||
"Clear formatting": "Cancella Formattazione",
|
||||
"Font Sizes": "Dimensioni font",
|
||||
"Subscript": "Pedice",
|
||||
"Header 6": "Intestazione 6",
|
||||
"Redo": "Ripeti",
|
||||
"Paragraph": "Paragrafo",
|
||||
"Ok": "Ok",
|
||||
"Bold": "Grassetto",
|
||||
"Code": "Codice",
|
||||
"Italic": "Corsivo",
|
||||
"Align center": "Allinea al Cento",
|
||||
"Header 5": "Intestazione 5",
|
||||
"Heading 6": "Intestazione 6",
|
||||
"Heading 3": "Intestazione 3",
|
||||
"Decrease indent": "Riduci Rientro",
|
||||
"Header 4": "Intestazione 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Incolla \u00e8 in modalit\u00e0 testo normale. I contenuti sono incollati come testo normale se non disattivi l'opzione.",
|
||||
"Underline": "Sottolineato",
|
||||
"Cancel": "Annulla",
|
||||
"Justify": "Giustifica",
|
||||
"Inline": "Inlinea",
|
||||
"Copy": "Copia",
|
||||
"Align left": "Allinea a Sinistra",
|
||||
"Visual aids": "Elementi Visivi",
|
||||
"Lower Greek": "Greek Minore",
|
||||
"Square": "Quadrato",
|
||||
"Default": "Default",
|
||||
"Lower Alpha": "Alpha Minore",
|
||||
"Circle": "Cerchio",
|
||||
"Disc": "Disco",
|
||||
"Upper Alpha": "Alpha Superiore",
|
||||
"Upper Roman": "Roman Superiore",
|
||||
"Lower Roman": "Roman Minore",
|
||||
"Name": "Nome",
|
||||
"Anchor": "Fissa",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Non hai salvato delle modifiche, sei sicuro di andartene?",
|
||||
"Restore last draft": "Ripristina l'ultima bozza.",
|
||||
"Special character": "Carattere Speciale",
|
||||
"Source code": "Codice Sorgente",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "Colore",
|
||||
"Right to left": "Da Destra a Sinistra",
|
||||
"Left to right": "Da Sinistra a Destra",
|
||||
"Emoticons": "Emoction",
|
||||
"Robots": "Robot",
|
||||
"Document properties": "Propriet\u00e0 Documento",
|
||||
"Title": "Titolo",
|
||||
"Keywords": "Parola Chiave",
|
||||
"Encoding": "Codifica",
|
||||
"Description": "Descrizione",
|
||||
"Author": "Autore",
|
||||
"Fullscreen": "Schermo Intero",
|
||||
"Horizontal line": "Linea Orizzontale",
|
||||
"Horizontal space": "Spazio Orizzontale",
|
||||
"Insert\/edit image": "Aggiungi\/Modifica Immagine",
|
||||
"General": "Generale",
|
||||
"Advanced": "Avanzato",
|
||||
"Source": "Fonte",
|
||||
"Border": "Bordo",
|
||||
"Constrain proportions": "Mantieni Proporzioni",
|
||||
"Vertical space": "Spazio Verticale",
|
||||
"Image description": "Descrizione Immagine",
|
||||
"Style": "Stile",
|
||||
"Dimensions": "Dimenzioni",
|
||||
"Insert image": "Inserisci immagine",
|
||||
"Zoom in": "Ingrandisci",
|
||||
"Contrast": "Contrasto",
|
||||
"Back": "Indietro",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "Rifletti orizzontalmente",
|
||||
"Resize": "Ridimensiona",
|
||||
"Sharpen": "Contrasta",
|
||||
"Zoom out": "Rimpicciolisci",
|
||||
"Image options": "Opzioni immagine",
|
||||
"Apply": "Applica",
|
||||
"Brightness": "Luminosit\u00e0",
|
||||
"Rotate clockwise": "Ruota in senso orario",
|
||||
"Rotate counterclockwise": "Ruota in senso antiorario",
|
||||
"Edit image": "Modifica immagine",
|
||||
"Color levels": "Livelli colore",
|
||||
"Crop": "Taglia",
|
||||
"Orientation": "Orientamento",
|
||||
"Flip vertically": "Rifletti verticalmente",
|
||||
"Invert": "Inverti",
|
||||
"Insert date\/time": "Inserisci Data\/Ora",
|
||||
"Remove link": "Rimuovi link",
|
||||
"Url": "Url",
|
||||
"Text to display": "Testo da Visualizzare",
|
||||
"Anchors": "Anchors",
|
||||
"Insert link": "Inserisci il Link",
|
||||
"New window": "Nuova Finestra",
|
||||
"None": "No",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "L'URL inserito sembra essere un collegamento esterno. Vuoi aggiungere il prefisso necessario http:\/\/?",
|
||||
"Target": "Target",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "L'URL inserito sembra essere un indirizzo email. Vuoi aggiungere il prefisso necessario mailto:?",
|
||||
"Insert\/edit link": "Inserisci\/Modifica Link",
|
||||
"Insert\/edit video": "Inserisci\/Modifica Video",
|
||||
"Poster": "Anteprima",
|
||||
"Alternative source": "Alternativo",
|
||||
"Paste your embed code below:": "Incolla il codice d'incorporamento qui:",
|
||||
"Insert video": "Inserisci Video",
|
||||
"Embed": "Incorporare",
|
||||
"Nonbreaking space": "Spazio unificatore",
|
||||
"Page break": "Interruzione di pagina",
|
||||
"Paste as text": "incolla come testo",
|
||||
"Preview": "Anteprima",
|
||||
"Print": "Stampa",
|
||||
"Save": "Salva",
|
||||
"Could not find the specified string.": "Impossibile trovare la parola specifica.",
|
||||
"Replace": "Sostituisci",
|
||||
"Next": "Successivo",
|
||||
"Whole words": "Parole Sbagliate",
|
||||
"Find and replace": "Trova e Sostituisci",
|
||||
"Replace with": "Sostituisci Con",
|
||||
"Find": "Trova",
|
||||
"Replace all": "Sostituisci Tutto",
|
||||
"Match case": "Maiuscole\/Minuscole ",
|
||||
"Prev": "Precedente",
|
||||
"Spellcheck": "Controllo ortografico",
|
||||
"Finish": "Termina",
|
||||
"Ignore all": "Ignora Tutto",
|
||||
"Ignore": "Ignora",
|
||||
"Add to Dictionary": "Aggiungi al Dizionario",
|
||||
"Insert row before": "Inserisci una Riga Prima",
|
||||
"Rows": "Righe",
|
||||
"Height": "Altezza",
|
||||
"Paste row after": "Incolla una Riga Dopo",
|
||||
"Alignment": "Allineamento",
|
||||
"Border color": "Colore bordo",
|
||||
"Column group": "Gruppo di Colonne",
|
||||
"Row": "Riga",
|
||||
"Insert column before": "Inserisci una Colonna Prima",
|
||||
"Split cell": "Dividi Cella",
|
||||
"Cell padding": "Padding della Cella",
|
||||
"Cell spacing": "Spaziatura della Cella",
|
||||
"Row type": "Tipo di Riga",
|
||||
"Insert table": "Inserisci Tabella",
|
||||
"Body": "Body",
|
||||
"Caption": "Didascalia",
|
||||
"Footer": "Footer",
|
||||
"Delete row": "Cancella Riga",
|
||||
"Paste row before": "Incolla una Riga Prima",
|
||||
"Scope": "Campo",
|
||||
"Delete table": "Cancella Tabella",
|
||||
"H Align": "Allineamento H",
|
||||
"Top": "In alto",
|
||||
"Header cell": "cella d'intestazione",
|
||||
"Column": "Colonna",
|
||||
"Row group": "Gruppo di Righe",
|
||||
"Cell": "Cella",
|
||||
"Middle": "In mezzo",
|
||||
"Cell type": "Tipo di Cella",
|
||||
"Copy row": "Copia Riga",
|
||||
"Row properties": "Propriet\u00e0 della Riga",
|
||||
"Table properties": "Propiet\u00e0 della Tabella",
|
||||
"Bottom": "In fondo",
|
||||
"V Align": "Allineamento V",
|
||||
"Header": "Header",
|
||||
"Right": "Destra",
|
||||
"Insert column after": "Inserisci una Colonna Dopo",
|
||||
"Cols": "Colonne",
|
||||
"Insert row after": "Inserisci una Riga Dopo",
|
||||
"Width": "Larghezza",
|
||||
"Cell properties": "Propiet\u00e0 della Cella",
|
||||
"Left": "Sinistra",
|
||||
"Cut row": "Taglia Riga",
|
||||
"Delete column": "Cancella Colonna",
|
||||
"Center": "Centro",
|
||||
"Merge cells": "Unisci Cella",
|
||||
"Insert template": "Inserisci Template",
|
||||
"Templates": "Template",
|
||||
"Background color": "Colore Background",
|
||||
"Custom...": "Personalizzato...",
|
||||
"Custom color": "Colore personalizzato",
|
||||
"No color": "Nessun colore",
|
||||
"Text color": "Colore Testo",
|
||||
"Show blocks": "Mostra Blocchi",
|
||||
"Show invisible characters": "Mostra Caratteri Invisibili",
|
||||
"Words: {0}": "Parole: {0}",
|
||||
"Insert": "Inserisci",
|
||||
"File": "File",
|
||||
"Edit": "Modifica",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Premi ALT-F9 per il men\u00f9. Premi ALT-F10 per la barra degli strumenti. Premi ALT-0 per l'aiuto.",
|
||||
"Tools": "Strumenti",
|
||||
"View": "Visualiza",
|
||||
"Table": "Tabella",
|
||||
"Format": "Formato"
|
||||
});
|
||||
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('ja',{
|
||||
"Cut": "\u5207\u308a\u53d6\u308a",
|
||||
"Heading 5": "\u898b\u51fa\u3057 5",
|
||||
"Header 2": "\u30d8\u30c3\u30c0\u30fc 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u304a\u4f7f\u3044\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u306f\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u6a5f\u80fd\u3092\u5229\u7528\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002\u30ad\u30fc\u30dc\u30fc\u30c9\u306e\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\uff08Ctrl+X, Ctrl+C, Ctrl+V\uff09\u3092\u304a\u4f7f\u3044\u4e0b\u3055\u3044\u3002",
|
||||
"Heading 4": "\u898b\u51fa\u3057 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "\u898b\u51fa\u3057 2",
|
||||
"Paste": "\u8cbc\u308a\u4ed8\u3051",
|
||||
"Close": "\u9589\u3058\u308b",
|
||||
"Font Family": "\u30d5\u30a9\u30f3\u30c8\u30d5\u30a1\u30df\u30ea\u30fc",
|
||||
"Pre": "Pre",
|
||||
"Align right": "\u53f3\u5bc4\u305b",
|
||||
"New document": "\u65b0\u898f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8",
|
||||
"Blockquote": "\u5f15\u7528",
|
||||
"Numbered list": "\u756a\u53f7\u4ed8\u304d\u7b87\u6761\u66f8\u304d",
|
||||
"Heading 1": "\u898b\u51fa\u3057 1",
|
||||
"Headings": "\u898b\u51fa\u3057",
|
||||
"Increase indent": "\u30a4\u30f3\u30c7\u30f3\u30c8\u3092\u5897\u3084\u3059",
|
||||
"Formats": "\u66f8\u5f0f",
|
||||
"Headers": "\u30d8\u30c3\u30c0\u30fc",
|
||||
"Select all": "\u5168\u3066\u3092\u9078\u629e",
|
||||
"Header 3": "\u30d8\u30c3\u30c0\u30fc 3",
|
||||
"Blocks": "\u30d6\u30ed\u30c3\u30af",
|
||||
"Undo": "\u5143\u306b\u623b\u3059",
|
||||
"Strikethrough": "\u53d6\u308a\u6d88\u3057\u7dda",
|
||||
"Bullet list": "\u7b87\u6761\u66f8\u304d",
|
||||
"Header 1": "\u30d8\u30c3\u30c0\u30fc 1",
|
||||
"Superscript": "\u4e0a\u4ed8\u304d\u6587\u5b57",
|
||||
"Clear formatting": "\u66f8\u5f0f\u3092\u30af\u30ea\u30a2",
|
||||
"Font Sizes": "\u30d5\u30a9\u30f3\u30c8\u30b5\u30a4\u30ba",
|
||||
"Subscript": "\u4e0b\u4ed8\u304d\u6587\u5b57",
|
||||
"Header 6": "\u30d8\u30c3\u30c0\u30fc 6",
|
||||
"Redo": "\u3084\u308a\u76f4\u3059",
|
||||
"Paragraph": "\u6bb5\u843d",
|
||||
"Ok": "OK",
|
||||
"Bold": "\u592a\u5b57",
|
||||
"Code": "\u30b3\u30fc\u30c9",
|
||||
"Italic": "\u659c\u4f53",
|
||||
"Align center": "\u4e2d\u592e\u63c3\u3048",
|
||||
"Header 5": "\u30d8\u30c3\u30c0\u30fc 5",
|
||||
"Heading 6": "\u898b\u51fa\u3057 6",
|
||||
"Heading 3": "\u898b\u51fa\u3057 3",
|
||||
"Decrease indent": "\u30a4\u30f3\u30c7\u30f3\u30c8\u3092\u6e1b\u3089\u3059",
|
||||
"Header 4": "\u30d8\u30c3\u30c0\u30fc 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u8cbc\u308a\u4ed8\u3051\u306f\u73fe\u5728\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8\u30e2\u30fc\u30c9\u3067\u3059\u3002\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u30aa\u30d5\u306b\u3057\u306a\u3044\u9650\u308a\u5185\u5bb9\u306f\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8\u3068\u3057\u3066\u8cbc\u308a\u4ed8\u3051\u3089\u308c\u307e\u3059\u3002",
|
||||
"Underline": "\u4e0b\u7dda",
|
||||
"Cancel": "\u30ad\u30e3\u30f3\u30bb\u30eb",
|
||||
"Justify": "\u4e21\u7aef\u63c3\u3048",
|
||||
"Inline": "\u30a4\u30f3\u30e9\u30a4\u30f3",
|
||||
"Copy": "\u30b3\u30d4\u30fc",
|
||||
"Align left": "\u5de6\u5bc4\u305b",
|
||||
"Visual aids": "\u8868\u306e\u67a0\u7dda\u3092\u70b9\u7dda\u3067\u8868\u793a",
|
||||
"Lower Greek": "\u5c0f\u6587\u5b57\u306e\u30ae\u30ea\u30b7\u30e3\u6587\u5b57",
|
||||
"Square": "\u56db\u89d2",
|
||||
"Default": "\u30c7\u30d5\u30a9\u30eb\u30c8",
|
||||
"Lower Alpha": "\u5c0f\u6587\u5b57\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8",
|
||||
"Circle": "\u5186",
|
||||
"Disc": "\u70b9",
|
||||
"Upper Alpha": "\u5927\u6587\u5b57\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8",
|
||||
"Upper Roman": "\u5927\u6587\u5b57\u306e\u30ed\u30fc\u30de\u6570\u5b57",
|
||||
"Lower Roman": "\u5c0f\u6587\u5b57\u306e\u30ed\u30fc\u30de\u6570\u5b57",
|
||||
"Name": "\u30a2\u30f3\u30ab\u30fc\u540d",
|
||||
"Anchor": "\u30a2\u30f3\u30ab\u30fc\uff08\u30ea\u30f3\u30af\u306e\u5230\u9054\u70b9\uff09",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "\u307e\u3060\u4fdd\u5b58\u3057\u3066\u3044\u306a\u3044\u5909\u66f4\u304c\u3042\u308a\u307e\u3059\u304c\u3001\u672c\u5f53\u306b\u3053\u306e\u30da\u30fc\u30b8\u3092\u96e2\u308c\u307e\u3059\u304b\uff1f",
|
||||
"Restore last draft": "\u524d\u56de\u306e\u4e0b\u66f8\u304d\u3092\u5fa9\u6d3b\u3055\u305b\u308b",
|
||||
"Special character": "\u7279\u6b8a\u6587\u5b57",
|
||||
"Source code": "\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "\u30ab\u30e9\u30fc",
|
||||
"Right to left": "\u53f3\u304b\u3089\u5de6",
|
||||
"Left to right": "\u5de6\u304b\u3089\u53f3",
|
||||
"Emoticons": "\u7d75\u6587\u5b57",
|
||||
"Robots": "\u30ed\u30dc\u30c3\u30c4",
|
||||
"Document properties": "\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u30d7\u30ed\u30d1\u30c6\u30a3",
|
||||
"Title": "\u30bf\u30a4\u30c8\u30eb",
|
||||
"Keywords": "\u30ad\u30fc\u30ef\u30fc\u30c9",
|
||||
"Encoding": "\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0",
|
||||
"Description": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u5185\u5bb9",
|
||||
"Author": "\u8457\u8005",
|
||||
"Fullscreen": "\u5168\u753b\u9762\u8868\u793a",
|
||||
"Horizontal line": "\u6c34\u5e73\u7f6b\u7dda",
|
||||
"Horizontal space": "\u6a2a\u65b9\u5411\u306e\u4f59\u767d",
|
||||
"Insert\/edit image": "\u753b\u50cf\u306e\u633f\u5165\u30fb\u7de8\u96c6",
|
||||
"General": "\u4e00\u822c",
|
||||
"Advanced": "\u8a73\u7d30\u8a2d\u5b9a",
|
||||
"Source": "\u753b\u50cf\u306e\u30bd\u30fc\u30b9",
|
||||
"Border": "\u67a0\u7dda",
|
||||
"Constrain proportions": "\u7e26\u6a2a\u6bd4\u3092\u4fdd\u6301\u3059\u308b",
|
||||
"Vertical space": "\u7e26\u65b9\u5411\u306e\u4f59\u767d",
|
||||
"Image description": "\u753b\u50cf\u306e\u8aac\u660e\u6587",
|
||||
"Style": "\u30b9\u30bf\u30a4\u30eb",
|
||||
"Dimensions": "\u753b\u50cf\u30b5\u30a4\u30ba\uff08\u6a2a\u30fb\u7e26\uff09",
|
||||
"Insert image": "\u753b\u50cf\u306e\u633f\u5165",
|
||||
"Zoom in": "\u30ba\u30fc\u30e0\u30a4\u30f3",
|
||||
"Contrast": "\u30b3\u30f3\u30c8\u30e9\u30b9\u30c8",
|
||||
"Back": "\u623b\u308b",
|
||||
"Gamma": "\u30ac\u30f3\u30de",
|
||||
"Flip horizontally": "\u6c34\u5e73\u306b\u53cd\u8ee2",
|
||||
"Resize": "\u30ea\u30b5\u30a4\u30ba",
|
||||
"Sharpen": "\u30b7\u30e3\u30fc\u30d7\u5316",
|
||||
"Zoom out": "\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8",
|
||||
"Image options": "\u753b\u50cf\u30aa\u30d7\u30b7\u30e7\u30f3",
|
||||
"Apply": "\u9069\u7528",
|
||||
"Brightness": "\u660e\u308b\u3055",
|
||||
"Rotate clockwise": "\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2",
|
||||
"Rotate counterclockwise": "\u53cd\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2",
|
||||
"Edit image": "\u753b\u50cf\u306e\u7de8\u96c6",
|
||||
"Color levels": "\u30ab\u30e9\u30fc\u30ec\u30d9\u30eb",
|
||||
"Crop": "\u30af\u30ed\u30c3\u30d7",
|
||||
"Orientation": "\u5411\u304d",
|
||||
"Flip vertically": "\u4e0a\u4e0b\u306b\u53cd\u8ee2",
|
||||
"Invert": "\u53cd\u8ee2",
|
||||
"Insert date\/time": "\u65e5\u4ed8\u30fb\u6642\u523b",
|
||||
"Remove link": "\u30ea\u30f3\u30af\u306e\u524a\u9664",
|
||||
"Url": "\u30ea\u30f3\u30af\u5148URL",
|
||||
"Text to display": "\u30ea\u30f3\u30af\u5143\u30c6\u30ad\u30b9\u30c8",
|
||||
"Anchors": "\u30a2\u30f3\u30ab\u30fc\uff08\u30ea\u30f3\u30af\u306e\u5230\u9054\u70b9\uff09",
|
||||
"Insert link": "\u30ea\u30f3\u30af",
|
||||
"New window": "\u65b0\u898f\u30a6\u30a3\u30f3\u30c9\u30a6",
|
||||
"None": "\u306a\u3057",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u5165\u529b\u3055\u308c\u305fURL\u306f\u5916\u90e8\u30ea\u30f3\u30af\u306e\u3088\u3046\u3067\u3059\u3002\u300chttp:\/\/\u300d\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f",
|
||||
"Target": "\u30bf\u30fc\u30b2\u30c3\u30c8\u5c5e\u6027",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u5165\u529b\u3055\u308c\u305fURL\u306f\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u3088\u3046\u3067\u3059\u3002\u300cmailto:\u300d\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f",
|
||||
"Insert\/edit link": "\u30ea\u30f3\u30af\u306e\u633f\u5165\u30fb\u7de8\u96c6",
|
||||
"Insert\/edit video": "\u52d5\u753b\u306e\u633f\u5165\u30fb\u7de8\u96c6",
|
||||
"Poster": "\u4ee3\u66ff\u753b\u50cf\u306e\u5834\u6240",
|
||||
"Alternative source": "\u4ee3\u66ff\u52d5\u753b\u306e\u5834\u6240",
|
||||
"Paste your embed code below:": "\u57cb\u3081\u8fbc\u307f\u7528\u30b3\u30fc\u30c9\u3092\u4e0b\u8a18\u306b\u8cbc\u308a\u4ed8\u3051\u3066\u304f\u3060\u3055\u3044\u3002",
|
||||
"Insert video": "\u52d5\u753b",
|
||||
"Embed": "\u57cb\u3081\u8fbc\u307f",
|
||||
"Nonbreaking space": "\u56fa\u5b9a\u30b9\u30da\u30fc\u30b9\uff08 \uff09",
|
||||
"Page break": "\u30da\u30fc\u30b8\u533a\u5207\u308a",
|
||||
"Paste as text": "\u30c6\u30ad\u30b9\u30c8\u3068\u3057\u3066\u8cbc\u308a\u4ed8\u3051",
|
||||
"Preview": "\u30d7\u30ec\u30d3\u30e5\u30fc",
|
||||
"Print": "\u5370\u5237",
|
||||
"Save": "\u4fdd\u5b58",
|
||||
"Could not find the specified string.": "\u304a\u63a2\u3057\u306e\u6587\u5b57\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002",
|
||||
"Replace": "\u7f6e\u304d\u63db\u3048",
|
||||
"Next": "\u6b21",
|
||||
"Whole words": "\u5358\u8a9e\u5358\u4f4d\u3067\u691c\u7d22\u3059\u308b",
|
||||
"Find and replace": "\u691c\u7d22\u3068\u7f6e\u304d\u63db\u3048",
|
||||
"Replace with": "\u7f6e\u304d\u63db\u3048\u308b\u6587\u5b57",
|
||||
"Find": "\u691c\u7d22",
|
||||
"Replace all": "\u5168\u3066\u3092\u7f6e\u304d\u63db\u3048\u308b",
|
||||
"Match case": "\u5927\u6587\u5b57\u30fb\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3059\u308b",
|
||||
"Prev": "\u524d",
|
||||
"Spellcheck": "\u30b9\u30da\u30eb\u30c1\u30a7\u30c3\u30af",
|
||||
"Finish": "\u7d42\u4e86",
|
||||
"Ignore all": "\u5168\u3066\u3092\u7121\u8996",
|
||||
"Ignore": "\u7121\u8996",
|
||||
"Add to Dictionary": "\u8f9e\u66f8\u306b\u8ffd\u52a0",
|
||||
"Insert row before": "\u4e0a\u5074\u306b\u884c\u3092\u633f\u5165",
|
||||
"Rows": "\u884c\u6570",
|
||||
"Height": "\u9ad8\u3055",
|
||||
"Paste row after": "\u4e0b\u5074\u306b\u884c\u3092\u8cbc\u308a\u4ed8\u3051",
|
||||
"Alignment": "\u914d\u7f6e",
|
||||
"Border color": "\u67a0\u7dda\u306e\u8272",
|
||||
"Column group": "\u5217\u30b0\u30eb\u30fc\u30d7",
|
||||
"Row": "\u884c",
|
||||
"Insert column before": "\u5de6\u5074\u306b\u5217\u3092\u633f\u5165",
|
||||
"Split cell": "\u30bb\u30eb\u306e\u5206\u5272",
|
||||
"Cell padding": "\u30bb\u30eb\u5185\u4f59\u767d\uff08\u30d1\u30c7\u30a3\u30f3\u30b0\uff09",
|
||||
"Cell spacing": "\u30bb\u30eb\u306e\u9593\u9694",
|
||||
"Row type": "\u884c\u30bf\u30a4\u30d7",
|
||||
"Insert table": "\u8868\u306e\u633f\u5165",
|
||||
"Body": "\u30dc\u30c7\u30a3\u30fc",
|
||||
"Caption": "\u8868\u984c",
|
||||
"Footer": "\u30d5\u30c3\u30bf\u30fc",
|
||||
"Delete row": "\u884c\u306e\u524a\u9664",
|
||||
"Paste row before": "\u4e0a\u5074\u306b\u884c\u3092\u8cbc\u308a\u4ed8\u3051",
|
||||
"Scope": "\u30b9\u30b3\u30fc\u30d7",
|
||||
"Delete table": "\u8868\u306e\u524a\u9664",
|
||||
"H Align": "\u6c34\u5e73\u65b9\u5411\u306e\u914d\u7f6e",
|
||||
"Top": "\u4e0a",
|
||||
"Header cell": "\u30d8\u30c3\u30c0\u30fc\u30bb\u30eb",
|
||||
"Column": "\u5217",
|
||||
"Row group": "\u884c\u30b0\u30eb\u30fc\u30d7",
|
||||
"Cell": "\u30bb\u30eb",
|
||||
"Middle": "\u4e2d\u592e",
|
||||
"Cell type": "\u30bb\u30eb\u30bf\u30a4\u30d7",
|
||||
"Copy row": "\u884c\u306e\u30b3\u30d4\u30fc",
|
||||
"Row properties": "\u884c\u306e\u8a73\u7d30\u8a2d\u5b9a",
|
||||
"Table properties": "\u8868\u306e\u8a73\u7d30\u8a2d\u5b9a",
|
||||
"Bottom": "\u4e0b",
|
||||
"V Align": "\u5782\u76f4\u65b9\u5411\u306e\u914d\u7f6e",
|
||||
"Header": "\u30d8\u30c3\u30c0\u30fc",
|
||||
"Right": "\u53f3\u5bc4\u305b",
|
||||
"Insert column after": "\u53f3\u5074\u306b\u5217\u3092\u633f\u5165",
|
||||
"Cols": "\u5217\u6570",
|
||||
"Insert row after": "\u4e0b\u5074\u306b\u884c\u3092\u633f\u5165",
|
||||
"Width": "\u5e45",
|
||||
"Cell properties": "\u30bb\u30eb\u306e\u8a73\u7d30\u8a2d\u5b9a",
|
||||
"Left": "\u5de6\u5bc4\u305b",
|
||||
"Cut row": "\u884c\u306e\u5207\u308a\u53d6\u308a",
|
||||
"Delete column": "\u5217\u306e\u524a\u9664",
|
||||
"Center": "\u4e2d\u592e\u63c3\u3048",
|
||||
"Merge cells": "\u30bb\u30eb\u306e\u7d50\u5408",
|
||||
"Insert template": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u633f\u5165",
|
||||
"Templates": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u540d",
|
||||
"Background color": "\u80cc\u666f\u8272",
|
||||
"Custom...": "\u30ab\u30b9\u30bf\u30e0...",
|
||||
"Custom color": "\u30ab\u30b9\u30bf\u30e0\u30ab\u30e9\u30fc",
|
||||
"No color": "\u30ab\u30e9\u30fc\u306a\u3057",
|
||||
"Text color": "\u30c6\u30ad\u30b9\u30c8\u306e\u8272",
|
||||
"Show blocks": "\u6587\u7ae0\u306e\u533a\u5207\u308a\u3092\u70b9\u7dda\u3067\u8868\u793a",
|
||||
"Show invisible characters": "\u4e0d\u53ef\u8996\u6587\u5b57\u3092\u8868\u793a",
|
||||
"Words: {0}": "\u5358\u8a9e\u6570: {0}",
|
||||
"Insert": "\u633f\u5165",
|
||||
"File": "\u30d5\u30a1\u30a4\u30eb",
|
||||
"Edit": "\u7de8\u96c6",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u66f8\u5f0f\u4ed8\u304d\u30c6\u30ad\u30b9\u30c8\u306e\u7de8\u96c6\u753b\u9762\u3002ALT-F9\u3067\u30e1\u30cb\u30e5\u30fc\u3001ALT-F10\u3067\u30c4\u30fc\u30eb\u30d0\u30fc\u3001ALT-0\u3067\u30d8\u30eb\u30d7\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u3002",
|
||||
"Tools": "\u30c4\u30fc\u30eb",
|
||||
"View": "\u8868\u793a",
|
||||
"Table": "\u8868",
|
||||
"Format": "\u66f8\u5f0f"
|
||||
});
|
||||
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('nl',{
|
||||
"Cut": "Knippen",
|
||||
"Heading 5": "Kop 5",
|
||||
"Header 2": "Kop 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Uw browser ondersteunt geen toegang tot het clipboard. Gelieve ctrl+X\/C\/V sneltoetsen te gebruiken.",
|
||||
"Heading 4": "Kop 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "Kop 2",
|
||||
"Paste": "Plakken",
|
||||
"Close": "Sluiten",
|
||||
"Font Family": "Lettertype",
|
||||
"Pre": "Pre",
|
||||
"Align right": "Rechts uitlijnen",
|
||||
"New document": "Nieuw document",
|
||||
"Blockquote": "Quote",
|
||||
"Numbered list": "Nummering",
|
||||
"Heading 1": "Kop 1",
|
||||
"Headings": "Koppen",
|
||||
"Increase indent": "Inspringen vergroten",
|
||||
"Formats": "Opmaak",
|
||||
"Headers": "Kopteksten",
|
||||
"Select all": "Alles selecteren",
|
||||
"Header 3": "Kop 3",
|
||||
"Blocks": "Blok",
|
||||
"Undo": "Ongedaan maken",
|
||||
"Strikethrough": "Doorhalen",
|
||||
"Bullet list": "Opsommingsteken",
|
||||
"Header 1": "Kop 1",
|
||||
"Superscript": "Superscript",
|
||||
"Clear formatting": "Opmaak verwijderen",
|
||||
"Font Sizes": "Tekengrootte",
|
||||
"Subscript": "Subscript",
|
||||
"Header 6": "Kop 6",
|
||||
"Redo": "Opnieuw",
|
||||
"Paragraph": "Paragraaf",
|
||||
"Ok": "Ok\u00e9",
|
||||
"Bold": "Vet",
|
||||
"Code": "Code",
|
||||
"Italic": "Cursief",
|
||||
"Align center": "Centreren",
|
||||
"Header 5": "Kop 5",
|
||||
"Heading 6": "Kop 6",
|
||||
"Heading 3": "Kop 3",
|
||||
"Decrease indent": "Inspringen verkleinen",
|
||||
"Header 4": "Kop 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Plakken gebeurt nu als platte tekst. Tekst wordt nu ingevoegd zonder opmaak tot deze optie uitgeschakeld wordt.",
|
||||
"Underline": "Onderstreept",
|
||||
"Cancel": "Annuleren",
|
||||
"Justify": "Uitlijnen",
|
||||
"Inline": "Inlijn",
|
||||
"Copy": "Kopi\u00ebren",
|
||||
"Align left": "Links uitlijnen",
|
||||
"Visual aids": "Hulpmiddelen",
|
||||
"Lower Greek": "Griekse letters",
|
||||
"Square": "Vierkant",
|
||||
"Default": "Standaard",
|
||||
"Lower Alpha": "Kleine letters",
|
||||
"Circle": "Cirkel",
|
||||
"Disc": "Bolletje",
|
||||
"Upper Alpha": "Hoofdletters",
|
||||
"Upper Roman": "Romeinse cijfers groot",
|
||||
"Lower Roman": "Romeinse cijfers klein",
|
||||
"Name": "Naam",
|
||||
"Anchor": "Anker",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "U hebt niet alles opgeslagen bent u zeker dat u de pagina wenst te verlaten?",
|
||||
"Restore last draft": "Herstel het laatste concept",
|
||||
"Special character": "Speciale karakters",
|
||||
"Source code": "Broncode",
|
||||
"B": "Blauw",
|
||||
"R": "Rood",
|
||||
"G": "Groen",
|
||||
"Color": "Kleur",
|
||||
"Right to left": "Rechts naar links",
|
||||
"Left to right": "Links naar rechts",
|
||||
"Emoticons": "Emoticons",
|
||||
"Robots": "Robots",
|
||||
"Document properties": "Document eigenschappen",
|
||||
"Title": "Titel",
|
||||
"Keywords": "Sleutelwoorden",
|
||||
"Encoding": "Codering",
|
||||
"Description": "Omschrijving",
|
||||
"Author": "Auteur",
|
||||
"Fullscreen": "Volledig scherm",
|
||||
"Horizontal line": "Horizontale lijn",
|
||||
"Horizontal space": "Horizontale ruimte",
|
||||
"Insert\/edit image": "Afbeelding invoegen\/bewerken",
|
||||
"General": "Algemeen",
|
||||
"Advanced": "Geavanceerd",
|
||||
"Source": "Bron",
|
||||
"Border": "Rand",
|
||||
"Constrain proportions": "Verhoudingen behouden",
|
||||
"Vertical space": "Verticale ruimte",
|
||||
"Image description": "Afbeelding omschrijving",
|
||||
"Style": "Stijl",
|
||||
"Dimensions": "Afmetingen",
|
||||
"Insert image": "Afbeelding invoegen",
|
||||
"Zoom in": "Inzoomen",
|
||||
"Contrast": "Contrast",
|
||||
"Back": "Terug",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "Horizontaal spiegelen",
|
||||
"Resize": "Formaat aanpassen",
|
||||
"Sharpen": "Scherpte",
|
||||
"Zoom out": "Uitzoomen",
|
||||
"Image options": "Afbeelding opties",
|
||||
"Apply": "Toepassen",
|
||||
"Brightness": "Helderheid",
|
||||
"Rotate clockwise": "Rechtsom draaien",
|
||||
"Rotate counterclockwise": "Linksom draaien",
|
||||
"Edit image": "Bewerk afbeelding",
|
||||
"Color levels": "Kleurniveau's",
|
||||
"Crop": "Uitsnijden",
|
||||
"Orientation": "Orientatie",
|
||||
"Flip vertically": "Verticaal spiegelen",
|
||||
"Invert": "Omkeren",
|
||||
"Insert date\/time": "Voeg datum\/tijd in",
|
||||
"Remove link": "Link verwijderen",
|
||||
"Url": "Url",
|
||||
"Text to display": "Linktekst",
|
||||
"Anchors": "Anker",
|
||||
"Insert link": "Hyperlink invoegen",
|
||||
"New window": "Nieuw venster",
|
||||
"None": "Geen",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "De ingegeven URL verwijst naar een extern adres. Wil je er \"http:\/\/\" aan toevoegen?",
|
||||
"Target": "Doel",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "De ingegeven URL lijkt op een e-mailadres. Wil je er \"mailto:\" aan toevoegen?",
|
||||
"Insert\/edit link": "Hyperlink invoegen\/bewerken",
|
||||
"Insert\/edit video": "Video invoegen\/bewerken",
|
||||
"Poster": "Poster",
|
||||
"Alternative source": "Alternatieve bron",
|
||||
"Paste your embed code below:": "Plak u in te sluiten code hieronder:",
|
||||
"Insert video": "Video invoegen",
|
||||
"Embed": "Insluiten",
|
||||
"Nonbreaking space": "Vaste spatie invoegen",
|
||||
"Page break": "Pagina einde",
|
||||
"Paste as text": "Plakken als tekst",
|
||||
"Preview": "Voorbeeld",
|
||||
"Print": "Print",
|
||||
"Save": "Opslaan",
|
||||
"Could not find the specified string.": "Geen resultaten gevonden",
|
||||
"Replace": "Vervangen",
|
||||
"Next": "Volgende",
|
||||
"Whole words": "Alleen hele woorden",
|
||||
"Find and replace": "Zoek en vervang",
|
||||
"Replace with": "Vervangen door",
|
||||
"Find": "Zoeken",
|
||||
"Replace all": "Alles vervangen",
|
||||
"Match case": "Identieke hoofd\/kleine letters",
|
||||
"Prev": "Vorige",
|
||||
"Spellcheck": "Spellingscontrole",
|
||||
"Finish": "Einde",
|
||||
"Ignore all": "Alles negeren",
|
||||
"Ignore": "Negeren",
|
||||
"Add to Dictionary": "Toevoegen aan woordenlijst",
|
||||
"Insert row before": "Voeg rij boven toe",
|
||||
"Rows": "Rijen",
|
||||
"Height": "Hoogte",
|
||||
"Paste row after": "Plak rij onder",
|
||||
"Alignment": "Uitlijning",
|
||||
"Border color": "Randkleur",
|
||||
"Column group": "Kolomgroep",
|
||||
"Row": "Rij",
|
||||
"Insert column before": "Voeg kolom in voor",
|
||||
"Split cell": "Cel splitsen",
|
||||
"Cell padding": "Ruimte binnen cel",
|
||||
"Cell spacing": "Celruimte",
|
||||
"Row type": "Rijtype",
|
||||
"Insert table": "Tabel invoegen",
|
||||
"Body": "Body",
|
||||
"Caption": "Onderschrift",
|
||||
"Footer": "Voettekst",
|
||||
"Delete row": "Verwijder rij",
|
||||
"Paste row before": "Plak rij boven",
|
||||
"Scope": "Bereik",
|
||||
"Delete table": "Verwijder tabel",
|
||||
"H Align": "Links uitlijnen",
|
||||
"Top": "Bovenaan",
|
||||
"Header cell": "Kopcel",
|
||||
"Column": "Kolom",
|
||||
"Row group": "Rijgroep",
|
||||
"Cell": "Cel",
|
||||
"Middle": "Centreren",
|
||||
"Cell type": "Celtype",
|
||||
"Copy row": "Kopieer rij",
|
||||
"Row properties": "Rij eigenschappen",
|
||||
"Table properties": "Tabel eigenschappen",
|
||||
"Bottom": "Onderaan",
|
||||
"V Align": "Boven uitlijnen",
|
||||
"Header": "Koptekst",
|
||||
"Right": "Rechts",
|
||||
"Insert column after": "Voeg kolom in na",
|
||||
"Cols": "Kolommen",
|
||||
"Insert row after": "Voeg rij onder toe",
|
||||
"Width": "Breedte",
|
||||
"Cell properties": "Cel eigenschappen",
|
||||
"Left": "Links",
|
||||
"Cut row": "Knip rij",
|
||||
"Delete column": "Verwijder kolom",
|
||||
"Center": "Midden",
|
||||
"Merge cells": "Cellen samenvoegen",
|
||||
"Insert template": "Sjabloon invoegen",
|
||||
"Templates": "Sjablonen",
|
||||
"Background color": "Achtergrondkleur",
|
||||
"Custom...": "Eigen...",
|
||||
"Custom color": "Eigen kleur",
|
||||
"No color": "Geen kleur",
|
||||
"Text color": "Tekstkleur",
|
||||
"Show blocks": "Blokken tonen",
|
||||
"Show invisible characters": "Onzichtbare karakters tonen",
|
||||
"Words: {0}": "Woorden: {0}",
|
||||
"Insert": "Invoegen",
|
||||
"File": "Bestand",
|
||||
"Edit": "Bewerken",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Druk ALT-F9 voor het menu. Druk ALT-F10 voor de toolbar. Druk ALT-0 voor help.",
|
||||
"Tools": "Gereedschap",
|
||||
"View": "Beeld",
|
||||
"Table": "Tabel",
|
||||
"Format": "Opmaak"
|
||||
});
|
||||
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js
Normal file
File diff suppressed because one or more lines are too long
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('pl',{
|
||||
"Cut": "Wytnij",
|
||||
"Heading 5": "Nag\u0142\u00f3wek 5",
|
||||
"Header 2": "Nag\u0142\u00f3wek 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Twoja przegl\u0105darka nie obs\u0142uguje bezpo\u015bredniego dost\u0119pu do schowka. U\u017cyj zamiast tego kombinacji klawiszy Ctrl+X\/C\/V.",
|
||||
"Heading 4": "Nag\u0142\u00f3wek 4",
|
||||
"Div": "Div",
|
||||
"Heading 2": "Nag\u0142\u00f3wek 2",
|
||||
"Paste": "Wklej",
|
||||
"Close": "Zamknij",
|
||||
"Font Family": "Kr\u00f3j fontu",
|
||||
"Pre": "Sformatowany tekst",
|
||||
"Align right": "Wyr\u00f3wnaj do prawej",
|
||||
"New document": "Nowy dokument",
|
||||
"Blockquote": "Blok cytatu",
|
||||
"Numbered list": "Lista numerowana",
|
||||
"Heading 1": "Nag\u0142\u00f3wek 1",
|
||||
"Headings": "Nag\u0142\u00f3wki",
|
||||
"Increase indent": "Zwi\u0119ksz wci\u0119cie",
|
||||
"Formats": "Formaty",
|
||||
"Headers": "Nag\u0142\u00f3wki",
|
||||
"Select all": "Zaznacz wszystko",
|
||||
"Header 3": "Nag\u0142\u00f3wek 3",
|
||||
"Blocks": "Bloki",
|
||||
"Undo": "Cofnij",
|
||||
"Strikethrough": "Przekre\u015blenie",
|
||||
"Bullet list": "Lista wypunktowana",
|
||||
"Header 1": "Nag\u0142\u00f3wek 1",
|
||||
"Superscript": "Indeks g\u00f3rny",
|
||||
"Clear formatting": "Wyczy\u015b\u0107 formatowanie",
|
||||
"Font Sizes": "Rozmiar fontu",
|
||||
"Subscript": "Indeks dolny",
|
||||
"Header 6": "Nag\u0142\u00f3wek 6",
|
||||
"Redo": "Pon\u00f3w",
|
||||
"Paragraph": "Akapit",
|
||||
"Ok": "Ok",
|
||||
"Bold": "Pogrubienie",
|
||||
"Code": "Kod \u017ar\u00f3d\u0142owy",
|
||||
"Italic": "Kursywa",
|
||||
"Align center": "Wyr\u00f3wnaj do \u015brodka",
|
||||
"Header 5": "Nag\u0142\u00f3wek 5",
|
||||
"Heading 6": "Nag\u0142\u00f3wek 6",
|
||||
"Heading 3": "Nag\u0142\u00f3wek 3",
|
||||
"Decrease indent": "Zmniejsz wci\u0119cie",
|
||||
"Header 4": "Nag\u0142\u00f3wek 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Wklejanie jest w trybie tekstowym. Zawarto\u015b\u0107 zostanie wklejona jako zwyk\u0142y tekst dop\u00f3ki nie wy\u0142\u0105czysz tej opcji.",
|
||||
"Underline": "Podkre\u015blenie",
|
||||
"Cancel": "Anuluj",
|
||||
"Justify": "Do lewej i prawej",
|
||||
"Inline": "W tek\u015bcie",
|
||||
"Copy": "Kopiuj",
|
||||
"Align left": "Wyr\u00f3wnaj do lewej",
|
||||
"Visual aids": "Pomoce wizualne",
|
||||
"Lower Greek": "Ma\u0142e greckie",
|
||||
"Square": "Kwadrat",
|
||||
"Default": "Domy\u015blne",
|
||||
"Lower Alpha": "Ma\u0142e litery",
|
||||
"Circle": "K\u00f3\u0142ko",
|
||||
"Disc": "Dysk",
|
||||
"Upper Alpha": "Wielkie litery",
|
||||
"Upper Roman": "Wielkie rzymskie",
|
||||
"Lower Roman": "Ma\u0142e rzymskie",
|
||||
"Name": "Nazwa",
|
||||
"Anchor": "Kotwica",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Masz niezapisane zmiany. Czy na pewno chcesz opu\u015bci\u0107 stron\u0119?",
|
||||
"Restore last draft": "Przywr\u00f3\u0107 ostatni szkic",
|
||||
"Special character": "Znak specjalny",
|
||||
"Source code": "Kod \u017ar\u00f3d\u0142owy",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "Kolor",
|
||||
"Right to left": "Od prawej do lewej",
|
||||
"Left to right": "Od lewej do prawej",
|
||||
"Emoticons": "Ikony emocji",
|
||||
"Robots": "Roboty",
|
||||
"Document properties": "W\u0142a\u015bciwo\u015bci dokumentu",
|
||||
"Title": "Tytu\u0142",
|
||||
"Keywords": "S\u0142owa kluczowe",
|
||||
"Encoding": "Kodowanie",
|
||||
"Description": "Opis",
|
||||
"Author": "Autor",
|
||||
"Fullscreen": "Pe\u0142ny ekran",
|
||||
"Horizontal line": "Pozioma linia",
|
||||
"Horizontal space": "Odst\u0119p poziomy",
|
||||
"Insert\/edit image": "Wstaw\/edytuj obrazek",
|
||||
"General": "Og\u00f3lne",
|
||||
"Advanced": "Zaawansowane",
|
||||
"Source": "\u0179r\u00f3d\u0142o",
|
||||
"Border": "Ramka",
|
||||
"Constrain proportions": "Zachowaj proporcje",
|
||||
"Vertical space": "Odst\u0119p pionowy",
|
||||
"Image description": "Opis obrazka",
|
||||
"Style": "Styl",
|
||||
"Dimensions": "Wymiary",
|
||||
"Insert image": "Wstaw obrazek",
|
||||
"Zoom in": "Powi\u0119ksz",
|
||||
"Contrast": "Kontrast",
|
||||
"Back": "Cofnij",
|
||||
"Gamma": "Gamma",
|
||||
"Flip horizontally": "Przerzu\u0107 w poziomie",
|
||||
"Resize": "Zmiana rozmiaru",
|
||||
"Sharpen": "Wyostrz",
|
||||
"Zoom out": "Pomniejsz",
|
||||
"Image options": "Opcje obrazu",
|
||||
"Apply": "Zaakceptuj",
|
||||
"Brightness": "Jasno\u015b\u0107",
|
||||
"Rotate clockwise": "Obr\u00f3\u0107 w prawo",
|
||||
"Rotate counterclockwise": "Obr\u00f3\u0107 w lewo",
|
||||
"Edit image": "Edytuj obrazek",
|
||||
"Color levels": "Poziom koloru",
|
||||
"Crop": "Przytnij",
|
||||
"Orientation": "Orientacja",
|
||||
"Flip vertically": "Przerzu\u0107 w pionie",
|
||||
"Invert": "Odwr\u00f3\u0107",
|
||||
"Insert date\/time": "Wstaw dat\u0119\/czas",
|
||||
"Remove link": "Usu\u0144 \u0142\u0105cze",
|
||||
"Url": "URL",
|
||||
"Text to display": "Tekst do wy\u015bwietlenia",
|
||||
"Anchors": "Kotwice",
|
||||
"Insert link": "Wstaw \u0142\u0105cze",
|
||||
"New window": "Nowe okno",
|
||||
"None": "\u017baden",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "URL, kt\u00f3ry wprowadzi\u0142e\u015b wygl\u0105da na link zewn\u0119trzny. Czy chcesz doda\u0107 http:\/\/ jako prefiks?",
|
||||
"Target": "Cel",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URL, kt\u00f3ry wprowadzi\u0142e\u015b wygl\u0105da na adres e-mail. Czy chcesz doda\u0107 mailto: jako prefiks?",
|
||||
"Insert\/edit link": "Wstaw\/edytuj \u0142\u0105cze",
|
||||
"Insert\/edit video": "Wstaw\/edytuj wideo",
|
||||
"Poster": "Plakat",
|
||||
"Alternative source": "Alternatywne \u017ar\u00f3d\u0142o",
|
||||
"Paste your embed code below:": "Wklej tutaj kod do osadzenia:",
|
||||
"Insert video": "Wstaw wideo",
|
||||
"Embed": "Osad\u017a",
|
||||
"Nonbreaking space": "Nie\u0142amliwa spacja",
|
||||
"Page break": "Podzia\u0142 strony",
|
||||
"Paste as text": "Wklej jako zwyk\u0142y tekst",
|
||||
"Preview": "Podgl\u0105d",
|
||||
"Print": "Drukuj",
|
||||
"Save": "Zapisz",
|
||||
"Could not find the specified string.": "Nie znaleziono szukanego tekstu.",
|
||||
"Replace": "Zamie\u0144",
|
||||
"Next": "Nast.",
|
||||
"Whole words": "Ca\u0142e s\u0142owa",
|
||||
"Find and replace": "Znajd\u017a i zamie\u0144",
|
||||
"Replace with": "Zamie\u0144 na",
|
||||
"Find": "Znajd\u017a",
|
||||
"Replace all": "Zamie\u0144 wszystko",
|
||||
"Match case": "Dopasuj wielko\u015b\u0107 liter",
|
||||
"Prev": "Poprz.",
|
||||
"Spellcheck": "Sprawdzanie pisowni",
|
||||
"Finish": "Zako\u0144cz",
|
||||
"Ignore all": "Ignoruj wszystko",
|
||||
"Ignore": "Ignoruj",
|
||||
"Add to Dictionary": "Dodaj do s\u0142ownika",
|
||||
"Insert row before": "Wstaw wiersz przed",
|
||||
"Rows": "Wiersz.",
|
||||
"Height": "Wysoko\u015b\u0107",
|
||||
"Paste row after": "Wklej wiersz po",
|
||||
"Alignment": "Wyr\u00f3wnanie",
|
||||
"Border color": "Kolor ramki",
|
||||
"Column group": "Grupa kolumn",
|
||||
"Row": "Wiersz",
|
||||
"Insert column before": "Wstaw kolumn\u0119 przed",
|
||||
"Split cell": "Podziel kom\u00f3rk\u0119",
|
||||
"Cell padding": "Dope\u0142nienie kom\u00f3rki",
|
||||
"Cell spacing": "Odst\u0119py kom\u00f3rek",
|
||||
"Row type": "Typ wiersza",
|
||||
"Insert table": "Wstaw tabel\u0119",
|
||||
"Body": "Tre\u015b\u0107",
|
||||
"Caption": "Tytu\u0142",
|
||||
"Footer": "Stopka",
|
||||
"Delete row": "Usu\u0144 wiersz",
|
||||
"Paste row before": "Wklej wiersz przed",
|
||||
"Scope": "Kontekst",
|
||||
"Delete table": "Usu\u0144 tabel\u0119",
|
||||
"H Align": "Wyr\u00f3wnanie w pionie",
|
||||
"Top": "G\u00f3ra",
|
||||
"Header cell": "Kom\u00f3rka nag\u0142\u00f3wka",
|
||||
"Column": "Kolumna",
|
||||
"Row group": "Grupa wierszy",
|
||||
"Cell": "Kom\u00f3rka",
|
||||
"Middle": "\u015arodek",
|
||||
"Cell type": "Typ kom\u00f3rki",
|
||||
"Copy row": "Kopiuj wiersz",
|
||||
"Row properties": "W\u0142a\u015bciwo\u015bci wiersza",
|
||||
"Table properties": "W\u0142a\u015bciwo\u015bci tabeli",
|
||||
"Bottom": "D\u00f3\u0142",
|
||||
"V Align": "Wyr\u00f3wnanie w poziomie",
|
||||
"Header": "Nag\u0142\u00f3wek",
|
||||
"Right": "Prawo",
|
||||
"Insert column after": "Wstaw kolumn\u0119 po",
|
||||
"Cols": "Kol.",
|
||||
"Insert row after": "Wstaw wiersz po",
|
||||
"Width": "Szeroko\u015b\u0107",
|
||||
"Cell properties": "W\u0142a\u015bciwo\u015bci kom\u00f3rki",
|
||||
"Left": "Lewo",
|
||||
"Cut row": "Wytnij wiersz",
|
||||
"Delete column": "Usu\u0144 kolumn\u0119",
|
||||
"Center": "\u015arodek",
|
||||
"Merge cells": "\u0141\u0105cz kom\u00f3rki",
|
||||
"Insert template": "Wstaw szablon",
|
||||
"Templates": "Szablony",
|
||||
"Background color": "Kolor t\u0142a",
|
||||
"Custom...": "Niestandardowy...",
|
||||
"Custom color": "Kolor niestandardowy",
|
||||
"No color": "Bez koloru",
|
||||
"Text color": "Kolor tekstu",
|
||||
"Show blocks": "Poka\u017c bloki",
|
||||
"Show invisible characters": "Poka\u017c niewidoczne znaki",
|
||||
"Words: {0}": "S\u0142\u00f3w: {0}",
|
||||
"Insert": "Wstaw",
|
||||
"File": "Plik",
|
||||
"Edit": "Edycja",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Obszar Edycji. ALT-F9 - menu. ALT-F10 - pasek narz\u0119dzi. ALT-0 - pomoc",
|
||||
"Tools": "Narz\u0119dzia",
|
||||
"View": "Widok",
|
||||
"Table": "Tabela",
|
||||
"Format": "Format"
|
||||
});
|
||||
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js
Normal file
File diff suppressed because one or more lines are too long
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js
Normal file
219
src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js
Normal file
@@ -0,0 +1,219 @@
|
||||
tinymce.addI18n('ru',{
|
||||
"Cut": "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c",
|
||||
"Heading 5": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 5",
|
||||
"Header 2": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 2",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u0412\u0430\u0448 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u0443\u0444\u0435\u0440\u0443 \u043e\u0431\u043c\u0435\u043d\u0430. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448: Ctrl+X\/C\/V.",
|
||||
"Heading 4": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 4",
|
||||
"Div": "\u0411\u043b\u043e\u043a",
|
||||
"Heading 2": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 2",
|
||||
"Paste": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c",
|
||||
"Close": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c",
|
||||
"Font Family": "\u0428\u0440\u0438\u0444\u0442",
|
||||
"Pre": "\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435",
|
||||
"Align right": "\u041f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e",
|
||||
"New document": "\u041d\u043e\u0432\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442",
|
||||
"Blockquote": "\u0426\u0438\u0442\u0430\u0442\u0430",
|
||||
"Numbered list": "\u041d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a",
|
||||
"Heading 1": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 1",
|
||||
"Headings": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438",
|
||||
"Increase indent": "\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0442\u0441\u0442\u0443\u043f",
|
||||
"Formats": "\u0424\u043e\u0440\u043c\u0430\u0442",
|
||||
"Headers": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438",
|
||||
"Select all": "\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0441\u0435",
|
||||
"Header 3": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 3",
|
||||
"Blocks": "\u0411\u043b\u043e\u043a\u0438",
|
||||
"Undo": "\u0412\u0435\u0440\u043d\u0443\u0442\u044c",
|
||||
"Strikethrough": "\u0417\u0430\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439",
|
||||
"Bullet list": "\u041c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a",
|
||||
"Header 1": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 1",
|
||||
"Superscript": "\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441",
|
||||
"Clear formatting": "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442",
|
||||
"Font Sizes": "\u0420\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430",
|
||||
"Subscript": "\u041d\u0438\u0436\u043d\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441",
|
||||
"Header 6": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 6",
|
||||
"Redo": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c",
|
||||
"Paragraph": "\u041f\u0430\u0440\u0430\u0433\u0440\u0430\u0444",
|
||||
"Ok": "\u041e\u043a",
|
||||
"Bold": "\u041f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u0439",
|
||||
"Code": "\u041a\u043e\u0434",
|
||||
"Italic": "\u041a\u0443\u0440\u0441\u0438\u0432",
|
||||
"Align center": "\u041f\u043e \u0446\u0435\u043d\u0442\u0440\u0443",
|
||||
"Header 5": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 5",
|
||||
"Heading 6": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 6",
|
||||
"Heading 3": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 3",
|
||||
"Decrease indent": "\u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043e\u0442\u0441\u0442\u0443\u043f",
|
||||
"Header 4": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 4",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u0412\u0441\u0442\u0430\u0432\u043a\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043e\u043f\u0446\u0438\u044e.",
|
||||
"Underline": "\u041f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439",
|
||||
"Cancel": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c",
|
||||
"Justify": "\u041f\u043e \u0448\u0438\u0440\u0438\u043d\u0435",
|
||||
"Inline": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435",
|
||||
"Copy": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
|
||||
"Align left": "\u041f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e",
|
||||
"Visual aids": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0440\u044b",
|
||||
"Lower Greek": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0433\u0440\u0435\u0447\u0435\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b",
|
||||
"Square": "\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u044b",
|
||||
"Default": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439",
|
||||
"Lower Alpha": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b",
|
||||
"Circle": "\u041e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u0438",
|
||||
"Disc": "\u041a\u0440\u0443\u0433\u0438",
|
||||
"Upper Alpha": "\u0417\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b",
|
||||
"Upper Roman": "\u0417\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u0440\u0438\u043c\u0441\u043a\u0438\u0435 \u0446\u0438\u0444\u0440\u044b",
|
||||
"Lower Roman": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0440\u0438\u043c\u0441\u043a\u0438\u0435 \u0446\u0438\u0444\u0440\u044b",
|
||||
"Name": "\u0418\u043c\u044f",
|
||||
"Anchor": "\u042f\u043a\u043e\u0440\u044c",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "\u0423 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0439\u0442\u0438?",
|
||||
"Restore last draft": "\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430",
|
||||
"Special character": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b",
|
||||
"Source code": "\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434",
|
||||
"B": "B",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"Color": "\u0426\u0432\u0435\u0442",
|
||||
"Right to left": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e",
|
||||
"Left to right": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e",
|
||||
"Emoticons": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043c\u0430\u0439\u043b",
|
||||
"Robots": "\u0420\u043e\u0431\u043e\u0442\u044b",
|
||||
"Document properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430",
|
||||
"Title": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a",
|
||||
"Keywords": "\u041a\u043b\u044e\u0447\u0438\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430",
|
||||
"Encoding": "\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430",
|
||||
"Description": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435",
|
||||
"Author": "\u0410\u0432\u0442\u043e\u0440",
|
||||
"Fullscreen": "\u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c",
|
||||
"Horizontal line": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043b\u0438\u043d\u0438\u044f",
|
||||
"Horizontal space": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b",
|
||||
"Insert\/edit image": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
|
||||
"General": "\u041e\u0431\u0449\u0435\u0435",
|
||||
"Advanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435",
|
||||
"Source": "\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a",
|
||||
"Border": "\u0420\u0430\u043c\u043a\u0430",
|
||||
"Constrain proportions": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438",
|
||||
"Vertical space": "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b",
|
||||
"Image description": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
|
||||
"Style": "\u0421\u0442\u0438\u043b\u044c",
|
||||
"Dimensions": "\u0420\u0430\u0437\u043c\u0435\u0440",
|
||||
"Insert image": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
|
||||
"Zoom in": "\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u044c",
|
||||
"Contrast": "\u041a\u043e\u043d\u0442\u0440\u0430\u0441\u0442",
|
||||
"Back": "\u041d\u0430\u0437\u0430\u0434",
|
||||
"Gamma": "\u0413\u0430\u043c\u043c\u0430",
|
||||
"Flip horizontally": "\u041e\u0442\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438",
|
||||
"Resize": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440",
|
||||
"Sharpen": "\u0427\u0435\u0442\u043a\u043e\u0441\u0442\u044c",
|
||||
"Zoom out": "\u041e\u0442\u0434\u0430\u043b\u0438\u0442\u044c",
|
||||
"Image options": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
|
||||
"Apply": "\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c",
|
||||
"Brightness": "\u042f\u0440\u043a\u043e\u0441\u0442\u044c",
|
||||
"Rotate clockwise": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043e \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0435",
|
||||
"Rotate counterclockwise": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0442\u0438\u0432 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0438",
|
||||
"Edit image": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
|
||||
"Color levels": "\u0426\u0432\u0435\u0442\u043e\u0432\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u0438",
|
||||
"Crop": "\u041e\u0431\u0440\u0435\u0437\u0430\u0442\u044c",
|
||||
"Orientation": "\u041e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044f",
|
||||
"Flip vertically": "\u041e\u0442\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438",
|
||||
"Invert": "\u0418\u043d\u0432\u0435\u0440\u0441\u0438\u044f",
|
||||
"Insert date\/time": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u0442\u0443\/\u0432\u0440\u0435\u043c\u044f",
|
||||
"Remove link": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443",
|
||||
"Url": "\u0410\u0434\u0440\u0435\u0441 \u0441\u0441\u044b\u043b\u043a\u0438",
|
||||
"Text to display": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442",
|
||||
"Anchors": "\u042f\u043a\u043e\u0440\u044f",
|
||||
"Insert link": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443",
|
||||
"New window": "\u0412 \u043d\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435",
|
||||
"None": "\u041d\u0435\u0442",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 URL \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439. \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00abhttp:\/\/\u00bb?",
|
||||
"Target": "\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 URL \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b. \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00abmailto:\u00bb?",
|
||||
"Insert\/edit link": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443",
|
||||
"Insert\/edit video": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0435\u043e",
|
||||
"Poster": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
|
||||
"Alternative source": "\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a",
|
||||
"Paste your embed code below:": "\u0412\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0432\u0430\u0448 \u043a\u043e\u0434 \u043d\u0438\u0436\u0435:",
|
||||
"Insert video": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0438\u0434\u0435\u043e",
|
||||
"Embed": "\u041a\u043e\u0434 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438",
|
||||
"Nonbreaking space": "\u041d\u0435\u0440\u0430\u0437\u0440\u044b\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0431\u0435\u043b",
|
||||
"Page break": "\u0420\u0430\u0437\u0440\u044b\u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b",
|
||||
"Paste as text": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0442\u0435\u043a\u0441\u0442",
|
||||
"Preview": "\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440",
|
||||
"Print": "\u041f\u0435\u0447\u0430\u0442\u044c",
|
||||
"Save": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c",
|
||||
"Could not find the specified string.": "\u0417\u0430\u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430",
|
||||
"Replace": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c",
|
||||
"Next": "\u0412\u043d\u0438\u0437",
|
||||
"Whole words": "\u0421\u043b\u043e\u0432\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c",
|
||||
"Find and replace": "\u041f\u043e\u0438\u0441\u043a \u0438 \u0437\u0430\u043c\u0435\u043d\u0430",
|
||||
"Replace with": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430",
|
||||
"Find": "\u041d\u0430\u0439\u0442\u0438",
|
||||
"Replace all": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0441\u0435",
|
||||
"Match case": "\u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440",
|
||||
"Prev": "\u0412\u0432\u0435\u0440\u0445",
|
||||
"Spellcheck": "\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435",
|
||||
"Finish": "\u0417\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c",
|
||||
"Ignore all": "\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435",
|
||||
"Ignore": "\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
|
||||
"Add to Dictionary": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c",
|
||||
"Insert row before": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u0432\u0435\u0440\u0445\u0443",
|
||||
"Rows": "\u0421\u0442\u0440\u043e\u043a\u0438",
|
||||
"Height": "\u0412\u044b\u0441\u043e\u0442\u0430",
|
||||
"Paste row after": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043d\u0438\u0437\u0443",
|
||||
"Alignment": "\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435",
|
||||
"Border color": "\u0426\u0432\u0435\u0442 \u0440\u0430\u043c\u043a\u0438",
|
||||
"Column group": "\u0413\u0440\u0443\u043f\u043f\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a",
|
||||
"Row": "\u0421\u0442\u0440\u043e\u043a\u0430",
|
||||
"Insert column before": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441\u043b\u0435\u0432\u0430",
|
||||
"Split cell": "\u0420\u0430\u0437\u0431\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0443",
|
||||
"Cell padding": "\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043e\u0442\u0441\u0442\u0443\u043f",
|
||||
"Cell spacing": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u043e\u0442\u0441\u0442\u0443\u043f",
|
||||
"Row type": "\u0422\u0438\u043f \u0441\u0442\u0440\u043e\u043a\u0438",
|
||||
"Insert table": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443",
|
||||
"Body": "\u0422\u0435\u043b\u043e",
|
||||
"Caption": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a",
|
||||
"Footer": "\u041d\u0438\u0437",
|
||||
"Delete row": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443",
|
||||
"Paste row before": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u0432\u0435\u0440\u0445\u0443",
|
||||
"Scope": "Scope",
|
||||
"Delete table": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443",
|
||||
"H Align": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435",
|
||||
"Top": "\u041f\u043e \u0432\u0435\u0440\u0445\u0443",
|
||||
"Header cell": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a",
|
||||
"Column": "\u0421\u0442\u043e\u043b\u0431\u0435\u0446",
|
||||
"Row group": "\u0413\u0440\u0443\u043f\u043f\u0430 \u0441\u0442\u0440\u043e\u043a",
|
||||
"Cell": "\u042f\u0447\u0435\u0439\u043a\u0430",
|
||||
"Middle": "\u041f\u043e \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435",
|
||||
"Cell type": "\u0422\u0438\u043f \u044f\u0447\u0435\u0439\u043a\u0438",
|
||||
"Copy row": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443",
|
||||
"Row properties": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0442\u0440\u043e\u043a\u0438",
|
||||
"Table properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b",
|
||||
"Bottom": "\u041f\u043e \u043d\u0438\u0437\u0443",
|
||||
"V Align": "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435",
|
||||
"Header": "\u0428\u0430\u043f\u043a\u0430",
|
||||
"Right": "\u041f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e",
|
||||
"Insert column after": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441\u043f\u0440\u0430\u0432\u0430",
|
||||
"Cols": "\u0421\u0442\u043e\u043b\u0431\u0446\u044b",
|
||||
"Insert row after": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043d\u0438\u0437\u0443",
|
||||
"Width": "\u0428\u0438\u0440\u0438\u043d\u0430",
|
||||
"Cell properties": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u044f\u0447\u0435\u0439\u043a\u0438",
|
||||
"Left": "\u041f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e",
|
||||
"Cut row": "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443",
|
||||
"Delete column": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446",
|
||||
"Center": "\u041f\u043e \u0446\u0435\u043d\u0442\u0440\u0443",
|
||||
"Merge cells": "\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438",
|
||||
"Insert template": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d",
|
||||
"Templates": "\u0428\u0430\u0431\u043b\u043e\u043d\u044b",
|
||||
"Background color": "\u0426\u0432\u0435\u0442 \u0444\u043e\u043d\u0430",
|
||||
"Custom...": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c\u2026",
|
||||
"Custom color": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0446\u0432\u0435\u0442",
|
||||
"No color": "\u0411\u0435\u0437 \u0446\u0432\u0435\u0442\u0430",
|
||||
"Text color": "\u0426\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430",
|
||||
"Show blocks": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438",
|
||||
"Show invisible characters": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b",
|
||||
"Words: {0}": "\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043b\u043e\u0432: {0}",
|
||||
"Insert": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c",
|
||||
"File": "\u0424\u0430\u0439\u043b",
|
||||
"Edit": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 ALT-F9 \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044e, ALT-F10 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, ALT-0 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u043f\u043e\u043c\u043e\u0449\u0438.",
|
||||
"Tools": "\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b",
|
||||
"View": "\u0412\u0438\u0434",
|
||||
"Table": "\u0422\u0430\u0431\u043b\u0438\u0446\u0430",
|
||||
"Format": "\u0424\u043e\u0440\u043c\u0430\u0442"
|
||||
});
|
||||
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js
Normal file
File diff suppressed because one or more lines are too long
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js
Normal file
1
src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
tinymce.addI18n('en',{
|
||||
'HTML source code': 'HTML source code',
|
||||
'Start search': 'Start search',
|
||||
'Find next': 'Find next',
|
||||
'Find previous': 'Find previous',
|
||||
'Replace': 'Replace',
|
||||
'Replace all': 'Replace all'
|
||||
});
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* editor_plugin_src.js
|
||||
*
|
||||
* Copyright 2012, Umbraco
|
||||
* Released under MIT License.
|
||||
*
|
||||
* License: http://opensource.org/licenses/mit-license.html
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM;
|
||||
|
||||
/**
|
||||
* This plugin modifies the standard TinyMCE context menu, with umbraco specific changes.
|
||||
*
|
||||
* @class tinymce.plugins.umbContextMenu
|
||||
*/
|
||||
tinymce.create('tinymce.plugins.UmbracoContextMenu', {
|
||||
/**
|
||||
* Initializes the plugin, this will be executed after the plugin has been created.
|
||||
* This call is done before the editor instance has finished it's initialization so use the onInit event
|
||||
* of the editor instance to intercept that event.
|
||||
*
|
||||
* @method init
|
||||
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
|
||||
* @param {string} url Absolute URL to where the plugin is located.
|
||||
*/
|
||||
init: function (ed) {
|
||||
if (ed.plugins.contextmenu) {
|
||||
|
||||
ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) {
|
||||
|
||||
var keys = UmbClientMgr.uiKeys();
|
||||
|
||||
$.each(menu.items, function (idx, el) {
|
||||
|
||||
switch (el.settings.cmd) {
|
||||
case "Cut":
|
||||
el.settings.title = keys['defaultdialogs_cut'];
|
||||
break;
|
||||
case "Copy":
|
||||
el.settings.title = keys['general_copy'];
|
||||
break;
|
||||
case "Paste":
|
||||
el.settings.title = keys['defaultdialogs_paste'];
|
||||
break;
|
||||
case "mceAdvLink":
|
||||
case "mceLink":
|
||||
el.settings.title = keys['defaultdialogs_insertlink'];
|
||||
break;
|
||||
case "UnLink":
|
||||
el.settings.title = keys['relatedlinks_removeLink'];
|
||||
break;
|
||||
case "mceImage":
|
||||
el.settings.title = keys['defaultdialogs_insertimage'];
|
||||
el.settings.cmd = "mceUmbimage";
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register plugin
|
||||
tinymce.PluginManager.add('umbracocontextmenu', tinymce.plugins.UmbracoContextMenu);
|
||||
})();
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* editor_plugin_src.js
|
||||
*
|
||||
* Copyright 2012, Umbraco
|
||||
* Released under MIT License.
|
||||
*
|
||||
* License: http://opensource.org/licenses/mit-license.html
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM;
|
||||
|
||||
/**
|
||||
* This plugin modifies the standard TinyMCE context menu, with umbraco specific changes.
|
||||
*
|
||||
* @class tinymce.plugins.umbContextMenu
|
||||
*/
|
||||
tinymce.create('tinymce.plugins.UmbracoContextMenu', {
|
||||
/**
|
||||
* Initializes the plugin, this will be executed after the plugin has been created.
|
||||
* This call is done before the editor instance has finished it's initialization so use the onInit event
|
||||
* of the editor instance to intercept that event.
|
||||
*
|
||||
* @method init
|
||||
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
|
||||
* @param {string} url Absolute URL to where the plugin is located.
|
||||
*/
|
||||
init: function (ed) {
|
||||
if (ed.plugins.contextmenu) {
|
||||
|
||||
ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) {
|
||||
|
||||
var keys = UmbClientMgr.uiKeys();
|
||||
|
||||
$.each(menu.items, function (idx, el) {
|
||||
|
||||
switch (el.settings.cmd) {
|
||||
case "Cut":
|
||||
el.settings.title = keys['defaultdialogs_cut'];
|
||||
break;
|
||||
case "Copy":
|
||||
el.settings.title = keys['general_copy'];
|
||||
break;
|
||||
case "Paste":
|
||||
el.settings.title = keys['defaultdialogs_paste'];
|
||||
break;
|
||||
case "mceAdvLink":
|
||||
case "mceLink":
|
||||
el.settings.title = keys['defaultdialogs_insertlink'];
|
||||
break;
|
||||
case "UnLink":
|
||||
el.settings.title = keys['relatedlinks_removeLink'];
|
||||
break;
|
||||
case "mceImage":
|
||||
el.settings.title = keys['defaultdialogs_insertimage'];
|
||||
el.settings.cmd = "mceUmbimage";
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register plugin
|
||||
tinymce.PluginManager.add('umbracocontextmenu', tinymce.plugins.UmbracoContextMenu);
|
||||
})();
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 87 B |
@@ -1,19 +0,0 @@
|
||||
tinyMCEPopup.requireLangPack();
|
||||
|
||||
var ExampleDialog = {
|
||||
init : function() {
|
||||
var f = document.forms[0];
|
||||
|
||||
// Get the selected contents as text and place it in the input
|
||||
f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'});
|
||||
f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg');
|
||||
},
|
||||
|
||||
insert : function() {
|
||||
// Insert the contents from the input into the document
|
||||
tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value);
|
||||
tinyMCEPopup.close();
|
||||
}
|
||||
};
|
||||
|
||||
tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog);
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('en.example',{
|
||||
desc : 'This is just a template button'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('en.example_dlg',{
|
||||
title : 'This is just a example title'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('en_us.example',{
|
||||
desc : 'This is just a template button'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('en_us.example_dlg',{
|
||||
title : 'This is just a example title'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('it.example',{
|
||||
desc : 'Esempio di pulsante'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('it.example_dlg',{
|
||||
title : 'Esempio di titolo'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('ja.example',{
|
||||
desc : 'これはテンプレートボタンです'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('ja.example_dlg',{
|
||||
title : 'これは見出しの例です'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('ru.example',{
|
||||
desc : 'Это просто образец кнопки'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('ru.example_dlg',{
|
||||
title : 'Это просто пример заголовка'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('sv.example',{
|
||||
desc : 'Detta är bara en mallknapp'
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
tinyMCE.addI18n('sv.example_dlg',{
|
||||
title : 'Detta är bara ett exempel på en titel'
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user