Skip to content

Commit 2d690ec

Browse files
committed
Update
- Added wan24-I8NKws JSON format support to the i8n API
1 parent d7867a5 commit 2d690ec

File tree

4 files changed

+198
-18
lines changed

4 files changed

+198
-18
lines changed

src/wan24-I8NTool CLI/I8NApi.Build.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ public sealed partial class I8NApi
1717
/// Build an internationalization file from multiple input sources
1818
/// </summary>
1919
/// <param name="jsonInput">JSON (UTF-8) input filenames</param>
20+
/// <param name="kwsInput">wan24-I8NKws JSON (UTF-8) input filenames</param>
2021
/// <param name="poInput">PO (gettext) input filenames</param>
2122
/// <param name="moInput">MO (gettext) input filenames</param>
2223
/// <param name="output">Internationalization output filename (if not given, STDOUT will be used; existing file will be overwritten)</param>
2324
/// <param name="compress">To compress the internationalization file</param>
2425
/// <param name="json">To read JSON (UTF-8) from STDIN</param>
26+
/// <param name="kws">To read wan24-I8NKws JSON (UTF-8) from STDIN</param>
2527
/// <param name="po">To read PO (gettext) from STDIN</param>
2628
/// <param name="mo">To read MO (gettext) from STDIN</param>
2729
/// <param name="noHeader">To skip writing a header with the version number and the compression flag</param>
@@ -40,6 +42,11 @@ public static async Task BuildAsync(
4042
[Description("JSON (UTF-8) input filenames")]
4143
string[]? jsonInput = null,
4244

45+
[CliApi(Example = "/path/to/input.kws")]
46+
[DisplayText("wan24-I8NKws JSON input")]
47+
[Description("wan24-I8NKws JSON (UTF-8) input filenames")]
48+
string[]? kwsInput = null,
49+
4350
[CliApi(Example = "/path/to/input.po")]
4451
[DisplayText("PO input")]
4552
[Description("PO (gettext) input filenames")]
@@ -65,6 +72,11 @@ public static async Task BuildAsync(
6572
[Description("To read JSON (UTF-8) from STDIN")]
6673
bool json = false,
6774

75+
[CliApi]
76+
[DisplayText("wan24-I8NKws JSON")]
77+
[Description("To read wan24-I8NKws JSON (UTF-8) from STDIN")]
78+
bool kws = false,
79+
6880
[CliApi]
6981
[DisplayText("PO")]
7082
[Description("To read PO (gettext) from STDIN")]
@@ -91,13 +103,13 @@ public static async Task BuildAsync(
91103
bool failOnExistingKey = false,
92104

93105
CancellationToken cancellationToken = default
94-
95106
)
96107
{
97108
verbose |= Trace;
98109
if (Trace) WriteTrace($"Creating internationalization to {(output is null ? "STDOUT" : $"output file \"{output}\"")}");
99110
int stdInCnt = 0;
100111
if (json) stdInCnt++;
112+
if (kws) stdInCnt++;
101113
if (po) stdInCnt++;
102114
if (mo) stdInCnt++;
103115
if (stdInCnt > 1)
@@ -117,6 +129,20 @@ await ReadJsonSourceAsync(
117129
cancellationToken
118130
).DynamicContext();
119131
}
132+
// Read KWS source files
133+
if (kwsInput is not null && kwsInput.Length > 0)
134+
foreach (string fn in kwsInput)
135+
{
136+
if (verbose) WriteInfo($"Processing wan24-I8NKws JSON source file \"{fn}\" for {(output is null ? "STDOUT" : $"output file \"{output}\"")}");
137+
await ReadJsonSourceAsync(//TODO
138+
FsHelper.CreateFileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read),
139+
fn,
140+
terms,
141+
failOnExistingKey,
142+
verbose,
143+
cancellationToken
144+
).DynamicContext();
145+
}
120146
// Read MO source files
121147
MoFileParser? moParser = null;
122148
if (moInput is not null && moInput.Length > 0)
@@ -165,6 +191,12 @@ await ReadPoSourceAsync(
165191
if (verbose) WriteInfo($"Processing JSON from STDIN for {(output is null ? "STDOUT" : $"output file \"{output}\"")}");
166192
await ReadJsonSourceAsync(Console.OpenStandardInput(), fn: null, terms, failOnExistingKey, verbose, cancellationToken).DynamicContext();
167193
}
194+
// Read JSON from STDIN
195+
if (kws)
196+
{
197+
if (verbose) WriteInfo($"Processing wan24-I8NKws JSON from STDIN for {(output is null ? "STDOUT" : $"output file \"{output}\"")}");
198+
await ReadJsonSourceAsync(Console.OpenStandardInput(), fn: null, terms, failOnExistingKey, verbose, cancellationToken).DynamicContext();//TODO
199+
}
168200
// Read MO from STDIN
169201
if (mo)
170202
{

src/wan24-I8NTool CLI/I8NApi.BuildMany.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public sealed partial class I8NApi
1515
/// </summary>
1616
/// <param name="jsonInput">JSON input file (UTF-8) folder (no recursion)</param>
1717
/// <param name="jsonInputPattern">JSON input pattern</param>
18+
/// <param name="kwsInput">wan24-I8NKws JSON input file (UTF-8) folder (no recursion)</param>
19+
/// <param name="kwsInputPattern">wan24-I8NKws JSON input pattern</param>
1820
/// <param name="poInput">PO (gettext) input file folder (no recursion)</param>
1921
/// <param name="poInputPattern">PO input pattern</param>
2022
/// <param name="moInput">MO (gettext) input file folder (no recursion)</param>
@@ -27,7 +29,7 @@ public sealed partial class I8NApi
2729
/// <returns>Exit code</returns>
2830
[CliApi("buildmany", IsDefault = true)]
2931
[DisplayText("Build i8n files")]
30-
[Description("Build many internationalization (i8n) files from JSON (UTF-8) or PO/MO (gettext) source files (output filename is the input filename with the \".i8n\" extension instead - existing files will be overwritten; default is to convert all *.json/po/mo files in the working folder)")]
32+
[Description("Build many internationalization (i8n) files from (wan24-I8N) JSON (UTF-8) or PO/MO (gettext) source files (output filename is the input filename with the \".i8n\" extension instead - existing files will be overwritten; default is to convert all *.json/kws/po/mo files in the working folder)")]
3133
[ExitCode(0, "Ok")]
3234
[ExitCode(1, "Had errors")]
3335
public static async Task<int> BuildManyAsync(
@@ -42,6 +44,16 @@ public static async Task<int> BuildManyAsync(
4244
[Description("JSON input pattern (default is \"*.json\")")]
4345
string jsonInputPattern = "*.json",
4446

47+
[CliApi(Example = "/path/to/sources")]
48+
[DisplayText("wan24-I8NKws JSON input")]
49+
[Description("wan24-I8NKws JSON input file (UTF-8) folder (no recursion; default is the working folder)")]
50+
string kwsInput = "./",
51+
52+
[CliApi(Example = "*.kws")]
53+
[DisplayText("wan24-I8NKws JSON input pattern")]
54+
[Description("wan24-I8NKws JSON input pattern (default is \"*.kws\")")]
55+
string kwsInputPattern = "*.kws",
56+
4557
[CliApi(Example = "/path/to/sources")]
4658
[DisplayText("PO input")]
4759
[Description("PO (gettext) input file folder (no recursion; default is the working folder)")]
@@ -102,6 +114,7 @@ public static async Task<int> BuildManyAsync(
102114
{
103115
// Output the used final settings
104116
WriteInfo($"JSON files: {Path.GetFullPath(jsonInput)}{(ENV.IsWindows ? '\\' : '/')}{jsonInputPattern}");
117+
WriteInfo($"wan24-I8NKws JSON files: {Path.GetFullPath(kwsInput)}{(ENV.IsWindows ? '\\' : '/')}{kwsInputPattern}");
105118
WriteInfo($"PO files: {Path.GetFullPath(poInput)}{(ENV.IsWindows ? '\\' : '/')}{poInputPattern}");
106119
WriteInfo($"MO files: {Path.GetFullPath(moInput)}{(ENV.IsWindows ? '\\' : '/')}{moInputPattern}");
107120
WriteInfo($"Header: {!noHeader}");
@@ -174,6 +187,52 @@ await BuildAsync(
174187
WriteInfo($"No JSON files found for \"{Path.GetFullPath(jsonInput)}{(ENV.IsWindows ? '\\' : '/')}{jsonInputPattern}\"");
175188
}
176189
}
190+
// KWS files
191+
if (Directory.Exists(kwsInput))
192+
{
193+
IEnumerable<string> files = FsHelper.FindFiles(kwsInput, searchPattern: kwsInputPattern, recursive: false);
194+
if (files.Any())
195+
{
196+
foreach (string fn in files)
197+
{
198+
if (excluding.IsMatch(fn))
199+
{
200+
if (verbose) WriteInfo($"File \"{fn}\" was excluded");
201+
continue;
202+
}
203+
if (Trace) WriteTrace($"Waiting for a thread for processing \"{fn}\"");
204+
await sync.WaitAsync(cts.Token).DynamicContext();
205+
_ = ((Func<Task>)(async () =>
206+
{
207+
try
208+
{
209+
if (Trace) WriteTrace($"Thread processing \"{fn}\"");
210+
await BuildAsync(
211+
kwsInput: [fn],
212+
output: Path.Combine(kwsInput, $"{Path.GetFileNameWithoutExtension(fn)}.i8n"),
213+
compress: compress,
214+
noHeader: noHeader,
215+
verbose: verbose,
216+
cancellationToken: cts.Token
217+
).DynamicContext();
218+
}
219+
catch (Exception ex)
220+
{
221+
HandleError(fn, ex);
222+
}
223+
finally
224+
{
225+
if (Trace) WriteTrace($"Processing \"{fn}\" done - releasing thread");
226+
sync.Release();
227+
}
228+
})).StartFairTask();
229+
}
230+
}
231+
else if (verbose)
232+
{
233+
WriteInfo($"No wan24-I8NKws JSON files found for \"{Path.GetFullPath(kwsInput)}{(ENV.IsWindows ? '\\' : '/')}{kwsInputPattern}\"");
234+
}
235+
}
177236
// PO files
178237
if (Directory.Exists(poInput))
179238
{

src/wan24-I8NTool CLI/I8NApi.Extract.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Reflection;
44
using wan24.CLI;
55
using wan24.Core;
6+
using wan24.I8NKws;
67
using static wan24.Core.Logger;
78
using static wan24.Core.Logging;
89

@@ -17,8 +18,10 @@ public sealed partial class I8NApi
1718
/// <param name="input">Internationalization input filename (if not given, STDIN will be used)</param>
1819
/// <param name="uncompress">To uncompress the internationalization file (not required to use, if a header will be red)</param>
1920
/// <param name="jsonOutput">JSON (UTF-8) output filename</param>
21+
/// <param name="kwsOutput">wan24-I8NKws JSON (UTF-8) output filename</param>
2022
/// <param name="poOutput">PO (gettext) output filename</param>
2123
/// <param name="json">To write JSON (UTF-8) to STDOUT</param>
24+
/// <param name="kws">To write wan24-I8NKws JSON (UTF-8) to STDOUT</param>
2225
/// <param name="po">To write PO (gettext) (UTF-8) to STDOUT</param>
2326
/// <param name="noHeader">To skip reading a header with the version number and the compression flag</param>
2427
/// <param name="verbose">Write verbose informations to STDERR</param>
@@ -44,6 +47,11 @@ public static async Task ExtractAsync(
4447
[Description("JSON (UTF-8) output filename")]
4548
string? jsonOutput = null,
4649

50+
[CliApi(Example = "/path/to/output.kws")]
51+
[DisplayText("wan24-I8NKws JSON output")]
52+
[Description("wan24-I8NKws JSON (UTF-8) output filename")]
53+
string? kwsOutput = null,
54+
4755
[CliApi(Example = "/path/to/output.po")]
4856
[DisplayText("PO output")]
4957
[Description("PO (gettext) (UTF-8) output filename")]
@@ -54,6 +62,11 @@ public static async Task ExtractAsync(
5462
[Description("To write JSON (UTF-8) to STDOUT")]
5563
bool json = false,
5664

65+
[CliApi]
66+
[DisplayText("KWS")]
67+
[Description("To write wan24-I8NKws JSON (UTF-8) to STDOUT")]
68+
bool kws = false,
69+
5770
[CliApi]
5871
[DisplayText("PO")]
5972
[Description("To write PO (gettext) (UTF-8) to STDOUT")]
@@ -74,7 +87,7 @@ public static async Task ExtractAsync(
7487
verbose |= Trace;
7588
if (Trace) WriteTrace("Extracting internationalization file");
7689
if (json && po) throw new ArgumentException("Can't write JSON AND PO to STDOUT", nameof(po));
77-
if (!json && !po && jsonOutput is null && poOutput is null) json = true;
90+
if (!json && !kws && !po && jsonOutput is null && kwsOutput is null && poOutput is null) json = true;
7891
// Read internationalization input
7992
Stream inputStream = input is null
8093
? Console.OpenStandardInput()
@@ -88,6 +101,22 @@ public static async Task ExtractAsync(
88101
await using (fs.DynamicContext())
89102
await JsonHelper.EncodeAsync(terms, fs, prettify: true).DynamicContext();
90103
}
104+
// Write KWS output file
105+
KwsCatalog? kwsCatalog = null;
106+
if(kwsOutput is not null)
107+
{
108+
if (verbose) WriteInfo($"Writing wan24-I8NKws JSON to ouput file \"{kwsOutput}\"");
109+
kwsCatalog = new KwsCatalog()
110+
{
111+
Keywords = new(terms.Select(kvp => new KwsKeyword(kvp.Key)
112+
{
113+
Translations = [.. kvp.Value]
114+
}))
115+
};
116+
FileStream fs = FsHelper.CreateFileStream(kwsOutput, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, overwrite: true);
117+
await using (fs.DynamicContext())
118+
await JsonHelper.EncodeAsync(kwsCatalog, fs, prettify: true).DynamicContext();
119+
}
91120
// Write JSON to STDOUT
92121
if (json)
93122
{
@@ -96,6 +125,21 @@ public static async Task ExtractAsync(
96125
await using (stdout.DynamicContext())
97126
await JsonHelper.EncodeAsync(terms, stdout, prettify: true).DynamicContext();
98127
}
128+
// Write KWS to STDOUT
129+
if (kws)
130+
{
131+
if (verbose) WriteInfo($"Writing wan24-I8NKws JSON to STDOUT");
132+
kwsCatalog ??= new KwsCatalog()
133+
{
134+
Keywords = new(terms.Select(kvp => new KwsKeyword(kvp.Key)
135+
{
136+
Translations = [.. kvp.Value]
137+
}))
138+
};
139+
Stream stdout = Console.OpenStandardOutput();
140+
await using (stdout.DynamicContext())
141+
await JsonHelper.EncodeAsync(kwsCatalog, stdout, prettify: true).DynamicContext();
142+
}
99143
// Generate PO in memory
100144
if (poOutput is null && !po)
101145
{

0 commit comments

Comments
 (0)