ソースを参照

Merge branch 'master' into feat-corel-pal-format

Krzysztof Krysiński 1 年間 前
コミット
5a347d0e46
50 ファイル変更1585 行追加909 行削除
  1. 1 1
      README.md
  2. 18 18
      src/ChunkyImageLib/Operations/OperationHelper.cs
  3. 4 1
      src/ChunkyImageLib/Surface.cs
  4. 0 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/SelectionToMask_Change.cs
  5. 5 0
      src/PixiEditor.DrawingApi.Core/Surface/Pixmap.cs
  6. 1 1
      src/PixiEditor.DrawingApi.Skia/Implementations/SkiaPathImplementation.cs
  7. 1 1
      src/PixiEditor.DrawingApi.Skia/Implementations/SkiaPixmapImplementation.cs
  8. 38 20
      src/PixiEditor/App.xaml.cs
  9. 4 1
      src/PixiEditor/Data/Localization/Languages/ar.json
  10. 5 2
      src/PixiEditor/Data/Localization/Languages/cs.json
  11. 4 1
      src/PixiEditor/Data/Localization/Languages/de.json
  12. 4 1
      src/PixiEditor/Data/Localization/Languages/en.json
  13. 4 1
      src/PixiEditor/Data/Localization/Languages/it.json
  14. 4 1
      src/PixiEditor/Data/Localization/Languages/pl.json
  15. 22 19
      src/PixiEditor/Data/Localization/Languages/pt-br.json
  16. 38 35
      src/PixiEditor/Data/Localization/Languages/ru.json
  17. 585 582
      src/PixiEditor/Data/Localization/Languages/tr.json
  18. 4 1
      src/PixiEditor/Data/Localization/Languages/uk.json
  19. 19 16
      src/PixiEditor/Data/Localization/Languages/zh.json
  20. 9 9
      src/PixiEditor/Data/Localization/LocalizationData.json
  21. 13 3
      src/PixiEditor/Helpers/CrashHelper.cs
  22. 1 0
      src/PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs
  23. 2 2
      src/PixiEditor/Models/AppExtensions/ExtensionLoader.cs
  24. 3 0
      src/PixiEditor/Models/Commands/CommandController.cs
  25. 43 0
      src/PixiEditor/Models/Commands/CommandLog/CommandLog.cs
  26. 19 0
      src/PixiEditor/Models/Commands/CommandLog/CommandLogEntry.cs
  27. 17 2
      src/PixiEditor/Models/Commands/CommandMethods.cs
  28. 38 95
      src/PixiEditor/Models/Controllers/MouseUpdateController.cs
  29. 117 0
      src/PixiEditor/Models/Controllers/MouseUpdateControllerSession.cs
  30. 263 39
      src/PixiEditor/Models/DataHolders/CrashReport.cs
  31. 5 1
      src/PixiEditor/Models/Dialogs/OptionsDialog.cs
  32. 37 21
      src/PixiEditor/Models/IO/Exporter.cs
  33. 122 0
      src/PixiEditor/Models/IO/PaletteParsers/DeluxePaintParser.cs
  34. 2 2
      src/PixiEditor/Models/Rendering/CanvasUpdater.cs
  35. 3 3
      src/PixiEditor/Properties/AssemblyInfo.cs
  36. 24 2
      src/PixiEditor/ViewModels/CrashReportViewModel.cs
  37. 6 1
      src/PixiEditor/ViewModels/SubViewModels/Document/TransformOverlays/DocumentTransformViewModel.cs
  38. 2 3
      src/PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs
  39. 2 2
      src/PixiEditor/ViewModels/SubViewModels/Main/MiscViewModel.cs
  40. 1 1
      src/PixiEditor/ViewModels/SubViewModels/Main/UpdateViewModel.cs
  41. 1 1
      src/PixiEditor/Views/Dialogs/HelloTherePopup.xaml.cs
  42. 1 0
      src/PixiEditor/Views/Dialogs/OptionsPopup.xaml.cs
  43. 48 5
      src/PixiEditor/Views/MainWindow.xaml.cs
  44. 7 1
      src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml.cs
  45. 7 1
      src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml.cs
  46. 2 5
      src/PixiEditor/Views/UserControls/Overlays/BrushShapeOverlay/BrushShapeOverlay.cs
  47. 6 0
      src/PixiEditor/Views/UserControls/Overlays/LineToolOverlay/LineToolOverlay.cs
  48. 7 1
      src/PixiEditor/Views/UserControls/Overlays/SymmetryOverlay/SymmetryOverlay.cs
  49. 13 2
      src/PixiEditor/Views/UserControls/PreviewWindow.xaml.cs
  50. 3 3
      src/PixiEditor/Views/UserControls/Viewport.xaml.cs

+ 1 - 1
README.md

@@ -98,4 +98,4 @@ Please read [CONTRIBUTING.md](https://github.com/flabbet/PixiEditor/blob/master/
 
 
 ## License
 ## License
 
 
-This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/flabbet/PixiEditor/blob/master/LICENSE) - file for details
+This project is licensed under the LGPLv3 License - see the [LICENSE.md](https://github.com/flabbet/PixiEditor/blob/master/LICENSE) - file for details

+ 18 - 18
src/ChunkyImageLib/Operations/OperationHelper.cs

@@ -120,25 +120,25 @@ public static class OperationHelper
         => CreateMatrixFromPoints((Point)corners.TopLeft, (Point)corners.TopRight, (Point)corners.BottomRight, (Point)corners.BottomLeft, (float)size.X, (float)size.Y);
         => CreateMatrixFromPoints((Point)corners.TopLeft, (Point)corners.TopRight, (Point)corners.BottomRight, (Point)corners.BottomLeft, (float)size.X, (float)size.Y);
 
 
     // see https://stackoverflow.com/questions/48416118/perspective-transform-in-skia/72364829#72364829
     // see https://stackoverflow.com/questions/48416118/perspective-transform-in-skia/72364829#72364829
-    public static Matrix3X3 CreateMatrixFromPoints(Point topLeft, Point topRight, Point botRight, Point botLeft, float width, float height)
+    public static Matrix3X3 CreateMatrixFromPoints(Point topLeft, Point topRight, Point botRight, Point botLeft, double width, double height)
     {
     {
-        (float x1, float y1) = (topLeft.X, topLeft.Y);
-        (float x2, float y2) = (topRight.X, topRight.Y);
-        (float x3, float y3) = (botRight.X, botRight.Y);
-        (float x4, float y4) = (botLeft.X, botLeft.Y);
-        (float w, float h) = (width, height);
-
-        float scaleX = (y1 * x2 * x4 - x1 * y2 * x4 + x1 * y3 * x4 - x2 * y3 * x4 - y1 * x2 * x3 + x1 * y2 * x3 - x1 * y4 * x3 + x2 * y4 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
-        float skewX = (-x1 * x2 * y3 - y1 * x2 * x4 + x2 * y3 * x4 + x1 * x2 * y4 + x1 * y2 * x3 + y1 * x4 * x3 - y2 * x4 * x3 - x1 * y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
-        float transX = x1;
-        float skewY = (-y1 * x2 * y3 + x1 * y2 * y3 + y1 * y3 * x4 - y2 * y3 * x4 + y1 * x2 * y4 - x1 * y2 * y4 - y1 * y4 * x3 + y2 * y4 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
-        float scaleY = (-y1 * x2 * y3 - y1 * y2 * x4 + y1 * y3 * x4 + x1 * y2 * y4 - x1 * y3 * y4 + x2 * y3 * y4 + y1 * y2 * x3 - y2 * y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
-        float transY = y1;
-        float persp0 = (x1 * y3 - x2 * y3 + y1 * x4 - y2 * x4 - x1 * y4 + x2 * y4 - y1 * x3 + y2 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
-        float persp1 = (-y1 * x2 + x1 * y2 - x1 * y3 - y2 * x4 + y3 * x4 + x2 * y4 + y1 * x3 - y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
-        float persp2 = 1;
-
-        return new Matrix3X3(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2);
+        (double x1, double y1) = (topLeft.X, topLeft.Y);
+        (double x2, double y2) = (topRight.X, topRight.Y);
+        (double x3, double y3) = (botRight.X, botRight.Y);
+        (double x4, double y4) = (botLeft.X, botLeft.Y);
+        (double w, double h) = (width, height);
+
+        double scaleX = (y1 * x2 * x4 - x1 * y2 * x4 + x1 * y3 * x4 - x2 * y3 * x4 - y1 * x2 * x3 + x1 * y2 * x3 - x1 * y4 * x3 + x2 * y4 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
+        double skewX = (-x1 * x2 * y3 - y1 * x2 * x4 + x2 * y3 * x4 + x1 * x2 * y4 + x1 * y2 * x3 + y1 * x4 * x3 - y2 * x4 * x3 - x1 * y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
+        double transX = x1;
+        double skewY = (-y1 * x2 * y3 + x1 * y2 * y3 + y1 * y3 * x4 - y2 * y3 * x4 + y1 * x2 * y4 - x1 * y2 * y4 - y1 * y4 * x3 + y2 * y4 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
+        double scaleY = (-y1 * x2 * y3 - y1 * y2 * x4 + y1 * y3 * x4 + x1 * y2 * y4 - x1 * y3 * y4 + x2 * y3 * y4 + y1 * y2 * x3 - y2 * y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
+        double transY = y1;
+        double persp0 = (x1 * y3 - x2 * y3 + y1 * x4 - y2 * x4 - x1 * y4 + x2 * y4 - y1 * x3 + y2 * x3) / (x2 * y3 * w + y2 * x4 * w - y3 * x4 * w - x2 * y4 * w - y2 * w * x3 + y4 * w * x3);
+        double persp1 = (-y1 * x2 + x1 * y2 - x1 * y3 - y2 * x4 + y3 * x4 + x2 * y4 + y1 * x3 - y4 * x3) / (x2 * y3 * h + y2 * x4 * h - y3 * x4 * h - x2 * y4 * h - y2 * h * x3 + y4 * h * x3);
+        double persp2 = 1;
+
+        return new Matrix3X3((float)scaleX, (float)skewX, (float)transX, (float)skewY, (float)scaleY, (float)transY, (float)persp0, (float)persp1, (float)persp2);
     }
     }
 
 
     public static (ShapeCorners, ShapeCorners) CreateStretchedHexagon(VecD centerPos, double hexagonSide, double stretchX)
     public static (ShapeCorners, ShapeCorners) CreateStretchedHexagon(VecD centerPos, double hexagonSide, double stretchX)

+ 4 - 1
src/ChunkyImageLib/Surface.cs

@@ -1,4 +1,5 @@
-using System.Runtime.CompilerServices;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
@@ -131,6 +132,7 @@ public class Surface : IDisposable
         return true;
         return true;
     }
     }
 
 
+#if DEBUG
     public void SaveToDesktop(string filename = "savedSurface.png")
     public void SaveToDesktop(string filename = "savedSurface.png")
     {
     {
         using var final = DrawingSurface.Create(new ImageInfo(Size.X, Size.Y, ColorType.Rgba8888, AlphaType.Premul, ColorSpace.CreateSrgb()));
         using var final = DrawingSurface.Create(new ImageInfo(Size.X, Size.Y, ColorType.Rgba8888, AlphaType.Premul, ColorSpace.CreateSrgb()));
@@ -142,6 +144,7 @@ public class Surface : IDisposable
             png.SaveTo(stream);
             png.SaveTo(stream);
         }
         }
     }
     }
+#endif
 
 
     private DrawingSurface CreateDrawingSurface()
     private DrawingSurface CreateDrawingSurface()
     {
     {

+ 0 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/SelectionToMask_Change.cs

@@ -48,8 +48,6 @@ internal class SelectionToMask_Change : Change
         image.SetBlendMode(blendMode);
         image.SetBlendMode(blendMode);
 
 
         var selectionImage = FloodFillHelper.FillSelection(target, selection!);
         var selectionImage = FloodFillHelper.FillSelection(target, selection!);
-        
-        selectionImage.SaveToDesktop();
 
 
         image.EnqueueDrawImage(new VecI(0, 0), selectionImage);
         image.EnqueueDrawImage(new VecI(0, 0), selectionImage);
         
         

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Surface/Pixmap.cs

@@ -9,6 +9,11 @@ public class Pixmap : NativeObject
     internal Pixmap(IntPtr objPtr) : base(objPtr)
     internal Pixmap(IntPtr objPtr) : base(objPtr)
     {
     {
     }
     }
+
+    public static Pixmap InternalCreateFromExistingPointer(IntPtr objPointer)
+    {
+        return new Pixmap(objPointer);
+    }
     
     
     public Pixmap(ImageInfo imgInfo, IntPtr dataPtr) : base(dataPtr)
     public Pixmap(ImageInfo imgInfo, IntPtr dataPtr) : base(dataPtr)
     {
     {

+ 1 - 1
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaPathImplementation.cs

@@ -99,7 +99,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         public RectD GetBounds(VectorPath vectorPath)
         public RectD GetBounds(VectorPath vectorPath)
         {
         {
             SKRect rect = ManagedInstances[vectorPath.ObjectPointer].Bounds;
             SKRect rect = ManagedInstances[vectorPath.ObjectPointer].Bounds;
-            return new RectD(rect.Left, rect.Top, rect.Right, rect.Bottom);
+            return RectD.FromSides(rect.Left, rect.Right, rect.Top, rect.Bottom);
         }
         }
 
 
         public void Reset(VectorPath vectorPath)
         public void Reset(VectorPath vectorPath)

+ 1 - 1
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaPixmapImplementation.cs

@@ -57,7 +57,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         public Pixmap CreateFrom(SKPixmap pixmap)
         public Pixmap CreateFrom(SKPixmap pixmap)
         {
         {
             ManagedInstances[pixmap.Handle] = pixmap;
             ManagedInstances[pixmap.Handle] = pixmap;
-            return new Pixmap(pixmap.Info.ToImageInfo(colorSpaceImplementation), pixmap.GetPixels());
+            return Pixmap.InternalCreateFromExistingPointer(pixmap.Handle);
         }
         }
     }
     }
 }
 }

+ 38 - 20
src/PixiEditor/App.xaml.cs

@@ -6,6 +6,7 @@ using System.Windows.Interop;
 using System.Windows.Media;
 using System.Windows.Media;
 using System.Windows.Threading;
 using System.Windows.Threading;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.Helpers;
 using PixiEditor.Models.AppExtensions;
 using PixiEditor.Models.AppExtensions;
 using PixiEditor.Helpers.UI;
 using PixiEditor.Helpers.UI;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
@@ -42,34 +43,37 @@ internal partial class App : Application
 
 
         if (ParseArgument("--crash (\"?)([A-z0-9:\\/\\ -_.]+)\\1", arguments, out Group[] groups))
         if (ParseArgument("--crash (\"?)([A-z0-9:\\/\\ -_.]+)\\1", arguments, out Group[] groups))
         {
         {
-            CrashReport report = CrashReport.Parse(groups[2].Value);
-            MainWindow = new CrashReportDialog(report);
-            MainWindow.Show();
+            try
+            {
+                CrashReport report = CrashReport.Parse(groups[2].Value);
+                MainWindow = new CrashReportDialog(report);
+                MainWindow.Show();
+            }
+            catch (Exception exception)
+            {
+                try
+                {
+                    CrashHelper.SendExceptionInfoToWebhook(exception, true);
+                }
+                finally
+                {
+                    MessageBox.Show("Fatal error", $"Fatal error while trying to open crash report in App.OnStartup()\n{exception}");
+                }
+            }
+
             return;
             return;
         }
         }
 
 
-        #if !STEAM
+#if !STEAM
         if (!HandleNewInstance())
         if (!HandleNewInstance())
         {
         {
             return;
             return;
         }
         }
-        #endif
-
-        LoadingWindow.ShowInNewThread();
-
-        AddNativeAssets();
-
-        InitPlatform();
-
-        ExtensionLoader extensionLoader = new ExtensionLoader();
-        extensionLoader.LoadExtensions();
-
+#endif
+        
+        var extensionLoader = InitApp();
+        
         MainWindow = new MainWindow(extensionLoader);
         MainWindow = new MainWindow(extensionLoader);
-        MainWindow.ContentRendered += (_, _) =>
-        {
-            LoadingWindow.Instance.SafeClose();
-            MainWindow.Activate();
-        };
         MainWindow.Show();
         MainWindow.Show();
     }
     }
 
 
@@ -80,6 +84,20 @@ internal partial class App : Application
         platform.PerformHandshake();
         platform.PerformHandshake();
     }
     }
 
 
+    public ExtensionLoader InitApp()
+    {
+        LoadingWindow.ShowInNewThread();
+
+        AddNativeAssets();
+
+        InitPlatform();
+
+        ExtensionLoader extensionLoader = new ExtensionLoader();
+        extensionLoader.LoadExtensions();
+        
+        return extensionLoader;
+    }
+
     private IPlatform GetActivePlatform()
     private IPlatform GetActivePlatform()
     {
     {
 #if STEAM
 #if STEAM

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/ar.json

@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "وضع النقر بزر الماوس الأيمن",
   "RIGHT_CLICK_MODE": "وضع النقر بزر الماوس الأيمن",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "أضف اللون الأساسي إلى لوح الألوان",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "أضف اللون الأساسي إلى لوح الألوان",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "أضف اللون الأساسي إلى اللوحة الحالية",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "أضف اللون الأساسي إلى اللوحة الحالية",
-  "COPY_COLOR": "انسخ اللون"
+  "COPY_COLOR": "انسخ اللون",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "لا يمكن فتح قائمة الملفات",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "لا يمكن استيراد الكل",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "لا يمكن استرداد الملفات بشكل كامل.\nإذا قمت بإرسال التقرير إلى المطورين\nقد يكونوا قادرين على مساعدتك."
 }
 }

+ 5 - 2
src/PixiEditor/Data/Localization/Languages/cs.json

@@ -23,7 +23,7 @@
   "UPDATE_CHANNEL_HELP_TOOLTIP": "Aktualizační  kanály mohou být aktualizovány jen v samostatných verzích aplikace (stáhnutých z https://pixieditor.net/) Steam a Microsoft Store verze zacházejí s jednotlivými verzemi odlišně.",
   "UPDATE_CHANNEL_HELP_TOOLTIP": "Aktualizační  kanály mohou být aktualizovány jen v samostatných verzích aplikace (stáhnutých z https://pixieditor.net/) Steam a Microsoft Store verze zacházejí s jednotlivými verzemi odlišně.",
   "DEBUG": "Debug",
   "DEBUG": "Debug",
   "ENABLE_DEBUG_MODE": "Aktivovat Debug mód",
   "ENABLE_DEBUG_MODE": "Aktivovat Debug mód",
-  "OPEN_CRASH_REPORTS_DIR": "Otevřít složku crash reportů",
+  "OPEN_CRASH_REPORTS_DIR": "Otevřít složku zpráv o selhání",
   "DISCORD_RICH_PRESENCE": "Bohatá přítomnost",
   "DISCORD_RICH_PRESENCE": "Bohatá přítomnost",
   "ENABLED": "Povoleno",
   "ENABLED": "Povoleno",
   "SHOW_IMAGE_NAME": "Ukázat jméno obrázku",
   "SHOW_IMAGE_NAME": "Ukázat jméno obrázku",
@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Režim pravého tlačítka",
   "RIGHT_CLICK_MODE": "Režim pravého tlačítka",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Přidat hlavní barvu do palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Přidat hlavní barvu do palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Přidat hlavní barvu do současné palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Přidat hlavní barvu do současné palety",
-  "COPY_COLOR": "Zkopírovat barvu"
+  "COPY_COLOR": "Zkopírovat barvu",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Nepodařilo se otevřít Průzkumníka Souborů",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Nepodařilo se obnovit všechno",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Nepodařilo se plně obnovit všechny soubory.\nKdyž pošlete zprávu o selhání vývojářům, možná vám budou schopni pomoct."
 }
 }

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/de.json

@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Rechtsklick Modus",
   "RIGHT_CLICK_MODE": "Rechtsklick Modus",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Primärfarbe zu Palette hinzufügen",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Primärfarbe zu Palette hinzufügen",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Primärfarbe der Farbpalette hinzufügen",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Primärfarbe der Farbpalette hinzufügen",
-  "COPY_COLOR": "Copy color"
+  "COPY_COLOR": "Farbe kopieren",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Windows Explorer konnte nicht geöffnet werden",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Konnte nicht alle Dokumente wiederherstellen",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Nichte alle Dateien konnten wiederhergestellt werden.\nDie Entwickler können dir eventuell helfen,\nalle Dateien wieder herzustellen."
 }
 }

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -589,5 +589,8 @@
   "COPY_COLOR": "Copy color",
   "COPY_COLOR": "Copy color",
 
 
   "FAILED_DOWNLOADING_TITLE": "Downloading update failed",
   "FAILED_DOWNLOADING_TITLE": "Downloading update failed",
-  "FAILED_DOWNLOADING": "Failed downloading the update, you might not have enough space on the disk"
+  "FAILED_DOWNLOADING": "Failed downloading the update, you might not have enough space on the disk",
+  
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Could not recover all",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Could not fully recover all files.\nIf you send the crash report to the developers\nthey might be able to help you."
 }
 }

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/it.json

@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Modalità tasto destro",
   "RIGHT_CLICK_MODE": "Modalità tasto destro",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Aggiungi colore primario alla tavolozza",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Aggiungi colore primario alla tavolozza",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Aggiungi colore primario alla tavolozza corrente",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Aggiungi colore primario alla tavolozza corrente",
-  "COPY_COLOR": "Copia colore"
+  "COPY_COLOR": "Copia colore",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Couldn't open File Explorer",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Could not recover all",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Could not fully recover all files.\nIf you send the crash report to the developers\nthey might be able to help you."
 }
 }

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/pl.json

@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Akcja prawego przysiku myszy",
   "RIGHT_CLICK_MODE": "Akcja prawego przysiku myszy",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Dodaj aktywny kolor do palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Dodaj aktywny kolor do palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Dodaj aktywny kolor do aktualnej palety",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Dodaj aktywny kolor do aktualnej palety",
-  "COPY_COLOR": "Kopiuj kolor"
+  "COPY_COLOR": "Kopiuj kolor",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Nie udało się otworzyć eksploratora plików",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Nie udało się odzyskać wszystkich plików",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Nie udało się odzyskać wszystkich plików. \nJeżeli wyślesz raport awarii do developerów, być może będą w stanie Ci pomóc."
 }
 }

+ 22 - 19
src/PixiEditor/Data/Localization/Languages/pt-br.json

@@ -561,24 +561,27 @@
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente. Mantenha pressionada a tecla Alt e arraste uma alça lateral para cortar. Arraste as alças externas para girar.",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente. Mantenha pressionada a tecla Alt e arraste uma alça lateral para cortar. Arraste as alças externas para girar.",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente. Arraste as alças externas para girar.",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente. Arraste as alças externas para girar.",
   "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente.",
   "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Arraste as alças para transformar a escala. Mantenha pressionada a tecla Shift para dimensionar proporcionalmente.",
-  "OPEN_DOCUMENTATION": "Open documentation",
+  "OPEN_DOCUMENTATION": "Abrir documentação",
   "LOCAL_PALETTE_SOURCE_NAME": "Local",
   "LOCAL_PALETTE_SOURCE_NAME": "Local",
-  "ERROR_FORBIDDEN_UNIQUE_NAME": "Extension unique name cannot start with 'pixieditor'.",
-  "ERROR_MISSING_METADATA": "Extension metadata key '{0}' is missing.",
-  "ERROR_NO_CLASS_ENTRY": "Extension class entry is missing on path '{0}'.",
-  "ERROR_NO_ENTRY_ASSEMBLY": "Extension entry assembly is missing on path '{0}'.",
-  "ERROR_MISSING_ADDITIONAL_CONTENT": "Your current setup doesn't allow loading this extension. Perhaps you don't own it or don't have it installed. You can purchase it here '{0}'.",
-  "BUY_SUPPORTER_PACK": "Buy Supporter Pack",
-  "NEWS": "News",
-  "DISABLE_NEWS_PANEL": "Disable News panel in startup window",
-  "FAILED_FETCH_NEWS": "Failed to fetch news",
-  "CROP_TO_SELECTION": "Crop to selection",
-  "CROP_TO_SELECTION_DESCRIPTIVE": "Crop image to selection",
-  "SHOW_CONTEXT_MENU": "Show context menu",
-  "ERASE": "Erase",
-  "USE_SECONDARY_COLOR": "Use secondary color",
-  "RIGHT_CLICK_MODE": "Right click mode",
-  "ADD_PRIMARY_COLOR_TO_PALETTE": "Add primary color to palette",
-  "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Add primary color to current palette",
-  "COPY_COLOR": "Copy color"
+  "ERROR_FORBIDDEN_UNIQUE_NAME": "O nome exclusivo da extensão não pode começar com \"pixieditor\".",
+  "ERROR_MISSING_METADATA": "A chave de metadados de extensão '{0}' está ausente.",
+  "ERROR_NO_CLASS_ENTRY": "A entrada da classe de extensão está ausente no caminho '{0}'.",
+  "ERROR_NO_ENTRY_ASSEMBLY": "O conjunto de entrada de extensão está ausente no caminho '{0}'.",
+  "ERROR_MISSING_ADDITIONAL_CONTENT": "Sua configuração atual não permite o carregamento dessa extensão. Talvez você não a possua ou não a tenha instalada. Você pode comprá-la aqui '{0}'",
+  "BUY_SUPPORTER_PACK": "Comprar Pacote de Apoiador",
+  "NEWS": "Notícias",
+  "DISABLE_NEWS_PANEL": "Desativar o painel Notícias na janela de inicialização",
+  "FAILED_FETCH_NEWS": "Falha ao buscar notícias",
+  "CROP_TO_SELECTION": "Cortar para a seleção",
+  "CROP_TO_SELECTION_DESCRIPTIVE": "Cortar imagem para seleção",
+  "SHOW_CONTEXT_MENU": "Mostrar menu de contexto",
+  "ERASE": "Apagar",
+  "USE_SECONDARY_COLOR": "Usar cor secundária",
+  "RIGHT_CLICK_MODE": "Modo de clique direito",
+  "ADD_PRIMARY_COLOR_TO_PALETTE": "Adicionar cor primária à paleta",
+  "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Adicionar cor primária à paleta atual",
+  "COPY_COLOR": "Copiar Cor",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Couldn't open File Explorer",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Could not recover all",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Could not fully recover all files.\nIf you send the crash report to the developers\nthey might be able to help you."
 }
 }

+ 38 - 35
src/PixiEditor/Data/Localization/Languages/ru.json

@@ -12,7 +12,7 @@
   "SHOW_IMAGE_PREVIEW_TASKBAR": "Отображать редактируемую картинку на иконке на панели задач",
   "SHOW_IMAGE_PREVIEW_TASKBAR": "Отображать редактируемую картинку на иконке на панели задач",
   "RECENT_FILE_LENGTH": "Длина списка недавних файлов",
   "RECENT_FILE_LENGTH": "Длина списка недавних файлов",
   "RECENT_FILE_LENGTH_TOOLTIP": "Сколько файлов показывать в списке Файл > Недавние. По умолчанию - 8.",
   "RECENT_FILE_LENGTH_TOOLTIP": "Сколько файлов показывать в списке Файл > Недавние. По умолчанию - 8.",
-  "DEFAULT_NEW_SIZE": "Размер нового файла по умолчанию",
+  "DEFAULT_NEW_SIZE": "Размер холста по умолчанию",
   "WIDTH": "Ширина",
   "WIDTH": "Ширина",
   "HEIGHT": "Высота",
   "HEIGHT": "Высота",
   "TOOLS": "Инструменты",
   "TOOLS": "Инструменты",
@@ -51,8 +51,8 @@
   "LICENSE": "Лицензия",
   "LICENSE": "Лицензия",
   "OPEN_LICENSE": "Открыть лицензию",
   "OPEN_LICENSE": "Открыть лицензию",
   "THIRD_PARTY_LICENSES": "Лицензии третьих сторон",
   "THIRD_PARTY_LICENSES": "Лицензии третьих сторон",
