Skip to content

Commit

Permalink
feat: add new IFormatBuilderOptions and FormatWriteOptions, add PoBui…
Browse files Browse the repository at this point in the history
…lderOptions to configure pipe splitting behaviour (#90)

* feat: add new IFormatBuilderOptions and FormatWriteOptions, add PoBuilderOptions to configure pipe splitting behaviour

* tests(po): add new test case to test po files that dont have a msgctxt

* cleanup

---------

Co-authored-by: Tjorven Kämpfer <[email protected]>
  • Loading branch information
RealLHI and tjorvenK authored Sep 18, 2024
1 parent 64046d8 commit ed57f62
Show file tree
Hide file tree
Showing 19 changed files with 120 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Ashampoo.Translation.Systems.Formats.Abstractions;
/// <summary>
/// This class is used to provide options for reading a <see cref="IFormat"/> from a file.
/// </summary>
public class FormatReadOptions
public record FormatReadOptions
{
/// <summary>
/// The target language of the format.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface IFormatBuilder<out T> where T : class, IFormat
/// <returns>
/// The instance of <see cref="IFormat"/>.
/// </returns>
T Build();
T Build(IFormatBuilderOptions? options = null);

/// <summary>
/// Set the header information. All information will be added to the header and will overwrite
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Ashampoo.Translation.Systems.Formats.Abstractions;

/// <summary>
/// An interface to add optional options to a format builder to manipulate its behaviour.
/// </summary>
public interface IFormatBuilderOptions;
67 changes: 65 additions & 2 deletions src/Ashampoo.Translation.Systems.Formats.PO/tests/FormatTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,69 @@ public void ReadFromFile()
.Be("Vielen Dank, dass Sie die Umfrage abgeschlossen haben!");
}

[Fact]
public void CreateBuilderWithDisabledPipeSplittingTest()
{
var format = CreateAndReadFromFile("translation_de.po",
new FormatReadOptions { SourceLanguage = new Language("en-US") });


var poHeader = format.Header as POHeader;
poHeader.Should().NotBeNull();

var poBuilder = new POFormatBuilder();
foreach (var unit in format.TranslationUnits)
{
foreach (var translation in unit.Translations)
{
poBuilder.Add(unit.Id, translation.Value);
}
}
poBuilder.SetTargetLanguage(format.Header.TargetLanguage);
var newFormat = poBuilder.Build(new PoBuilderOptions { SplitContextAndId = false });
var memoryStream = new MemoryStream();
newFormat.Write(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream);
var result = streamReader.ReadToEnd();
result.Should().NotContain("msgctxt ");
}

[Fact]
public void ReadWithoutMsgCtxtText()
{
var format = CreateAndReadFromFile("test.po",
new FormatReadOptions { SourceLanguage = new Language("en-US") });

var poHeader = format.Header as POHeader;
poHeader.Should().NotBeNull();

format.TranslationUnits.Count.Should().Be(2);
format.Header.TargetLanguage.Should().Be(new Language("de-DE"));

const string id = "testid2";

format.TranslationUnits.GetTranslationUnit(id).Translations.GetTranslation(new Language("de-DE")).Value.Should()
.Be("deutscher testid2 Text");
}

[Fact]
public async Task ReadAndWriteWithoutMsgCtxtText()
{
var format = await CreateAndReadFromFileAsync("test.po",
new FormatReadOptions { SourceLanguage = new Language("en-US") });

var outStream = new MemoryStream();
await format.WriteAsync(outStream);
await outStream.FlushAsync();
outStream.Seek(0, SeekOrigin.Begin);

var reader = new StreamReader(outStream);
var result = await reader.ReadToEndAsync();
result.Should().NotBeEmpty();
result.Should().NotContain("msgctxt ");
}

[Fact]
public async Task ReadAndWriteAsync()
{
Expand All @@ -66,7 +129,7 @@ public async Task ReadAndWriteAsync()
//fs.MustBeEqualTo(ms);
File.Delete($"{temp}normalized_translation_de.po");
}

[Fact]
public void ReadAndWrite()
{
Expand Down Expand Up @@ -105,7 +168,7 @@ public void WriteFormatLeavesStreamOpen()
memoryStream.CanRead.Should().BeTrue();
memoryStream.CanWrite.Should().BeTrue();
}

[Fact]
public async Task WriteFormatLeavesStreamOpenAsync()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
msgid ""
msgstr ""
"Language: de-DE\n"

msgid "testid1"
msgstr "deutscher testid1 Text"

msgid "testid2"
msgstr "deutscher testid2 Text"
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class AshLangFormatBuilder : IFormatBuilderWithSourceAndTarget<AshLangFor
private Dictionary<string, string> _information = new();

/// <inheritdoc />
public AshLangFormat Build()
public AshLangFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage.Value, nameof(_targetLanguage));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public sealed class CsvFormatBuilder : IFormatBuilderWithSourceAndTarget<CsvForm
private Dictionary<string, string> CustomHeaderInformation { get; set; } = new();

/// <inheritdoc />
public CsvFormat Build()
public CsvFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage.Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Ashampoo.Translation.Systems.Formats.Json;
using Ashampoo.Translation.Systems.Formats.NLang;
using Ashampoo.Translation.Systems.Formats.PO;
using Ashampoo.Translation.Systems.Formats.QT;
using Ashampoo.Translation.Systems.Formats.ResX;
using Ashampoo.Translation.Systems.Formats.TsProj;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -34,13 +35,14 @@ public static IServiceCollection RegisterFormats(this IServiceCollection service
services.AddSingleton<IFormatFactory, DefaultFormatFactory>();
services
.AddAshLangFormatFeatures()
.AddCsvFormat()
.AddGengoFormatFeatures()
.AddJavaPropertiesFormatFeatures()
.AddJsonFormatFeatures()
.AddNLangFormatFeatures()
.AddPOFormatFeatures()
.AddQtFormat()
.AddResXFormatFeatures()
.AddCsvFormat()
.AddTsProjFormatFeatures();

return services;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void Add(string id, string source, string target)
}

/// <inheritdoc />
public GengoFormat Build()
public GengoFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_sourceLanguage?.Value, nameof(_sourceLanguage));
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class JavaPropertiesFormatBuilder : IFormatBuilderWithTarget<JavaProperti
private readonly Dictionary<string, string> _translations = new();

/// <inheritdoc/>
public JavaPropertiesFormat Build()
public JavaPropertiesFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage.Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,13 @@ public async Task WriteAsync(Stream stream)
var root = new JsonObject();
CreateJsonObjects(root); // Create JSON objects from TranslationUnits

var options = new JsonSerializerOptions // Create JSON serializer options
var serializerOptions = new JsonSerializerOptions // Create JSON serializer options
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

await JsonSerializer.SerializeAsync(stream, root, options);
await JsonSerializer.SerializeAsync(stream, root, serializerOptions);
await stream.FlushAsync();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void Add(string id, string target)
}

/// <inheritdoc />
public JsonFormat Build()
public JsonFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Add(string id, string target)
}

/// <inheritdoc />
public NLangFormat Build()
public NLangFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage));

Expand Down
10 changes: 7 additions & 3 deletions src/Ashampoo.Translation.Systems.Formats/src/PO/MessageString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ public class MessageString : ITranslation
/// <summary>
/// Provides the id for the ITranslation interface.
/// </summary>
public string Id => !string.IsNullOrWhiteSpace(MsgCtxt) ? $"{MsgCtxt}{POConstants.Divider}{MsgId}" : MsgId;

public string Id => !string.IsNullOrWhiteSpace(MsgCtxt)
? $"{MsgCtxt}{POConstants.Divider}{MsgId}"
: MsgId;

/// <summary>
/// Provides the comment for the ITranslation interface.
/// </summary>
public IList<string> Comments { get; set; } = [];

/// <inheritdoc />
public Language Language { get; set; }

/// <summary>
/// Message string of the po format.
/// </summary>
Expand All @@ -53,6 +55,7 @@ public string Value
/// <param name="language"></param>
/// <param name="comments"></param>
/// <param name="msgCtxt"></param>
/// <param name="pipeSplitting"></param>

Check warning on line 58 in src/Ashampoo.Translation.Systems.Formats/src/PO/MessageString.cs

View workflow job for this annotation

GitHub Actions / build-and-test

XML comment has a param tag for 'pipeSplitting', but there is no parameter by that name

Check warning on line 58 in src/Ashampoo.Translation.Systems.Formats/src/PO/MessageString.cs

View workflow job for this annotation

GitHub Actions / build-and-test

XML comment has a param tag for 'pipeSplitting', but there is no parameter by that name

Check warning on line 58 in src/Ashampoo.Translation.Systems.Formats/src/PO/MessageString.cs

View workflow job for this annotation

GitHub Actions / publish-formats-package / publish-nuget-package

XML comment has a param tag for 'pipeSplitting', but there is no parameter by that name
public MessageString(string id, string value, Language language, IList<string> comments, string msgCtxt = "")
{
MsgId = id;
Expand Down Expand Up @@ -88,6 +91,7 @@ public virtual async Task WriteAsync(TextWriter writer)
await writer.WriteLineAsync($"{Escape(comment)}");
}
}

if (!string.IsNullOrWhiteSpace(MsgCtxt))
await writer.WriteLineAsync($"{POConstants.TypeMsgCtxt}\"{Escape(MsgCtxt)}\"");
await writer.WriteLineAsync($"{POConstants.TypeMsgId}\"{Escape(MsgId)}\"");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Add(string id, string target)
}

/// <inheritdoc />
public POFormat Build()
public POFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage));

Expand All @@ -32,11 +32,12 @@ public POFormat Build()
}
};

var builderOptions = options as PoBuilderOptions ?? new PoBuilderOptions();
foreach (var translation in _translations)
{
var translationUnit = new TranslationUnit(translation.Key);
var index = translation.Key.IndexOf(POConstants.Divider, StringComparison.InvariantCulture);
if (index > 0) // if divider exists, then a message context is used
if (builderOptions.SplitContextAndId && index > 0) // if divider exists, then a message context is used
{
var ctxt = translation.Key[..index];
var msgId = translation.Key[(index + POConstants.Divider.Length)..];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Ashampoo.Translation.Systems.Formats.Abstractions;

namespace Ashampoo.Translation.Systems.Formats.PO;

/// <summary>
/// IFormatBuilderOptions for POFormat
/// </summary>
public sealed record PoBuilderOptions : IFormatBuilderOptions
{
/// <summary>
/// Disables splitting of the id into msgctxt and msgid if a pipe separator is detected.
/// </summary>
public bool SplitContextAndId { get; init; } = true;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class QtFormatBuilder : IFormatBuilderWithTarget<QtFormat>
private readonly Dictionary<string, string> _translations = new();

/// <inheritdoc />
public QtFormat Build()
public QtFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage.Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class ResXFormatBuilder : IFormatBuilderWithTarget<ResXFormat>
private readonly Dictionary<string, string> _translations = new();

/// <inheritdoc />
public ResXFormat Build()
public ResXFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void Add(string id, string source, string target)
}

/// <inheritdoc />
public TsProjFormat Build()
public TsProjFormat Build(IFormatBuilderOptions? options = null)
{
Guard.IsNotNullOrWhiteSpace(_sourceLanguage?.Value, nameof(_sourceLanguage)); // sourceLanguage is required
Guard.IsNotNullOrWhiteSpace(_targetLanguage?.Value, nameof(_targetLanguage)); // targetLanguage is required
Expand Down

0 comments on commit ed57f62

Please sign in to comment.