Skip to content

Commit c6d308b

Browse files
committed
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 <[email protected]>
1 parent 63f75dc commit c6d308b

File tree

9 files changed

+103
-10
lines changed

9 files changed

+103
-10
lines changed

src/Commands/GenerateCommitMessage.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,22 @@ public string Result()
7070
}
7171
}
7272

73+
private static string GetSelectedLanguagePrompt()
74+
{
75+
var selectedLanguage = Models.OpenAI.SelectedLanguage == "English"
76+
? string.Empty
77+
: $"{Environment.NewLine}Always write in {Models.OpenAI.SelectedLanguage}";
78+
79+
return selectedLanguage;
80+
}
81+
7382
private string GenerateChangeSummary(Models.Change change)
7483
{
7584
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
7685
var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
86+
var selectedLanguagePrompt = GetSelectedLanguagePrompt();
7787

78-
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
88+
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt + selectedLanguagePrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
7989
if (rsp != null && rsp.Choices.Count > 0)
8090
return rsp.Choices[0].Message.Content;
8191

@@ -84,7 +94,8 @@ private string GenerateChangeSummary(Models.Change change)
8494

8595
private string GenerateSubject(string summary)
8696
{
87-
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
97+
var selectedLanguagePrompt = GetSelectedLanguagePrompt();
98+
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt + selectedLanguagePrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
8899
if (rsp != null && rsp.Choices.Count > 0)
89100
return rsp.Choices[0].Message.Content;
90101

src/Models/OpenAI.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ public static string Model
9494
set;
9595
}
9696

97+
public static string SelectedLanguage
98+
{
99+
get;
100+
set;
101+
}
102+
97103
public static string AnalyzeDiffPrompt
98104
{
99105
get;

src/Resources/Icons.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<StreamGeometry x:Key="Icons.Init">M412 66C326 132 271 233 271 347c0 17 1 34 4 50-41-48-98-79-162-83a444 444 0 00-46 196c0 207 142 382 337 439h2c19 0 34 15 34 33 0 11-6 21-14 26l1 14C183 973 0 763 0 511 0 272 166 70 393 7A35 35 0 01414 0c19 0 34 15 34 33a33 33 0 01-36 33zm200 893c86-66 141-168 141-282 0-17-1-34-4-50 41 48 98 79 162 83a444 444 0 0046-196c0-207-142-382-337-439h-2a33 33 0 01-34-33c0-11 6-21 14-26L596 0C841 51 1024 261 1024 513c0 239-166 441-393 504A35 35 0 01610 1024a33 33 0 01-34-33 33 33 0 0136-33zM512 704a192 192 0 110-384 192 192 0 010 384z</StreamGeometry>
6262
<StreamGeometry x:Key="Icons.InteractiveRebase">M512 64A447 447 0 0064 512c0 248 200 448 448 448s448-200 448-448S760 64 512 64zM218 295h31c54 0 105 19 145 55 13 12 13 31 3 43a35 35 0 01-22 10 36 36 0 01-21-7 155 155 0 00-103-39h-31a32 32 0 01-31-31c0-18 13-31 30-31zm31 433h-31a32 32 0 01-31-31c0-16 13-31 31-31h31A154 154 0 00403 512 217 217 0 01620 295h75l-93-67a33 33 0 01-7-43 33 33 0 0143-7l205 148-205 148a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67H620a154 154 0 00-154 154c0 122-97 220-217 220zm390 118a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67h-75c-52 0-103-19-143-54-12-12-13-31-1-43a30 30 0 0142-3 151 151 0 00102 39h75L602 599a33 33 0 01-7-43 33 33 0 0143-7l205 148-203 151z</StreamGeometry>
6363
<StreamGeometry x:Key="Icons.Issue">M922 39H102A65 65 0 0039 106v609a65 65 0 0063 68h94v168a34 34 0 0019 31 30 30 0 0012 3 30 30 0 0022-10l182-192H922a65 65 0 0063-68V106A65 65 0 00922 39zM288 378h479a34 34 0 010 68H288a34 34 0 010-68zm0-135h479a34 34 0 010 68H288a34 34 0 010-68zm0 270h310a34 34 0 010 68H288a34 34 0 010-68z</StreamGeometry>
64+
<StreamGeometry x:Key="Icons.LanguageSelection">M480-120q-74.31 0-140-28.42-65.69-28.43-114.42-77.16-48.73-48.73-77.16-114.42Q120-405.69 120-480q0-74.54 28.42-140.12 28.43-65.57 77.16-114.3 48.73-48.73 114.42-77.16Q405.69-840 480-840q74.54 0 140.12 28.42 65.57 28.43 114.3 77.16 48.73 48.73 77.16 114.3Q840-554.54 840-480q0 74.31-28.42 140-28.43 65.69-77.16 114.42-48.73 48.73-114.3 77.16Q554.54-120 480-120Zm0-39.69q35.23-45.23 58.08-88.85 22.84-43.61 37.15-97.61H384.77q15.85 57.07 37.92 100.69 22.08 43.61 57.31 85.77Zm-50.92-6q-28-33-51.12-81.58-23.11-48.58-34.42-98.88H190.15q34.39 74.61 97.5 122.38 63.12 47.77 141.43 58.08Zm101.84 0q78.31-10.31 141.43-58.08 63.11-47.77 97.5-122.38H616.46q-15.15 51.07-38.27 99.65-23.11 48.58-47.27 80.81ZM173.85-386.15h161.38q-4.54-24.62-6.42-47.97-1.89-23.34-1.89-45.88 0-22.54 1.89-45.88 1.88-23.35 6.42-47.97H173.85q-6.54 20.77-10.2 45.27Q160-504.08 160-480t3.65 48.58q3.66 24.5 10.2 45.27Zm201.38 0h209.54q4.54-24.62 6.42-47.2 1.89-22.57 1.89-46.65t-1.89-46.65q-1.88-22.58-6.42-47.2H375.23q-4.54 24.62-6.42 47.2-1.89 22.57-1.89 46.65t1.89 46.65q1.88 22.58 6.42 47.2Zm249.54 0h161.38q6.54-20.77 10.2-45.27Q800-455.92 800-480t-3.65-48.58q-3.66-24.5-10.2-45.27H624.77q4.54 24.62 6.42 47.97 1.89 23.34 1.89 45.88 0 22.54-1.89 45.88-1.88 23.35-6.42 47.97Zm-8.31-227.7h153.39Q734.69-690 673.5-736.23q-61.19-46.23-142.58-58.85 28 36.85 50.35 84.27 22.35 47.43 35.19 96.96Zm-231.69 0h190.46q-15.85-56.3-39.08-101.84-23.23-45.54-56.15-84.62-32.92 39.08-56.15 84.62-23.23 45.54-39.08 101.84Zm-194.62 0h153.39q12.84-49.53 35.19-96.96 22.35-47.42 50.35-84.27-82.16 12.62-142.96 59.23-60.81 46.62-95.97 122Z</StreamGeometry>
6465
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
6566
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
6667
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
2020
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
2121
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI Assistant</x:String>
22+
<x:String x:Key="Text.AIAssistant.SelectedLanguageTip" xml:space="preserve">Language used to generate commit message</x:String>
2223
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use OpenAI to generate commit message</x:String>
2324
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
2425
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>

src/Resources/Locales/pt_BR.axaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Branch Existente</x:String>
2121
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">O que Checar:</x:String>
2222
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Adicionar Worktree</x:String>
23+
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Assistente do OpenAI</x:String>
24+
<x:String x:Key="Text.AIAssistant.SelectedLanguageTip" xml:space="preserve">Idioma usado a gerar a mensagem de commit</x:String>
25+
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para gerar mensagem de commit</x:String>
2326
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Erros levantados e se recusa a aplicar o patch</x:String>
2427
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erro</x:String>
2528
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Semelhante a 'erro', mas mostra mais</x:String>

src/ViewModels/Preference.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,19 @@ public string OpenAIModel
316316
}
317317
}
318318

319+
public string SelectedLanguage
320+
{
321+
get => Models.OpenAI.SelectedLanguage;
322+
set
323+
{
324+
if (value != Models.OpenAI.SelectedLanguage)
325+
{
326+
Models.OpenAI.SelectedLanguage = value;
327+
OnPropertyChanged();
328+
}
329+
}
330+
}
331+
319332
public string OpenAIAnalyzeDiffPrompt
320333
{
321334
get => Models.OpenAI.AnalyzeDiffPrompt;
@@ -591,6 +604,9 @@ Your only goal is to retrieve a single commit message.
591604
- Be as concise as possible, keep the message under 50 characters.
592605
""";
593606
}
607+
608+
if (string.IsNullOrEmpty(Models.OpenAI.SelectedLanguage))
609+
Models.OpenAI.SelectedLanguage = "English";
594610
}
595611

596612
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)

src/ViewModels/WorkingCopy.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Avalonia.Threading;
99

1010
using CommunityToolkit.Mvvm.ComponentModel;
11+
using SourceGit.Models;
1112

1213
namespace SourceGit.ViewModels
1314
{
@@ -1147,6 +1148,37 @@ public ContextMenu CreateContextMenuForStagedChanges()
11471148
return menu;
11481149
}
11491150

1151+
public ContextMenu CreateContextMenuForSelectedLanguage()
1152+
{
1153+
var menu = new ContextMenu();
1154+
var selectedLanguage = string.IsNullOrEmpty(Preference.Instance.SelectedLanguage)
1155+
? "English"
1156+
: Preference.Instance.SelectedLanguage;
1157+
1158+
foreach (var locale in Locale.Supported)
1159+
{
1160+
var language = locale.Name;
1161+
1162+
var item = new MenuItem
1163+
{
1164+
Header = language,
1165+
Icon = selectedLanguage.Equals(language, StringComparison.OrdinalIgnoreCase)
1166+
? App.CreateMenuIcon("Icons.Check")
1167+
: null
1168+
};
1169+
1170+
item.Click += (_, e) =>
1171+
{
1172+
Preference.Instance.SelectedLanguage = language;
1173+
e.Handled = true;
1174+
};
1175+
1176+
menu.Items.Add(item);
1177+
}
1178+
1179+
return menu;
1180+
}
1181+
11501182
public ContextMenu CreateContextMenuForCommitMessages()
11511183
{
11521184
var menu = new ContextMenu();

src/Views/WorkingCopy.axaml

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
Classes="icon_button"
5656
Width="26" Height="14"
5757
Padding="0"
58-
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"
58+
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"
5959
Command="{Binding StageAll}">
6060
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleDown}"/>
6161
</Button>
@@ -99,7 +99,7 @@
9999
<Button Grid.Column="6" Classes="icon_button" Width="26" Height="14" Padding="0" ToolTip.Tip="{DynamicResource Text.WorkingCopy.Staged.UnstageAll}" Command="{Binding UnstageAll}">
100100
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleUp}"/>
101101
</Button>
102-
<v:ChangeViewModeSwitcher Grid.Column="7"
102+
<v:ChangeViewModeSwitcher Grid.Column="7"
103103
Width="26" Height="14"
104104
Margin="0,1,0,0"
105105
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=StagedChangeViewMode, Mode=TwoWay}"/>
@@ -135,7 +135,7 @@
135135
<RowDefinition Height="128" MinHeight="100"/>
136136
<RowDefinition Height="36"/>
137137
</Grid.RowDefinitions>
138-
138+
139139
<!-- Select Change Detail -->
140140
<Grid Grid.Row="0">
141141
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
@@ -165,7 +165,7 @@
165165
<TextBlock Margin="0,16,0,8" FontSize="20" FontWeight="Bold" Text="{DynamicResource Text.WorkingCopy.Conflicts.Resolved}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
166166
<TextBlock Text="{DynamicResource Text.WorkingCopy.CanStageTip}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
167167
</StackPanel>
168-
</Grid>
168+
</Grid>
169169
</Border>
170170
</DataTemplate>
171171

@@ -185,7 +185,7 @@
185185
<v:CommitMessageTextBox Grid.Row="2" Text="{Binding CommitMessage, Mode=TwoWay}"/>
186186

187187
<!-- Commit Options -->
188-
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto">
188+
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto">
189189
<Button Grid.Column="0"
190190
Classes="icon_button"
191191
Margin="4,0,0,0" Padding="0"
@@ -206,7 +206,19 @@
206206
<Path Width="15" Height="15" Data="{StaticResource Icons.AIAssist}"/>
207207
</Button>
208208

209-
<Button Grid.Column="2"
209+
<Button Grid.Column="2"
210+
Classes="icon_button"
211+
Margin="0,2,0,0"
212+
ToolTip.Tip="{DynamicResource Text.AIAssistant.SelectedLanguageTip}"
213+
ToolTip.Placement="Top"
214+
Click="OnOpenSelectLanguage"
215+
ToolTip.VerticalOffset="0">
216+
<Path Width="15" Height="15" Data="{StaticResource Icons.LanguageSelection}"/>
217+
</Button>
218+
219+
220+
221+
<Button Grid.Column="3"
210222
Classes="icon_button"
211223
Margin="0,2,0,0"
212224
Click="OnOpenConventionalCommitHelper"
@@ -216,7 +228,7 @@
216228
<Path Width="15" Height="15" Data="{StaticResource Icons.CommitMessageGenerator}"/>
217229
</Button>
218230

219-
<CheckBox Grid.Column="3"
231+
<CheckBox Grid.Column="4"
220232
Height="24"
221233
Margin="8,0,0,0"
222234
HorizontalAlignment="Left"
@@ -248,7 +260,7 @@
248260
</StackPanel>
249261
</ToolTip.Tip>
250262
</Button>
251-
263+
252264
<!-- Invisible button just to add another hotkey `Ctrl+Shift+Enter` to commit with auto-stage -->
253265
<Button Grid.Column="7"
254266
Width="0" Height="0"

src/Views/WorkingCopy.axaml.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ private void OnOpenCommitMessagePicker(object sender, RoutedEventArgs e)
2222
}
2323
}
2424

25+
public void OnOpenSelectLanguage(object sender, RoutedEventArgs e)
26+
{
27+
if (sender is Button button && DataContext is ViewModels.WorkingCopy vm)
28+
{
29+
var menu = vm.CreateContextMenuForSelectedLanguage();
30+
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
31+
button.OpenContextMenu(menu);
32+
e.Handled = true;
33+
}
34+
}
35+
2536
private void OnUnstagedContextRequested(object sender, ContextRequestedEventArgs e)
2637
{
2738
if (DataContext is ViewModels.WorkingCopy vm)

0 commit comments

Comments
 (0)