-  "OPEN_THIRD_PARTY_LICENSES": "Открыть лицензии третьих сторон",
-  "APPLY_TRANSFORM": "Применить трансформирование",
+  "OPEN_THIRD_PARTY_LICENSES": "Открыть сторонние лицензии",
+  "APPLY_TRANSFORM": "Применить масштабирование",
   "INCREASE_TOOL_SIZE": "Увеличить размер кисти",
   "INCREASE_TOOL_SIZE": "Увеличить размер кисти",
   "DECREASE_TOOL_SIZE": "Уменьшить размер кисти",
   "DECREASE_TOOL_SIZE": "Уменьшить размер кисти",
   "TO_INSTALL_UPDATE": "для установки обновления {0}",
   "TO_INSTALL_UPDATE": "для установки обновления {0}",
@@ -133,9 +133,9 @@
   "MERGE_WITH_BELOW_DESCRIPTIVE": "Объединить выбранный слой со слоем ниже от него",
   "MERGE_WITH_BELOW_DESCRIPTIVE": "Объединить выбранный слой со слоем ниже от него",
   "ADD_REFERENCE_LAYER": "Добавить референс",
   "ADD_REFERENCE_LAYER": "Добавить референс",
   "DELETE_REFERENCE_LAYER": "Удалить референс",
   "DELETE_REFERENCE_LAYER": "Удалить референс",
-  "TRANSFORM_REFERENCE_LAYER": "Трансформировать референс",
+  "TRANSFORM_REFERENCE_LAYER": "Масштабировать референс",
   "TOGGLE_REFERENCE_LAYER_POS": "Изменить позицию референса",
   "TOGGLE_REFERENCE_LAYER_POS": "Изменить позицию референса",
-  "TOGGLE_REFERENCE_LAYER_POS_DESCRIPTIVE": "Переключение между двумя положениями референса: поверх рисунка и ниже рисунка",
+  "TOGGLE_REFERENCE_LAYER_POS_DESCRIPTIVE": "Переключение между двумя положениями референса: поверх хоста и под холстом",
   "RESET_REFERENCE_LAYER_POS": "Сбросить положение референса",
   "RESET_REFERENCE_LAYER_POS": "Сбросить положение референса",
   "CLIP_CANVAS": "Обрезать прозрачные края",
   "CLIP_CANVAS": "Обрезать прозрачные края",
   "FLIP_IMG_VERTICALLY": "Отразить по вертикали",
   "FLIP_IMG_VERTICALLY": "Отразить по вертикали",
@@ -162,7 +162,7 @@
   "PASTE_AS_NEW_LAYER": "Вставить в новый слой",
   "PASTE_AS_NEW_LAYER": "Вставить в новый слой",
   "PASTE_AS_NEW_LAYER_DESCRIPTIVE": "Вставить изображение из буфера обмена в новый слой",
   "PASTE_AS_NEW_LAYER_DESCRIPTIVE": "Вставить изображение из буфера обмена в новый слой",
   "PASTE_REFERENCE_LAYER": "Вставить референс",
   "PASTE_REFERENCE_LAYER": "Вставить референс",
-  "PASTE_REFERENCE_LAYER_DESCRIPTIVE": "Вставить изображение-референс из буфера обмена",
+  "PASTE_REFERENCE_LAYER_DESCRIPTIVE": "Вставить референс из буфера обмена",
   "PASTE_COLOR": "Вставить цвет",
   "PASTE_COLOR": "Вставить цвет",
   "PASTE_COLOR_DESCRIPTIVE": "Вставить HEX-код цвета из буфера обмена",
   "PASTE_COLOR_DESCRIPTIVE": "Вставить HEX-код цвета из буфера обмена",
   "PASTE_COLOR_SECONDARY": "Вставить цвет как дополнительный",
   "PASTE_COLOR_SECONDARY": "Вставить цвет как дополнительный",
@@ -223,7 +223,7 @@
   "CLEAR_SELECTION": "Снять выделение",
   "CLEAR_SELECTION": "Снять выделение",
   "INVERT_SELECTION": "Инвертировать выделение",
   "INVERT_SELECTION": "Инвертировать выделение",
   "INVERT_SELECTION_DESCRIPTIVE": "Инвертировать выделенную область",
   "INVERT_SELECTION_DESCRIPTIVE": "Инвертировать выделенную область",
-  "TRANSFORM_SELECTED_AREA": "Трансформировать выбранную область",
+  "TRANSFORM_SELECTED_AREA": "Масштабировать выбранную область",
   "NUDGE_SELECTED_LEFT": "Сдвинуть выделение влево",
   "NUDGE_SELECTED_LEFT": "Сдвинуть выделение влево",
   "NUDGE_SELECTED_RIGHT": "Сдвинуть выделение вправо",
   "NUDGE_SELECTED_RIGHT": "Сдвинуть выделение вправо",
   "NUDGE_SELECTED_UP": "Сдвинуть выделение вверх",
   "NUDGE_SELECTED_UP": "Сдвинуть выделение вверх",
@@ -275,7 +275,7 @@
   "UNNAMED": "Безымянный",
   "UNNAMED": "Безымянный",
   "OPEN_COMMAND_DEBUG_WINDOW": "Открыть окно отладки команд",
   "OPEN_COMMAND_DEBUG_WINDOW": "Открыть окно отладки команд",
   "DELETE": "Удалить",
   "DELETE": "Удалить",
-  "USER_PREFS": "Предпочтения пользователя (Локальные)",
+  "USER_PREFS": "Предпочтения пользователя (Roaming)",
   "SHORTCUT_FILE": "Сочетания клавиш (Локальные)",
   "SHORTCUT_FILE": "Сочетания клавиш (Локальные)",
   "EDITOR_DATA": "Данные редактора (Локальные)",
   "EDITOR_DATA": "Данные редактора (Локальные)",
   "MOVE_VIEWPORT_TOOLTIP": "Передвигает область просмотра.",
   "MOVE_VIEWPORT_TOOLTIP": "Передвигает область просмотра.",
@@ -359,7 +359,7 @@
   "ENABLE_MASK": "Включить маску",
   "ENABLE_MASK": "Включить маску",
   "SELECTED_AREA_EMPTY": "Выбранная область пуста",
   "SELECTED_AREA_EMPTY": "Выбранная область пуста",
   "NOTHING_TO_COPY": "Нечего копировать",
   "NOTHING_TO_COPY": "Нечего копировать",
-  "REFERENCE_LAYER_PATH": "Путь к референс слою",
+  "REFERENCE_LAYER_PATH": "Путь к референсу",
   "FLIP": "Отразить",
   "FLIP": "Отразить",
   "ROTATION": "Поворот",
   "ROTATION": "Поворот",
   "ROT_IMG_90_D": "Повернуть изображение на 90°",
   "ROT_IMG_90_D": "Повернуть изображение на 90°",
@@ -481,10 +481,10 @@
   "STOP_IT_TEXT4": "sans undertale reference omg so cool",
   "STOP_IT_TEXT4": "sans undertale reference omg so cool",
   "LINEAR_DODGE_BLEND_MODE": "Линейный осветлитель (добавить)",
   "LINEAR_DODGE_BLEND_MODE": "Линейный осветлитель (добавить)",
   "PRESS_ANY_KEY": "Нажмите любую клавишу",
   "PRESS_ANY_KEY": "Нажмите любую клавишу",
-  "NONE_SHORTCUT": "Ничего",
+  "NONE_SHORTCUT": "Нет",
   "REFERENCE": "Референс",
   "REFERENCE": "Референс",
-  "PUT_REFERENCE_LAYER_ABOVE": "Показать слой референса",
-  "PUT_REFERENCE_LAYER_BELOW": "Спрятать слой референса",
+  "PUT_REFERENCE_LAYER_ABOVE": "Отображать референс поверх холста",
+  "PUT_REFERENCE_LAYER_BELOW": "Отображать референс под холстом",
   "TOGGLE_VERTICAL_SYMMETRY": "Переключить вертикальную ось симметрии",
   "TOGGLE_VERTICAL_SYMMETRY": "Переключить вертикальную ось симметрии",
   "TOGGLE_HORIZONTAL_SYMMETRY": "Переключить горизонтальную ось симметрии",
   "TOGGLE_HORIZONTAL_SYMMETRY": "Переключить горизонтальную ось симметрии",
   "RESET_VIEWPORT": "Сбросить область просмотра",
   "RESET_VIEWPORT": "Сбросить область просмотра",
@@ -533,52 +533,55 @@
   "IMPORT_PALETTE_FILE": "Импортировать файл палитры",
   "IMPORT_PALETTE_FILE": "Импортировать файл палитры",
   "IMPORT_MULTIPLE_PALETTE_COLORS": "Импортировать цвета в палитру",
   "IMPORT_MULTIPLE_PALETTE_COLORS": "Импортировать цвета в палитру",
   "IMPORT_SINGLE_PALETTE_COLOR": "Импортировать цвет в палитру",
   "IMPORT_SINGLE_PALETTE_COLOR": "Импортировать цвет в палитру",
-  "IMPORT_AS_REFERENCE_LAYER": "Импортировать как слой референса",
+  "IMPORT_AS_REFERENCE_LAYER": "Импортировать как референс",
   "NAVIGATOR_PICK_ACTION_DISPLAY": "ПКМ чтобы взять цвет, Shift + ПКМ чтобы скопировать цвет в буфер обмена",
   "NAVIGATOR_PICK_ACTION_DISPLAY": "ПКМ чтобы взять цвет, Shift + ПКМ чтобы скопировать цвет в буфер обмена",
   "OPEN_FILE_FROM_CLIPBOARD": "Открыть из буфера обмена",
   "OPEN_FILE_FROM_CLIPBOARD": "Открыть из буфера обмена",
   "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "Открыть из буфера обмена",
   "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "Открыть из буфера обмена",
   "OPEN_LOCALIZATION_DATA": "Хотите открыть LocalizationData.json? Обновлённая дата добавлена в буфер обмена. Перезапустите чтобы применить изменения.",
   "OPEN_LOCALIZATION_DATA": "Хотите открыть LocalizationData.json? Обновлённая дата добавлена в буфер обмена. Перезапустите чтобы применить изменения.",
-  "DOWNLOADING_LANGUAGE_FAILED": "Не удалось загрузить язык. API ключ может быть использован слишком часто.",
+  "DOWNLOADING_LANGUAGE_FAILED": "Не удалось загрузить язык. \nВозможно был превышена допустимая частота запросов для API ключа.",
   "LOCALIZATION_DATA_NOT_FOUND": "Путь к данным локализации не найден",
   "LOCALIZATION_DATA_NOT_FOUND": "Путь к данным локализации не найден",
   "APPLY": "Применить",
   "APPLY": "Применить",
   "UPDATE_SOURCE": "Обновить источник",
   "UPDATE_SOURCE": "Обновить источник",
   "COPY_TO_CLIPBOARD": "Скопировать в буфер обмена",
   "COPY_TO_CLIPBOARD": "Скопировать в буфер обмена",
-  "LANGUAGE_FILE_NOT_FOUND": "Файл языка не найден. Идёт поиск {0}",
-  "PROJECT_ROOT_NOT_FOUND": "Корневой файл проекта PixiEditor не был найден. Идёт поиск PixiEditor.csproj",
-  "LOCALIZATION_FOLDER_NOT_FOUND": "Путь к папке локализации не найден. Идёт поиск /Data/Localization",
+  "LANGUAGE_FILE_NOT_FOUND": "Файл языка не найден. \nИщем {0}",
+  "PROJECT_ROOT_NOT_FOUND": "Корневой файл проекта PixiEditor не был найден. \nИщем PixiEditor.csproj",
+  "LOCALIZATION_FOLDER_NOT_FOUND": "Путь к папке локализации не найден. \nИщем /Data/Localization",
   "SELECT_A_LANGUAGE": "Выберите язык",
   "SELECT_A_LANGUAGE": "Выберите язык",
   "DONE": "Готово",
   "DONE": "Готово",
-  "SOURCE_UNSET_OR_MISSING": "Источник отсутствует/не поставлен",
+  "SOURCE_UNSET_OR_MISSING": "Источник отсутствует/не проставлен",
   "SOURCE_NEWER": "Источник новее",
   "SOURCE_NEWER": "Источник новее",
   "SOURCE_UP_TO_DATE": "Источник обновлён",
   "SOURCE_UP_TO_DATE": "Источник обновлён",
-  "SOURCE_OLDER": "Облако новее",
-  "COLOR_PICKER_ACTION_DISPLAY_REFERENCE_ONLY": "Нажмите чтобы брать цвета из рефернс слоя.",
+  "SOURCE_OLDER": "Облачная версия новее",
+  "COLOR_PICKER_ACTION_DISPLAY_REFERENCE_ONLY": "Кликните для выбора цвета из референса.",
   "COLOR_PICKER_ACTION_DISPLAY_CANVAS_ONLY": "Нажмите чтобы брать цвета из холста.",
   "COLOR_PICKER_ACTION_DISPLAY_CANVAS_ONLY": "Нажмите чтобы брать цвета из холста.",
-  "LOCALIZATION_DEBUG_WINDOW_TITLE": "Окно дебага локализаций",
-  "COMMAND_DEBUG_WINDOW_TITLE": "Окно дебага команд",
-  "SHORTCUTS_TITLE": "Ярлыки",
-  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_PERSPECTIVE": "Двигайте ручки чтобы изменить масштаб. Удерживайте Ctrl и передвигайте ручку чтобы передвигать ручку без изменений масштаба. Удерживайте Alt и передвигайте сторону ручки чтобы сдвинуть. Выдвиньте из ручки чтобы повернуть.",
-  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Двигайте ручки чтобы изменить масштаб. Удерживайте Shift чтобы масштабировать пропорционально. Удерживайте Alt и передвигайте сторону ручки чтобы сдвинуть. Выдвиньте из ручки чтобы повернуть.",
-  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Двигайте ручки чтобы изменить масштаб. Удерживайте Shift чтобы масштабировать пропорционально. Выдвиньте из ручек чтобы повернуть.",
-  "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Двигайте ручки чтобы изменить масштаб. Удерживайте Shift чтобы масштабировать пропорционально.",
+  "LOCALIZATION_DEBUG_WINDOW_TITLE": "Окно отладки локализаций",
+  "COMMAND_DEBUG_WINDOW_TITLE": "Окно отладки команд",
+  "SHORTCUTS_TITLE": "Сочетания клавиш",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_PERSPECTIVE": "Перетащите углы и края для масштабирования. Зажмите Ctrl для свободного масштабирования. Удерживайте Alt и перемещайте края для бокового сдвига. Для поворота зажмите и перетащите вблизи выделения.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Перетащите углы и края для масштабирования. Зажмите Shift для пропорционального масштабирования. Удерживайте Alt и перемещайте края для бокового сдвига. Для поворота зажмите и перетащите вблизи выделения.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Двигайте ручки чтобы изменить масштаб. Удерживайте Shift чтобы масштабировать пропорционально. Для поворота зажмите и перетащите вблизи выделения.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Перемещайте углы и края для масштабирования. Зажмите Shift для пропорционального масштабирования.",
   "OPEN_DOCUMENTATION": "Открыть документацию",
   "OPEN_DOCUMENTATION": "Открыть документацию",
   "LOCAL_PALETTE_SOURCE_NAME": "Локально",
   "LOCAL_PALETTE_SOURCE_NAME": "Локально",
-  "ERROR_FORBIDDEN_UNIQUE_NAME": "Уникальное имя приложения не может начинаться с 'pixieditor'.",
-  "ERROR_MISSING_METADATA": "Ключ метадаты приложения '{0}' отсутствует.",
-  "ERROR_NO_CLASS_ENTRY": "Запись в классе приложения отсутствует в папке '{0}'.",
-  "ERROR_NO_ENTRY_ASSEMBLY": "Входная сборка приложения отсутствует в папке '{0}'.",
-  "ERROR_MISSING_ADDITIONAL_CONTENT": "Ваша нынешняя сборка не позволяет загрузить это приложение. Возможно вы не приобрели его или не установили. Вы можете приобрести его здесь '{0}'.",
-  "BUY_SUPPORTER_PACK": "Приобретите Supporter Pack",
+  "ERROR_FORBIDDEN_UNIQUE_NAME": "Уникальное имя расширения не может начинаться с 'pixieditor'.",
+  "ERROR_MISSING_METADATA": "Ключ метадаты расширения '{0}' отсутствует.",
+  "ERROR_NO_CLASS_ENTRY": "Запись в классе расширения отсутствует в папке '{0}'.",
+  "ERROR_NO_ENTRY_ASSEMBLY": "Входная сборка расширения отсутствует в папке '{0}'.",
+  "ERROR_MISSING_ADDITIONAL_CONTENT": "Ваша нынешняя сборка не позволяет загрузить это расширение. Возможно вы не приобрели его или не установили. Вы можете приобрести его здесь '{0}'.",
+  "BUY_SUPPORTER_PACK": "Приобрести Supporter Pack",
   "NEWS": "Новости",
   "NEWS": "Новости",
   "DISABLE_NEWS_PANEL": "Отключить новостную панель в окне приветствия",
   "DISABLE_NEWS_PANEL": "Отключить новостную панель в окне приветствия",
   "FAILED_FETCH_NEWS": "Не удалось загрузить новости",
   "FAILED_FETCH_NEWS": "Не удалось загрузить новости",
   "CROP_TO_SELECTION": "Обрезать выделение",
   "CROP_TO_SELECTION": "Обрезать выделение",
   "CROP_TO_SELECTION_DESCRIPTIVE": "Обрезать изображение до выделения",
   "CROP_TO_SELECTION_DESCRIPTIVE": "Обрезать изображение до выделения",
-  "SHOW_CONTEXT_MENU": "Показать меню контекста",
+  "SHOW_CONTEXT_MENU": "Открыть контекстное меню",
   "ERASE": "Стереть",
   "ERASE": "Стереть",
   "USE_SECONDARY_COLOR": "Использовать дополнительный цвет",
   "USE_SECONDARY_COLOR": "Использовать дополнительный цвет",
   "RIGHT_CLICK_MODE": "Режим ПКМ",
   "RIGHT_CLICK_MODE": "Режим ПКМ",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Добавить основной цвет в палитру",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Добавить основной цвет в палитру",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Добавить основной цвет в нынешнюю палитру",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Добавить основной цвет в нынешнюю палитру",
-  "COPY_COLOR": "Скопировать цвет"
+  "COPY_COLOR": "Скопировать цвет",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Не удалось открыть Проводник",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Не удалось восстановить все файлы",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Не удалось восстановить все файлы.\nЕсли вы отправите отчет о сбое разработчикам, возможно, они смогут вам помочь."
 }
 }

+ 585 - 582
src/PixiEditor/Data/Localization/Languages/tr.json

@@ -1,584 +1,587 @@
 {
 {
-    "RECENT_FILES": "Son Dosyalar",
-    "OPEN_FILE": "Dosya Aç",
-    "NEW_FILE": "Yeni",
-    "RECENT_EMPTY_TEXT": "Çok fazla boşluk",
-    "LANGUAGE": "Dil",
-    "GENERAL": "Genel",
-    "DISCORD": "Discord",
-    "KEY_BINDINGS": "Tuş Atamaları",
-    "MISC": "Çeşitli",
-    "SHOW_STARTUP_WINDOW": "Başlangıç Ekranını Göster",
-    "SHOW_IMAGE_PREVIEW_TASKBAR": "Görev çubuğunda resim önizlemesini göster",
-    "RECENT_FILE_LENGTH": "Son dosya listesi uzunluğu",
-    "RECENT_FILE_LENGTH_TOOLTIP": "Dosya > Son dosyalar altında gösterilen belge sayısı. Varsayılan: 8",
-    "DEFAULT_NEW_SIZE": "Varsayılan yeni dosya boyutu",
-    "WIDTH": "Genişlik",
-    "HEIGHT": "Yükseklik",
-    "TOOLS": "Araçlar",
-    "ENABLE_SHARED_TOOLBAR": "Paylaşılan araç çubuğunu etkinleştir",
-    "AUTOMATIC_UPDATES": "Otomatik Güncellemeler",
-    "CHECK_FOR_UPDATES": "Başlangıçta güncellemeleri kontrol et",
-    "UPDATE_STREAM": "Güncelleme akışı",
-    "UPDATE_CHANNEL_HELP_TOOLTIP": "Güncelleme kanalları yalnızca bağımsız sürümde (https://pixieditor.net'den indirilen) değiştirilebilir.\nSteam ve Microsoft Store sürümleri güncellemeleri ayrı şekilde yönetir.",
-    "DEBUG": "Hata Ayıklama",
-    "ENABLE_DEBUG_MODE": "Hata Ayıklama modunu etkinleştir",
-    "OPEN_CRASH_REPORTS_DIR": "Çökme raporları dizinini aç",
-    "DISCORD_RICH_PRESENCE": "Zengin Durum",
-    "ENABLED": "Etkin",
-    "SHOW_IMAGE_NAME": "Resim adını göster",
-    "SHOW_IMAGE_SIZE": "Resim boyutunu göster",
-    "SHOW_LAYER_COUNT": "Katman sayısını göster",
-    "FILE": "Dosya",
-    "RECENT": "Son",
-    "OPEN": "Aç",
-    "SAVE_PIXI": "Kaydet (.pixi)",
-    "SAVE_AS_PIXI": "Farklı Kaydet... (.pixi)",
-    "EXPORT_IMG": "Dışa Aktar (.png, .jpg, vb.)",
-    "EDIT": "Düzenle",
-    "EXIT": "Çıkış",
-    "PERCENTAGE": "Yüzde",
-    "ABSOLUTE": "Mutlak",
-    "PRESERVE_ASPECT_RATIO": "En-boy oranını koru",
-    "ANCHOR_POINT": "Bağlama Noktası",
-    "RESIZE_IMAGE": "Resmi Yeniden Boyutlandır",
-    "RESIZE": "Yeniden Boyutlandır",
-    "DOCUMENTATION": "Dokümantasyon",
-    "WEBSITE": "Web Sitesi",
-    "OPEN_WEBSITE": "Web sitesini aç",
-    "REPOSITORY": "Depo",
-    "OPEN_REPOSITORY": "Depoyu aç",
-    "LICENSE": "Lisans",
-    "OPEN_LICENSE": "Lisansı aç",
-    "THIRD_PARTY_LICENSES": "Üçüncü Taraf Lisansları",
-    "OPEN_THIRD_PARTY_LICENSES": "Üçüncü taraf lisanslarını aç",
-    "APPLY_TRANSFORM": "Dönüşümü Uygula",
-    "INCREASE_TOOL_SIZE": "Araç boyutunu artır",
-    "DECREASE_TOOL_SIZE": "Araç boyutunu azalt",
-    "TO_INSTALL_UPDATE": "güncellemeyi yüklemek için {0}",
-    "DOWNLOADING_UPDATE": "Güncelleme indiriliyor...",
-    "UPDATE_READY": "Güncelleme yüklemeye hazır. Şimdi yüklemek istiyor musunuz?",
-    "NEW_UPDATE": "Yeni güncelleme",
-    "COULD_NOT_UPDATE_WITHOUT_ADMIN": "Yönetici ayrıcalıkları olmadan güncelleme yapılamadı. Lütfen PixiEditor'ü yönetici olarak çalıştırın.",
-    "INSUFFICIENT_PERMISSIONS": "Yetersiz izinler",
-    "UPDATE_CHECK_FAILED": "Güncelleme kontrolü başarısız oldu",
-    "COULD_NOT_CHECK_FOR_UPDATES": "Güncelleme mevcut olup olmadığı kontrol edilemedi.",
-    "VERSION": "Sürüm {0}",
-    "OPEN_TEMP_DIR": "Geçici dizini aç",
-    "OPEN_LOCAL_APPDATA_DIR": "Yerel AppData dizinini aç",
-    "OPEN_ROAMING_APPDATA_DIR": "Gezintili AppData dizinini aç",
-    "OPEN_INSTALLATION_DIR": "Kurulum dizinini aç",
-    "DUMP_ALL_COMMANDS": "Tüm komutları dök",
-    "DUMP_ALL_COMMANDS_DESCRIPTIVE": "Tüm komutları bir metin dosyasına dök",
-    "CRASH": "Çökme",
-    "CRASH_APP": "Uygulamayı çökert",
-    "DELETE_USR_PREFS": "Kullanıcı tercihlerini sil (Gezintili AppData)",
-    "DELETE_SHORTCUT_FILE": "Kısayol dosyasını sil (Gezintili AppData)",
-    "DELETE_EDITOR_DATA": "Düzenleyici verilerini sil (Yerel AppData)",
-    "GENERATE_KEY_BINDINGS_TEMPLATE": "Tuş atama şablonu oluştur",
-    "GENERATE_KEY_BINDINGS_TEMPLATE_DESCRIPTIVE": "Tuş atama json şablonu oluştur",
-    "VALIDATE_SHORTCUT_MAP": "Kısayol haritasını doğrula",
-    "VALIDATE_SHORTCUT_MAP_DESCRIPTIVE": "Kısayol haritasını doğrular",
-    "VALIDATION_KEYS_NOTICE_DIALOG": "Boş anahtarlar: {0}\nBilinmeyen Komutlar: {1}",
-    "RESULT": "Sonuç",
-    "CLEAR_RECENT_DOCUMENTS": "Son belgeleri temizle",
-    "CLEAR_RECENTLY_OPENED_DOCUMENTS": "Yeni açılan belgeleri temizle",
-    "OPEN_CMD_DEBUG_WINDOW": "Komut hata ayıklama penceresini aç",
-    "PATH_DOES_NOT_EXIST": "{0} mevcut değil.",
-    "LOCATION_DOES_NOT_EXIST": "Konum mevcut değil.",
-    "FILE_NOT_FOUND": "Dosya bulunamadı.",
-    "ARE_YOU_SURE": "Emin misiniz?",
-    "ARE_YOU_SURE_PATH_FULL_PATH": "{0}'yi silmek istediğinizden emin misiniz?\nBu veri tüm yüklemeler için kaybolacak.\n(Tam Yol: {1})",
-    "FAILED_TO_OPEN_FILE": "Dosya açılamadı",
-    "OLD_FILE_FORMAT": "Eski dosya formatı",
-    "OLD_FILE_FORMAT_DESCRIPTION": "Bu .pixi dosyası eski formatta kullanılmıştır,\n artık desteklenmiyor ve açılamaz.",
-    "NOTHING_FOUND": "Hiçbir şey bulunamadı",
-    "EXPORT": "Dışa Aktar",
-    "EXPORT_IMAGE": "Resmi Dışa Aktar",
-    "IMPORT": "İçe Aktar",
-    "SHORTCUT_TEMPLATES": "Kısayol şablonları",
-    "RESET_ALL": "Hepsini Sıfırla",
-    "LAYER": "Katman",
-    "LAYER_DELETE_SELECTED": "Aktif katmanı/dizini sil",
-    "LAYER_DELETE_SELECTED_DESCRIPTIVE": "Aktif katmanı veya dizini sil",
-    "LAYER_DELETE_ALL_SELECTED": "Tüm seçili katmanları/dizinleri sil",
-    "LAYER_DELETE_ALL_SELECTED_DESCRIPTIVE": "Tüm seçili katmanları ve/veya dizinleri sil",
-    "DELETE_SELECTED_PIXELS": "Seçili pikselleri sil",
-    "NEW_FOLDER": "Yeni klasör",
-    "CREATE_NEW_FOLDER": "Yeni klasör oluştur",
-    "NEW_LAYER": "Yeni katman",
-    "CREATE_NEW_LAYER": "Yeni katman oluştur",
-    "NEW_IMAGE": "Yeni görüntü",
-    "CREATE_NEW_IMAGE": "Yeni görüntü oluştur",
-    "SAVE": "Kaydet",
-    "SAVE_AS": "Farklı Kaydet...",
-    "IMAGE": "Görüntü",
-    "SAVE_IMAGE": "Görüntüyü kaydet",
-    "SAVE_IMAGE_AS": "Yeni olarak görüntüyü kaydet",
-    "DUPLICATE": "Kopyala",
-    "DUPLICATE_SELECTED_LAYER": "Seçili katmanı kopyala",
-    "CREATE_MASK": "Maske oluştur",
-    "DELETE_MASK": "Maskeyi sil",
-    "TOGGLE_MASK": "Maskesi aç/kapat",
-    "APPLY_MASK": "Maskeyi uygula",
-    "TOGGLE_VISIBILITY": "Görünürlüğü aç/kapat",
-    "MOVE_MEMBER_UP": "Üyeyi yukarı taşı",
-    "MOVE_MEMBER_UP_DESCRIPTIVE": "Seçili katmanı veya dizini yukarı taşı",
-    "MOVE_MEMBER_DOWN": "Üyeyi aşağı taşı",
-    "MOVE_MEMBER_DOWN_DESCRIPTIVE": "Seçili katmanı veya dizini aşağı taşı",
-    "MERGE_ALL_SELECTED_LAYERS": "Tüm seçili katmanları birleştir",
-    "MERGE_WITH_ABOVE": "Seçili katmanı üsttekiyle birleştir",
-    "MERGE_WITH_ABOVE_DESCRIPTIVE": "Seçili katmanı üzerindekiyle birleştir",
-    "MERGE_WITH_BELOW": "Seçili katmanı alttakilerle birleştir",
-    "MERGE_WITH_BELOW_DESCRIPTIVE": "Seçili katmanı altındakilerle birleştir",
-    "ADD_REFERENCE_LAYER": "Referans Katman Ekle",
-    "DELETE_REFERENCE_LAYER": "Referans katmanı sil",
-    "TRANSFORM_REFERENCE_LAYER": "Referans katmanını dönüştür",
-    "TOGGLE_REFERENCE_LAYER_POS": "Referans katmanının konumunu değiştir",
-    "TOGGLE_REFERENCE_LAYER_POS_DESCRIPTIVE": "Referans katmanını en üstte veya en altta arasında değiştir",
-    "RESET_REFERENCE_LAYER_POS": "Referans katmanının konumunu sıfırla",
-    "CLIP_CANVAS": "Kanvası Kırp",
-    "FLIP_IMG_VERTICALLY": "Görüntüyü Dikey Olarak Çevir",
-    "FLIP_IMG_HORIZONTALLY": "Görüntüyü Yatay Olarak Çevir",
-    "FLIP_LAYERS_VERTICALLY": "Seçili Katmanları Dikey Olarak Çevir",
-    "FLIP_LAYERS_HORIZONTALLY": "Seçili Katmanları Yatay Olarak Çevir",
-    "ROT_IMG_90": "Görüntüyü 90 derece döndür",
-    "ROT_IMG_180": "Görüntüyü 180 derece döndür",
-    "ROT_IMG_-90": "Görüntüyü -90 derece döndür",
-    "ROT_LAYERS_90": "Seçili Katmanları 90 derece döndür",
-    "ROT_LAYERS_180": "Seçili Katmanları 180 derece döndür",
-    "ROT_LAYERS_-90": "Seçili Katmanları -90 derece döndür",
-    "TOGGLE_VERT_SYMMETRY_AXIS": "Dikey simetri eksenini aç/kapat",
-    "TOGGLE_HOR_SYMMETRY_AXIS": "Yatay simetri eksenini aç/kapat",
-    "DELETE_PIXELS": "Pikselleri sil",
-    "DELETE_PIXELS_DESCRIPTIVE": "Seçili pikselleri sil",
-    "RESIZE_DOCUMENT": "Belgeyi Yeniden Boyutlandır",
-    "RESIZE_CANVAS": "Kanvası Yeniden Boyutlandır",
-    "CENTER_CONTENT": "İçeriği Ortala",
-    "CUT": "Kes",
-    "CUT_DESCRIPTIVE": "Seçili alanı/katmanları kes",
-    "PASTE": "Yapıştır",
-    "PASTE_DESCRIPTIVE": "Pano içeriğini yapıştır",
-    "PASTE_AS_NEW_LAYER": "Yeni katman olarak yapıştır",
-    "PASTE_AS_NEW_LAYER_DESCRIPTIVE": "Panodan yeni bir katman olarak yapıştır",
-    "PASTE_REFERENCE_LAYER": "Referans katmanını yapıştır",
-    "PASTE_REFERENCE_LAYER_DESCRIPTIVE": "Panodaki içeriği referans katmanı olarak yapıştır",
-    "PASTE_COLOR": "Rengi yapıştır",
-    "PASTE_COLOR_DESCRIPTIVE": "Panodan rengi yapıştır",
-    "PASTE_COLOR_SECONDARY": "İkincil olarak yapıştır",
-    "PASTE_COLOR_SECONDARY_DESCRIPTIVE": "Panodan rengi ikincil renk olarak yapıştır",
-    "CLIPBOARD": "Pano",
-    "COPY": "Kopyala",
-    "COPY_DESCRIPTIVE": "Panoya kopyala",
-    "COPY_COLOR_HEX": "Birincil rengi kopyala (HEX)",
-    "COPY_COLOR_HEX_DESCRIPTIVE": "Birincil rengi HEX kodu olarak kopyala",
-    "COPY_COLOR_RGB": "Birincil rengi kopyala (RGB)",
-    "COPY_COLOR_RGB_DESCRIPTIVE": "Birincil rengi RGB kodu olarak kopyala",
-    "COPY_COLOR_SECONDARY_HEX": "İkincil rengi kopyala (HEX)",
-    "COPY_COLOR_SECONDARY_HEX_DESCRIPTIVE": "İkincil rengi HEX kodu olarak kopyala",
-    "COPY_COLOR_SECONDARY_RGB": "İkincil rengi kopyala (RGB)",
-    "COPY_COLOR_SECONDARY_RGB_DESCRIPTIVE": "İkincil rengi RGB kodu olarak kopyala",
-    "PALETTE_COLORS": "Palet Renkleri",
-    "REPLACE_SECONDARY_BY_PRIMARY": "İkincil rengi birincil renk ile değiştir",
-    "REPLACE_SECONDARY_BY_PRIMARY_DESCRIPTIVE": "İkincil rengi birincil renk ile değiştir",
-    "REPLACE_PRIMARY_BY_SECONDARY": "Birincil rengi ikincil renk ile değiştir",
-    "REPLACE_PRIMARY_BY_SECONDARY_DESCRIPTIVE": "Birincil rengi ikincil renk ile değiştir",
-    "OPEN_PALETTE_BROWSER": "Palet tarayıcısını aç",
-    "OVERWRITE_PALETTE_CONSENT": "'{0}' paleti zaten mevcut, üzerine yazmak istiyor musunuz?",
-    "PALETTE_EXISTS": "Palet zaten mevcut",
-    "REPLACE_PALETTE_CONSENT": "Geçerli palet seçilenle değiştirilsin mi?",
-    "REPLACE_PALETTE": "Geçerli paleti değiştir",
-    "SELECT_COLOR_1": "Renk 1'i seç",
-    "SELECT_COLOR_2": "Renk 2'yi seç",
-    "SELECT_COLOR_3": "Renk 3'ü seç",
-    "SELECT_COLOR_4": "Renk 4'ü seç",
-    "SELECT_COLOR_5": "Renk 5'i seç",
-    "SELECT_COLOR_6": "Renk 6'yı seç",
-    "SELECT_COLOR_7": "Renk 7'yi seç",
-    "SELECT_COLOR_8": "Renk 8'i seç",
-    "SELECT_COLOR_9": "Renk 9'u seç",
-    "SELECT_COLOR_10": "Renk 10'u seç",
-    "SELECT_TOOL": "{0} Aracını Seç",
-    "SELECT_COLOR_1_DESCRIPTIVE": "Paletin ilk rengini seçin",
-    "SELECT_COLOR_2_DESCRIPTIVE": "Paletin ikinci rengini seçin",
-    "SELECT_COLOR_3_DESCRIPTIVE": "Paletin üçüncü rengini seçin",
-    "SELECT_COLOR_4_DESCRIPTIVE": "Paletin dördüncü rengini seçin",
-    "SELECT_COLOR_5_DESCRIPTIVE": "Paletin beşinci rengini seçin",
-    "SELECT_COLOR_6_DESCRIPTIVE": "Paletin altıncı rengini seçin",
-    "SELECT_COLOR_7_DESCRIPTIVE": "Paletin yedinci rengini seçin",
-    "SELECT_COLOR_8_DESCRIPTIVE": "Paletin sekizinci rengini seçin",
-    "SELECT_COLOR_9_DESCRIPTIVE": "Paletin dokuzuncu rengini seçin",
-    "SELECT_COLOR_10_DESCRIPTIVE": "Paletin onuncu rengini seçin",
-    "SWAP_COLORS": "Renkleri Değiştir",
-    "SWAP_COLORS_DESCRIPTIVE": "Birincil ve ikincil renkleri değiştir",
-    "SEARCH": "Ara",
-    "COMMAND_SEARCH": "Komut arama",
-    "OPEN_COMMAND_SEARCH": "Komut arama penceresini aç",
-    "SELECT": "Seç",
-    "DESELECT": "Seçimi Kaldır",
-    "INVERT": "Tersine Çevir",
-    "SELECTION": "Seçim",
-    "SELECT_ALL": "Hepsini Seç",
-    "SELECT_ALL_DESCRIPTIVE": "Hepsini seç",
-    "CLEAR_SELECTION": "Seçimi Temizle",
-    "INVERT_SELECTION": "Seçimi Tersine Çevir",
-    "INVERT_SELECTION_DESCRIPTIVE": "Seçimi tersine çevir",
-    "TRANSFORM_SELECTED_AREA": "Seçili alanı dönüştür",
-    "NUDGE_SELECTED_LEFT": "Seçili nesneyi sola kaydır",
-    "NUDGE_SELECTED_RIGHT": "Seçili nesneyi sağa kaydır",
-    "NUDGE_SELECTED_UP": "Seçili nesneyi yukarı kaydır",
-    "NUDGE_SELECTED_DOWN": "Seçili nesneyi aşağı kaydır",
-    "MASK_FROM_SELECTION": "Yeni maske oluştur",
-    "MASK_FROM_SELECTION_DESCRIPTIVE": "Seçimi yeni maskeye dönüştür",
-    "ADD_SELECTION_TO_MASK": "Seçimi maskeye ekle",
-    "SUBTRACT_SELECTION_FROM_MASK": "Seçimi maskeye çıkar",
-    "INTERSECT_SELECTION_MASK": "Seçimi maskeyle kesiştir",
-    "SELECTION_TO_MASK": "Seçimi maskeye dönüştür",
-    "TO_NEW_MASK": "yeni maske için",
-    "ADD_TO_MASK": "maskeye ekle",
-    "SUBTRACT_FROM_MASK": "maskeden çıkar",
-    "INTERSECT_WITH_MASK": "maskelerle kesiştir",
-    "STYLUS": "Stylus",
-    "TOGGLE_PEN_MODE": "Kalem modunu aç/kapat",
-    "UNDO": "Geri Al",
-    "UNDO_DESCRIPTIVE": "Son işlemi geri al",
-    "REDO": "Yinele",
-    "REDO_DESCRIPTIVE": "Son işlemi yeniden yap",
-    "WINDOWS": "Windows",
-    "TOGGLE_GRIDLINES": "Kılavuz çizgilerini aç/kapat",
-    "ZOOM_IN": "Yakınlaştır",
-    "ZOOM_OUT": "Uzaklaştır",
-    "NEW_WINDOW_FOR_IMG": "Mevcut resim için yeni pencere aç",
-    "CENTER_ACTIVE_VIEWPORT": "Etkin görünümü ortala",
-    "FLIP_VIEWPORT_HORIZONTALLY": "Görünümü yatay olarak çevir",
-    "FLIP_VIEWPORT_VERTICALLY": "Görünümü dikey olarak çevir",
-    "SETTINGS": "Ayarlar",
-    "OPEN_SETTINGS": "Ayarları aç",
-    "OPEN_SETTINGS_DESCRIPTIVE": "Ayarlar penceresini aç",
-    "OPEN_STARTUP_WINDOW": "Başlangıç penceresini aç",
-    "OPEN_SHORTCUT_WINDOW": "Kısayol penceresini aç",
-    "OPEN_ABOUT_WINDOW": "Hakkında penceresini aç",
-    "OPEN_NAVIGATION_WINDOW": "Gezinme penceresini aç",
-    "ERROR": "Hata",
-    "INTERNAL_ERROR": "Dahili hata",
-    "ERROR_SAVE_LOCATION": "Dosyayı belirtilen konuma kaydedemedim",
-    "ERROR_WHILE_SAVING": "Kaydetme sırasında dahili bir hata oluştu. Lütfen tekrar deneyin.",
-    "UNKNOWN_ERROR_SAVING": "Kaydetme sırasında bir hata oluştu.",
-    "FAILED_ASSOCIATE_LOSPEC": "Lospec Palet protokolü ilişkilendirilemedi.",
-    "REDDIT": "Reddit",
-    "GITHUB": "GitHub",
-    "YOUTUBE": "YouTube",
-    "DONATE": "Bağış Yap",
-    "YES": "Evet",
-    "NO": "Hayır",
-    "CANCEL": "İptal",
-    "UNNAMED": "İsimsiz",
-    "OPEN_COMMAND_DEBUG_WINDOW": "Komut hata ayıklama penceresini aç",
-    "DELETE": "Sil",
-    "USER_PREFS": "Kullanıcı tercihleri (Gezinti)",
-    "SHORTCUT_FILE": "Kısayol dosyası (Gezinti)",
-    "EDITOR_DATA": "Düzenleyici verileri (Yerel)",
-    "MOVE_VIEWPORT_TOOLTIP": "Görünümü taşı. ({0})",
-    "MOVE_VIEWPORT_ACTION_DISPLAY": "Görünümü kaydırmak için tıklayın ve sürükleyin",
-    "MOVE_TOOL_TOOLTIP": "Seçili pikselleri taşır ({0}). Tüm katmanları taşımak için Ctrl tuşuna basılı tutun.",
-    "MOVE_TOOL_ACTION_DISPLAY": "Seçili pikselleri taşımak için fareyi basılı tutun. Tüm katmanları taşımak için Ctrl tuşuna basılı tutun.",
-    "PEN_TOOL_TOOLTIP": "Kalem. ({0})",
-    "PEN_TOOL_ACTION_DISPLAY": "Çizmek için tıklayın ve sürükleyin.",
-    "PIXEL_PERFECT_SETTING": "Mükemmel piksel",
-    "RECTANGLE_TOOL_TOOLTIP": "Tuval üzerinde dikdörtgen çizer ({0}). Kare çizmek için Shift tuşunu basılı tutun.",
-    "RECTANGLE_TOOL_ACTION_DISPLAY_DEFAULT": "Dikdörtgen çizmek için tıklayın ve sürükleyin. Kare çizmek için Shift tuşunu basılı tutun.",
-    "RECTANGLE_TOOL_ACTION_DISPLAY_SHIFT": "Kare çizmek için tıklayın ve sürükleyin.",
-    "KEEP_ORIGINAL_IMAGE_SETTING": "Orijinal resmi koru",
-    "ROTATE_VIEWPORT_TOOLTIP": "Görünümü döndür. ({0})",
-    "ROTATE_VIEWPORT_ACTION_DISPLAY": "Görünümü döndürmek için tıklayın ve sürükleyin",
-    "SELECT_TOOL_TOOLTIP": "Alan seçer. ({0})",
-    "SELECT_TOOL_ACTION_DISPLAY_DEFAULT": "Bir alan seçmek için tıklayın ve sürükleyin. Mevcut seçime eklemek için Shift tuşunu basılı tutun. Çıkarmak için Ctrl tuşuna basılı tutun.",
-    "SELECT_TOOL_ACTION_DISPLAY_SHIFT": "Mevcut seçime eklemek için tıklayın ve sürükleyin.",
-    "SELECT_TOOL_ACTION_DISPLAY_CTRL": "Mevcut seçimden çıkarmak için tıklayın ve sürükleyin.",
-    "ZOOM_TOOL_TOOLTIP": "Görünümü yakınlaştırır ({0}). Yakınlaştırmak için tıklayın, alt tuşunu basılı tutun ve tıklayınarak uzaklaştırın.",
-    "ZOOM_TOOL_ACTION_DISPLAY_DEFAULT": "Yakınlaştırmak için tıklayın ve sürükleyin. Yakınlaştırmak için Ctrl tuşunu basılı tutun ve tıklayınarak uzaklaştırın.",
-    "ZOOM_TOOL_ACTION_DISPLAY_CTRL": "Yakınlaştırmak için tıklayın ve sürükleyin. Uzaklaştırmak için Ctrl tuşunu bırakın ve tıklayın.",
-    "BRIGHTNESS_TOOL_TOOLTIP": "Pikselleri daha parlak veya daha koyu hale getirir ({0}). Pikselleri daha koyu yapmak için Ctrl tuşunu basılı tutun.",
-    "BRIGHTNESS_TOOL_ACTION_DISPLAY_DEFAULT": "Pikselleri daha parlak hale getirmek için üzerlerine çizin. Pikselleri daha koyu yapmak için Ctrl tuşunu basılı tutun.",
-    "BRIGHTNESS_TOOL_ACTION_DISPLAY_CTRL": "Pikselleri daha koyu yapmak için üzerlerine çizin. Daha parlak hale getirmek için Ctrl tuşunu bırakın.",
-    "COLOR_PICKER_TOOLTIP": "Tuvalden birincil rengi seçer. ({0})",
-    "COLOR_PICKER_ACTION_DISPLAY_DEFAULT": "Renkleri seçmek için tıklayın. Tuvali gizlemek için Ctrl tuşunu basılı tutun. Referans katmanı gizlemek için Shift tuşunu basılı tutun",
-    "ELLIPSE_TOOL_TOOLTIP": "Tuval üzerinde bir elips çizer ({0}). Bir daire çizmek için Shift tuşunu basılı tutun.",
-    "ELLIPSE_TOOL_ACTION_DISPLAY_DEFAULT": "Bir elips çizmek için tıklayın ve sürükleyin. Bir daire çizmek için Shift tuşunu basılı tutun.",
-    "ELLIPSE_TOOL_ACTION_DISPLAY_SHIFT": "Bir daire çizmek için tıklayın ve sürükleyin.",
-    "ERASER_TOOL_TOOLTIP": "Piksellerden rengi siler. ({0})",
-    "ERASER_TOOL_ACTION_DISPLAY": "Silmek için tıklayın ve sürükleyin.",
-    "FLOOD_FILL_TOOL_TOOLTIP": "Alanı renkle doldurur. ({0})",
-    "FLOOD_FILL_TOOL_ACTION_DISPLAY_DEFAULT": "Doldurmak için bir alana basın. Tüm katmanları dikkate almak için Ctrl tuşunu basılı tutun.",
-    "FLOOD_FILL_TOOL_ACTION_DISPLAY_CTRL": "Doldurmak için bir alana basın. Yalnızca geçerli katmanları dikkate almak için Ctrl tuşunu bırakın.",
-    "LASSO_TOOL_TOOLTIP": "Lasso. ({0})",
-    "LASSO_TOOL_ACTION_DISPLAY_DEFAULT": "Lasso içindeki pikselleri seçmek için tıklayın ve sürükleyin. Mevcut seçime eklemek için Shift tuşunu basılı tutun. Çıkarmak için Ctrl tuşunu basılı tutun.",
-    "LASSO_TOOL_ACTION_DISPLAY_SHIFT": "Lasso içindeki pikselleri seçmek için tıklayın ve sürükleyin.",
-    "LASSO_TOOL_ACTION_DISPLAY_CTRL": "Lasso içindeki pikselleri mevcut seçimden çıkarmak için tıklayın ve sürükleyin.",
-    "LINE_TOOL_TOOLTIP": "Tuval üzerinde çizgi çizer ({0}). Yakalama etkinleştirmek için Shift tuşunu basılı tutun.",
-    "LINE_TOOL_ACTION_DISPLAY_DEFAULT": "Bir çizgi çizmek için tıklayın ve sürükleyin. Yakalamayı etkinleştirmek için Shift tuşunu basılı tutun.",
-    "LINE_TOOL_ACTION_DISPLAY_SHIFT": "Yakalama etkinleştirilmiş bir çizgi çizmek için tıklayın ve sürükleyin.",
-    "MAGIC_WAND_TOOL_TOOLTIP": "Sihirli Değnek ({0}). Seçimi doldurur",
-    "MAGIC_WAND_ACTION_DISPLAY": "Seçimi doldurmak için tıklayın.",
-    "PEN_TOOL": "Kalem",
-    "BRIGHTNESS_TOOL": "Parlaklık",
-    "COLOR_PICKER_TOOL": "Renk Seçici",
-    "ELLIPSE_TOOL": "Elips",
-    "ERASER_TOOL": "Silgi",
-    "FLOOD_FILL_TOOL": "Doldurma",
-    "LASSO_TOOL": "Lasso",
-    "LINE_TOOL": "Çizgi",
-    "MAGIC_WAND_TOOL": "Sihirli Değnek",
-    "MOVE_TOOL": "Taşı",
-    "MOVE_VIEWPORT_TOOL": "Görünümü Taşı",
-    "RECTANGLE_TOOL": "Dikdörtgen",
-    "ROTATE_VIEWPORT_TOOL": "Görünümü Döndür",
-    "SELECT_TOOL_NAME": "Seçim",
-    "ZOOM_TOOL": "Yakınlaştırma",
-    "SHAPE_LABEL": "Şekil",
-    "MODE_LABEL": "Mod",
-    "SCOPE_LABEL": "Kapsam",
-    "FILL_SHAPE_LABEL": "Şekli Doldur",
-    "FILL_COLOR_LABEL": "Renk Doldur",
-    "TOOL_SIZE_LABEL": "Araç Boyutu",
-    "STRENGTH_LABEL": "Güç",
-    "NEW": "Yeni",
-    "ADD": "Ekle",
-    "SUBTRACT": "Çıkar",
-    "INTERSECT": "Kesişim",
-    "RECTANGLE": "Dikdörtgen",
-    "CIRCLE": "Daire",
-    "ABOUT": "Hakkında",
-    "MINIMIZE": "Simge Durumuna Küçült",
-    "RESTORE": "Geri Al",
-    "MAXIMIZE": "Büyüt",
-    "CLOSE": "Kapat",
-    "EXPORT_SIZE_HINT": "Görüntüyü paylaşmak isterseniz, en iyi netlik için {0}% önerilir",
-    "CREATE": "Oluştur",
-    "BASE_LAYER_NAME": "Ana katman",
-    "ENABLE_MASK": "Maskeleri Etkinleştir",
-    "SELECTED_AREA_EMPTY": "Seçilen alan boş",
-    "NOTHING_TO_COPY": "Kopyalanacak bir şey yok",
-    "REFERENCE_LAYER_PATH": "Referans katmanı yolu",
-    "FLIP": "Çevir",
-    "ROTATION": "Döndürme",
-    "ROT_IMG_90_D": "Görüntüyü 90° Döndür",
-    "ROT_IMG_180_D": "Görüntüyü 180° Döndür",
-    "ROT_IMG_-90_D": "Görüntüyü -90° Döndür",
-    "ROT_LAYERS_90_D": "Seçili Katmanları 90° Döndür",
-    "ROT_LAYERS_180_D": "Seçili Katmanları 180° Döndür",
-    "ROT_LAYERS_-90_D": "Seçili Katmanları -90° Döndür",
-    "UNNAMED_PALETTE": "Adsız Palet",
-    "CLICK_SELECT_PRIMARY": "Ana rengi seçmek için tıklayın.",
-    "PEN_MODE": "Kalem modu",
-    "VIEW": "Görünüm",
-    "HORIZONTAL_LINE_SYMMETRY": "Yatay çizgi simetrisi",
-    "VERTICAL_LINE_SYMMETRY": "Dikey çizgi simetrisi",
-    "COLOR_PICKER_TITLE": "Renk Seçici",
-    "COLOR_SLIDERS_TITLE": "Renk Kaydırıcıları",
-    "PALETTE_TITLE": "Palet",
-    "SWATCHES_TITLE": "Renk Örnekleri",
-    "LAYERS_TITLE": "Katmanlar",
-    "NAVIGATION_TITLE": "Gezinme",
-    "NORMAL_BLEND_MODE": "Normal",
-    "DARKEN_BLEND_MODE": "Karartma",
-    "MULTIPLY_BLEND_MODE": "Çarpma",
-    "COLOR_BURN_BLEND_MODE": "Renk Yakma",
-    "LIGHTEN_BLEND_MODE": "Aydınlatma",
-    "SCREEN_BLEND_MODE": "Ekran",
-    "COLOR_DODGE_BLEND_MODE": "Renk Geçişi",
-    "OVERLAY_BLEND_MODE": "Üzerine Yerleştirme",
-    "SOFT_LIGHT_BLEND_MODE": "Yumuşak Işık",
-    "HARD_LIGHT_BLEND_MODE": "Sert Işık",
-    "DIFFERENCE_BLEND_MODE": "Fark",
-    "EXCLUSION_BLEND_MODE": "Dışlama",
-    "HUE_BLEND_MODE": "Ton",
-    "SATURATION_BLEND_MODE": "Doygunluk",
-    "LUMINOSITY_BLEND_MODE": "Parlaklık",
-    "COLOR_BLEND_MODE": "Renk",
-    "NOT_SUPPORTED_BLEND_MODE": "Desteklenmeyen",
-    "RESTART": "Yeniden Başlat",
-    "SORT_BY": "Sırala",
-    "NAME": "İsim",
-    "COLORS": "Renkler",
-    "DEFAULT": "Varsayılan",
-    "ALPHABETICAL": "Alfabetik",
-    "COLOR_COUNT": "Renk sayısı",
-    "ANY": "Herhangi biri",
-    "MAX": "Maksimum",
-    "MIN": "Minimum",
-    "EXACT": "Tam",
-    "ASCENDING": "Artan",
-    "DESCENDING": "Azalan",
-    "NAME_IS_TOO_LONG": "İsim çok uzun",
-    "STOP_IT_TEXT1": "Yeter. Dosya isimlerinizi düzgünleştirin.",
-    "STOP_IT_TEXT2": "Bu isimleri kopyalamayı bırakabilir misiniz?",
-    "REPLACER_TOOLTIP": "Palet renginin üzerine sağ tıklayın ve 'Değiştir' seçeneğini seçin veya buraya bırakın.",
-    "CLICK_TO_CHOOSE_COLOR": "Renk seçmek için tıklayın",
-    "REPLACE_COLOR": "Rengi değiştir",
-    "PALETTE_COLOR_TOOLTIP": "Ana renk olarak seçmek için tıklayın. Başka bir palet renginin üzerine sürükleyip bırakarak değiştirin.",
-    "ADD_FROM_SWATCHES": "Renk örneklerinden ekle",
-    "ADD_COLOR_TO_PALETTE": "Palet'e renk ekle",
-    "USE_IN_CURRENT_IMAGE": "Geçerli görüntüde kullan",
-    "ADD_TO_FAVORITES": "Favorilere ekle",
-    "BROWSE_PALETTES": "Paletlere göz at",
-    "LOAD_PALETTE": "Paleti yükle",
-    "SAVE_PALETTE": "Paleti kaydet",
-    "FAVORITES": "Favoriler",
-    "ADD_FROM_CURRENT_PALETTE": "Mevcut paletten ekle",
-    "OPEN_PALETTES_DIR_TOOLTIP": "Paletler dizinini gezginde aç",
-    "BROWSE_ON_LOSPEC_TOOLTIP": "Lospec'te paletlere göz at",
-    "IMPORT_FROM_FILE_TOOLTIP": "Dosyadan içe aktar",
-    "TOP_LEFT": "Sol üst",
-    "TOP_CENTER": "Orta üst",
-    "TOP_RIGHT": "Sağ üst",
-    "MIDDLE_LEFT": "Sol orta",
-    "MIDDLE_CENTER": "Orta",
-    "MIDDLE_RIGHT": "Sağ orta",
-    "BOTTOM_LEFT": "Sol alt",
-    "BOTTOM_CENTER": "Orta alt",
-    "BOTTOM_RIGHT": "Sağ alt",
-    "CLIP_TO_BELOW": "Alt katmana kırp",
-    "MOVE_UPWARDS": "Yukarı taşı",
-    "MOVE_DOWNWARDS": "Aşağı taşı",
-    "MERGE_SELECTED": "Seçilenleri birleştir",
-    "LOCK_TRANSPARENCY": "Şeffaflığı kilitle",
-    "COULD_NOT_LOAD_PALETTE": "Palet alınamadı",
-    "NO_PALETTES_FOUND": "Palet bulunamadı.",
-    "LOSPEC_LINK_TEXT": "İşte bazılarına buradan ulaşabilirsiniz: lospec.com/palette-list",
-    "PALETTE_BROWSER": "Palet Tarayıcısı",
-    "DELETE_PALETTE_CONFIRMATION": "Bu paleti silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.",
-    "SHORTCUTS_IMPORTED": "{0} kaynaklı kısayollar başarıyla içe aktarıldı.",
-    "SHORTCUT_PROVIDER_DETECTED": "{0} yüklendiği tespit edildi. Kısayollarını içe aktarmak istiyor musunuz?",
-    "IMPORT_FROM_INSTALLATION": "Yüklemeyi içe aktar",
-    "IMPORT_INSTALLATION_OPTION1": "Yüklemeyi içe aktar",
-    "IMPORT_INSTALLATION_OPTION2": "Varsayılanları kullan",
-    "IMPORT_FROM_TEMPLATE": "Şablondan içe aktar",
-    "SHORTCUTS_IMPORTED_SUCCESS": "Kısayollar başarıyla içe aktarıldı.",
-    "WARNING_RESET_SHORTCUTS_DEFAULT": "Tüm kısayolları varsayılan değerlerine sıfırlamak istediğinizden emin misiniz?",
-    "SUCCESS": "Başarılı",
-    "WARNING": "Uyarı",
-    "ERROR_IMPORTING_IMAGE": "Resim içe aktarılırken bir hata oluştu.",
-    "SHORTCUTS_CORRUPTED_TITLE": "Bozuk kısayollar dosyası",
-    "SHORTCUTS_CORRUPTED": "Kısayollar dosyası bozuldu, varsayılanlara sıfırlanıyor.",
-    "FAILED_DOWNLOAD_PALETTE": "Palet indirilemedi",
-    "FILE_INCORRECT_FORMAT": "Dosya doğru bir formatta değil",
-    "INVALID_FILE": "Geçersiz dosya",
-    "SHORTCUTS_FILE_INCORRECT_FORMAT": "Kısayollar dosyası doğru bir formatta değil",
-    "UNSUPPORTED_FILE_FORMAT": "Bu dosya formatı desteklenmiyor",
-    "ALREADY_ASSIGNED": "Zaten atanmış",
-    "REPLACE": "Değiştir",
-    "SWAP": "Değiştir",
-    "SHORTCUT_ALREADY_ASSIGNED_SWAP": "Bu kısayol zaten '{0}' için atanmış\nMevcut kısayolu değiştirmek veya ikisini değiştirmek istiyor musunuz?",
-    "SHORTCUT_ALREADY_ASSIGNED_OVERWRITE": "Bu kısayol zaten '{0}' için atanmış\nMevcut kısayolu değiştirmek istiyor musunuz?",
-    "UNSAVED_CHANGES": "Kaydedilmemiş değişiklikler",
-    "DOCUMENT_MODIFIED_SAVE": "Belge değiştirildi. Değişiklikleri kaydetmek istiyor musunuz?",
-    "SESSION_UNSAVED_DATA": "{0} kaydedilmemiş veri içeriyor. Emin misiniz?",
-    "PROJECT_MAINTAINERS": "Proje Bakımcıları",
-    "OTHER_AWESOME_CONTRIBUTORS": "Ve diğer harika katkıda bulunanlar",
-    "HELP": "Yardım",
-    "STOP_IT_TEXT3": "Hayır gerçekten, yeter.",
-    "STOP_IT_TEXT4": "Daha iyi yapacak başka bir şeyiniz yok mu?",
-    "LINEAR_DODGE_BLEND_MODE": "Lineer dodge (Ekleme)",
-    "PRESS_ANY_KEY": "Herhangi bir tuşa basın",
-    "NONE_SHORTCUT": "Hiçbiri",
-    "REFERENCE": "Referans",
-    "PUT_REFERENCE_LAYER_ABOVE": "Referans katmanını üste yerleştir",
-    "PUT_REFERENCE_LAYER_BELOW": "Referans katmanını alta yerleştir",
-    "TOGGLE_VERTICAL_SYMMETRY": "Dikey simetriyi aç/kapat",
-    "TOGGLE_HORIZONTAL_SYMMETRY": "Yatay simetriyi aç/kapat",
-    "RESET_VIEWPORT": "Görünümü sıfırla",
-    "VIEWPORT_SETTINGS": "Görünüm ayarları",
-    "MOVE_TOOL_ACTION_DISPLAY_TRANSFORMING": "Tıklanıp basılı tutarak seçili katmanlardaki pikselleri taşımak için fareyi kullanın.",
-    "MOVE_TOOL_ACTION_DISPLAY_CTRL": "Tüm katmanları taşımak için fareyi basılı tutun.",
-    "CTRL_KEY": "Ctrl",
-    "SHIFT_KEY": "Shift",
-    "ALT_KEY": "Alt",
-    "RENAME": "Yeniden adlandır",
-    "PIXEL_UNIT": "px",
-    "OPEN_LOCALIZATION_DEBUG_WINDOW": "Yerelleştirme Hata Ayıklama Penceresini Aç",
-    "FORCE_OTHER_FLOW_DIRECTION": "Diğer akış yönünü zorla",
-    "API_KEY": "API Anahtarı",
-    "LOCALIZATION_VIEW_TYPE": "Yerelleştirme Görünüm Türü",
-    "LOAD_LANGUAGE_FROM_FILE": "Dili dosyadan yükle",
-    "LOG_IN": "Giriş yap",
-    "SYNC": "Senkronize Et",
-    "NOT_LOGGED_IN": "Giriş Yapılmadı",
-    "POE_EDITOR_ERROR": "POEditor Hatası: {0} {1}",
-    "HTTP_ERROR_MESSAGE": "HTTP Hatası: {0} {1}",
-    "LOGGED_IN": "Giriş Yapıldı",
-    "SYNCED_SUCCESSFULLY": "Başarıyla Senkronize Edildi",
-    "EXCEPTION_ERROR": "Hata: {0}",
-    "DROP_PALETTE": "Paleti Buraya Bırak",
-    "SECURITY_ERROR": "Güvenlik Hatası",
-    "SECURITY_ERROR_MSG": "Belirtilen konuma yazma izni yok.",
-    "IO_ERROR": "G/Ç Hatası",
-    "IO_ERROR_MSG": "Disk'e yazarken hata oluştu.",
-    "FAILED_ASSOCIATE_PIXI": ".pixi dosyası PixiEditor ile ilişkilendirilemedi.",
-    "COULD_NOT_SAVE_PALETTE": "Palet kaydedilirken bir hata oluştu.",
-    "NO_COLORS_TO_SAVE": "Kaydedilecek renk bulunmuyor.",
-    "ALL_LAYERS": "Tüm Katmanlar",
-    "SINGLE_LAYER": "Tek Katman",
-    "CHOOSE": "Seç",
-    "REMOVE": "Kaldır",
-    "FILE_FORMAT_NOT_ASEPRITE_KEYS": "Dosya bir \".aseprite-keys\" dosyası değil",
-    "FILE_HAS_INVALID_SHORTCUT": "Dosya geçersiz bir kısayol içeriyor",
-    "FILE_EXTENSION_NOT_SUPPORTED": "Dosya türü '{0}' desteklenmiyor",
-    "ERROR_READING_FILE": "Dosya okunurken hata oluştu",
-    "DISCARD_PALETTE": "Paleti At",
-    "DISCARD_PALETTE_CONFIRMATION": "Mevcut paleti atmak istediğinizden emin misiniz? Bu işlem geri alınamaz.",
-    "IMPORT_AS_NEW_LAYER": "Yeni katman olarak içe aktar",
-    "PASTE_AS_PRIMARY_COLOR": "Birincil renk olarak yapıştır",
-    "IMPORT_AS_NEW_FILE": "Yeni dosya olarak içe aktar",
-    "IMPORT_PALETTE_FILE": "Palet dosyasını içe aktar",
-    "IMPORT_MULTIPLE_PALETTE_COLORS": "Renkleri palet içine aktar",
-    "IMPORT_SINGLE_PALETTE_COLOR": "Renkleri palet içine aktar",
-    "IMPORT_AS_REFERENCE_LAYER": "Referans katmanı olarak içe aktar",
-    "NAVIGATOR_PICK_ACTION_DISPLAY": "Renk seçmek için sağ tıklayın, Renkleri panoya kopyalamak için Shift tuşuna basılı tutun",
-    "OPEN_FILE_FROM_CLIPBOARD": "Panodan aç",
-    "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "Panodan aç",
-    "OPEN_LOCALIZATION_DATA": "LocalizationData.json dosyasını mı açmak istiyorsunuz?\nGüncellenmiş tarih panoya kopyalandı.\nNot Değişiklikler, yeniden başlatma yapılana kadar uygulanmayacaktır",
-    "DOWNLOADING_LANGUAGE_FAILED": "Dil indirme başarısız oldu.\nAPI Anahtarı aşırı kullanılmış olabilir.",
-    "LOCALIZATION_DATA_NOT_FOUND": "Yerelleştirme veri yolu bulunamadı",
-    "APPLY": "Uygula",
-    "UPDATE_SOURCE": "Kaynağı Güncelle",
-    "COPY_TO_CLIPBOARD": "Panoya Kopyala",
-    "LANGUAGE_FILE_NOT_FOUND": "Dil dosyası bulunamadı.\n'{0}' dosyası aranıyor",
-    "PROJECT_ROOT_NOT_FOUND": "PixiEditor proje kökü bulunamadı.\nPixiEditor.csproj dosyası aranıyor",
-    "LOCALIZATION_FOLDER_NOT_FOUND": "Yerelleştirme klasörü bulunamadı.\n/Data/Localization dizini aranıyor",
-    "SELECT_A_LANGUAGE": "Bir dil seçin",
-    "DONE": "Tamamlandı",
-    "SOURCE_UNSET_OR_MISSING": "Kaynak eksik/belirtilmemiş",
-    "SOURCE_NEWER": "Kaynak daha yeni",
-    "SOURCE_UP_TO_DATE": "Kaynak güncel",
-    "SOURCE_OLDER": "Bulut daha yeni",
-    "COLOR_PICKER_ACTION_DISPLAY_REFERENCE_ONLY": "Referans katmanından renk seçmek için tıklayın.",
-    "COLOR_PICKER_ACTION_DISPLAY_CANVAS_ONLY": "Tuvalden renk seçmek için tıklayın.",
-    "LOCALIZATION_DEBUG_WINDOW_TITLE": "Yerelleştirme Hata Ayıklama Penceresi",
-    "COMMAND_DEBUG_WINDOW_TITLE": "Komut Hata Ayıklama Penceresi",
-    "SHORTCUTS_TITLE": "Kısayollar",
-    "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_PERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Bir kolun üzerine tıklayıp Ctrl tuşunu basılı tutarak kolun serbestçe hareket etmesini sağlayın. Orantılı olarak ölçeklendirmek için Shift tuşunu basılı tutun. Bir yan kolun üzerine tıklayıp Alt tuşunu basılı tutarak kaydırın. Dış kolları sürükleyerek döndürün.",
-    "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Orantılı olarak ölçeklendirmek için Shift tuşunu basılı tutun. Bir yan kolun üzerine tıklayıp Alt tuşunu basılı tutarak kaydırın. Dış kolları sürükleyerek döndürün.",
-    "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Shift tuşunu basılı tutunarak orantılı olarak ölçeklendirin. Dış kolları sürükleyerek döndürün.",
-    "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Shift tuşunu basılı tutarak orantılı olarak ölçeklendirin.",
-    "OPEN_DOCUMENTATION": "Dokümantasyonu aç",
-    "LOCAL_PALETTE_SOURCE_NAME": "Yerel",
-    "ERROR_FORBIDDEN_UNIQUE_NAME": "Uzantı benzersiz adı 'pixieditor' ile başlayamaz.",
-    "ERROR_MISSING_METADATA": "Uzantı metaverisi '{0}' eksik.",
-    "ERROR_NO_CLASS_ENTRY": "Uzantı sınıf girişi '{0}' yolda eksik.",
-    "ERROR_NO_ENTRY_ASSEMBLY": "Uzantı giriş derlemesi '{0}' yolda eksik.",
-    "ERROR_MISSING_ADDITIONAL_CONTENT": "Mevcut yapılandırmanız bu uzantının yüklenmesine izin vermiyor. Belki de sahibi değilsiniz veya yüklü değil. Uzantıyı buradan satın alabilirsiniz '{0}'.",
-    "BUY_SUPPORTER_PACK": "Destekçi Paketi Satın Al",
-    "NEWS": "Haberler",
-    "DISABLE_NEWS_PANEL": "Başlangıç penceresinde Haberler panelini devre dışı bırak",
-    "FAILED_FETCH_NEWS": "Haberleri alırken hata oluştu",
-    "CROP_TO_SELECTION": "Seçime Kırp",
-    "CROP_TO_SELECTION_DESCRIPTIVE": "Resmi seçime kırp",
-    "SHOW_CONTEXT_MENU": "Bağlam Menüsünü Göster",
-    "ERASE": "Sil",
-    "USE_SECONDARY_COLOR": "İkincil rengi kullan",
-    "RIGHT_CLICK_MODE": "Sağ Tıklama Modu",
-    "ADD_PRIMARY_COLOR_TO_PALETTE": "Birincil rengi palete ekle",
-    "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Birincil rengi mevcut palete ekle",
-    "COPY_COLOR": "Rengi Kopyala"
+  "RECENT_FILES": "Son Dosyalar",
+  "OPEN_FILE": "Dosya Aç",
+  "NEW_FILE": "Yeni",
+  "RECENT_EMPTY_TEXT": "Çok fazla boşluk",
+  "LANGUAGE": "Dil",
+  "GENERAL": "Genel",
+  "DISCORD": "Discord",
+  "KEY_BINDINGS": "Tuş Atamaları",
+  "MISC": "Çeşitli",
+  "SHOW_STARTUP_WINDOW": "Başlangıç Ekranını Göster",
+  "SHOW_IMAGE_PREVIEW_TASKBAR": "Görev çubuğunda resim önizlemesini göster",
+  "RECENT_FILE_LENGTH": "Son dosya listesi uzunluğu",
+  "RECENT_FILE_LENGTH_TOOLTIP": "Dosya > Son dosyalar altında gösterilen belge sayısı. Varsayılan: 8",
+  "DEFAULT_NEW_SIZE": "Varsayılan yeni dosya boyutu",
+  "WIDTH": "Genişlik",
+  "HEIGHT": "Yükseklik",
+  "TOOLS": "Araçlar",
+  "ENABLE_SHARED_TOOLBAR": "Paylaşılan araç çubuğunu etkinleştir",
+  "AUTOMATIC_UPDATES": "Otomatik Güncellemeler",
+  "CHECK_FOR_UPDATES": "Başlangıçta güncellemeleri kontrol et",
+  "UPDATE_STREAM": "Güncelleme akışı",
+  "UPDATE_CHANNEL_HELP_TOOLTIP": "Güncelleme kanalları yalnızca bağımsız sürümde (https://pixieditor.net'den indirilen) değiştirilebilir.\nSteam ve Microsoft Store sürümleri güncellemeleri ayrı şekilde yönetir.",
+  "DEBUG": "Hata Ayıklama",
+  "ENABLE_DEBUG_MODE": "Hata Ayıklama modunu etkinleştir",
+  "OPEN_CRASH_REPORTS_DIR": "Çökme raporları dizinini aç",
+  "DISCORD_RICH_PRESENCE": "Zengin Durum",
+  "ENABLED": "Etkin",
+  "SHOW_IMAGE_NAME": "Resim adını göster",
+  "SHOW_IMAGE_SIZE": "Resim boyutunu göster",
+  "SHOW_LAYER_COUNT": "Katman sayısını göster",
+  "FILE": "Dosya",
+  "RECENT": "Son",
+  "OPEN": "Aç",
+  "SAVE_PIXI": "Kaydet (.pixi)",
+  "SAVE_AS_PIXI": "Farklı Kaydet... (.pixi)",
+  "EXPORT_IMG": "Dışa Aktar (.png, .jpg, vb.)",
+  "EDIT": "Düzenle",
+  "EXIT": "Çıkış",
+  "PERCENTAGE": "Yüzde",
+  "ABSOLUTE": "Mutlak",
+  "PRESERVE_ASPECT_RATIO": "En-boy oranını koru",
+  "ANCHOR_POINT": "Bağlama Noktası",
+  "RESIZE_IMAGE": "Resmi Yeniden Boyutlandır",
+  "RESIZE": "Yeniden Boyutlandır",
+  "DOCUMENTATION": "Dokümantasyon",
+  "WEBSITE": "Web Sitesi",
+  "OPEN_WEBSITE": "Web sitesini aç",
+  "REPOSITORY": "Depo",
+  "OPEN_REPOSITORY": "Depoyu aç",
+  "LICENSE": "Lisans",
+  "OPEN_LICENSE": "Lisansı aç",
+  "THIRD_PARTY_LICENSES": "Üçüncü Taraf Lisansları",
+  "OPEN_THIRD_PARTY_LICENSES": "Üçüncü taraf lisanslarını aç",
+  "APPLY_TRANSFORM": "Dönüşümü Uygula",
+  "INCREASE_TOOL_SIZE": "Araç boyutunu artır",
+  "DECREASE_TOOL_SIZE": "Araç boyutunu azalt",
+  "TO_INSTALL_UPDATE": "güncellemeyi yüklemek için {0}",
+  "DOWNLOADING_UPDATE": "Güncelleme indiriliyor...",
+  "UPDATE_READY": "Güncelleme yüklemeye hazır. Şimdi yüklemek istiyor musunuz?",
+  "NEW_UPDATE": "Yeni güncelleme",
+  "COULD_NOT_UPDATE_WITHOUT_ADMIN": "Yönetici ayrıcalıkları olmadan güncelleme yapılamadı. Lütfen PixiEditor'ü yönetici olarak çalıştırın.",
+  "INSUFFICIENT_PERMISSIONS": "Yetersiz izinler",
+  "UPDATE_CHECK_FAILED": "Güncelleme kontrolü başarısız oldu",
+  "COULD_NOT_CHECK_FOR_UPDATES": "Güncelleme mevcut olup olmadığı kontrol edilemedi.",
+  "VERSION": "Sürüm {0}",
+  "OPEN_TEMP_DIR": "Geçici dizini aç",
+  "OPEN_LOCAL_APPDATA_DIR": "Yerel AppData dizinini aç",
+  "OPEN_ROAMING_APPDATA_DIR": "Gezintili AppData dizinini aç",
+  "OPEN_INSTALLATION_DIR": "Kurulum dizinini aç",
+  "DUMP_ALL_COMMANDS": "Tüm komutları dök",
+  "DUMP_ALL_COMMANDS_DESCRIPTIVE": "Tüm komutları bir metin dosyasına dök",
+  "CRASH": "Çökme",
+  "CRASH_APP": "Uygulamayı çökert",
+  "DELETE_USR_PREFS": "Kullanıcı tercihlerini sil (Gezintili AppData)",
+  "DELETE_SHORTCUT_FILE": "Kısayol dosyasını sil (Gezintili AppData)",
+  "DELETE_EDITOR_DATA": "Düzenleyici verilerini sil (Yerel AppData)",
+  "GENERATE_KEY_BINDINGS_TEMPLATE": "Tuş atama şablonu oluştur",
+  "GENERATE_KEY_BINDINGS_TEMPLATE_DESCRIPTIVE": "Tuş atama json şablonu oluştur",
+  "VALIDATE_SHORTCUT_MAP": "Kısayol haritasını doğrula",
+  "VALIDATE_SHORTCUT_MAP_DESCRIPTIVE": "Kısayol haritasını doğrular",
+  "VALIDATION_KEYS_NOTICE_DIALOG": "Boş anahtarlar: {0}\nBilinmeyen Komutlar: {1}",
+  "RESULT": "Sonuç",
+  "CLEAR_RECENT_DOCUMENTS": "Son belgeleri temizle",
+  "CLEAR_RECENTLY_OPENED_DOCUMENTS": "Yeni açılan belgeleri temizle",
+  "OPEN_CMD_DEBUG_WINDOW": "Komut hata ayıklama penceresini aç",
+  "PATH_DOES_NOT_EXIST": "{0} mevcut değil.",
+  "LOCATION_DOES_NOT_EXIST": "Konum mevcut değil.",
+  "FILE_NOT_FOUND": "Dosya bulunamadı.",
+  "ARE_YOU_SURE": "Emin misiniz?",
+  "ARE_YOU_SURE_PATH_FULL_PATH": "{0}'yi silmek istediğinizden emin misiniz?\nBu veri tüm yüklemeler için kaybolacak.\n(Tam Yol: {1})",
+  "FAILED_TO_OPEN_FILE": "Dosya açılamadı",
+  "OLD_FILE_FORMAT": "Eski dosya formatı",
+  "OLD_FILE_FORMAT_DESCRIPTION": "Bu .pixi dosyası eski formatta kullanılmıştır,\n artık desteklenmiyor ve açılamaz.",
+  "NOTHING_FOUND": "Hiçbir şey bulunamadı",
+  "EXPORT": "Dışa Aktar",
+  "EXPORT_IMAGE": "Resmi Dışa Aktar",
+  "IMPORT": "İçe Aktar",
+  "SHORTCUT_TEMPLATES": "Kısayol şablonları",
+  "RESET_ALL": "Hepsini Sıfırla",
+  "LAYER": "Katman",
+  "LAYER_DELETE_SELECTED": "Aktif katmanı/dizini sil",
+  "LAYER_DELETE_SELECTED_DESCRIPTIVE": "Aktif katmanı veya dizini sil",
+  "LAYER_DELETE_ALL_SELECTED": "Tüm seçili katmanları/dizinleri sil",
+  "LAYER_DELETE_ALL_SELECTED_DESCRIPTIVE": "Tüm seçili katmanları ve/veya dizinleri sil",
+  "DELETE_SELECTED_PIXELS": "Seçili pikselleri sil",
+  "NEW_FOLDER": "Yeni klasör",
+  "CREATE_NEW_FOLDER": "Yeni klasör oluştur",
+  "NEW_LAYER": "Yeni katman",
+  "CREATE_NEW_LAYER": "Yeni katman oluştur",
+  "NEW_IMAGE": "Yeni görüntü",
+  "CREATE_NEW_IMAGE": "Yeni görüntü oluştur",
+  "SAVE": "Kaydet",
+  "SAVE_AS": "Farklı Kaydet...",
+  "IMAGE": "Görüntü",
+  "SAVE_IMAGE": "Görüntüyü kaydet",
+  "SAVE_IMAGE_AS": "Yeni olarak görüntüyü kaydet",
+  "DUPLICATE": "Kopyala",
+  "DUPLICATE_SELECTED_LAYER": "Seçili katmanı kopyala",
+  "CREATE_MASK": "Maske oluştur",
+  "DELETE_MASK": "Maskeyi sil",
+  "TOGGLE_MASK": "Maskesi aç/kapat",
+  "APPLY_MASK": "Maskeyi uygula",
+  "TOGGLE_VISIBILITY": "Görünürlüğü aç/kapat",
+  "MOVE_MEMBER_UP": "Üyeyi yukarı taşı",
+  "MOVE_MEMBER_UP_DESCRIPTIVE": "Seçili katmanı veya dizini yukarı taşı",
+  "MOVE_MEMBER_DOWN": "Üyeyi aşağı taşı",
+  "MOVE_MEMBER_DOWN_DESCRIPTIVE": "Seçili katmanı veya dizini aşağı taşı",
+  "MERGE_ALL_SELECTED_LAYERS": "Tüm seçili katmanları birleştir",
+  "MERGE_WITH_ABOVE": "Seçili katmanı üsttekiyle birleştir",
+  "MERGE_WITH_ABOVE_DESCRIPTIVE": "Seçili katmanı üzerindekiyle birleştir",
+  "MERGE_WITH_BELOW": "Seçili katmanı alttakilerle birleştir",
+  "MERGE_WITH_BELOW_DESCRIPTIVE": "Seçili katmanı altındakilerle birleştir",
+  "ADD_REFERENCE_LAYER": "Referans Katman Ekle",
+  "DELETE_REFERENCE_LAYER": "Referans katmanı sil",
+  "TRANSFORM_REFERENCE_LAYER": "Referans katmanını dönüştür",
+  "TOGGLE_REFERENCE_LAYER_POS": "Referans katmanının konumunu değiştir",
+  "TOGGLE_REFERENCE_LAYER_POS_DESCRIPTIVE": "Referans katmanını en üstte veya en altta arasında değiştir",
+  "RESET_REFERENCE_LAYER_POS": "Referans katmanının konumunu sıfırla",
+  "CLIP_CANVAS": "Kanvası Kırp",
+  "FLIP_IMG_VERTICALLY": "Görüntüyü Dikey Olarak Çevir",
+  "FLIP_IMG_HORIZONTALLY": "Görüntüyü Yatay Olarak Çevir",
+  "FLIP_LAYERS_VERTICALLY": "Seçili Katmanları Dikey Olarak Çevir",
+  "FLIP_LAYERS_HORIZONTALLY": "Seçili Katmanları Yatay Olarak Çevir",
+  "ROT_IMG_90": "Görüntüyü 90 derece döndür",
+  "ROT_IMG_180": "Görüntüyü 180 derece döndür",
+  "ROT_IMG_-90": "Görüntüyü -90 derece döndür",
+  "ROT_LAYERS_90": "Seçili Katmanları 90 derece döndür",
+  "ROT_LAYERS_180": "Seçili Katmanları 180 derece döndür",
+  "ROT_LAYERS_-90": "Seçili Katmanları -90 derece döndür",
+  "TOGGLE_VERT_SYMMETRY_AXIS": "Dikey simetri eksenini aç/kapat",
+  "TOGGLE_HOR_SYMMETRY_AXIS": "Yatay simetri eksenini aç/kapat",
+  "DELETE_PIXELS": "Pikselleri sil",
+  "DELETE_PIXELS_DESCRIPTIVE": "Seçili pikselleri sil",
+  "RESIZE_DOCUMENT": "Belgeyi Yeniden Boyutlandır",
+  "RESIZE_CANVAS": "Kanvası Yeniden Boyutlandır",
+  "CENTER_CONTENT": "İçeriği Ortala",
+  "CUT": "Kes",
+  "CUT_DESCRIPTIVE": "Seçili alanı/katmanları kes",
+  "PASTE": "Yapıştır",
+  "PASTE_DESCRIPTIVE": "Pano içeriğini yapıştır",
+  "PASTE_AS_NEW_LAYER": "Yeni katman olarak yapıştır",
+  "PASTE_AS_NEW_LAYER_DESCRIPTIVE": "Panodan yeni bir katman olarak yapıştır",
+  "PASTE_REFERENCE_LAYER": "Referans katmanını yapıştır",
+  "PASTE_REFERENCE_LAYER_DESCRIPTIVE": "Panodaki içeriği referans katmanı olarak yapıştır",
+  "PASTE_COLOR": "Rengi yapıştır",
+  "PASTE_COLOR_DESCRIPTIVE": "Panodan rengi yapıştır",
+  "PASTE_COLOR_SECONDARY": "İkincil olarak yapıştır",
+  "PASTE_COLOR_SECONDARY_DESCRIPTIVE": "Panodan rengi ikincil renk olarak yapıştır",
+  "CLIPBOARD": "Pano",
+  "COPY": "Kopyala",
+  "COPY_DESCRIPTIVE": "Panoya kopyala",
+  "COPY_COLOR_HEX": "Birincil rengi kopyala (HEX)",
+  "COPY_COLOR_HEX_DESCRIPTIVE": "Birincil rengi HEX kodu olarak kopyala",
+  "COPY_COLOR_RGB": "Birincil rengi kopyala (RGB)",
+  "COPY_COLOR_RGB_DESCRIPTIVE": "Birincil rengi RGB kodu olarak kopyala",
+  "COPY_COLOR_SECONDARY_HEX": "İkincil rengi kopyala (HEX)",
+  "COPY_COLOR_SECONDARY_HEX_DESCRIPTIVE": "İkincil rengi HEX kodu olarak kopyala",
+  "COPY_COLOR_SECONDARY_RGB": "İkincil rengi kopyala (RGB)",
+  "COPY_COLOR_SECONDARY_RGB_DESCRIPTIVE": "İkincil rengi RGB kodu olarak kopyala",
+  "PALETTE_COLORS": "Palet Renkleri",
+  "REPLACE_SECONDARY_BY_PRIMARY": "İkincil rengi birincil renk ile değiştir",
+  "REPLACE_SECONDARY_BY_PRIMARY_DESCRIPTIVE": "İkincil rengi birincil renk ile değiştir",
+  "REPLACE_PRIMARY_BY_SECONDARY": "Birincil rengi ikincil renk ile değiştir",
+  "REPLACE_PRIMARY_BY_SECONDARY_DESCRIPTIVE": "Birincil rengi ikincil renk ile değiştir",
+  "OPEN_PALETTE_BROWSER": "Palet tarayıcısını aç",
+  "OVERWRITE_PALETTE_CONSENT": "'{0}' paleti zaten mevcut, üzerine yazmak istiyor musunuz?",
+  "PALETTE_EXISTS": "Palet zaten mevcut",
+  "REPLACE_PALETTE_CONSENT": "Geçerli palet seçilenle değiştirilsin mi?",
+  "REPLACE_PALETTE": "Geçerli paleti değiştir",
+  "SELECT_COLOR_1": "Renk 1'i seç",
+  "SELECT_COLOR_2": "Renk 2'yi seç",
+  "SELECT_COLOR_3": "Renk 3'ü seç",
+  "SELECT_COLOR_4": "Renk 4'ü seç",
+  "SELECT_COLOR_5": "Renk 5'i seç",
+  "SELECT_COLOR_6": "Renk 6'yı seç",
+  "SELECT_COLOR_7": "Renk 7'yi seç",
+  "SELECT_COLOR_8": "Renk 8'i seç",
+  "SELECT_COLOR_9": "Renk 9'u seç",
+  "SELECT_COLOR_10": "Renk 10'u seç",
+  "SELECT_TOOL": "{0} Aracını Seç",
+  "SELECT_COLOR_1_DESCRIPTIVE": "Paletin ilk rengini seçin",
+  "SELECT_COLOR_2_DESCRIPTIVE": "Paletin ikinci rengini seçin",
+  "SELECT_COLOR_3_DESCRIPTIVE": "Paletin üçüncü rengini seçin",
+  "SELECT_COLOR_4_DESCRIPTIVE": "Paletin dördüncü rengini seçin",
+  "SELECT_COLOR_5_DESCRIPTIVE": "Paletin beşinci rengini seçin",
+  "SELECT_COLOR_6_DESCRIPTIVE": "Paletin altıncı rengini seçin",
+  "SELECT_COLOR_7_DESCRIPTIVE": "Paletin yedinci rengini seçin",
+  "SELECT_COLOR_8_DESCRIPTIVE": "Paletin sekizinci rengini seçin",
+  "SELECT_COLOR_9_DESCRIPTIVE": "Paletin dokuzuncu rengini seçin",
+  "SELECT_COLOR_10_DESCRIPTIVE": "Paletin onuncu rengini seçin",
+  "SWAP_COLORS": "Renkleri Değiştir",
+  "SWAP_COLORS_DESCRIPTIVE": "Birincil ve ikincil renkleri değiştir",
+  "SEARCH": "Ara",
+  "COMMAND_SEARCH": "Komut arama",
+  "OPEN_COMMAND_SEARCH": "Komut arama penceresini aç",
+  "SELECT": "Seç",
+  "DESELECT": "Seçimi Kaldır",
+  "INVERT": "Tersine Çevir",
+  "SELECTION": "Seçim",
+  "SELECT_ALL": "Hepsini Seç",
+  "SELECT_ALL_DESCRIPTIVE": "Hepsini seç",
+  "CLEAR_SELECTION": "Seçimi Temizle",
+  "INVERT_SELECTION": "Seçimi Tersine Çevir",
+  "INVERT_SELECTION_DESCRIPTIVE": "Seçimi tersine çevir",
+  "TRANSFORM_SELECTED_AREA": "Seçili alanı dönüştür",
+  "NUDGE_SELECTED_LEFT": "Seçili nesneyi sola kaydır",
+  "NUDGE_SELECTED_RIGHT": "Seçili nesneyi sağa kaydır",
+  "NUDGE_SELECTED_UP": "Seçili nesneyi yukarı kaydır",
+  "NUDGE_SELECTED_DOWN": "Seçili nesneyi aşağı kaydır",
+  "MASK_FROM_SELECTION": "Yeni maske oluştur",
+  "MASK_FROM_SELECTION_DESCRIPTIVE": "Seçimi yeni maskeye dönüştür",
+  "ADD_SELECTION_TO_MASK": "Seçimi maskeye ekle",
+  "SUBTRACT_SELECTION_FROM_MASK": "Seçimi maskeye çıkar",
+  "INTERSECT_SELECTION_MASK": "Seçimi maskeyle kesiştir",
+  "SELECTION_TO_MASK": "Seçimi maskeye dönüştür",
+  "TO_NEW_MASK": "yeni maske için",
+  "ADD_TO_MASK": "maskeye ekle",
+  "SUBTRACT_FROM_MASK": "maskeden çıkar",
+  "INTERSECT_WITH_MASK": "maskelerle kesiştir",
+  "STYLUS": "Stylus",
+  "TOGGLE_PEN_MODE": "Kalem modunu aç/kapat",
+  "UNDO": "Geri Al",
+  "UNDO_DESCRIPTIVE": "Son işlemi geri al",
+  "REDO": "Yinele",
+  "REDO_DESCRIPTIVE": "Son işlemi yeniden yap",
+  "WINDOWS": "Windows",
+  "TOGGLE_GRIDLINES": "Kılavuz çizgilerini aç/kapat",
+  "ZOOM_IN": "Yakınlaştır",
+  "ZOOM_OUT": "Uzaklaştır",
+  "NEW_WINDOW_FOR_IMG": "Mevcut resim için yeni pencere aç",
+  "CENTER_ACTIVE_VIEWPORT": "Etkin görünümü ortala",
+  "FLIP_VIEWPORT_HORIZONTALLY": "Görünümü yatay olarak çevir",
+  "FLIP_VIEWPORT_VERTICALLY": "Görünümü dikey olarak çevir",
+  "SETTINGS": "Ayarlar",
+  "OPEN_SETTINGS": "Ayarları aç",
+  "OPEN_SETTINGS_DESCRIPTIVE": "Ayarlar penceresini aç",
+  "OPEN_STARTUP_WINDOW": "Başlangıç penceresini aç",
+  "OPEN_SHORTCUT_WINDOW": "Kısayol penceresini aç",
+  "OPEN_ABOUT_WINDOW": "Hakkında penceresini aç",
+  "OPEN_NAVIGATION_WINDOW": "Gezinme penceresini aç",
+  "ERROR": "Hata",
+  "INTERNAL_ERROR": "Dahili hata",
+  "ERROR_SAVE_LOCATION": "Dosyayı belirtilen konuma kaydedemedim",
+  "ERROR_WHILE_SAVING": "Kaydetme sırasında dahili bir hata oluştu. Lütfen tekrar deneyin.",
+  "UNKNOWN_ERROR_SAVING": "Kaydetme sırasında bir hata oluştu.",
+  "FAILED_ASSOCIATE_LOSPEC": "Lospec Palet protokolü ilişkilendirilemedi.",
+  "REDDIT": "Reddit",
+  "GITHUB": "GitHub",
+  "YOUTUBE": "YouTube",
+  "DONATE": "Bağış Yap",
+  "YES": "Evet",
+  "NO": "Hayır",
+  "CANCEL": "İptal",
+  "UNNAMED": "İsimsiz",
+  "OPEN_COMMAND_DEBUG_WINDOW": "Komut hata ayıklama penceresini aç",
+  "DELETE": "Sil",
+  "USER_PREFS": "Kullanıcı tercihleri (Gezinti)",
+  "SHORTCUT_FILE": "Kısayol dosyası (Gezinti)",
+  "EDITOR_DATA": "Düzenleyici verileri (Yerel)",
+  "MOVE_VIEWPORT_TOOLTIP": "Görünümü taşı. ({0})",
+  "MOVE_VIEWPORT_ACTION_DISPLAY": "Görünümü kaydırmak için tıklayın ve sürükleyin",
+  "MOVE_TOOL_TOOLTIP": "Seçili pikselleri taşır ({0}). Tüm katmanları taşımak için Ctrl tuşuna basılı tutun.",
+  "MOVE_TOOL_ACTION_DISPLAY": "Seçili pikselleri taşımak için fareyi basılı tutun. Tüm katmanları taşımak için Ctrl tuşuna basılı tutun.",
+  "PEN_TOOL_TOOLTIP": "Kalem. ({0})",
+  "PEN_TOOL_ACTION_DISPLAY": "Çizmek için tıklayın ve sürükleyin.",
+  "PIXEL_PERFECT_SETTING": "Mükemmel piksel",
+  "RECTANGLE_TOOL_TOOLTIP": "Tuval üzerinde dikdörtgen çizer ({0}). Kare çizmek için Shift tuşunu basılı tutun.",
+  "RECTANGLE_TOOL_ACTION_DISPLAY_DEFAULT": "Dikdörtgen çizmek için tıklayın ve sürükleyin. Kare çizmek için Shift tuşunu basılı tutun.",
+  "RECTANGLE_TOOL_ACTION_DISPLAY_SHIFT": "Kare çizmek için tıklayın ve sürükleyin.",
+  "KEEP_ORIGINAL_IMAGE_SETTING": "Orijinal resmi koru",
+  "ROTATE_VIEWPORT_TOOLTIP": "Görünümü döndür. ({0})",
+  "ROTATE_VIEWPORT_ACTION_DISPLAY": "Görünümü döndürmek için tıklayın ve sürükleyin",
+  "SELECT_TOOL_TOOLTIP": "Alan seçer. ({0})",
+  "SELECT_TOOL_ACTION_DISPLAY_DEFAULT": "Bir alan seçmek için tıklayın ve sürükleyin. Mevcut seçime eklemek için Shift tuşunu basılı tutun. Çıkarmak için Ctrl tuşuna basılı tutun.",
+  "SELECT_TOOL_ACTION_DISPLAY_SHIFT": "Mevcut seçime eklemek için tıklayın ve sürükleyin.",
+  "SELECT_TOOL_ACTION_DISPLAY_CTRL": "Mevcut seçimden çıkarmak için tıklayın ve sürükleyin.",
+  "ZOOM_TOOL_TOOLTIP": "Görünümü yakınlaştırır ({0}). Yakınlaştırmak için tıklayın, alt tuşunu basılı tutun ve tıklayınarak uzaklaştırın.",
+  "ZOOM_TOOL_ACTION_DISPLAY_DEFAULT": "Yakınlaştırmak için tıklayın ve sürükleyin. Yakınlaştırmak için Ctrl tuşunu basılı tutun ve tıklayınarak uzaklaştırın.",
+  "ZOOM_TOOL_ACTION_DISPLAY_CTRL": "Yakınlaştırmak için tıklayın ve sürükleyin. Uzaklaştırmak için Ctrl tuşunu bırakın ve tıklayın.",
+  "BRIGHTNESS_TOOL_TOOLTIP": "Pikselleri daha parlak veya daha koyu hale getirir ({0}). Pikselleri daha koyu yapmak için Ctrl tuşunu basılı tutun.",
+  "BRIGHTNESS_TOOL_ACTION_DISPLAY_DEFAULT": "Pikselleri daha parlak hale getirmek için üzerlerine çizin. Pikselleri daha koyu yapmak için Ctrl tuşunu basılı tutun.",
+  "BRIGHTNESS_TOOL_ACTION_DISPLAY_CTRL": "Pikselleri daha koyu yapmak için üzerlerine çizin. Daha parlak hale getirmek için Ctrl tuşunu bırakın.",
+  "COLOR_PICKER_TOOLTIP": "Tuvalden birincil rengi seçer. ({0})",
+  "COLOR_PICKER_ACTION_DISPLAY_DEFAULT": "Renkleri seçmek için tıklayın. Tuvali gizlemek için Ctrl tuşunu basılı tutun. Referans katmanı gizlemek için Shift tuşunu basılı tutun",
+  "ELLIPSE_TOOL_TOOLTIP": "Tuval üzerinde bir elips çizer ({0}). Bir daire çizmek için Shift tuşunu basılı tutun.",
+  "ELLIPSE_TOOL_ACTION_DISPLAY_DEFAULT": "Bir elips çizmek için tıklayın ve sürükleyin. Bir daire çizmek için Shift tuşunu basılı tutun.",
+  "ELLIPSE_TOOL_ACTION_DISPLAY_SHIFT": "Bir daire çizmek için tıklayın ve sürükleyin.",
+  "ERASER_TOOL_TOOLTIP": "Piksellerden rengi siler. ({0})",
+  "ERASER_TOOL_ACTION_DISPLAY": "Silmek için tıklayın ve sürükleyin.",
+  "FLOOD_FILL_TOOL_TOOLTIP": "Alanı renkle doldurur. ({0})",
+  "FLOOD_FILL_TOOL_ACTION_DISPLAY_DEFAULT": "Doldurmak için bir alana basın. Tüm katmanları dikkate almak için Ctrl tuşunu basılı tutun.",
+  "FLOOD_FILL_TOOL_ACTION_DISPLAY_CTRL": "Doldurmak için bir alana basın. Yalnızca geçerli katmanları dikkate almak için Ctrl tuşunu bırakın.",
+  "LASSO_TOOL_TOOLTIP": "Lasso. ({0})",
+  "LASSO_TOOL_ACTION_DISPLAY_DEFAULT": "Lasso içindeki pikselleri seçmek için tıklayın ve sürükleyin. Mevcut seçime eklemek için Shift tuşunu basılı tutun. Çıkarmak için Ctrl tuşunu basılı tutun.",
+  "LASSO_TOOL_ACTION_DISPLAY_SHIFT": "Lasso içindeki pikselleri seçmek için tıklayın ve sürükleyin.",
+  "LASSO_TOOL_ACTION_DISPLAY_CTRL": "Lasso içindeki pikselleri mevcut seçimden çıkarmak için tıklayın ve sürükleyin.",
+  "LINE_TOOL_TOOLTIP": "Tuval üzerinde çizgi çizer ({0}). Yakalama etkinleştirmek için Shift tuşunu basılı tutun.",
+  "LINE_TOOL_ACTION_DISPLAY_DEFAULT": "Bir çizgi çizmek için tıklayın ve sürükleyin. Yakalamayı etkinleştirmek için Shift tuşunu basılı tutun.",
+  "LINE_TOOL_ACTION_DISPLAY_SHIFT": "Yakalama etkinleştirilmiş bir çizgi çizmek için tıklayın ve sürükleyin.",
+  "MAGIC_WAND_TOOL_TOOLTIP": "Sihirli Değnek ({0}). Seçimi doldurur",
+  "MAGIC_WAND_ACTION_DISPLAY": "Seçimi doldurmak için tıklayın.",
+  "PEN_TOOL": "Kalem",
+  "BRIGHTNESS_TOOL": "Parlaklık",
+  "COLOR_PICKER_TOOL": "Renk Seçici",
+  "ELLIPSE_TOOL": "Elips",
+  "ERASER_TOOL": "Silgi",
+  "FLOOD_FILL_TOOL": "Doldurma",
+  "LASSO_TOOL": "Lasso",
+  "LINE_TOOL": "Çizgi",
+  "MAGIC_WAND_TOOL": "Sihirli Değnek",
+  "MOVE_TOOL": "Taşı",
+  "MOVE_VIEWPORT_TOOL": "Görünümü Taşı",
+  "RECTANGLE_TOOL": "Dikdörtgen",
+  "ROTATE_VIEWPORT_TOOL": "Görünümü Döndür",
+  "SELECT_TOOL_NAME": "Seçim",
+  "ZOOM_TOOL": "Yakınlaştırma",
+  "SHAPE_LABEL": "Şekil",
+  "MODE_LABEL": "Mod",
+  "SCOPE_LABEL": "Kapsam",
+  "FILL_SHAPE_LABEL": "Şekli Doldur",
+  "FILL_COLOR_LABEL": "Renk Doldur",
+  "TOOL_SIZE_LABEL": "Araç Boyutu",
+  "STRENGTH_LABEL": "Güç",
+  "NEW": "Yeni",
+  "ADD": "Ekle",
+  "SUBTRACT": "Çıkar",
+  "INTERSECT": "Kesişim",
+  "RECTANGLE": "Dikdörtgen",
+  "CIRCLE": "Daire",
+  "ABOUT": "Hakkında",
+  "MINIMIZE": "Simge Durumuna Küçült",
+  "RESTORE": "Geri Al",
+  "MAXIMIZE": "Büyüt",
+  "CLOSE": "Kapat",
+  "EXPORT_SIZE_HINT": "Görüntüyü paylaşmak isterseniz, en iyi netlik için {0}% önerilir",
+  "CREATE": "Oluştur",
+  "BASE_LAYER_NAME": "Ana katman",
+  "ENABLE_MASK": "Maskeleri Etkinleştir",
+  "SELECTED_AREA_EMPTY": "Seçilen alan boş",
+  "NOTHING_TO_COPY": "Kopyalanacak bir şey yok",
+  "REFERENCE_LAYER_PATH": "Referans katmanı yolu",
+  "FLIP": "Çevir",
+  "ROTATION": "Döndürme",
+  "ROT_IMG_90_D": "Görüntüyü 90° Döndür",
+  "ROT_IMG_180_D": "Görüntüyü 180° Döndür",
+  "ROT_IMG_-90_D": "Görüntüyü -90° Döndür",
+  "ROT_LAYERS_90_D": "Seçili Katmanları 90° Döndür",
+  "ROT_LAYERS_180_D": "Seçili Katmanları 180° Döndür",
+  "ROT_LAYERS_-90_D": "Seçili Katmanları -90° Döndür",
+  "UNNAMED_PALETTE": "Adsız Palet",
+  "CLICK_SELECT_PRIMARY": "Ana rengi seçmek için tıklayın.",
+  "PEN_MODE": "Kalem modu",
+  "VIEW": "Görünüm",
+  "HORIZONTAL_LINE_SYMMETRY": "Yatay çizgi simetrisi",
+  "VERTICAL_LINE_SYMMETRY": "Dikey çizgi simetrisi",
+  "COLOR_PICKER_TITLE": "Renk Seçici",
+  "COLOR_SLIDERS_TITLE": "Renk Kaydırıcıları",
+  "PALETTE_TITLE": "Palet",
+  "SWATCHES_TITLE": "Renk Örnekleri",
+  "LAYERS_TITLE": "Katmanlar",
+  "NAVIGATION_TITLE": "Gezinme",
+  "NORMAL_BLEND_MODE": "Normal",
+  "DARKEN_BLEND_MODE": "Karartma",
+  "MULTIPLY_BLEND_MODE": "Çarpma",
+  "COLOR_BURN_BLEND_MODE": "Renk Yakma",
+  "LIGHTEN_BLEND_MODE": "Aydınlatma",
+  "SCREEN_BLEND_MODE": "Ekran",
+  "COLOR_DODGE_BLEND_MODE": "Renk Geçişi",
+  "OVERLAY_BLEND_MODE": "Üzerine Yerleştirme",
+  "SOFT_LIGHT_BLEND_MODE": "Yumuşak Işık",
+  "HARD_LIGHT_BLEND_MODE": "Sert Işık",
+  "DIFFERENCE_BLEND_MODE": "Fark",
+  "EXCLUSION_BLEND_MODE": "Dışlama",
+  "HUE_BLEND_MODE": "Ton",
+  "SATURATION_BLEND_MODE": "Doygunluk",
+  "LUMINOSITY_BLEND_MODE": "Parlaklık",
+  "COLOR_BLEND_MODE": "Renk",
+  "NOT_SUPPORTED_BLEND_MODE": "Desteklenmeyen",
+  "RESTART": "Yeniden Başlat",
+  "SORT_BY": "Sırala",
+  "NAME": "İsim",
+  "COLORS": "Renkler",
+  "DEFAULT": "Varsayılan",
+  "ALPHABETICAL": "Alfabetik",
+  "COLOR_COUNT": "Renk sayısı",
+  "ANY": "Herhangi biri",
+  "MAX": "Maksimum",
+  "MIN": "Minimum",
+  "EXACT": "Tam",
+  "ASCENDING": "Artan",
+  "DESCENDING": "Azalan",
+  "NAME_IS_TOO_LONG": "İsim çok uzun",
+  "STOP_IT_TEXT1": "Yeter. Dosya isimlerinizi düzgünleştirin.",
+  "STOP_IT_TEXT2": "Bu isimleri kopyalamayı bırakabilir misiniz?",
+  "REPLACER_TOOLTIP": "Palet renginin üzerine sağ tıklayın ve 'Değiştir' seçeneğini seçin veya buraya bırakın.",
+  "CLICK_TO_CHOOSE_COLOR": "Renk seçmek için tıklayın",
+  "REPLACE_COLOR": "Rengi değiştir",
+  "PALETTE_COLOR_TOOLTIP": "Ana renk olarak seçmek için tıklayın. Başka bir palet renginin üzerine sürükleyip bırakarak değiştirin.",
+  "ADD_FROM_SWATCHES": "Renk örneklerinden ekle",
+  "ADD_COLOR_TO_PALETTE": "Palet'e renk ekle",
+  "USE_IN_CURRENT_IMAGE": "Geçerli görüntüde kullan",
+  "ADD_TO_FAVORITES": "Favorilere ekle",
+  "BROWSE_PALETTES": "Paletlere göz at",
+  "LOAD_PALETTE": "Paleti yükle",
+  "SAVE_PALETTE": "Paleti kaydet",
+  "FAVORITES": "Favoriler",
+  "ADD_FROM_CURRENT_PALETTE": "Mevcut paletten ekle",
+  "OPEN_PALETTES_DIR_TOOLTIP": "Paletler dizinini gezginde aç",
+  "BROWSE_ON_LOSPEC_TOOLTIP": "Lospec'te paletlere göz at",
+  "IMPORT_FROM_FILE_TOOLTIP": "Dosyadan içe aktar",
+  "TOP_LEFT": "Sol üst",
+  "TOP_CENTER": "Orta üst",
+  "TOP_RIGHT": "Sağ üst",
+  "MIDDLE_LEFT": "Sol orta",
+  "MIDDLE_CENTER": "Orta",
+  "MIDDLE_RIGHT": "Sağ orta",
+  "BOTTOM_LEFT": "Sol alt",
+  "BOTTOM_CENTER": "Orta alt",
+  "BOTTOM_RIGHT": "Sağ alt",
+  "CLIP_TO_BELOW": "Alt katmana kırp",
+  "MOVE_UPWARDS": "Yukarı taşı",
+  "MOVE_DOWNWARDS": "Aşağı taşı",
+  "MERGE_SELECTED": "Seçilenleri birleştir",
+  "LOCK_TRANSPARENCY": "Şeffaflığı kilitle",
+  "COULD_NOT_LOAD_PALETTE": "Palet alınamadı",
+  "NO_PALETTES_FOUND": "Palet bulunamadı.",
+  "LOSPEC_LINK_TEXT": "İşte bazılarına buradan ulaşabilirsiniz: lospec.com/palette-list",
+  "PALETTE_BROWSER": "Palet Tarayıcısı",
+  "DELETE_PALETTE_CONFIRMATION": "Bu paleti silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.",
+  "SHORTCUTS_IMPORTED": "{0} kaynaklı kısayollar başarıyla içe aktarıldı.",
+  "SHORTCUT_PROVIDER_DETECTED": "{0} yüklendiği tespit edildi. Kısayollarını içe aktarmak istiyor musunuz?",
+  "IMPORT_FROM_INSTALLATION": "Yüklemeyi içe aktar",
+  "IMPORT_INSTALLATION_OPTION1": "Yüklemeyi içe aktar",
+  "IMPORT_INSTALLATION_OPTION2": "Varsayılanları kullan",
+  "IMPORT_FROM_TEMPLATE": "Şablondan içe aktar",
+  "SHORTCUTS_IMPORTED_SUCCESS": "Kısayollar başarıyla içe aktarıldı.",
+  "WARNING_RESET_SHORTCUTS_DEFAULT": "Tüm kısayolları varsayılan değerlerine sıfırlamak istediğinizden emin misiniz?",
+  "SUCCESS": "Başarılı",
+  "WARNING": "Uyarı",
+  "ERROR_IMPORTING_IMAGE": "Resim içe aktarılırken bir hata oluştu.",
+  "SHORTCUTS_CORRUPTED_TITLE": "Bozuk kısayollar dosyası",
+  "SHORTCUTS_CORRUPTED": "Kısayollar dosyası bozuldu, varsayılanlara sıfırlanıyor.",
+  "FAILED_DOWNLOAD_PALETTE": "Palet indirilemedi",
+  "FILE_INCORRECT_FORMAT": "Dosya doğru bir formatta değil",
+  "INVALID_FILE": "Geçersiz dosya",
+  "SHORTCUTS_FILE_INCORRECT_FORMAT": "Kısayollar dosyası doğru bir formatta değil",
+  "UNSUPPORTED_FILE_FORMAT": "Bu dosya formatı desteklenmiyor",
+  "ALREADY_ASSIGNED": "Zaten atanmış",
+  "REPLACE": "Değiştir",
+  "SWAP": "Değiştir",
+  "SHORTCUT_ALREADY_ASSIGNED_SWAP": "Bu kısayol zaten '{0}' için atanmış\nMevcut kısayolu değiştirmek veya ikisini değiştirmek istiyor musunuz?",
+  "SHORTCUT_ALREADY_ASSIGNED_OVERWRITE": "Bu kısayol zaten '{0}' için atanmış\nMevcut kısayolu değiştirmek istiyor musunuz?",
+  "UNSAVED_CHANGES": "Kaydedilmemiş değişiklikler",
+  "DOCUMENT_MODIFIED_SAVE": "Belge değiştirildi. Değişiklikleri kaydetmek istiyor musunuz?",
+  "SESSION_UNSAVED_DATA": "{0} kaydedilmemiş veri içeriyor. Emin misiniz?",
+  "PROJECT_MAINTAINERS": "Proje Bakımcıları",
+  "OTHER_AWESOME_CONTRIBUTORS": "Ve diğer harika katkıda bulunanlar",
+  "HELP": "Yardım",
+  "STOP_IT_TEXT3": "Hayır gerçekten, yeter.",
+  "STOP_IT_TEXT4": "Daha iyi yapacak başka bir şeyiniz yok mu?",
+  "LINEAR_DODGE_BLEND_MODE": "Lineer dodge (Ekleme)",
+  "PRESS_ANY_KEY": "Herhangi bir tuşa basın",
+  "NONE_SHORTCUT": "Hiçbiri",
+  "REFERENCE": "Referans",
+  "PUT_REFERENCE_LAYER_ABOVE": "Referans katmanını üste yerleştir",
+  "PUT_REFERENCE_LAYER_BELOW": "Referans katmanını alta yerleştir",
+  "TOGGLE_VERTICAL_SYMMETRY": "Dikey simetriyi aç/kapat",
+  "TOGGLE_HORIZONTAL_SYMMETRY": "Yatay simetriyi aç/kapat",
+  "RESET_VIEWPORT": "Görünümü sıfırla",
+  "VIEWPORT_SETTINGS": "Görünüm ayarları",
+  "MOVE_TOOL_ACTION_DISPLAY_TRANSFORMING": "Tıklanıp basılı tutarak seçili katmanlardaki pikselleri taşımak için fareyi kullanın.",
+  "MOVE_TOOL_ACTION_DISPLAY_CTRL": "Tüm katmanları taşımak için fareyi basılı tutun.",
+  "CTRL_KEY": "Ctrl",
+  "SHIFT_KEY": "Shift",
+  "ALT_KEY": "Alt",
+  "RENAME": "Yeniden adlandır",
+  "PIXEL_UNIT": "px",
+  "OPEN_LOCALIZATION_DEBUG_WINDOW": "Yerelleştirme Hata Ayıklama Penceresini Aç",
+  "FORCE_OTHER_FLOW_DIRECTION": "Diğer akış yönünü zorla",
+  "API_KEY": "API Anahtarı",
+  "LOCALIZATION_VIEW_TYPE": "Yerelleştirme Görünüm Türü",
+  "LOAD_LANGUAGE_FROM_FILE": "Dili dosyadan yükle",
+  "LOG_IN": "Giriş yap",
+  "SYNC": "Senkronize Et",
+  "NOT_LOGGED_IN": "Giriş Yapılmadı",
+  "POE_EDITOR_ERROR": "POEditor Hatası: {0} {1}",
+  "HTTP_ERROR_MESSAGE": "HTTP Hatası: {0} {1}",
+  "LOGGED_IN": "Giriş Yapıldı",
+  "SYNCED_SUCCESSFULLY": "Başarıyla Senkronize Edildi",
+  "EXCEPTION_ERROR": "Hata: {0}",
+  "DROP_PALETTE": "Paleti Buraya Bırak",
+  "SECURITY_ERROR": "Güvenlik Hatası",
+  "SECURITY_ERROR_MSG": "Belirtilen konuma yazma izni yok.",
+  "IO_ERROR": "G/Ç Hatası",
+  "IO_ERROR_MSG": "Disk'e yazarken hata oluştu.",
+  "FAILED_ASSOCIATE_PIXI": ".pixi dosyası PixiEditor ile ilişkilendirilemedi.",
+  "COULD_NOT_SAVE_PALETTE": "Palet kaydedilirken bir hata oluştu.",
+  "NO_COLORS_TO_SAVE": "Kaydedilecek renk bulunmuyor.",
+  "ALL_LAYERS": "Tüm Katmanlar",
+  "SINGLE_LAYER": "Tek Katman",
+  "CHOOSE": "Seç",
+  "REMOVE": "Kaldır",
+  "FILE_FORMAT_NOT_ASEPRITE_KEYS": "Dosya bir \".aseprite-keys\" dosyası değil",
+  "FILE_HAS_INVALID_SHORTCUT": "Dosya geçersiz bir kısayol içeriyor",
+  "FILE_EXTENSION_NOT_SUPPORTED": "Dosya türü '{0}' desteklenmiyor",
+  "ERROR_READING_FILE": "Dosya okunurken hata oluştu",
+  "DISCARD_PALETTE": "Paleti At",
+  "DISCARD_PALETTE_CONFIRMATION": "Mevcut paleti atmak istediğinizden emin misiniz? Bu işlem geri alınamaz.",
+  "IMPORT_AS_NEW_LAYER": "Yeni katman olarak içe aktar",
+  "PASTE_AS_PRIMARY_COLOR": "Birincil renk olarak yapıştır",
+  "IMPORT_AS_NEW_FILE": "Yeni dosya olarak içe aktar",
+  "IMPORT_PALETTE_FILE": "Palet dosyasını içe aktar",
+  "IMPORT_MULTIPLE_PALETTE_COLORS": "Renkleri palet içine aktar",
+  "IMPORT_SINGLE_PALETTE_COLOR": "Renkleri palet içine aktar",
+  "IMPORT_AS_REFERENCE_LAYER": "Referans katmanı olarak içe aktar",
+  "NAVIGATOR_PICK_ACTION_DISPLAY": "Renk seçmek için sağ tıklayın, Renkleri panoya kopyalamak için Shift tuşuna basılı tutun",
+  "OPEN_FILE_FROM_CLIPBOARD": "Panodan aç",
+  "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "Panodan aç",
+  "OPEN_LOCALIZATION_DATA": "LocalizationData.json dosyasını mı açmak istiyorsunuz?\nGüncellenmiş tarih panoya kopyalandı.\nNot Değişiklikler, yeniden başlatma yapılana kadar uygulanmayacaktır",
+  "DOWNLOADING_LANGUAGE_FAILED": "Dil indirme başarısız oldu.\nAPI Anahtarı aşırı kullanılmış olabilir.",
+  "LOCALIZATION_DATA_NOT_FOUND": "Yerelleştirme veri yolu bulunamadı",
+  "APPLY": "Uygula",
+  "UPDATE_SOURCE": "Kaynağı Güncelle",
+  "COPY_TO_CLIPBOARD": "Panoya Kopyala",
+  "LANGUAGE_FILE_NOT_FOUND": "Dil dosyası bulunamadı.\n'{0}' dosyası aranıyor",
+  "PROJECT_ROOT_NOT_FOUND": "PixiEditor proje kökü bulunamadı.\nPixiEditor.csproj dosyası aranıyor",
+  "LOCALIZATION_FOLDER_NOT_FOUND": "Yerelleştirme klasörü bulunamadı.\n/Data/Localization dizini aranıyor",
+  "SELECT_A_LANGUAGE": "Bir dil seçin",
+  "DONE": "Tamamlandı",
+  "SOURCE_UNSET_OR_MISSING": "Kaynak eksik/belirtilmemiş",
+  "SOURCE_NEWER": "Kaynak daha yeni",
+  "SOURCE_UP_TO_DATE": "Kaynak güncel",
+  "SOURCE_OLDER": "Bulut daha yeni",
+  "COLOR_PICKER_ACTION_DISPLAY_REFERENCE_ONLY": "Referans katmanından renk seçmek için tıklayın.",
+  "COLOR_PICKER_ACTION_DISPLAY_CANVAS_ONLY": "Tuvalden renk seçmek için tıklayın.",
+  "LOCALIZATION_DEBUG_WINDOW_TITLE": "Yerelleştirme Hata Ayıklama Penceresi",
+  "COMMAND_DEBUG_WINDOW_TITLE": "Komut Hata Ayıklama Penceresi",
+  "SHORTCUTS_TITLE": "Kısayollar",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_PERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Bir kolun üzerine tıklayıp Ctrl tuşunu basılı tutarak kolun serbestçe hareket etmesini sağlayın. Orantılı olarak ölçeklendirmek için Shift tuşunu basılı tutun. Bir yan kolun üzerine tıklayıp Alt tuşunu basılı tutarak kaydırın. Dış kolları sürükleyerek döndürün.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Orantılı olarak ölçeklendirmek için Shift tuşunu basılı tutun. Bir yan kolun üzerine tıklayıp Alt tuşunu basılı tutarak kaydırın. Dış kolları sürükleyerek döndürün.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Shift tuşunu basılı tutunarak orantılı olarak ölçeklendirin. Dış kolları sürükleyerek döndürün.",
+  "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "Dönüştürmeyi ölçeklendirmek için kolları sürükleyin. Shift tuşunu basılı tutarak orantılı olarak ölçeklendirin.",
+  "OPEN_DOCUMENTATION": "Dokümantasyonu aç",
+  "LOCAL_PALETTE_SOURCE_NAME": "Yerel",
+  "ERROR_FORBIDDEN_UNIQUE_NAME": "Uzantı benzersiz adı 'pixieditor' ile başlayamaz.",
+  "ERROR_MISSING_METADATA": "Uzantı metaverisi '{0}' eksik.",
+  "ERROR_NO_CLASS_ENTRY": "Uzantı sınıf girişi '{0}' yolda eksik.",
+  "ERROR_NO_ENTRY_ASSEMBLY": "Uzantı giriş derlemesi '{0}' yolda eksik.",
+  "ERROR_MISSING_ADDITIONAL_CONTENT": "Mevcut yapılandırmanız bu uzantının yüklenmesine izin vermiyor. Belki de sahibi değilsiniz veya yüklü değil. Uzantıyı buradan satın alabilirsiniz '{0}'.",
+  "BUY_SUPPORTER_PACK": "Destekçi Paketi Satın Al",
+  "NEWS": "Haberler",
+  "DISABLE_NEWS_PANEL": "Başlangıç penceresinde Haberler panelini devre dışı bırak",
+  "FAILED_FETCH_NEWS": "Haberleri alırken hata oluştu",
+  "CROP_TO_SELECTION": "Seçime Kırp",
+  "CROP_TO_SELECTION_DESCRIPTIVE": "Resmi seçime kırp",
+  "SHOW_CONTEXT_MENU": "Bağlam Menüsünü Göster",
+  "ERASE": "Sil",
+  "USE_SECONDARY_COLOR": "İkincil rengi kullan",
+  "RIGHT_CLICK_MODE": "Sağ Tıklama Modu",
+  "ADD_PRIMARY_COLOR_TO_PALETTE": "Birincil rengi palete ekle",
+  "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Birincil rengi mevcut palete ekle",
+  "COPY_COLOR": "Rengi Kopyala",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Couldn't open File Explorer",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Could not recover all",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Could not fully recover all files.\nIf you send the crash report to the developers\nthey might be able to help you."
 }
 }

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/uk.json

