diff --git a/README.md b/README.md
index ce69f11..7a84a0f 100755
--- a/README.md
+++ b/README.md
@@ -17,12 +17,12 @@
### Windows
数据库: %APPDATA%\Local\OCES\Resonance\Databases
-偏好设置: %APPDATA%\Roaming\OCES\Resonance\
+偏好设置: %APPDATA%\Roaming\OCES\Resonance\preferences.json
### Linux
数据库: XDG_DATA_HOME
-偏好设置: XDG_CONFIG_HOME
+偏好设置: XDG_CONFIG_HOME/preferences.json
缓存数据: XDG_CACHE_HOME
### TODO
@@ -30,7 +30,8 @@
- [ ] 扫描时如果报错,报错信息可能会填满整个窗口,导致Overlay无法关闭。
- [ ] 读取时如果报错,没有任何警告,会静默报错。需要有一个界面右下方的toast,或是发送系统通知告知用户遇到了错误。
- [x] 指针化Artwork字段。如果artwork的md5
-- [ ] 本地化框架
+- [x] 本地化框架
+- [ ] 偏好设置/控制面板
## 技术栈
diff --git a/src/GUI/App.axaml b/src/GUI/App.axaml
index e849f37..e222270 100644
--- a/src/GUI/App.axaml
+++ b/src/GUI/App.axaml
@@ -3,22 +3,22 @@
x:Class="GUI.App"
Name="Resonance"
xmlns:local="using:GUI"
+ xmlns:l10n="using:GUI.Converters"
RequestedThemeVariant="Default">
-
-
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/src/GUI/App.axaml.cs b/src/GUI/App.axaml.cs
index 45bfd43..78fed5f 100644
--- a/src/GUI/App.axaml.cs
+++ b/src/GUI/App.axaml.cs
@@ -1,9 +1,7 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Data.Core;
-using Avalonia.Data.Core.Plugins;
-using System.Linq;
using Avalonia.Markup.Xaml;
+using GUI.Services;
using GUI.ViewModels;
using GUI.Views;
diff --git a/src/GUI/Assets/Locale.Designer.cs b/src/GUI/Assets/Locale.Designer.cs
deleted file mode 100644
index 25b1099..0000000
--- a/src/GUI/Assets/Locale.Designer.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace GUI {
- using System;
-
-
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
- [System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Locale {
-
- private static System.Resources.ResourceManager resourceMan;
-
- private static System.Globalization.CultureInfo resourceCulture;
-
- [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Locale() {
- }
-
- [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static System.Resources.ResourceManager ResourceManager {
- get {
- if (object.Equals(null, resourceMan)) {
- System.Resources.ResourceManager temp = new System.Resources.ResourceManager("GUI.Locale", typeof(Locale).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
- }
-}
diff --git a/src/GUI/Assets/Locale.resx b/src/GUI/Assets/Locale.resx
deleted file mode 100644
index a4c5284..0000000
--- a/src/GUI/Assets/Locale.resx
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
\ No newline at end of file
diff --git a/src/GUI/Converters/LocalizeExtension.cs b/src/GUI/Converters/LocalizeExtension.cs
new file mode 100644
index 0000000..e3a0ed3
--- /dev/null
+++ b/src/GUI/Converters/LocalizeExtension.cs
@@ -0,0 +1,25 @@
+using Avalonia.Data;
+using Avalonia.Markup.Xaml;
+using GUI.Services;
+
+namespace GUI.Converters;
+
+public class LocalizeExtension : MarkupExtension
+{
+ public string Key { get; set; }
+
+ public LocalizeExtension(string key)
+ {
+ Key = key;
+ }
+
+ public override object ProvideValue(IServiceProvider serviceProvider)
+ {
+ return new Binding
+ {
+ Source = LocalizationService.Instance,
+ Path = $"[{Key}]",
+ Mode = BindingMode.OneWay,
+ };
+ }
+}
diff --git a/src/GUI/Converters/ValueConverters.cs b/src/GUI/Converters/ValueConverters.cs
index 1e3b729..2d2b08c 100644
--- a/src/GUI/Converters/ValueConverters.cs
+++ b/src/GUI/Converters/ValueConverters.cs
@@ -1,5 +1,6 @@
using System.Globalization;
using Avalonia.Data.Converters;
+using GUI.Services;
namespace GUI.Converters;
@@ -36,8 +37,8 @@ public class ChannelsFormatConverter : IValueConverter
{
return value switch
{
- int ch when ch == 1 => "Mono",
- int ch when ch == 2 => "Stereo",
+ int ch when ch == 1 => LocalizationService.Instance["ChannelsMono"],
+ int ch when ch == 2 => LocalizationService.Instance["ChannelsStereo"],
null => "--",
int ch => $"{ch}ch",
_ => "--",
diff --git a/src/GUI/GUI.csproj b/src/GUI/GUI.csproj
index 36d9b4a..9e59251 100644
--- a/src/GUI/GUI.csproj
+++ b/src/GUI/GUI.csproj
@@ -10,6 +10,7 @@
+
@@ -32,17 +33,11 @@
-
- ResXFileCodeGenerator
- Locale.Designer.cs
+
+ GUI.LocaleZh.xml
+
+
+ GUI.LocaleEn.xml
-
-
-
- True
- True
- Locale.resx
-
-
diff --git a/src/GUI/Resources/LocaleEn.xml b/src/GUI/Resources/LocaleEn.xml
new file mode 100644
index 0000000..fd6e4c1
--- /dev/null
+++ b/src/GUI/Resources/LocaleEn.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ About…
+
+
+ Preferences…
+
+
+ Database
+
+
+ Delete Unused Artworks
+
+
+ Open database file in Finder...
+
+
+ Scan Directory
+
+
+ Select Audio Directory
+
+
+ Search files...
+
+
+ Refresh
+
+
+ Reset Filters
+
+
+ No files yet. Scan a directory to add audio files.
+
+
+ Metadata
+
+
+ Save
+
+
+ Basic Info
+
+
+ Rating
+
+
+ Tags & Description
+
+
+ Category
+
+
+ Keywords (comma-separated)
+
+
+ Description
+
+
+ Notes
+
+
+ Duration:
+
+
+ Sample Rate:
+
+
+ Bit Depth:
+
+
+ Channels:
+
+
+ Format:
+
+
+ Select a file to view metadata
+
+
+ Enter category...
+
+
+ Enter keywords...
+
+
+ Enter description...
+
+
+ Enter notes...
+
+
+ Processed:
+
+
+ Added: {0}
+
+
+ Skipped: {0}
+
+
+ Close
+
+
+ Browse
+
+
+ All Files
+
+
+ Tags
+
+
+ Preparing to scan...
+
+
+ Discovering files...
+
+
+ Found {0} files, parsing metadata...
+
+
+ Scan complete: {0} added, {1} skipped
+
+
+ Scan error: {0}
+
+
+ No file selected
+
+
+ Mono
+
+
+ Stereo
+
+
+ Sort by
+
+
diff --git a/src/GUI/Resources/LocaleZh.xml b/src/GUI/Resources/LocaleZh.xml
new file mode 100644
index 0000000..924d574
--- /dev/null
+++ b/src/GUI/Resources/LocaleZh.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 关于…
+
+
+ 偏好设置…
+
+
+ 数据库
+
+
+ 删除没有使用的封面
+
+
+ 在访达中打开数据库文件…
+
+
+ 扫描目录
+
+
+ 选择音频目录
+
+
+ 搜索文件...
+
+
+ 刷新
+
+
+ 重置筛选
+
+
+ 暂无文件,请先扫描目录添加音频文件。
+
+
+ 元数据
+
+
+ 保存
+
+
+ 基础信息
+
+
+ 评分
+
+
+ 标签与描述
+
+
+ 分类
+
+
+ 关键词(逗号分隔)
+
+
+ 描述
+
+
+ 备注
+
+
+ 时长:
+
+
+ 采样率:
+
+
+ 位深:
+
+
+ 声道:
+
+
+ 格式:
+
+
+ 选择文件查看元数据
+
+
+ 输入分类...
+
+
+ 输入关键词...
+
+
+ 输入描述...
+
+
+ 输入备注...
+
+
+ 已处理:
+
+
+ 新增: {0}
+
+
+ 跳过: {0}
+
+
+ 关闭
+
+
+ 浏览
+
+
+ 全部文件
+
+
+ 标签
+
+
+ 准备扫描...
+
+
+ 正在发现文件...
+
+
+ 发现 {0} 个文件,正在解析元数据...
+
+
+ 扫描完成:新增 {0},跳过 {1}
+
+
+ 扫描出错:{0}
+
+
+ 未选择文件
+
+
+ 单声道
+
+
+ 立体声
+
+
+ 排序字段
+
+
diff --git a/src/GUI/Services/LocalizationService.cs b/src/GUI/Services/LocalizationService.cs
new file mode 100644
index 0000000..6408b07
--- /dev/null
+++ b/src/GUI/Services/LocalizationService.cs
@@ -0,0 +1,168 @@
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using System.Text.Json;
+using System.Xml;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace GUI.Services;
+
+public sealed class LocalizationService : ObservableObject
+{
+ public static LocalizationService Instance { get; } = new();
+
+ private readonly Dictionary> _strings = new();
+
+ private CultureInfo _currentCulture = CultureInfo.GetCultureInfo("zh-CN");
+ private string _currentCultureKey = "zh-CN";
+
+ public CultureInfo CurrentCulture
+ {
+ get => _currentCulture;
+ set
+ {
+ var key = value.Name;
+ if (key != "zh-CN" && key != "en-US")
+ key = "zh-CN";
+
+ if (!SetProperty(ref _currentCulture, CultureInfo.GetCultureInfo(key), nameof(CurrentCulture)))
+ return;
+
+ _currentCultureKey = key;
+ CultureInfo.CurrentCulture = _currentCulture;
+ CultureInfo.CurrentUICulture = _currentCulture;
+ OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
+ }
+ }
+
+ public IReadOnlyList SupportedCultures { get; }
+
+ private LocalizationService()
+ {
+ LoadResources("zh-CN", "GUI.LocaleZh.xml");
+ LoadResources("en-US", "GUI.LocaleEn.xml");
+
+ SupportedCultures = new ReadOnlyCollection(
+ [
+ CultureInfo.GetCultureInfo("zh-CN"),
+ CultureInfo.GetCultureInfo("en-US"),
+ ]);
+
+ LoadCulturePreference();
+ }
+
+ private void LoadResources(string cultureKey, string resourceName)
+ {
+ var dict = new Dictionary();
+ var assembly = Assembly.GetExecutingAssembly();
+
+ using var stream = FindResource(assembly, resourceName);
+ if (stream == null) return;
+
+ using var reader = XmlReader.Create(stream);
+ while (reader.Read())
+ {
+ if (reader.NodeType != XmlNodeType.Element || reader.Name != "data") continue;
+ var name = reader.GetAttribute("name");
+ reader.ReadToDescendant("value");
+ var value = reader.ReadElementContentAsString();
+ if (name != null)
+ dict[name] = value;
+ }
+
+ _strings[cultureKey] = dict;
+ }
+
+ private static Stream? FindResource(Assembly assembly, string resourceName)
+ {
+ var stream = assembly.GetManifestResourceStream(resourceName);
+ if (stream != null) return stream;
+
+ foreach (var name in assembly.GetManifestResourceNames())
+ {
+ if (name.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase))
+ return assembly.GetManifestResourceStream(name);
+ }
+
+ return null;
+ }
+
+ public string this[string key]
+ {
+ get
+ {
+ if (_strings.TryGetValue(_currentCultureKey, out var dict) && dict.TryGetValue(key, out var val))
+ return val;
+ if (_currentCultureKey != "zh-CN" && _strings.TryGetValue("zh-CN", out var fallback) && fallback.TryGetValue(key, out var fb))
+ return fb;
+ return $"<{key}>";
+ }
+ }
+
+ public string GetFormatted(string key, params object[] args)
+ {
+ try
+ {
+ return string.Format(_currentCulture, this[key], args);
+ }
+ catch
+ {
+ return this[key];
+ }
+ }
+
+ private void LoadCulturePreference()
+ {
+ var path = GetPreferencesPath();
+ if (!File.Exists(path)) return;
+
+ try
+ {
+ var json = File.ReadAllText(path);
+ using var doc = JsonDocument.Parse(json);
+ if (doc.RootElement.TryGetProperty("Language", out var lang))
+ {
+ var langStr = lang.GetString();
+ if (langStr is "zh-CN" or "en-US")
+ {
+ CurrentCulture = CultureInfo.GetCultureInfo(langStr);
+ }
+ }
+ }
+ catch
+ {
+ // ignore malformed preference file
+ }
+ }
+
+ public void SaveCulturePreference()
+ {
+ var path = GetPreferencesPath();
+ var dir = Path.GetDirectoryName(path);
+ if (dir != null)
+ Directory.CreateDirectory(dir);
+
+ var opts = new JsonSerializerOptions { WriteIndented = true };
+ var json = JsonSerializer.Serialize(new Dictionary
+ {
+ ["Language"] = _currentCultureKey,
+ }, opts);
+ File.WriteAllText(path, json);
+ }
+
+ private static string GetPreferencesPath()
+ {
+ if (OperatingSystem.IsMacOS())
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+ "Library", "Preferences", "com.oces.Resonance.json");
+ if (OperatingSystem.IsWindows())
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ "OCES", "Resonance", "preferences.json");
+ return Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ "OCES", "Resonance", "preferences.json");
+ }
+}
diff --git a/src/GUI/ViewModels/PlayerBarViewModel.cs b/src/GUI/ViewModels/PlayerBarViewModel.cs
index 6a89e67..51b2e98 100644
--- a/src/GUI/ViewModels/PlayerBarViewModel.cs
+++ b/src/GUI/ViewModels/PlayerBarViewModel.cs
@@ -11,7 +11,7 @@ public partial class PlayerBarViewModel : ViewModelBase
[ObservableProperty] private AudioFileMeta? _currentFile;
[ObservableProperty] private bool _hasFile;
- [ObservableProperty] private string _currentFileName = "未选择文件";
+ [ObservableProperty] private string _currentFileName = string.Empty;
[ObservableProperty] private bool _isPlaying;
[ObservableProperty] private double _currentPosition;
@@ -21,6 +21,7 @@ public partial class PlayerBarViewModel : ViewModelBase
public PlayerBarViewModel(SyncChannel channel)
{
_channel = channel;
+ CurrentFileName = Loc["NoFileSelected"];
_channel.PropertyChanged += (_, e) =>
{
@@ -39,7 +40,7 @@ public partial class PlayerBarViewModel : ViewModelBase
if (file == null)
{
- CurrentFileName = "未选择文件";
+ CurrentFileName = Loc["NoFileSelected"];
Duration = 0;
HasFile = false;
return;
diff --git a/src/GUI/ViewModels/ScanProgressViewModel.cs b/src/GUI/ViewModels/ScanProgressViewModel.cs
index 05b89da..b958ea5 100644
--- a/src/GUI/ViewModels/ScanProgressViewModel.cs
+++ b/src/GUI/ViewModels/ScanProgressViewModel.cs
@@ -15,6 +15,9 @@ public partial class ScanProgressViewModel : ViewModelBase
[ObservableProperty] private double _progress;
[ObservableProperty] private string _currentFile = string.Empty;
+ public string AddedText => Loc.GetFormatted("AddedFormat", AddedFiles);
+ public string SkippedText => Loc.GetFormatted("SkippedFormat", SkippedFiles);
+
public event Action? ScanCompleted;
[RelayCommand]
@@ -22,6 +25,7 @@ public partial class ScanProgressViewModel : ViewModelBase
{
if (string.IsNullOrWhiteSpace(directory)) return;
+ StatusText = Loc["ScanPreparing"];
Task.Run(() => ScanDirectoryInternal(directory));
}
@@ -32,7 +36,7 @@ public partial class ScanProgressViewModel : ViewModelBase
{
IsScanning = false;
HasError = false;
- StatusText = "准备扫描...";
+ StatusText = Loc["ScanPreparing"];
}
private void ScanDirectoryInternal(string directory)
@@ -41,7 +45,7 @@ public partial class ScanProgressViewModel : ViewModelBase
{
HasError = false;
IsScanning = true;
- StatusText = "正在发现文件...";
+ StatusText = Loc["ScanDiscovering"];
Database.InitializeDatabase();
@@ -56,7 +60,7 @@ public partial class ScanProgressViewModel : ViewModelBase
SkippedFiles = 0;
Progress = 0;
- StatusText = $"发现 {TotalFiles} 个文件,正在解析元数据...";
+ StatusText = Loc.GetFormatted("ScanParsing", TotalFiles);
foreach (string filePath in files)
{
@@ -100,12 +104,12 @@ public partial class ScanProgressViewModel : ViewModelBase
UpdateProgress();
}
- StatusText = $"扫描完成:新增 {AddedFiles},跳过 {SkippedFiles}";
+ StatusText = Loc.GetFormatted("ScanComplete", AddedFiles, SkippedFiles);
}
catch (Exception ex)
{
HasError = true;
- StatusText = $"扫描出错:{ex.Message}";
+ StatusText = Loc.GetFormatted("ScanError", ex.Message);
}
finally
{
@@ -119,4 +123,7 @@ public partial class ScanProgressViewModel : ViewModelBase
{
Progress = TotalFiles > 0 ? (double)ProcessedFiles / TotalFiles * 100 : 0;
}
+
+ partial void OnAddedFilesChanged(int value) => OnPropertyChanged(nameof(AddedText));
+ partial void OnSkippedFilesChanged(int value) => OnPropertyChanged(nameof(SkippedText));
}
diff --git a/src/GUI/ViewModels/ViewModelBase.cs b/src/GUI/ViewModels/ViewModelBase.cs
index 1abda89..0f00f01 100644
--- a/src/GUI/ViewModels/ViewModelBase.cs
+++ b/src/GUI/ViewModels/ViewModelBase.cs
@@ -1,7 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
+using GUI.Services;
namespace GUI.ViewModels;
public abstract class ViewModelBase : ObservableObject
{
+ public LocalizationService Loc => LocalizationService.Instance;
}
diff --git a/src/GUI/Views/FileListView.axaml b/src/GUI/Views/FileListView.axaml
index a43200d..8f7a81d 100644
--- a/src/GUI/Views/FileListView.axaml
+++ b/src/GUI/Views/FileListView.axaml
@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:GUI.Converters"
+ xmlns:l10n="using:GUI.Converters"
mc:Ignorable="d"
x:Class="GUI.Views.FileListView"
x:DataType="vm:FileListViewModel">
@@ -25,22 +26,22 @@
BorderThickness="0,0,0,1">
-
+
+ Width="28" Height="28" ToolTip.Tip="{l10n:Localize Refresh}" Margin="4,0,0,0"/>
-
+
-
-
+
-
-
+
+
@@ -34,8 +35,8 @@
-
-
+
+
diff --git a/src/GUI/Views/MainWindow.axaml.cs b/src/GUI/Views/MainWindow.axaml.cs
index edd9665..a947322 100644
--- a/src/GUI/Views/MainWindow.axaml.cs
+++ b/src/GUI/Views/MainWindow.axaml.cs
@@ -1,6 +1,7 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
+using GUI.Services;
using GUI.ViewModels;
namespace GUI.Views;
@@ -19,7 +20,7 @@ public partial class MainWindow : Window
IReadOnlyList folders = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
- Title = "选择音频目录",
+ Title = LocalizationService.Instance["SelectAudioDirectory"],
AllowMultiple = false,
});
diff --git a/src/GUI/Views/MetadataPanelView.axaml b/src/GUI/Views/MetadataPanelView.axaml
index d4271cb..5820169 100644
--- a/src/GUI/Views/MetadataPanelView.axaml
+++ b/src/GUI/Views/MetadataPanelView.axaml
@@ -3,7 +3,7 @@
xmlns:vm="using:GUI.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:converters="using:GUI.Converters"
+ xmlns:l10n="using:GUI.Converters"
mc:Ignorable="d"
x:Class="GUI.Views.MetadataPanelView"
x:DataType="vm:MetadataPanelViewModel">
@@ -14,8 +14,8 @@
-
-
+
@@ -27,14 +27,29 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -42,7 +57,7 @@
-
-
diff --git a/src/GUI/Views/ScanProgressView.axaml b/src/GUI/Views/ScanProgressView.axaml
index 7ae413b..178eafa 100644
--- a/src/GUI/Views/ScanProgressView.axaml
+++ b/src/GUI/Views/ScanProgressView.axaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:GUI.ViewModels"
xmlns:converters="using:GUI.Converters"
+ xmlns:l10n="using:GUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
@@ -21,21 +22,25 @@
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
-
diff --git a/src/GUI/Views/TagTreeView.axaml b/src/GUI/Views/TagTreeView.axaml
index 7bf382d..a46b86c 100644
--- a/src/GUI/Views/TagTreeView.axaml
+++ b/src/GUI/Views/TagTreeView.axaml
@@ -3,6 +3,7 @@
xmlns:vm="using:GUI.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:l10n="using:GUI.Converters"
mc:Ignorable="d"
x:Class="GUI.Views.TagTreeView"
x:DataType="vm:TagTreeViewModel">
@@ -12,18 +13,18 @@
-
-
+
-
-
-
- True
+ False
+ True
False
True
False
True
- True
\ No newline at end of file
+ True
+ False
\ No newline at end of file