Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void ReviewedGrammarWarningsBecomeCorrections(string source, string expec
[InlineData("É difícil dizer que foi pelo o que aconteceu.", "É difícil dizer que foi pelo que aconteceu.")]
[InlineData("Tenho um ideia melhor.", "Tenho uma ideia melhor.")]
[InlineData("Faz todo sentido.", "Faz todo o sentido.")]
[InlineData("Dei a ela todo dinheiro.", "Dei a ela todo o dinheiro.")]
[InlineData("Dei a ela todo dinheiro.", "Dei-lhe todo o dinheiro.")]
public void RepeatedMissedEpisodeFamiliesBecomeSelectableChanges(string source, string expected) => Converts(source, expected);

[Theory]
Expand Down
594 changes: 594 additions & 0 deletions se5/BrazilianToEuropeanPortuguese.Tests/BigCompareObjectTests.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
using SubtitleEdit.Plugins.BrazilianToEuropeanPortuguese;
using SubtitleEdit.Plugins.Shared;

namespace BrazilianToEuropeanPortuguese.Tests;

public sealed class ClauseAgreementAnalysisTests
{
[Theory]
[InlineData("Certeza?", "Certeza", "NominalUse")]
[InlineData("Ajuda financeira.", "Ajuda", "NominalUse")]
[InlineData("Ela precisa de ajuda.", "precisa", "OtherSubject")]
[InlineData("Maria trabalha aqui.", "trabalha", "OtherSubject")]
[InlineData("É necessário sair.", "É", "Impersonal")]
[InlineData("A pessoa que tu achas que precisa de ajuda.", "precisa", "RelativeSubject")]
[InlineData("A médica que tu pensas que trabalha aqui.", "trabalha", "RelativeSubject")]
[InlineData("Não tens o que fazer.", "fazer", "NonFiniteUse")]
[InlineData("Que miúda esperta tens.", "miúda", "NominalUse")]
public void StructuralReasonsBlockUnsafeAgreement(string text, string verb, string reason)
{
var decision = new ClauseAgreementAnalysis(text).Decide(text.IndexOf(verb, StringComparison.Ordinal),
ReferenceHint.FromText("You think this works."));
Assert.False(decision.Allowed);
Assert.Equal(reason, decision.Block.ToString());
}

[Theory]
[InlineData("Precisa de ajuda.", "Precisa")]
[InlineData("Se não precisar de ajuda.", "precisar")]
[InlineData("Tu sabes que precisa de ajuda.", "precisa")]
[InlineData("Ela saiu. Precisa de ajuda.", "Precisa")]
[InlineData("Ela saiu… Precisa de ajuda.", "Precisa")]
[InlineData("Ela saiu;\nprecisa de ajuda.", "precisa")]
[InlineData("-Ela saiu.\n-Precisa de ajuda.", "Precisa")]
[InlineData("<i>Precisa</i> de ajuda.", "Precisa")]
[InlineData("E está certo.", "está")]
[InlineData("Eu gostaria que confirmasse comigo.", "confirmasse")]
[InlineData("Disseste que sairia.", "sairia")]
[InlineData("Se mentir, é um crime.", "mentir")]
[InlineData("A pessoa que tu achas que você precisa de ajuda.", "precisa")]
public void BoundariesDoNotLeakAnUnrelatedSubject(string text, string verb)
{
var decision = new ClauseAgreementAnalysis(text).Decide(text.IndexOf(verb, StringComparison.Ordinal),
ReferenceHint.FromText("You need help."));
Assert.True(decision.Allowed);
}

[Theory]
[InlineData("Ajuda financeira.", "You help financially.", "Ajuda financeira.")]
[InlineData("Conta própria.", "You count on yourself.", "Conta própria.")]
[InlineData("É necessário sair.", "You need to leave.", "É necessário sair.")]
[InlineData("Era possível sair.", "You could leave.", "Era possível sair.")]
[InlineData("É possível.", "You can do it.", "É possível.")]
[InlineData("A médica que você pensa que precisa de ajuda.", "The doctor you think needs help.",
"A médica que pensas que precisa de ajuda.")]
[InlineData("Está falando com um cara que costumava pesar 65kg.",
"You're talking to a guy that used to weigh a buck 45 soaking wet.",
"Estás a falar com um tipo que costumava pesar 65kg.")]
[InlineData("Estamos atrás do cara que comanda o jogo de pôquer.",
"That'll get you killed, all right. The guy we're looking at runs the poker game.",
"Estamos atrás do tipo que comanda o jogo de póquer.")]
[InlineData("Que garota esperta você tem.", "Smart kid you got there.", "Que miúda esperta tens.")]
[InlineData("Não tem o que fazer.", "You have nothing to do.", "Não tens o que fazer.")]
[InlineData("O que significa que Reid terá acabado com dois policiais.",
"And you'll go to jail. Which means Reid takes out two cops.",
"O que significa que Reid terá acabado com dois polícias.")]
public void ReviewedNegativeCasesDoNotChangeMeaning(string source, string english, string expected) =>
Assert.Equal(expected, new PortugueseConverter().Convert(source, reference: ReferenceHint.FromText(english)));

[Theory]
[InlineData("Precisa de ajuda.", "You need help.", "Precisas de ajuda.")]
[InlineData("Se precisar de ajuda.", "If you need help.", "Se precisares de ajuda.")]
[InlineData("Você pensa que precisa de ajuda.", "You think you need help.", "Pensas que precisas de ajuda.")]
[InlineData("Você trabalha aqui e mora perto.", "You work here and you live nearby.", "Trabalhas aqui e vives perto.")]
[InlineData("Então soube que chegou.", "Then I learned you arrived.", "Então soube que chegaste.")]
[InlineData("É possível que ajude.", "You might help.", "É possível que ajudes.")]
[InlineData("E está certo.", "And you'd be right.", "E estás certo.")]
[InlineData("Eu gostaria que confirmasse comigo.", "I wish you would check in with me.",
"Eu gostaria que confirmasses comigo.")]
[InlineData("Você disse que sairia daqui.", "You said you would be out of here.",
"Disseste que sairias daqui.")]
[InlineData("Se mentir, é um crime.", "If you lie, it is a felony.", "Se mentires, é um crime.")]
[InlineData("O serviço que comanda?", "Why don't you tell us about the service you're running?", "O serviço que comandas?")]
[InlineData("O livro que quer ler.", "The book you want to read.", "O livro que queres ler.")]
public void ReviewedPositiveCasesKeepRequiredConversions(string source, string english, string expected) =>
Assert.Equal(expected, new PortugueseConverter().Convert(source, reference: ReferenceHint.FromText(english)));

[Fact]
public void CandidatesRetainMorphologicalAmbiguity()
{
Assert.True(ClauseAgreementAnalysis.Candidates("ajuda").HasFlag(VerbCandidate.ThirdPerson));
Assert.True(ClauseAgreementAnalysis.Candidates("ajuda").HasFlag(VerbCandidate.NominalHomograph));
Assert.True(ClauseAgreementAnalysis.Candidates("ajudas").HasFlag(VerbCandidate.SecondPerson));
Assert.False(ClauseAgreementAnalysis.Candidates("certeza").HasFlag(VerbCandidate.ThirdPerson));
}

[Theory]
[InlineData("O que está fazendo?", "What the hell are you doing?", "O que estás a fazer?")]
[InlineData("Pode fazer o que quiser.", "You can do whatever you want.", "Podes fazer o que quiseres.")]
[InlineData("Tem certeza que está pronta?", "You sure you're up for this?", "Tens a certeza que estás pronta?")]
[InlineData("Você lê o que está nos rótulos.", "You read what's on the labels.",
"Lês o que está nos rótulos.")]
[InlineData("É tudo que pode fazer.", "That's all you can do.", "É tudo o que podes fazer.")]
[InlineData("Estou preocupada com o que está fazendo.",
"Are you worried I don't know what I'm doing? I'm worried about what you are doing.",
"Estou preocupada com o que estás a fazer.")]
[InlineData("Dou o tempo que precisar.", "I'll give you as much time as you need.",
"Dou o tempo que precisares.")]
[InlineData("O que sabe da testemunha que desapareceu?",
"What do you know about the witness that disappeared?",
"O que sabes da testemunha que desapareceu?")]
public void ComplementAndObjectRelativeSubjectsRemainDistinct(string source, string english, string expected) =>
Assert.Equal(expected, new PortugueseConverter().Convert(source, reference: ReferenceHint.FromText(english)));

[Fact]
public void FormalAndDisabledAddressStayUnchanged()
{
const string source = "Precisa de ajuda.";
var reference = ReferenceHint.FromText("You need help.")!;
Assert.Equal(source, new PortugueseConverter().Convert(source, reference: reference with { FormalAddress = true }));
Assert.Equal(source, new PortugueseConverter(new ConversionOptions(YouToTu: false)).Convert(source, reference: reference));
Assert.Equal(source, new PortugueseConverter(new ConversionOptions(DisabledRules: "address")).Convert(source, reference: reference));
}

[Fact]
public void SharedPipelinePreservesSelectionOriginalsAndTiming()
{
var blocks = SubRipParser.Parse("1\n00:00:01,000 --> 00:00:02,000\nÉ necessário sair.\n\n" +
"2\n00:00:02,100 --> 00:00:03,000\nPrecisa de ajuda.\n\n");
var result = SubtitleConversion.Convert(blocks, new ConversionOptions(),
english: new string?[] { "You need to leave.", "You need help." }, selected: new HashSet<int> { 0 });
Assert.Equal("É necessário sair.", result[0].Text);
Assert.Equal("Precisa de ajuda.", result[1].Text);
Assert.Equal("É necessário sair.", blocks[0].Text);
Assert.Equal(3000L, blocks[1].EndMs);
var selected = SubtitleConversion.Convert(blocks, new ConversionOptions(),
english: new string?[] { "You need to leave.", "You need help." }, selected: new HashSet<int> { 1 });
Assert.Equal("Precisas de ajuda.", selected[1].Text);
Assert.Equal(2100L, blocks[1].StartMs);
Assert.Equal("Precisa de ajuda.", blocks[1].Text);
}
}
147 changes: 147 additions & 0 deletions se5/BrazilianToEuropeanPortuguese.Tests/ConflictVocabularyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using SubtitleEdit.Plugins.BrazilianToEuropeanPortuguese;
using SubtitleEdit.Plugins.Shared;

namespace BrazilianToEuropeanPortuguese.Tests;

public sealed class ConflictVocabularyTests
{
[Theory]
[InlineData("A briga estourou\nfaz 20 minutos.", "Fighting broke out\n20 minutes ago.",
"A luta estourou\nfaz 20 minutos.")]
[InlineData("As brigas terminaram.", "The physical fights ended.", "As lutas terminaram.")]
[InlineData("Uma briga violenta.", "A violent brawl.", "Uma rixa violenta.")]
[InlineData("As brigas violentas.", "The violent brawls.", "As rixas violentas.")]
[InlineData("Uma briga.", "A physical scuffle.", "Uma rixa.")]
[InlineData("A briga foi por dinheiro.", "The argument was about money.", "A discussão foi por dinheiro.")]
[InlineData("As brigas foram por dinheiro.", "The arguments were about money.", "As discussões foram por dinheiro.")]
[InlineData("A briga pela propriedade.", "The dispute over the property.", "A disputa pela propriedade.")]
[InlineData("A briga pelo título.", null, "A luta pelo título.")]
[InlineData("Uma briga de rua.", null, "Uma luta de rua.")]
[InlineData("Uma briga de faca.", null, "Uma luta de faca.")]
[InlineData("Uma briga corpo a corpo.", null, "Uma luta corpo a corpo.")]
[InlineData("A briga contra o câncer.", null, "A luta contra o cancro.")]
[InlineData("A briga verbal.", null, "A discussão verbal.")]
[InlineData("A BRIGA ESTOUROU.", "Fighting broke out.", "A LUTA ESTOUROU.")]
[InlineData("<i>A briga estourou.</i>", "Fighting broke out.", "<i>A luta estourou.</i>")]
[InlineData("Um bate-boca acalorado.", "A heated argument.", "Uma discussão acalorada.")]
[InlineData("Os bate-bocas acalorados.", "The heated arguments.", "As discussões acaloradas.")]
[InlineData("Um bate-boca.", "A chat.", "Uma conversa.")]
[InlineData("Um bate-boca.", "An uproar.", "Uma algazarra.")]
[InlineData("Eles brigaram.", "They fought with their fists.", "Eles lutaram.")]
[InlineData("Ele brigou.", "He fought in battle.", "Ele lutou.")]
[InlineData("Eles estavam brigando.", "They were fighting with their fists.", "Eles estavam a lutar.")]
[InlineData("Ele vai brigar.", "He will fight in battle.", "Ele vai lutar.")]
[InlineData("Se eles brigarem.", "If they fight with their fists.", "Se eles lutarem.")]
[InlineData("Eles brigaram a socos.", null, "Eles lutaram a socos.")]
[InlineData("Eles brigam pela liberdade.", null, "Eles lutam pela liberdade.")]
[InlineData("Ele briga.", "He fights with his fists.", "Ele luta.")]
[InlineData("Tu brigas.", "You fight with your fists.", "Tu lutas.")]
[InlineData("Ele briga por dinheiro.", "He argues about money.", "Ele discute por dinheiro.")]
public void ContextDistinguishesCombatArgumentsAndDisputes(string source, string? english, string expected) =>
Assert.Equal(expected, new PortugueseConverter().Convert(source, reference: ReferenceHint.FromText(english)));

[Theory]
[InlineData("Uma briga.", null, "Uma zanga.")]
[InlineData("Eles brigaram.", null, "Eles discutiram.")]
[InlineData("Eles brigaram.", "They argued about dinner.", "Eles discutiram.")]
[InlineData("Eles brigaram.", "They fight about money.", "Eles discutiram.")]
[InlineData("Estamos brigados.", "We had a fight.", "Estamos brigados.")]
[InlineData("Uma briga de palavras.", "A physical fight.", "Uma zanga de palavras.")]
[InlineData("A luta terminou.", "The argument ended.", "A luta terminou.")]
[InlineData("A zanga terminou.", "The fighting ended.", "A zanga terminou.")]
[InlineData("Obrigado, brigada.", "The fighting ended.", "Obrigado, brigada.")]
[InlineData("Uma briga e uma briga.", "A fight and an argument.", "Uma zanga e uma zanga.")]
[InlineData("Uma pancadaria.", "A brawl.", "Uma pancadaria.")]
[InlineData("Um barraco.", "A small shack.", "Um barraco.")]
[InlineData("Briga começou.", "Fighting started.", "Briga começou.")]
[InlineData("Brigas violentas.", "Violent fights.", "Brigas violentas.")]
[InlineData("Uma briga.", "A fight and an argument.", "Uma zanga.")]
[InlineData("Eles brigaram.", "They argued, then fought.", "Eles discutiram.")]
[InlineData("Eles brigavam como um velho casal.", "They would fight like an old married couple.",
"Eles discutiam como um velho casal.")]
[InlineData("Uma briga doméstica.", "A domestic dispute.", "Uma discussão doméstica.")]
[InlineData("Uma briga.", "A fight.", "Uma zanga.")]
[InlineData("Eles brigaram.", "They fought.", "Eles discutiram.")]
[InlineData("Uma briga.", "A battle of words.", "Uma discussão.")]
[InlineData("Um bate-boca.", "A physical fight.", "Uma discussão.")]
[InlineData("Eles brigaram com o NCIS.", "They got into a scuffle with NCIS over a theory.",
"Eles discutiram com o NCIS.")]
[InlineData("brigue com o NCIS por um palpite\nde que a Força Quds está",
"get into a scuffle with NCIS over some harebrained notion\nthat Quds Force is picking off SEALs",
"discuta com o NCIS por um palpite\nde que a Força Quds está")]
public void AmbiguousAndAlreadyEuropeanReadingsAreNotRewritten(string source, string? english, string expected) =>
Assert.Equal(expected, new PortugueseConverter().Convert(source, reference: ReferenceHint.FromText(english)));

[Fact]
public void SeparateClausesKeepTheirOwnConflictSense()
{
const string source = "A briga acabou. A briga começou.";
var hint = ReferenceHint.FromText("The physical fight ended. The argument started.");
Assert.Equal("A luta acabou. A discussão começou.", new PortugueseConverter().Convert(source, reference: hint));
Assert.Equal("- Uma luta.\n- Uma discussão.", new PortugueseConverter().Convert("- Uma briga.\n- Uma briga.",
reference: ReferenceHint.FromText("- A physical fight.\n- An argument.")));
}

[Fact]
public void EveryUnambiguousGeneratedVerbFormRetainsTenseAndPerson()
{
var entry = new VerbEntry("brigar", "discutir", null, null,
new[] { "brigado", "brigada", "brigados", "brigadas" }, new[] { "briga", "brigas" });
var verbs = new VerbVocabulary(new[] { entry }, _ => false, _ => false);
Assert.True(VerbConjugator.TryConjugate("brigar", out var source));
Assert.True(VerbConjugator.TryConjugate("lutar", out var combat));
Assert.True(VerbConjugator.TryConjugate("discutir", out var argument));
var checkedForms = 0;
foreach (var group in source.Select((form, index) => (form, index)).GroupBy(pair => pair.form))
{
if (entry.Skip.Contains(group.Key) || group.Select(pair => argument[pair.index]).Distinct().Count() != 1 ||
group.Select(pair => combat[pair.index]).Distinct().Count() != 1) continue;
var index = group.First().index;
Assert.Equal("Eles " + combat[index], verbs.Apply("Eles " + group.Key, ReferenceHint.FromText("They fought with their fists.")));
Assert.Equal("Eles " + argument[index], verbs.Apply("Eles " + group.Key, ReferenceHint.FromText("They argued.")));
checkedForms++;
}
Assert.True(checkedForms >= 30, $"Only {checkedForms} inflections checked.");
}

[Fact]
public void ExistingControlsAndLocalEntriesTakePrecedence()
{
var hint = ReferenceHint.FromText("Fighting broke out.")!;
const string source = "A briga estourou.";
Assert.Equal(source, new PortugueseConverter(new ConversionOptions(Vocabulary: false)).Convert(source, reference: hint));
Assert.Equal(source, new PortugueseConverter(new ConversionOptions(DisabledRules: "word-list")).Convert(source, reference: hint));
var ignored = new PortugueseLocalWordList();
ignored.Ignored.Add("briga");
Assert.Equal(source, new PortugueseConverter(localWordList: ignored).Convert(source, reference: hint));
var local = new PortugueseLocalWordList();
local.Words.Add(("briga", "contenda"));
Assert.Equal("A contenda estourou.", new PortugueseConverter(localWordList: local).Convert(source, reference: hint));
Assert.Equal("Eles brigaram.", new PortugueseConverter(new ConversionOptions(DisabledRules: "verb-vocabulary"))
.Convert("Eles brigaram.", reference: ReferenceHint.FromText("They fought.")));
var ignoredVerb = new PortugueseLocalWordList();
ignoredVerb.Ignored.Add("brigar");
Assert.Equal("Eles brigaram.", new PortugueseConverter(localWordList: ignoredVerb)
.Convert("Eles brigaram.", reference: ReferenceHint.FromText("They fought.")));
var nounOverride = new PortugueseLocalWordList();
nounOverride.Words.Add(("briga", "disputa"));
Assert.Equal("Ele disputa.", new PortugueseConverter(localWordList: nounOverride)
.Convert("Ele briga.", reference: ReferenceHint.FromText("He fights.")));
}

[Fact]
public void BatchPipelinePreservesOriginalsTimingsAndRepeatedOutput()
{
const string source = "A briga estourou\nfaz 20 minutos.";
var blocks = new List<SrtBlock> { new() { StartMs = 1045145, EndMs = 1046574, Text = source } };
var results = SubtitleConversion.Convert(blocks, new ConversionOptions(),
english: new string?[] { "Fighting broke out\n20 minutes ago." });
Assert.Equal("A luta estourou\nfaz 20 minutos.", results[0].Text);
Assert.Equal(source, blocks[0].Text);
Assert.Equal(1045145, blocks[0].StartMs);
Assert.Equal(1046574, blocks[0].EndMs);
Assert.Contains(results[0].Rules, r => r.Id == "word-list");
Assert.Equal(results[0].Text, new PortugueseConverter().Convert(results[0].Text,
reference: ReferenceHint.FromText("Fighting broke out\n20 minutes ago.")));
}
}
Loading
Loading