@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Режим правої кнопки миші",
   "RIGHT_CLICK_MODE": "Режим правої кнопки миші",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Додати основний колір до палітри",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Додати основний колір до палітри",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Додати основний колір до поточної палітри",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Додати основний колір до поточної палітри",
-  "COPY_COLOR": "Copy color"
+  "COPY_COLOR": "Копія кольору",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Не вдалося відкрити Провідник",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Не вдалося відновити все",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Не вдалося повністю відновити всі файли.\nЯкщо ви надішлете звіт про збій розробникам\nвони можуть вам допомогти."
 }
 }

+ 19 - 16
src/PixiEditor/Data/Localization/Languages/zh.json

@@ -1,8 +1,8 @@
 {
 {
   "RECENT_FILES": "最近",
   "RECENT_FILES": "最近",
-  "OPEN_FILE": "打开",
+  "OPEN_FILE": "打开文件",
   "NEW_FILE": "新建",
   "NEW_FILE": "新建",
-  "RECENT_EMPTY_TEXT": "空空如也……",
+  "RECENT_EMPTY_TEXT": "这里空空如也……",
   "LANGUAGE": "语言",
   "LANGUAGE": "语言",
   "GENERAL": "基础设置",
   "GENERAL": "基础设置",
   "DISCORD": "Discord",
   "DISCORD": "Discord",
@@ -88,7 +88,7 @@
   "LOCATION_DOES_NOT_EXIST": "位置不存在。",
   "LOCATION_DOES_NOT_EXIST": "位置不存在。",
   "FILE_NOT_FOUND": "无法找到文件。",
   "FILE_NOT_FOUND": "无法找到文件。",
   "ARE_YOU_SURE": "你确定吗?",
   "ARE_YOU_SURE": "你确定吗?",
-  "ARE_YOU_SURE_PATH_FULL_PATH": "你确定要删除{0}吗?\n所有安装都将丢失此资料。\n(完整位置:{1})",
+  "ARE_YOU_SURE_PATH_FULL_PATH": "你确定要删除{0}吗?\n所有安装都将丢失此资料。\n(完整路径:{1})",
   "FAILED_TO_OPEN_FILE": "无法打开文件",
   "FAILED_TO_OPEN_FILE": "无法打开文件",
   "OLD_FILE_FORMAT": "旧文件格式",
   "OLD_FILE_FORMAT": "旧文件格式",
   "OLD_FILE_FORMAT_DESCRIPTION": "此 .pixi 文件使用了已被停止支持的旧文件格式。",
   "OLD_FILE_FORMAT_DESCRIPTION": "此 .pixi 文件使用了已被停止支持的旧文件格式。",
@@ -325,7 +325,7 @@
   "COLOR_PICKER_TOOL": "选色器",
   "COLOR_PICKER_TOOL": "选色器",
   "ELLIPSE_TOOL": "椭圆",
   "ELLIPSE_TOOL": "椭圆",
   "ERASER_TOOL": "橡皮",
   "ERASER_TOOL": "橡皮",
-  "FLOOD_FILL_TOOL": "填满",
+  "FLOOD_FILL_TOOL": "颜料桶",
   "LASSO_TOOL": "拉索",
   "LASSO_TOOL": "拉索",
   "LINE_TOOL": "直线",
   "LINE_TOOL": "直线",
   "MAGIC_WAND_TOOL": "魔法棒",
   "MAGIC_WAND_TOOL": "魔法棒",
@@ -537,7 +537,7 @@
   "NAVIGATOR_PICK_ACTION_DISPLAY": "右键以选择颜色,按住Shift时右键以将其复制至剪贴薄",
   "NAVIGATOR_PICK_ACTION_DISPLAY": "右键以选择颜色,按住Shift时右键以将其复制至剪贴薄",
   "OPEN_FILE_FROM_CLIPBOARD": "从剪贴薄中打开",
   "OPEN_FILE_FROM_CLIPBOARD": "从剪贴薄中打开",
   "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "从剪贴薄中打开文件",
   "OPEN_FILE_FROM_CLIPBOARD_DESCRIPTIVE": "从剪贴薄中打开文件",
-  "OPEN_LOCALIZATION_DATA": "是否打开 LocalizationData.json?更新日期已被加入至剪贴板。\n注意更改只会在重启此程序后启用。",
+  "OPEN_LOCALIZATION_DATA": "是否打开 LocalizationData.json?\n更新日期已被加入至剪贴板。\n注意更改只会在重启此程序后启用。",
   "DOWNLOADING_LANGUAGE_FAILED": "无法下载语言。\nAPI密码可能被过度使用。",
   "DOWNLOADING_LANGUAGE_FAILED": "无法下载语言。\nAPI密码可能被过度使用。",
   "LOCALIZATION_DATA_NOT_FOUND": "无法找到本地化资料路径",
   "LOCALIZATION_DATA_NOT_FOUND": "无法找到本地化资料路径",
   "APPLY": "应用",
   "APPLY": "应用",
@@ -561,17 +561,17 @@
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。按住 Alt 并拖动侧手柄进行剪切。拖动外部手柄进行旋转。",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_SHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。按住 Alt 并拖动侧手柄进行剪切。拖动外部手柄进行旋转。",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。拖动外部手柄进行旋转。",
   "TRANSFORM_ACTION_DISPLAY_SCALE_ROTATE_NOSHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。拖动外部手柄进行旋转。",
   "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。",
   "TRANSFORM_ACTION_DISPLAY_SCALE_NOROTATE_NOSHEAR_NOPERSPECTIVE": "拖动手柄以缩放已选像素。按住 Shift 键按比例缩放。",
-  "OPEN_DOCUMENTATION": "Open documentation",
-  "LOCAL_PALETTE_SOURCE_NAME": "Local",
+  "OPEN_DOCUMENTATION": "打开文档",
+  "LOCAL_PALETTE_SOURCE_NAME": "本地",
   "ERROR_FORBIDDEN_UNIQUE_NAME": "Extension unique name cannot start with 'pixieditor'.",
   "ERROR_FORBIDDEN_UNIQUE_NAME": "Extension unique name cannot start with 'pixieditor'.",
-  "ERROR_MISSING_METADATA": "Extension metadata key '{0}' is missing.",
-  "ERROR_NO_CLASS_ENTRY": "Extension class entry is missing on path '{0}'.",
-  "ERROR_NO_ENTRY_ASSEMBLY": "Extension entry assembly is missing on path '{0}'.",
-  "ERROR_MISSING_ADDITIONAL_CONTENT": "Your current setup doesn't allow loading this extension. Perhaps you don't own it or don't have it installed. You can purchase it here '{0}'.",
-  "BUY_SUPPORTER_PACK": "Buy Supporter Pack",
-  "NEWS": "News",
-  "DISABLE_NEWS_PANEL": "Disable News panel in startup window",
-  "FAILED_FETCH_NEWS": "Failed to fetch news",
+  "ERROR_MISSING_METADATA": "扩展元数据键 “{0}” 丢失。",
+  "ERROR_NO_CLASS_ENTRY": "路径“{0}”上缺少扩展类程序。",
+  "ERROR_NO_ENTRY_ASSEMBLY": "路径“{0}”上缺少扩展程序集。",
+  "ERROR_MISSING_ADDITIONAL_CONTENT": "你当前的设置不允许加载此扩展。 也许你不拥有它或没有安装它。 你可以在“{0}”处购买。",
+  "BUY_SUPPORTER_PACK": "购买支持者包",
+  "NEWS": "新消息",
+  "DISABLE_NEWS_PANEL": "禁用开始窗口的新消息页面",
+  "FAILED_FETCH_NEWS": "无法获取新消息",
   "CROP_TO_SELECTION": "Crop to selection",
   "CROP_TO_SELECTION": "Crop to selection",
   "CROP_TO_SELECTION_DESCRIPTIVE": "Crop image to selection",
   "CROP_TO_SELECTION_DESCRIPTIVE": "Crop image to selection",
   "SHOW_CONTEXT_MENU": "Show context menu",
   "SHOW_CONTEXT_MENU": "Show context menu",
@@ -580,5 +580,8 @@
   "RIGHT_CLICK_MODE": "Right click mode",
   "RIGHT_CLICK_MODE": "Right click mode",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Add primary color to palette",
   "ADD_PRIMARY_COLOR_TO_PALETTE": "Add primary color to palette",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Add primary color to current palette",
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Add primary color to current palette",
-  "COPY_COLOR": "Copy color"
+  "COPY_COLOR": "Copy color",
+  "ERROR_FAILED_TO_OPEN_EXPLORER": "Couldn't open File Explorer",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Could not recover all",
+  "CRASH_NOT_ALL_DOCUMENTS_RECOVERED": "Could not fully recover all files.\nIf you send the crash report to the developers\nthey might be able to help you."
 }
 }

+ 9 - 9
src/PixiEditor/Data/Localization/LocalizationData.json

@@ -13,14 +13,14 @@
       "code": "pl",
       "code": "pl",
       "localeFileName": "pl.json",
       "localeFileName": "pl.json",
       "iconFileName": "pl.png",
       "iconFileName": "pl.png",
-      "lastUpdated": "2023-06-25 14:16:00"
+      "lastUpdated": "2023-12-14 16:59:56"
     },
     },
     {
     {
       "name": "Deutsch",
       "name": "Deutsch",
       "code": "de",
       "code": "de",
       "localeFileName": "de.json",
       "localeFileName": "de.json",
       "iconFileName": "de.png",
       "iconFileName": "de.png",
-      "lastUpdated": "2023-06-25 12:55:11"
+      "lastUpdated": "2023-12-14 16:40:04"
     },
     },
     {
     {
       "name": "Español",
       "name": "Español",
@@ -34,21 +34,21 @@
       "code": "zh",
       "code": "zh",
       "localeFileName": "zh.json",
       "localeFileName": "zh.json",
       "iconFileName": "zh.png",
       "iconFileName": "zh.png",
-      "lastUpdated": "2023-06-01 12:32:02"
+      "lastUpdated": "2023-08-14 07:59:43"
     },
     },
     {
     {
       "name": "Русский",
       "name": "Русский",
       "code": "ru",
       "code": "ru",
       "localeFileName": "ru.json",
       "localeFileName": "ru.json",
       "iconFileName": "ru.png",
       "iconFileName": "ru.png",
-      "lastUpdated": "2023-06-25 14:17:44"
+      "lastUpdated": "2023-12-14 16:54:15"
     },
     },
     {
     {
       "name": "Українська",
       "name": "Українська",
       "code": "uk",
       "code": "uk",
       "localeFileName": "uk.json",
       "localeFileName": "uk.json",
       "iconFileName": "uk.png",
       "iconFileName": "uk.png",
-      "lastUpdated": "2023-06-25 11:35:31"
+      "lastUpdated": "2023-12-14 16:56:58"
     },
     },
     {
     {
       "name": "عربي",
       "name": "عربي",
@@ -56,21 +56,21 @@
       "localeFileName": "ar.json",
       "localeFileName": "ar.json",
       "iconFileName": "ar.png",
       "iconFileName": "ar.png",
       "rightToLeft": true,
       "rightToLeft": true,
-      "lastUpdated": "2023-06-25 14:47:47"
+      "lastUpdated": "2023-12-14 17:25:23"
     },
     },
     {
     {
       "name": "Čeština",
       "name": "Čeština",
       "code": "cs",
       "code": "cs",
       "localeFileName": "cs.json",
       "localeFileName": "cs.json",
       "iconFileName": "cs.png",
       "iconFileName": "cs.png",
-      "lastUpdated": "2023-06-27 18:55:52"
+      "lastUpdated": "2023-12-14 20:10:32"
     },
     },
     {
     {
       "name": "Português (Brasil)",
       "name": "Português (Brasil)",
       "code": "pt-br",
       "code": "pt-br",
       "localeFileName": "pt-br.json",
       "localeFileName": "pt-br.json",
       "iconFileName": "pt-br.png",
       "iconFileName": "pt-br.png",
-      "lastUpdated": "2023-06-01 21:22:27"
+      "lastUpdated": "2023-07-06 04:00:53"
     },
     },
     {
     {
       "name": "Magyar",
       "name": "Magyar",
@@ -91,7 +91,7 @@
       "code": "tr",
       "code": "tr",
       "localeFileName": "tr.json",
       "localeFileName": "tr.json",
       "iconFileName": "tr.png",
       "iconFileName": "tr.png",
-      "lastUpdated": "2023-06-25 19:43:24"
+      "lastUpdated": "2023-06-29 22:44:34"
     }
     }
   ]
   ]
 }
 }

