Skip to content

Commit

Permalink
Simplified command line, help, error file split
Browse files Browse the repository at this point in the history
Changed arguments to only require path.

Changed to output errors to SimpEn_Errors.txt instead of in the
translated file.

Removed second parameter.  Now always exports to SimpEn.csv in the
current working folder.
  • Loading branch information
NBKRedSpy committed Apr 1, 2023
1 parent ecb383f commit 15b64d7
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 56 deletions.
4 changes: 2 additions & 2 deletions CardSurvival-Localization/CardSurvival-Localization.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<RootNamespace>CardSurvival_Localization</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<FileVersion>1.2.0</FileVersion>
<AssemblyVersion>1.2.0</AssemblyVersion>
<FileVersion>2.0.0</FileVersion>
<AssemblyVersion>2.0.0</AssemblyVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
127 changes: 84 additions & 43 deletions CardSurvival-Localization/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,119 @@
using CsvHelper;
using CsvHelper.Configuration;


namespace CardSurvival_Localization
{
internal class Program
{
static void Main(string[] args)
static int Main(string[] args)
{

if (args.Length < 1)
try
{
if (ShowUsage(args))
{
return -2;
}

Console.Error.WriteLine("Must be at least 1 argument: SearchPath [OutputFile]");
return;
}
Utilities.ThrowIfNull(args[0]);
string sourceDirectory;

//---Extract info from .json files
string[] files = Directory.GetFiles(Path.GetDirectoryName(args[0])!, Path.GetFileName(args[0])!, SearchOption.AllDirectories);
if (!Directory.Exists(args[0]))
{
throw new ArgumentException($"Mod Directory does not exist: {args[0]}");
}

LocalizationKeyExtrator localizationKeyExtrator = new();

List<LocalizationInfo> localizationInfos = new();
Console.WriteLine("Processing...");

foreach (string file in files)
{
List<LocalizationInfo> result = localizationKeyExtrator.Extract(File.ReadAllText(file));
sourceDirectory = args[0];

result.ForEach(x => x.FileName = file);
localizationInfos.AddRange(result);
}
//---Extract info from .json files
string[] files = Directory.GetFiles(sourceDirectory, "*.json", SearchOption.AllDirectories);

LocalizationKeyExtrator localizationKeyExtrator = new();
List<LocalizationInfo> localizationInfos = new();

//---- Remove exact duplicates
foreach (string file in files)
{
List<LocalizationInfo> result = localizationKeyExtrator.Extract(File.ReadAllText(file));

//Remove exact key/text (case insensitive) duplicates.
//Group by items that have more than one text for the same key.
// Note - Keys are case insensitive. Currently CSTI-ModLoader is case sensitive.
List<IGrouping<string, LocalizationInfo>> groupedInfo = localizationInfos
.Distinct(new LocalizationGroupCompare())
.OrderBy(x => x.LocalizationKey)
.ThenBy(x => x.DefaultText)
.GroupBy(x => x.LocalizationKey)
.OrderBy(x => x.Key)
.ToList();
result.ForEach(x => x.FileName = file);
localizationInfos.AddRange(result);
}

bool isConsole = args.Length < 2;
//---- Remove exact duplicates

TextWriter outputWriter = isConsole ? Console.Out : new StreamWriter(args[1]);
using (outputWriter)
{
//Remove exact key/text (case insensitive) duplicates.
//Group by items that have more than one text for the same key.
// Note - Keys are case insensitive. Currently CSTI-ModLoader is case sensitive.
List<IGrouping<string, LocalizationInfo>> groupedInfo = localizationInfos
.Distinct(new LocalizationGroupCompare())
.OrderBy(x => x.LocalizationKey)
.ThenBy(x => x.DefaultText)
.GroupBy(x => x.LocalizationKey)
.OrderBy(x => x.Key)
.ToList();

//---Write Output Errors to file.

StringWriter sw = new StringWriter();
GetErrorText(sw, groupedInfo);

string errors = sw.ToString();

//---- Output warnings to stderr
WriteErrors(outputWriter, groupedInfo);
const string errorFileName = "SimpEn_Errors.txt";

//---- Write to output
using (CsvWriter csvWriter = new CsvWriter(outputWriter, CultureInfo.InvariantCulture))
if (errors.Length >0)
{
foreach (var item in groupedInfo.SelectMany(x => x.ToList()))
File.WriteAllText(errorFileName ,errors);
Console.WriteLine($"One or more translation errors occurred. See {errorFileName}");
}

const string localizationFilePath = "SimpEn.csv";

using (var outputWriter = new StreamWriter(localizationFilePath))
{
//---- Write to output
using (CsvWriter csvWriter = new CsvWriter(outputWriter, CultureInfo.InvariantCulture))
{
//The game's example SimpCn.csv shows new lines to be escaped.
string encodedText = item.DefaultText.Replace("\n", "\\n");
foreach (var item in groupedInfo.SelectMany(x => x.ToList()))
{
//The game's example SimpCn.csv shows new lines to be escaped.
string encodedText = item.DefaultText.Replace("\n", "\\n");

csvWriter.WriteField(item.LocalizationKey);
csvWriter.WriteField("");
csvWriter.WriteField(encodedText);
csvWriter.WriteField(item.LocalizationKey);
csvWriter.WriteField("");
csvWriter.WriteField(encodedText);

csvWriter.NextRecord();
csvWriter.NextRecord();
}
}
}

Console.WriteLine("Translation Completed.");

return 0;
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return -1;
}
}

private static void WriteErrors(TextWriter output, List<IGrouping<string, LocalizationInfo>> groupedInfo)
private static bool ShowUsage(string[] args)
{
if(args.Length != 1 || args[0].Trim() == "-h" || args[0].Trim() == "/?" || args[0].Trim() == "--help")
{
Console.WriteLine("Usage: CardSurvival-Localization <path to mod directory>");
Console.WriteLine();
return true;
}

return false;
}
private static void GetErrorText(TextWriter output, List<IGrouping<string, LocalizationInfo>> groupedInfo)
{
var multiDefinedInfo = groupedInfo.Where(x => x.Count() > 1);

Expand Down
2 changes: 1 addition & 1 deletion CardSurvival-Localization/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"CardSurvival-Localization": {
"commandName": "Project",
"commandLineArgs": "$(ProjectDir)TestData/Test.json"
"commandLineArgs": "$(ProjectDir)TestData/"
}
}
}
2 changes: 1 addition & 1 deletion CardSurvival-Localization/TestData/Test.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"Description": {
"DefaultText": "test",
"LocalizationKey": "test_key",
"LocalizationKey": "test_key1",
"ParentObjectID": "577682ed932c11ed892404ea56599bd2",
"subTest": {
"DefaultText": "some \"text\"",
Expand Down
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ This mod parses all the .json files and extracts the card translation key and re
To translate a mod based on CSTI-ModLoader to English, the process is as follows:

* Run the tool, pointing to the mod's folder.
* Example: `CardSurvival-Localization.exe "E:\Mods\Apocalypse-43-1-39-1679945367\*.json" ".\SimpEn.csv"`
* Example: `CardSurvival-Localization.exe "E:\Mods\Apocalypse-43-1-39-1679945367\`
* If there are errors, there will be a file named SimpEn_Errors.txt.
* Translate the SimpEnv.csv output file manually or with a translator such as translate.google.com or DeepL.com.
* Put the text translated from the third column into the second column.
* Fix any errors listed at the top of the output.
* Remove the error info at the top of the file.
* Copy the file into the Mod's Localization folder as SimpEn.csv.
* Fix any errors listed in the SimpEn_Errors.txt file.
* Copy the SimpEn.csv into the Mod's Localization folder.

## Example Output

### Output From Tool
SimpEn_Errors.txt
```
Error: Multiple keys exist with different text
Key: "Bp_ConservatoriesNc_CardDescription"
Expand All @@ -42,8 +43,10 @@ Key: "Bp_ConservatoriesNc_CardDescription"
Text: 保护植物并加速生长
File: .\example.json
JSON Path: CardDescription2
```

-----
SimpEn.csv
```
Bp_ConservatoriesNc_CardDescription,,为植物生长提供一个温馨的家园。
Bp_ConservatoriesNc_CardDescription,,保护植物并加速生长
Bp_ConservatoriesNc_Two_CardName,,二号温室
Expand All @@ -59,12 +62,12 @@ Bp_ConservatoriesNc_Two_CardName,Greenhouse No. 2,二号温室
# Spreadsheet Recommended Workflow
My recommendation would be to do as follows:
* Run the tool to create the SimpEn.csv output.
* Import the CSV part of the document into Excel or Google Sheets, excluding any errors at the top of the output.
* Import the CSV part of the document into Excel or Google Sheets.
* Copy the entirety of the third column (which will be in Chinese) and run it through a translator like translate.google.com or deepl.com.
* Alternatively, Google Sheets has a function called GoogleTranslate that can translate text in the spreadsheet. For example Chinese to English is `=GOOGLETRANSLATE(C1,"zh","en")`.
* Paste those results into the spreadsheet's second column.
* Save the spreadsheet as SimpEn.csv.
* With the newly created SimpEn.csv file, fix any errors that were listed at the top of the original output.
* With the newly created SimpEn.csv file, if there is an SimpEn_Error.txt file, fix any errors indicated in that file.
* Copy the SimpEn.csv file to the Mod's Localization directory.

When starting the game, the Mod's text should now reflect the translated text.
Expand All @@ -80,8 +83,7 @@ A couple of things I've noticed in the current mods.
# Command Line Parameters
|Arguments|Description|
|--|--|
|File Pattern|The full path to the mod with *.json at the end. For example: "SomeModLoaderMod\\\*.json"|
|Output File|If not provided, will output to the console. Otherwise, it will write to the path specified. It is recommended to use this argument since the console can corrupt Chinese characters.|
|File Pattern|The full path to the mod|

## Source and Releases for this Utility
https://github.com/NBKRedSpy/CardSurvival-Localization
Expand All @@ -95,6 +97,15 @@ https://github.com/dop-lm/CSTI-ModLoader (Currently the NoReflection branch has

# Version

## 2.0.0

### Upgrade Notes
For users that have used a previous version of the app, the arguments have changed. The application now only requires the path to the target mod and will automatically create a SimpEx.csv and SimpEx_Errors.txt in the current working directory.
### Changes
* Changed arguments to only require path.
* Changed to output errors to SimpEn_Errors.txt instead of in the translated file.
* Removed second parameter. Now always exports to SimpEn.csv in the current working folder.

## 1.2.0
* Moved errors to output instead of stderr.
* Added File Name and JSON path to errors.
Expand Down

0 comments on commit 15b64d7

Please sign in to comment.