Compare commits

...

5 commits

Author SHA1 Message Date
github-actions[bot]
fa13139754 doc: Update translation status and missing keys 2024-10-27 18:07:27 +00:00
Douglas Cunha
3a0ae1c6e0
feat: support language for commit message generation
- Extend the GenerateCommitMessage constructor to include a language parameter and use it in the selected language prompt logic.
- Add property for commit message language with default value "English".
- Add integration related configuration strings for commit message language.
- Add property for CommitMessageLanguage in RepositoryConfigure.
- Add language parameter to AIAssistant constructor and propagate it to GenerateCommitMessage.
- Add integration configuration options in the repository settings view.
2024-10-27 15:08:54 -03:00
Douglas Cunha
ac543dbe07
Merge branch 'develop' into custom 2024-10-27 13:09:11 -03:00
Douglas Cunha
e7ac482490
Merge branch 'develop' into custom 2024-10-25 09:49:03 -03:00
Douglas Cunha
c6d308be2c
feat: Add dynamic language support in commit message generation with OpenAI
- Add support for dynamic language prompts in commit message generation.
- Add property to store selected language in OpenAI model.
- Add new icon definition for language selection in the icon resource file.
- Add localization string for the tip regarding the selected language in the OpenAI Assistant feature.
- Add OpenAI assistant strings for commit message generation in Brazilian Portuguese localization.
- Add SelectedLanguage property to manage language preference.
- Add method to create context menu for selecting language.
- Refactor tooltips and adjust button layouts for better alignment and additional functionality.
- Add a method to open a context menu for language selection in the WorkingCopy view.

Signed-off-by: Douglas Cunha <dougcunha@gmail.com>
2024-10-24 18:35:50 -03:00
10 changed files with 91 additions and 17 deletions

View file

@ -43,7 +43,7 @@
## Translation Status
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.95%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-90.36%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-93.52%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.80%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-99.10%25-yellow)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-98.65%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-90.09%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-93.84%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.50%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-98.80%25-yellow)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-99.70%25-yellow)](TRANSLATION.md)
## How to Use

View file

@ -1,10 +1,12 @@
### de_DE.axaml: 98.95%
### de_DE.axaml: 98.65%
<details>
<summary>Missing Keys</summary>
- Text.Configure.Git.EnableSignOff
- Text.Configure.Integration
- Text.Configure.Integration.Language
- Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.Preference.Advanced
@ -14,7 +16,7 @@
</details>
### fr_FR.axaml: 90.36%
### fr_FR.axaml: 90.09%
<details>
@ -31,6 +33,8 @@
- Text.CommitDetail.Info.WebLinks
- Text.Configure.Git.DefaultRemote
- Text.Configure.Git.EnableSignOff
- Text.Configure.Integration
- Text.Configure.Integration.Language
- Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.ConfigureWorkspace
@ -87,15 +91,13 @@
</details>
### pt_BR.axaml: 93.52%
### pt_BR.axaml: 93.84%
<details>
<summary>Missing Keys</summary>
- Text.About.Chart
- Text.AIAssistant
- Text.AIAssistant.Tip
- Text.CherryPick.AppendSourceToMessage
- Text.CherryPick.Mainline
- Text.CherryPick.Mainline.Tips
@ -139,13 +141,15 @@
</details>
### ru_RU.axaml: 98.80%
### ru_RU.axaml: 98.50%
<details>
<summary>Missing Keys</summary>
- Text.Configure.Git.EnableSignOff
- Text.Configure.Integration
- Text.Configure.Integration.Language
- Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.Preference.Advanced
@ -156,12 +160,14 @@
</details>
### zh_CN.axaml: 99.10%
### zh_CN.axaml: 98.80%
<details>
<summary>Missing Keys</summary>
- Text.Configure.Integration
- Text.Configure.Integration.Language
- Text.Preference.AI
- Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.ApiKey
@ -171,12 +177,13 @@
</details>
### zh_TW.axaml: 100.00%
### zh_TW.axaml: 99.70%
<details>
<summary>Missing Keys</summary>
- Text.Configure.Integration
- Text.Configure.Integration.Language
</details>

View file

@ -20,9 +20,10 @@ namespace SourceGit.Commands
}
}
public GenerateCommitMessage(string repo, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress)
public GenerateCommitMessage(string repo, string language, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress)
{
_repo = repo;
_language = language ?? "English";
_changes = changes;
_cancelToken = cancelToken;
_onProgress = onProgress;
@ -70,12 +71,22 @@ namespace SourceGit.Commands
}
}
private string GetSelectedLanguagePrompt()
{
var selectedLanguage = _language == "English"
? string.Empty
: $"{Environment.NewLine}Always write in {_language}";
return selectedLanguage;
}
private string GenerateChangeSummary(Models.Change change)
{
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
var selectedLanguagePrompt = GetSelectedLanguagePrompt();
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt + selectedLanguagePrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
if (rsp != null && rsp.Choices.Count > 0)
return rsp.Choices[0].Message.Content;
@ -84,7 +95,8 @@ namespace SourceGit.Commands
private string GenerateSubject(string summary)
{
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
var selectedLanguagePrompt = GetSelectedLanguagePrompt();
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt + selectedLanguagePrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
if (rsp != null && rsp.Choices.Count > 0)
return rsp.Choices[0].Message.Content;
@ -95,5 +107,6 @@ namespace SourceGit.Commands
private List<Models.Change> _changes;
private CancellationToken _cancelToken;
private Action<string> _onProgress;
private readonly string _language;
}
}

