139 lines
5.9 KiB
C#
139 lines
5.9 KiB
C#
using System.Text;
|
|
|
|
namespace Processor.Generators;
|
|
|
|
public class GodotCSV : IGenerator
|
|
{
|
|
private static readonly List<string> CULTURE_CODES = new();
|
|
|
|
#region Implementation of IGenerator
|
|
|
|
/// <inheritdoc />
|
|
public async Task<ProcessorResult<long>> GenerateAsync()
|
|
{
|
|
const string filename = "I18N.csv";
|
|
const char delimiter = ',';
|
|
|
|
var destPath = await AppSettings.GetGeneratorGodotDestinationPath();
|
|
destPath = Environment.ExpandEnvironmentVariables(destPath);
|
|
long destBytesWritten = 0;
|
|
|
|
var pathFinal = Path.Join(destPath, filename);
|
|
var pathTemp = Path.Join(destPath, filename + ".gen");
|
|
var issueFinal = string.Empty;
|
|
|
|
try
|
|
{
|
|
if(File.Exists(pathTemp))
|
|
File.Delete(pathTemp);
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
return new ProcessorResult<long>(0, false, $"Cannot delete the temporary file: '{e.Message}'. Hint: Is the ransomware protection enabled in your Windows system? If so, please make sure that the I18N Commander has write permission.");
|
|
}
|
|
|
|
CULTURE_CODES.Clear();
|
|
var cultures = await AppSettings.GetCultureInfos();
|
|
foreach (var (code, _) in cultures.OrderBy(n => n.Code))
|
|
CULTURE_CODES.Add(code);
|
|
|
|
if (CULTURE_CODES.Count == 0)
|
|
return new ProcessorResult<long>(0, true, string.Empty);
|
|
|
|
try
|
|
{
|
|
await using var fileStream = new FileStream(pathTemp, FileMode.CreateNew, FileAccess.Write, FileShare.None);
|
|
await using var writer = new StreamWriter(fileStream, Encoding.UTF8);
|
|
|
|
// Write the header:
|
|
await writer.WriteLineAsync($"keys{delimiter}{string.Join(delimiter, CULTURE_CODES)}");
|
|
|
|
//
|
|
// Iterate through all sections and text elements:
|
|
//
|
|
var sectionDepth = await SectionProcessor.GetDepth();
|
|
foreach (var sectionLayer in Enumerable.Range(0, sectionDepth + 1))
|
|
{
|
|
var sections = await SectionProcessor.LoadLayer(sectionLayer);
|
|
foreach (var section in sections.OrderBy(n => n.DataKey))
|
|
foreach (var textElement in section.TextElements.OrderBy(n => n.Code))
|
|
{
|
|
// Get the key for this text element:
|
|
var key = await TextElementProcessor.GetKey(textElement.Id);
|
|
|
|
// Write the path to the text element as key:
|
|
await writer.WriteAsync($"{key}{delimiter}");
|
|
|
|
// Load all translations:
|
|
var translations = textElement.Translations.DistinctBy(n => n.Culture).ToDictionary(translation => translation.Culture, translation => translation.Text);
|
|
|
|
// Iterate through all text elements and write the translations out:
|
|
for (var cultureIndex = 0; cultureIndex < CULTURE_CODES.Count; cultureIndex++)
|
|
{
|
|
var cultureCode = CULTURE_CODES[cultureIndex];
|
|
var cultureText = translations.TryGetValue(cultureCode, out var text) ? text : string.Empty;
|
|
|
|
// Write the text with delimiter or only the text in case of the last column:
|
|
if (cultureIndex < CULTURE_CODES.Count - 1)
|
|
await writer.WriteAsync($@"""{Escape4CSV(cultureText)}""{delimiter}");
|
|
else
|
|
await writer.WriteLineAsync($@"""{Escape4CSV(cultureText)}""");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(IOException e)
|
|
{
|
|
// Happens, e.g. when the ransomware protection on Windows is active and
|
|
// the I18N commander is not on the exclusion list.
|
|
return new ProcessorResult<long>(0, false, $"Cannot write the generator's result file: '{e.Message}'. Hint: Is the ransomware protection enabled in your Windows system? If so, please make sure that the I18N Commander has write permission.");
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(pathTemp))
|
|
{
|
|
destBytesWritten = new FileInfo(pathTemp).Length;
|
|
if (destBytesWritten > 0)
|
|
{
|
|
try
|
|
{
|
|
if (File.Exists(pathFinal))
|
|
File.Delete(pathFinal);
|
|
|
|
File.Move(pathTemp, pathFinal);
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
// Happens when the file is still in use by the compiler, the IDE, etc.
|
|
// Depends on the timing, this happens sometimes. We ignore it, though.
|
|
issueFinal = e.Message;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(string.IsNullOrWhiteSpace(issueFinal))
|
|
return new ProcessorResult<long>(destBytesWritten, true, string.Empty);
|
|
else
|
|
return new ProcessorResult<long>(0, false, $"Cannot move the generator's result file to the destination: '{issueFinal}'. Hint: Is the ransomware protection enabled in your Windows system? If so, please make sure that the I18N Commander has write permission.");
|
|
}
|
|
|
|
private static string Escape4CSV(string text)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
return string.Empty;
|
|
|
|
var sb = new StringBuilder(text.Length);
|
|
foreach (var c in text)
|
|
{
|
|
if (c == '"')
|
|
sb.Append(@""""""); // quoted double quote, i.e. prints ""
|
|
else
|
|
sb.Append(c);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
#endregion
|
|
} |