2
2
using System . Collections . Concurrent ;
3
3
using System . Collections . Generic ;
4
4
using System . Collections . ObjectModel ;
5
+ using System . IO ;
5
6
using System . Text ;
7
+ using System . Text . Json ;
6
8
using CommunityToolkit . Mvvm . DependencyInjection ;
7
9
using Flow . Launcher . Infrastructure . UserSettings ;
8
10
using ToolGood . Words . Pinyin ;
11
+ using Flow . Launcher . Infrastructure . Logger ;
9
12
10
13
namespace Flow . Launcher . Infrastructure
11
14
{
@@ -16,9 +19,49 @@ public class PinyinAlphabet : IAlphabet
16
19
17
20
private readonly Settings _settings ;
18
21
22
+ private ReadOnlyDictionary < string , string > currentDoublePinyinTable ;
23
+
19
24
public PinyinAlphabet ( )
20
25
{
21
26
_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
+ }
22
65
}
23
66
24
67
public bool ShouldTranslate ( string stringToTranslate )
@@ -50,26 +93,27 @@ public bool ShouldTranslate(string stringToTranslate)
50
93
var resultBuilder = new StringBuilder ( ) ;
51
94
var map = new TranslationMapping ( ) ;
52
95
53
- var pre = false ;
96
+ var previousIsChinese = false ;
54
97
55
98
for ( var i = 0 ; i < resultList . Length ; i ++ )
56
99
{
57
100
if ( content [ i ] >= 0x3400 && content [ i ] <= 0x9FD5 )
58
101
{
59
102
string dp = _settings . UseDoublePinyin ? ToDoublePin ( resultList [ i ] ) : resultList [ i ] ;
60
103
map . AddNewIndex ( i , resultBuilder . Length , dp . Length + 1 ) ;
61
- resultBuilder . Append ( ' ' ) ;
104
+ if ( previousIsChinese )
105
+ {
106
+ resultBuilder . Append ( ' ' ) ;
107
+ }
62
108
resultBuilder . Append ( dp ) ;
63
- pre = true ;
64
109
}
65
110
else
66
111
{
67
- if ( pre )
112
+ if ( previousIsChinese )
68
113
{
69
- pre = false ;
114
+ previousIsChinese = false ;
70
115
resultBuilder . Append ( ' ' ) ;
71
116
}
72
-
73
117
resultBuilder . Append ( resultList [ i ] ) ;
74
118
}
75
119
}
@@ -83,115 +127,13 @@ public bool ShouldTranslate(string stringToTranslate)
83
127
84
128
#region Double Pinyin
85
129
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 )
107
131
{
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 ) )
151
133
{
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 ;
193
135
}
194
- return doublePin . ToString ( ) ;
136
+ return fullPinyin ;
195
137
}
196
138
197
139
#endregion
0 commit comments