From d042993eb750177bc91d5b1622aa44ab2473d110 Mon Sep 17 00:00:00 2001 From: Zhe Fang Date: Sat, 10 Jan 2026 18:07:57 -0500 Subject: [PATCH] feat: romaji plugin (without dict) --- .github/workflows/plugin-registry-check.yml | 20 + ...-to-discord.yml => release-to-discord.yml} | 0 ...ricsProvider.cs => ILyricsSearchPlugin.cs} | 6 +- .../ILyricsTransliterationPlugin.cs | 11 + BetterLyrics.Core/Interfaces/IPlugin.cs | 17 + .../DemoLyricsProvider.cs | 8 +- .../BetterLyrics.Plugins.Romaji.csproj | 101 +++++ BetterLyrics.Plugins.Romaji/RomajiPlugin.cs | 34 ++ BetterLyrics.Plugins.Romaji/customizeDict.txt | 1 + .../BetterLyrics.WinUI3/App.xaml.cs | 4 + .../BetterLyrics.WinUI3.csproj | 6 + .../Controls/PluginManagerControl.xaml | 83 ++++ .../Controls/PluginManagerControl.xaml.cs | 151 +++++++ .../Models/Entities/LyricsCacheItem.cs | 5 - .../Models/PluginDisplayModel.cs | 25 ++ .../LyricsSearchService.cs | 15 +- .../Services/PluginService/IPluginService.cs | 4 +- .../PluginService/PluginLoadContext.cs | 28 +- .../Services/PluginService/PluginService.cs | 181 ++++++++- .../TransliterationService.cs | 53 ++- .../Strings/ar/Resources.resw | 46 ++- .../Strings/de/Resources.resw | 46 ++- .../Strings/en/Resources.resw | 12 + .../Strings/es/Resources.resw | 46 ++- .../Strings/fr/Resources.resw | 46 ++- .../Strings/hi/Resources.resw | 46 ++- .../Strings/id/Resources.resw | 46 ++- .../Strings/ja/Resources.resw | 46 ++- .../Strings/ko/Resources.resw | 46 ++- .../Strings/ms/Resources.resw | 46 ++- .../Strings/pt/Resources.resw | 46 ++- .../Strings/ru/Resources.resw | 46 ++- .../Strings/th/Resources.resw | 46 ++- .../Strings/vi/Resources.resw | 46 ++- .../Strings/zh-Hans/Resources.resw | 46 ++- .../Strings/zh-Hant/Resources.resw | 46 ++- .../Views/SettingsPage.xaml | 11 + BetterLyrics.sln | 28 ++ Community/plugins-registry.json | 1 + Community/scripts/check-hash-collision.js | 40 ++ .../Extensions/StringExtension.cs | 13 + RomajiConverter.Core/Helpers/KanaHelper.cs | 203 ++++++++++ RomajiConverter.Core/Helpers/LrcParser.cs | 41 ++ .../Helpers/RomajiAIHelper.cs | 239 +++++++++++ RomajiConverter.Core/Helpers/RomajiHelper.cs | 372 ++++++++++++++++++ RomajiConverter.Core/Models/ConvertedLine.cs | 18 + RomajiConverter.Core/Models/ConvertedUnit.cs | 125 ++++++ RomajiConverter.Core/Models/ReplaceString.cs | 23 ++ .../Options/ToRomajiAIOptions.cs | 16 + .../Options/ToRomajiOptions.cs | 9 + .../RomajiConverter.Core.csproj | 25 ++ .../RomajiConverter.Core.targets | 13 + RomajiConverter.Core/docs/README.md | 58 +++ 53 files changed, 2391 insertions(+), 299 deletions(-) create mode 100644 .github/workflows/plugin-registry-check.yml rename .github/workflows/{releases-to-discord.yml => release-to-discord.yml} (100%) rename BetterLyrics.Core/Interfaces/{ILyricsProvider.cs => ILyricsSearchPlugin.cs} (68%) create mode 100644 BetterLyrics.Core/Interfaces/ILyricsTransliterationPlugin.cs create mode 100644 BetterLyrics.Core/Interfaces/IPlugin.cs create mode 100644 BetterLyrics.Plugins.Romaji/BetterLyrics.Plugins.Romaji.csproj create mode 100644 BetterLyrics.Plugins.Romaji/RomajiPlugin.cs create mode 100644 BetterLyrics.Plugins.Romaji/customizeDict.txt create mode 100644 BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PluginManagerControl.xaml create mode 100644 BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PluginManagerControl.xaml.cs create mode 100644 BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/PluginDisplayModel.cs create mode 100644 Community/plugins-registry.json create mode 100644 Community/scripts/check-hash-collision.js create mode 100644 RomajiConverter.Core/Extensions/StringExtension.cs create mode 100644 RomajiConverter.Core/Helpers/KanaHelper.cs create mode 100644 RomajiConverter.Core/Helpers/LrcParser.cs create mode 100644 RomajiConverter.Core/Helpers/RomajiAIHelper.cs create mode 100644 RomajiConverter.Core/Helpers/RomajiHelper.cs create mode 100644 RomajiConverter.Core/Models/ConvertedLine.cs create mode 100644 RomajiConverter.Core/Models/ConvertedUnit.cs create mode 100644 RomajiConverter.Core/Models/ReplaceString.cs create mode 100644 RomajiConverter.Core/Options/ToRomajiAIOptions.cs create mode 100644 RomajiConverter.Core/Options/ToRomajiOptions.cs create mode 100644 RomajiConverter.Core/RomajiConverter.Core.csproj create mode 100644 RomajiConverter.Core/RomajiConverter.Core.targets create mode 100644 RomajiConverter.Core/docs/README.md diff --git a/.github/workflows/plugin-registry-check.yml b/.github/workflows/plugin-registry-check.yml new file mode 100644 index 0000000..e89fb66 --- /dev/null +++ b/.github/workflows/plugin-registry-check.yml @@ -0,0 +1,20 @@ +name: Plugin Registry Check + +on: + pull_request: + paths: + - 'Community/plugins-registry.json' + +jobs: + check-collision: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Run Hash Collision Check + run: node Community/scripts/check-hash-collision.js diff --git a/.github/workflows/releases-to-discord.yml b/.github/workflows/release-to-discord.yml similarity index 100% rename from .github/workflows/releases-to-discord.yml rename to .github/workflows/release-to-discord.yml diff --git a/BetterLyrics.Core/Interfaces/ILyricsProvider.cs b/BetterLyrics.Core/Interfaces/ILyricsSearchPlugin.cs similarity index 68% rename from BetterLyrics.Core/Interfaces/ILyricsProvider.cs rename to BetterLyrics.Core/Interfaces/ILyricsSearchPlugin.cs index ce97800..cb957ed 100644 --- a/BetterLyrics.Core/Interfaces/ILyricsProvider.cs +++ b/BetterLyrics.Core/Interfaces/ILyricsSearchPlugin.cs @@ -5,12 +5,8 @@ using System.Text; namespace BetterLyrics.Core.Interfaces { - public interface ILyricsProvider + public interface ILyricsSearchPlugin : IPlugin { - string Id { get; } - string Name { get; } - string Author { get; } - Task GetLyricsAsync(string title, string artist, string album, double duration); } } diff --git a/BetterLyrics.Core/Interfaces/ILyricsTransliterationPlugin.cs b/BetterLyrics.Core/Interfaces/ILyricsTransliterationPlugin.cs new file mode 100644 index 0000000..5aaad32 --- /dev/null +++ b/BetterLyrics.Core/Interfaces/ILyricsTransliterationPlugin.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BetterLyrics.Core.Interfaces +{ + public interface ILyricsTransliterationPlugin : IPlugin + { + Task GetTransliterationAsync(string text, string targetLangCode); + } +} diff --git a/BetterLyrics.Core/Interfaces/IPlugin.cs b/BetterLyrics.Core/Interfaces/IPlugin.cs new file mode 100644 index 0000000..06332ca --- /dev/null +++ b/BetterLyrics.Core/Interfaces/IPlugin.cs @@ -0,0 +1,17 @@ +using BetterLyrics.Core.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BetterLyrics.Core.Interfaces +{ + public interface IPlugin + { + string Id { get; } + string Name { get; } + string Description { get; } + string Author { get; } + + void Initialize(); + } +} diff --git a/BetterLyrics.Plugins.Demo/DemoLyricsProvider.cs b/BetterLyrics.Plugins.Demo/DemoLyricsProvider.cs index ce1cb78..d8bb179 100644 --- a/BetterLyrics.Plugins.Demo/DemoLyricsProvider.cs +++ b/BetterLyrics.Plugins.Demo/DemoLyricsProvider.cs @@ -3,12 +3,16 @@ using BetterLyrics.Core.Models; namespace BetterLyrics.Plugins.Demo { - public class DemoLyricsProvider : ILyricsProvider + public class DemoLyricsProvider : ILyricsSearchPlugin { public string Id => "f7acc86b-6e3d-42c3-a9a9-8c05c5339412"; - public string Name => "Demo Plugin"; + public string Name => "Plugin name"; public string Author => "jayfunc"; + public string Description => "Plugin description"; + + public void Initialize() { } + public async Task GetLyricsAsync(string title, string artist, string album, double duration) { await Task.Delay(300); diff --git a/BetterLyrics.Plugins.Romaji/BetterLyrics.Plugins.Romaji.csproj b/BetterLyrics.Plugins.Romaji/BetterLyrics.Plugins.Romaji.csproj new file mode 100644 index 0000000..7e8c132 --- /dev/null +++ b/BetterLyrics.Plugins.Romaji/BetterLyrics.Plugins.Romaji.csproj @@ -0,0 +1,101 @@ + + + + net10.0 + enable + enable + + + + + contentFiles\any\any\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + contentFiles\any\any\unidic\ + Always + true + true + + + + + + + + + diff --git a/BetterLyrics.Plugins.Romaji/RomajiPlugin.cs b/BetterLyrics.Plugins.Romaji/RomajiPlugin.cs new file mode 100644 index 0000000..6b7ed9b --- /dev/null +++ b/BetterLyrics.Plugins.Romaji/RomajiPlugin.cs @@ -0,0 +1,34 @@ +using BetterLyrics.Core.Interfaces; +using RomajiConverter.Core.Helpers; +using System.Reflection; + +namespace BetterLyrics.Plugins.Romaji +{ + public class RomajiPlugin : ILyricsTransliterationPlugin + { + public string Id => "jayfunc.romaji"; + + public string Name => "Romaji"; + + public string Description => "Convert Japanese lyrics to Romaji transliteration."; + + public string Author => "jayfunc"; + + public void Initialize() + { + string? pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + RomajiHelper.Init(pluginPath); + } + + public Task GetTransliterationAsync(string text, string targetLangCode) + { + string? result = null; + if (targetLangCode == "ja-latin") + { + var lines = RomajiHelper.ToRomaji(text); + result = string.Join("\r\n", lines.Select(p => string.Join(" ", p.Units.Select(q => q.Romaji)))); + } + return Task.FromResult(result); + } + } +} diff --git a/BetterLyrics.Plugins.Romaji/customizeDict.txt b/BetterLyrics.Plugins.Romaji/customizeDict.txt new file mode 100644 index 0000000..783d573 --- /dev/null +++ b/BetterLyrics.Plugins.Romaji/customizeDict.txt @@ -0,0 +1 @@ +私 わたし \ No newline at end of file diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs index a3f57e8..968bbbe 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs @@ -155,6 +155,10 @@ namespace BetterLyrics.WinUI3 } fileSystemService.StartAllFolderTimers(); + // Ensure plugins + var pluginService = Ioc.Default.GetRequiredService(); + pluginService.LoadPlugins(); + // Init system tray m_window = WindowHook.OpenOrShowWindow(); diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj index 4b28fd7..8d49504 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj @@ -45,6 +45,7 @@ + @@ -271,6 +272,11 @@ Always + + + MSBuild:Compile + + MSBuild:Compile diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PluginManagerControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PluginManagerControl.xaml new file mode 100644 index 0000000..cbedeec --- /dev/null +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/PluginManagerControl.xaml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +