translation using NGettext.Wpf
This commit is contained in:
@@ -165,11 +165,16 @@ public class GuiCommand
|
||||
proc.WaitForExit();
|
||||
|
||||
if (proc.ExitCode == 0)
|
||||
Msg.ShowInfo("File associations were successfully " +
|
||||
(perceivedType == "unreg" ? "removed" : "created") +
|
||||
".\n\nFile Explorer icons will refresh after process restart.");
|
||||
{
|
||||
string msgRestart = _("File Explorer icons will refresh after process restart.");
|
||||
|
||||
if (perceivedType == "unreg")
|
||||
Msg.ShowInfo(_("File associations were successfully removed.") + BR2 + msgRestart);
|
||||
else
|
||||
Msg.ShowInfo(_("File associations were successfully created.") + BR2 + msgRestart);
|
||||
}
|
||||
else
|
||||
Msg.ShowError("Error creating file associations.");
|
||||
Msg.ShowError(_("Error creating file associations."));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MpvNet\MpvNet.csproj" />
|
||||
<ProjectReference Include="..\NGettext.Wpf\NGettext.Wpf.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -32,8 +33,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
|
||||
@@ -6,6 +7,7 @@ using MpvNet.Windows.Native;
|
||||
using MpvNet.Help;
|
||||
using MpvNet.Windows.UI;
|
||||
using MpvNet.Windows.Help;
|
||||
using MpvNet.Windows.WPF;
|
||||
|
||||
namespace MpvNet.Windows;
|
||||
|
||||
@@ -17,6 +19,7 @@ static class Program
|
||||
try
|
||||
{
|
||||
RegistryHelp.ProductName = AppInfo.Product;
|
||||
Translator.Current = new WpfTranslator();
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
@@ -518,6 +518,16 @@ file = mpv
|
||||
directory = Input
|
||||
help = Number of key presses to generate per second on autorepeat.
|
||||
|
||||
name = language
|
||||
file = mpvnet
|
||||
default = system
|
||||
directory = UI
|
||||
help = User interface display language.\nmpv.net must be restarted after a change.
|
||||
option = system
|
||||
option = english
|
||||
option = chinese-china
|
||||
option = german
|
||||
|
||||
name = dark-mode
|
||||
file = mpvnet
|
||||
default = always
|
||||
|
||||
@@ -762,7 +762,7 @@ namespace HandyControl.Tools.Interop
|
||||
this.DataStream = dataStream ?? throw new ArgumentNullException(nameof(dataStream));
|
||||
}
|
||||
|
||||
private void ActualizeVirtualPosition()
|
||||
void ActualizeVirtualPosition()
|
||||
{
|
||||
if (_virtualPosition == -1) return;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public partial class InputWindow : Window
|
||||
else
|
||||
return item.Input.ToLower().Contains(searchText);
|
||||
}
|
||||
else if (searchText.StartsWith("m ") || searchText.StartsWith("m:"))
|
||||
else if (searchText.StartsWith("n ") || searchText.StartsWith("n:"))
|
||||
return item.Comment.ToLower().Contains(searchText.Substring(2).Trim());
|
||||
else if (searchText.StartsWith("c ") || searchText.StartsWith("c:"))
|
||||
return item.Command.ToLower().Contains(searchText.Substring(2).Trim());
|
||||
@@ -93,22 +93,7 @@ public partial class InputWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
CollectionView.Refresh();
|
||||
|
||||
if (SearchControl.SearchTextBox.Text == "?")
|
||||
{
|
||||
SearchControl.SearchTextBox.Text = "";
|
||||
|
||||
Msg.ShowInfo("Filtering" + BR2 +
|
||||
"Reduce the filter scope with:" + BR2 +
|
||||
"i input" + BR2 +
|
||||
"m menu" + BR2 +
|
||||
"c command" + BR2 +
|
||||
"If only one character is entered input search is performed.");
|
||||
}
|
||||
}
|
||||
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) => CollectionView.Refresh();
|
||||
|
||||
void Window_Loaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox);
|
||||
|
||||
@@ -132,7 +117,7 @@ public partial class InputWindow : Window
|
||||
File.WriteAllText(App.InputConf.Path, App.InputConf.Content = newContent);
|
||||
}
|
||||
|
||||
Msg.ShowInfo("Changes will be available on next startup.");
|
||||
Msg.ShowInfo(_("Changes will be available on next startup."));
|
||||
}
|
||||
|
||||
void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
|
||||
|
||||
@@ -350,7 +350,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
private void InitBottom(MessageBoxImage image)
|
||||
void InitBottom(MessageBoxImage image)
|
||||
{
|
||||
MessageBackground = (MessageBackground == null) ? new SolidColorBrush(Colors.White) : MessageBackground;
|
||||
MessageForeground = (MessageForeground == null) ? new SolidColorBrush(Colors.Black) : MessageForeground;
|
||||
@@ -498,7 +498,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
private void FindDefaultButtonEx(MessageBoxButtonDefault buttonDefault)
|
||||
void FindDefaultButtonEx(MessageBoxButtonDefault buttonDefault)
|
||||
{
|
||||
// determine default button
|
||||
IsDefaultOK = false;
|
||||
@@ -634,7 +634,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
private void FindDefaultButton(MessageBoxButtonDefault buttonDefault)
|
||||
void FindDefaultButton(MessageBoxButtonDefault buttonDefault)
|
||||
{
|
||||
// determine default button
|
||||
IsDefaultOK = false;
|
||||
@@ -735,7 +735,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnOK_Click(object sender, RoutedEventArgs e)
|
||||
void BtnOK_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.OK;
|
||||
this.MessageResultEx = MessageBoxResultEx.OK;
|
||||
@@ -747,7 +747,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnYes_Click(object sender, RoutedEventArgs e)
|
||||
void BtnYes_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.Yes;
|
||||
this.MessageResultEx = MessageBoxResultEx.Yes;
|
||||
@@ -759,28 +759,28 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnNo_Click(object sender, RoutedEventArgs e)
|
||||
void BtnNo_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.No;
|
||||
this.MessageResultEx = MessageBoxResultEx.No;
|
||||
this.DialogResult = true;
|
||||
}
|
||||
|
||||
private void BtnAbort_Click(object sender, RoutedEventArgs e)
|
||||
void BtnAbort_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.None;
|
||||
this.MessageResultEx = MessageBoxResultEx.Abort;
|
||||
this.DialogResult = true;
|
||||
}
|
||||
|
||||
private void BtnRetry_Click(object sender, RoutedEventArgs e)
|
||||
void BtnRetry_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.None;
|
||||
this.MessageResultEx = MessageBoxResultEx.Retry;
|
||||
this.DialogResult = true;
|
||||
}
|
||||
|
||||
private void BtnIgnore_Click(object sender, RoutedEventArgs e)
|
||||
void BtnIgnore_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.None;
|
||||
this.MessageResultEx = MessageBoxResultEx.Ignore;
|
||||
@@ -792,7 +792,7 @@ public partial class MessageBoxEx : Window, INotifyPropertyChanged
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnCancel_Click(object sender, RoutedEventArgs e)
|
||||
void BtnCancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.MessageResult = MessageBoxResult.Cancel;
|
||||
this.MessageResultEx = MessageBoxResultEx.Cancel;
|
||||
|
||||
63
src/MpvNet.Windows/WPF/WpfTranslator.cs
Normal file
63
src/MpvNet.Windows/WPF/WpfTranslator.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
using NGettext.Wpf;
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace MpvNet.Windows.WPF;
|
||||
|
||||
public class WpfTranslator : ITranslator
|
||||
{
|
||||
static Language[] Languages { get; } = new Language[] {
|
||||
new("english", "en", "en"),
|
||||
new("chinese-china", "zh-Hans", "zh"), // Chinese (Simplified)
|
||||
new("german", "de", "de"),
|
||||
};
|
||||
|
||||
public string Gettext(string msgId)
|
||||
{
|
||||
InitNGettextWpf();
|
||||
return Translation._(msgId);
|
||||
}
|
||||
|
||||
void InitNGettextWpf()
|
||||
{
|
||||
if (Translation.Localizer == null)
|
||||
CompositionRoot.Compose("mpvnet", GetCulture(App.Language), Folder.Startup + "Locale");
|
||||
}
|
||||
|
||||
string GetSystemLanguage()
|
||||
{
|
||||
string twoLetterName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
|
||||
|
||||
if (twoLetterName == "zh")
|
||||
return "chinese-china"; // Chinese (Simplified)
|
||||
|
||||
return new CultureInfo(twoLetterName).EnglishName.ToLowerInvariant();
|
||||
}
|
||||
|
||||
CultureInfo GetCulture(string name)
|
||||
{
|
||||
if (name == "system")
|
||||
name = GetSystemLanguage();
|
||||
|
||||
foreach (Language lang in Languages)
|
||||
if (lang.MpvNetName == name)
|
||||
return new CultureInfo(lang.CultureInfoName);
|
||||
|
||||
throw new Exception($"Unknown language {name}.");
|
||||
}
|
||||
|
||||
class Language
|
||||
{
|
||||
public string MpvNetName { get; }
|
||||
public string CultureInfoName { get; }
|
||||
public string TwoLetterName { get; }
|
||||
|
||||
public Language(string mpvNetName, string cultureInfoName, string twoLetterName)
|
||||
{
|
||||
MpvNetName = mpvNetName;
|
||||
CultureInfoName = cultureInfoName;
|
||||
TwoLetterName = twoLetterName;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
src/MpvNet.Windows/WinForms/MainForm.Designer.cs
generated
2
src/MpvNet.Windows/WinForms/MainForm.Designer.cs
generated
@@ -27,7 +27,7 @@ partial class MainForm
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
|
||||
@@ -286,7 +286,7 @@ public partial class MainForm : Form
|
||||
|
||||
lock (Player.MediaTracksLock)
|
||||
{
|
||||
var trackMenuItem = FindMenuItem("Track");
|
||||
var trackMenuItem = FindMenuItem(_("Track"));
|
||||
|
||||
if (trackMenuItem != null)
|
||||
{
|
||||
@@ -348,7 +348,7 @@ public partial class MainForm : Form
|
||||
}
|
||||
}
|
||||
|
||||
var chaptersMenuItem = FindMenuItem("Chapters");
|
||||
var chaptersMenuItem = FindMenuItem(_("Chapter"));
|
||||
|
||||
if (chaptersMenuItem != null)
|
||||
{
|
||||
@@ -369,7 +369,7 @@ public partial class MainForm : Form
|
||||
}
|
||||
}
|
||||
|
||||
var recentMenuItem = FindMenuItem("Recent");
|
||||
var recentMenuItem = FindMenuItem(_("Recent Files"));
|
||||
|
||||
if (recentMenuItem != null)
|
||||
{
|
||||
@@ -391,7 +391,7 @@ public partial class MainForm : Form
|
||||
recentMenuItem.Items.Add(clearMenuItem);
|
||||
}
|
||||
|
||||
var titlesMenuItem = FindMenuItem("Titles");
|
||||
var titlesMenuItem = FindMenuItem(_("Title"));
|
||||
|
||||
if (titlesMenuItem != null)
|
||||
{
|
||||
@@ -424,7 +424,7 @@ public partial class MainForm : Form
|
||||
}
|
||||
}
|
||||
|
||||
var profilesMenuItem = FindMenuItem("Profile");
|
||||
var profilesMenuItem = FindMenuItem(_("Profile"));
|
||||
|
||||
if (profilesMenuItem != null && !profilesMenuItem.HasItems)
|
||||
{
|
||||
@@ -446,7 +446,7 @@ public partial class MainForm : Form
|
||||
}
|
||||
}
|
||||
|
||||
var customMenuItem = FindMenuItem("Custom");
|
||||
var customMenuItem = FindMenuItem(_("Custom"));
|
||||
|
||||
if (customMenuItem != null)
|
||||
{
|
||||
@@ -770,16 +770,24 @@ public partial class MainForm : Form
|
||||
|
||||
foreach (Binding binding in menuBindings)
|
||||
{
|
||||
Binding tempBinding = binding;
|
||||
|
||||
if (MenuItemDuplicate.ContainsKey(tempBinding.Command) && tempBinding.Input != "")
|
||||
{
|
||||
var mi = MenuItemDuplicate[tempBinding.Command];
|
||||
mi.InputGestureText = mi.InputGestureText + ", " + tempBinding.Input;
|
||||
}
|
||||
|
||||
if (!binding.IsMenu)
|
||||
continue;
|
||||
|
||||
Binding tempBinding = binding;
|
||||
|
||||
var menuItem = MenuHelp.Add(ContextMenu.Items, tempBinding.Comment);
|
||||
|
||||
var menuItem = MenuHelp.Add(ContextMenu.Items, tempBinding.Comment);
|
||||
|
||||
if (menuItem != null)
|
||||
{
|
||||
MenuItemDuplicate[tempBinding.Comment] = menuItem;
|
||||
if (tempBinding.Input != "")
|
||||
MenuItemDuplicate[tempBinding.Command] = menuItem;
|
||||
|
||||
menuItem.Click += (sender, args) => {
|
||||
try {
|
||||
TaskHelp.Run(() => {
|
||||
@@ -1286,7 +1294,7 @@ public partial class MainForm : Form
|
||||
Player.CommandV("quit");
|
||||
|
||||
if (!Player.ShutdownAutoResetEvent.WaitOne(10000))
|
||||
Msg.ShowError("Shutdown thread failed to complete within 10 seconds.");
|
||||
Msg.ShowError(_("Shutdown thread failed to complete within 10 seconds."));
|
||||
|
||||
Player.Destroy();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user