View file

@ -112,6 +112,12 @@ namespace SourceGit.Models
set;
} = false;
public string CommitMessageLanguage
{
get;
set;
} = "English";
public void PushCommitMessage(string message)
{
var existIdx = CommitMessages.IndexOf(message);

View file

@ -144,6 +144,8 @@
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(s)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Default Remote</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Enable --signoff for commit</x:String>
<x:String x:Key="Text.Configure.Integration" xml:space="preserve">INTEGRATION</x:String>
<x:String x:Key="Text.Configure.Integration.Language" xml:space="preserve">Commit Message Language</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Add Sample Jira Rule</x:String>

View file

@ -20,6 +20,8 @@
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Branch Existente</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">O que Checar:</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Adicionar Worktree</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Assistente do OpenAI</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para gerar mensagem de commit</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Erros levantados e se recusa a aplicar o patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erro</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Semelhante a 'erro', mas mostra mais</x:String>
@ -133,6 +135,8 @@
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Buscar remotos automaticamente</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minuto(s)</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Integration" xml:space="preserve">INTEGRAÇÃO</x:String>
<x:String x:Key="Text.Configure.Integration.Language" xml:space="preserve">Idioma para mensagem de commit</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Adicionar Regra de Exemplo do Github</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Adicionar Regra de Exemplo do Jira</x:String>
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">Nova Regra</x:String>

View file

@ -86,6 +86,12 @@ namespace SourceGit.ViewModels
}
}
public string CommitMessageLanguage
{
get => _repo.Settings.CommitMessageLanguage;
set => _repo.Settings.CommitMessageLanguage = value;
}
public AvaloniaList<Models.CommitTemplate> CommitTemplates
{
get => _repo.Settings.CommitTemplates;

View file

@ -8,6 +8,7 @@ using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using SourceGit.Models;
namespace SourceGit.ViewModels
{
@ -413,7 +414,7 @@ namespace SourceGit.ViewModels
if (_staged is { Count: > 0 })
{
var dialog = new Views.AIAssistant(_repo.FullPath, _staged, generated => CommitMessage = generated);
var dialog = new Views.AIAssistant(_repo.FullPath, _repo.Settings.CommitMessageLanguage, _staged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
}
else
@ -1147,7 +1148,7 @@ namespace SourceGit.ViewModels
return menu;
}
public ContextMenu CreateContextMenuForCommitMessages()
public ContextMenu CreateContextMenuForCommitMessages()
{
var menu = new ContextMenu();

View file

@ -17,9 +17,10 @@ namespace SourceGit.Views
InitializeComponent();
}
public AIAssistant(string repo, List<Models.Change> changes, Action<string> onDone)
public AIAssistant(string repo, string language, List<Models.Change> changes, Action<string> onDone)
{
_repo = repo;
_language = language;
_changes = changes;
_onDone = onDone;
_cancel = new CancellationTokenSource();
@ -35,7 +36,7 @@ namespace SourceGit.Views
Task.Run(() =>
{
var message = new Commands.GenerateCommitMessage(_repo, _changes, _cancel.Token, SetDescription).Result();
var message = new Commands.GenerateCommitMessage(_repo, _language, _changes, _cancel.Token, SetDescription).Result();
if (_cancel.IsCancellationRequested)
return;
@ -67,5 +68,6 @@ namespace SourceGit.Views
private List<Models.Change> _changes;
private Action<string> _onDone;
private CancellationTokenSource _cancel;
private readonly string _language;
}
}

View file

@ -5,6 +5,7 @@
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RepositoryConfigure"
x:DataType="vm:RepositoryConfigure"
@ -340,6 +341,38 @@
</ContentControl>
</Grid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Integration}"/>
</TabItem.Header>
<StackPanel Margin="0" MaxWidth="580" Orientation="Vertical" Grid.IsSharedSizeScope="True">
<StackPanel Orientation="Horizontal" Margin="0,24,0,0">
<Path Width="12" Height="12" Data="{StaticResource Icons.AIAssist}"/>
<TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.AI}"/>
</StackPanel>
<Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/>
<Grid Margin="8,0,0,12" RowDefinitions="32,Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Configure.Integration.Language}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<ComboBox Grid.Row="0" Grid.Column="1"
MinHeight="28"
Padding="8,0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Source={x:Static m:Locale.Supported}}"
DisplayMemberBinding="{Binding Name, x:DataType=m:Locale}"
SelectedItem="{Binding CommitMessageLanguage, Mode=TwoWay, Converter={x:Static c:StringConverters.ToLocale}}"/>
</Grid>
</StackPanel>
</TabItem>
</TabControl>
</Grid>
</v:ChromelessWindow>