22using System . Collections . Concurrent ;
33using System . Collections . Generic ;
44using System . Collections . ObjectModel ;
5+ using System . IO ;
56using System . Text ;
7+ using System . Text . Json ;
68using CommunityToolkit . Mvvm . DependencyInjection ;
79using Flow . Launcher . Infrastructure . UserSettings ;
810using ToolGood . Words . Pinyin ;
11+ using Flow . Launcher . Infrastructure . Logger ;
912
1013namespace Flow . Launcher . Infrastructure
1114{
@@ -16,9 +19,49 @@ public class PinyinAlphabet : IAlphabet
1619
1720 private readonly Settings _settings ;
1821
22+ private ReadOnlyDictionary < string , string > currentDoublePinyinTable ;
23+
1924 public PinyinAlphabet ( )
2025 {
2126 _settings = Ioc . Default . GetRequiredService < Settings > ( ) ;
27+ LoadDoublePinyinTable ( ) ;
28+
29+ _settings . PropertyChanged += ( sender , e ) =>
30+ {
31+ if ( e . PropertyName == nameof ( Settings . UseDoublePinyin ) ||
32+ e . PropertyName == nameof ( Settings . DoublePinyinSchema ) )
33+ {
34+ LoadDoublePinyinTable ( ) ;
35+ _pinyinCache . Clear ( ) ;
36+ }
37+ } ;
38+ }
39+
40+ private void LoadDoublePinyinTable ( )
41+ {
42+ if ( _settings . UseDoublePinyin )
43+ {
44+ var tablePath = Path . Join ( AppContext . BaseDirectory , "Resources" , "double_pinyin.json" ) ;
45+ try
46+ {
47+ using var fs = File . OpenRead ( tablePath ) ;
48+ Dictionary < string , Dictionary < string , string > > table = JsonSerializer . Deserialize < Dictionary < string , Dictionary < string , string > > > ( fs ) ;
49+ if ( ! table . TryGetValue ( _settings . DoublePinyinSchema , out var value ) )
50+ {
51+ throw new InvalidOperationException ( "DoublePinyinSchema is invalid." ) ;
52+ }
53+ currentDoublePinyinTable = new ReadOnlyDictionary < string , string > ( value ) ;
54+ }
55+ catch ( System . Exception e )
56+ {
57+ Log . Exception ( nameof ( PinyinAlphabet ) , "Failed to load double pinyin table from file: " + tablePath , e ) ;
58+ currentDoublePinyinTable = new ReadOnlyDictionary < string , string > ( new Dictionary < string , string > ( ) ) ;
59+ }
60+ }
61+ else
62+ {
63+ currentDoublePinyinTable = new ReadOnlyDictionary < string , string > ( new Dictionary < string , string > ( ) ) ;
64+ }
2265 }
2366
2467 public bool ShouldTranslate ( string stringToTranslate )
@@ -50,26 +93,27 @@ public bool ShouldTranslate(string stringToTranslate)
5093 var resultBuilder = new StringBuilder ( ) ;
5194 var map = new TranslationMapping ( ) ;
5295
53- var pre = false ;
96+ var previousIsChinese = false ;
5497
5598 for ( var i = 0 ; i < resultList . Length ; i ++ )
5699 {
57100 if ( content [ i ] >= 0x3400 && content [ i ] <= 0x9FD5 )
58101 {
59102 string dp = _settings . UseDoublePinyin ? ToDoublePin ( resultList [ i ] ) : resultList [ i ] ;
60103 map . AddNewIndex ( i , resultBuilder . Length , dp . Length + 1 ) ;
61- resultBuilder . Append ( ' ' ) ;
104+ if ( previousIsChinese )
105+ {
106+ resultBuilder . Append ( ' ' ) ;
107+ }
62108 resultBuilder . Append ( dp ) ;
63- pre = true ;
64109 }
65110 else
66111 {
67- if ( pre )
112+ if ( previousIsChinese )
68113 {
69- pre = false ;
114+ previousIsChinese = false ;
70115 resultBuilder . Append ( ' ' ) ;
71116 }
72-
73117 resultBuilder . Append ( resultList [ i ] ) ;
74118 }
75119 }
@@ -83,115 +127,13 @@ public bool ShouldTranslate(string stringToTranslate)
83127
84128 #region Double Pinyin
85129
86- private static readonly ReadOnlyDictionary < string , string > special = new ( new Dictionary < string , string > ( ) {
87- { "A" , "aa" } ,
88- { "Ai" , "ai" } ,
89- { "An" , "an" } ,
90- { "Ang" , "ah" } ,
91- { "Ao" , "ao" } ,
92- { "E" , "ee" } ,
93- { "Ei" , "ei" } ,
94- { "En" , "en" } ,
95- { "Er" , "er" } ,
96- { "O" , "oo" } ,
97- { "Ou" , "ou" }
98- } ) ;
99-
100- private static readonly ReadOnlyDictionary < string , string > first = new ( new Dictionary < string , string > ( ) {
101- { "Ch" , "i" } ,
102- { "Sh" , "u" } ,
103- { "Zh" , "v" }
104- } ) ;
105-
106- private static readonly ReadOnlyDictionary < string , string > second = new ( new Dictionary < string , string > ( )
130+ private string ToDoublePin ( string fullPinyin )
107131 {
108- { "ua" , "x" } ,
109- { "ei" , "w" } ,
110- { "e" , "e" } ,
111- { "ou" , "z" } ,
112- { "iu" , "q" } ,
113- { "ve" , "t" } ,
114- { "ue" , "t" } ,
115- { "u" , "u" } ,
116- { "i" , "i" } ,
117- { "o" , "o" } ,
118- { "uo" , "o" } ,
119- { "ie" , "p" } ,
120- { "a" , "a" } ,
121- { "ong" , "s" } ,
122- { "iong" , "s" } ,
123- { "ai" , "d" } ,
124- { "ing" , "k" } ,
125- { "uai" , "k" } ,
126- { "ang" , "h" } ,
127- { "uan" , "r" } ,
128- { "an" , "j" } ,
129- { "en" , "f" } ,
130- { "ia" , "x" } ,
131- { "iang" , "l" } ,
132- { "uang" , "l" } ,
133- { "eng" , "g" } ,
134- { "in" , "b" } ,
135- { "ao" , "c" } ,
136- { "v" , "v" } ,
137- { "ui" , "v" } ,
138- { "un" , "y" } ,
139- { "iao" , "n" } ,
140- { "ian" , "m" }
141- } ) ;
142-
143- private static string ToDoublePin ( string fullPinyin )
144- {
145- // Assuming s is valid
146- var fullPinyinSpan = fullPinyin . AsSpan ( ) ;
147- var doublePin = new StringBuilder ( ) ;
148-
149- // Handle special cases (a, o, e)
150- if ( fullPinyin . Length <= 3 && ( fullPinyinSpan [ 0 ] == 'a' || fullPinyinSpan [ 0 ] == 'e' || fullPinyinSpan [ 0 ] == 'o' ) )
132+ if ( currentDoublePinyinTable . TryGetValue ( fullPinyin , out var doublePinyinValue ) )
151133 {
152- if ( special . TryGetValue ( fullPinyin , out var value ) )
153- {
154- return value ;
155- }
156- }
157-
158- // Check for initials that are two characters long (zh, ch, sh)
159- if ( fullPinyin . Length >= 2 )
160- {
161- var firstTwoString = fullPinyinSpan [ ..2 ] . ToString ( ) ;
162- if ( first . TryGetValue ( firstTwoString , out var firstTwoDoublePin ) )
163- {
164- doublePin . Append ( firstTwoDoublePin ) ;
165-
166- var lastTwo = fullPinyinSpan [ 2 ..] ;
167- var lastTwoString = lastTwo . ToString ( ) ;
168- if ( second . TryGetValue ( lastTwoString , out var tmp ) )
169- {
170- doublePin . Append ( tmp ) ;
171- }
172- else
173- {
174- doublePin . Append ( lastTwo ) ; // Todo: original pinyin, remove this line if not needed
175- }
176- }
177- else
178- {
179- // Handle single-character initials
180- doublePin . Append ( fullPinyinSpan [ 0 ] ) ;
181-
182- var lastOne = fullPinyinSpan [ 1 ..] ;
183- var lastOneString = lastOne . ToString ( ) ;
184- if ( second . TryGetValue ( lastOneString , out var tmp ) )
185- {
186- doublePin . Append ( tmp ) ;
187- }
188- else
189- {
190- doublePin . Append ( lastOne ) ;
191- }
192- }
134+ return doublePinyinValue ;
193135 }
194- return doublePin . ToString ( ) ;
136+ return fullPinyin ;
195137 }
196138
197139 #endregion
0 commit comments