mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Use lookup table to translate full pinyin to double pinyin
This commit is contained in:
parent
b31a7408d3
commit
818aac715e
4 changed files with 3805 additions and 112 deletions
|
|
@ -2,10 +2,13 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||||
using Flow.Launcher.Infrastructure.UserSettings;
|
using Flow.Launcher.Infrastructure.UserSettings;
|
||||||
using ToolGood.Words.Pinyin;
|
using ToolGood.Words.Pinyin;
|
||||||
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
|
|
||||||
namespace Flow.Launcher.Infrastructure
|
namespace Flow.Launcher.Infrastructure
|
||||||
{
|
{
|
||||||
|
|
@ -16,9 +19,49 @@ namespace Flow.Launcher.Infrastructure
|
||||||
|
|
||||||
private readonly Settings _settings;
|
private readonly Settings _settings;
|
||||||
|
|
||||||
|
private ReadOnlyDictionary<string, string> currentDoublePinyinTable;
|
||||||
|
|
||||||
public PinyinAlphabet()
|
public PinyinAlphabet()
|
||||||
{
|
{
|
||||||
_settings = Ioc.Default.GetRequiredService<Settings>();
|
_settings = Ioc.Default.GetRequiredService<Settings>();
|
||||||
|
LoadDoublePinyinTable();
|
||||||
|
|
||||||
|
_settings.PropertyChanged += (sender, e) =>
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(Settings.UseDoublePinyin) ||
|
||||||
|
e.PropertyName == nameof(Settings.DoublePinyinSchema))
|
||||||
|
{
|
||||||
|
LoadDoublePinyinTable();
|
||||||
|
_pinyinCache.Clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadDoublePinyinTable()
|
||||||
|
{
|
||||||
|
if (_settings.UseDoublePinyin)
|
||||||
|
{
|
||||||
|
var tablePath = Path.Join(AppContext.BaseDirectory, "Resources", "double_pinyin.json");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var fs = File.OpenRead(tablePath);
|
||||||
|
Dictionary<string, Dictionary<string, string>> table = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(fs);
|
||||||
|
if (!table.TryGetValue(_settings.DoublePinyinSchema, out var value))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("DoublePinyinSchema is invalid.");
|
||||||
|
}
|
||||||
|
currentDoublePinyinTable = new ReadOnlyDictionary<string, string>(value);
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(nameof(PinyinAlphabet), "Failed to load double pinyin table from file: " + tablePath, e);
|
||||||
|
currentDoublePinyinTable = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentDoublePinyinTable = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldTranslate(string stringToTranslate)
|
public bool ShouldTranslate(string stringToTranslate)
|
||||||
|
|
@ -50,7 +93,7 @@ namespace Flow.Launcher.Infrastructure
|
||||||
var resultBuilder = new StringBuilder();
|
var resultBuilder = new StringBuilder();
|
||||||
var map = new TranslationMapping();
|
var map = new TranslationMapping();
|
||||||
|
|
||||||
var pre = false;
|
var previousIsChinese = false;
|
||||||
|
|
||||||
for (var i = 0; i < resultList.Length; i++)
|
for (var i = 0; i < resultList.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -58,18 +101,19 @@ namespace Flow.Launcher.Infrastructure
|
||||||
{
|
{
|
||||||
string dp = _settings.UseDoublePinyin ? ToDoublePin(resultList[i]) : resultList[i];
|
string dp = _settings.UseDoublePinyin ? ToDoublePin(resultList[i]) : resultList[i];
|
||||||
map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1);
|
map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1);
|
||||||
resultBuilder.Append(' ');
|
if (previousIsChinese)
|
||||||
|
{
|
||||||
|
resultBuilder.Append(' ');
|
||||||
|
}
|
||||||
resultBuilder.Append(dp);
|
resultBuilder.Append(dp);
|
||||||
pre = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pre)
|
if (previousIsChinese)
|
||||||
{
|
{
|
||||||
pre = false;
|
previousIsChinese = false;
|
||||||
resultBuilder.Append(' ');
|
resultBuilder.Append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
resultBuilder.Append(resultList[i]);
|
resultBuilder.Append(resultList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -83,115 +127,13 @@ namespace Flow.Launcher.Infrastructure
|
||||||
|
|
||||||
#region Double Pinyin
|
#region Double Pinyin
|
||||||
|
|
||||||
private static readonly ReadOnlyDictionary<string, string> special = new(new Dictionary<string, string>(){
|
private string ToDoublePin(string fullPinyin)
|
||||||
{"A", "aa"},
|
|
||||||
{"Ai", "ai"},
|
|
||||||
{"An", "an"},
|
|
||||||
{"Ang", "ah"},
|
|
||||||
{"Ao", "ao"},
|
|
||||||
{"E", "ee"},
|
|
||||||
{"Ei", "ei"},
|
|
||||||
{"En", "en"},
|
|
||||||
{"Er", "er"},
|
|
||||||
{"O", "oo"},
|
|
||||||
{"Ou", "ou"}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static readonly ReadOnlyDictionary<string, string> first = new(new Dictionary<string, string>(){
|
|
||||||
{"Ch", "i"},
|
|
||||||
{"Sh", "u"},
|
|
||||||
{"Zh", "v"}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static readonly ReadOnlyDictionary<string, string> second = new(new Dictionary<string, string>()
|
|
||||||
{
|
{
|
||||||
{"ua", "x"},
|
if (currentDoublePinyinTable.TryGetValue(fullPinyin, out var doublePinyinValue))
|
||||||
{"ei", "w"},
|
|
||||||
{"e", "e"},
|
|
||||||
{"ou", "z"},
|
|
||||||
{"iu", "q"},
|
|
||||||
{"ve", "t"},
|
|
||||||
{"ue", "t"},
|
|
||||||
{"u", "u"},
|
|
||||||
{"i", "i"},
|
|
||||||
{"o", "o"},
|
|
||||||
{"uo", "o"},
|
|
||||||
{"ie", "p"},
|
|
||||||
{"a", "a"},
|
|
||||||
{"ong", "s"},
|
|
||||||
{"iong", "s"},
|
|
||||||
{"ai", "d"},
|
|
||||||
{"ing", "k"},
|
|
||||||
{"uai", "k"},
|
|
||||||
{"ang", "h"},
|
|
||||||
{"uan", "r"},
|
|
||||||
{"an", "j"},
|
|
||||||
{"en", "f"},
|
|
||||||
{"ia", "x"},
|
|
||||||
{"iang", "l"},
|
|
||||||
{"uang", "l"},
|
|
||||||
{"eng", "g"},
|
|
||||||
{"in", "b"},
|
|
||||||
{"ao", "c"},
|
|
||||||
{"v", "v"},
|
|
||||||
{"ui", "v"},
|
|
||||||
{"un", "y"},
|
|
||||||
{"iao", "n"},
|
|
||||||
{"ian", "m"}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static string ToDoublePin(string fullPinyin)
|
|
||||||
{
|
|
||||||
// Assuming s is valid
|
|
||||||
var fullPinyinSpan = fullPinyin.AsSpan();
|
|
||||||
var doublePin = new StringBuilder();
|
|
||||||
|
|
||||||
// Handle special cases (a, o, e)
|
|
||||||
if (fullPinyin.Length <= 3 && (fullPinyinSpan[0] == 'a' || fullPinyinSpan[0] == 'e' || fullPinyinSpan[0] == 'o'))
|
|
||||||
{
|
{
|
||||||
if (special.TryGetValue(fullPinyin, out var value))
|
return doublePinyinValue;
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return fullPinyin;
|
||||||
// Check for initials that are two characters long (zh, ch, sh)
|
|
||||||
if (fullPinyin.Length >= 2)
|
|
||||||
{
|
|
||||||
var firstTwoString = fullPinyinSpan[..2].ToString();
|
|
||||||
if (first.TryGetValue(firstTwoString, out var firstTwoDoublePin))
|
|
||||||
{
|
|
||||||
doublePin.Append(firstTwoDoublePin);
|
|
||||||
|
|
||||||
var lastTwo = fullPinyinSpan[2..];
|
|
||||||
var lastTwoString = lastTwo.ToString();
|
|
||||||
if (second.TryGetValue(lastTwoString, out var tmp))
|
|
||||||
{
|
|
||||||
doublePin.Append(tmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
doublePin.Append(lastTwo); // Todo: original pinyin, remove this line if not needed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Handle single-character initials
|
|
||||||
doublePin.Append(fullPinyinSpan[0]);
|
|
||||||
|
|
||||||
var lastOne = fullPinyinSpan[1..];
|
|
||||||
var lastOneString = lastOne.ToString();
|
|
||||||
if (second.TryGetValue(lastOneString, out var tmp))
|
|
||||||
{
|
|
||||||
doublePin.Append(tmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
doublePin.Append(lastOne);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return doublePin.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
||||||
|
|
||||||
public bool UseDoublePinyin { get; set; } = true; //For developing
|
public bool UseDoublePinyin { get; set; } = true; //For developing
|
||||||
|
|
||||||
|
public string DoublePinyinSchema { get; set; } = "XiaoHe"; //For developing
|
||||||
|
|
||||||
public bool AlwaysPreview { get; set; } = false;
|
public bool AlwaysPreview { get; set; } = false;
|
||||||
|
|
||||||
public bool AlwaysStartEn { get; set; } = false;
|
public bool AlwaysStartEn { get; set; } = false;
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,9 @@
|
||||||
<None Update="Resources\dev.ico">
|
<None Update="Resources\dev.ico">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Resources\double_pinyin.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||||
|
|
|
||||||
3746
Flow.Launcher/Resources/double_pinyin.json
Normal file
3746
Flow.Launcher/Resources/double_pinyin.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue