From 5989c4305518174717c6c03ac06e3a199b6518fe Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Mon, 10 Mar 2025 11:59:56 +0800 Subject: [PATCH 1/4] Add FLLUseDependencyInjection property group --- ...low.Launcher.Localization.Analyzers.csproj | 4 + .../Localize/ContextAvailabilityAnalyzer.cs | 17 +-- .../OldGetTranslateAnalyzerCodeFixProvider.cs | 1 - .../Constants.cs | 18 +++ .../Flow.Launcher.Localization.Shared.csproj | 14 +++ Flow.Launcher.Localization.Shared/Helper.cs | 17 +++ ...ncher.Localization.SourceGenerators.csproj | 4 + .../Localize/LocalizeSourceGenerator.cs | 113 ++++++++---------- Flow.Launcher.Localization.slnx | 1 + .../Flow.Launcher.Localization.csproj | 72 +++++------ 10 files changed, 159 insertions(+), 102 deletions(-) create mode 100644 Flow.Launcher.Localization.Shared/Constants.cs create mode 100644 Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj create mode 100644 Flow.Launcher.Localization.Shared/Helper.cs diff --git a/Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj b/Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj index ce219d0..523f664 100644 --- a/Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj +++ b/Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj @@ -16,4 +16,8 @@ + + + + diff --git a/Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs b/Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs index 8123d25..72a2775 100644 --- a/Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs +++ b/Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using System.Linq; +using Flow.Launcher.Localization.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -17,10 +18,6 @@ public class ContextAvailabilityAnalyzer : DiagnosticAnalyzer AnalyzerDiagnostics.ContextIsNotDeclared ); - private const string PluginContextTypeName = "PluginInitContext"; - - private const string PluginInterfaceName = "IPluginI18n"; - public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); @@ -30,6 +27,12 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { + var configOptions = context.Options.AnalyzerConfigOptionsProvider; + var useDI = configOptions.GetFLLUseDependencyInjection(); + + // If we use dependency injection, we don't need to check for this context property + if (useDI) return; + var classDeclaration = (ClassDeclarationSyntax)context.Node; var semanticModel = context.SemanticModel; var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration); @@ -38,7 +41,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) var contextProperty = classDeclaration.Members.OfType() .Select(p => semanticModel.GetDeclaredSymbol(p)) - .FirstOrDefault(p => p?.Type.Name is PluginContextTypeName); + .FirstOrDefault(p => p?.Type.Name is Constants.PluginContextTypeName); if (contextProperty != null) { @@ -67,7 +70,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) .OfType() .SelectMany(f => f.Declaration.Variables) .Select(f => semanticModel.GetDeclaredSymbol(f)) - .FirstOrDefault(f => f is IFieldSymbol fs && fs.Type.Name is PluginContextTypeName); + .FirstOrDefault(f => f is IFieldSymbol fs && fs.Type.Name is Constants.PluginContextTypeName); var parentSyntax = fieldDeclaration ?.DeclaringSyntaxReferences[0] .GetSyntax() @@ -89,6 +92,6 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context) } private static bool IsPluginEntryClass(INamedTypeSymbol namedTypeSymbol) => - namedTypeSymbol?.Interfaces.Any(i => i.Name == PluginInterfaceName) ?? false; + namedTypeSymbol?.Interfaces.Any(i => i.Name == Constants.PluginInterfaceName) ?? false; } } diff --git a/Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs b/Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs index 37552ce..1040270 100644 --- a/Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs +++ b/Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs @@ -109,6 +109,5 @@ InvocationExpressionSyntax invocationExpr var newRoot = root.ReplaceNode(invocationExpr, newInnerInvocationExpr); return context.Document.WithSyntaxRoot(newRoot); } - } } diff --git a/Flow.Launcher.Localization.Shared/Constants.cs b/Flow.Launcher.Localization.Shared/Constants.cs new file mode 100644 index 0000000..341c0b2 --- /dev/null +++ b/Flow.Launcher.Localization.Shared/Constants.cs @@ -0,0 +1,18 @@ +using System.Text.RegularExpressions; + +namespace Flow.Launcher.Localization.Shared +{ + public static class Constants + { + public const string DefaultNamespace = "Flow.Launcher"; + public const string ClassName = "Localize"; + public const string PluginInterfaceName = "IPluginI18n"; + public const string PluginContextTypeName = "PluginInitContext"; + public const string SystemPrefixUri = "clr-namespace:System;assembly=mscorlib"; + public const string XamlPrefixUri = "http://schemas.microsoft.com/winfx/2006/xaml"; + public const string XamlTag = "String"; + public const string KeyTag = "Key"; + + public static readonly Regex LanguagesXamlRegex = new Regex(@"\\Languages\\[^\\]+\.xaml$", RegexOptions.IgnoreCase); + } +} diff --git a/Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj b/Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj new file mode 100644 index 0000000..ae15976 --- /dev/null +++ b/Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj @@ -0,0 +1,14 @@ + + + + 0.0.1 + netstandard2.0 + true + Flow.Launcher.Localization.Shared + + + + + + + diff --git a/Flow.Launcher.Localization.Shared/Helper.cs b/Flow.Launcher.Localization.Shared/Helper.cs new file mode 100644 index 0000000..94b186c --- /dev/null +++ b/Flow.Launcher.Localization.Shared/Helper.cs @@ -0,0 +1,17 @@ +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Flow.Launcher.Localization.Shared +{ + public static class Helper + { + public static bool GetFLLUseDependencyInjection(this AnalyzerConfigOptionsProvider configOptions) + { + if (!configOptions.GlobalOptions.TryGetValue("build_property.FLLUseDependencyInjection", out var result) || + !bool.TryParse(result, out var useDI)) + { + return false; // Default to false + } + return useDI; + } + } +} diff --git a/Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj b/Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj index 40d585d..db8fa41 100644 --- a/Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj +++ b/Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj @@ -14,5 +14,9 @@ + + + + diff --git a/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs b/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs index 9a52e3e..0feb23c 100644 --- a/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs +++ b/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs @@ -3,12 +3,13 @@ using System.Collections.Immutable; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Xml.Linq; +using Flow.Launcher.Localization.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; namespace Flow.Launcher.Localization.SourceGenerators.Localize @@ -21,19 +22,6 @@ public partial class LocalizeSourceGenerator : IIncrementalGenerator { #region Fields - private const string CoreNamespace1 = "Flow.Launcher"; - private const string CoreNamespace2 = "Flow.Launcher.Core"; - private const string DefaultNamespace = "Flow.Launcher"; - private const string ClassName = "Localize"; - private const string PluginInterfaceName = "IPluginI18n"; - private const string PluginContextTypeName = "PluginInitContext"; - private const string systemPrefixUri = "clr-namespace:System;assembly=mscorlib"; - private const string xamlPrefixUri = "http://schemas.microsoft.com/winfx/2006/xaml"; - private const string XamlTag = "String"; - private const string KeyTag = "Key"; - - private static readonly Regex _languagesXamlRegex = new Regex(@"\\Languages\\[^\\]+\.xaml$", RegexOptions.IgnoreCase); - private static readonly Version PackageVersion = typeof(LocalizeSourceGenerator).Assembly.GetName().Version; private static readonly ImmutableArray _emptyLocalizableStrings = ImmutableArray.Empty; @@ -50,7 +38,7 @@ public partial class LocalizeSourceGenerator : IIncrementalGenerator public void Initialize(IncrementalGeneratorInitializationContext context) { var xamlFiles = context.AdditionalTextsProvider - .Where(file => _languagesXamlRegex.IsMatch(file.Path)); + .Where(file => Constants.LanguagesXamlRegex.IsMatch(file.Path)); var localizedStrings = xamlFiles .Select((file, ct) => ParseXamlFile(file, ct)) @@ -75,7 +63,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var compilation = context.CompilationProvider; - var combined = localizedStrings.Combine(invocationKeys).Combine(pluginClasses).Combine(compilation).Combine(xamlFiles.Collect()); + var configOptions = context.AnalyzerConfigOptionsProvider; + + var combined = localizedStrings.Combine(invocationKeys).Combine(pluginClasses).Combine(configOptions).Combine(compilation).Combine(xamlFiles.Collect()); context.RegisterSourceOutput(combined, Execute); } @@ -86,10 +76,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) /// The source production context. /// The provided data. private void Execute(SourceProductionContext spc, - ((((ImmutableArray LocalizableStrings, - ImmutableHashSet InvocationKeys), - ImmutableArray PluginClassInfos), - Compilation Compilation), + (((((ImmutableArray LocalizableStrings, + ImmutableHashSet InvocationKeys), + ImmutableArray PluginClassInfos), + AnalyzerConfigOptionsProvider ConfigOptionsProvider), + Compilation Compilation), ImmutableArray AdditionalTexts) data) { var xamlFiles = data.AdditionalTexts; @@ -103,23 +94,28 @@ private void Execute(SourceProductionContext spc, } var compilation = data.Item1.Compilation; - var pluginClasses = data.Item1.Item1.PluginClassInfos; - var usedKeys = data.Item1.Item1.Item1.InvocationKeys; - var localizedStrings = data.Item1.Item1.Item1.LocalizableStrings; + var configOptions = data.Item1.Item1.ConfigOptionsProvider; + var pluginClasses = data.Item1.Item1.Item1.PluginClassInfos; + var usedKeys = data.Item1.Item1.Item1.Item1.InvocationKeys; + var localizedStrings = data.Item1.Item1.Item1.Item1.LocalizableStrings; - var assemblyName = compilation.AssemblyName ?? DefaultNamespace; + var assemblyName = compilation.AssemblyName ?? Constants.DefaultNamespace; var optimizationLevel = compilation.Options.OptimizationLevel; + var useDI = configOptions.GetFLLUseDependencyInjection(); - var pluginInfo = GetValidPluginInfo(pluginClasses, spc); - var isCoreAssembly = assemblyName == CoreNamespace1 || assemblyName == CoreNamespace2; - + PluginClassInfo pluginInfo = null; + if (!useDI) + { + pluginInfo = GetValidPluginInfo(pluginClasses, spc); + } + GenerateSource( spc, xamlFiles[0], localizedStrings, optimizationLevel, assemblyName, - isCoreAssembly, + useDI, pluginInfo, usedKeys); } @@ -155,11 +151,11 @@ private static ImmutableArray ParseXamlFile(AdditionalText fi string uri = attr.Value; string prefix = attr.Name.LocalName; - if (uri == systemPrefixUri) + if (uri == Constants.SystemPrefixUri) { systemPrefix = prefix; } - else if (uri == xamlPrefixUri) + else if (uri == Constants.XamlPrefixUri) { xamlPrefix = prefix; } @@ -179,14 +175,14 @@ private static ImmutableArray ParseXamlFile(AdditionalText fi } var localizableStrings = new List(); - foreach (var element in doc.Descendants(systemNs + XamlTag)) // "String" elements in system namespace + foreach (var element in doc.Descendants(systemNs + Constants.XamlTag)) // "String" elements in system namespace { if (ct.IsCancellationRequested) { return _emptyLocalizableStrings; } - var key = element.Attribute(xNs + KeyTag)?.Value; // "Key" attribute in xaml namespace + var key = element.Attribute(xNs + Constants.KeyTag)?.Value; // "Key" attribute in xaml namespace var value = element.Value; var comment = element.PreviousNode as XComment; @@ -424,7 +420,7 @@ private static string GetLocalizationKeyFromInvocation(GeneratorSyntaxContext co parts.Reverse(); // Check if the first part is ClassName and there's at least one more part - if (parts.Count < 2 || parts[0] != ClassName) + if (parts.Count < 2 || parts[0] != Constants.ClassName) { return null; } @@ -440,7 +436,7 @@ private static PluginClassInfo GetPluginClassInfo(GeneratorSyntaxContext context { var classDecl = (ClassDeclarationSyntax)context.Node; var location = GetLocation(context.SemanticModel.SyntaxTree, classDecl); - if (!classDecl.BaseList?.Types.Any(t => t.Type.ToString() == PluginInterfaceName) ?? true) + if (!classDecl.BaseList?.Types.Any(t => t.Type.ToString() == Constants.PluginInterfaceName) ?? true) { // Cannot find class that implements IPluginI18n return null; @@ -448,7 +444,7 @@ private static PluginClassInfo GetPluginClassInfo(GeneratorSyntaxContext context var property = classDecl.Members .OfType() - .FirstOrDefault(p => p.Type.ToString() == PluginContextTypeName); + .FirstOrDefault(p => p.Type.ToString() == Constants.PluginContextTypeName); if (property is null) { // Cannot find context @@ -532,7 +528,7 @@ private static void GenerateSource( ImmutableArray localizedStrings, OptimizationLevel optimizationLevel, string assemblyName, - bool isCoreAssembly, + bool useDI, PluginClassInfo pluginInfo, IEnumerable usedKeys) { @@ -560,13 +556,6 @@ private static void GenerateSource( GeneratedHeaderFromPath(sourceBuilder, xamlFile.Path); sourceBuilder.AppendLine(); - // Generate usings - if (isCoreAssembly) - { - sourceBuilder.AppendLine("using Flow.Launcher.Core.Resource;"); - sourceBuilder.AppendLine(); - } - // Generate nullable enable sourceBuilder.AppendLine("#nullable enable"); sourceBuilder.AppendLine(); @@ -603,11 +592,26 @@ private static void GenerateSource( // Generate class sourceBuilder.AppendLine($"[System.CodeDom.Compiler.GeneratedCode(\"{nameof(LocalizeSourceGenerator)}\", \"{PackageVersion}\")]"); - sourceBuilder.AppendLine($"public static class {ClassName}"); + sourceBuilder.AppendLine($"public static class {Constants.ClassName}"); sourceBuilder.AppendLine("{"); - // Generate localization methods var tabString = Spacing(1); + + // Generate API instance + string getTranslation = null; + if (useDI) + { + sourceBuilder.AppendLine($"{tabString}private static Flow.Launcher.Plugin.IPublicAPI? api = null;"); + sourceBuilder.AppendLine($"{tabString}private static Flow.Launcher.Plugin.IPublicAPI Api => api ??= CommunityToolkit.Mvvm.DependencyInjection.Ioc.Default.GetRequiredService();"); + sourceBuilder.AppendLine(); + getTranslation = "Api.GetTranslation"; + } + else if (pluginInfo?.IsValid == true) + { + getTranslation = $"{pluginInfo.ContextAccessor}.API.GetTranslation"; + } + + // Generate localization methods foreach (var ls in localizedStrings) { // TODO: Add support for usedKeys @@ -617,13 +621,13 @@ private static void GenerateSource( }*/ GenerateDocComments(sourceBuilder, ls, tabString); - GenerateLocalizationMethod(sourceBuilder, ls, isCoreAssembly, pluginInfo, tabString); + GenerateLocalizationMethod(sourceBuilder, ls, getTranslation, tabString); } sourceBuilder.AppendLine("}"); // Add source to context - spc.AddSource($"{ClassName}.{assemblyName}.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); + spc.AddSource($"{Constants.ClassName}.{assemblyName}.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); } private static void GeneratedHeaderFromPath(StringBuilder sb, string xamlFilePath) @@ -673,8 +677,7 @@ private static void GenerateDocComments(StringBuilder sb, LocalizableString ls, private static void GenerateLocalizationMethod( StringBuilder sb, LocalizableString ls, - bool isCoreAssembly, - PluginClassInfo pluginInfo, + string getTranslation, string tabString) { sb.Append($"{tabString}public static string {ls.Key}("); @@ -687,18 +690,8 @@ private static void GenerateLocalizationMethod( ? $", {string.Join(", ", parameters.Select(p => p.Name))}" : string.Empty; - if (isCoreAssembly) - { - var getTranslation = "InternationalizationManager.Instance.GetTranslation"; - sb.AppendLine(parameters.Count > 0 - ? !ls.Format ? - $"string.Format({getTranslation}(\"{ls.Key}\"){formatArgs});" - : $"string.Format(System.Globalization.CultureInfo.CurrentCulture, {getTranslation}(\"{ls.Key}\"){formatArgs});" - : $"{getTranslation}(\"{ls.Key}\");"); - } - else if (pluginInfo?.IsValid == true) + if (!(string.IsNullOrEmpty(getTranslation))) { - var getTranslation = $"{pluginInfo.ContextAccessor}.API.GetTranslation"; sb.AppendLine(parameters.Count > 0 ? !ls.Format ? $"string.Format({getTranslation}(\"{ls.Key}\"){formatArgs});" diff --git a/Flow.Launcher.Localization.slnx b/Flow.Launcher.Localization.slnx index dc9bd15..27c8f44 100644 --- a/Flow.Launcher.Localization.slnx +++ b/Flow.Launcher.Localization.slnx @@ -1,5 +1,6 @@ + diff --git a/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj b/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj index e2f86be..7214d3a 100644 --- a/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj +++ b/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj @@ -1,41 +1,45 @@  - - 0.0.1 - netstandard2.0 - true - Flow.Launcher.Localization + + 0.0.1 + netstandard2.0 + true + Flow.Launcher.Localization - false - true - true - true - + false + true + true + true + - - - - + + + All + + + All + + + All + + - - - - + + + true + analyzers/dotnet/cs + false + + + true + analyzers/dotnet/cs + false + + + true + analyzers/dotnet/cs + false + + From ae8403f96371c6c34cbec2131e5dcfc366225212 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Mon, 10 Mar 2025 14:38:25 +0600 Subject: [PATCH 2/4] Add .props file to automatically allow reading FLLUsePropertyInjection value --- Flow.Launcher.Localization/Flow.Launcher.Localization.csproj | 1 + .../build/Flow.Launcher.Localization.props | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 Flow.Launcher.Localization/build/Flow.Launcher.Localization.props diff --git a/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj b/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj index 7214d3a..03db6d9 100644 --- a/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj +++ b/Flow.Launcher.Localization/Flow.Launcher.Localization.csproj @@ -40,6 +40,7 @@ analyzers/dotnet/cs false + diff --git a/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props b/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props new file mode 100644 index 0000000..ff97093 --- /dev/null +++ b/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props @@ -0,0 +1,5 @@ + + + + + From 8ce1201d3b282fe9a493bc43745f9a39e648afed Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Mon, 10 Mar 2025 16:57:29 +0800 Subject: [PATCH 3/4] Change constant name --- Flow.Launcher.Localization.Shared/Constants.cs | 2 +- .../Localize/LocalizeSourceGenerator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Localization.Shared/Constants.cs b/Flow.Launcher.Localization.Shared/Constants.cs index 341c0b2..beac8aa 100644 --- a/Flow.Launcher.Localization.Shared/Constants.cs +++ b/Flow.Launcher.Localization.Shared/Constants.cs @@ -11,7 +11,7 @@ public static class Constants public const string SystemPrefixUri = "clr-namespace:System;assembly=mscorlib"; public const string XamlPrefixUri = "http://schemas.microsoft.com/winfx/2006/xaml"; public const string XamlTag = "String"; - public const string KeyTag = "Key"; + public const string KeyAttribute = "Key"; public static readonly Regex LanguagesXamlRegex = new Regex(@"\\Languages\\[^\\]+\.xaml$", RegexOptions.IgnoreCase); } diff --git a/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs b/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs index 0feb23c..583ea8d 100644 --- a/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs +++ b/Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs @@ -182,7 +182,7 @@ private static ImmutableArray ParseXamlFile(AdditionalText fi return _emptyLocalizableStrings; } - var key = element.Attribute(xNs + Constants.KeyTag)?.Value; // "Key" attribute in xaml namespace + var key = element.Attribute(xNs + Constants.KeyAttribute)?.Value; // "Key" attribute in xaml namespace var value = element.Value; var comment = element.PreviousNode as XComment; From fdf2cb166ff375cde72e11d8359aec4141e4aba0 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Mon, 10 Mar 2025 15:59:14 +0600 Subject: [PATCH 4/4] Add Languages\en.xaml to .props file --- .../build/Flow.Launcher.Localization.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props b/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props index ff97093..80b3641 100644 --- a/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props +++ b/Flow.Launcher.Localization/build/Flow.Launcher.Localization.props @@ -1,5 +1,6 @@  +