+ 13 - 3
src/PixiEditor/Helpers/CrashHelper.cs

@@ -112,14 +112,24 @@ internal class CrashHelper
         }
         }
     }
     }
 
 
-    public static async Task SendExceptionInfoToWebhook(Exception e, [CallerFilePath] string filePath = "<unknown>", [CallerMemberName] string memberName = "<unknown>")
+    public static void SendExceptionInfoToWebhook(Exception e, bool wait = false,
+        [CallerFilePath] string filePath = "<unknown>", [CallerMemberName] string memberName = "<unknown>")
+    {
+        var task = Task.Run(() => SendExceptionInfoToWebhookAsync(e, filePath, memberName));
+        if (wait)
+        {
+            task.Wait();
+        }
+    }
+
+    public static async Task SendExceptionInfoToWebhookAsync(Exception e, [CallerFilePath] string filePath = "<unknown>", [CallerMemberName] string memberName = "<unknown>")
     {
     {
         if (DebugViewModel.IsDebugBuild)
         if (DebugViewModel.IsDebugBuild)
             return;
             return;
-        await SendReportTextToWebhook(CrashReport.Generate(e), $"{filePath}; Method {memberName}");
+        await SendReportTextToWebhookAsync(CrashReport.Generate(e), $"{filePath}; Method {memberName}");
     }
     }
 
 
-    public static async Task SendReportTextToWebhook(CrashReport report, string catchLocation = null)
+    public static async Task SendReportTextToWebhookAsync(CrashReport report, string catchLocation = null)
     {
     {
         string reportText = report.ReportText;
         string reportText = report.ReportText;
         if (catchLocation is not null)
         if (catchLocation is not null)

+ 1 - 0
src/PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs

@@ -72,6 +72,7 @@ internal static class ServiceCollectionHelpers
         .AddSingleton<PaletteFileParser, JascFileParser>()
         .AddSingleton<PaletteFileParser, JascFileParser>()
         .AddSingleton<PaletteFileParser, ClsFileParser>()
         .AddSingleton<PaletteFileParser, ClsFileParser>()
         .AddSingleton<PaletteFileParser, CorelDrawPalParser>()
         .AddSingleton<PaletteFileParser, CorelDrawPalParser>()
+        .AddSingleton<PaletteFileParser, DeluxePaintParser>()
         .AddSingleton<PaletteFileParser, PngPaletteParser>()
         .AddSingleton<PaletteFileParser, PngPaletteParser>()
         .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
         .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
         .AddSingleton<PaletteFileParser, HexPaletteParser>()
         .AddSingleton<PaletteFileParser, HexPaletteParser>()

+ 2 - 2
src/PixiEditor/Models/AppExtensions/ExtensionLoader.cs

@@ -49,7 +49,7 @@ internal class ExtensionLoader
         }
         }
         catch (Exception ex)
         catch (Exception ex)
         {
         {
-            Task.Run(async () => await CrashHelper.SendExceptionInfoToWebhook(ex));
+            CrashHelper.SendExceptionInfoToWebhook(ex);
         }
         }
     }
     }
 
 
@@ -86,7 +86,7 @@ internal class ExtensionLoader
         catch (Exception ex)
         catch (Exception ex)
         {
         {
             //MessageBox.Show(new LocalizedString("ERROR_LOADING_PACKAGE", packageJsonPath), "ERROR");
             //MessageBox.Show(new LocalizedString("ERROR_LOADING_PACKAGE", packageJsonPath), "ERROR");
-            Task.Run(async () => await CrashHelper.SendExceptionInfoToWebhook(ex));
+            CrashHelper.SendExceptionInfoToWebhook(ex);
         }
         }
     }
     }
 
 

+ 3 - 0
src/PixiEditor/Models/Commands/CommandController.cs

@@ -25,6 +25,8 @@ internal class CommandController
     public CommandCollection Commands { get; }
     public CommandCollection Commands { get; }
 
 
     public List<CommandGroup> CommandGroups { get; }
     public List<CommandGroup> CommandGroups { get; }
+    
+    public CommandLog.CommandLog Log { get; }
 
 
     public OneToManyDictionary<string, Command> FilterCommands { get; }
     public OneToManyDictionary<string, Command> FilterCommands { get; }
     
     
@@ -37,6 +39,7 @@ internal class CommandController
     public CommandController()
     public CommandController()
     {
     {
         Current ??= this;
         Current ??= this;
+        Log = new CommandLog.CommandLog();
 
 
         ShortcutsPath = Path.Join(
         ShortcutsPath = Path.Join(
             Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
             Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),

+ 43 - 0
src/PixiEditor/Models/Commands/CommandLog/CommandLog.cs

@@ -0,0 +1,43 @@
+using System.Globalization;
+using System.Text;
+using PixiEditor.Models.Commands.Commands;
+
+namespace PixiEditor.Models.Commands.CommandLog;
+
+internal class CommandLog
+{
+    private readonly List<CommandLogEntry> list = new(MaxEntries);
+
+    private const int MaxEntries = 8;
+
+    public void Log(Command command, bool? canExecute)
+    {
+        if (canExecute.HasValue && !list[0].CanExecute.HasValue)
+        {
+            list[0].CanExecute = canExecute;
+            return;
+        }
+        
+        if (list.Count >= MaxEntries)
+        {
+            list.RemoveRange(MaxEntries - 1, list.Count - MaxEntries + 1);
+        }
+        
+        list.Insert(0, new CommandLogEntry(command, canExecute, DateTime.Now));
+    }
+
+    public string GetSummary(DateTime relativeTime)
+    {
+        var builder = new StringBuilder();
+
+        foreach (var entry in list)
+        {
+            var relativeSpan = entry.DateTime - relativeTime;
+            string canExecute = entry.CanExecute.HasValue ? entry.CanExecute.ToString() : "not executed";
+            
+            builder.AppendLine($"{entry.Command.InternalName} | CanExecute: {canExecute} | {relativeSpan.TotalSeconds.ToString("F3", CultureInfo.InvariantCulture)}s ago | {entry.DateTime.ToString("O", CultureInfo.InvariantCulture)}");
+        }
+
+        return builder.ToString();
+    }
+}

+ 19 - 0
src/PixiEditor/Models/Commands/CommandLog/CommandLogEntry.cs

@@ -0,0 +1,19 @@
+using PixiEditor.Models.Commands.Commands;
+
+namespace PixiEditor.Models.Commands.CommandLog;
+
+internal class CommandLogEntry
+{
+    public Command Command { get; }
+
+    public bool? CanExecute { get; set; }
+    
+    public DateTime DateTime { get; }
+    
+    public CommandLogEntry(Command command, bool? commandMethod, DateTime dateTime)
+    {
+        Command = command;
+        CanExecute = commandMethod;
+        DateTime = dateTime;
+    }
+}

+ 17 - 2
src/PixiEditor/Models/Commands/CommandMethods.cs

@@ -18,11 +18,26 @@ internal class CommandMethods
 
 
     public void Execute(object parameter)
     public void Execute(object parameter)
     {
     {
-        if (CanExecute(parameter))
+        var log = CommandController.Current?.Log;
+        ToLog(log, null);
+        
+        if (!CanExecute(parameter))
         {
         {
-            _execute(parameter);
+            ToLog(log, false);
+            return;
         }
         }
+        ToLog(log, true);
+
+        _execute(parameter);
     }
     }
 
 
     public bool CanExecute(object parameter) => _canExecute.CallEvaluate(_command, parameter);
     public bool CanExecute(object parameter) => _canExecute.CallEvaluate(_command, parameter);
+
+    private void ToLog(CommandLog.CommandLog? log, bool? canExecute)
+    {
+        if (log != null && _command != null)
+        {
+            log.Log(_command, canExecute);
+        }
+    }
 }
 }

+ 38 - 95
src/PixiEditor/Models/Controllers/MouseUpdateController.cs

@@ -1,126 +1,69 @@
-using System.Diagnostics;
-using System.Windows;
+using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
-using System.Windows.Threading;
 
 
 namespace PixiEditor.Models.Controllers;
 namespace PixiEditor.Models.Controllers;
 
 
 #nullable enable
 #nullable enable
 public class MouseUpdateController : IDisposable
 public class MouseUpdateController : IDisposable
 {
 {
-    private const double MouseUpdateIntervalMs = 1000 / 142.0; //142 Hz
-
-    private Thread timerThread;
-    private readonly AutoResetEvent resetEvent = new(false);
-    private readonly object lockObj = new();
-    private bool isAborted = false;
+    private bool isDisposed = false;
 
 
     private readonly FrameworkElement element;
     private readonly FrameworkElement element;
     private readonly MouseEventHandler mouseMoveHandler;
     private readonly MouseEventHandler mouseMoveHandler;
+    private MouseUpdateControllerSession? session;
     
     
     public MouseUpdateController(FrameworkElement uiElement, MouseEventHandler onMouseMove)
     public MouseUpdateController(FrameworkElement uiElement, MouseEventHandler onMouseMove)
     {
     {
         mouseMoveHandler = onMouseMove;
         mouseMoveHandler = onMouseMove;
         element = uiElement;
         element = uiElement;
-        element.MouseMove += OnMouseMove;
-
-        bool wasThreadCreated = !element.IsLoaded;
-        element.Loaded += (_, _) =>
-        {
-            wasThreadCreated = true;
-            CreateTimerThread();
-        };
-
-        if (!wasThreadCreated)
-            CreateTimerThread();
-
-        element.Unloaded += (_, _) =>
-        {
-            isAborted = true;
-        };
+        
+        element.Loaded += OnElementLoaded;
+        element.Unloaded += OnElementUnloaded;
+        
+        session ??= new MouseUpdateControllerSession(StartListening, StopListening, mouseMoveHandler); 
+        
+        element.MouseMove += CallMouseMoveInput;
     }
     }
-
-    private void CreateTimerThread()
-    {
-        timerThread = new Thread(TimerThread);
-        timerThread.Name = "MouseUpdateController thread";
-        timerThread.Start();
-        isAborted = false;
-    }
-
-    private bool IsThreadShouldStop()
+    
+    void OnElementLoaded(object o, RoutedEventArgs routedEventArgs)
     {
     {
-        return isAborted || timerThread != Thread.CurrentThread || Application.Current is null;
+        session ??= new MouseUpdateControllerSession(StartListening, StopListening, mouseMoveHandler);
     }
     }
     
     
-    private void TimerThread()
+    private void OnElementUnloaded(object o, RoutedEventArgs routedEventArgs)
     {
     {
-        try
-        {
-            long lastThreadIter = Stopwatch.GetTimestamp();
-            
-            // abort if a new thread was created
-            while (!IsThreadShouldStop())
-            {
-                // call waitOne periodically instead of waiting infinitely to make sure we crash or exit when resetEvent is disposed
-                if (!resetEvent.WaitOne(300))
-                {
-                    lastThreadIter = Stopwatch.GetTimestamp();
-                    continue;
-                }
+        session.Dispose();
+        session = null;
+    }
 
 
-                lock (lockObj)
-                {
-                    double sleepDur = Math.Clamp(MouseUpdateIntervalMs - Stopwatch.GetElapsedTime(lastThreadIter).TotalMilliseconds, 0, MouseUpdateIntervalMs);
-                    lastThreadIter += (long)(MouseUpdateIntervalMs * Stopwatch.Frequency / 1000);
-                    if (sleepDur > 0)
-                        Thread.Sleep((int)Math.Round(sleepDur));
-                    
-                    if (IsThreadShouldStop())
-                        return;
-                    Application.Current?.Dispatcher.Invoke(() =>
-                    {
-                        element.MouseMove += OnMouseMove;
-                    });
-                    
-                }
-            }
-        }
-        catch (ObjectDisposedException)
-        {
+    private void StartListening()
+    {
+        if (isDisposed)
             return;
             return;
-        }
-        catch (Exception e)
-        {
-            Application.Current?.Dispatcher.BeginInvoke(() => throw new AggregateException("Input handling thread died", e), DispatcherPriority.SystemIdle);
-            throw;
-        }
+        element.MouseMove -= CallMouseMoveInput;
+        element.MouseMove += CallMouseMoveInput;
     }
     }
 
 
-    private void OnMouseMove(object sender, MouseEventArgs e)
+    private void CallMouseMoveInput(object sender, MouseEventArgs e)
+    {
+        if (isDisposed)
+            return;
+        session?.MouseMoveInput(sender, e);
+    }
+    
+    private void StopListening()
     {
     {
-        bool lockWasTaken = false;
-        try
-        {
-            Monitor.TryEnter(lockObj, ref lockWasTaken);
-            if (lockWasTaken)
-            {
-                resetEvent.Set();
-                element.MouseMove -= OnMouseMove;
-                mouseMoveHandler(sender, e);
-            }
-        }
-        finally
-        {
-            if (lockWasTaken)
-                Monitor.Exit(lockObj);
-        }
+        if (isDisposed)
+            return;
+        element.MouseMove -= CallMouseMoveInput;
     }
     }
 
 
     public void Dispose()
     public void Dispose()
     {
     {
-        element.MouseMove -= OnMouseMove;
-        isAborted = true;
-        resetEvent.Dispose();
+        element.MouseMove -= CallMouseMoveInput;
+        element.Loaded -= OnElementLoaded;
+        element.Unloaded -= OnElementUnloaded;
+        session?.Dispose();
+        isDisposed = true;
     }
     }
 }
 }

+ 117 - 0
src/PixiEditor/Models/Controllers/MouseUpdateControllerSession.cs

@@ -0,0 +1,117 @@
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
+
+namespace PixiEditor.Models.Controllers;
+
+#nullable enable
+internal class MouseUpdateControllerSession : IDisposable
+{
+    private const double IntervalMs = 1000 / 142.0; //142 Hz
+
+    private readonly Action onStartListening;
+    private readonly Action onStopListening;
+    private readonly MouseEventHandler onMouseMove;
+    
+    private readonly AutoResetEvent resetEvent = new(false);
+    private readonly object lockObj = new();
+
+    /// <summary>
+    /// <see cref="MouseUpdateControllerSession"/> doesn't rely on attaching and detaching mouse move handler,
+    /// it just ignores mouse move events when not listening. <br/>
+    /// Yet it still calls <see cref="onStartListening"/> and <see cref="onStopListening"/> which can be used to attach and detach event handler elsewhere.
+    /// </summary>
+    private bool isListening = true;
+    private bool isDisposed = false;
+
+    public MouseUpdateControllerSession(Action onStartListening, Action onStopListening, MouseEventHandler onMouseMove)
+    {
+        this.onStartListening = onStartListening;
+        this.onStopListening = onStopListening;
+        this.onMouseMove = onMouseMove;
+
+        Thread timerThread = new(TimerLoop)
+        {
+            IsBackground = true, Name = "MouseUpdateController thread"
+        };
+
+        timerThread.Start();
+
+        onStartListening();
+    }
+
+    public void MouseMoveInput(object sender, MouseEventArgs e)
+    {
+        if (!isListening || isDisposed)
+            return;
+        
+        bool lockWasTaken = false;
+        try
+        {
+            Monitor.TryEnter(lockObj, ref lockWasTaken);
+            if (lockWasTaken)
+            {
+                isListening = false;
+                onStopListening();
+                onMouseMove(sender, e);
+                resetEvent.Set();
+            }
+        }
+        finally
+        {
+            if (lockWasTaken)
+                Monitor.Exit(lockObj);
+        }
+    }
+    
+    public void Dispose()
+    {
+        isDisposed = true;
+        resetEvent.Dispose();
+    }
+
+    private void TimerLoop()
+    {
+        try
+        {
+            long lastThreadIter = Stopwatch.GetTimestamp();
+            while (!isDisposed)
+            {
+                // call waitOne periodically instead of waiting infinitely to make sure we crash or exit when resetEvent is disposed
+                if (!resetEvent.WaitOne(300))
+                {
+                    lastThreadIter = Stopwatch.GetTimestamp();
+                    continue;
+                }
+
+                lock (lockObj)
+                {
+                    double sleepDur = Math.Clamp(IntervalMs - Stopwatch.GetElapsedTime(lastThreadIter).TotalMilliseconds, 0, IntervalMs);
+                    lastThreadIter += (long)(IntervalMs * Stopwatch.Frequency / 1000);
+                    if (sleepDur > 0)
+                        Thread.Sleep((int)Math.Round(sleepDur));
+                    
+                    if (isDisposed)
+                        return;
+
+                    isListening = true;
+                    Application.Current?.Dispatcher.Invoke(() =>
+                    {
+                        if (!isDisposed)
+                            onStartListening();
+                    });
+                }
+            }
+        }
+        catch (ObjectDisposedException)
+        {
+            return;
+        }
+        catch (Exception e)
+        {
+            Application.Current?.Dispatcher.BeginInvoke(() => throw new AggregateException("Input handling thread died", e), DispatcherPriority.SystemIdle);
+            throw;
+        }
+    }
+}

+ 263 - 39
src/PixiEditor/Models/DataHolders/CrashReport.cs

@@ -1,12 +1,19 @@
 using System.Diagnostics;
 using System.Diagnostics;
+using System.Globalization;
 using System.IO;
 using System.IO;
 using System.IO.Compression;
 using System.IO.Compression;
 using System.Reflection;
 using System.Reflection;
 using System.Text;
 using System.Text;
+using System.Windows.Input;
 using Newtonsoft.Json;
 using Newtonsoft.Json;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.Extensions.Common.UserPreferences;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands;
+using PixiEditor.Models.Enums;
 using PixiEditor.Parser;
 using PixiEditor.Parser;
 using PixiEditor.ViewModels.SubViewModels.Document;
 using PixiEditor.ViewModels.SubViewModels.Document;
+using PixiEditor.Views;
 
 
 namespace PixiEditor.Models.DataHolders;
 namespace PixiEditor.Models.DataHolders;
 
 
@@ -20,14 +27,59 @@ internal class CrashReport : IDisposable
 
 
         builder
         builder
             .AppendLine($"PixiEditor {VersionHelpers.GetCurrentAssemblyVersionString(moreSpecific: true)} x{IntPtr.Size * 8} crashed on {currentTime:yyyy.MM.dd} at {currentTime:HH:mm:ss} {currentTime:zzz}")
             .AppendLine($"PixiEditor {VersionHelpers.GetCurrentAssemblyVersionString(moreSpecific: true)} x{IntPtr.Size * 8} crashed on {currentTime:yyyy.MM.dd} at {currentTime:HH:mm:ss} {currentTime:zzz}")
+            .AppendLine($"Application started {GetFormatted(() => Process.GetCurrentProcess().StartTime, "yyyy.MM.dd HH:hh:ss")}, {GetFormatted(() => DateTime.Now - Process.GetCurrentProcess().StartTime, @"d\ hh\:mm\.ss")} ago")
             .AppendLine($"Report: {Guid.NewGuid()}\n")
             .AppendLine($"Report: {Guid.NewGuid()}\n")
             .AppendLine("-----System Information----")
             .AppendLine("-----System Information----")
             .AppendLine("General:")
             .AppendLine("General:")
             .AppendLine($"  OS: {Environment.OSVersion.VersionString}")
             .AppendLine($"  OS: {Environment.OSVersion.VersionString}")
+            .AppendLine($"  Has Stylus Tablet Device: {GetFormatted(() => HasTabletDevice(TabletDeviceType.Stylus))}")
+            .AppendLine($"  Has Touch Tablet Device: {GetFormatted(() => HasTabletDevice(TabletDeviceType.Touch))}")
             .AppendLine();
             .AppendLine();
 
 
         CrashHelper helper = new();
         CrashHelper helper = new();
 
 
+        AppendHardwareInfo(helper, builder);
+
+        builder.AppendLine("\n--------Command Log--------\n");
+
+        try
+        {
+            builder.Append(CommandController.Current.Log.GetSummary(currentTime.LocalDateTime));
+        }
+        catch (Exception cemLogException)
+        {
+            builder.AppendLine($"Error ({cemLogException.GetType().FullName}: {cemLogException.Message}) while gathering command log, skipping...");
+        }
+        
+        builder.AppendLine("\n-----------State-----------");
+
+        try
+        {
+            AppendStateInfo(builder);
+        }
+        catch (Exception stateException)
+        {
+            builder.AppendLine($"Error ({stateException.GetType().FullName}: {stateException.Message}) while gathering state (Must be bug in GetPreferenceFormatted, GetFormatted or StringBuilder.AppendLine as these should not throw), skipping...");
+        }
+        
+        CrashHelper.AddExceptionMessage(builder, exception);
+
+        string filename = $"crash-{currentTime:yyyy-MM-dd_HH-mm-ss_fff}.zip";
+        string path = Path.Combine(
+            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+            "PixiEditor",
+            "crash_logs");
+        Directory.CreateDirectory(path);
+
+        CrashReport report = new();
+        report.FilePath = Path.Combine(path, filename);
+        report.ReportText = builder.ToString();
+
+        return report;
+    }
+
+    private static void AppendHardwareInfo(CrashHelper helper, StringBuilder builder)
+    {
         try
         try
         {
         {
             helper.GetCPUInformation(builder);
             helper.GetCPUInformation(builder);
@@ -54,21 +106,146 @@ internal class CrashReport : IDisposable
         {
         {
             builder.AppendLine($"Error ({memE.GetType().FullName}: {memE.Message}) while gathering memory information, skipping...");
             builder.AppendLine($"Error ({memE.GetType().FullName}: {memE.Message}) while gathering memory information, skipping...");
         }
         }
+    }
 
 
-        CrashHelper.AddExceptionMessage(builder, exception);
+    private static void AppendStateInfo(StringBuilder builder)
+    {
+        builder
+            .AppendLine("Environment:")
+            .AppendLine($"  Thread Count: {GetFormatted(() => Process.GetCurrentProcess().Threads.Count)}")
+            .AppendLine("\nCulture:")
+            .AppendLine($"  Selected language: {GetPreferenceFormatted("LanguageCode", true, "system")}")
+            .AppendLine($"  Current Culture: {GetFormatted(() => CultureInfo.CurrentCulture)}")
+            .AppendLine($"  Current UI Culture: {GetFormatted(() => CultureInfo.CurrentUICulture)}")
+            .AppendLine("\nPreferences:")
+            .AppendLine($"  Has shared toolbar enabled: {GetPreferenceFormatted("EnableSharedToolbar", true, false)}")
+            .AppendLine($"  Right click mode: {GetPreferenceFormatted<RightClickMode>("RightClickMode", true)}")
+            .AppendLine($"  Has Rich presence enabled: {GetPreferenceFormatted("EnableRichPresence", true, true)}")
+            .AppendLine($"  Debug Mode enabled: {GetPreferenceFormatted("IsDebugModeEnabled", true, false)}")
+            .AppendLine("\nUI:")
+            .AppendLine($"  MainWindow not null: {GetFormatted(() => MainWindow.Current != null)}")
+            .AppendLine($"  MainWindow Size: {GetFormatted(() => MainWindow.Current.RenderSize)}")
+            .AppendLine($"  MainWindow State: {GetFormatted(() => MainWindow.Current.WindowState)}")
+            .AppendLine("\nViewModels:")
+            .AppendLine($"  Has active updateable change: {GetFormatted(() => ViewModelMain.Current?.DocumentManagerSubViewModel?.ActiveDocument?.UpdateableChangeActive)}")
+            .AppendLine($"  Current Tool: {GetFormattedFromViewModelMain(x => x.ToolsSubViewModel?.ActiveTool?.ToolName)}")
+            .AppendLine($"  Primary Color: {GetFormattedFromViewModelMain(x => x.ColorsSubViewModel?.PrimaryColor)}")
+            .AppendLine($"  Secondary Color: {GetFormattedFromViewModelMain(x => x.ColorsSubViewModel?.SecondaryColor)}")
+            .Append("\nActive Document: ");
 
 
-        string filename = $"crash-{currentTime:yyyy-MM-dd_HH-mm-ss_fff}.zip";
-        string path = Path.Combine(
-            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
-            "PixiEditor",
-            "crash_logs");
-        Directory.CreateDirectory(path);
+        try
+        {
+            AppendActiveDocumentInfo(builder);
+        }
+        catch (Exception e)
+        {
+            builder.AppendLine($"Could not get active document info:\n{e}");
+        }
+    }
 
 
-        CrashReport report = new();
-        report.FilePath = Path.Combine(path, filename);
-        report.ReportText = builder.ToString();
+    private static void AppendActiveDocumentInfo(StringBuilder builder)
+    {
+        var main = ViewModelMain.Current;
+        
+        if (main == null)
+        {
+            builder.AppendLine("{ ViewModelMain.Current is null }");
+            return;
+        }
 
 
-        return report;
+        var manager = main.DocumentManagerSubViewModel;
+
+        if (manager == null)
+        {
+            builder.AppendLine("{ DocumentManagerSubViewModel is null }");
+            return;
+        }
+
+        var document = manager.ActiveDocument;
+
+        if (document == null)
+        {
+            builder.AppendLine("null");
+            return;
+        }
+
+        builder
+            .AppendLine()
+            .AppendLine($"  Size: {document.SizeBindable}")
+            .AppendLine($"  Layer Count: {FormatObject(document.StructureHelper.GetAllLayers().Count)}")
+            .AppendLine($"  Has all changes saved: {document.AllChangesSaved}")
+            .AppendLine($"  Horizontal Symmetry Enabled: {document.HorizontalSymmetryAxisEnabledBindable}")
+            .AppendLine($"  Horizontal Symmetry Value: {FormatObject(document.HorizontalSymmetryAxisYBindable)}")
+            .AppendLine($"  Vertical Symmetry Enabled: {document.VerticalSymmetryAxisEnabledBindable}")
+            .AppendLine($"  Vertical Symmetry Value: {FormatObject(document.VerticalSymmetryAxisXBindable)}")
+            .AppendLine($"  Updateable Change Active: {FormatObject(document.UpdateableChangeActive)}")
+            .AppendLine($"  Transform: {FormatObject(document.TransformViewModel)}");
+    }
+
+    private static bool HasTabletDevice(TabletDeviceType type) => Tablet.TabletDevices.Cast<TabletDevice>().Any(tabletDevice => tabletDevice.Type == type);
+
+    private static string GetPreferenceFormatted<T>(string name, bool roaming, T defaultValue = default, string? format = null)
+    {
+        try
+        {
+            var preferences = IPreferences.Current;
+
+            if (preferences == null)
+                return "{ Preferences are null }";
+            
+            var value = roaming
+                ? preferences.GetPreference(name, defaultValue)
+                : preferences.GetLocalPreference(name, defaultValue);
+
+            return FormatObject(value, format);
+        }
+        catch (Exception e)
+        {
+            return $$"""{ Failed getting preference: {{e.Message}} }""";
+        }
+    }
+
+    private static string GetFormattedFromViewModelMain<T>(Func<ViewModelMain, T?> getter, string? format = null)
+    {
+        var main = ViewModelMain.Current;
+        
+        if (main == null)
+            return "{ ViewModelMain.Current is null }";
+
+        return GetFormatted(() => getter(main), format);
+    }
+
+    private static string GetFormatted<T>(Func<T?> getter, string? format = null)
+    {
+        try
+        {
+            var value = getter();
+
+            return FormatObject(value, format);
+        }
+        catch (Exception e)
+        {
+            return $$"""{ Failed retrieving: {{e.Message}} }""";
+        }
+    }
+
+    private static string FormatObject<T>(T? value, string? format = null)
+    {
+        return value switch
+        {
+            null => "null",
+            IFormattable formattable => formattable.ToString(format, CultureInfo.InvariantCulture),
+            LocalizedString localizedS => FormatLocalizedString(localizedS),
+            string s => $"\"{s}\"",
+            _ => value.ToString()
+        };
+
+        string FormatLocalizedString(LocalizedString localizedS)
+        {
+            return localizedS.Parameters != null
+                ? $"{localizedS.Key} @({string.Join(", ", localizedS.Parameters.Select(x => FormatObject(x, format)))})" 
+                : localizedS.Key;
+        }
     }
     }
 
 
     public static CrashReport Parse(string path)
     public static CrashReport Parse(string path)
@@ -90,38 +267,66 @@ internal class CrashReport : IDisposable
 
 
     public int GetDocumentCount() => ZipFile.Entries.Where(x => x.FullName.EndsWith(".pixi")).Count();
     public int GetDocumentCount() => ZipFile.Entries.Where(x => x.FullName.EndsWith(".pixi")).Count();
 
 
-    public List<(string? originalPath, byte[] dotPixiBytes)> RecoverDocuments()
+    public bool TryRecoverDocuments(out List<RecoveredPixi> list)
     {
     {
-        // Load .pixi files
-        Dictionary<string, byte[]> recoveredDocuments = new();
-        foreach (ZipArchiveEntry entry in ZipFile.Entries.Where(x => x.FullName.EndsWith(".pixi")))
+        try
         {
         {
-            using Stream stream = entry.Open();
-            using MemoryStream memStream = new();
-            stream.CopyTo(memStream);
-            recoveredDocuments.Add(entry.Name, memStream.ToArray());
+            list = RecoverDocuments();
+        }
+        catch (Exception e)
+        {
+            list = null;
+            CrashHelper.SendExceptionInfoToWebhook(e);
+            return false;
         }
         }
 
 
-        ZipArchiveEntry? originalPathsEntry = ZipFile.Entries.Where(entry => entry.FullName == "DocumentInfo.json").FirstOrDefault();
-        if (originalPathsEntry is null)
-            return recoveredDocuments.Select<KeyValuePair<string, byte[]>, (string?, byte[])>(keyValue => (null, keyValue.Value)).ToList();
+        return true;
+    }
+    
+    public List<RecoveredPixi> RecoverDocuments()
+    {
+        List<RecoveredPixi> recoveredDocuments = new();
 
 
-        // Load original paths
-        Dictionary<string, string?> originalPaths;
+        var paths = TryGetOriginalPaths();
+        if (paths == null)
         {
         {
-            using Stream stream = originalPathsEntry.Open();
-            using StreamReader reader = new(stream);
-            string json = reader.ReadToEnd();
-            originalPaths = JsonConvert.DeserializeObject<Dictionary<string, string?>>(json);
+            recoveredDocuments.AddRange(
+                ZipFile.Entries
+                    .Where(x => 
+                        x.FullName.StartsWith("Documents") && 
+                        x.FullName.EndsWith(".pixi"))
+                    .Select(entry => new RecoveredPixi(null, entry)));
+
+            return recoveredDocuments;
         }
         }
 
 
-        return (
-            from docKeyValue in recoveredDocuments
-            join pathKeyValue in originalPaths on docKeyValue.Key equals pathKeyValue.Key
-            select (pathKeyValue.Value, docKeyValue.Value)
-            ).ToList();
+        recoveredDocuments.AddRange(paths.Select(path => new RecoveredPixi(path.Value, ZipFile.GetEntry($"Documents/{path.Key}"))));
+
+        return recoveredDocuments;
+
+        Dictionary<string, string>? TryGetOriginalPaths()
+        {
+            var originalPathsEntry = ZipFile.Entries.FirstOrDefault(entry => entry.FullName == "DocumentInfo.json");
+
+            if (originalPathsEntry == null)
+                return null;
+            
+            try
+            {
+                using var stream = originalPathsEntry.Open();
+                using var reader = new StreamReader(stream);
+                string json = reader.ReadToEnd();
+                
+                return JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
+            }
+            catch
+            {
+                return null;
+            }
+        }
     }
     }
 
 
+
     public void Dispose()
     public void Dispose()
     {
     {
         ZipFile.Dispose();
         ZipFile.Dispose();
@@ -169,13 +374,15 @@ internal class CrashReport : IDisposable
 
 
         // Write the documents into zip
         // Write the documents into zip
         int counter = 0;
         int counter = 0;
-        Dictionary<string, string?> originalPaths = new();
-        foreach (DocumentViewModel document in vm.DocumentManagerSubViewModel.Documents)
+        var originalPaths = new Dictionary<string, string>();
+        foreach (var document in vm.DocumentManagerSubViewModel.Documents)
         {
         {
             try
             try
             {
             {
                 string fileName = string.IsNullOrWhiteSpace(document.FullFilePath) ? "Unsaved" : Path.GetFileNameWithoutExtension(document.FullFilePath);
                 string fileName = string.IsNullOrWhiteSpace(document.FullFilePath) ? "Unsaved" : Path.GetFileNameWithoutExtension(document.FullFilePath);
-                string nameInZip = $"{fileName}-{document.OpenedUTC}-{counter}.pixi".Replace(':', '_');
+                string nameInZip = $"{fileName}-{document.OpenedUTC.ToString(CultureInfo.InvariantCulture)}-{counter.ToString(CultureInfo.InvariantCulture)}.pixi"
+                    .Replace(':', '_')
+                    .Replace('/', '_');
 
 
                 byte[] serialized = PixiParser.Serialize(document.ToSerializable());
                 byte[] serialized = PixiParser.Serialize(document.ToSerializable());
 
 
@@ -209,10 +416,27 @@ internal class CrashReport : IDisposable
         ReportText = Encoding.UTF8.GetString(encodedReport);
         ReportText = Encoding.UTF8.GetString(encodedReport);
     }
     }
 
 
-    internal class CrashReportUserMessage
+
+    public class RecoveredPixi
     {
     {
-        public string Message { get; set; }
+        public string? Path { get; }
+        
+        public ZipArchiveEntry RecoveredEntry { get; }
+        
+        public byte[] GetRecoveredBytes()
+        {
+            var buffer = new byte[RecoveredEntry.Length];
+            using var stream = RecoveredEntry.Open();
 
 
-        public string Mail { get; set; }
+            stream.ReadExactly(buffer);
+            
+            return buffer;
+        }
+        
+        public RecoveredPixi(string? path, ZipArchiveEntry recoveredEntry)
+        {
+            Path = path;
+            RecoveredEntry = recoveredEntry;
+        }
     }
     }
 }
 }

+ 5 - 1
src/PixiEditor/Models/Dialogs/OptionsDialog.cs

@@ -2,6 +2,7 @@
 using System.Windows.Controls;
 using System.Windows.Controls;
 using System.Windows.Media;
 using System.Windows.Media;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.Extensions.UI;
 using PixiEditor.Models.Localization;
 using PixiEditor.Models.Localization;
 using PixiEditor.Views.Dialogs;
 using PixiEditor.Views.Dialogs;
 
 
@@ -51,9 +52,12 @@ internal class OptionsDialog<T> : CustomDialog, IEnumerable<T>
         set => _results.Add(name, value);
         set => _results.Add(name, value);
     }
     }
 
 
-    public override bool ShowDialog()
+    public override bool ShowDialog() => ShowDialog(false);
+
+    public bool ShowDialog(bool topmost)
     {
     {
         var popup = new OptionPopup(Title, Content, new(_results.Keys.Select(x => (object)x)));
         var popup = new OptionPopup(Title, Content, new(_results.Keys.Select(x => (object)x)));
+        popup.Topmost = topmost;
         var popupResult = popup.ShowDialog();
         var popupResult = popup.ShowDialog();
 
 
         Result = (T)popup.Result;
         Result = (T)popup.Result;

+ 37 - 21
src/PixiEditor/Models/IO/Exporter.cs

@@ -92,33 +92,23 @@ internal class Exporter
 
 
         var typeFromPath = SupportedFilesHelper.ParseImageFormat(Path.GetExtension(pathWithExtension));
         var typeFromPath = SupportedFilesHelper.ParseImageFormat(Path.GetExtension(pathWithExtension));
 
 
-        if (typeFromPath != FileType.Pixi)
+        if (typeFromPath == FileType.Pixi)
         {
         {
-            var maybeBitmap = document.MaybeRenderWholeImage();
-            if (maybeBitmap.IsT0)
-                return SaveResult.ConcurrencyError;
-            var bitmap = maybeBitmap.AsT1;
+            return TrySaveAsPixi(document, pathWithExtension);
+        }
 
 
-            if (!encodersFactory.ContainsKey(typeFromPath))
-            {
-                return SaveResult.UnknownError;
-            }
+        var maybeBitmap = document.MaybeRenderWholeImage();
+        if (maybeBitmap.IsT0)
+            return SaveResult.ConcurrencyError;
+        var bitmap = maybeBitmap.AsT1;
 
 
-            return TrySaveAs(encodersFactory[typeFromPath](), pathWithExtension, bitmap, exportSize);
-        }
-        else
+        if (!encodersFactory.ContainsKey(typeFromPath))
         {
         {
-            try
-            {
-                Parser.PixiParser.Serialize(document.ToSerializable(), pathWithExtension);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                return SaveResult.SecurityError;
-            }
+            return SaveResult.UnknownError;
         }
         }
 
 
-        return SaveResult.Success;
+        return TrySaveAs(encodersFactory[typeFromPath](), pathWithExtension, bitmap, exportSize);
+
     }
     }
 
 
     static Dictionary<FileType, Func<BitmapEncoder>> encodersFactory = new Dictionary<FileType, Func<BitmapEncoder>>();
     static Dictionary<FileType, Func<BitmapEncoder>> encodersFactory = new Dictionary<FileType, Func<BitmapEncoder>>();
@@ -179,6 +169,10 @@ internal class Exporter
         {
         {
             return SaveResult.SecurityError;
             return SaveResult.SecurityError;
         }
         }
+        catch (UnauthorizedAccessException e)
+        {
+            return SaveResult.SecurityError;
+        }
         catch (IOException)
         catch (IOException)
         {
         {
             return SaveResult.IoError;
             return SaveResult.IoError;
@@ -189,4 +183,26 @@ internal class Exporter
         }
         }
         return SaveResult.Success;
         return SaveResult.Success;
     }
     }
