feat: add translation local cache function

main 0.20
DESKTOP-3BO4HSG\ksat 2 years ago
parent a93c422838
commit 5fbfc19ec3

@ -36,7 +36,7 @@
- [x] 添加语音合成 - [x] 添加语音合成
- [x] 添加离线截图翻译 - [x] 添加离线截图翻译
- [x] 添加检查更新 - [x] 添加检查更新
- [ ] 添加翻译记录缓存功能 - [x] 添加翻译记录缓存功能
## 使用 ## 使用
@ -66,6 +66,8 @@
## 开发历史 ## 开发历史
- 2023-01-17 0.20 添加翻译记录缓存功能,重复翻译从本地数据库获取,本地记录数量上限可调整
- 2023-01-12 0.18 优化 GC 后台静默运行内存占用保持 4MB 左右 - 2023-01-12 0.18 优化 GC 后台静默运行内存占用保持 4MB 左右
- 2023-01-12 0.17 添加检查更新功能 - 2023-01-12 0.17 添加检查更新功能

@ -0,0 +1,97 @@
using SQLite;
using STranslate.Model;
using STranslate.ViewModel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace STranslate.Helper
{
public class SqliteHelper : IDisposable
{
public SqliteHelper()
{
_sqlDB = new SQLiteConnection(_dbName);
_sqlDB.CreateTable<SqliteModel>();
}
public void Insert(DateTime time, string source, string target, LanguageEnum sourceLang, LanguageEnum targetLang, string api)
{
try
{
var model = new SqliteModel
{
Time = time,
SourceText = source,
TargetText = target,
SourceLang = sourceLang.ToString(),
TargetLang = targetLang.ToString(),
Api = api,
};
//查询最大数量
var count = _sqlDB.Table<SqliteModel>().Count();
if (count >= SettingsVM.Instance.MaxHistoryCount)
{
_sqlDB.Execute("delete from histories where id in (select id from histories limit (?))"
, count + 1 - SettingsVM.Instance.MaxHistoryCount);
}
//手动切换目标语言强制插入替换
_sqlDB.Table<SqliteModel>()
.Where(x => x.SourceText.Equals(model.SourceText))
.ToList().ForEach(x =>
{
_sqlDB.Delete(x);
});
_sqlDB.Insert(model);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show($"本地记录插入错误\n{ex.Message}");
}
}
/// <summary>
/// 查询记录
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public string Query(string str)
{
var query = _sqlDB.Table<SqliteModel>().Where(x => x.SourceText.Equals(str));
if (query.Count() <= 0)
{
return string.Empty;
}
else//如果超过一个删除多余的
{
var tmp = query.ToList();
for (int i = 1; i < tmp.Count; i++)
{
_sqlDB.Delete(tmp[i]);
}
return query.First().TargetText;
}
}
public void Dispose()
{
_sqlDB.Close();
}
private readonly SQLiteConnection _sqlDB;
/// <summary>
/// 数据文件
/// </summary>
private static string _dbName => $"{_ApplicationData}\\{_AppName.ToLower()}.db";
/// <summary>
/// C:\Users\user\AppData\Local\STranslate
/// </summary>
private static string _ApplicationData => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\{_AppName}";
private static readonly string _AppName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
}
}

@ -17,6 +17,7 @@ namespace STranslate.Model
{ {
return new ConfigModel return new ConfigModel
{ {
MaxHistoryCount = 100,
AutoScale = 0.8, AutoScale = 0.8,
WordPickupInterval = 200, WordPickupInterval = 200,
IsBright = true, IsBright = true,
@ -44,6 +45,11 @@ namespace STranslate.Model
}; };
} }
/// <summary>
/// 最大历史记录数量
/// </summary>
[JsonProperty("maxHistoryCount")]
public int MaxHistoryCount { get; set; }
/// <summary> /// <summary>
/// 自动识别语种标度 /// 自动识别语种标度
/// </summary> /// </summary>

@ -0,0 +1,38 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STranslate.Model
{
[Table("Histories")]
public class SqliteModel
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("time")]
public DateTime Time { get; set; }
[Column("source_lang")]
public string SourceLang { get; set; }
[Column("target_lang")]
public string TargetLang { get; set; }
[Column("source_text")]
public string SourceText { get; set; }
[Column("target_text")]
public string TargetText { get; set; }
[Column("api")]
public string Api { get; set; }
[Column("remark")]
public string Remark { get; set; }
}
}

@ -47,6 +47,6 @@ using System.Windows;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示: //通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.9.0")] [assembly: AssemblyVersion("0.2.0.0")]
[assembly: AssemblyFileVersion("0.1.9.0")] [assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: Guid("CE252DD8-179F-4544-9989-453F5DEA378D")] [assembly: Guid("CE252DD8-179F-4544-9989-453F5DEA378D")]

