Port 7.7 - WIP

This commit is contained in:
Stephan
2017-08-14 18:21:48 +02:00
parent 1a40dd8d78
commit ab8fc33691
435 changed files with 15298 additions and 5993 deletions

10
.editorconfig Normal file
View 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

View File

@@ -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" />

View File

@@ -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"

View File

@@ -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__";
}
}

View 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;
}
}
}

View File

@@ -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>

View File

@@ -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]));
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -0,0 +1,8 @@
namespace Umbraco.Core.Configuration.HealthChecks
{
public enum HealthCheckNotificationVerbosity
{
Summary,
Detailed
}
}

View File

@@ -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; }
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace Umbraco.Core.Configuration.HealthChecks
{
public interface IDisabledHealthCheck
{
Guid Id { get; }
DateTime DisabledOn { get; }
int DisabledBy { get; }
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.HealthChecks
{
public interface IHealthChecks
{
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
IHealthCheckNotificationSettings NotificationSettings { get; }
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Umbraco.Core.Configuration.HealthChecks
{
public interface INotificationMethodSettings
{
string Key { get; }
string Value { get; }
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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];
}
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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>

View File

@@ -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; }

View File

@@ -12,6 +12,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool ConvertUrlsToAscii { get; }
bool TryConvertUrlsToAscii { get; }
IEnumerable<IChar> CharCollection { get; }
}
}

View File

@@ -1,4 +1,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
using System;
using System.ComponentModel;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
{

View File

@@ -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

View File

@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Configuration;
using System.Linq;

View File

@@ -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")]

View File

@@ -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;

View File

@@ -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)

View File

@@ -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"

View File

@@ -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>

View File

@@ -0,0 +1,8 @@
namespace Umbraco.Core.Models.EntityBase
{
public class EntityPath
{
public int Id { get; set; }
public string Path { get; set; }
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}
}

View 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
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}
}
}

View File

@@ -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; }
}
}

View 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; }
}
}

View File

@@ -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; }
}
}

View 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; }
}
}

View File

@@ -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; }
}
}

View 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);
}
}
}

View File

@@ -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 &lt; 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()

View 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()));
}
}
}

View 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;
}
}
}

View 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
}
}

View File

@@ -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);

View File

@@ -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" />

View File

@@ -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

View File

@@ -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"
}
}

View File

@@ -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']
}
}
}

View 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"
});

View 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"
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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"
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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"
});

View 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&nbsp;\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"
});

View 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"
});

File diff suppressed because one or more lines are too long

View 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"
});

File diff suppressed because one or more lines are too long

View 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"
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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'
});

View File

@@ -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);
})();

View File

@@ -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

View File

@@ -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);

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('en.example',{
desc : 'This is just a template button'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('en.example_dlg',{
title : 'This is just a example title'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('en_us.example',{
desc : 'This is just a template button'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('en_us.example_dlg',{
title : 'This is just a example title'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('it.example',{
desc : 'Esempio di pulsante'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('it.example_dlg',{
title : 'Esempio di titolo'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('ja.example',{
desc : 'これはテンプレートボタンです'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('ja.example_dlg',{
title : 'これは見出しの例です'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('ru.example',{
desc : 'Это просто образец кнопки'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('ru.example_dlg',{
title : 'Это просто пример заголовка'
});

View File

@@ -1,3 +0,0 @@
tinyMCE.addI18n('sv.example',{
desc : 'Detta är bara en mallknapp'
});

View File

@@ -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