+
+    private static SaveResult TrySaveAsPixi(DocumentViewModel document, string pathWithExtension)
+    {
+        try
+        {
+            Parser.PixiParser.Serialize(document.ToSerializable(), pathWithExtension);
+        }
+        catch (UnauthorizedAccessException e)
+        {
+            return SaveResult.SecurityError;
+        }
+        catch (IOException)
+        {
+            return SaveResult.IoError;
+        }
+        catch
+        {
+            return SaveResult.UnknownError;
+        }
+
+        return SaveResult.Success;
+    }
 }
 }

+ 122 - 0
src/PixiEditor/Models/IO/PaletteParsers/DeluxePaintParser.cs

@@ -0,0 +1,122 @@
+using System.IO;
+using System.Text;
+using PixiEditor.Extensions.Palettes;
+using PixiEditor.Extensions.Palettes.Parsers;
+
+namespace PixiEditor.Models.IO.PaletteParsers;
+
+// Reads 8-bit color palette data from Interleaved Bitmap format (LBM/BBM)
+// most commonly used by DeluxePaint on Amiga and MS DOS.
+//
+// https://en.wikipedia.org/wiki/ILBM
+
+// Note: A BBM file is essentially a LBM without a full image.
+
+internal class DeluxePaintParser : PaletteFileParser
+{
+    public override string FileName { get; } = "DeluxePaint Interleaved Bitmap Palette";
+    public override string[] SupportedFileExtensions { get; } = new string[] { ".bbm", ".lbm" };
+    public override async Task<PaletteFileData> Parse(string path)
+    {
+        try
+        {
+            return await ParseFile(path);
+        }
+        catch
+        {
+            return PaletteFileData.Corrupted;
+        }
+    }
+
+    private static async Task<PaletteFileData> ParseFile(string path)
+    {
+        List<PaletteColor> colorPalette = new();
+        string name = Path.GetFileNameWithoutExtension(path);
+
+        await using (Stream stream = File.OpenRead(path))
+        {
+            byte[] buffer;
+            string header;
+
+            // read the FORM header that identifies the document as an IFF file
+            buffer = new byte[4];
+            stream.Read(buffer, 0, buffer.Length);
+            if (Encoding.ASCII.GetString(buffer) != "FORM")
+                return PaletteFileData.Corrupted; // Form header not found
+
+            // the next value is the size of all the data in the FORM chunk
+            // We don't actually need this value, but we have to read it
+            // regardless to advance the stream
+            ReadInt(stream);
+
+            stream.Read(buffer, 0, buffer.Length);
+            header = Encoding.ASCII.GetString(buffer);
+            if (header != "PBM " && header != "ILBM")
+                return PaletteFileData.Corrupted; // Bitmap header not found
+
+            while (stream.Read(buffer, 0, buffer.Length) == buffer.Length)
+            {
+                int chunkLength;
+
+                chunkLength = ReadInt(stream);
+
+                if (Encoding.ASCII.GetString(buffer) != "CMAP")
+                {
+                    // some other LBM chunk, skip it
+                    if (stream.CanSeek)
+                    {
+                        stream.Seek(chunkLength, SeekOrigin.Current);
+                    }
+                    else
+                    {
+                        for (int i = 0; i < chunkLength; i++)
+                            stream.ReadByte();
+                    }
+                }
+                else
+                {
+                    // color map chunk
+                    for (int i = 0; i < chunkLength / 3; i++)
+                    {
+                        int[] rgb = new int[3];
+
+                        rgb[0] = stream.ReadByte();
+                        rgb[1] = stream.ReadByte();
+                        rgb[2] = stream.ReadByte();
+
+                        colorPalette.Add(new PaletteColor((byte)rgb[0], (byte)rgb[1], (byte)rgb[2]));
+                    }
+
+                    // all done so stop reading the rest of the file
+                    break;
+                }
+
+                // chunks always contain an even number of bytes even if the recorded length is odd
+                // if the length is odd, then there's a padding byte in the file - just read and discard
+                if (chunkLength % 2 != 0)
+                    stream.ReadByte();
+            }
+        }
+
+        return new PaletteFileData(name, colorPalette.ToArray());
+    }
+
+    public override bool CanSave => false;
+
+    public override async Task<bool> Save(string path, PaletteFileData data)
+    {
+        throw new SavingNotSupportedException("Saving palette as .bbm or .lbm is not supported.");
+    }
+
+    private static int ReadInt(Stream stream)
+    {
+        byte[] buffer;
+
+        // big endian conversion: http://stackoverflow.com/a/14401341/148962
+
+        buffer = new byte[4];
+        stream.Read(buffer, 0, buffer.Length);
+
+        return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
+    }
+}

+ 2 - 2
src/PixiEditor/Models/Rendering/CanvasUpdater.cs

@@ -147,6 +147,8 @@ internal class CanvasUpdater
                 break;
                 break;
             }
             }
         }
         }
+        
+        UpdateAffectedNonRerenderedChunks(chunksToRerender, chunkGatherer.MainImageArea);
 
 
         bool anythingToUpdate = false;
         bool anythingToUpdate = false;
         foreach (var (_, chunks) in chunksToRerender)
         foreach (var (_, chunks) in chunksToRerender)
@@ -156,8 +158,6 @@ internal class CanvasUpdater
         if (!anythingToUpdate)
         if (!anythingToUpdate)
             return new();
             return new();
 
 
-        UpdateAffectedNonRerenderedChunks(chunksToRerender, chunkGatherer.MainImageArea);
-        
         List<IRenderInfo> infos = new();
         List<IRenderInfo> infos = new();
         UpdateMainImage(chunksToRerender, updatingStoredChunks ? null : chunkGatherer.MainImageArea.GlobalArea.Value, infos);
         UpdateMainImage(chunksToRerender, updatingStoredChunks ? null : chunkGatherer.MainImageArea.GlobalArea.Value, infos);
         return infos;
         return infos;

+ 3 - 3
src/PixiEditor/Properties/AssemblyInfo.cs

@@ -10,7 +10,7 @@ using System.Windows;
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("PixiEditor")]
 [assembly: AssemblyCompany("PixiEditor")]
 [assembly: AssemblyProduct("PixiEditor")]
 [assembly: AssemblyProduct("PixiEditor")]
-[assembly: AssemblyCopyright("Copyright PixiEditor © 2017 - 2023")]
+[assembly: AssemblyCopyright("Copyright PixiEditor © 2017 - 2024")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 [assembly: AssemblyCulture("")]
 
 
@@ -50,5 +50,5 @@ using System.Windows;
 // You can specify all the values or you can default the Build and Revision Numbers
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.1.2")]
-[assembly: AssemblyFileVersion("1.2.1.2")]
+[assembly: AssemblyVersion("1.2.3.1")]
+[assembly: AssemblyFileVersion("1.2.3.1")]

+ 24 - 2
src/PixiEditor/ViewModels/CrashReportViewModel.cs

@@ -3,8 +3,11 @@ using System.IO;
 using System.Net.Http;
 using System.Net.Http;
 using System.Text;
 using System.Text;
 using System.Windows;
 using System.Windows;
+using System.Windows.Threading;
+using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Dialogs;
 using PixiEditor.Views;
 using PixiEditor.Views;
 using PixiEditor.Views.Dialogs;
 using PixiEditor.Views.Dialogs;
 
 
@@ -40,16 +43,35 @@ internal class CrashReportViewModel : ViewModelBase
         AttachDebuggerCommand = new(AttachDebugger);
         AttachDebuggerCommand = new(AttachDebugger);
 
 
         if (!IsDebugBuild)
         if (!IsDebugBuild)
-            _ = CrashHelper.SendReportTextToWebhook(report);
+            _ = CrashHelper.SendReportTextToWebhookAsync(report);
     }
     }
 
 
     public void RecoverDocuments(object args)
     public void RecoverDocuments(object args)
     {
     {
-        MainWindow window = MainWindow.CreateWithDocuments(CrashReport.RecoverDocuments());
+        MainWindow window = MainWindow.CreateWithRecoveredDocuments(CrashReport, out var showMissingFilesDialog);
 
 
         Application.Current.MainWindow = window;
         Application.Current.MainWindow = window;
         window.Show();
         window.Show();
         hasRecoveredDocuments = false;
         hasRecoveredDocuments = false;
+
+        if (showMissingFilesDialog)
+        {
+            var dialog = new OptionsDialog<LocalizedString>(
+                "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE",
+                new LocalizedString("CRASH_NOT_ALL_DOCUMENTS_RECOVERED"))
+            {
+                {
+                    "SEND", _ =>
+                    {
+                        var sendReportDialog = new SendCrashReportWindow(CrashReport);
+                        sendReportDialog.ShowDialog();
+                    }
+                },
+                "CLOSE"
+            };
+
+            dialog.ShowDialog(true);
+        }
     }
     }
 
 
     [Conditional("DEBUG")]
     [Conditional("DEBUG")]

+ 6 - 1
src/PixiEditor/ViewModels/SubViewModels/Document/TransformOverlays/DocumentTransformViewModel.cs

@@ -1,4 +1,6 @@
-using System.Windows.Input;
+using System.Diagnostics;
+using System.Text;
+using System.Windows.Input;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Common.Localization;
@@ -10,6 +12,7 @@ using PixiEditor.Views.UserControls.Overlays.TransformOverlay;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Document.TransformOverlays;
 namespace PixiEditor.ViewModels.SubViewModels.Document.TransformOverlays;
 #nullable enable
 #nullable enable
+[DebuggerDisplay("{ToString(),nq}")]
 internal class DocumentTransformViewModel : NotifyableObject
 internal class DocumentTransformViewModel : NotifyableObject
 {
 {
     private DocumentViewModel document;
     private DocumentViewModel document;
@@ -246,4 +249,6 @@ internal class DocumentTransformViewModel : NotifyableObject
                 break;
                 break;
         }
         }
     }
     }
+
+    public override string ToString() => !TransformActive ? "Not active" : $"Transform Mode: {activeTransformMode}; Corner Freedom: {CornerFreedom}; Side Freedom: {SideFreedom}";
 }
 }

+ 2 - 3
src/PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs

@@ -102,8 +102,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
         {
         {
             OpenFromPath(file);
             OpenFromPath(file);
         }
         }
-        else if ((Owner.DocumentManagerSubViewModel.Documents.Count == 0
-                  || !args.Contains("--crash")) && !args.Contains("--openedInExisting"))
+        else if ((Owner.DocumentManagerSubViewModel.Documents.Count == 0 && !args.Contains("--crash")) && !args.Contains("--openedInExisting"))
         {
         {
             if (IPreferences.Current.GetPreference("ShowStartupWindow", true))
             if (IPreferences.Current.GetPreference("ShowStartupWindow", true))
             {
             {
@@ -157,7 +156,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
                 continue;
                 continue;
             }
             }
             
             
-            OpenFromPath(dataImage.name, false);
+            OpenRegularImage(dataImage.image, null);
         }
         }
     }
     }
 
 

+ 2 - 2
src/PixiEditor/ViewModels/SubViewModels/Main/MiscViewModel.cs

@@ -20,7 +20,7 @@ internal class MiscViewModel : SubViewModel<ViewModelMain>
     [Command.Basic("PixiEditor.Links.OpenRepository", "https://github.com/PixiEditor/PixiEditor", "REPOSITORY", "OPEN_REPOSITORY", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenRepository", "https://github.com/PixiEditor/PixiEditor", "REPOSITORY", "OPEN_REPOSITORY", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenLicense", "https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE", "LICENSE", "OPEN_LICENSE", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenLicense", "https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE", "LICENSE", "OPEN_LICENSE", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenOtherLicenses", "https://pixieditor.net/docs/Third-party-licenses", "THIRD_PARTY_LICENSES", "OPEN_THIRD_PARTY_LICENSES", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenOtherLicenses", "https://pixieditor.net/docs/Third-party-licenses", "THIRD_PARTY_LICENSES", "OPEN_THIRD_PARTY_LICENSES", IconPath = "Globe.png")]
-    public static async Task OpenHyperlink(string url)
+    public static void OpenHyperlink(string url)
     {
     {
         try
         try
         {
         {
@@ -28,8 +28,8 @@ internal class MiscViewModel : SubViewModel<ViewModelMain>
         }
         }
         catch (Exception e)
         catch (Exception e)
         {
         {
+            CrashHelper.SendExceptionInfoToWebhook(e);
             NoticeDialog.Show(title: "Error", message: $"Couldn't open the address {url} in your default browser");
             NoticeDialog.Show(title: "Error", message: $"Couldn't open the address {url} in your default browser");
-            await CrashHelper.SendExceptionInfoToWebhook(e);
         }
         }
     }
     }
 }
 }

+ 1 - 1
src/PixiEditor/ViewModels/SubViewModels/Main/UpdateViewModel.cs

@@ -222,7 +222,7 @@ internal class UpdateViewModel : SubViewModel<ViewModelMain>
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                CrashHelper.SendExceptionInfoToWebhook(e);
+                CrashHelper.SendExceptionInfoToWebhookAsync(e);
                 NoticeDialog.Show("COULD_NOT_CHECK_FOR_UPDATES", "UPDATE_CHECK_FAILED");
                 NoticeDialog.Show("COULD_NOT_CHECK_FOR_UPDATES", "UPDATE_CHECK_FAILED");
             }
             }
 
 

+ 1 - 1
src/PixiEditor/Views/Dialogs/HelloTherePopup.xaml.cs

@@ -238,7 +238,7 @@ internal partial class HelloTherePopup : Window
         {
         {
             IsFetchingNews = false;
             IsFetchingNews = false;
             FailedFetchingNews = true;
             FailedFetchingNews = true;
-            await CrashHelper.SendExceptionInfoToWebhook(ex);
+            await CrashHelper.SendExceptionInfoToWebhookAsync(ex);
         }
         }
     }
     }
 }
 }

+ 1 - 0
src/PixiEditor/Views/Dialogs/OptionsPopup.xaml.cs

@@ -39,6 +39,7 @@ internal partial class OptionPopup : Window
 
 
     public OptionPopup(string title, object content, ObservableCollection<object> options)
     public OptionPopup(string title, object content, ObservableCollection<object> options)
     {
     {
+        Title = title;
         PopupContent = content;
         PopupContent = content;
         Options = options;
         Options = options;
         CancelCommand = new RelayCommand(Cancel);
         CancelCommand = new RelayCommand(Cancel);

+ 48 - 5
src/PixiEditor/Views/MainWindow.xaml.cs

@@ -16,11 +16,14 @@ using PixiEditor.Extensions.UI;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.AppExtensions;
 using PixiEditor.Models.AppExtensions;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
 using PixiEditor.Platform;
 using PixiEditor.Platform;
 using PixiEditor.ViewModels.SubViewModels.Document;
 using PixiEditor.ViewModels.SubViewModels.Document;
 using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
+using PixiEditor.Views.Dialogs;
 
 
 namespace PixiEditor.Views;
 namespace PixiEditor.Views;
 
 
@@ -79,6 +82,14 @@ internal partial class MainWindow : Window
         });
         });
 
 
         DataContext.DocumentManagerSubViewModel.ActiveDocumentChanged += DocumentChanged;
         DataContext.DocumentManagerSubViewModel.ActiveDocumentChanged += DocumentChanged;
+        
+        ContentRendered += OnContentRendered;
+    }
+
+    private void OnContentRendered(object sender, EventArgs e)
+    {
+        LoadingWindow.Instance?.SafeClose();
+        Activate();
     }
     }
 
 
     private void SetupTranslator()
     private void SetupTranslator()
@@ -96,17 +107,49 @@ internal partial class MainWindow : Window
         GlobalMouseHook.Instance.Initilize(this);
         GlobalMouseHook.Instance.Initilize(this);
     }
     }
 
 
-    public static MainWindow CreateWithDocuments(IEnumerable<(string? originalPath, byte[] dotPixiBytes)> documents)
+    public static MainWindow CreateWithRecoveredDocuments(CrashReport report, out bool showMissingFilesDialog)
     {
     {
-        MainWindow window = new(extLoader);
-        FileViewModel fileVM = window.services.GetRequiredService<FileViewModel>();
+        var window = GetMainWindow();
+        var fileVM = window.services.GetRequiredService<FileViewModel>();
 
 
-        foreach (var (path, bytes) in documents)
+        if (!report.TryRecoverDocuments(out var documents))
         {
         {
-            fileVM.OpenRecoveredDotPixi(path, bytes);
+            showMissingFilesDialog = true;
+            return window;
         }
         }
 
 
+        var i = 0;
+
+        foreach (var document in documents)
+        {
+            try
+            {
+                fileVM.OpenRecoveredDotPixi(document.Path, document.GetRecoveredBytes());
+                i++;
+            }
+            catch (Exception e)
+            {
+                CrashHelper.SendExceptionInfoToWebhook(e);
+            }
+        }
+
+        showMissingFilesDialog = documents.Count != i;
+
         return window;
         return window;
+
+        MainWindow GetMainWindow()
+        {
+            try
+            {
+                var app = (App)Application.Current;
+                return new MainWindow(app.InitApp());
+            }
+            catch (Exception e)
+            {
+                CrashHelper.SendExceptionInfoToWebhook(e, true);
+                throw;
+            }
+        }
     }
     }
 
 
     /// <summary>Brings main window to foreground.</summary>
     /// <summary>Brings main window to foreground.</summary>

+ 7 - 1
src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml.cs

@@ -32,13 +32,19 @@ internal partial class FolderControl : UserControl
 
 
     private readonly Brush? highlightColor;
     private readonly Brush? highlightColor;
     
     
-    private MouseUpdateController mouseUpdateController;
+    private MouseUpdateController? mouseUpdateController;
 
 
     public FolderControl()
     public FolderControl()
     {
     {
         InitializeComponent();
         InitializeComponent();
         highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
         highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
         Loaded += OnLoaded;
         Loaded += OnLoaded;
+        Unloaded += OnUnloaded;
+    }
+
+    private void OnUnloaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController?.Dispose();
     }
     }
 
 
     private void OnLoaded(object sender, RoutedEventArgs e)
     private void OnLoaded(object sender, RoutedEventArgs e)

+ 7 - 1
src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml.cs

@@ -62,15 +62,21 @@ internal partial class LayerControl : UserControl
         nameof(MoveToFrontCommand), typeof(RelayCommand), typeof(LayerControl), new PropertyMetadata(default(RelayCommand)));
         nameof(MoveToFrontCommand), typeof(RelayCommand), typeof(LayerControl), new PropertyMetadata(default(RelayCommand)));
 
 
 
 
-    private MouseUpdateController mouseUpdateController;
+    private MouseUpdateController? mouseUpdateController;
     
     
     public LayerControl()
     public LayerControl()
     {
     {
         InitializeComponent();
         InitializeComponent();
         Loaded += LayerControl_Loaded;
         Loaded += LayerControl_Loaded;
+        Unloaded += LayerControl_Unloaded;
         highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
         highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
     }
     }
 
 
+    private void LayerControl_Unloaded(object sender, RoutedEventArgs e)
+    { 
+        mouseUpdateController?.Dispose();
+    }
+
     private void LayerControl_Loaded(object sender, RoutedEventArgs e)
     private void LayerControl_Loaded(object sender, RoutedEventArgs e)
     {
     {
         mouseUpdateController = new MouseUpdateController(this, Manager.LayerControl_MouseMove);
         mouseUpdateController = new MouseUpdateController(this, Manager.LayerControl_MouseMove);

+ 2 - 5
src/PixiEditor/Views/UserControls/Overlays/BrushShapeOverlay/BrushShapeOverlay.cs

@@ -65,7 +65,7 @@ internal class BrushShapeOverlay : Control
     private Pen whitePen = new Pen(Brushes.LightGray, 1);
     private Pen whitePen = new Pen(Brushes.LightGray, 1);
     private Point lastMousePos = new();
     private Point lastMousePos = new();
 
 
-    private MouseUpdateController mouseUpdateController;
+    private MouseUpdateController? mouseUpdateController;
 
 
     public BrushShapeOverlay()
     public BrushShapeOverlay()
     {
     {
@@ -75,10 +75,7 @@ internal class BrushShapeOverlay : Control
 
 
     private void ControlUnloaded(object sender, RoutedEventArgs e)
     private void ControlUnloaded(object sender, RoutedEventArgs e)
     {
     {
-        if (MouseEventSource is null)
-            return;
-        
-        mouseUpdateController.Dispose();
+        mouseUpdateController?.Dispose();
     }
     }
 
 
     private void ControlLoaded(object sender, RoutedEventArgs e)
     private void ControlLoaded(object sender, RoutedEventArgs e)

+ 6 - 0
src/PixiEditor/Views/UserControls/Overlays/LineToolOverlay/LineToolOverlay.cs

@@ -72,12 +72,18 @@ internal class LineToolOverlay : Control
     {
     {
         Cursor = Cursors.Arrow;
         Cursor = Cursors.Arrow;
         Loaded += OnLoaded;
         Loaded += OnLoaded;
+        Unloaded += OnUnloaded;
     }
     }
 
 
     private void OnLoaded(object sender, RoutedEventArgs e)
     private void OnLoaded(object sender, RoutedEventArgs e)
     {
     {
         mouseUpdateController = new MouseUpdateController(this, MouseMoved);
         mouseUpdateController = new MouseUpdateController(this, MouseMoved);
     }
     }
+    
+    private void OnUnloaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController?.Dispose();
+    }
 
 
     private static void OnZoomboxScaleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
     private static void OnZoomboxScaleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
     {
     {

+ 7 - 1
src/PixiEditor/Views/UserControls/Overlays/SymmetryOverlay/SymmetryOverlay.cs

@@ -119,11 +119,17 @@ internal class SymmetryOverlay : Control
     private double horizontalAxisY;
     private double horizontalAxisY;
     private double verticalAxisX;
     private double verticalAxisX;
 
 
-    private MouseUpdateController mouseUpdateController;
+    private MouseUpdateController? mouseUpdateController;
 
 
     public SymmetryOverlay()
     public SymmetryOverlay()
     {
     {
         Loaded += OnLoaded;
         Loaded += OnLoaded;
+        Unloaded += OnUnloaded;
+    }
+
+    private void OnUnloaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController?.Dispose();
     }
     }
 
 
     private void OnLoaded(object sender, RoutedEventArgs e)
     private void OnLoaded(object sender, RoutedEventArgs e)

+ 13 - 2
src/PixiEditor/Views/UserControls/PreviewWindow.xaml.cs

@@ -54,11 +54,22 @@ internal partial class PreviewWindow : UserControl
     {
     {
         InitializeComponent();
         InitializeComponent();
         
         
-        mouseUpdateController = new MouseUpdateController(imageGrid, ImageGrid_MouseMove);
-        
         imageGrid.MouseRightButtonDown += ImageGrid_MouseRightButtonDown;
         imageGrid.MouseRightButtonDown += ImageGrid_MouseRightButtonDown;
         imageGrid.MouseEnter += ImageGrid_MouseEnter;
         imageGrid.MouseEnter += ImageGrid_MouseEnter;
         imageGrid.MouseLeave += ImageGrid_MouseLeave;
         imageGrid.MouseLeave += ImageGrid_MouseLeave;
+        
+        imageGrid.Loaded += OnGridLoaded;
+        imageGrid.Unloaded += OnGridUnloaded;
+    }
+
+    private void OnGridUnloaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController?.Dispose();
+    }
+
+    private void OnGridLoaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController = new MouseUpdateController(imageGrid, ImageGrid_MouseMove);
     }
     }
 
 
     private void ImageGrid_MouseLeave(object sender, MouseEventArgs e)
     private void ImageGrid_MouseLeave(object sender, MouseEventArgs e)

+ 3 - 3
src/PixiEditor/Views/UserControls/Viewport.xaml.cs

@@ -283,7 +283,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
 
     public Guid GuidValue { get; } = Guid.NewGuid();
     public Guid GuidValue { get; } = Guid.NewGuid();
 
 
-    private MouseUpdateController mouseUpdateController;
+    private MouseUpdateController? mouseUpdateController;
 
 
     public Viewport()
     public Viewport()
     {
     {
@@ -295,8 +295,6 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         MainImage!.Loaded += OnImageLoaded;
         MainImage!.Loaded += OnImageLoaded;
         Loaded += OnLoad;
         Loaded += OnLoad;
         Unloaded += OnUnload;
         Unloaded += OnUnload;
-        
-        mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
     }
     }
 
 
     public Image? MainImage => (Image?)((Grid?)((Border?)zoombox.AdditionalContent)?.Child)?.Children[1];
     public Image? MainImage => (Image?)((Grid?)((Border?)zoombox.AdditionalContent)?.Child)?.Children[1];
@@ -310,11 +308,13 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
     private void OnUnload(object sender, RoutedEventArgs e)
     private void OnUnload(object sender, RoutedEventArgs e)
     {
     {
         Document?.Operations.RemoveViewport(GuidValue);
         Document?.Operations.RemoveViewport(GuidValue);
+        mouseUpdateController?.Dispose();
     }
     }
 
 
     private void OnLoad(object sender, RoutedEventArgs e)
     private void OnLoad(object sender, RoutedEventArgs e)
     {
     {
         Document?.Operations.AddOrUpdateViewport(GetLocation());
         Document?.Operations.AddOrUpdateViewport(GetLocation());
+        mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
     }
     }
 
 
     private static void OnDocumentChange(DependencyObject viewportObj, DependencyPropertyChangedEventArgs args)
     private static void OnDocumentChange(DependencyObject viewportObj, DependencyPropertyChangedEventArgs args)