@ -59,9 +59,37 @@
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="SQLite-net, Version=1.8.116.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\sqlite-net-pcl.1.8.116\lib\netstandard2.0\SQLite-net.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.batteries_v2, Version=2.0.4.976, Culture=neutral, PublicKeyToken=8226ea5df37bcae9, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.bundle_green.2.0.4\lib\net461\SQLitePCLRaw.batteries_v2.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=2.0.4.976, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.core.2.0.4\lib\netstandard2.0\SQLitePCLRaw.core.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.nativelibrary, Version=2.0.4.976, Culture=neutral, PublicKeyToken=502ed628492ab262, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.bundle_green.2.0.4\lib\net461\SQLitePCLRaw.nativelibrary.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.provider.dynamic_cdecl, Version=2.0.4.976, Culture=neutral, PublicKeyToken=b68184102cba0b3b, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.provider.dynamic_cdecl.2.0.4\lib\netstandard2.0\SQLitePCLRaw.provider.dynamic_cdecl.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Speech" /> <Reference Include="System.Speech" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
@ -95,8 +123,10 @@
<Compile Include="Helper\MvvmHelper.cs" /> <Compile Include="Helper\MvvmHelper.cs" />
<Compile Include="Helper\NativeMethodHelper.cs" /> <Compile Include="Helper\NativeMethodHelper.cs" />
<Compile Include="Helper\Processhelper.cs" /> <Compile Include="Helper\Processhelper.cs" />
<Compile Include="Helper\SqliteHelper.cs" />
<Compile Include="Helper\StartupHelper.cs" /> <Compile Include="Helper\StartupHelper.cs" />
<Compile Include="Model\ConfigModel.cs" /> <Compile Include="Model\ConfigModel.cs" />
<Compile Include="Model\SqliteModel.cs" />
<Compile Include="Model\VisibilityConverter.cs" /> <Compile Include="Model\VisibilityConverter.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@ -230,5 +260,7 @@
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText> <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tesseract.5.2.0\build\Tesseract.targets'))" /> <Error Condition="!Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tesseract.5.2.0\build\Tesseract.targets'))" />
<Error Condition="!Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets'))" />
</Target> </Target>
<Import Project="..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.2.0.4\build\net461\SQLitePCLRaw.lib.e_sqlite3.targets')" />
</Project> </Project>

@ -80,6 +80,21 @@
</WrapPanel> </WrapPanel>
</GroupBox> </GroupBox>
<GroupBox Header="历史记录数量"
ToolTip="记录记录至本地数据库,以便省去重复查询的时间,调整最大历史记录数量">
<WrapPanel Margin="0,5,0,5">
<Slider Value="{Binding DataContext.MaxHistoryCount, ElementName=window}"
Minimum="1"
Maximum="1000"
MinWidth="200"
TickFrequency="10"
TickPlacement="None"
IsSnapToTickEnabled="True">
</Slider>
<TextBlock Text="{Binding MaxHistoryCount, StringFormat={}{0}条}" Margin="10,0,0,0" />
</WrapPanel>
</GroupBox>
<GroupBox Header="取词间隔" <GroupBox Header="取词间隔"
ToolTip="划词翻译实现原理是用户用鼠标划词后模拟Ctrl+C间隔一定时间后程序再从剪切板取词如果电脑反应慢可能会出现取不到词的问题将间隔调大可以适配一些老旧的机器"> ToolTip="划词翻译实现原理是用户用鼠标划词后模拟Ctrl+C间隔一定时间后程序再从剪切板取词如果电脑反应慢可能会出现取不到词的问题将间隔调大可以适配一些老旧的机器">
<WrapPanel Margin="0,5,0,5"> <WrapPanel Margin="0,5,0,5">

