├── .gitattributes
├── .gitignore
├── Chinese.Abstract
├── Chinese.Abstract.csproj
├── ChineseChar.cs
├── ChineseType.cs
├── ChineseWord.cs
├── IWord.cs
├── IWordSource.cs
└── PinyinFormat.cs
├── Chinese.Lexicon
├── Chinese.Lexicon.csproj
└── Data
│ ├── Char.cs
│ ├── ChineseDbContext.cs
│ ├── Word.cs
│ └── WordType.cs
├── Chinese.Region
├── Chinese.Region.csproj
├── City.cs
├── Country.cs
├── Generator.cs
├── Generator.tt
├── ICodeName.cs
├── Model.cs
├── Province.cs
└── source
│ └── 202201xzqh
├── Chinese.Test
├── Chinese.Test.csproj
├── ChineseConverterTests.cs
├── ChineseCurrencyTests.cs
├── ChineseNumberTests.cs
├── ChineseTokenizerTests.cs
└── PinyinTest.cs
├── Chinese.lutconfig
├── Chinese.png
├── Chinese.sln
├── Chinese
├── Chinese.csproj
├── Grammars
│ ├── Grammar.cs
│ ├── GrammarPart.cs
│ └── WordType.cs
├── Lexicon.cs
└── Lexicons
│ ├── Builtin.cs
│ ├── CurrencyLexicon.cs
│ ├── NumberLexicon.cs
│ └── NumberMode.cs
├── ChineseApp
├── ChineseApp.csproj
└── Program.cs
├── LICENSE.md
├── LexiconBuilder
├── LexiconBuilder.csproj
└── Program.cs
├── README.md
├── Tests
├── Chinese.Test
│ ├── Chinese.Test.csproj
│ ├── ConverterTests.cs
│ ├── CurrencyTests.cs
│ ├── NumberTests.cs
│ ├── PinyinTest.cs
│ ├── RegionTests.cs
│ ├── TokenizerTests.cs
│ └── Util
│ │ └── MySqlLexicon.cs
└── DbCreator.MySql
│ ├── .config
│ └── dotnet-tools.json
│ ├── ApplicationDbContextFactory.cs
│ ├── DbCreator.MySql.csproj
│ ├── Migrations
│ ├── 20221112224627_202211130646.Designer.cs
│ ├── 20221112224627_202211130646.cs
│ ├── 20221113154648_202211132346.Designer.cs
│ ├── 20221113154648_202211132346.cs
│ ├── 20230221003235_202302210832.Designer.cs
│ ├── 20230221003235_202302210832.cs
│ ├── 20230221004748_202302210846.Designer.cs
│ ├── 20230221004748_202302210846.cs
│ ├── 20230221032034_202302211120.Designer.cs
│ ├── 20230221032034_202302211120.cs
│ ├── 20230227074215_202302271541.Designer.cs
│ ├── 20230227074215_202302271541.cs
│ └── ApplicationDbContextModelSnapshot.cs
│ └── Program.cs
├── UPDATE_LOG.md
├── lib
└── netstandard2.0
│ ├── ChineseConverter.dll
│ └── ChnCharInfo.dll
└── push.cmd
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/Chinese.Abstract/Chinese.Abstract.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net7.0;net8.0
5 | enable
6 | enable
7 | 0.0.1
8 | true
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Chinese.Abstract/ChineseChar.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace Chinese;
4 |
5 | [DebuggerDisplay("{Char}")]
6 | public class ChineseChar : ChineseWord
7 | {
8 | public ChineseChar(char ch, ChineseType types, string[] pinyins)
9 | {
10 | Char = ch;
11 | Pinyins = pinyins;
12 | IsPolyphone = Pinyins.Length > 1;
13 | Types = types;
14 | }
15 |
16 | public char Char { get; }
17 | public string[] Pinyins { get; }
18 | public bool IsPolyphone { get; }
19 | public ChineseType Types { get; }
20 | }
21 |
--------------------------------------------------------------------------------
/Chinese.Abstract/ChineseType.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese;
2 |
3 | public enum ChineseType
4 | {
5 | Undefined = 0,
6 |
7 | ///
8 | /// 简体中文
9 | ///
10 | Simplified = 1,
11 |
12 | ///
13 | /// 繁体中文
14 | ///
15 | Traditional = 2,
16 |
17 | ///
18 | /// 未简化字
19 | ///
20 | Both = Simplified | Traditional,
21 | }
22 |
--------------------------------------------------------------------------------
/Chinese.Abstract/ChineseWord.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Diagnostics;
3 |
4 | namespace Chinese;
5 |
6 | [DebuggerDisplay("{Simplified}")]
7 | public class ChineseWord : IWord
8 | {
9 | ///
10 | /// 中文字符串
11 | ///
12 | public string? Word
13 | {
14 | set
15 | {
16 | Simplified = value;
17 | Traditional = value;
18 | }
19 | }
20 | ///
21 | /// 简体中文字符串
22 | ///
23 | public string? Simplified { get; set; }
24 | ///
25 | /// 繁体中文字符串
26 | ///
27 | public string? Traditional { get; set; }
28 |
29 | ///
30 | /// 拼音
31 | ///
32 | public string? Pinyin
33 | {
34 | set
35 | {
36 | SimplifiedPinyin = value;
37 | TraditionalPinyin = value;
38 | }
39 | }
40 | ///
41 | /// 简体中文拼音
42 | ///
43 | public string? SimplifiedPinyin { get; set; }
44 | ///
45 | /// 繁体中文拼音
46 | ///
47 | public string? TraditionalPinyin { get; set; }
48 |
49 | ///
50 | /// 额外数据
51 | ///
52 | public object? Tag { get; set; }
53 |
54 | public bool Equals(IWord other)
55 | {
56 | return Simplified == other.Simplified && Traditional == other.Traditional;
57 | }
58 |
59 | public override string ToString()
60 | {
61 | return $"{Simplified}, {Traditional}";
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/Chinese.Abstract/IWord.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese;
2 |
3 | public interface IWord : IEquatable
4 | {
5 | /// 简体中文字符串
6 | ///
7 | string? Simplified { get; }
8 | ///
9 | /// 繁体中文字符串
10 | ///
11 | string? Traditional { get; }
12 |
13 | ///
14 | /// 简体中文拼音
15 | ///
16 | string? SimplifiedPinyin { get; }
17 | ///
18 | /// 繁体中文拼音
19 | ///
20 | string? TraditionalPinyin { get; }
21 |
22 | string? GetString(ChineseType type)
23 | {
24 | if (type == ChineseType.Simplified) return Simplified;
25 | else if (type == ChineseType.Traditional) return Traditional;
26 | else throw new NotSupportedException($"The type is not supported. (type: {type})");
27 | }
28 |
29 | string? GetPinyin(ChineseType type)
30 | {
31 | if (type == ChineseType.Simplified) return SimplifiedPinyin;
32 | else if (type == ChineseType.Traditional) return TraditionalPinyin;
33 | else throw new NotSupportedException($"The type is not supported. (type: {type})");
34 | }
35 |
36 | ///
37 | /// 额外数据
38 | ///
39 | object? Tag { get; }
40 | }
41 |
--------------------------------------------------------------------------------
/Chinese.Abstract/IWordSource.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese;
2 |
3 | public interface IWordSource
4 | {
5 | string DbFileName { get; }
6 | string ResourceName { get; }
7 |
8 | void CreateDbFile();
9 | ChineseChar[] GetChars(ChineseType type, IEnumerable chars);
10 | ChineseWord[] GetWords(ChineseType type, IEnumerable chars);
11 | }
12 |
13 | public static class WordSourceExtensions
14 | {
15 | public static bool IsDbFileExsist(this IWordSource @this) => File.Exists(@this.DbFileName);
16 | }
17 |
--------------------------------------------------------------------------------
/Chinese.Abstract/PinyinFormat.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese;
2 |
3 | public enum PinyinFormat
4 | {
5 | Default,
6 | WithoutTone,
7 | Phonetic,
8 | InitialConsonant,
9 | }
10 |
--------------------------------------------------------------------------------
/Chinese.Lexicon/Chinese.Lexicon.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 | preview
8 | 0.7.0-alpha
9 | zmjack
10 | 中文解析通用工具。包括拼音,简繁转换,数字读法,货币读法。
11 | Copyright © nstandard.net 2023
12 | Chinese
13 | LICENSE.md
14 | https://github.com/zmjack/Chinese
15 | Chinese.png
16 | https://github.com/zmjack/Chinese
17 | git
18 | Chinese Pinyin Numerics
19 | true
20 |
21 |
22 |
23 |
24 | 6.0.14
25 |
26 |
27 |
28 |
29 |
30 | 6.0.14
31 |
32 |
33 |
34 |
35 |
36 | \
37 | True
38 |
39 |
40 | \
41 | True
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Chinese.Lexicon/Data/Char.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.ComponentModel.DataAnnotations.Schema;
3 | using System.Diagnostics;
4 | using System.Text.Json;
5 |
6 | namespace Chinese.Data;
7 |
8 | [DebuggerDisplay("{Character}")]
9 | public class Char : IWord, IEquatable
10 | {
11 | [Key]
12 | public int Unicode { get; set; }
13 |
14 | public char Character { get; set; }
15 |
16 | [StringLength(64)]
17 | public string Pinyins { get; set; }
18 |
19 | [NotMapped]
20 | public string[] PinyinsProxy
21 | {
22 | get => JsonSerializer.Deserialize(Pinyins);
23 | set => Pinyins = JsonSerializer.Serialize(value);
24 | }
25 |
26 | public bool IsPolyphone { get; set; }
27 |
28 | public ChineseType Types { get; set; }
29 |
30 | [StringLength(64)]
31 | public string Simplified { get; set; }
32 |
33 | [StringLength(64)]
34 | public string Traditional { get; set; }
35 |
36 | ///
37 | /// 默认拼音
38 | ///
39 | [StringLength(64)]
40 | public string DefaultPinyin { get; set; }
41 |
42 | public bool Sight { get; set; }
43 |
44 | public string SimplifiedPinyin => DefaultPinyin;
45 | public string TraditionalPinyin => DefaultPinyin;
46 | public object Tag => null;
47 |
48 | public bool Equals(Char other)
49 | {
50 | return Unicode == other.Unicode;
51 | }
52 |
53 | public bool Equals(IWord other)
54 | {
55 | throw new NotImplementedException();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chinese.Lexicon/Data/ChineseDbContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 |
3 | namespace Chinese.Data;
4 |
5 | public class ChineseDbContext : DbContext
6 | {
7 | public ChineseDbContext(DbContextOptions options) : base(options) { }
8 |
9 | public DbSet Chars { get; set; }
10 | public DbSet Words { get; set; }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/Chinese.Lexicon/Data/Word.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.ComponentModel.DataAnnotations.Schema;
3 | using System.Diagnostics;
4 |
5 | namespace Chinese.Data;
6 |
7 | [DebuggerDisplay("{Simplified}")]
8 | public class Word : IWord
9 | {
10 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
11 | public Guid Id { get; set; }
12 |
13 | ///
14 | /// 词组类型
15 | ///
16 | public WordType Type { get; set; }
17 |
18 | ///
19 | /// 简体中文字符串
20 | ///
21 | [StringLength(64)]
22 | public string Simplified { get; set; }
23 |
24 | ///
25 | /// 繁体中文字符串
26 | ///
27 | [StringLength(64)]
28 | public string Traditional { get; set; }
29 |
30 | ///
31 | /// 简体中文拼音
32 | ///
33 | [StringLength(64)]
34 | public string SimplifiedPinyin { get; set; }
35 |
36 | ///
37 | /// 繁体中文拼音
38 | ///
39 | [StringLength(64)]
40 | public string TraditionalPinyin { get; set; }
41 |
42 | public int HashCode { get; set; }
43 |
44 | public object Tag => null;
45 |
46 | public bool Equals(IWord other)
47 | {
48 | return Simplified == other.Simplified && Traditional == other.Traditional;
49 | }
50 |
51 | public override int GetHashCode()
52 | {
53 | return HashCode;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/Chinese.Lexicon/Data/WordType.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Data;
2 |
3 | public enum WordType
4 | {
5 | Unspecified,
6 | Numberics,
7 | }
8 |
--------------------------------------------------------------------------------
/Chinese.Region/Chinese.Region.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 | preview
8 |
9 |
10 |
11 |
12 | True
13 | True
14 | Generator.tt
15 |
16 |
17 |
18 |
19 |
20 | TextTemplatingFileGenerator
21 | Generator.cs
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | True
32 | True
33 | Generator.tt
34 |
35 |
36 | True
37 | True
38 | Source.tt
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Chinese.Region/City.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Mainland;
2 |
3 | public class City : ICodeName
4 | {
5 | public required string Code { get; set; }
6 | public required string Name { get; set; }
7 | public required Province Province { get; set; }
8 | public required ICollection Countries { get; set; }
9 | }
10 |
--------------------------------------------------------------------------------
/Chinese.Region/Country.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Mainland;
2 |
3 | public class Country : ICodeName
4 | {
5 | public required string Code { get; set; }
6 | public required string Name { get; set; }
7 | public required City City { get; set; }
8 | public Province Province => City.Province;
9 | }
10 |
--------------------------------------------------------------------------------
/Chinese.Region/Generator.tt:
--------------------------------------------------------------------------------
1 | <#@ template debug="false" hostspecific="true" language="C#" #>
2 | <#@ assembly name="System.Core" #>
3 | <#@ assembly name="System.Xml" #>
4 | <#@ import namespace="System.Linq" #>
5 | <#@ import namespace="System.Net" #>
6 | <#@ import namespace="System.Text" #>
7 | <#@ import namespace="System.IO" #>
8 | <#@ import namespace="System.Collections.Generic" #>
9 | <#@ import namespace="System.Text.RegularExpressions" #>
10 | <#@ import namespace="System.Xml" #>
11 | <#@ import namespace="System.Xml.XPath" #>
12 | <#@ output extension=".cs" #>
13 | namespace Chinese.Mainland;
14 |
15 | public static class Generator
16 | {
17 | public class Result
18 | {
19 | public required Province[] Provinces { get; set; }
20 | public required City[] Cities { get; set; }
21 | public required Country[] Countries { get; set; }
22 | }
23 |
24 | #pragma warning disable IDE0028 // Simplify collection initialization
25 | public static Result Build()
26 | {
27 | var list = GetModels();
28 |
29 | Province? province = null;
30 | City? city = null;
31 |
32 | List provinces = [];
33 | List cities = [];
34 | List countries = [];
35 |
36 | foreach (var item in list)
37 | {
38 | if (item.Level == 0)
39 | {
40 | province = new()
41 | {
42 | Code = item.Code,
43 | Name = item.Name,
44 | Cities = new List(),
45 | };
46 | provinces.Add(province);
47 | }
48 | else if (item.Level == 1)
49 | {
50 | city = new()
51 | {
52 | Code = item.Code,
53 | Name = item.Name,
54 | Province = province!,
55 | Countries = new List(),
56 | };
57 | cities.Add(city);
58 | (province!.Cities as List)!.Add(city);
59 | }
60 | else if (item.Level == 2)
61 | {
62 | var country = new Country()
63 | {
64 | Code = item.Code,
65 | Name = item.Name,
66 | City = city!,
67 | };
68 | countries.Add(country);
69 | (city!.Countries as List)!.Add(country);
70 | }
71 | }
72 |
73 | return new Result
74 | {
75 | Provinces = [.. provinces],
76 | Cities = [.. cities],
77 | Countries = [.. countries],
78 | };
79 | }
80 | #pragma warning restore IDE0028 // Simplify collection initialization
81 |
82 | internal static IEnumerable GetModels()
83 | {
84 | <#
85 | foreach(var model in GetModels())
86 | {
87 | #>
88 | yield return new Model { Level = <#=model.Level#>, Code = "<#=model.Code#>", Name = "<#=model.Name#>" };
89 | <#
90 | }
91 | #>
92 | }
93 | }
94 |
95 | <#+
96 | class Model
97 | {
98 | public int Level { get; set; }
99 | public string Code { get; set; }
100 | public string Name { get; set; }
101 | }
102 |
103 | IEnumerable GetModels()
104 | {
105 | var projectPath = Host.ResolveAssemblyReference("$(ProjectDir)");
106 | var path = Path.Combine(projectPath, @"source\202201xzqh");
107 | var html = File.ReadAllText(path);
108 |
109 | var regex = new Regex(@"()", RegexOptions.Singleline);
110 | var match = regex.Match(html);
111 | var table = match.Groups[1].Value;
112 |
113 | table = table.Replace(Encoding.UTF8.GetString(new byte[] { 0xc2, 0xa0 }), " ");
114 | table = new Regex(@"", RegexOptions.Singleline).Replace(table, "");
115 | table = new Regex(@"(\r\n)\s+", RegexOptions.Singleline).Replace(table, "");
116 | table = new Regex(@"(\r\n)\s+", RegexOptions.Singleline).Replace(table, "");
117 | table = new Regex(@" style='.+?'", RegexOptions.Singleline).Replace(table, "");
118 | table = new Regex(@" (cellpadding|cellspacing|border|colspan|height|width|class)=.+?(?= |>)", RegexOptions.Singleline).Replace(table, "");
119 | table = new Regex(@"(.+?)", RegexOptions.Singleline).Replace(table, "$1");
120 | table = new Regex(@"(.+?)", RegexOptions.Singleline).Replace(table, "$1");
121 |
122 | var doc = new XmlDocument();
123 | doc.LoadXml($"""
124 |
125 | {table}
126 | """
127 | );
128 |
129 | var list = new List();
130 | var start = false;
131 | Model pre = null;
132 |
133 | foreach (XmlNode child in doc.DocumentElement.ChildNodes)
134 | {
135 | if (child.ChildNodes[1].InnerText == "行政区划代码")
136 | {
137 | start = true;
138 | continue;
139 | }
140 |
141 | if (start)
142 | {
143 | var col2 = child.ChildNodes[2].InnerText;
144 | if (!string.IsNullOrEmpty(col2))
145 | {
146 | var level = col2.StartsWith(" ") ? 2
147 | : col2.StartsWith(" ") ? 1
148 | : 0;
149 | var name = col2.Trim();
150 |
151 | Model item;
152 | if (level == 2 && pre.Level == 0)
153 | {
154 | item = new Model
155 | {
156 | Level = 1,
157 | Code = pre.Code,
158 | Name = pre.Name,
159 | };
160 | list.Add(item);
161 | pre = item;
162 | }
163 |
164 | var col1 = child.ChildNodes[1].InnerText.Trim();
165 | if (int.TryParse(col1, out var _code))
166 | {
167 | var code = _code.ToString();
168 | item = new()
169 | {
170 | Level = level,
171 | Code = code,
172 | Name = name,
173 | };
174 | }
175 | else
176 | {
177 | item = new()
178 | {
179 | Level = level,
180 | Code = pre.Code,
181 | Name = name,
182 | };
183 | }
184 |
185 | list.Add(item);
186 | pre = item;
187 | }
188 | else break;
189 | }
190 | }
191 |
192 | return list;
193 | }
194 | #>
195 |
--------------------------------------------------------------------------------
/Chinese.Region/ICodeName.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Mainland;
2 |
3 | public interface ICodeName
4 | {
5 | string Code { get; set; }
6 | string Name { get; set; }
7 | }
8 |
--------------------------------------------------------------------------------
/Chinese.Region/Model.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Mainland;
2 |
3 | internal class Model : ICodeName
4 | {
5 | public required int Level { get; set; }
6 | public required string Code { get; set; }
7 | public required string Name { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/Chinese.Region/Province.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Mainland;
2 |
3 | public class Province : ICodeName
4 | {
5 | public required string Code { get; set; }
6 | public required string Name { get; set; }
7 | public required ICollection Cities { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/Chinese.Test/Chinese.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | false
6 | preview
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Chinese.Test/ChineseConverterTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace Chinese.Test
4 | {
5 | public class ChineseConverterTests
6 | {
7 | [Fact]
8 | public void Test1()
9 | {
10 | Assert.Equal("免費,跨平臺,開源!", ChineseConverter.ToTraditional("免费,跨平台,开源!"));
11 | Assert.Equal("免费,跨平台,开源!", ChineseConverter.ToSimplified("免費,跨平臺,開源!"));
12 | }
13 |
14 | [Fact]
15 | public void Test2()
16 | {
17 | Assert.Equal("皇后在國王后面。", ChineseConverter.ToTraditional("皇后在国王后面。"));
18 |
19 | var words = new[]
20 | {
21 | new ChineseWord { Simplified = "皇后", Traditional = "皇后", Pinyin = "huang2 hou4" },
22 | new ChineseWord { Simplified = "后面", Traditional = "後面", Pinyin = "hou4 mian4" },
23 | };
24 |
25 | using (new ChineseLexicon(Builtin.ChineseChars, words).BeginScope())
26 | {
27 | Assert.Equal("皇后在國王後面。", ChineseConverter.ToTraditional("皇后在国王后面。"));
28 | }
29 | }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Chinese.Test/ChineseCurrencyTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace Chinese.Test
4 | {
5 | public class ChineseCurrencyTests
6 | {
7 | [Fact]
8 | public void LastZeroTest()
9 | {
10 | ChineseCurrency.GetString(10203040);
11 |
12 | var options = new ChineseNumberOptions { Simplified = false, Upper = false };
13 | Assert.Equal("一十万元整", ChineseCurrency.GetString(10_0000m, options));
14 | Assert.Equal("一十亿元整", ChineseCurrency.GetString(10_0000_0000m, options));
15 | Assert.Equal("一十亿零一元整", ChineseCurrency.GetString(10_0000_0001m, options));
16 | Assert.Equal("一十亿零一千零一元整", ChineseCurrency.GetString(10_0000_1001m, options));
17 | Assert.Equal("一十亿零一百万一千零一元整", ChineseCurrency.GetString(10_0100_1001m, options));
18 | Assert.Equal("一千零二十万三千零四十元整", ChineseCurrency.GetString(1020_3040m, options));
19 |
20 | Assert.Equal(10_0000m, ChineseCurrency.GetNumber("一十万元整"));
21 | Assert.Equal(10_0000_0000m, ChineseCurrency.GetNumber("一十亿元整"));
22 | Assert.Equal(10_0000_0001m, ChineseCurrency.GetNumber("一十亿零一元整"));
23 | Assert.Equal(10_0000_1001m, ChineseCurrency.GetNumber("一十亿零一千零一元整"));
24 | Assert.Equal(10_0100_1001m, ChineseCurrency.GetNumber("一十亿零一百万一千零一元整"));
25 | Assert.Equal(1020_3040m, ChineseCurrency.GetNumber("一千零二十万三千零四十元整"));
26 | }
27 |
28 |
29 | [Fact]
30 | public void LowerTest()
31 | {
32 | var options = new ChineseNumberOptions { Simplified = false, Upper = false };
33 | Assert.Equal("一元整", ChineseCurrency.GetString(1, options));
34 | Assert.Equal("一十万零一元整", ChineseCurrency.GetString(10_0001, options));
35 | Assert.Equal("一十万零一百零一元整", ChineseCurrency.GetString(10_0101, options));
36 | Assert.Equal("一十万一千零一元整", ChineseCurrency.GetString(10_1001, options));
37 | Assert.Equal("一十万一千零一十元整", ChineseCurrency.GetString(10_1010, options));
38 | Assert.Equal("一十万零一元二角整", ChineseCurrency.GetString(10_0001.2m, options));
39 | Assert.Equal("一十万零一元二角三分", ChineseCurrency.GetString(10_0001.23m, options));
40 | Assert.Equal("一十万零一元零三分", ChineseCurrency.GetString(10_0001.03m, options));
41 |
42 | Assert.Equal(1, ChineseCurrency.GetNumber("一元整"));
43 | Assert.Equal(10_0001, ChineseCurrency.GetNumber("一十万零一元整"));
44 | Assert.Equal(10_0101, ChineseCurrency.GetNumber("一十万零一百零一元整"));
45 | Assert.Equal(10_1001, ChineseCurrency.GetNumber("一十万一千零一元整"));
46 | Assert.Equal(10_1010, ChineseCurrency.GetNumber("一十万一千零一十元整"));
47 | Assert.Equal(10_0001.2m, ChineseCurrency.GetNumber("一十万零一元二角整"));
48 | Assert.Equal(10_0001.23m, ChineseCurrency.GetNumber("一十万零一元二角三分"));
49 | Assert.Equal(10_0001.03m, ChineseCurrency.GetNumber("一十万零一元零三分"));
50 | }
51 |
52 | [Fact]
53 | public void SimplifiedLowerTest()
54 | {
55 | var options = new ChineseNumberOptions { Simplified = true, Upper = false };
56 | Assert.Equal("一元整", ChineseCurrency.GetString(1, options));
57 | Assert.Equal("十万零一元整", ChineseCurrency.GetString(10_0001, options));
58 | Assert.Equal("十万零一百零一元整", ChineseCurrency.GetString(10_0101, options));
59 | Assert.Equal("十万一千零一元整", ChineseCurrency.GetString(10_1001, options));
60 | Assert.Equal("十万一千零一十元整", ChineseCurrency.GetString(10_1010, options));
61 | Assert.Equal("十万零一元二角整", ChineseCurrency.GetString(10_0001.2m, options));
62 | Assert.Equal("十万零一元二角三分", ChineseCurrency.GetString(10_0001.23m, options));
63 | Assert.Equal("十万零一元零三分", ChineseCurrency.GetString(10_0001.03m, options));
64 |
65 | Assert.Equal(1, ChineseCurrency.GetNumber("一元整"));
66 | Assert.Equal(10_0001, ChineseCurrency.GetNumber("十万零一元整"));
67 | Assert.Equal(10_0101, ChineseCurrency.GetNumber("十万零一百零一元整"));
68 | Assert.Equal(10_1001, ChineseCurrency.GetNumber("十万一千零一元整"));
69 | Assert.Equal(10_1010, ChineseCurrency.GetNumber("十万一千零一十元整"));
70 | Assert.Equal(10_0001.2m, ChineseCurrency.GetNumber("十万零一元二角整"));
71 | Assert.Equal(10_0001.23m, ChineseCurrency.GetNumber("十万零一元二角三分"));
72 | Assert.Equal(10_0001.03m, ChineseCurrency.GetNumber("十万零一元零三分"));
73 | }
74 |
75 | [Fact]
76 | public void UpperTest()
77 | {
78 | var options = new ChineseNumberOptions { Simplified = false, Upper = true };
79 | Assert.Equal("壹圆整", ChineseCurrency.GetString(1, options));
80 | Assert.Equal("壹拾万零壹圆整", ChineseCurrency.GetString(10_0001, options));
81 | Assert.Equal("壹拾万零壹佰零壹圆整", ChineseCurrency.GetString(10_0101, options));
82 | Assert.Equal("壹拾万壹仟零壹圆整", ChineseCurrency.GetString(10_1001, options));
83 | Assert.Equal("壹拾万壹仟零壹拾圆整", ChineseCurrency.GetString(10_1010, options));
84 | Assert.Equal("壹拾万零壹圆贰角整", ChineseCurrency.GetString(10_0001.2m, options));
85 | Assert.Equal("壹拾万零壹圆贰角叁分", ChineseCurrency.GetString(10_0001.23m, options));
86 | Assert.Equal("壹拾万零壹圆零叁分", ChineseCurrency.GetString(10_0001.03m, options));
87 |
88 | Assert.Equal(1, ChineseCurrency.GetNumber("壹圆整"));
89 | Assert.Equal(10_0001, ChineseCurrency.GetNumber("壹拾万零壹圆整"));
90 | Assert.Equal(10_0101, ChineseCurrency.GetNumber("壹拾万零壹佰零壹圆整"));
91 | Assert.Equal(10_1001, ChineseCurrency.GetNumber("壹拾万壹仟零壹圆整"));
92 | Assert.Equal(10_1010, ChineseCurrency.GetNumber("壹拾万壹仟零壹拾圆整"));
93 | Assert.Equal(10_0001.2m, ChineseCurrency.GetNumber("壹拾万零壹圆贰角整"));
94 | Assert.Equal(10_0001.23m, ChineseCurrency.GetNumber("壹拾万零壹圆贰角叁分"));
95 | Assert.Equal(10_0001.03m, ChineseCurrency.GetNumber("壹拾万零壹圆零叁分"));
96 | }
97 |
98 | [Fact]
99 | public void SimplifiedUpperTest()
100 | {
101 | var options = new ChineseNumberOptions { Simplified = true, Upper = true };
102 | Assert.Equal("壹圆整", ChineseCurrency.GetString(1, options));
103 | Assert.Equal("拾万零壹圆整", ChineseCurrency.GetString(10_0001, options));
104 | Assert.Equal("拾万零壹佰零壹圆整", ChineseCurrency.GetString(10_0101, options));
105 | Assert.Equal("拾万壹仟零壹圆整", ChineseCurrency.GetString(10_1001, options));
106 | Assert.Equal("拾万壹仟零壹拾圆整", ChineseCurrency.GetString(10_1010, options));
107 | Assert.Equal("拾万零壹圆贰角整", ChineseCurrency.GetString(10_0001.2m, options));
108 | Assert.Equal("拾万零壹圆贰角叁分", ChineseCurrency.GetString(10_0001.23m, options));
109 | Assert.Equal("拾万零壹圆零叁分", ChineseCurrency.GetString(10_0001.03m, options));
110 |
111 | Assert.Equal(1, ChineseCurrency.GetNumber("壹圆整"));
112 | Assert.Equal(10_0001, ChineseCurrency.GetNumber("拾万零壹圆整"));
113 | Assert.Equal(10_0101, ChineseCurrency.GetNumber("拾万零壹佰零壹圆整"));
114 | Assert.Equal(10_1001, ChineseCurrency.GetNumber("拾万壹仟零壹圆整"));
115 | Assert.Equal(10_1010, ChineseCurrency.GetNumber("拾万壹仟零壹拾圆整"));
116 | Assert.Equal(10_0001.2m, ChineseCurrency.GetNumber("拾万零壹圆贰角整"));
117 | Assert.Equal(10_0001.23m, ChineseCurrency.GetNumber("拾万零壹圆贰角叁分"));
118 | Assert.Equal(10_0001.03m, ChineseCurrency.GetNumber("拾万零壹圆零叁分"));
119 | }
120 |
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Chinese.Test/ChineseNumberTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 |
4 | namespace Chinese.Test
5 | {
6 | public class ChineseNumberTests
7 | {
8 | [Fact]
9 | public void LowerTest()
10 | {
11 | var options = new ChineseNumberOptions { Simplified = false, Upper = false };
12 | Assert.Equal("一", ChineseNumber.GetString(1, options));
13 | Assert.Equal("一十万零一", ChineseNumber.GetString(10_0001, options));
14 | Assert.Equal("一十万零一百零一", ChineseNumber.GetString(10_0101, options));
15 | Assert.Equal("一十万一千零一", ChineseNumber.GetString(10_1001, options));
16 | Assert.Equal("一十万一千零一十", ChineseNumber.GetString(10_1010, options));
17 |
18 | Assert.Equal(1, ChineseNumber.GetNumber("一"));
19 | Assert.Equal(10_0001, ChineseNumber.GetNumber("一十万零一"));
20 | Assert.Equal(10_0101, ChineseNumber.GetNumber("一十万零一百零一"));
21 | Assert.Equal(10_1001, ChineseNumber.GetNumber("一十万一千零一"));
22 | Assert.Equal(10_1010, ChineseNumber.GetNumber("一十万一千零一十"));
23 | }
24 |
25 | [Fact]
26 | public void SimplifiedLowerTest()
27 | {
28 | var options = new ChineseNumberOptions { Simplified = true, Upper = false };
29 | Assert.Equal("一", ChineseNumber.GetString(1, options));
30 | Assert.Equal("十万零一", ChineseNumber.GetString(10_0001, options));
31 | Assert.Equal("十万零一百零一", ChineseNumber.GetString(10_0101, options));
32 | Assert.Equal("十万一千零一", ChineseNumber.GetString(10_1001, options));
33 | Assert.Equal("十万一千零一十", ChineseNumber.GetString(10_1010, options));
34 |
35 | Assert.Equal(1, ChineseNumber.GetNumber("一"));
36 | Assert.Equal(10_0001, ChineseNumber.GetNumber("十万零一"));
37 | Assert.Equal(10_0101, ChineseNumber.GetNumber("十万零一百零一"));
38 | Assert.Equal(10_1001, ChineseNumber.GetNumber("十万一千零一"));
39 | Assert.Equal(10_1010, ChineseNumber.GetNumber("十万一千零一十"));
40 | }
41 |
42 | [Fact]
43 | public void UpperTest()
44 | {
45 | var options = new ChineseNumberOptions { Simplified = false, Upper = true };
46 | Assert.Equal("壹", ChineseNumber.GetString(1, options));
47 | Assert.Equal("壹拾万零壹", ChineseNumber.GetString(10_0001, options));
48 | Assert.Equal("壹拾万零壹佰零壹", ChineseNumber.GetString(10_0101, options));
49 | Assert.Equal("壹拾万壹仟零壹", ChineseNumber.GetString(10_1001, options));
50 | Assert.Equal("壹拾万壹仟零壹拾", ChineseNumber.GetString(10_1010, options));
51 |
52 | Assert.Equal(1, ChineseNumber.GetNumber("壹"));
53 | Assert.Equal(10_0001, ChineseNumber.GetNumber("壹拾万零壹"));
54 | Assert.Equal(10_0101, ChineseNumber.GetNumber("壹拾万零壹佰零壹"));
55 | Assert.Equal(10_1001, ChineseNumber.GetNumber("壹拾万壹仟零壹"));
56 | Assert.Equal(10_1010, ChineseNumber.GetNumber("壹拾万壹仟零壹拾"));
57 | }
58 |
59 | [Fact]
60 | public void SimplifiedUpperTest()
61 | {
62 | var options = new ChineseNumberOptions { Simplified = true, Upper = true };
63 | Assert.Equal("壹", ChineseNumber.GetString(1, options));
64 | Assert.Equal("拾万零壹", ChineseNumber.GetString(10_0001, options));
65 | Assert.Equal("拾万零壹佰零壹", ChineseNumber.GetString(10_0101, options));
66 | Assert.Equal("拾万壹仟零壹", ChineseNumber.GetString(10_1001, options));
67 | Assert.Equal("拾万壹仟零壹拾", ChineseNumber.GetString(10_1010, options));
68 |
69 | Assert.Equal(1, ChineseNumber.GetNumber("壹"));
70 | Assert.Equal(10_0001, ChineseNumber.GetNumber("拾万零壹"));
71 | Assert.Equal(10_0101, ChineseNumber.GetNumber("拾万零壹佰零壹"));
72 | Assert.Equal(10_1001, ChineseNumber.GetNumber("拾万壹仟零壹"));
73 | Assert.Equal(10_1010, ChineseNumber.GetNumber("拾万壹仟零壹拾"));
74 | }
75 |
76 | [Fact]
77 | public void CodeLowerTest()
78 | {
79 | Assert.Equal("一〇〇〇〇一", ChineseNumber.GetCodeString(10_0001.ToString(), upper: false));
80 | Assert.Equal("一〇〇一〇一", ChineseNumber.GetCodeString(10_0101.ToString(), upper: false));
81 | Assert.Equal("一〇一〇〇一", ChineseNumber.GetCodeString(10_1001.ToString(), upper: false));
82 | Assert.Equal("一〇一〇一〇", ChineseNumber.GetCodeString(10_1010.ToString(), upper: false));
83 |
84 | Assert.Equal(10_0001.ToString(), ChineseNumber.GetCodeNumber("一〇〇〇〇一"));
85 | Assert.Equal(10_0101.ToString(), ChineseNumber.GetCodeNumber("一〇〇一〇一"));
86 | Assert.Equal(10_1001.ToString(), ChineseNumber.GetCodeNumber("一〇一〇〇一"));
87 | Assert.Equal(10_1010.ToString(), ChineseNumber.GetCodeNumber("一〇一〇一〇"));
88 | }
89 |
90 | [Fact]
91 | public void CodeUpperTest()
92 | {
93 | Assert.Equal("壹零零零零壹", ChineseNumber.GetCodeString(10_0001.ToString(), upper: true));
94 | Assert.Equal("壹零零壹零壹", ChineseNumber.GetCodeString(10_0101.ToString(), upper: true));
95 | Assert.Equal("壹零壹零零壹", ChineseNumber.GetCodeString(10_1001.ToString(), upper: true));
96 | Assert.Equal("壹零壹零壹零", ChineseNumber.GetCodeString(10_1010.ToString(), upper: true));
97 |
98 | Assert.Equal(10_0001.ToString(), ChineseNumber.GetCodeNumber("壹零零零零壹"));
99 | Assert.Equal(10_0101.ToString(), ChineseNumber.GetCodeNumber("壹零零壹零壹"));
100 | Assert.Equal(10_1001.ToString(), ChineseNumber.GetCodeNumber("壹零壹零零壹"));
101 | Assert.Equal(10_1010.ToString(), ChineseNumber.GetCodeNumber("壹零壹零壹零"));
102 | }
103 |
104 | [Fact]
105 | public void BigIntegerTest()
106 | {
107 | Assert.Equal("一穰二千三百四十五秭六千七百八十九垓零一百二十三京四千五百六十七兆八千九百零一亿二千三百四十五万六千七百八十九", ChineseNumber.GetString(1_2345_6789_0123_4567_8901_2345_6789m));
108 | Assert.Equal("壹穰贰仟叁佰肆拾伍秭陆仟柒佰捌拾玖垓零壹佰贰拾叁京肆仟伍佰陆拾柒兆捌仟玖佰零壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖", ChineseNumber.GetString(1_2345_6789_0123_4567_8901_2345_6789m, x => x.Upper = true));
109 |
110 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, ChineseNumber.GetNumber("一穰二千三百四十五秭六千七百八十九垓零一百二十三京四千五百六十七兆八千九百零一亿二千三百四十五万六千七百八十九"));
111 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, ChineseNumber.GetNumber("壹穰贰仟叁佰肆拾伍秭陆仟柒佰捌拾玖垓零壹佰贰拾叁京肆仟伍佰陆拾柒兆捌仟玖佰零壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖"));
112 | }
113 |
114 | [Fact]
115 | public void MutilZeroTest()
116 | {
117 | Assert.Equal("二十亿零一", ChineseNumber.GetString(20_0000_0001));
118 | Assert.Equal("二十兆零一", ChineseNumber.GetString(20_0000_0000_0001));
119 |
120 | Assert.Equal(20_0000_0001, ChineseNumber.GetNumber("二十亿零一"));
121 | Assert.Equal(20_0000_0000_0001, ChineseNumber.GetNumber("二十兆零一"));
122 | }
123 |
124 | [Fact]
125 | public void AliasTest()
126 | {
127 | Assert.Equal(22222, ChineseNumber.GetNumber("两万二千两百二十二"));
128 | Assert.Throws(() => ChineseNumber.GetNumber("两"));
129 | Assert.Throws(() => ChineseNumber.GetNumber("两万二千两百二十两"));
130 | }
131 |
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/Chinese.Test/ChineseTokenizerTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace Chinese.Test
4 | {
5 | public class ChineseTokenizerTests
6 | {
7 | [Fact]
8 | public void Test1()
9 | {
10 | using var tokenizer = new ChineseLexicon(Builtin.ChineseChars, new[]
11 | {
12 | new ChineseWord { Simplified = "中国", Traditional = "中國", Pinyin = "zhong1 guo2" },
13 | new ChineseWord { Word = "北京", Pinyin = "bei3 jing1" },
14 | new ChineseWord { Simplified = "重庆", Traditional = "重慶", Pinyin = "chong2 qing4" },
15 | new ChineseWord { Simplified = "直辖市", Traditional = "直轄市", Pinyin = "zhi2 xia2 shi4" },
16 | }).BeginScope();
17 |
18 | var sentence = "中国北京是直辖市,重庆也是直辖市。";
19 | var actual = ChineseTokenizer.SplitWords(ChineseTypes.Simplified, sentence);
20 | var excepted = new[] { "中国", "北京", "是", "直辖市", ",", "重庆", "也", "是", "直辖市", "。" };
21 | var pinyin = Pinyin.GetString(sentence, PinyinFormat.Phonetic);
22 |
23 | Assert.Equal(excepted, actual);
24 | Assert.Equal("zhōng guó běi jīng shì zhí xiá shì,chóng qìng yě shì zhí xiá shì。", pinyin);
25 | }
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Chinese.Test/PinyinTest.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | namespace Chinese.Test
4 | {
5 | public class PinyinTest
6 | {
7 | [Fact]
8 | public void TmpTest1()
9 | {
10 | }
11 |
12 | [Fact]
13 | public void Test1()
14 | {
15 | var str = "免费,跨平台,开源!";
16 | Assert.Equal("mian3 fei4,kua4 ping2 tai2,kai1 yuan2!", Pinyin.GetString(str, PinyinFormat.Default));
17 | Assert.Equal("mian fei,kua ping tai,kai yuan!", Pinyin.GetString(str, PinyinFormat.WithoutTone));
18 | Assert.Equal("miǎn fèi,kuà píng tái,kāi yuán!", Pinyin.GetString(str, PinyinFormat.Phonetic));
19 | Assert.Equal("mf,kpt,ky!", Pinyin.GetString(str, PinyinFormat.InitialConsonant));
20 | }
21 |
22 | [Fact]
23 | public void ChineseLexiconTest1()
24 | {
25 | var str = "他是来自重庆的重量级选手。";
26 | var pinyin = Pinyin.GetString(str, PinyinFormat.Default);
27 | Assert.Equal("ta1 shi4 lai2 zi4 zhong4 qing4 de5 zhong4 liang4 ji2 xuan3 shou3。", pinyin);
28 |
29 | var words = new ChineseWord[]
30 | {
31 | new ChineseWord { Simplified = "重庆", Traditional = "重慶", Pinyin = "chong2 qing4" },
32 | new ChineseWord { Simplified = "重量", Traditional = "重量", Pinyin = "zhong4 liang4" },
33 | };
34 |
35 | using (new ChineseLexicon(Builtin.ChineseChars, words).BeginScope())
36 | {
37 | Assert.Equal("ta1 shi4 lai2 zi4 chong2 qing4 de5 zhong4 liang4 ji2 xuan3 shou3。", Pinyin.GetString(str, PinyinFormat.Default));
38 | }
39 | }
40 |
41 | [Fact]
42 | public void ChineseLexiconTest2()
43 | {
44 | Assert.Equal("服務器中止了服務。", ChineseConverter.ToTraditional("服务器中止了服务。"));
45 |
46 | var words = new[]
47 | {
48 | new ChineseWord { Simplified = "服务器", Traditional = "伺服器", SimplifiedPinyin = "fu2 wu4 qi4", TraditionalPinyin = "si4 fu2 qi4" },
49 | };
50 |
51 | using (new ChineseLexicon(Builtin.ChineseChars, words).BeginScope())
52 | {
53 | Assert.Equal("伺服器中止了服務。", ChineseConverter.ToTraditional("服务器中止了服务。"));
54 | Assert.Equal("fu2 wu4 qi4 zhong1 zhi3 le5 fu2 wu4。", Pinyin.GetString(ChineseTypes.Simplified, "服务器中止了服务。"));
55 | Assert.Equal("si4 fu2 qi4 zhong1 zhi3 le5 fu2 wu4。", Pinyin.GetString(ChineseTypes.Traditional, "伺服器中止了服務。"));
56 | }
57 | }
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Chinese.lutconfig:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | true
5 | 180000
6 |
--------------------------------------------------------------------------------
/Chinese.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmjack/Chinese/92a75fbdbc4f310257211256d557101544e32b3c/Chinese.png
--------------------------------------------------------------------------------
/Chinese.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32210.238
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chinese", "Chinese\Chinese.csproj", "{52E605E4-17C4-4B45-8159-4804653592A7}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9C18C921-F5AD-4B85-AB91-DB23E38991C7}"
9 | ProjectSection(SolutionItems) = preProject
10 | LICENSE.md = LICENSE.md
11 | push.cmd = push.cmd
12 | README.md = README.md
13 | EndProjectSection
14 | EndProject
15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9E0D9B3-382B-4C6F-AF78-87C3D1BFA458}"
16 | EndProject
17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chinese.Test", "Tests\Chinese.Test\Chinese.Test.csproj", "{F1C9D79A-9CC2-4832-BBD7-3040833B30A9}"
18 | EndProject
19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbCreator.MySql", "Tests\DbCreator.MySql\DbCreator.MySql.csproj", "{A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chinese.Lexicon", "Chinese.Lexicon\Chinese.Lexicon.csproj", "{0A8968BC-6BFD-450D-A912-DF071B3B5A8C}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chinese.Abstract", "Chinese.Abstract\Chinese.Abstract.csproj", "{ED49ED61-0BC1-4679-84B9-A14903064EFF}"
24 | EndProject
25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChineseApp", "ChineseApp\ChineseApp.csproj", "{D5538A26-2797-417C-8B8D-892799D47A7F}"
26 | EndProject
27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chinese.Region", "Chinese.Region\Chinese.Region.csproj", "{B147BCEE-BF76-4130-BE05-3E223A841213}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LexiconBuilder", "LexiconBuilder\LexiconBuilder.csproj", "{48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}"
30 | EndProject
31 | Global
32 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
33 | Debug|Any CPU = Debug|Any CPU
34 | Debug|x64 = Debug|x64
35 | Debug|x86 = Debug|x86
36 | Release|Any CPU = Release|Any CPU
37 | Release|x64 = Release|x64
38 | Release|x86 = Release|x86
39 | EndGlobalSection
40 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
41 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|x64.ActiveCfg = Debug|Any CPU
44 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|x64.Build.0 = Debug|Any CPU
45 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|x86.ActiveCfg = Debug|Any CPU
46 | {52E605E4-17C4-4B45-8159-4804653592A7}.Debug|x86.Build.0 = Debug|Any CPU
47 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|x64.ActiveCfg = Release|Any CPU
50 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|x64.Build.0 = Release|Any CPU
51 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|x86.ActiveCfg = Release|Any CPU
52 | {52E605E4-17C4-4B45-8159-4804653592A7}.Release|x86.Build.0 = Release|Any CPU
53 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|x64.ActiveCfg = Debug|Any CPU
56 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|x64.Build.0 = Debug|Any CPU
57 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|x86.ActiveCfg = Debug|Any CPU
58 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Debug|x86.Build.0 = Debug|Any CPU
59 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|x64.ActiveCfg = Release|Any CPU
62 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|x64.Build.0 = Release|Any CPU
63 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|x86.ActiveCfg = Release|Any CPU
64 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9}.Release|x86.Build.0 = Release|Any CPU
65 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|x64.ActiveCfg = Debug|Any CPU
68 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|x64.Build.0 = Debug|Any CPU
69 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|x86.ActiveCfg = Debug|Any CPU
70 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Debug|x86.Build.0 = Debug|Any CPU
71 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|Any CPU.ActiveCfg = Release|Any CPU
72 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|Any CPU.Build.0 = Release|Any CPU
73 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|x64.ActiveCfg = Release|Any CPU
74 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|x64.Build.0 = Release|Any CPU
75 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|x86.ActiveCfg = Release|Any CPU
76 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C}.Release|x86.Build.0 = Release|Any CPU
77 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
79 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|x64.ActiveCfg = Debug|Any CPU
80 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|x64.Build.0 = Debug|Any CPU
81 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|x86.ActiveCfg = Debug|Any CPU
82 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Debug|x86.Build.0 = Debug|Any CPU
83 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
84 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|Any CPU.Build.0 = Release|Any CPU
85 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|x64.ActiveCfg = Release|Any CPU
86 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|x64.Build.0 = Release|Any CPU
87 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|x86.ActiveCfg = Release|Any CPU
88 | {0A8968BC-6BFD-450D-A912-DF071B3B5A8C}.Release|x86.Build.0 = Release|Any CPU
89 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
90 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
91 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|x64.ActiveCfg = Debug|Any CPU
92 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|x64.Build.0 = Debug|Any CPU
93 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|x86.ActiveCfg = Debug|Any CPU
94 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Debug|x86.Build.0 = Debug|Any CPU
95 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
96 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|Any CPU.Build.0 = Release|Any CPU
97 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|x64.ActiveCfg = Release|Any CPU
98 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|x64.Build.0 = Release|Any CPU
99 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|x86.ActiveCfg = Release|Any CPU
100 | {ED49ED61-0BC1-4679-84B9-A14903064EFF}.Release|x86.Build.0 = Release|Any CPU
101 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
102 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
103 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|x64.ActiveCfg = Debug|Any CPU
104 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|x64.Build.0 = Debug|Any CPU
105 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|x86.ActiveCfg = Debug|Any CPU
106 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Debug|x86.Build.0 = Debug|Any CPU
107 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
108 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|Any CPU.Build.0 = Release|Any CPU
109 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|x64.ActiveCfg = Release|Any CPU
110 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|x64.Build.0 = Release|Any CPU
111 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|x86.ActiveCfg = Release|Any CPU
112 | {D5538A26-2797-417C-8B8D-892799D47A7F}.Release|x86.Build.0 = Release|Any CPU
113 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
114 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|Any CPU.Build.0 = Debug|Any CPU
115 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|x64.ActiveCfg = Debug|Any CPU
116 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|x64.Build.0 = Debug|Any CPU
117 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|x86.ActiveCfg = Debug|Any CPU
118 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Debug|x86.Build.0 = Debug|Any CPU
119 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|Any CPU.ActiveCfg = Release|Any CPU
120 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|Any CPU.Build.0 = Release|Any CPU
121 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|x64.ActiveCfg = Release|Any CPU
122 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|x64.Build.0 = Release|Any CPU
123 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|x86.ActiveCfg = Release|Any CPU
124 | {B147BCEE-BF76-4130-BE05-3E223A841213}.Release|x86.Build.0 = Release|Any CPU
125 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
126 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
127 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|x64.ActiveCfg = Debug|Any CPU
128 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|x64.Build.0 = Debug|Any CPU
129 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|x86.ActiveCfg = Debug|Any CPU
130 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Debug|x86.Build.0 = Debug|Any CPU
131 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
132 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|Any CPU.Build.0 = Release|Any CPU
133 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|x64.ActiveCfg = Release|Any CPU
134 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|x64.Build.0 = Release|Any CPU
135 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|x86.ActiveCfg = Release|Any CPU
136 | {48FFAC19-3D9A-4C6F-BB63-3B060536A8C7}.Release|x86.Build.0 = Release|Any CPU
137 | EndGlobalSection
138 | GlobalSection(SolutionProperties) = preSolution
139 | HideSolutionNode = FALSE
140 | EndGlobalSection
141 | GlobalSection(NestedProjects) = preSolution
142 | {F1C9D79A-9CC2-4832-BBD7-3040833B30A9} = {D9E0D9B3-382B-4C6F-AF78-87C3D1BFA458}
143 | {A4AC1F3A-94E5-41AF-A8ED-51480D01D30C} = {D9E0D9B3-382B-4C6F-AF78-87C3D1BFA458}
144 | EndGlobalSection
145 | GlobalSection(ExtensibilityGlobals) = postSolution
146 | SolutionGuid = {B428A319-CD27-4E8D-AAEF-BE69A7F02F09}
147 | EndGlobalSection
148 | EndGlobal
149 |
--------------------------------------------------------------------------------
/Chinese/Chinese.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net7.0;net8.0
5 | preview
6 | enable
7 | 0.8.1-alpha
8 | zmjack
9 | 中文解析通用工具。包括拼音,简繁转换,数字读法,货币读法。
10 | Copyright © nstandard.net 2023
11 | Chinese
12 | LICENSE.md
13 | https://github.com/zmjack/Chinese
14 | Chinese.png
15 | https://github.com/zmjack/Chinese
16 | git
17 | Chinese Pinyin Numerics
18 | true
19 | README.md
20 |
21 |
22 |
23 |
24 | True
25 |
26 |
27 |
28 | True
29 |
30 |
31 |
32 | True
33 | \
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Chinese/Grammars/Grammar.cs:
--------------------------------------------------------------------------------
1 | #if NEW_FEATURE
2 | namespace Chinese.Grammars
3 | {
4 | public class Grammar
5 | {
6 | }
7 | }
8 | #endif
9 |
--------------------------------------------------------------------------------
/Chinese/Grammars/GrammarPart.cs:
--------------------------------------------------------------------------------
1 | #if NEW_FEATURE
2 | namespace Chinese.Grammars
3 | {
4 | public class GrammarPart
5 | {
6 | public WordType[][] WordClasses { get; private set; }
7 | private GrammarPart(WordType[][] wordClasses) { WordClasses = wordClasses; }
8 |
9 | public GrammarPart Subject = new GrammarPart(new[]
10 | {
11 | new[] { WordType.Noun },
12 | new[] { WordType.Pronoun },
13 | new[] { WordType.Time },
14 | new[] { WordType.Adjective },
15 | new[] { WordType.Verb },
16 | new[] { WordType.Numeral },
17 | new[] { WordType.Numeral, WordType.Quantity },
18 | });
19 | public GrammarPart Predicate = new GrammarPart(new[]
20 | {
21 | new[] { WordType.Verb },
22 | });
23 | }
24 | }
25 | #endif
26 |
--------------------------------------------------------------------------------
/Chinese/Grammars/WordType.cs:
--------------------------------------------------------------------------------
1 | #if NEW_FEATURE
2 | using Chinese.Attributes;
3 |
4 | namespace Chinese.Grammars
5 | {
6 | public enum WordType
7 | {
8 | ///
9 | /// 未知词
10 | ///
11 | [Abbreviation("un")] Unknown,
12 |
13 | ///
14 | /// 形容词
15 | ///
16 | [Abbreviation("d")] Adjective,
17 |
18 | ///
19 | /// 连词
20 | ///
21 | [Abbreviation("c")] Conjunction,
22 |
23 | ///
24 | /// 叹词
25 | ///
26 | [Abbreviation("e")] Exclamation,
27 |
28 | ///
29 | /// 成语
30 | ///
31 | [Abbreviation("i")] Idiom,
32 |
33 | ///
34 | /// 数词
35 | ///
36 | [Abbreviation("e")] Numeral,
37 |
38 | ///
39 | /// 名词
40 | ///
41 | [Abbreviation("n")] Noun,
42 |
43 | ///
44 | /// 拟声词
45 | ///
46 | [Abbreviation("o")] Onomatopoeia,
47 |
48 | ///
49 | /// 介词
50 | ///
51 | [Abbreviation("p")] Prepositional,
52 |
53 | ///
54 | /// 量词
55 | ///
56 | [Abbreviation("q")] Quantity,
57 |
58 | ///
59 | /// 代词
60 | ///
61 | [Abbreviation("r")] Pronoun,
62 |
63 | ///
64 | /// 处所词
65 | ///
66 | [Abbreviation("s")] Space,
67 |
68 | ///
69 | /// 时间词
70 | ///
71 | [Abbreviation("t")] Time,
72 |
73 | ///
74 | /// 助词
75 | ///
76 | [Abbreviation("u")] Auxiliary,
77 |
78 | ///
79 | /// 动词
80 | ///
81 | [Abbreviation("v")] Verb,
82 | }
83 |
84 | }
85 | #endif
86 |
--------------------------------------------------------------------------------
/Chinese/Lexicon.cs:
--------------------------------------------------------------------------------
1 | using NStandard;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using LinqSharp;
7 | using Chinese.Lexicons;
8 | using Microsoft.Extensions.Caching.Memory;
9 |
10 | namespace Chinese;
11 |
12 | public class Lexicon
13 | {
14 | private static ArgumentException NotSupportedChineseType(ChineseType chineseType, string argument) => new($"不支持的简繁类型({chineseType})。", argument);
15 |
16 | private readonly HashSet _wordSet = [];
17 | private int _maxWordLength = 0;
18 | private const int COMBINE_QUERY_COUNT = 100;
19 | private readonly List> _sourceList = [];
20 |
21 | private static readonly Lazy _number = new(() => new(new()));
22 | public static NumberLexicon Number => _number.Value;
23 |
24 | private static readonly MemoryCache _numberCache = new(new MemoryCacheOptions());
25 | public static NumberLexicon NumberWith(NumberMode mode)
26 | {
27 | return _numberCache.GetOrCreate(mode, entry =>
28 | {
29 | return new NumberLexicon(mode);
30 | });
31 | }
32 |
33 | private static readonly Lazy _currency = new(() => new(new()));
34 | public static CurrencyLexicon Currency => _currency.Value;
35 |
36 | private static readonly MemoryCache _currencyCache = new(new MemoryCacheOptions());
37 | public static CurrencyLexicon CurrencyWith(NumberMode mode)
38 | {
39 | return _currencyCache.GetOrCreate(mode, entry =>
40 | {
41 | return new CurrencyLexicon(mode);
42 | });
43 | }
44 |
45 | private IEnumerable> GetSources()
46 | {
47 | yield return _wordSet;
48 |
49 | foreach (var source in _sourceList)
50 | {
51 | yield return source;
52 | }
53 | }
54 |
55 | public Lexicon()
56 | {
57 | }
58 |
59 | public void Add(IWord[] words)
60 | {
61 | foreach (var word in words)
62 | {
63 | _wordSet.Add(word);
64 | var length = Math.Max(word.Simplified.Length, word.Traditional.Length);
65 | if (length > _maxWordLength)
66 | {
67 | _maxWordLength = length;
68 | }
69 | }
70 | }
71 |
72 | public void Add(IQueryable source)
73 | {
74 | _sourceList.Add(source);
75 |
76 | var length = source.Max(x => Math.Max(x.Simplified.Length, x.Traditional.Length));
77 | if (length > _maxWordLength)
78 | {
79 | _maxWordLength = length;
80 | }
81 | }
82 |
83 | public IEnumerable GetWords(ChineseType chineseType, string sentence)
84 | {
85 | if (sentence.Any())
86 | {
87 | var length = sentence.Length;
88 | for (int i = 0; i < length; i += COMBINE_QUERY_COUNT)
89 | {
90 | var prev = i - 1;
91 | var start = prev < 0 ? 0 : prev;
92 | var end = i + COMBINE_QUERY_COUNT;
93 | end = end <= length ? end : length;
94 |
95 | var chunk = sentence[start..end];
96 | foreach (var word in GetSourceWords(chineseType, chunk))
97 | {
98 | yield return word;
99 | }
100 | }
101 |
102 | var sources = GetSources();
103 | var last = sentence[^1].ToString();
104 | foreach (var source in sources)
105 | {
106 | if (chineseType == ChineseType.Simplified)
107 | {
108 | var find = source.FirstOrDefault(x => x.Simplified == last);
109 | if (find is not null) yield return find;
110 | }
111 | else if (chineseType == ChineseType.Traditional)
112 | {
113 | var find = source.FirstOrDefault(x => x.Traditional == last);
114 | if (find is not null) yield return find;
115 | }
116 | else throw NotSupportedChineseType(chineseType, nameof(chineseType));
117 | }
118 | }
119 | }
120 |
121 | private IEnumerable GetSourceWords(ChineseType chineseType, string chunk)
122 | {
123 | var sources = GetSources();
124 | foreach (IEnumerable source in sources)
125 | {
126 | IWord[] queryResult;
127 |
128 | if (chineseType == ChineseType.Simplified)
129 | {
130 | queryResult =
131 | [
132 | ..
133 | source.Filter(h =>
134 | {
135 | var exp = h.Empty;
136 | foreach (var window in chunk.Slide(2, true))
137 | {
138 | var ch0 = window[0];
139 | var ch1 = window[1];
140 |
141 | var ch_str = ch0.ToString();
142 | var str = $"{ch0}{ch1}";
143 | exp |= h.Where(x => x.Simplified == ch_str) | h.Where(x => x.Simplified.Contains(str));
144 | }
145 | return exp.DefaultIfEmpty(h.False);
146 | }),
147 | ];
148 | }
149 | else if (chineseType == ChineseType.Traditional)
150 | {
151 | queryResult =
152 | [
153 | ..
154 | source.Filter(h =>
155 | {
156 | var exp = h.Empty;
157 | foreach (var window in chunk.Slide(2, true))
158 | {
159 | var ch0 = window[0];
160 | var ch1 = window[1];
161 |
162 | var ch_str = ch0.ToString();
163 | var str = $"{ch0}{ch1}";
164 | exp |= h.Where(x => x.Traditional == ch_str) | h.Where(x => x.Traditional.Contains(str));
165 | }
166 | return exp.DefaultIfEmpty(h.False);
167 | }),
168 | ];
169 | }
170 | else throw NotSupportedChineseType(chineseType, nameof(chineseType));
171 |
172 | foreach (var word in queryResult)
173 | {
174 | yield return word;
175 | }
176 | }
177 | }
178 |
179 | private readonly char[] _punctuations = ['。', ',', '、', ';', ':', '?', '!', '…', '—', '·', 'ˉ', '¨', '‘', '’', '“', '”', '々', '~', '‖', '∶', '"', ''', '`', '|', '〃', '〔', '〕', '〈', '〉', '《', '》', '「', '」', '『', '』', '.', '〖', '〗', '【', '】', '(', ')', '[', ']', '{', '}'];
180 |
181 | ///
182 | /// 获取分词结果。
183 | ///
184 | ///
185 | ///
186 | ///
187 | public IWord[] SplitWords(string sentence, ChineseType chineseType)
188 | {
189 | var words = GetWords(chineseType, sentence).ToArray();
190 |
191 | var list = new LinkedList();
192 | var length = sentence.Length;
193 |
194 | var maxOffset = Math.Min(sentence.Length, _maxWordLength);
195 | var ptext = length - maxOffset;
196 | var maxLengthPerTurn = maxOffset;
197 | int matchLength;
198 |
199 | int Resolve(string part)
200 | {
201 | var word = chineseType switch
202 | {
203 | ChineseType.Simplified => words.FirstOrDefault(x => x.Simplified == part),
204 | ChineseType.Traditional => words.FirstOrDefault(x => x.Traditional == part),
205 | _ => throw NotSupportedChineseType(chineseType, nameof(chineseType)),
206 | };
207 |
208 | if (word is not null)
209 | {
210 | list.AddFirst(word);
211 | return part.Length;
212 | }
213 | else
214 | {
215 | if (part.Length == 1)
216 | {
217 | list.AddFirst(new ChineseWord
218 | {
219 | Simplified = part,
220 | SimplifiedPinyin = null,
221 | Traditional = part,
222 | TraditionalPinyin = null,
223 | });
224 | return 1;
225 | }
226 | }
227 |
228 | return 0;
229 | }
230 |
231 | for (; ptext + maxLengthPerTurn >= 0; ptext -= matchLength)
232 | {
233 | matchLength = 1;
234 | for (var i = ptext > 0 ? 0 : -ptext; i < maxLengthPerTurn;)
235 | {
236 | var part = sentence.Substring(ptext + i, maxLengthPerTurn - i);
237 |
238 | if (part.Length > 1)
239 | {
240 | var index = part.LastIndexOfAny(_punctuations);
241 | if (index > -1)
242 | {
243 | if (index == part.Length - 1)
244 | {
245 | if (Resolve(part[index].ToString()) != 0) break;
246 | else throw new NotImplementedException();
247 | }
248 | else
249 | {
250 | i += index + 1;
251 | continue;
252 | }
253 | }
254 | }
255 |
256 | var _matchLength = Resolve(part);
257 | if (_matchLength != 0)
258 | {
259 | matchLength = _matchLength;
260 | break;
261 | }
262 | else i++;
263 | }
264 | }
265 |
266 | return [.. list];
267 | }
268 |
269 | ///
270 | /// 转换指定字符串到繁体中文。
271 | ///
272 | ///
273 | ///
274 | public string ToTraditional(string chinese)
275 | {
276 | var words = SplitWords(chinese, ChineseType.Simplified);
277 | var sb = new StringBuilder(chinese.Length * 2);
278 |
279 | foreach (var word in words)
280 | {
281 | sb.Append(word?.Traditional);
282 | }
283 | return sb.ToString();
284 | }
285 |
286 | ///
287 | /// 转换指定字符串到简体中文。
288 | ///
289 | ///
290 | ///
291 | public string ToSimplified(string chinese)
292 | {
293 | var words = SplitWords(chinese, ChineseType.Traditional);
294 | var sb = new StringBuilder(chinese.Length * 2);
295 |
296 | foreach (var word in words)
297 | {
298 | sb.Append(word?.Simplified);
299 | }
300 | return sb.ToString();
301 | }
302 |
303 | ///
304 | /// 获取拼音(简体中文)
305 | ///
306 | ///
307 | ///
308 | ///
309 | public string GetPinyin(string chinese, PinyinFormat format = PinyinFormat.Default)
310 | {
311 | return GetPinyin(chinese, ChineseType.Simplified, format);
312 | }
313 |
314 | ///
315 | /// 获取指定类型字符串的拼音
316 | ///
317 | ///
318 | ///
319 | ///
320 | ///
321 | [Obsolete("Use GetPinyin(string chinese, ChineseType type, PinyinFormat format = PinyinFormat.Default) instead.")]
322 | public string GetPinyin(ChineseType type, string chinese, PinyinFormat format = PinyinFormat.Default)
323 | {
324 | return GetPinyin(chinese, type, format);
325 | }
326 |
327 | ///
328 | /// 获取指定类型字符串的拼音
329 | ///
330 | ///
331 | ///
332 | ///
333 | ///
334 | public string GetPinyin(string chinese, ChineseType type, PinyinFormat format = PinyinFormat.Default)
335 | {
336 | var words = SplitWords(chinese, type);
337 |
338 | if (!chinese.IsNullOrWhiteSpace())
339 | {
340 | var sb = new StringBuilder();
341 | var insertSpace = false;
342 | bool? prevLatin = null;
343 |
344 | foreach (var word in words)
345 | {
346 | var latin = false;
347 | var str = word.GetString(type);
348 | if (str?.Length == 1)
349 | {
350 | var ch = str.ToCharArray()[0];
351 | if ((int)ch is >= 0x21 and <= 0x7E)
352 | {
353 | latin = true;
354 | }
355 | }
356 |
357 | var pinyin = word.GetPinyin(type);
358 |
359 | if (pinyin is not null)
360 | {
361 | if ((prevLatin == true) || (insertSpace && format != PinyinFormat.InitialConsonant))
362 | {
363 | sb.Append(' ');
364 | }
365 |
366 | switch (format)
367 | {
368 | case PinyinFormat.Default: sb.Append(pinyin); break;
369 | case PinyinFormat.WithoutTone: sb.Append(GetPinyinWithoutTone(pinyin)); break;
370 | case PinyinFormat.Phonetic: sb.Append(GetPhoneticSymbol(pinyin)); break;
371 | case PinyinFormat.InitialConsonant: sb.Append(GetPinyinInitialConsonant(pinyin)); break;
372 | }
373 | insertSpace = true;
374 | prevLatin = false;
375 | }
376 | else
377 | {
378 | if (prevLatin.HasValue && !prevLatin.Value && latin)
379 | {
380 | sb.Append(' ');
381 | }
382 |
383 | sb.Append(word.GetString(type));
384 | insertSpace = false;
385 | prevLatin = latin;
386 | }
387 | }
388 |
389 | return sb.ToString();
390 | }
391 | return chinese;
392 | }
393 |
394 | private readonly static char[] one_to_five = ['1', '2', '3', '4', '5'];
395 |
396 | internal static string? GetPinyinInitialConsonant(string pinyin)
397 | {
398 | var parts = pinyin.Split(' ');
399 | var sb = new StringBuilder(parts.Length);
400 | foreach (var part in parts)
401 | {
402 | sb.Append(part[0]);
403 | }
404 | return sb.ToString();
405 | }
406 | internal static string? GetPinyinWithoutTone(string pinyin)
407 | {
408 | var sb = new StringBuilder(pinyin.Length);
409 | foreach (var ch in pinyin)
410 | {
411 | if (!one_to_five.Contains(ch)) sb.Append(ch);
412 | }
413 | return sb.ToString();
414 | }
415 | internal static string? GetPhoneticSymbol(string pinyin)
416 | {
417 | var parts = pinyin.Split(' ').Select(part =>
418 | {
419 | if (part.Length == 1) return part;
420 |
421 | var _pinyin = part.Slice(0, -1);
422 | var tone = part[^1];
423 |
424 | string yunmu;
425 |
426 | if (part.Contains("v")) yunmu = "v";
427 | else if (part.Contains("iu")) yunmu = "u";
428 | else if (part.Contains("ui")) yunmu = "i";
429 | else if (part.Contains("a")) yunmu = "a";
430 | else if (part.Contains("o")) yunmu = "o";
431 | else if (part.Contains("e")) yunmu = "e";
432 | else if (part.Contains("i")) yunmu = "i";
433 | else if (part.Contains("u")) yunmu = "u";
434 | else throw new InvalidCastException("Not a Pinyin.");
435 |
436 | var _yunmu = yunmu switch
437 | {
438 | "a" => tone switch { '1' => "ā", '2' => "á", '3' => "ǎ", '4' => "à", _ => "a" },
439 | "o" => tone switch { '1' => "ō", '2' => "ó", '3' => "ǒ", '4' => "ò", _ => "o" },
440 | "e" => tone switch { '1' => "ē", '2' => "é", '3' => "ě", '4' => "è", _ => "e" },
441 | "i" => tone switch { '1' => "ī", '2' => "í", '3' => "ǐ", '4' => "ì", _ => "i" },
442 | "u" => tone switch { '1' => "ū", '2' => "ú", '3' => "ǔ", '4' => "ù", _ => "u" },
443 | "v" => tone switch { '1' => "ǖ", '2' => "ǘ", '3' => "ǚ", '4' => "ǜ", _ => "ü" },
444 | _ => throw new NotImplementedException(),
445 | };
446 |
447 | return _pinyin.Replace(yunmu, _yunmu);
448 | });
449 |
450 | return parts.Join(" ");
451 | }
452 |
453 | }
454 |
--------------------------------------------------------------------------------
/Chinese/Lexicons/Builtin.cs:
--------------------------------------------------------------------------------
1 | namespace Chinese.Lexicons;
2 |
3 | public static class Builtin
4 | {
5 | public static readonly IWord[] NumericalWords =
6 | [
7 | new ChineseWord { Simplified = "壹", SimplifiedPinyin = "yi1", Traditional = "壹", TraditionalPinyin = "yi1", Tag = 1 },
8 | new ChineseWord { Simplified = "贰", SimplifiedPinyin = "er4", Traditional = "貳", TraditionalPinyin = "er4", Tag = 2 },
9 | new ChineseWord { Simplified = "叁", SimplifiedPinyin = "san1", Traditional = "叁", TraditionalPinyin = "san1", Tag = 3 },
10 | new ChineseWord { Simplified = "肆", SimplifiedPinyin = "si4", Traditional = "肆", TraditionalPinyin = "si4", Tag = 4 },
11 | new ChineseWord { Simplified = "伍", SimplifiedPinyin = "wu3", Traditional = "伍", TraditionalPinyin = "wu3", Tag = 5 },
12 | new ChineseWord { Simplified = "陆", SimplifiedPinyin = "lu4", Traditional = "陸", TraditionalPinyin = "lu4", Tag = 6 },
13 | new ChineseWord { Simplified = "柒", SimplifiedPinyin = "qi1", Traditional = "柒", TraditionalPinyin = "qi1", Tag = 7 },
14 | new ChineseWord { Simplified = "捌", SimplifiedPinyin = "ba1", Traditional = "捌", TraditionalPinyin = "ba1", Tag = 8 },
15 | new ChineseWord { Simplified = "玖", SimplifiedPinyin = "jiu3", Traditional = "玖", TraditionalPinyin = "jiu3", Tag = 9 },
16 | new ChineseWord { Simplified = "壹拾", SimplifiedPinyin = "yi1 shi2", Traditional = "壹拾", TraditionalPinyin = "yi1 shi2", Tag = 10 },
17 | new ChineseWord { Simplified = "贰拾", SimplifiedPinyin = "er4 shi2", Traditional = "貳拾", TraditionalPinyin = "er4 shi2", Tag = 20 },
18 | new ChineseWord { Simplified = "叁拾", SimplifiedPinyin = "san1 shi2", Traditional = "叁拾", TraditionalPinyin = "san1 shi2", Tag = 30 },
19 | new ChineseWord { Simplified = "肆拾", SimplifiedPinyin = "si4 shi2", Traditional = "肆拾", TraditionalPinyin = "si4 shi2", Tag = 40 },
20 | new ChineseWord { Simplified = "伍拾", SimplifiedPinyin = "wu3 shi2", Traditional = "伍拾", TraditionalPinyin = "wu3 shi2", Tag = 50 },
21 | new ChineseWord { Simplified = "陆拾", SimplifiedPinyin = "lu4 shi2", Traditional = "陸拾", TraditionalPinyin = "lu4 shi2", Tag = 60 },
22 | new ChineseWord { Simplified = "柒拾", SimplifiedPinyin = "qi1 shi2", Traditional = "柒拾", TraditionalPinyin = "qi1 shi2", Tag = 70 },
23 | new ChineseWord { Simplified = "捌拾", SimplifiedPinyin = "ba1 shi2", Traditional = "捌拾", TraditionalPinyin = "ba1 shi2", Tag = 80 },
24 | new ChineseWord { Simplified = "玖拾", SimplifiedPinyin = "jiu3 shi2", Traditional = "玖拾", TraditionalPinyin = "jiu3 shi2", Tag = 90 },
25 | new ChineseWord { Simplified = "壹佰", SimplifiedPinyin = "yi1 bai3", Traditional = "壹佰", TraditionalPinyin = "yi1 bai3", Tag = 100 },
26 | new ChineseWord { Simplified = "贰佰", SimplifiedPinyin = "er4 bai3", Traditional = "貳佰", TraditionalPinyin = "er4 bai3", Tag = 200 },
27 | new ChineseWord { Simplified = "叁佰", SimplifiedPinyin = "san1 bai3", Traditional = "叁佰", TraditionalPinyin = "san1 bai3", Tag = 300 },
28 | new ChineseWord { Simplified = "肆佰", SimplifiedPinyin = "si4 bai3", Traditional = "肆佰", TraditionalPinyin = "si4 bai3", Tag = 400 },
29 | new ChineseWord { Simplified = "伍佰", SimplifiedPinyin = "wu3 bai3", Traditional = "伍佰", TraditionalPinyin = "wu3 bai3", Tag = 500 },
30 | new ChineseWord { Simplified = "陆佰", SimplifiedPinyin = "lu4 bai3", Traditional = "陸佰", TraditionalPinyin = "lu4 bai3", Tag = 600 },
31 | new ChineseWord { Simplified = "柒佰", SimplifiedPinyin = "qi1 bai3", Traditional = "柒佰", TraditionalPinyin = "qi1 bai3", Tag = 700 },
32 | new ChineseWord { Simplified = "捌佰", SimplifiedPinyin = "ba1 bai3", Traditional = "捌佰", TraditionalPinyin = "ba1 bai3", Tag = 800 },
33 | new ChineseWord { Simplified = "玖佰", SimplifiedPinyin = "jiu3 bai3", Traditional = "玖佰", TraditionalPinyin = "jiu3 bai3", Tag = 900 },
34 | new ChineseWord { Simplified = "壹仟", SimplifiedPinyin = "yi1 qian1", Traditional = "壹仟", TraditionalPinyin = "yi1 qian1", Tag = 1000 },
35 | new ChineseWord { Simplified = "贰仟", SimplifiedPinyin = "er4 qian1", Traditional = "貳仟", TraditionalPinyin = "er4 qian1", Tag = 2000 },
36 | new ChineseWord { Simplified = "叁仟", SimplifiedPinyin = "san1 qian1", Traditional = "叁仟", TraditionalPinyin = "san1 qian1", Tag = 3000 },
37 | new ChineseWord { Simplified = "肆仟", SimplifiedPinyin = "si4 qian1", Traditional = "肆仟", TraditionalPinyin = "si4 qian1", Tag = 4000 },
38 | new ChineseWord { Simplified = "伍仟", SimplifiedPinyin = "wu3 qian1", Traditional = "伍仟", TraditionalPinyin = "wu3 qian1", Tag = 5000 },
39 | new ChineseWord { Simplified = "陆仟", SimplifiedPinyin = "lu4 qian1", Traditional = "陸仟", TraditionalPinyin = "lu4 qian1", Tag = 6000 },
40 | new ChineseWord { Simplified = "柒仟", SimplifiedPinyin = "qi1 qian1", Traditional = "柒仟", TraditionalPinyin = "qi1 qian1", Tag = 7000 },
41 | new ChineseWord { Simplified = "捌仟", SimplifiedPinyin = "ba1 qian1", Traditional = "捌仟", TraditionalPinyin = "ba1 qian1", Tag = 8000 },
42 | new ChineseWord { Simplified = "玖仟", SimplifiedPinyin = "jiu3 qian1", Traditional = "玖仟", TraditionalPinyin = "jiu3 qian1", Tag = 9000 },
43 | new ChineseWord { Simplified = "一", SimplifiedPinyin = "yi1", Traditional = "一", TraditionalPinyin = "yi1", Tag = 1 },
44 | new ChineseWord { Simplified = "二", SimplifiedPinyin = "er4", Traditional = "二", TraditionalPinyin = "er4", Tag = 2 },
45 | new ChineseWord { Simplified = "三", SimplifiedPinyin = "san1", Traditional = "三", TraditionalPinyin = "san1", Tag = 3 },
46 | new ChineseWord { Simplified = "四", SimplifiedPinyin = "si4", Traditional = "四", TraditionalPinyin = "si4", Tag = 4 },
47 | new ChineseWord { Simplified = "五", SimplifiedPinyin = "wu3", Traditional = "五", TraditionalPinyin = "wu3", Tag = 5 },
48 | new ChineseWord { Simplified = "六", SimplifiedPinyin = "liu4", Traditional = "六", TraditionalPinyin = "liu4", Tag = 6 },
49 | new ChineseWord { Simplified = "七", SimplifiedPinyin = "qi1", Traditional = "七", TraditionalPinyin = "qi1", Tag = 7 },
50 | new ChineseWord { Simplified = "八", SimplifiedPinyin = "ba1", Traditional = "八", TraditionalPinyin = "ba1", Tag = 8 },
51 | new ChineseWord { Simplified = "九", SimplifiedPinyin = "jiu3", Traditional = "九", TraditionalPinyin = "jiu3", Tag = 9 },
52 | new ChineseWord { Simplified = "一十", SimplifiedPinyin = "yi1 shi2", Traditional = "一十", TraditionalPinyin = "yi1 shi2", Tag = 10 },
53 | new ChineseWord { Simplified = "二十", SimplifiedPinyin = "er4 shi2", Traditional = "二十", TraditionalPinyin = "er4 shi2", Tag = 20 },
54 | new ChineseWord { Simplified = "三十", SimplifiedPinyin = "san1 shi2", Traditional = "三十", TraditionalPinyin = "san1 shi2", Tag = 30 },
55 | new ChineseWord { Simplified = "四十", SimplifiedPinyin = "si4 shi2", Traditional = "四十", TraditionalPinyin = "si4 shi2", Tag = 40 },
56 | new ChineseWord { Simplified = "五十", SimplifiedPinyin = "wu3 shi2", Traditional = "五十", TraditionalPinyin = "wu3 shi2", Tag = 50 },
57 | new ChineseWord { Simplified = "六十", SimplifiedPinyin = "liu4 shi2", Traditional = "六十", TraditionalPinyin = "liu4 shi2", Tag = 60 },
58 | new ChineseWord { Simplified = "七十", SimplifiedPinyin = "qi1 shi2", Traditional = "七十", TraditionalPinyin = "qi1 shi2", Tag = 70 },
59 | new ChineseWord { Simplified = "八十", SimplifiedPinyin = "ba1 shi2", Traditional = "八十", TraditionalPinyin = "ba1 shi2", Tag = 80 },
60 | new ChineseWord { Simplified = "九十", SimplifiedPinyin = "jiu3 shi2", Traditional = "九十", TraditionalPinyin = "jiu3 shi2", Tag = 90 },
61 | new ChineseWord { Simplified = "一百", SimplifiedPinyin = "yi1 bai3", Traditional = "一百", TraditionalPinyin = "yi1 bai3", Tag = 100 },
62 | new ChineseWord { Simplified = "二百", SimplifiedPinyin = "er4 bai3", Traditional = "二百", TraditionalPinyin = "er4 bai3", Tag = 200 },
63 | new ChineseWord { Simplified = "三百", SimplifiedPinyin = "san1 bai3", Traditional = "三百", TraditionalPinyin = "san1 bai3", Tag = 300 },
64 | new ChineseWord { Simplified = "四百", SimplifiedPinyin = "si4 bai3", Traditional = "四百", TraditionalPinyin = "si4 bai3", Tag = 400 },
65 | new ChineseWord { Simplified = "五百", SimplifiedPinyin = "wu3 bai3", Traditional = "五百", TraditionalPinyin = "wu3 bai3", Tag = 500 },
66 | new ChineseWord { Simplified = "六百", SimplifiedPinyin = "liu4 bai3", Traditional = "六百", TraditionalPinyin = "liu4 bai3", Tag = 600 },
67 | new ChineseWord { Simplified = "七百", SimplifiedPinyin = "qi1 bai3", Traditional = "七百", TraditionalPinyin = "qi1 bai3", Tag = 700 },
68 | new ChineseWord { Simplified = "八百", SimplifiedPinyin = "ba1 bai3", Traditional = "八百", TraditionalPinyin = "ba1 bai3", Tag = 800 },
69 | new ChineseWord { Simplified = "九百", SimplifiedPinyin = "jiu3 bai3", Traditional = "九百", TraditionalPinyin = "jiu3 bai3", Tag = 900 },
70 | new ChineseWord { Simplified = "一千", SimplifiedPinyin = "yi1 qian1", Traditional = "一千", TraditionalPinyin = "yi1 qian1", Tag = 1000 },
71 | new ChineseWord { Simplified = "二千", SimplifiedPinyin = "er4 qian1", Traditional = "二千", TraditionalPinyin = "er4 qian1", Tag = 2000 },
72 | new ChineseWord { Simplified = "三千", SimplifiedPinyin = "san1 qian1", Traditional = "三千", TraditionalPinyin = "san1 qian1", Tag = 3000 },
73 | new ChineseWord { Simplified = "四千", SimplifiedPinyin = "si4 qian1", Traditional = "四千", TraditionalPinyin = "si4 qian1", Tag = 4000 },
74 | new ChineseWord { Simplified = "五千", SimplifiedPinyin = "wu3 qian1", Traditional = "五千", TraditionalPinyin = "wu3 qian1", Tag = 5000 },
75 | new ChineseWord { Simplified = "六千", SimplifiedPinyin = "liu4 qian1", Traditional = "六千", TraditionalPinyin = "liu4 qian1", Tag = 6000 },
76 | new ChineseWord { Simplified = "七千", SimplifiedPinyin = "qi1 qian1", Traditional = "七千", TraditionalPinyin = "qi1 qian1", Tag = 7000 },
77 | new ChineseWord { Simplified = "八千", SimplifiedPinyin = "ba1 qian1", Traditional = "八千", TraditionalPinyin = "ba1 qian1", Tag = 8000 },
78 | new ChineseWord { Simplified = "九千", SimplifiedPinyin = "jiu3 qian1", Traditional = "九千", TraditionalPinyin = "jiu3 qian1", Tag = 9000 },
79 | new ChineseWord { Simplified = "两", SimplifiedPinyin = "liang3", Traditional = "两", TraditionalPinyin = "liang3", Tag = 2 },
80 | new ChineseWord { Simplified = "两百", SimplifiedPinyin = "liang3 bai3", Traditional = "两百", TraditionalPinyin = "liang3 bai3", Tag = 200 },
81 | new ChineseWord { Simplified = "两千", SimplifiedPinyin = "liang3 qian1", Traditional = "两千", TraditionalPinyin = "liang3 qian1", Tag = 2000 },
82 |
83 | new ChineseWord { Simplified = "〇", SimplifiedPinyin = "ling2", Traditional = "〇", TraditionalPinyin = "ling2", Tag = 0 },
84 |
85 | new ChineseWord { Simplified = "十", SimplifiedPinyin = "shi2", Traditional = "十", TraditionalPinyin = "shi2", Tag = null },
86 | new ChineseWord { Simplified = "百", SimplifiedPinyin = "bai3", Traditional = "百", TraditionalPinyin = "bai3", Tag = null },
87 | new ChineseWord { Simplified = "千", SimplifiedPinyin = "qian1", Traditional = "千", TraditionalPinyin = "qian1", Tag = null },
88 | new ChineseWord { Simplified = "拾", SimplifiedPinyin = "shi2", Traditional = "拾", TraditionalPinyin = "shi2", Tag = null },
89 | new ChineseWord { Simplified = "佰", SimplifiedPinyin = "bai3", Traditional = "佰", TraditionalPinyin = "bai3", Tag = null },
90 | new ChineseWord { Simplified = "仟", SimplifiedPinyin = "qian1", Traditional = "仟", TraditionalPinyin = "qian1", Tag = null },
91 |
92 | new ChineseWord { Simplified = "万", SimplifiedPinyin = "wan4", Traditional = "萬", TraditionalPinyin = "wan4", Tag = null },
93 | new ChineseWord { Simplified = "亿", SimplifiedPinyin = "yi4", Traditional = "億", TraditionalPinyin = "yi4", Tag = null },
94 |
95 | new ChineseWord { Simplified = "兆", SimplifiedPinyin = "zhao4", Traditional = "兆", TraditionalPinyin = "zhao4", Tag = null },
96 | new ChineseWord { Simplified = "京", SimplifiedPinyin = "jing1", Traditional = "京", TraditionalPinyin = "jing1", Tag = null },
97 | new ChineseWord { Simplified = "垓", SimplifiedPinyin = "gai1", Traditional = "垓", TraditionalPinyin = "gai1", Tag = null },
98 | new ChineseWord { Simplified = "秭", SimplifiedPinyin = "zi3", Traditional = "秭", TraditionalPinyin = "zi3", Tag = null },
99 | new ChineseWord { Simplified = "穰", SimplifiedPinyin = "rang2", Traditional = "穰", TraditionalPinyin = "rang2", Tag = null },
100 |
101 | new ChineseWord { Simplified = "万亿", SimplifiedPinyin = "wan4 yi4", Traditional = "萬億", TraditionalPinyin = "wan4 yi4", Tag = null },
102 | new ChineseWord { Simplified = "亿亿", SimplifiedPinyin = "yi4 yi4", Traditional = "億億", TraditionalPinyin = "yi4 yi4", Tag = null },
103 | new ChineseWord { Simplified = "万亿亿", SimplifiedPinyin = "wan4 yi4 yi4", Traditional = "萬億億", TraditionalPinyin = "wan4 yi4 yi4", Tag = null },
104 | new ChineseWord { Simplified = "亿亿亿", SimplifiedPinyin = "yi4 yi4 yi4", Traditional = "億億億", TraditionalPinyin = "yi4 yi4 yi4", Tag = null },
105 | new ChineseWord { Simplified = "万亿亿亿", SimplifiedPinyin = "wan4 yi4 yi4 yi4", Traditional = "萬億億億", TraditionalPinyin = "wan4 yi4 yi4 yi4", Tag = null },
106 |
107 | new ChineseWord { Simplified = "元", SimplifiedPinyin = "yuan2", Traditional = "元", TraditionalPinyin = "yuan2", Tag = null },
108 | new ChineseWord { Simplified = "圆", SimplifiedPinyin = "yuan2", Traditional = "圓", TraditionalPinyin = "yuan2", Tag = null },
109 | new ChineseWord { Simplified = "角", SimplifiedPinyin = "jiao3", Traditional = "角", TraditionalPinyin = "jiao3", Tag = null },
110 | new ChineseWord { Simplified = "分", SimplifiedPinyin = "fen1", Traditional = "分", TraditionalPinyin = "fen1", Tag = null },
111 | ];
112 | }
113 |
--------------------------------------------------------------------------------
/Chinese/Lexicons/CurrencyLexicon.cs:
--------------------------------------------------------------------------------
1 | using NStandard;
2 | using System;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace Chinese.Lexicons;
6 |
7 | public class CurrencyLexicon : Lexicon
8 | {
9 | private readonly NumberLexicon _numericLexicon;
10 |
11 | private readonly Regex _currencyRegex;
12 | private readonly string[] _levels;
13 |
14 | public CurrencyLexicon(NumberMode mode)
15 | {
16 | _numericLexicon = new(mode);
17 |
18 | if (mode.HasFlag(NumberMode.Upper))
19 | {
20 | _levels = ["圆", "角", "分"];
21 | _currencyRegex = new Regex(@"^(.+)(?:圆)(?:整|(.)角整|(.)角(.)分|零(.)分)$", RegexOptions.Compiled);
22 | }
23 | else
24 | {
25 | _levels = ["元", "角", "分"];
26 | _currencyRegex = new Regex(@"^(.+)(?:元)(?:整|(.)角整|(.)角(.)分|零(.)分)$", RegexOptions.Compiled);
27 | }
28 | }
29 |
30 | ///
31 | /// 获取数值的货币读法。
32 | ///
33 | ///
34 | ///
35 | ///
36 | public string GetString(decimal currency)
37 | {
38 | var fractional100 = (int)(currency % 1 * 100 % 100);
39 |
40 | var yuan = $"{_numericLexicon.GetString(currency)}{_levels[0]}";
41 | if (fractional100 == 0)
42 | {
43 | return $"{yuan}整";
44 | }
45 | else if (fractional100 % 10 == 0)
46 | {
47 | var jiao = $"{_numericLexicon.GetString(fractional100 / 10)}{_levels[1]}";
48 | return $"{yuan}{jiao}整";
49 | }
50 | else
51 | {
52 | var jiao_value = fractional100 / 10;
53 | var jiao = jiao_value > 0
54 | ? $"{_numericLexicon.GetString(fractional100 / 10)}{_levels[1]}"
55 | : "零";
56 |
57 | var fen = $"{_numericLexicon.GetString(fractional100 % 10)}{_levels[2]}";
58 | return $"{yuan}{jiao}{fen}";
59 | }
60 | }
61 |
62 | ///
63 | /// 获取货币读法的数值。
64 | ///
65 | ///
66 | ///
67 | public decimal GetNumber(string currency)
68 | {
69 | var match = _currencyRegex.Match(currency);
70 |
71 | if (!match.Success) throw new ArgumentException("不是合法的中文货币描述。", nameof(currency));
72 |
73 | var yuan = _numericLexicon.GetNumber(match.Groups[1].Value);
74 |
75 | var jiao_value = match.Groups[2].Value;
76 | if (jiao_value.IsWhiteSpace()) jiao_value = match.Groups[3].Value;
77 | var jiao = jiao_value.IsWhiteSpace() ? 0m : _numericLexicon.GetNumber(jiao_value);
78 |
79 | var fen_value = match.Groups[4].Value;
80 | if (fen_value.IsWhiteSpace()) fen_value = match.Groups[5].Value;
81 | var fen = fen_value.IsWhiteSpace() ? 0m : _numericLexicon.GetNumber(fen_value);
82 |
83 | return yuan + jiao * 0.1m + fen * 0.01m;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Chinese/Lexicons/NumberLexicon.cs:
--------------------------------------------------------------------------------
1 | using NStandard;
2 | using System;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Chinese.Lexicons;
7 |
8 | public class NumberLexicon : Lexicon
9 | {
10 | private const int PART_COUNT = 4;
11 | private const int SUPPORTED_SEPARATOR_COUNT = 8;
12 | private string[] _separators;
13 | ///
14 | /// 数值分级单位
15 | ///
16 | public string[] Separators
17 | {
18 | get => _separators;
19 | set
20 | {
21 | if (value.Length > SUPPORTED_SEPARATOR_COUNT) throw new NotSupportedException($"超过最大支持分隔符数量({SUPPORTED_SEPARATOR_COUNT})。");
22 | _separators = value;
23 | }
24 | }
25 | public bool Code { get; set; }
26 | public bool Concise { get; set; }
27 | public ChineseType ChineseType { get; set; }
28 |
29 | private readonly string[] _values;
30 | private readonly string[] _levels;
31 |
32 | public NumberLexicon(NumberMode mode)
33 | {
34 | Add(Builtin.NumericalWords);
35 |
36 | Code = mode.HasFlag(NumberMode.Code);
37 | Concise = mode.HasFlag(NumberMode.Concise);
38 | ChineseType = mode.HasFlag(NumberMode.Traditional) ? ChineseType.Traditional : ChineseType.Simplified;
39 |
40 | if (mode.HasFlag(NumberMode.Classical))
41 | {
42 | Separators = [string.Empty, "万", "亿", "兆", "京", "垓", "秭", "穰"];
43 | }
44 | else
45 | {
46 | Separators = [string.Empty, "万", "亿", "万亿", "亿亿", "万亿亿", "亿亿亿", "万亿亿亿"];
47 | }
48 |
49 | if (mode.HasFlag(NumberMode.Upper))
50 | {
51 | _levels = [string.Empty, "拾", "佰", "仟"];
52 | _values = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
53 | }
54 | else
55 | {
56 | _levels = [string.Empty, "十", "百", "千"];
57 | _values =
58 | [
59 | mode.HasFlag(NumberMode.Code) ? "〇" : "零",
60 | "一", "二", "三", "四", "五", "六", "七", "八", "九"
61 | ];
62 | }
63 | }
64 |
65 | ///
66 | /// 获取数字的编号读法。
67 | ///
68 | ///
69 | ///
70 | private string GetCodeString(decimal number)
71 | {
72 | var s_number = number.ToString();
73 | if (!s_number.All(ch => '0' <= ch && ch <= '9')) throw new ArgumentException("不是合法的数字编号。");
74 |
75 | var sb = new StringBuilder(s_number.Length + 1);
76 | foreach (var ch in s_number) sb.Append(_values[ch - '0']);
77 |
78 | return sb.ToString();
79 | }
80 |
81 | ///
82 | /// 获取数字的编号读法。
83 | ///
84 | ///
85 | ///
86 | private decimal GetCodeNumber(string number)
87 | {
88 | var sb = new StringBuilder(number.Length + 1);
89 | foreach (var ch in number)
90 | {
91 | var value = _values.IndexOf(ch.ToString());
92 |
93 | if (value > -1) sb.Append(value);
94 | else throw new ArgumentException("不是合法的中文数字编号描述。", nameof(number));
95 | }
96 |
97 | return decimal.Parse(sb.ToString());
98 | }
99 |
100 | ///
101 | /// 获取数值的数值读法。
102 | ///
103 | ///
104 | ///
105 | public string GetString(decimal number)
106 | {
107 | if (Code) return GetCodeString(number);
108 |
109 | number = number switch
110 | {
111 | 0 => number,
112 | > 0 => decimal.Floor(number),
113 | < 0 => decimal.Ceiling(number),
114 | };
115 |
116 | string GetPartString(char[] singles, string level, bool prevZero)
117 | {
118 | if (!singles.Any()) return string.Empty;
119 |
120 | var sb = new StringBuilder();
121 | var zero = prevZero;
122 | foreach (var (index, single) in singles.Pairs())
123 | {
124 | if (single != '0')
125 | {
126 | var value = _values[single - '0'];
127 | var unit = _levels[singles.Length - 1 - index];
128 |
129 | if (zero) sb.Append(_values[0]);
130 | sb.Append($"{value}{unit}");
131 |
132 | zero = false;
133 | }
134 | else
135 | {
136 | zero = true;
137 | }
138 | }
139 |
140 | if (sb.Length == 0) return null;
141 | else
142 | {
143 | sb.Append(level);
144 | return sb.ToString();
145 | }
146 | }
147 |
148 | var s_number = number.ToString();
149 | var enumerator_s_number = s_number.GetEnumerator();
150 |
151 | var levelParts = new char[(s_number.Length - 1) / 4 + 1][];
152 | var enumerator_levelParts = levelParts.GetEnumerator();
153 | if (enumerator_levelParts.MoveNext())
154 | {
155 | var mod = s_number.Length % PART_COUNT;
156 | levelParts[0] = new char[mod > 0 ? mod : 4];
157 | for (int j = 0; j < levelParts[0].Length; j++)
158 | {
159 | enumerator_s_number.MoveNext();
160 | levelParts[0][j] = enumerator_s_number.Current;
161 | }
162 |
163 | int i = 1;
164 | while (enumerator_levelParts.MoveNext())
165 | {
166 | levelParts[i] = new char[4];
167 | for (int j = 0; j < PART_COUNT; j++)
168 | {
169 | enumerator_s_number.MoveNext();
170 | levelParts[i][j] = enumerator_s_number.Current;
171 | }
172 | i++;
173 | }
174 | }
175 |
176 | var sb = new StringBuilder();
177 | int part_i = 0;
178 | bool prevZero = false;
179 | foreach (var part in levelParts)
180 | {
181 | var partString = GetPartString(part, Separators[levelParts.Length - 1 - part_i], prevZero);
182 | if (partString is not null)
183 | {
184 | sb.Append(partString);
185 | prevZero = false;
186 | }
187 | else prevZero = true;
188 | part_i++;
189 | }
190 |
191 | if (sb.Length == 0) return _values[0];
192 |
193 | if (Concise && sb.Length > 1)
194 | {
195 | if (sb[0] == '一' && sb[1] == '十' || sb[0] == '壹' && sb[1] == '拾')
196 | {
197 | sb.Remove(0, 1);
198 | }
199 | }
200 |
201 | return sb.ToString();
202 | }
203 |
204 | ///
205 | /// 获取数值读法的数值。
206 | ///
207 | ///
208 | ///
209 | public decimal GetNumber(string number)
210 | {
211 | if (Code) return GetCodeNumber(number);
212 |
213 | if (number.Length == 0) return default;
214 |
215 | var last = number.Last();
216 | if (last == '两') throw new ArgumentException($"不能以该字结尾:{last}", nameof(number));
217 |
218 | var words = SplitWords(number, ChineseType);
219 | var total = 0m;
220 | var levelNumber = 0;
221 | foreach (var word in words)
222 | {
223 | var ch = word.Simplified;
224 |
225 | if (ch == "零") continue;
226 | else if (ch == "十" || ch == "拾") levelNumber += 10;
227 | else
228 | {
229 | if (word.Tag is int @int)
230 | {
231 | levelNumber += @int;
232 | }
233 | else
234 | {
235 | var level = _separators.IndexOf(ch);
236 | if (level > -1)
237 | {
238 | total += levelNumber * level switch
239 | {
240 | 1 => 1_0000,
241 | 2 => 1_0000_0000,
242 | 3 => 1_0000_0000_0000,
243 | 4 => 1_0000_0000_0000_0000,
244 | 5 => 1_0000_0000_0000_0000_0000m,
245 | 6 => 1_0000_0000_0000_0000_0000_0000m,
246 | 7 => 1_0000_0000_0000_0000_0000_0000_0000m,
247 | _ => throw new NotImplementedException(),
248 | };
249 | levelNumber = 0;
250 | }
251 | else throw new ArgumentException($"不能解析的词汇:{word}", nameof(number));
252 | }
253 | }
254 | }
255 | total += levelNumber;
256 | return total;
257 | }
258 |
259 | }
260 |
--------------------------------------------------------------------------------
/Chinese/Lexicons/NumberMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Chinese.Lexicons;
4 |
5 | [Flags]
6 | public enum NumberMode
7 | {
8 | Default = 0,
9 |
10 | Traditional = 0b0010,
11 | Classical = 0b0100,
12 | Concise = 0b1000,
13 |
14 | Upper = 0b1_00000000,
15 | Code = 0b10_00000000,
16 | }
17 |
--------------------------------------------------------------------------------
/ChineseApp/ChineseApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ChineseApp/Program.cs:
--------------------------------------------------------------------------------
1 | using Chinese;
2 | using Chinese.Data;
3 | using Chinese.Lexicons;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.Extensions.Logging;
6 | using System.Diagnostics;
7 |
8 | namespace ChineseApp;
9 |
10 | internal class Program
11 | {
12 | public class MySqlLexicon : Lexicon
13 | {
14 | public static MySqlLexicon UseDefault()
15 | {
16 | var mysqlConnectionString = "server=127.0.0.1;port=33306;user=root;password=root;database=chinese";
17 | var mysqlOptions = new DbContextOptionsBuilder()
18 | .UseMySql(mysqlConnectionString, ServerVersion.AutoDetect(mysqlConnectionString), null)
19 | .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole())).Options;
20 |
21 | var context = new ChineseDbContext(mysqlOptions);
22 | return new MySqlLexicon(context);
23 | }
24 |
25 | public MySqlLexicon(ChineseDbContext context)
26 | {
27 | Add(context.Words);
28 | Add(context.Chars);
29 | }
30 | }
31 |
32 | static void Main(string[] args)
33 | {
34 | var watch = new Stopwatch();
35 |
36 | //var lexicon = MySqlLexicon.UseDefault();
37 | //Console.WriteLine(lexicon.GetPinyin("只有这只鸟跑得很快。"));
38 |
39 | {
40 | var lexicon = Lexicon.Currency;
41 | Console.WriteLine(
42 | Lexicon.Currency.GetString(0.1m)
43 | );
44 | }
45 |
46 | {
47 | watch.Restart();
48 | var currency = Lexicon.Currency;
49 | for (int i = 0; i < 100; i++)
50 | {
51 | var result = currency.GetNumber("一百二十三亿亿亿四千五百六十七万亿亿八千九百零一亿亿二千三百四十五万亿六千七百八十九亿零一百二十三万四千五百六十七元八角九分");
52 | if (i == 0) Console.WriteLine(result);
53 | }
54 | watch.Stop();
55 | Console.WriteLine(watch.Elapsed);
56 |
57 | watch.Restart();
58 | for (int i = 0; i < 100; i++)
59 | {
60 | var result = currency.GetString(123456789012345678901234567.89M);
61 | if (i == 0) Console.WriteLine(result);
62 | }
63 | watch.Stop();
64 | Console.WriteLine(watch.Elapsed);
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 zmjack
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LexiconBuilder/LexiconBuilder.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | true
9 | true
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LexiconBuilder/Program.cs:
--------------------------------------------------------------------------------
1 | namespace LexiconBuilder;
2 |
3 | internal class Program
4 | {
5 | static void Main(string[] args)
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Chinese
2 |
3 | 中文解析通用工具。包括拼音,简繁转换,数字读法,货币读法。
4 |
5 |
6 |
7 | ## 安装
8 |
9 | 通过 **Nuget** 使用 **.NET CLI** 安装:
10 |
11 | ```powershell
12 | dotnet add package Chinese
13 | ```
14 |
15 |
16 |
17 | ## 版本更新
18 |
19 | ### 版本:0.8.1-alpha
20 |
21 | 欢迎仅使用 **数字转换** / **货币转换** 功能的项目升级试用。
22 |
23 | - [x] 大量逻辑优化,优化内存使用。
24 |
25 | - [x] 提高 **数字转换** / **货币转换** 性能,修复一些 **BUG**(Issues: #10)。
26 |
27 | ```csharp
28 | Lexicon.Currency.GetString(0.1m); // 零元一角整
29 | ```
30 |
31 | - [x] 修复 **中文掺杂字母或拼音** 转换时缺少 **空格** 的问题(Issues: #12)。
32 |
33 | - [ ] 数值读法增加 **小数** 读法。
34 |
35 | - [ ] 提供外部词库支持,现可使用 **数据库** 作为外部词库源。(结构需优化)
36 |
37 | - [ ] 词库编译生成器(解析 **文本结构** 到 **Sqlite** 数据库文件,用户可以通过文本结构提交 PR 贡献)。
38 |
39 | ### 版本:0.5.0
40 |
41 | - 简繁转换性能优化(**NETStandard2.0+**,**NET5.0+**,通常情况耗时减少约 **90%**)。
42 |
43 | - 计量读法性能优化(耗时减少约 **85%**)。
44 |
45 | - 修复计量读法尾零转换错误问题:
46 |
47 | ```csharp
48 | var wrong = ChineseCurrency.GetString(10_0000); // 错误:一十万零元整
49 | var right = ChineseCurrency.GetString(10_0000); // 正确:一十万元整
50 | ```
51 |
52 | ### 版本:4.5.0
53 |
54 | - 更新部分字默认拼音。
55 | - 发布测试词库 **Chinese.Words**(v0.0.1)。
56 |
57 | ### 版本:4.1.0
58 |
59 | - 按词频为单字提供默认拼音。
60 |
61 |
62 |
63 | ## 拼音
64 |
65 | ```c#
66 | // "mian3 fei4,kua4 ping2 tai2,kai1 yuan2!"
67 | Pinyin.GetString("免费,跨平台,开源!", PinyinFormat.Default);
68 | ```
69 |
70 | ```c#
71 | // "mian fei,kua ping tai,kai yuan!"
72 | Pinyin.GetString("免费,跨平台,开源!", PinyinFormat.WithoutTone);
73 | ```
74 |
75 | ```c#
76 | // "miǎn fèi,kuà píng tái,kāi yuán!"
77 | Pinyin.GetString("免费,跨平台,开源!", PinyinFormat.Phonetic);
78 | ```
79 |
80 | ```c#
81 | // "mf,kpt,ky!"
82 | Pinyin.GetString("免费,跨平台,开源!", PinyinFormat.InitialConsonant);
83 | ```
84 |
85 |
86 |
87 | ## 简繁转换
88 |
89 | ```c#
90 | ChineseConverter.ToTraditional("免费,跨平台,开源!"); // "免費,跨平臺,開源!"
91 | ChineseConverter.ToSimplified("免費,跨平臺,開源!"); // "免费,跨平台,开源!"
92 | ```
93 |
94 |
95 |
96 | ## 数字读法
97 |
98 | | NumberMode 选项 | 描述 | 示例 |
99 | | --------------- | ------------------------------------------------------------ | ------------------------- |
100 | | **Default** | 流行读法,亿级以上使用 `千亿` `万亿` 等单位;
不省略第一个 `十` 前的 `一` ;
小写读法。 | - |
101 | | **Classical** | 经典读法,亿级以上使用 `兆` `京` 等单位 | - |
102 | | **Concise** | 简洁读法,省略第一个 `十` 前的 `一` | `10_0001` 读作 `十万零一` |
103 | | **Upper** | 大写读法 | `1` 读作 `壹` |
104 |
105 |
106 |
107 | ### 计量读法
108 |
109 | ```c#
110 | var lexicon = Lexicon.Number;
111 | lexicon.GetString(10_0001); // "一十万零一"
112 | lexicon.GetString(10_0101); // "一十万零一百零一"
113 | lexicon.GetString(10_1001); // "一十万一千零一"
114 | lexicon.GetString(10_1010); // "一十万一千零一十"
115 |
116 | lexicon.GetNumber("一十万零一"); // 10_0001
117 | lexicon.GetNumber("一十万零一百零一"); // 10_0101
118 | lexicon.GetNumber("一十万一千零一"); // 10_1001
119 | lexicon.GetNumber("一十万一千零一十"); // 10_1010
120 | ```
121 |
122 | #### 大数读法
123 |
124 | ##### 流行读法
125 |
126 | 亿级以上使用(万亿、亿亿、万亿亿、亿亿亿、万亿亿亿):
127 |
128 | ```csharp
129 | var lexicon = Lexicon.Number;
130 |
131 | // "一万亿亿亿二千三百四十五亿亿亿六千七百八十九万亿亿零一百二十三亿亿四千五百六十七万亿八千九百零一亿二千三百四十五万六千七百八十九"
132 | lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m);
133 |
134 | // 12345678901234567890123456789
135 | lexicon.GetNumber("一万亿亿亿二千三百四十五亿亿亿六千七百八十九万亿亿零一百二十三亿亿四千五百六十七万亿八千九百零一亿二千三百四十五万六千七百八十九");
136 | ```
137 |
138 | ##### 经典读法
139 |
140 | 亿级以上使用(兆、京、垓、秭、穰):
141 |
142 | ```c#
143 | var lexicon = Lexicon.NumberWith(NumberMode.Classical);
144 |
145 | // "一穰二千三百四十五秭六千七百八十九垓零一百二十三京四千五百六十七兆八千九百零一亿二千三百四十五万六千七百八十九"
146 | lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m);
147 |
148 | // 12345678901234567890123456789
149 | lexicon.GetNumber("一穰二千三百四十五秭六千七百八十九垓零一百二十三京四千五百六十七兆八千九百零一亿二千三百四十五万六千七百八十九");
150 | ```
151 |
152 |
153 |
154 | ### 编号读法
155 |
156 | ```c#
157 | var lexicon = Lexicon.NumberWith(NumberMode.Code);
158 | lexicon.GetString(10_0001); // "一〇〇〇〇一"
159 | lexicon.GetString(10_0101); // "一〇〇一〇一"
160 | lexicon.GetString(10_1001); // "一〇一〇〇一"
161 | lexicon.GetString(10_1010); // "一〇一〇一〇"
162 |
163 | lexicon.GetNumber("一〇〇〇〇一"); // 10_0001
164 | lexicon.GetNumber("一〇〇一〇一"); // 10_0101
165 | lexicon.GetNumber("一〇一〇〇一"); // 10_1001
166 | lexicon.GetNumber("一〇一〇一〇"); // 10_1010
167 | ```
168 |
169 |
170 |
171 | ### 货币读法
172 |
173 | ```c#
174 | var lexicon = Lexicon.Currency;
175 |
176 | lexicon.GetString(1); // "一元整"
177 | lexicon.GetString(10_0001); // "一十万零一元整"
178 | lexicon.GetString(10_0101); // "一十万零一百零一元整"
179 | lexicon.GetString(10_1001); // "一十万一千零一元整"
180 | lexicon.GetString(10_1010); // "一十万一千零一十元整"
181 | lexicon.GetString(10_0001.2m); // "一十万零一元二角整"
182 | lexicon.GetString(10_0001.23m); // "一十万零一元二角三分"
183 | lexicon.GetString(10_0001.03m); // "一十万零一元零三分"
184 |
185 | lexicon.GetNumber("一元整"); // 1
186 | lexicon.GetNumber("一十万零一元整"); // 10_0001
187 | lexicon.GetNumber("一十万零一百零一元整"); // 10_0101
188 | lexicon.GetNumber("一十万一千零一元整"); // 10_1001
189 | lexicon.GetNumber("一十万一千零一十元整"); // 10_1010
190 | lexicon.GetNumber("一十万零一元二角整"); // 10_0001.2m
191 | lexicon.GetNumber("一十万零一元二角三分"); // 10_0001.23m
192 | lexicon.GetNumber("一十万零一元零三分"); // 10_0001.03m
193 | ```
194 |
195 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/Chinese.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | false
6 | preview
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/ConverterTests.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Test.Util;
2 | using Xunit;
3 |
4 | namespace Chinese.Test;
5 |
6 | public class ConverterTests
7 | {
8 | [Fact]
9 | public void Test1()
10 | {
11 | var lexicon = MySqlLexicon.UseDefault();
12 | Assert.Equal("免費,跨平臺,開源!", lexicon.ToTraditional("免费,跨平台,开源!"));
13 | Assert.Equal("免费,跨平台,开源!", lexicon.ToSimplified("免費,跨平臺,開源!"));
14 | }
15 |
16 | [Fact]
17 | public void Test2()
18 | {
19 | var lexicon = MySqlLexicon.UseDefault();
20 | Assert.Equal("皇后在國王後面。", lexicon.ToTraditional("皇后在国王后面。"));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/CurrencyTests.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Lexicons;
2 | using Xunit;
3 |
4 | namespace Chinese.Test;
5 |
6 | public class CurrencyTests
7 | {
8 | [Fact]
9 | public void Test()
10 | {
11 | var lexicon = Lexicon.Currency;
12 |
13 | Assert.Equal("一元整", lexicon.GetString(1));
14 | Assert.Equal("一十万零一元整", lexicon.GetString(10_0001));
15 | Assert.Equal("一十万零一百零一元整", lexicon.GetString(10_0101));
16 | Assert.Equal("一十万一千零一元整", lexicon.GetString(10_1001));
17 | Assert.Equal("一十万一千零一十元整", lexicon.GetString(10_1010));
18 | Assert.Equal("一十万零一元二角整", lexicon.GetString(10_0001.2m));
19 | Assert.Equal("一十万零一元二角三分", lexicon.GetString(10_0001.23m));
20 | Assert.Equal("一十万零一元零三分", lexicon.GetString(10_0001.03m));
21 |
22 | Assert.Equal(1, lexicon.GetNumber("一元整"));
23 | Assert.Equal(10_0001, lexicon.GetNumber("一十万零一元整"));
24 | Assert.Equal(10_0101, lexicon.GetNumber("一十万零一百零一元整"));
25 | Assert.Equal(10_1001, lexicon.GetNumber("一十万一千零一元整"));
26 | Assert.Equal(10_1010, lexicon.GetNumber("一十万一千零一十元整"));
27 | Assert.Equal(10_0001.2m, lexicon.GetNumber("一十万零一元二角整"));
28 | Assert.Equal(10_0001.23m, lexicon.GetNumber("一十万零一元二角三分"));
29 | Assert.Equal(10_0001.03m, lexicon.GetNumber("一十万零一元零三分"));
30 | }
31 |
32 | [Fact]
33 | public void UpperTest()
34 | {
35 | var lexicon = Lexicon.CurrencyWith(NumberMode.Upper);
36 |
37 | Assert.Equal("壹圆整", lexicon.GetString(1));
38 | Assert.Equal("壹拾万零壹圆整", lexicon.GetString(10_0001));
39 | Assert.Equal("壹拾万零壹佰零壹圆整", lexicon.GetString(10_0101));
40 | Assert.Equal("壹拾万壹仟零壹圆整", lexicon.GetString(10_1001));
41 | Assert.Equal("壹拾万壹仟零壹拾圆整", lexicon.GetString(10_1010));
42 | Assert.Equal("壹拾万零壹圆贰角整", lexicon.GetString(10_0001.2m));
43 | Assert.Equal("壹拾万零壹圆贰角叁分", lexicon.GetString(10_0001.23m));
44 | Assert.Equal("壹拾万零壹圆零叁分", lexicon.GetString(10_0001.03m));
45 |
46 | Assert.Equal(1, lexicon.GetNumber("壹圆整"));
47 | Assert.Equal(10_0001, lexicon.GetNumber("壹拾万零壹圆整"));
48 | Assert.Equal(10_0101, lexicon.GetNumber("壹拾万零壹佰零壹圆整"));
49 | Assert.Equal(10_1001, lexicon.GetNumber("壹拾万壹仟零壹圆整"));
50 | Assert.Equal(10_1010, lexicon.GetNumber("壹拾万壹仟零壹拾圆整"));
51 | Assert.Equal(10_0001.2m, lexicon.GetNumber("壹拾万零壹圆贰角整"));
52 | Assert.Equal(10_0001.23m, lexicon.GetNumber("壹拾万零壹圆贰角叁分"));
53 | Assert.Equal(10_0001.03m, lexicon.GetNumber("壹拾万零壹圆零叁分"));
54 | }
55 |
56 | [Fact]
57 | public void LastZeroTest()
58 | {
59 | var lexicon = Lexicon.Currency;
60 |
61 | Assert.Equal("一十万元整", lexicon.GetString(10_0000m));
62 | Assert.Equal("一十亿元整", lexicon.GetString(10_0000_0000m));
63 | Assert.Equal("一十亿零一元整", lexicon.GetString(10_0000_0001m));
64 | Assert.Equal("一十亿零一千零一元整", lexicon.GetString(10_0000_1001m));
65 | Assert.Equal("一十亿零一百万一千零一元整", lexicon.GetString(10_0100_1001m));
66 | Assert.Equal("一千零二十万三千零四十元整", lexicon.GetString(1020_3040m));
67 |
68 | Assert.Equal(10_0000m, lexicon.GetNumber("一十万元整"));
69 | Assert.Equal(10_0000_0000m, lexicon.GetNumber("一十亿元整"));
70 | Assert.Equal(10_0000_0001m, lexicon.GetNumber("一十亿零一元整"));
71 | Assert.Equal(10_0000_1001m, lexicon.GetNumber("一十亿零一千零一元整"));
72 | Assert.Equal(10_0100_1001m, lexicon.GetNumber("一十亿零一百万一千零一元整"));
73 | Assert.Equal(1020_3040m, lexicon.GetNumber("一千零二十万三千零四十元整"));
74 | }
75 |
76 | [Fact]
77 | public void FirstZeroTest()
78 | {
79 | var lexicon = Lexicon.Currency;
80 |
81 | Assert.Equal("零元一角整", lexicon.GetString(0.1m));
82 | Assert.Equal("零元零一分", lexicon.GetString(0.01m));
83 |
84 | Assert.Equal(0.1m, lexicon.GetNumber("零元一角整"));
85 | Assert.Equal(0.01m, lexicon.GetNumber("零元零一分"));
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/NumberTests.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Lexicons;
2 | using System;
3 | using Xunit;
4 |
5 | namespace Chinese.Test;
6 |
7 | public class NumberTests
8 | {
9 | [Fact]
10 | public void Test()
11 | {
12 | var lexicon = Lexicon.Number;
13 |
14 | Assert.Equal("一", lexicon.GetString(1));
15 | Assert.Equal("一十万零一", lexicon.GetString(10_0001));
16 | Assert.Equal("一十万零一百零一", lexicon.GetString(10_0101));
17 | Assert.Equal("一十万一千零一", lexicon.GetString(10_1001));
18 | Assert.Equal("一十万一千零一十", lexicon.GetString(10_1010));
19 |
20 | Assert.Equal(1, lexicon.GetNumber("一"));
21 | Assert.Equal(10_0001, lexicon.GetNumber("一十万零一"));
22 | Assert.Equal(10_0101, lexicon.GetNumber("一十万零一百零一"));
23 | Assert.Equal(10_1001, lexicon.GetNumber("一十万一千零一"));
24 | Assert.Equal(10_1010, lexicon.GetNumber("一十万一千零一十"));
25 | }
26 |
27 | [Fact]
28 | public void UpperTest()
29 | {
30 | var lexicon = Lexicon.NumberWith(NumberMode.Upper);
31 |
32 | Assert.Equal("壹", lexicon.GetString(1));
33 | Assert.Equal("壹拾万零壹", lexicon.GetString(10_0001));
34 | Assert.Equal("壹拾万零壹佰零壹", lexicon.GetString(10_0101));
35 | Assert.Equal("壹拾万壹仟零壹", lexicon.GetString(10_1001));
36 | Assert.Equal("壹拾万壹仟零壹拾", lexicon.GetString(10_1010));
37 |
38 | Assert.Equal(1, lexicon.GetNumber("壹"));
39 | Assert.Equal(10_0001, lexicon.GetNumber("壹拾万零壹"));
40 | Assert.Equal(10_0101, lexicon.GetNumber("壹拾万零壹佰零壹"));
41 | Assert.Equal(10_1001, lexicon.GetNumber("壹拾万壹仟零壹"));
42 | Assert.Equal(10_1010, lexicon.GetNumber("壹拾万壹仟零壹拾"));
43 | }
44 |
45 | [Fact]
46 | public void ConciseTest()
47 | {
48 | var lexicon = Lexicon.NumberWith(NumberMode.Concise);
49 |
50 | Assert.Equal("一", lexicon.GetString(1));
51 | Assert.Equal("十万零一", lexicon.GetString(10_0001));
52 | Assert.Equal("十万零一百零一", lexicon.GetString(10_0101));
53 | Assert.Equal("十万一千零一", lexicon.GetString(10_1001));
54 | Assert.Equal("十万一千零一十", lexicon.GetString(10_1010));
55 |
56 | Assert.Equal(1, lexicon.GetNumber("一"));
57 | Assert.Equal(10_0001, lexicon.GetNumber("十万零一"));
58 | Assert.Equal(10_0101, lexicon.GetNumber("十万零一百零一"));
59 | Assert.Equal(10_1001, lexicon.GetNumber("十万一千零一"));
60 | Assert.Equal(10_1010, lexicon.GetNumber("十万一千零一十"));
61 | }
62 |
63 | [Fact]
64 | public void ConciseUpperTest()
65 | {
66 | var lexicon = Lexicon.NumberWith(NumberMode.Concise | NumberMode.Upper);
67 |
68 | Assert.Equal("壹", lexicon.GetString(1));
69 | Assert.Equal("拾万零壹", lexicon.GetString(10_0001));
70 | Assert.Equal("拾万零壹佰零壹", lexicon.GetString(10_0101));
71 | Assert.Equal("拾万壹仟零壹", lexicon.GetString(10_1001));
72 | Assert.Equal("拾万壹仟零壹拾", lexicon.GetString(10_1010));
73 |
74 | Assert.Equal(1, lexicon.GetNumber("壹"));
75 | Assert.Equal(10_0001, lexicon.GetNumber("拾万零壹"));
76 | Assert.Equal(10_0101, lexicon.GetNumber("拾万零壹佰零壹"));
77 | Assert.Equal(10_1001, lexicon.GetNumber("拾万壹仟零壹"));
78 | Assert.Equal(10_1010, lexicon.GetNumber("拾万壹仟零壹拾"));
79 | }
80 |
81 | [Fact]
82 | public void CodeTest()
83 | {
84 | var lexicon = Lexicon.NumberWith(NumberMode.Code);
85 |
86 | Assert.Equal("一〇〇〇〇一", lexicon.GetString(10_0001));
87 | Assert.Equal("一〇〇一〇一", lexicon.GetString(10_0101));
88 | Assert.Equal("一〇一〇〇一", lexicon.GetString(10_1001));
89 | Assert.Equal("一〇一〇一〇", lexicon.GetString(10_1010));
90 |
91 | Assert.Equal(10_0001, lexicon.GetNumber("一〇〇〇〇一"));
92 | Assert.Equal(10_0101, lexicon.GetNumber("一〇〇一〇一"));
93 | Assert.Equal(10_1001, lexicon.GetNumber("一〇一〇〇一"));
94 | Assert.Equal(10_1010, lexicon.GetNumber("一〇一〇一〇"));
95 | }
96 |
97 | [Fact]
98 | public void CodeUpperTest()
99 | {
100 | var lexicon = Lexicon.NumberWith(NumberMode.Code | NumberMode.Upper);
101 |
102 | Assert.Equal("壹零零零零壹", lexicon.GetString(10_0001));
103 | Assert.Equal("壹零零壹零壹", lexicon.GetString(10_0101));
104 | Assert.Equal("壹零壹零零壹", lexicon.GetString(10_1001));
105 | Assert.Equal("壹零壹零壹零", lexicon.GetString(10_1010));
106 |
107 | Assert.Equal(10_0001, lexicon.GetNumber("壹零零零零壹"));
108 | Assert.Equal(10_0101, lexicon.GetNumber("壹零零壹零壹"));
109 | Assert.Equal(10_1001, lexicon.GetNumber("壹零壹零零壹"));
110 | Assert.Equal(10_1010, lexicon.GetNumber("壹零壹零壹零"));
111 | }
112 |
113 | [Fact]
114 | public void BigIntegerTest()
115 | {
116 | var lexicon = Lexicon.Number;
117 | var expected = "一万亿亿亿二千三百四十五亿亿亿六千七百八十九万亿亿零一百二十三亿亿四千五百六十七万亿八千九百零一亿二千三百四十五万六千七百八十九";
118 |
119 | Assert.Equal(expected, lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m));
120 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, lexicon.GetNumber(expected));
121 | }
122 |
123 | [Fact]
124 | public void BigIntegerUpperTest()
125 | {
126 | var lexicon = Lexicon.NumberWith(NumberMode.Upper);
127 | var expected = "壹万亿亿亿贰仟叁佰肆拾伍亿亿亿陆仟柒佰捌拾玖万亿亿零壹佰贰拾叁亿亿肆仟伍佰陆拾柒万亿捌仟玖佰零壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖";
128 |
129 | Assert.Equal(expected, lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m));
130 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, lexicon.GetNumber(expected));
131 | }
132 |
133 | [Fact]
134 | public void BigIntegerTraditionalTest()
135 | {
136 | var lexicon = Lexicon.NumberWith(NumberMode.Classical);
137 | var expected = "一穰二千三百四十五秭六千七百八十九垓零一百二十三京四千五百六十七兆八千九百零一亿二千三百四十五万六千七百八十九";
138 |
139 | Assert.Equal(expected, lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m));
140 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, lexicon.GetNumber(expected));
141 | }
142 |
143 | [Fact]
144 | public void BigIntegerTraditionalUpperTest()
145 | {
146 | var lexicon = Lexicon.NumberWith(NumberMode.Classical | NumberMode.Upper);
147 | var expected = "壹穰贰仟叁佰肆拾伍秭陆仟柒佰捌拾玖垓零壹佰贰拾叁京肆仟伍佰陆拾柒兆捌仟玖佰零壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖";
148 |
149 | Assert.Equal(expected, lexicon.GetString(1_2345_6789_0123_4567_8901_2345_6789m));
150 | Assert.Equal(1_2345_6789_0123_4567_8901_2345_6789m, lexicon.GetNumber(expected));
151 | }
152 |
153 | [Fact]
154 | public void MutilZeroTest()
155 | {
156 | var lexicon = Lexicon.Number;
157 | Assert.Equal("二十亿零一", lexicon.GetString(20_0000_0001));
158 | Assert.Equal("二十万亿零一", lexicon.GetString(20_0000_0000_0001));
159 | Assert.Equal(20_0000_0001, lexicon.GetNumber("二十亿零一"));
160 | Assert.Equal(20_0000_0000_0001, lexicon.GetNumber("二十万亿零一"));
161 | }
162 |
163 | [Fact]
164 | public void MutilZeroTraditionalTest()
165 | {
166 | var lexicon = Lexicon.NumberWith(NumberMode.Classical);
167 | Assert.Equal("二十亿零一", lexicon.GetString(20_0000_0001));
168 | Assert.Equal("二十兆零一", lexicon.GetString(20_0000_0000_0001));
169 | Assert.Equal(20_0000_0001, lexicon.GetNumber("二十亿零一"));
170 | Assert.Equal(20_0000_0000_0001, lexicon.GetNumber("二十兆零一"));
171 | }
172 |
173 | [Fact]
174 | public void AliasTest()
175 | {
176 | var lexicon = Lexicon.Number;
177 | Assert.Equal(22222, lexicon.GetNumber("两万二千两百二十二"));
178 | Assert.Throws(() => lexicon.GetNumber("两"));
179 | Assert.Throws(() => lexicon.GetNumber("两万二千两百二十两"));
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/PinyinTest.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Test.Util;
2 | using Xunit;
3 |
4 | namespace Chinese.Test;
5 |
6 | public class PinyinTest
7 | {
8 | [Fact]
9 | public void SimpleTest1()
10 | {
11 | var lexicon = MySqlLexicon.UseDefault();
12 | var str = "免费,跨平台,开源!";
13 | Assert.Equal("mian3 fei4,kua4 ping2 tai2,kai1 yuan2!", lexicon.GetPinyin(str));
14 | Assert.Equal("mian fei,kua ping tai,kai yuan!", lexicon.GetPinyin(str, PinyinFormat.WithoutTone));
15 | Assert.Equal("miǎn fèi,kuà píng tái,kāi yuán!", lexicon.GetPinyin(str, PinyinFormat.Phonetic));
16 | Assert.Equal("mf,kpt,ky!", lexicon.GetPinyin(str, PinyinFormat.InitialConsonant));
17 | }
18 |
19 | [Fact]
20 | public void SimpleTest2()
21 | {
22 | var lexicon = MySqlLexicon.UseDefault();
23 | var str = "Chinese是基于.NET平台的Chinese库。";
24 | Assert.Equal("Chinese shi4 ji1 yu2 .NET ping2 tai2 de5 Chinese ku4。", lexicon.GetPinyin(str));
25 | Assert.Equal("Chinese shi ji yu .NET ping tai de Chinese ku。", lexicon.GetPinyin(str, PinyinFormat.WithoutTone));
26 | Assert.Equal("Chinese shì jī yú .NET píng tái de Chinese kù。", lexicon.GetPinyin(str, PinyinFormat.Phonetic));
27 | Assert.Equal("Chinese sjy .NET ptd Chinese k。", lexicon.GetPinyin(str, PinyinFormat.InitialConsonant));
28 | }
29 |
30 | [Fact]
31 | public void NormalTest()
32 | {
33 | var lexicon = MySqlLexicon.UseDefault();
34 | var str = "温度设定为1度。";
35 |
36 | // 错误, 需要词性分析
37 | //TODO: 为 = wéi
38 | Assert.Equal("wen1 du4 she4 ding4 wei4 1 du4。", lexicon.GetPinyin(str));
39 | }
40 |
41 | [Fact]
42 | public void ChineseLexiconTest1()
43 | {
44 | var lexicon = MySqlLexicon.UseDefault();
45 | var str = "他是来自重庆的重量级选手。";
46 | Assert.Equal("ta1 shi4 lai2 zi4 chong2 qing4 de5 zhong4 liang4 ji2 xuan3 shou3。", lexicon.GetPinyin(str));
47 | }
48 |
49 | [Fact]
50 | public void NotSameWordTest()
51 | {
52 | var lexicon = MySqlLexicon.UseDefault();
53 | Assert.Equal("伺服器中止了服務。", lexicon.ToTraditional("服务器中止了服务。"));
54 | Assert.Equal("fu2 wu4 qi4 zhong1 zhi3 le5 fu2 wu4。", lexicon.GetPinyin("服务器中止了服务。", ChineseType.Simplified));
55 | Assert.Equal("si4 fu2 qi4 zhong1 zhi3 le5 fu2 wu4。", lexicon.GetPinyin("伺服器中止了服務。", ChineseType.Traditional));
56 | }
57 |
58 | [Fact]
59 | public void ParagraghTest()
60 | {
61 | var lexicon = MySqlLexicon.UseDefault();
62 | var text = @"这地方的火烧云变化极多,一会儿红彤彤的,一会儿金灿灿的,一会儿半紫半黄,一会儿半灰半百合色。葡萄灰、梨黄、茄子紫,这些颜色天空都有。还有些说也说不出来、见也没见过的颜色。
63 |
64 | 一会儿,天空出现一匹马,马头向南,马尾向西。马是跪着的,像等人骑上它的背,它才站起来似的。过了两三秒钟,那匹马大起来了,腿伸开了,脖子也长了,尾巴却不见了。看的人正在寻找马尾巴,那匹马变模糊了。
65 |
66 | 忽然又来了一条大狗。那条狗十分凶猛,在向前跑,后边似乎还跟着好几条小狗。跑着跑着,小狗不知哪里去了,大狗也不见了。
67 |
68 | 接着又来了一头大狮子,跟庙门前的石头狮子一模一样,也那么大,也那样蹲着,很威武很镇静地蹲着。可是一转眼就变了,再也找不着了。";
69 |
70 | var pinyin = lexicon.GetPinyin(text, ChineseType.Simplified, PinyinFormat.Phonetic);
71 |
72 | // 错误, 需要词性分析
73 | //TODO: 的背 = de / bēi
74 | //TODO: 还跟着 = huán / gēn zhe
75 | Assert.Equal(
76 | """
77 | zhè dì fāng de huǒ shāo yún biàn huà jí duō,yī huì er hóng tóng tóng de,yī huì er jīn càn càn de,yī huì er bàn zǐ bàn huáng,yī huì er bàn huī bàn bǎi hé sè。pú táo huī、lí huáng、qié zi zǐ,zhè xiē yán sè tiān kōng dōu yǒu。huán yǒu xiē shuō yě shuō bù chū lái、jiàn yě méi jiàn guò de yán sè。
78 |
79 | yī huì er,tiān kōng chū xiàn yī pǐ mǎ,mǎ tóu xiàng nán,mǎ wěi xiàng xī。mǎ shì guì zhe de,xiàng děng rén qí shàng tā de bēi,tā cái zhàn qǐ lái shì de。guò le liǎng sān miǎo zhōng,nà pǐ mǎ dà qǐ lái le,tuǐ shēn kāi le,bó zi yě zhǎng le,wěi bā què bù jiàn le。kàn de rén zhèng zài xún zhǎo mǎ wěi bā,nà pǐ mǎ biàn mó hú le。
80 |
81 | hū rán yòu lái le yī tiáo dà gǒu。nà tiáo gǒu shí fēn xiōng měng,zài xiàng qián pǎo,hòu biān sì hū huán gēn zhe hǎo jǐ tiáo xiǎo gǒu。pǎo zhe pǎo zhe,xiǎo gǒu bù zhī nǎ lǐ qù le,dà gǒu yě bù jiàn le。
82 |
83 | jiē zhe yòu lái le yī tóu dà shī zi,gēn miào mén qián de shí tou shī zi yī mú yī yàng,yě nà me dà,yě nà yàng dūn zhe,hěn wēi wǔ hěn zhèn jìng dì dūn zhe。kě shì yī zhuǎn yǎn jiù biàn le,zài yě zhǎo bù zháo le。
84 | """
85 | , pinyin);
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/RegionTests.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Mainland;
2 | using NStandard;
3 | using System.Linq;
4 | using Xunit;
5 |
6 | namespace Chinese.Test;
7 |
8 | public class RegionTests
9 | {
10 | [Fact]
11 | public void Test1()
12 | {
13 | var result = Generator.Build();
14 | var country = result.Cities.First(x => x.Name == "北京市");
15 | Assert.Equal("东城区,西城区", country.Countries.Select(x => x.Name).Take(2).Join(","));
16 | }
17 |
18 | [Fact]
19 | public void Test2()
20 | {
21 | var result = Generator.Build();
22 | var country = result.Countries.First(x => x.Name == "长安区");
23 | Assert.Equal("石家庄市", country.City.Name);
24 | Assert.Equal("河北省", country.Province.Name);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/TokenizerTests.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Test.Util;
2 | using System.Linq;
3 | using Xunit;
4 |
5 | namespace Chinese.Test;
6 |
7 | public class TokenizerTests
8 | {
9 | [Fact]
10 | public void Test1()
11 | {
12 | var lexicon = MySqlLexicon.UseDefault();
13 | var sentence = "中国北京是直辖市,重庆也是直辖市。";
14 |
15 | var words = lexicon.SplitWords(sentence, ChineseType.Simplified);
16 | var exceptedWords = new[] { "中国", "北京", "是", "直辖市", ",", "重庆", "也是", "直辖市", "。" };
17 | Assert.Equal(exceptedWords, [.. words.Select(x => x.Simplified)]);
18 |
19 | var pinyin = lexicon.GetPinyin(sentence, PinyinFormat.Phonetic);
20 | Assert.Equal("zhōng guó běi jīng shì zhí xiá shì,chóng qìng yě shì zhí xiá shì。", pinyin);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Tests/Chinese.Test/Util/MySqlLexicon.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Data;
2 | using Microsoft.EntityFrameworkCore;
3 |
4 | namespace Chinese.Test.Util;
5 |
6 | public class MySqlLexicon : Lexicon
7 | {
8 | public static MySqlLexicon UseDefault()
9 | {
10 | var mysqlConnectionString = "server=127.0.0.1;port=33306;user=root;password=root;database=chinese";
11 | var mysqlOptions = new DbContextOptionsBuilder().UseMySql(mysqlConnectionString, ServerVersion.AutoDetect(mysqlConnectionString), null).Options;
12 |
13 | var context = new ChineseDbContext(mysqlOptions);
14 | return new MySqlLexicon(context);
15 | }
16 |
17 | public MySqlLexicon(ChineseDbContext context)
18 | {
19 | Add(context.Words);
20 | Add(context.Chars);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-ef": {
6 | "version": "6.0.11",
7 | "commands": [
8 | "dotnet-ef"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/ApplicationDbContextFactory.cs:
--------------------------------------------------------------------------------
1 | using Chinese.Data;
2 | using Microsoft.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore.Design;
4 |
5 | namespace DbCreator.MySql;
6 |
7 | public class ApplicationDbContextFactory : IDesignTimeDbContextFactory
8 | {
9 | public ChineseDbContext CreateDbContext(string[] args)
10 | {
11 | var mysqlConnectionString = "server=127.0.0.1;port=33306;user=root;password=root;database=chinese";
12 | var mysqlOptions = new DbContextOptionsBuilder().UseMySql(
13 | mysqlConnectionString,
14 | ServerVersion.AutoDetect(mysqlConnectionString),
15 | b => b.MigrationsAssembly("DbCreator.MySql")
16 | ).Options;
17 |
18 | return new ChineseDbContext(mysqlOptions);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/DbCreator.MySql.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 | all
15 | runtime; build; native; contentfiles; analyzers; buildtransitive
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20221112224627_202211130646.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20221112224627_202211130646")]
15 | partial class _202211130646
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("IsPolyphone")
35 | .HasColumnType("tinyint(1)");
36 |
37 | b.Property("Pinyins")
38 | .IsRequired()
39 | .HasColumnType("longtext");
40 |
41 | b.Property("Simplified")
42 | .IsRequired()
43 | .HasColumnType("longtext");
44 |
45 | b.Property("SimplifiedPinyin")
46 | .IsRequired()
47 | .HasColumnType("longtext");
48 |
49 | b.Property("Traditional")
50 | .IsRequired()
51 | .HasColumnType("longtext");
52 |
53 | b.Property("TraditionalPinyin")
54 | .IsRequired()
55 | .HasColumnType("longtext");
56 |
57 | b.Property("Types")
58 | .HasColumnType("int");
59 |
60 | b.HasKey("Unicode");
61 |
62 | b.ToTable("Chars");
63 | });
64 |
65 | modelBuilder.Entity("Chinese.Data.Data.NumericWord", b =>
66 | {
67 | b.Property("Id")
68 | .ValueGeneratedOnAdd()
69 | .HasColumnType("char(36)");
70 |
71 | b.Property("Simplified")
72 | .IsRequired()
73 | .HasColumnType("longtext");
74 |
75 | b.Property("SimplifiedPinyin")
76 | .IsRequired()
77 | .HasColumnType("longtext");
78 |
79 | b.Property("Traditional")
80 | .IsRequired()
81 | .HasColumnType("longtext");
82 |
83 | b.Property("TraditionalPinyin")
84 | .IsRequired()
85 | .HasColumnType("longtext");
86 |
87 | b.Property("Type")
88 | .HasColumnType("int");
89 |
90 | b.Property("Value")
91 | .HasColumnType("int");
92 |
93 | b.HasKey("Id");
94 |
95 | b.ToTable("NumericWords");
96 | });
97 |
98 | modelBuilder.Entity("Chinese.Word", b =>
99 | {
100 | b.Property("Id")
101 | .ValueGeneratedOnAdd()
102 | .HasColumnType("char(36)");
103 |
104 | b.Property("Simplified")
105 | .IsRequired()
106 | .HasColumnType("longtext");
107 |
108 | b.Property("SimplifiedPinyin")
109 | .IsRequired()
110 | .HasColumnType("longtext");
111 |
112 | b.Property("Traditional")
113 | .IsRequired()
114 | .HasColumnType("longtext");
115 |
116 | b.Property("TraditionalPinyin")
117 | .IsRequired()
118 | .HasColumnType("longtext");
119 |
120 | b.Property("Type")
121 | .HasColumnType("int");
122 |
123 | b.HasKey("Id");
124 |
125 | b.ToTable("Words");
126 | });
127 | #pragma warning restore 612, 618
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20221112224627_202211130646.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Metadata;
2 | using Microsoft.EntityFrameworkCore.Migrations;
3 |
4 | #nullable disable
5 |
6 | namespace DbCreator.MySql.Migrations;
7 |
8 | public partial class _202211130646 : Migration
9 | {
10 | protected override void Up(MigrationBuilder migrationBuilder)
11 | {
12 | migrationBuilder.AlterDatabase()
13 | .Annotation("MySql:CharSet", "utf8mb4");
14 |
15 | migrationBuilder.CreateTable(
16 | name: "Chars",
17 | columns: table => new
18 | {
19 | Unicode = table.Column(type: "int", nullable: false)
20 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
21 | Character = table.Column(type: "varchar(1)", nullable: false)
22 | .Annotation("MySql:CharSet", "utf8mb4"),
23 | Pinyins = table.Column(type: "longtext", nullable: false)
24 | .Annotation("MySql:CharSet", "utf8mb4"),
25 | IsPolyphone = table.Column(type: "tinyint(1)", nullable: false),
26 | Types = table.Column(type: "int", nullable: false),
27 | Simplified = table.Column(type: "longtext", nullable: false)
28 | .Annotation("MySql:CharSet", "utf8mb4"),
29 | Traditional = table.Column(type: "longtext", nullable: false)
30 | .Annotation("MySql:CharSet", "utf8mb4"),
31 | SimplifiedPinyin = table.Column(type: "longtext", nullable: false)
32 | .Annotation("MySql:CharSet", "utf8mb4"),
33 | TraditionalPinyin = table.Column(type: "longtext", nullable: false)
34 | .Annotation("MySql:CharSet", "utf8mb4")
35 | },
36 | constraints: table =>
37 | {
38 | table.PrimaryKey("PK_Chars", x => x.Unicode);
39 | })
40 | .Annotation("MySql:CharSet", "utf8mb4");
41 |
42 | migrationBuilder.CreateTable(
43 | name: "NumericWords",
44 | columns: table => new
45 | {
46 | Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
47 | Type = table.Column(type: "int", nullable: false),
48 | Simplified = table.Column(type: "longtext", nullable: false)
49 | .Annotation("MySql:CharSet", "utf8mb4"),
50 | Traditional = table.Column(type: "longtext", nullable: false)
51 | .Annotation("MySql:CharSet", "utf8mb4"),
52 | SimplifiedPinyin = table.Column(type: "longtext", nullable: false)
53 | .Annotation("MySql:CharSet", "utf8mb4"),
54 | TraditionalPinyin = table.Column(type: "longtext", nullable: false)
55 | .Annotation("MySql:CharSet", "utf8mb4"),
56 | Value = table.Column(type: "int", nullable: false)
57 | },
58 | constraints: table =>
59 | {
60 | table.PrimaryKey("PK_NumericWords", x => x.Id);
61 | })
62 | .Annotation("MySql:CharSet", "utf8mb4");
63 |
64 | migrationBuilder.CreateTable(
65 | name: "Words",
66 | columns: table => new
67 | {
68 | Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
69 | Type = table.Column(type: "int", nullable: false),
70 | Simplified = table.Column(type: "longtext", nullable: false)
71 | .Annotation("MySql:CharSet", "utf8mb4"),
72 | Traditional = table.Column(type: "longtext", nullable: false)
73 | .Annotation("MySql:CharSet", "utf8mb4"),
74 | SimplifiedPinyin = table.Column(type: "longtext", nullable: false)
75 | .Annotation("MySql:CharSet", "utf8mb4"),
76 | TraditionalPinyin = table.Column(type: "longtext", nullable: false)
77 | .Annotation("MySql:CharSet", "utf8mb4")
78 | },
79 | constraints: table =>
80 | {
81 | table.PrimaryKey("PK_Words", x => x.Id);
82 | })
83 | .Annotation("MySql:CharSet", "utf8mb4");
84 | }
85 |
86 | protected override void Down(MigrationBuilder migrationBuilder)
87 | {
88 | migrationBuilder.DropTable(
89 | name: "Chars");
90 |
91 | migrationBuilder.DropTable(
92 | name: "NumericWords");
93 |
94 | migrationBuilder.DropTable(
95 | name: "Words");
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20221113154648_202211132346.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20221113154648_202211132346")]
15 | partial class _202211132346
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("IsPolyphone")
35 | .HasColumnType("tinyint(1)");
36 |
37 | b.Property("Pinyins")
38 | .IsRequired()
39 | .HasMaxLength(64)
40 | .HasColumnType("varchar(64)");
41 |
42 | b.Property("Simplified")
43 | .IsRequired()
44 | .HasMaxLength(64)
45 | .HasColumnType("varchar(64)");
46 |
47 | b.Property("SimplifiedPinyin")
48 | .IsRequired()
49 | .HasMaxLength(64)
50 | .HasColumnType("varchar(64)");
51 |
52 | b.Property("Traditional")
53 | .IsRequired()
54 | .HasMaxLength(64)
55 | .HasColumnType("varchar(64)");
56 |
57 | b.Property("TraditionalPinyin")
58 | .IsRequired()
59 | .HasMaxLength(64)
60 | .HasColumnType("varchar(64)");
61 |
62 | b.Property("Types")
63 | .HasColumnType("int");
64 |
65 | b.HasKey("Unicode");
66 |
67 | b.ToTable("Chars");
68 | });
69 |
70 | modelBuilder.Entity("Chinese.Data.Data.NumericWord", b =>
71 | {
72 | b.Property("Id")
73 | .ValueGeneratedOnAdd()
74 | .HasColumnType("char(36)");
75 |
76 | b.Property("Simplified")
77 | .IsRequired()
78 | .HasMaxLength(64)
79 | .HasColumnType("varchar(64)");
80 |
81 | b.Property("SimplifiedPinyin")
82 | .IsRequired()
83 | .HasMaxLength(64)
84 | .HasColumnType("varchar(64)");
85 |
86 | b.Property("Traditional")
87 | .IsRequired()
88 | .HasMaxLength(64)
89 | .HasColumnType("varchar(64)");
90 |
91 | b.Property("TraditionalPinyin")
92 | .IsRequired()
93 | .HasMaxLength(64)
94 | .HasColumnType("varchar(64)");
95 |
96 | b.Property("Type")
97 | .HasColumnType("int");
98 |
99 | b.Property("Value")
100 | .HasColumnType("int");
101 |
102 | b.HasKey("Id");
103 |
104 | b.ToTable("Numerics");
105 | });
106 |
107 | modelBuilder.Entity("Chinese.Word", b =>
108 | {
109 | b.Property("Id")
110 | .ValueGeneratedOnAdd()
111 | .HasColumnType("char(36)");
112 |
113 | b.Property("Simplified")
114 | .IsRequired()
115 | .HasMaxLength(64)
116 | .HasColumnType("varchar(64)");
117 |
118 | b.Property("SimplifiedPinyin")
119 | .IsRequired()
120 | .HasMaxLength(64)
121 | .HasColumnType("varchar(64)");
122 |
123 | b.Property("Traditional")
124 | .IsRequired()
125 | .HasMaxLength(64)
126 | .HasColumnType("varchar(64)");
127 |
128 | b.Property("TraditionalPinyin")
129 | .IsRequired()
130 | .HasMaxLength(64)
131 | .HasColumnType("varchar(64)");
132 |
133 | b.Property("Type")
134 | .HasColumnType("int");
135 |
136 | b.HasKey("Id");
137 |
138 | b.ToTable("Words");
139 | });
140 | #pragma warning restore 612, 618
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20221113154648_202211132346.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace DbCreator.MySql.Migrations;
6 |
7 | public partial class _202211132346 : Migration
8 | {
9 | protected override void Up(MigrationBuilder migrationBuilder)
10 | {
11 | migrationBuilder.DropPrimaryKey(
12 | name: "PK_NumericWords",
13 | table: "NumericWords");
14 |
15 | migrationBuilder.RenameTable(
16 | name: "NumericWords",
17 | newName: "Numerics");
18 |
19 | migrationBuilder.AlterColumn(
20 | name: "TraditionalPinyin",
21 | table: "Words",
22 | type: "varchar(64)",
23 | maxLength: 64,
24 | nullable: false,
25 | oldClrType: typeof(string),
26 | oldType: "longtext")
27 | .Annotation("MySql:CharSet", "utf8mb4")
28 | .OldAnnotation("MySql:CharSet", "utf8mb4");
29 |
30 | migrationBuilder.AlterColumn(
31 | name: "Traditional",
32 | table: "Words",
33 | type: "varchar(64)",
34 | maxLength: 64,
35 | nullable: false,
36 | oldClrType: typeof(string),
37 | oldType: "longtext")
38 | .Annotation("MySql:CharSet", "utf8mb4")
39 | .OldAnnotation("MySql:CharSet", "utf8mb4");
40 |
41 | migrationBuilder.AlterColumn(
42 | name: "SimplifiedPinyin",
43 | table: "Words",
44 | type: "varchar(64)",
45 | maxLength: 64,
46 | nullable: false,
47 | oldClrType: typeof(string),
48 | oldType: "longtext")
49 | .Annotation("MySql:CharSet", "utf8mb4")
50 | .OldAnnotation("MySql:CharSet", "utf8mb4");
51 |
52 | migrationBuilder.AlterColumn(
53 | name: "Simplified",
54 | table: "Words",
55 | type: "varchar(64)",
56 | maxLength: 64,
57 | nullable: false,
58 | oldClrType: typeof(string),
59 | oldType: "longtext")
60 | .Annotation("MySql:CharSet", "utf8mb4")
61 | .OldAnnotation("MySql:CharSet", "utf8mb4");
62 |
63 | migrationBuilder.AlterColumn(
64 | name: "TraditionalPinyin",
65 | table: "Chars",
66 | type: "varchar(64)",
67 | maxLength: 64,
68 | nullable: false,
69 | oldClrType: typeof(string),
70 | oldType: "longtext")
71 | .Annotation("MySql:CharSet", "utf8mb4")
72 | .OldAnnotation("MySql:CharSet", "utf8mb4");
73 |
74 | migrationBuilder.AlterColumn(
75 | name: "Traditional",
76 | table: "Chars",
77 | type: "varchar(64)",
78 | maxLength: 64,
79 | nullable: false,
80 | oldClrType: typeof(string),
81 | oldType: "longtext")
82 | .Annotation("MySql:CharSet", "utf8mb4")
83 | .OldAnnotation("MySql:CharSet", "utf8mb4");
84 |
85 | migrationBuilder.AlterColumn(
86 | name: "SimplifiedPinyin",
87 | table: "Chars",
88 | type: "varchar(64)",
89 | maxLength: 64,
90 | nullable: false,
91 | oldClrType: typeof(string),
92 | oldType: "longtext")
93 | .Annotation("MySql:CharSet", "utf8mb4")
94 | .OldAnnotation("MySql:CharSet", "utf8mb4");
95 |
96 | migrationBuilder.AlterColumn(
97 | name: "Simplified",
98 | table: "Chars",
99 | type: "varchar(64)",
100 | maxLength: 64,
101 | nullable: false,
102 | oldClrType: typeof(string),
103 | oldType: "longtext")
104 | .Annotation("MySql:CharSet", "utf8mb4")
105 | .OldAnnotation("MySql:CharSet", "utf8mb4");
106 |
107 | migrationBuilder.AlterColumn(
108 | name: "Pinyins",
109 | table: "Chars",
110 | type: "varchar(64)",
111 | maxLength: 64,
112 | nullable: false,
113 | oldClrType: typeof(string),
114 | oldType: "longtext")
115 | .Annotation("MySql:CharSet", "utf8mb4")
116 | .OldAnnotation("MySql:CharSet", "utf8mb4");
117 |
118 | migrationBuilder.AlterColumn(
119 | name: "TraditionalPinyin",
120 | table: "Numerics",
121 | type: "varchar(64)",
122 | maxLength: 64,
123 | nullable: false,
124 | oldClrType: typeof(string),
125 | oldType: "longtext")
126 | .Annotation("MySql:CharSet", "utf8mb4")
127 | .OldAnnotation("MySql:CharSet", "utf8mb4");
128 |
129 | migrationBuilder.AlterColumn(
130 | name: "Traditional",
131 | table: "Numerics",
132 | type: "varchar(64)",
133 | maxLength: 64,
134 | nullable: false,
135 | oldClrType: typeof(string),
136 | oldType: "longtext")
137 | .Annotation("MySql:CharSet", "utf8mb4")
138 | .OldAnnotation("MySql:CharSet", "utf8mb4");
139 |
140 | migrationBuilder.AlterColumn(
141 | name: "SimplifiedPinyin",
142 | table: "Numerics",
143 | type: "varchar(64)",
144 | maxLength: 64,
145 | nullable: false,
146 | oldClrType: typeof(string),
147 | oldType: "longtext")
148 | .Annotation("MySql:CharSet", "utf8mb4")
149 | .OldAnnotation("MySql:CharSet", "utf8mb4");
150 |
151 | migrationBuilder.AlterColumn(
152 | name: "Simplified",
153 | table: "Numerics",
154 | type: "varchar(64)",
155 | maxLength: 64,
156 | nullable: false,
157 | oldClrType: typeof(string),
158 | oldType: "longtext")
159 | .Annotation("MySql:CharSet", "utf8mb4")
160 | .OldAnnotation("MySql:CharSet", "utf8mb4");
161 |
162 | migrationBuilder.AddPrimaryKey(
163 | name: "PK_Numerics",
164 | table: "Numerics",
165 | column: "Id");
166 | }
167 |
168 | protected override void Down(MigrationBuilder migrationBuilder)
169 | {
170 | migrationBuilder.DropPrimaryKey(
171 | name: "PK_Numerics",
172 | table: "Numerics");
173 |
174 | migrationBuilder.RenameTable(
175 | name: "Numerics",
176 | newName: "NumericWords");
177 |
178 | migrationBuilder.AlterColumn(
179 | name: "TraditionalPinyin",
180 | table: "Words",
181 | type: "longtext",
182 | nullable: false,
183 | oldClrType: typeof(string),
184 | oldType: "varchar(64)",
185 | oldMaxLength: 64)
186 | .Annotation("MySql:CharSet", "utf8mb4")
187 | .OldAnnotation("MySql:CharSet", "utf8mb4");
188 |
189 | migrationBuilder.AlterColumn(
190 | name: "Traditional",
191 | table: "Words",
192 | type: "longtext",
193 | nullable: false,
194 | oldClrType: typeof(string),
195 | oldType: "varchar(64)",
196 | oldMaxLength: 64)
197 | .Annotation("MySql:CharSet", "utf8mb4")
198 | .OldAnnotation("MySql:CharSet", "utf8mb4");
199 |
200 | migrationBuilder.AlterColumn(
201 | name: "SimplifiedPinyin",
202 | table: "Words",
203 | type: "longtext",
204 | nullable: false,
205 | oldClrType: typeof(string),
206 | oldType: "varchar(64)",
207 | oldMaxLength: 64)
208 | .Annotation("MySql:CharSet", "utf8mb4")
209 | .OldAnnotation("MySql:CharSet", "utf8mb4");
210 |
211 | migrationBuilder.AlterColumn(
212 | name: "Simplified",
213 | table: "Words",
214 | type: "longtext",
215 | nullable: false,
216 | oldClrType: typeof(string),
217 | oldType: "varchar(64)",
218 | oldMaxLength: 64)
219 | .Annotation("MySql:CharSet", "utf8mb4")
220 | .OldAnnotation("MySql:CharSet", "utf8mb4");
221 |
222 | migrationBuilder.AlterColumn(
223 | name: "TraditionalPinyin",
224 | table: "Chars",
225 | type: "longtext",
226 | nullable: false,
227 | oldClrType: typeof(string),
228 | oldType: "varchar(64)",
229 | oldMaxLength: 64)
230 | .Annotation("MySql:CharSet", "utf8mb4")
231 | .OldAnnotation("MySql:CharSet", "utf8mb4");
232 |
233 | migrationBuilder.AlterColumn(
234 | name: "Traditional",
235 | table: "Chars",
236 | type: "longtext",
237 | nullable: false,
238 | oldClrType: typeof(string),
239 | oldType: "varchar(64)",
240 | oldMaxLength: 64)
241 | .Annotation("MySql:CharSet", "utf8mb4")
242 | .OldAnnotation("MySql:CharSet", "utf8mb4");
243 |
244 | migrationBuilder.AlterColumn(
245 | name: "SimplifiedPinyin",
246 | table: "Chars",
247 | type: "longtext",
248 | nullable: false,
249 | oldClrType: typeof(string),
250 | oldType: "varchar(64)",
251 | oldMaxLength: 64)
252 | .Annotation("MySql:CharSet", "utf8mb4")
253 | .OldAnnotation("MySql:CharSet", "utf8mb4");
254 |
255 | migrationBuilder.AlterColumn(
256 | name: "Simplified",
257 | table: "Chars",
258 | type: "longtext",
259 | nullable: false,
260 | oldClrType: typeof(string),
261 | oldType: "varchar(64)",
262 | oldMaxLength: 64)
263 | .Annotation("MySql:CharSet", "utf8mb4")
264 | .OldAnnotation("MySql:CharSet", "utf8mb4");
265 |
266 | migrationBuilder.AlterColumn(
267 | name: "Pinyins",
268 | table: "Chars",
269 | type: "longtext",
270 | nullable: false,
271 | oldClrType: typeof(string),
272 | oldType: "varchar(64)",
273 | oldMaxLength: 64)
274 | .Annotation("MySql:CharSet", "utf8mb4")
275 | .OldAnnotation("MySql:CharSet", "utf8mb4");
276 |
277 | migrationBuilder.AlterColumn(
278 | name: "TraditionalPinyin",
279 | table: "NumericWords",
280 | type: "longtext",
281 | nullable: false,
282 | oldClrType: typeof(string),
283 | oldType: "varchar(64)",
284 | oldMaxLength: 64)
285 | .Annotation("MySql:CharSet", "utf8mb4")
286 | .OldAnnotation("MySql:CharSet", "utf8mb4");
287 |
288 | migrationBuilder.AlterColumn(
289 | name: "Traditional",
290 | table: "NumericWords",
291 | type: "longtext",
292 | nullable: false,
293 | oldClrType: typeof(string),
294 | oldType: "varchar(64)",
295 | oldMaxLength: 64)
296 | .Annotation("MySql:CharSet", "utf8mb4")
297 | .OldAnnotation("MySql:CharSet", "utf8mb4");
298 |
299 | migrationBuilder.AlterColumn(
300 | name: "SimplifiedPinyin",
301 | table: "NumericWords",
302 | type: "longtext",
303 | nullable: false,
304 | oldClrType: typeof(string),
305 | oldType: "varchar(64)",
306 | oldMaxLength: 64)
307 | .Annotation("MySql:CharSet", "utf8mb4")
308 | .OldAnnotation("MySql:CharSet", "utf8mb4");
309 |
310 | migrationBuilder.AlterColumn(
311 | name: "Simplified",
312 | table: "NumericWords",
313 | type: "longtext",
314 | nullable: false,
315 | oldClrType: typeof(string),
316 | oldType: "varchar(64)",
317 | oldMaxLength: 64)
318 | .Annotation("MySql:CharSet", "utf8mb4")
319 | .OldAnnotation("MySql:CharSet", "utf8mb4");
320 |
321 | migrationBuilder.AddPrimaryKey(
322 | name: "PK_NumericWords",
323 | table: "NumericWords",
324 | column: "Id");
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221003235_202302210832.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20230221003235_202302210832")]
15 | partial class _202302210832
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("IsPolyphone")
35 | .HasColumnType("tinyint(1)");
36 |
37 | b.Property("Pinyins")
38 | .IsRequired()
39 | .HasMaxLength(64)
40 | .HasColumnType("varchar(64)");
41 |
42 | b.Property("Simplified")
43 | .IsRequired()
44 | .HasMaxLength(64)
45 | .HasColumnType("varchar(64)");
46 |
47 | b.Property("SimplifiedPinyin")
48 | .IsRequired()
49 | .HasMaxLength(64)
50 | .HasColumnType("varchar(64)");
51 |
52 | b.Property("Traditional")
53 | .IsRequired()
54 | .HasMaxLength(64)
55 | .HasColumnType("varchar(64)");
56 |
57 | b.Property("TraditionalPinyin")
58 | .IsRequired()
59 | .HasMaxLength(64)
60 | .HasColumnType("varchar(64)");
61 |
62 | b.Property("Types")
63 | .HasColumnType("int");
64 |
65 | b.HasKey("Unicode");
66 |
67 | b.ToTable("Chars");
68 | });
69 |
70 | modelBuilder.Entity("Chinese.Data.Data.NumericWord", b =>
71 | {
72 | b.Property("Id")
73 | .ValueGeneratedOnAdd()
74 | .HasColumnType("char(36)");
75 |
76 | b.Property("Simplified")
77 | .IsRequired()
78 | .HasMaxLength(64)
79 | .HasColumnType("varchar(64)");
80 |
81 | b.Property("SimplifiedPinyin")
82 | .IsRequired()
83 | .HasMaxLength(64)
84 | .HasColumnType("varchar(64)");
85 |
86 | b.Property("Traditional")
87 | .IsRequired()
88 | .HasMaxLength(64)
89 | .HasColumnType("varchar(64)");
90 |
91 | b.Property("TraditionalPinyin")
92 | .IsRequired()
93 | .HasMaxLength(64)
94 | .HasColumnType("varchar(64)");
95 |
96 | b.Property("Type")
97 | .HasColumnType("int");
98 |
99 | b.Property("Value")
100 | .HasColumnType("int");
101 |
102 | b.HasKey("Id");
103 |
104 | b.ToTable("Numerics");
105 | });
106 |
107 | modelBuilder.Entity("Chinese.Word", b =>
108 | {
109 | b.Property("Id")
110 | .ValueGeneratedOnAdd()
111 | .HasColumnType("char(36)");
112 |
113 | b.Property("HashCode")
114 | .HasColumnType("int");
115 |
116 | b.Property("Simplified")
117 | .IsRequired()
118 | .HasMaxLength(64)
119 | .HasColumnType("varchar(64)");
120 |
121 | b.Property("SimplifiedPinyin")
122 | .IsRequired()
123 | .HasMaxLength(64)
124 | .HasColumnType("varchar(64)");
125 |
126 | b.Property("Traditional")
127 | .IsRequired()
128 | .HasMaxLength(64)
129 | .HasColumnType("varchar(64)");
130 |
131 | b.Property("TraditionalPinyin")
132 | .IsRequired()
133 | .HasMaxLength(64)
134 | .HasColumnType("varchar(64)");
135 |
136 | b.Property("Type")
137 | .HasColumnType("int");
138 |
139 | b.HasKey("Id");
140 |
141 | b.ToTable("Words");
142 | });
143 | #pragma warning restore 612, 618
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221003235_202302210832.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace DbCreator.MySql.Migrations;
6 |
7 | public partial class _202302210832 : Migration
8 | {
9 | protected override void Up(MigrationBuilder migrationBuilder)
10 | {
11 | migrationBuilder.AddColumn(
12 | name: "HashCode",
13 | table: "Words",
14 | type: "int",
15 | nullable: false,
16 | defaultValue: 0);
17 | }
18 |
19 | protected override void Down(MigrationBuilder migrationBuilder)
20 | {
21 | migrationBuilder.DropColumn(
22 | name: "HashCode",
23 | table: "Words");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221004748_202302210846.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20230221004748_202302210846")]
15 | partial class _202302210846
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("DefaultPinyin")
35 | .IsRequired()
36 | .HasMaxLength(64)
37 | .HasColumnType("varchar(64)");
38 |
39 | b.Property("IsPolyphone")
40 | .HasColumnType("tinyint(1)");
41 |
42 | b.Property("Pinyins")
43 | .IsRequired()
44 | .HasMaxLength(64)
45 | .HasColumnType("varchar(64)");
46 |
47 | b.Property("Simplified")
48 | .IsRequired()
49 | .HasMaxLength(64)
50 | .HasColumnType("varchar(64)");
51 |
52 | b.Property("SimplifiedPinyin")
53 | .IsRequired()
54 | .HasMaxLength(64)
55 | .HasColumnType("varchar(64)");
56 |
57 | b.Property("Traditional")
58 | .IsRequired()
59 | .HasMaxLength(64)
60 | .HasColumnType("varchar(64)");
61 |
62 | b.Property("TraditionalPinyin")
63 | .IsRequired()
64 | .HasMaxLength(64)
65 | .HasColumnType("varchar(64)");
66 |
67 | b.Property("Types")
68 | .HasColumnType("int");
69 |
70 | b.HasKey("Unicode");
71 |
72 | b.ToTable("Chars");
73 | });
74 |
75 | modelBuilder.Entity("Chinese.Data.Data.NumericWord", b =>
76 | {
77 | b.Property("Id")
78 | .ValueGeneratedOnAdd()
79 | .HasColumnType("char(36)");
80 |
81 | b.Property("Simplified")
82 | .IsRequired()
83 | .HasMaxLength(64)
84 | .HasColumnType("varchar(64)");
85 |
86 | b.Property("SimplifiedPinyin")
87 | .IsRequired()
88 | .HasMaxLength(64)
89 | .HasColumnType("varchar(64)");
90 |
91 | b.Property("Traditional")
92 | .IsRequired()
93 | .HasMaxLength(64)
94 | .HasColumnType("varchar(64)");
95 |
96 | b.Property("TraditionalPinyin")
97 | .IsRequired()
98 | .HasMaxLength(64)
99 | .HasColumnType("varchar(64)");
100 |
101 | b.Property("Type")
102 | .HasColumnType("int");
103 |
104 | b.Property("Value")
105 | .HasColumnType("int");
106 |
107 | b.HasKey("Id");
108 |
109 | b.ToTable("Numerics");
110 | });
111 |
112 | modelBuilder.Entity("Chinese.Word", b =>
113 | {
114 | b.Property("Id")
115 | .ValueGeneratedOnAdd()
116 | .HasColumnType("char(36)");
117 |
118 | b.Property("HashCode")
119 | .HasColumnType("int");
120 |
121 | b.Property("Simplified")
122 | .IsRequired()
123 | .HasMaxLength(64)
124 | .HasColumnType("varchar(64)");
125 |
126 | b.Property("SimplifiedPinyin")
127 | .IsRequired()
128 | .HasMaxLength(64)
129 | .HasColumnType("varchar(64)");
130 |
131 | b.Property("Traditional")
132 | .IsRequired()
133 | .HasMaxLength(64)
134 | .HasColumnType("varchar(64)");
135 |
136 | b.Property("TraditionalPinyin")
137 | .IsRequired()
138 | .HasMaxLength(64)
139 | .HasColumnType("varchar(64)");
140 |
141 | b.Property("Type")
142 | .HasColumnType("int");
143 |
144 | b.HasKey("Id");
145 |
146 | b.ToTable("Words");
147 | });
148 | #pragma warning restore 612, 618
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221004748_202302210846.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace DbCreator.MySql.Migrations;
6 |
7 | public partial class _202302210846 : Migration
8 | {
9 | protected override void Up(MigrationBuilder migrationBuilder)
10 | {
11 | migrationBuilder.AddColumn(
12 | name: "DefaultPinyin",
13 | table: "Chars",
14 | type: "varchar(64)",
15 | maxLength: 64,
16 | nullable: false,
17 | defaultValue: "")
18 | .Annotation("MySql:CharSet", "utf8mb4");
19 | }
20 |
21 | protected override void Down(MigrationBuilder migrationBuilder)
22 | {
23 | migrationBuilder.DropColumn(
24 | name: "DefaultPinyin",
25 | table: "Chars");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221032034_202302211120.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20230221032034_202302211120")]
15 | partial class _202302211120
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("DefaultPinyin")
35 | .IsRequired()
36 | .HasMaxLength(64)
37 | .HasColumnType("varchar(64)");
38 |
39 | b.Property("IsPolyphone")
40 | .HasColumnType("tinyint(1)");
41 |
42 | b.Property("Pinyins")
43 | .IsRequired()
44 | .HasMaxLength(64)
45 | .HasColumnType("varchar(64)");
46 |
47 | b.Property("Sight")
48 | .HasColumnType("tinyint(1)");
49 |
50 | b.Property("Simplified")
51 | .IsRequired()
52 | .HasMaxLength(64)
53 | .HasColumnType("varchar(64)");
54 |
55 | b.Property("Traditional")
56 | .IsRequired()
57 | .HasMaxLength(64)
58 | .HasColumnType("varchar(64)");
59 |
60 | b.Property("Types")
61 | .HasColumnType("int");
62 |
63 | b.HasKey("Unicode");
64 |
65 | b.ToTable("Chars");
66 | });
67 |
68 | modelBuilder.Entity("Chinese.Data.Data.NumericWord", b =>
69 | {
70 | b.Property("Id")
71 | .ValueGeneratedOnAdd()
72 | .HasColumnType("char(36)");
73 |
74 | b.Property("Simplified")
75 | .IsRequired()
76 | .HasMaxLength(64)
77 | .HasColumnType("varchar(64)");
78 |
79 | b.Property("SimplifiedPinyin")
80 | .IsRequired()
81 | .HasMaxLength(64)
82 | .HasColumnType("varchar(64)");
83 |
84 | b.Property("Traditional")
85 | .IsRequired()
86 | .HasMaxLength(64)
87 | .HasColumnType("varchar(64)");
88 |
89 | b.Property("TraditionalPinyin")
90 | .IsRequired()
91 | .HasMaxLength(64)
92 | .HasColumnType("varchar(64)");
93 |
94 | b.Property("Type")
95 | .HasColumnType("int");
96 |
97 | b.Property("Value")
98 | .HasColumnType("int");
99 |
100 | b.HasKey("Id");
101 |
102 | b.ToTable("Numerics");
103 | });
104 |
105 | modelBuilder.Entity("Chinese.Word", b =>
106 | {
107 | b.Property("Id")
108 | .ValueGeneratedOnAdd()
109 | .HasColumnType("char(36)");
110 |
111 | b.Property("HashCode")
112 | .HasColumnType("int");
113 |
114 | b.Property("Simplified")
115 | .IsRequired()
116 | .HasMaxLength(64)
117 | .HasColumnType("varchar(64)");
118 |
119 | b.Property("SimplifiedPinyin")
120 | .IsRequired()
121 | .HasMaxLength(64)
122 | .HasColumnType("varchar(64)");
123 |
124 | b.Property("Traditional")
125 | .IsRequired()
126 | .HasMaxLength(64)
127 | .HasColumnType("varchar(64)");
128 |
129 | b.Property("TraditionalPinyin")
130 | .IsRequired()
131 | .HasMaxLength(64)
132 | .HasColumnType("varchar(64)");
133 |
134 | b.Property("Type")
135 | .HasColumnType("int");
136 |
137 | b.HasKey("Id");
138 |
139 | b.ToTable("Words");
140 | });
141 | #pragma warning restore 612, 618
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230221032034_202302211120.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace DbCreator.MySql.Migrations;
6 |
7 | public partial class _202302211120 : Migration
8 | {
9 | protected override void Up(MigrationBuilder migrationBuilder)
10 | {
11 | migrationBuilder.AddColumn(
12 | name: "Simplified",
13 | table: "Chars",
14 | type: "varchar(64)",
15 | maxLength: 64,
16 | nullable: false,
17 | defaultValue: "")
18 | .Annotation("MySql:CharSet", "utf8mb4");
19 |
20 | migrationBuilder.AddColumn(
21 | name: "Traditional",
22 | table: "Chars",
23 | type: "varchar(64)",
24 | maxLength: 64,
25 | nullable: false,
26 | defaultValue: "")
27 | .Annotation("MySql:CharSet", "utf8mb4");
28 | }
29 |
30 | protected override void Down(MigrationBuilder migrationBuilder)
31 | {
32 | migrationBuilder.DropColumn(
33 | name: "Simplified",
34 | table: "Chars");
35 |
36 | migrationBuilder.DropColumn(
37 | name: "Traditional",
38 | table: "Chars");
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230227074215_202302271541.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | #nullable disable
10 |
11 | namespace DbCreator.MySql.Migrations;
12 |
13 | [DbContext(typeof(ChineseDbContext))]
14 | [Migration("20230227074215_202302271541")]
15 | partial class _202302271541
16 | {
17 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
18 | {
19 | #pragma warning disable 612, 618
20 | modelBuilder
21 | .HasAnnotation("ProductVersion", "6.0.11")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 |
24 | modelBuilder.Entity("Chinese.Data.Char", b =>
25 | {
26 | b.Property("Unicode")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int");
29 |
30 | b.Property("Character")
31 | .IsRequired()
32 | .HasColumnType("varchar(1)");
33 |
34 | b.Property("DefaultPinyin")
35 | .HasMaxLength(64)
36 | .HasColumnType("varchar(64)");
37 |
38 | b.Property("IsPolyphone")
39 | .HasColumnType("tinyint(1)");
40 |
41 | b.Property("Pinyins")
42 | .HasMaxLength(64)
43 | .HasColumnType("varchar(64)");
44 |
45 | b.Property("Sight")
46 | .HasColumnType("tinyint(1)");
47 |
48 | b.Property("Simplified")
49 | .HasMaxLength(64)
50 | .HasColumnType("varchar(64)");
51 |
52 | b.Property("Traditional")
53 | .HasMaxLength(64)
54 | .HasColumnType("varchar(64)");
55 |
56 | b.Property("Types")
57 | .HasColumnType("int");
58 |
59 | b.HasKey("Unicode");
60 |
61 | b.ToTable("Chars");
62 | });
63 |
64 | modelBuilder.Entity("Chinese.Data.Word", b =>
65 | {
66 | b.Property("Id")
67 | .ValueGeneratedOnAdd()
68 | .HasColumnType("char(36)");
69 |
70 | b.Property("HashCode")
71 | .HasColumnType("int");
72 |
73 | b.Property("Simplified")
74 | .HasMaxLength(64)
75 | .HasColumnType("varchar(64)");
76 |
77 | b.Property("SimplifiedPinyin")
78 | .HasMaxLength(64)
79 | .HasColumnType("varchar(64)");
80 |
81 | b.Property("Traditional")
82 | .HasMaxLength(64)
83 | .HasColumnType("varchar(64)");
84 |
85 | b.Property("TraditionalPinyin")
86 | .HasMaxLength(64)
87 | .HasColumnType("varchar(64)");
88 |
89 | b.Property("Type")
90 | .HasColumnType("int");
91 |
92 | b.HasKey("Id");
93 |
94 | b.ToTable("Words");
95 | });
96 | #pragma warning restore 612, 618
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/20230227074215_202302271541.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace DbCreator.MySql.Migrations;
6 |
7 | public partial class _202302271541 : Migration
8 | {
9 | protected override void Up(MigrationBuilder migrationBuilder)
10 | {
11 | migrationBuilder.DropTable(
12 | name: "Numerics");
13 |
14 | migrationBuilder.AlterColumn(
15 | name: "TraditionalPinyin",
16 | table: "Words",
17 | type: "varchar(64)",
18 | maxLength: 64,
19 | nullable: true,
20 | oldClrType: typeof(string),
21 | oldType: "varchar(64)",
22 | oldMaxLength: 64)
23 | .Annotation("MySql:CharSet", "utf8mb4")
24 | .OldAnnotation("MySql:CharSet", "utf8mb4");
25 |
26 | migrationBuilder.AlterColumn(
27 | name: "Traditional",
28 | table: "Words",
29 | type: "varchar(64)",
30 | maxLength: 64,
31 | nullable: true,
32 | oldClrType: typeof(string),
33 | oldType: "varchar(64)",
34 | oldMaxLength: 64)
35 | .Annotation("MySql:CharSet", "utf8mb4")
36 | .OldAnnotation("MySql:CharSet", "utf8mb4");
37 |
38 | migrationBuilder.AlterColumn(
39 | name: "SimplifiedPinyin",
40 | table: "Words",
41 | type: "varchar(64)",
42 | maxLength: 64,
43 | nullable: true,
44 | oldClrType: typeof(string),
45 | oldType: "varchar(64)",
46 | oldMaxLength: 64)
47 | .Annotation("MySql:CharSet", "utf8mb4")
48 | .OldAnnotation("MySql:CharSet", "utf8mb4");
49 |
50 | migrationBuilder.AlterColumn(
51 | name: "Simplified",
52 | table: "Words",
53 | type: "varchar(64)",
54 | maxLength: 64,
55 | nullable: true,
56 | oldClrType: typeof(string),
57 | oldType: "varchar(64)",
58 | oldMaxLength: 64)
59 | .Annotation("MySql:CharSet", "utf8mb4")
60 | .OldAnnotation("MySql:CharSet", "utf8mb4");
61 |
62 | migrationBuilder.AlterColumn(
63 | name: "Traditional",
64 | table: "Chars",
65 | type: "varchar(64)",
66 | maxLength: 64,
67 | nullable: true,
68 | oldClrType: typeof(string),
69 | oldType: "varchar(64)",
70 | oldMaxLength: 64)
71 | .Annotation("MySql:CharSet", "utf8mb4")
72 | .OldAnnotation("MySql:CharSet", "utf8mb4");
73 |
74 | migrationBuilder.AlterColumn(
75 | name: "Simplified",
76 | table: "Chars",
77 | type: "varchar(64)",
78 | maxLength: 64,
79 | nullable: true,
80 | oldClrType: typeof(string),
81 | oldType: "varchar(64)",
82 | oldMaxLength: 64)
83 | .Annotation("MySql:CharSet", "utf8mb4")
84 | .OldAnnotation("MySql:CharSet", "utf8mb4");
85 |
86 | migrationBuilder.AlterColumn(
87 | name: "Pinyins",
88 | table: "Chars",
89 | type: "varchar(64)",
90 | maxLength: 64,
91 | nullable: true,
92 | oldClrType: typeof(string),
93 | oldType: "varchar(64)",
94 | oldMaxLength: 64)
95 | .Annotation("MySql:CharSet", "utf8mb4")
96 | .OldAnnotation("MySql:CharSet", "utf8mb4");
97 |
98 | migrationBuilder.AlterColumn(
99 | name: "DefaultPinyin",
100 | table: "Chars",
101 | type: "varchar(64)",
102 | maxLength: 64,
103 | nullable: true,
104 | oldClrType: typeof(string),
105 | oldType: "varchar(64)",
106 | oldMaxLength: 64)
107 | .Annotation("MySql:CharSet", "utf8mb4")
108 | .OldAnnotation("MySql:CharSet", "utf8mb4");
109 | }
110 |
111 | protected override void Down(MigrationBuilder migrationBuilder)
112 | {
113 | migrationBuilder.UpdateData(
114 | table: "Words",
115 | keyColumn: "TraditionalPinyin",
116 | keyValue: null,
117 | column: "TraditionalPinyin",
118 | value: "");
119 |
120 | migrationBuilder.AlterColumn(
121 | name: "TraditionalPinyin",
122 | table: "Words",
123 | type: "varchar(64)",
124 | maxLength: 64,
125 | nullable: false,
126 | oldClrType: typeof(string),
127 | oldType: "varchar(64)",
128 | oldMaxLength: 64,
129 | oldNullable: true)
130 | .Annotation("MySql:CharSet", "utf8mb4")
131 | .OldAnnotation("MySql:CharSet", "utf8mb4");
132 |
133 | migrationBuilder.UpdateData(
134 | table: "Words",
135 | keyColumn: "Traditional",
136 | keyValue: null,
137 | column: "Traditional",
138 | value: "");
139 |
140 | migrationBuilder.AlterColumn(
141 | name: "Traditional",
142 | table: "Words",
143 | type: "varchar(64)",
144 | maxLength: 64,
145 | nullable: false,
146 | oldClrType: typeof(string),
147 | oldType: "varchar(64)",
148 | oldMaxLength: 64,
149 | oldNullable: true)
150 | .Annotation("MySql:CharSet", "utf8mb4")
151 | .OldAnnotation("MySql:CharSet", "utf8mb4");
152 |
153 | migrationBuilder.UpdateData(
154 | table: "Words",
155 | keyColumn: "SimplifiedPinyin",
156 | keyValue: null,
157 | column: "SimplifiedPinyin",
158 | value: "");
159 |
160 | migrationBuilder.AlterColumn(
161 | name: "SimplifiedPinyin",
162 | table: "Words",
163 | type: "varchar(64)",
164 | maxLength: 64,
165 | nullable: false,
166 | oldClrType: typeof(string),
167 | oldType: "varchar(64)",
168 | oldMaxLength: 64,
169 | oldNullable: true)
170 | .Annotation("MySql:CharSet", "utf8mb4")
171 | .OldAnnotation("MySql:CharSet", "utf8mb4");
172 |
173 | migrationBuilder.UpdateData(
174 | table: "Words",
175 | keyColumn: "Simplified",
176 | keyValue: null,
177 | column: "Simplified",
178 | value: "");
179 |
180 | migrationBuilder.AlterColumn(
181 | name: "Simplified",
182 | table: "Words",
183 | type: "varchar(64)",
184 | maxLength: 64,
185 | nullable: false,
186 | oldClrType: typeof(string),
187 | oldType: "varchar(64)",
188 | oldMaxLength: 64,
189 | oldNullable: true)
190 | .Annotation("MySql:CharSet", "utf8mb4")
191 | .OldAnnotation("MySql:CharSet", "utf8mb4");
192 |
193 | migrationBuilder.UpdateData(
194 | table: "Chars",
195 | keyColumn: "Traditional",
196 | keyValue: null,
197 | column: "Traditional",
198 | value: "");
199 |
200 | migrationBuilder.AlterColumn(
201 | name: "Traditional",
202 | table: "Chars",
203 | type: "varchar(64)",
204 | maxLength: 64,
205 | nullable: false,
206 | oldClrType: typeof(string),
207 | oldType: "varchar(64)",
208 | oldMaxLength: 64,
209 | oldNullable: true)
210 | .Annotation("MySql:CharSet", "utf8mb4")
211 | .OldAnnotation("MySql:CharSet", "utf8mb4");
212 |
213 | migrationBuilder.UpdateData(
214 | table: "Chars",
215 | keyColumn: "Simplified",
216 | keyValue: null,
217 | column: "Simplified",
218 | value: "");
219 |
220 | migrationBuilder.AlterColumn(
221 | name: "Simplified",
222 | table: "Chars",
223 | type: "varchar(64)",
224 | maxLength: 64,
225 | nullable: false,
226 | oldClrType: typeof(string),
227 | oldType: "varchar(64)",
228 | oldMaxLength: 64,
229 | oldNullable: true)
230 | .Annotation("MySql:CharSet", "utf8mb4")
231 | .OldAnnotation("MySql:CharSet", "utf8mb4");
232 |
233 | migrationBuilder.UpdateData(
234 | table: "Chars",
235 | keyColumn: "Pinyins",
236 | keyValue: null,
237 | column: "Pinyins",
238 | value: "");
239 |
240 | migrationBuilder.AlterColumn(
241 | name: "Pinyins",
242 | table: "Chars",
243 | type: "varchar(64)",
244 | maxLength: 64,
245 | nullable: false,
246 | oldClrType: typeof(string),
247 | oldType: "varchar(64)",
248 | oldMaxLength: 64,
249 | oldNullable: true)
250 | .Annotation("MySql:CharSet", "utf8mb4")
251 | .OldAnnotation("MySql:CharSet", "utf8mb4");
252 |
253 | migrationBuilder.UpdateData(
254 | table: "Chars",
255 | keyColumn: "DefaultPinyin",
256 | keyValue: null,
257 | column: "DefaultPinyin",
258 | value: "");
259 |
260 | migrationBuilder.AlterColumn(
261 | name: "DefaultPinyin",
262 | table: "Chars",
263 | type: "varchar(64)",
264 | maxLength: 64,
265 | nullable: false,
266 | oldClrType: typeof(string),
267 | oldType: "varchar(64)",
268 | oldMaxLength: 64,
269 | oldNullable: true)
270 | .Annotation("MySql:CharSet", "utf8mb4")
271 | .OldAnnotation("MySql:CharSet", "utf8mb4");
272 |
273 | migrationBuilder.CreateTable(
274 | name: "Numerics",
275 | columns: table => new
276 | {
277 | Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
278 | Simplified = table.Column(type: "varchar(64)", maxLength: 64, nullable: false)
279 | .Annotation("MySql:CharSet", "utf8mb4"),
280 | SimplifiedPinyin = table.Column(type: "varchar(64)", maxLength: 64, nullable: false)
281 | .Annotation("MySql:CharSet", "utf8mb4"),
282 | Traditional = table.Column(type: "varchar(64)", maxLength: 64, nullable: false)
283 | .Annotation("MySql:CharSet", "utf8mb4"),
284 | TraditionalPinyin = table.Column(type: "varchar(64)", maxLength: 64, nullable: false)
285 | .Annotation("MySql:CharSet", "utf8mb4"),
286 | Type = table.Column(type: "int", nullable: false),
287 | Value = table.Column(type: "int", nullable: false)
288 | },
289 | constraints: table =>
290 | {
291 | table.PrimaryKey("PK_Numerics", x => x.Id);
292 | })
293 | .Annotation("MySql:CharSet", "utf8mb4");
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/Tests/DbCreator.MySql/Migrations/ApplicationDbContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Chinese.Data;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
7 |
8 | #nullable disable
9 |
10 | namespace DbCreator.MySql.Migrations;
11 |
12 | [DbContext(typeof(ChineseDbContext))]
13 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot
14 | {
15 | protected override void BuildModel(ModelBuilder modelBuilder)
16 | {
17 | #pragma warning disable 612, 618
18 | modelBuilder
19 | .HasAnnotation("ProductVersion", "6.0.11")
20 | .HasAnnotation("Relational:MaxIdentifierLength", 64);
21 |
22 | modelBuilder.Entity("Chinese.Data.Char", b =>
23 | {
24 | b.Property("Unicode")
25 | .ValueGeneratedOnAdd()
26 | .HasColumnType("int");
27 |
28 | b.Property("Character")
29 | .IsRequired()
30 | .HasColumnType("varchar(1)");
31 |
32 | b.Property("DefaultPinyin")
33 | .HasMaxLength(64)
34 | .HasColumnType("varchar(64)");
35 |
36 | b.Property("IsPolyphone")
37 | .HasColumnType("tinyint(1)");
38 |
39 | b.Property("Pinyins")
40 | .HasMaxLength(64)
41 | .HasColumnType("varchar(64)");
42 |
43 | b.Property("Sight")
44 | .HasColumnType("tinyint(1)");
45 |
46 | b.Property("Simplified")
47 | .HasMaxLength(64)
48 | .HasColumnType("varchar(64)");
49 |
50 | b.Property("Traditional")
51 | .HasMaxLength(64)
52 | .HasColumnType("varchar(64)");
53 |
54 | b.Property("Types")
55 | .HasColumnType("int");
56 |
57 | b.HasKey("Unicode");
58 |
59 | b.ToTable("Chars");
60 | });
61 |
62 | modelBuilder.Entity("Chinese.Data.Word", b =>
63 | {
64 | b.Property("Id")
65 | .ValueGeneratedOnAdd()
66 | .HasColumnType("char(36)");
67 |
68 | b.Property("HashCode")
69 | .HasColumnType("int");
70 |
71 | b.Property("Simplified")
72 | .HasMaxLength(64)
73 | .HasColumnType("varchar(64)");
74 |
75 | b.Property