Skip to content

Commit

Permalink
De-dupe and CSV Encoding��* Added CSV encoding
Browse files Browse the repository at this point in the history
* Remove duplicates based on key/text
* Warns if a key has multiple entries with different versions.
  • Loading branch information
NBKRedSpy committed Mar 29, 2023
1 parent 0b5bc24 commit 2fde5b5
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,5 @@ MigrationBackup/
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
/CardSurvival-Localization.zip
3 changes: 3 additions & 0 deletions CardSurvival-Localization/CardSurvival-Localization.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
<RootNamespace>CardSurvival_Localization</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<FileVersion>1.1.0</FileVersion>
<AssemblyVersion>1.1.0</AssemblyVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup>
Expand Down
23 changes: 23 additions & 0 deletions CardSurvival-Localization/LocalizationInfo.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

Expand All @@ -13,4 +16,24 @@ public class LocalizationInfo
public string DefaultText { get; set; } = "";
public string LocalizationKey { get; set; } = "";
}

public class LocalizationGroupCompare : IEqualityComparer<LocalizationInfo>
{
public bool Equals(LocalizationInfo? x, LocalizationInfo? y)
{
StringComparer comparer = StringComparer.OrdinalIgnoreCase;

return String.Equals(x?.LocalizationKey, y?.LocalizationKey)
&& String.Equals(x?.DefaultText, y?.DefaultText, StringComparison.OrdinalIgnoreCase);
}

public int GetHashCode([DisallowNull] LocalizationInfo obj)
{

return (
obj.LocalizationKey.GetHashCode(),
obj.DefaultText.GetHashCode(StringComparison.OrdinalIgnoreCase))
.GetHashCode();
}
}
}
74 changes: 54 additions & 20 deletions CardSurvival-Localization/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Net;
using System.Runtime.CompilerServices;
using CsvHelper;
using CsvHelper.Configuration;

namespace CardSurvival_Localization
{
Expand All @@ -7,18 +11,17 @@ internal class Program
static void Main(string[] args)
{

if(args.Length < 1)
if (args.Length < 1)
{

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

//---Extract info from .json files
string[] files = Directory.GetFiles(Path.GetDirectoryName(args[0])!, Path.GetFileName(args[0])!, SearchOption.AllDirectories);

//const string FilePath = @"C:\src\CardSurvival\CardSurvival-Localization\CardSurvival-Localization\TestData\Test.json";

LocalizationKeyExtrator localizationKeyExtrator = new();

List<LocalizationInfo> localizationInfos = new();
Expand All @@ -27,35 +30,66 @@ static void Main(string[] args)
{
List<LocalizationInfo> result = localizationKeyExtrator.Extract(File.ReadAllText(file));

localizationInfos.ForEach(x=> x.FileName = file);
localizationInfos.ForEach(x => x.FileName = file);
localizationInfos.AddRange(result);
}

bool isConsole = args.Length < 2;

StreamWriter outputStream = null;

if (isConsole == false)
//---- Remove exact duplicates

//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();

//---- Output warnings to stderr
var multiDefinedInfo = groupedInfo.Where(x => x.Count() > 1);

if(multiDefinedInfo.Count() > 0)
{
outputStream = File.CreateText(args[1]);
Console.Error.WriteLine("Error: Multiple keys exist with different text");

foreach (var multiGroup in multiDefinedInfo)
{
Console.Error.WriteLine($"Key: \"{multiGroup.Key}\"");

foreach (var info in multiGroup)
{
Console.Error.WriteLine($"\t{info.DefaultText}");
}
}

Console.Error.WriteLine("-----");
Console.Error.WriteLine();
}

using (outputStream)
//---- Write to output
bool isConsole = args.Length < 2;

TextWriter outputWriter = isConsole ? Console.Out : new StreamWriter(args[1]);

using (outputWriter)
using (CsvWriter csvWriter = new CsvWriter(outputWriter, CultureInfo.InvariantCulture))
{
foreach (var item in localizationInfos)
foreach (var item in groupedInfo.SelectMany(x=> x.ToList()))
{
//CsvHelper.CsvWriter csvWriter = new CsvWriter()
string result = string.Join(',', item.LocalizationKey, "", item.DefaultText);

if (isConsole)
{
Console.WriteLine(result);
}
else
{
outputStream!.WriteLine(result);
}
csvWriter.WriteField(item.LocalizationKey);
csvWriter.WriteField("");
csvWriter.WriteField(item.DefaultText);

csvWriter.NextRecord();
}
}
}

}
}
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": "\"E:\\Downloads\\Games\\Card Survival\\Apocalypse-43-1-39-1679945367\\*.json\" \"c:\\work\\out.txt\""
"commandLineArgs": "$(ProjectDir)TestData/Test.json"
}
}
}
18 changes: 14 additions & 4 deletions CardSurvival-Localization/TestData/Test.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
"LocalizationKey": "Gs_Hail_IceCool_Descriptions"
},
"Description": {
"DefaultText": "\u51b0\u723d\u7684\u611f\u89c9",
"LocalizationKey": "Gs_Hail_IceCool_Descriptions",
"DefaultText": "test",
"LocalizationKey": "test_key",
"ParentObjectID": "577682ed932c11ed892404ea56599bd2",
"subTest": {
"DefaultText": "\u51b0\u723d\u7684\u611f\u89c9",
"LocalizationKey": "Gs_Hail_IceCool_Descriptions"
"DefaultText": " \"quoted test\"",
"LocalizationKey": "test_key"
},
"subTest1": {
"DefaultText": "duplicate test",
"LocalizationKey": "dupe_test"
},
"subTest3": {
"DefaultText": "duplicate test",
"LocalizationKey": "dupe_test2"
}


}
}
}
5 changes: 5 additions & 0 deletions Package.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dotnet publish
# Get the file name from the C# project name
$ProjectName = "CardSurvival-Localization"

Compress-Archive -Path "C:\src\CardSurvival\CardSurvival-Localization\CardSurvival-Localization\bin\Debug\net6.0\publish\*" -Force -DestinationPath ./$ProjectName.zip
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The utility goes through every .json file in a ModLoader based mod's folder and
The output is a CSV in the same format as SimpCn.csv
The result can be exported to the console or a file.

If there are any errors or warnings, they would be outputted to stderr. For example, multiple entries of the same key with different text.

# Usage:
Run the exe, passing in the folder with *.json at the end.

Expand Down Expand Up @@ -44,8 +46,12 @@ Bp_Hail_IceCoolBall.LogText,,冰晶球完成了
An easy way to translate is using Google Sheets with the translate function.
For example, translating Chinese to English: `=GOOGLETRANSLATE(C1,"zh","en")`

# Todo:
* Maybe use tabs instead of commas since the text can have commas. Maybe have option between CSV and TSV since tabs are easier import and manipulate.
* It needs to remove duplicates, or at least warn about them. There are mods which have the same key multiple times. Usually it has the same text. Maybe it is duped because object references are duped?
* Should remove the *.json glob. They will always be .json and just needs a root directory specified.
* CSV output should support wrapping the columns in quotes and quotation escaping.
# Version

## 1.1.0
* Added CSV encoding
* Remove duplicates based on key/text
* Warns if a key has multiple entries with different versions.

## 1.0.0
* Release

0 comments on commit 2fde5b5

Please sign in to comment.