@ -25,6 +25,7 @@ namespace STranslate.ViewModel
InputCombo = LanguageEnumDict.Keys.ToList(); InputCombo = LanguageEnumDict.Keys.ToList();
OutputCombo = LanguageEnumDict.Keys.ToList(); OutputCombo = LanguageEnumDict.Keys.ToList();
_sqlHelper = new SqliteHelper();
#endregion #endregion
#region Common #region Common
@ -209,6 +210,8 @@ namespace STranslate.ViewModel
Util.Util.FlushMemory(); Util.Util.FlushMemory();
Mainwin.NotifyIcon.Dispose(); Mainwin.NotifyIcon.Dispose();
Mainwin.Close(); Mainwin.Close();
//关闭数据库
_sqlHelper.Dispose();
//语音合成销毁 //语音合成销毁
_speech.Dispose(); _speech.Dispose();
//注销快捷键 //注销快捷键
@ -231,6 +234,10 @@ namespace STranslate.ViewModel
{ {
_globalConfig = ConfigHelper.Instance.ReadConfig<ConfigModel>(); _globalConfig = ConfigHelper.Instance.ReadConfig<ConfigModel>();
//读取历史记录数量
var count = _globalConfig.MaxHistoryCount;
SettingsVM.Instance.MaxHistoryCount = (count <= 0 || count >= 1000) ? 100 : count;
//读取自动识别语种比例 //读取自动识别语种比例
var scale = _globalConfig.AutoScale; var scale = _globalConfig.AutoScale;
SettingsVM.Instance.AutoScale = (scale <= 0 || scale >= 1) ? 0.8 : scale; SettingsVM.Instance.AutoScale = (scale <= 0 || scale >= 1) ? 0.8 : scale;
@ -275,6 +282,7 @@ namespace STranslate.ViewModel
{ {
ConfigHelper.Instance.WriteConfig(new ConfigModel ConfigHelper.Instance.WriteConfig(new ConfigModel
{ {
MaxHistoryCount = SettingsVM.Instance.MaxHistoryCount,
AutoScale = SettingsVM.Instance.AutoScale, AutoScale = SettingsVM.Instance.AutoScale,
WordPickupInterval = SettingsVM.Instance.WordPickupInterval, WordPickupInterval = SettingsVM.Instance.WordPickupInterval,
IsBright = Application.Current.Resources.MergedDictionaries[0].Source.ToString() == ThemeDefault ? true : false, IsBright = Application.Current.Resources.MergedDictionaries[0].Source.ToString() == ThemeDefault ? true : false,
@ -330,7 +338,8 @@ namespace STranslate.ViewModel
{ {
try try
{ {
if (string.IsNullOrEmpty(InputTxt.Trim())) throw new Exception("输入值为空!"); if (string.IsNullOrEmpty(InputTxt.Trim()))
throw new Exception("输入值为空!");
var isEng = string.Empty; var isEng = string.Empty;
IdentifyLanguage = string.Empty; IdentifyLanguage = string.Empty;
OutputTxt = "翻译中..."; OutputTxt = "翻译中...";
@ -342,6 +351,13 @@ namespace STranslate.ViewModel
//自动选择目标语言 //自动选择目标语言
if (OutputComboSelected == LanguageEnum.AUTO.GetDescription()) if (OutputComboSelected == LanguageEnum.AUTO.GetDescription())
{ {
//只有在自动的模式下读取
var resp = _sqlHelper.Query(InputTxt);
if (!string.IsNullOrEmpty(resp))
{
OutputTxt = resp;
return;
}
var autoRet = AutomaticLanguageRecognition(InputTxt); var autoRet = AutomaticLanguageRecognition(InputTxt);
IdentifyLanguage = autoRet.Item1; IdentifyLanguage = autoRet.Item1;
isEng = autoRet.Item2; isEng = autoRet.Item2;
@ -361,6 +377,16 @@ namespace STranslate.ViewModel
} }
OutputTxt = _translateResp; OutputTxt = _translateResp;
await Task.Run(() =>
{
_sqlHelper.Insert(DateTime.Now,
InputTxt,
OutputTxt,
LanguageEnumDict[string.IsNullOrEmpty(IdentifyLanguage) ? InputComboSelected : IdentifyLanguage],
LanguageEnumDict[string.IsNullOrEmpty(isEng) ? OutputComboSelected : isEng],
SelectedTranslationInterface.Api);
});
//如果目标语言不是英文则不进行转换 //如果目标语言不是英文则不进行转换
//1. 自动判断语种Tuple item2 不为 EN //1. 自动判断语种Tuple item2 不为 EN
//2. 非自动判断语种,目标语种不为 EN //2. 非自动判断语种,目标语种不为 EN
@ -390,6 +416,7 @@ namespace STranslate.ViewModel
#endregion handle #endregion handle
#region Params #region Params
private readonly SqliteHelper _sqlHelper;
private string _translateResp; private string _translateResp;
public ICommand MouseLeftDownCmd { get; set; } public ICommand MouseLeftDownCmd { get; set; }
public ICommand DeactivatedCmd { get; set; } public ICommand DeactivatedCmd { get; set; }

@ -136,5 +136,11 @@ namespace STranslate.ViewModel
private double _wordPickupInterval; private double _wordPickupInterval;
public double WordPickupInterval { get => _wordPickupInterval; set => UpdateProperty(ref _wordPickupInterval, value); } public double WordPickupInterval { get => _wordPickupInterval; set => UpdateProperty(ref _wordPickupInterval, value); }
/// <summary>
/// 最大历史记录数量
/// </summary>
private int _maxHistoryCount;
public int MaxHistoryCount { get => _maxHistoryCount; set => UpdateProperty(ref _maxHistoryCount, value); }
} }
} }

@ -2,6 +2,15 @@
<packages> <packages>
<package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net48" /> <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net48" /> <package id="Newtonsoft.Json" version="13.0.2" targetFramework="net48" />
<package id="sqlite-net-pcl" version="1.8.116" targetFramework="net48" />
<package id="SQLitePCLRaw.bundle_green" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.core" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.lib.e_sqlite3" version="2.0.4" targetFramework="net48" />
<package id="SQLitePCLRaw.provider.dynamic_cdecl" version="2.0.4" targetFramework="net48" />
<package id="System.Buffers" version="4.4.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.3" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net48" />
<package id="Tesseract" version="5.2.0" targetFramework="net48" /> <package id="Tesseract" version="5.2.0" targetFramework="net48" />
<package id="WpfScreenHelper" version="2.1.0" targetFramework="net48" /> <package id="WpfScreenHelper" version="2.1.0" targetFramework="net48" />
</packages> </packages>
Loading…
Cancel
Save