Add per-form English translations to verb conjugation table
New EnglishConjugator in SharedModels constructs English translations by combining the verb's infinitive with person pronouns and tense auxiliaries (e.g., abatir conditional yo → "I would knock down"). Covers all 20 tense IDs, handles 60+ irregular English verbs, multi-word verbs, 3rd person rules, gerund and participle formation. VerbDetailView shows the English below each conjugated form, plus a legend explaining red = irregular conjugation. 42 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
import Testing
|
||||
@testable import SharedModels
|
||||
|
||||
@Suite("EnglishConjugator")
|
||||
struct EnglishConjugatorTests {
|
||||
|
||||
// MARK: - haber (to have) — irregular English verb
|
||||
|
||||
@Test("haber present: I have / you have / he/she has")
|
||||
func haberPresent() {
|
||||
#expect(t("to have", "ind_presente", 0) == "I have")
|
||||
#expect(t("to have", "ind_presente", 1) == "you have")
|
||||
#expect(t("to have", "ind_presente", 2) == "he/she has")
|
||||
#expect(t("to have", "ind_presente", 3) == "we have")
|
||||
#expect(t("to have", "ind_presente", 5) == "they have")
|
||||
}
|
||||
|
||||
@Test("haber preterite: I had")
|
||||
func haberPreterite() {
|
||||
#expect(t("to have", "ind_preterito", 0) == "I had")
|
||||
#expect(t("to have", "ind_preterito", 2) == "he/she had")
|
||||
}
|
||||
|
||||
@Test("haber future: I will have")
|
||||
func haberFuture() {
|
||||
#expect(t("to have", "ind_futuro", 0) == "I will have")
|
||||
#expect(t("to have", "ind_futuro", 3) == "we will have")
|
||||
}
|
||||
|
||||
@Test("haber conditional: I would have")
|
||||
func haberConditional() {
|
||||
#expect(t("to have", "cond_presente", 0) == "I would have")
|
||||
}
|
||||
|
||||
@Test("haber present perfect: I have had / he/she has had")
|
||||
func haberPresentPerfect() {
|
||||
#expect(t("to have", "ind_perfecto", 0) == "I have had")
|
||||
#expect(t("to have", "ind_perfecto", 2) == "he/she has had")
|
||||
}
|
||||
|
||||
// MARK: - ir (to go) — irregular English verb
|
||||
|
||||
@Test("ir present: I go / he/she goes")
|
||||
func irPresent() {
|
||||
#expect(t("to go", "ind_presente", 0) == "I go")
|
||||
#expect(t("to go", "ind_presente", 2) == "he/she goes")
|
||||
#expect(t("to go", "ind_presente", 5) == "they go")
|
||||
}
|
||||
|
||||
@Test("ir preterite: I went")
|
||||
func irPreterite() {
|
||||
#expect(t("to go", "ind_preterito", 0) == "I went")
|
||||
#expect(t("to go", "ind_preterito", 2) == "he/she went")
|
||||
}
|
||||
|
||||
@Test("ir imperfect: I used to go")
|
||||
func irImperfect() {
|
||||
#expect(t("to go", "ind_imperfecto", 0) == "I used to go")
|
||||
}
|
||||
|
||||
@Test("ir present perfect: I have gone")
|
||||
func irPresentPerfect() {
|
||||
#expect(t("to go", "ind_perfecto", 0) == "I have gone")
|
||||
#expect(t("to go", "ind_perfecto", 2) == "he/she has gone")
|
||||
}
|
||||
|
||||
// MARK: - ser (to be) — most irregular English verb
|
||||
|
||||
@Test("ser present: he/she is")
|
||||
func serPresent() {
|
||||
#expect(t("to be", "ind_presente", 2) == "he/she is")
|
||||
}
|
||||
|
||||
@Test("ser preterite: I was/were")
|
||||
func serPreterite() {
|
||||
#expect(t("to be", "ind_preterito", 0) == "I was/were")
|
||||
}
|
||||
|
||||
@Test("ser present perfect: I have been")
|
||||
func serPresentPerfect() {
|
||||
#expect(t("to be", "ind_perfecto", 0) == "I have been")
|
||||
}
|
||||
|
||||
// MARK: - hablar (to speak)
|
||||
|
||||
@Test("hablar present: I speak / he/she speaks")
|
||||
func hablarPresent() {
|
||||
#expect(t("to speak", "ind_presente", 0) == "I speak")
|
||||
#expect(t("to speak", "ind_presente", 2) == "he/she speaks")
|
||||
}
|
||||
|
||||
@Test("hablar preterite: I spoke")
|
||||
func hablarPreterite() {
|
||||
#expect(t("to speak", "ind_preterito", 0) == "I spoke")
|
||||
}
|
||||
|
||||
@Test("hablar present perfect: I have spoken")
|
||||
func hablarPresentPerfect() {
|
||||
#expect(t("to speak", "ind_perfecto", 0) == "I have spoken")
|
||||
}
|
||||
|
||||
// MARK: - comer (to eat)
|
||||
|
||||
@Test("comer preterite: I ate")
|
||||
func comerPreterite() {
|
||||
#expect(t("to eat", "ind_preterito", 0) == "I ate")
|
||||
}
|
||||
|
||||
@Test("comer present perfect: I have eaten")
|
||||
func comerPresentPerfect() {
|
||||
#expect(t("to eat", "ind_perfecto", 0) == "I have eaten")
|
||||
}
|
||||
|
||||
// MARK: - vivir (to live) — regular English verb
|
||||
|
||||
@Test("vivir present: I live / he/she lives")
|
||||
func vivirPresent() {
|
||||
#expect(t("to live", "ind_presente", 0) == "I live")
|
||||
#expect(t("to live", "ind_presente", 2) == "he/she lives")
|
||||
}
|
||||
|
||||
@Test("vivir preterite: I lived")
|
||||
func vivirPreterite() {
|
||||
#expect(t("to live", "ind_preterito", 0) == "I lived")
|
||||
}
|
||||
|
||||
// MARK: - abatir (to knock down) — multi-word verb
|
||||
|
||||
@Test("abatir present: I knock down / he/she knocks down")
|
||||
func abatirPresent() {
|
||||
#expect(t("to knock down", "ind_presente", 0) == "I knock down")
|
||||
#expect(t("to knock down", "ind_presente", 2) == "he/she knocks down")
|
||||
}
|
||||
|
||||
@Test("abatir conditional: I would knock down")
|
||||
func abatirConditional() {
|
||||
#expect(t("to knock down", "cond_presente", 0) == "I would knock down")
|
||||
#expect(t("to knock down", "cond_presente", 2) == "he/she would knock down")
|
||||
}
|
||||
|
||||
@Test("abatir preterite: I knocked down")
|
||||
func abatirPreterite() {
|
||||
#expect(t("to knock down", "ind_preterito", 0) == "I knocked down")
|
||||
}
|
||||
|
||||
// MARK: - Conditional
|
||||
|
||||
@Test("conditional: I would speak")
|
||||
func conditional() {
|
||||
#expect(t("to speak", "cond_presente", 0) == "I would speak")
|
||||
#expect(t("to speak", "cond_presente", 2) == "he/she would speak")
|
||||
}
|
||||
|
||||
@Test("conditional perfect: I would have gone")
|
||||
func conditionalPerfect() {
|
||||
#expect(t("to go", "cond_perfecto", 0) == "I would have gone")
|
||||
}
|
||||
|
||||
// MARK: - Subjunctive
|
||||
|
||||
@Test("present subjunctive: that I speak")
|
||||
func presentSubjunctive() {
|
||||
#expect(t("to speak", "subj_presente", 0) == "that I speak")
|
||||
#expect(t("to speak", "subj_presente", 2) == "that he/she speak")
|
||||
}
|
||||
|
||||
@Test("imperfect subjunctive (ra): that I would speak")
|
||||
func imperfectSubjunctive1() {
|
||||
#expect(t("to speak", "subj_imperfecto_1", 0) == "that I would speak")
|
||||
}
|
||||
|
||||
@Test("imperfect subjunctive (se): that I would speak")
|
||||
func imperfectSubjunctive2() {
|
||||
#expect(t("to speak", "subj_imperfecto_2", 0) == "that I would speak")
|
||||
}
|
||||
|
||||
@Test("subjunctive perfect: that I have spoken")
|
||||
func subjunctivePerfect() {
|
||||
#expect(t("to speak", "subj_perfecto", 0) == "that I have spoken")
|
||||
#expect(t("to speak", "subj_perfecto", 2) == "that he/she has spoken")
|
||||
}
|
||||
|
||||
@Test("subjunctive pluperfect: that I had gone")
|
||||
func subjunctivePluperfect() {
|
||||
#expect(t("to go", "subj_pluscuamperfecto_1", 0) == "that I had gone")
|
||||
#expect(t("to go", "subj_pluscuamperfecto_2", 0) == "that I had gone")
|
||||
}
|
||||
|
||||
@Test("subjunctive future: that I will speak")
|
||||
func subjunctiveFuture() {
|
||||
#expect(t("to speak", "subj_futuro", 0) == "that I will speak")
|
||||
}
|
||||
|
||||
@Test("subjunctive future perfect: that I will have spoken")
|
||||
func subjunctiveFuturePerfect() {
|
||||
#expect(t("to speak", "subj_futuro_perfecto", 0) == "that I will have spoken")
|
||||
}
|
||||
|
||||
// MARK: - Imperative
|
||||
|
||||
@Test("imperative affirmative")
|
||||
func imperativeAffirmative() {
|
||||
#expect(t("to speak", "imp_afirmativo", 1) == "speak!")
|
||||
#expect(t("to speak", "imp_afirmativo", 3) == "let's speak!")
|
||||
}
|
||||
|
||||
@Test("imperative negative")
|
||||
func imperativeNegative() {
|
||||
#expect(t("to speak", "imp_negativo", 1) == "don't speak")
|
||||
}
|
||||
|
||||
// MARK: - Compound indicative tenses
|
||||
|
||||
@Test("pluperfect: I had spoken")
|
||||
func pluperfect() {
|
||||
#expect(t("to speak", "ind_pluscuamperfecto", 0) == "I had spoken")
|
||||
#expect(t("to go", "ind_pluscuamperfecto", 0) == "I had gone")
|
||||
}
|
||||
|
||||
@Test("future perfect: I will have spoken")
|
||||
func futurePerfect() {
|
||||
#expect(t("to speak", "ind_futuro_perfecto", 0) == "I will have spoken")
|
||||
}
|
||||
|
||||
@Test("preterite anterior: I had spoken (same as pluperfect in English)")
|
||||
func preteriteAnterior() {
|
||||
#expect(t("to speak", "ind_preterito_anterior", 0) == "I had spoken")
|
||||
}
|
||||
|
||||
// MARK: - Edge cases
|
||||
|
||||
@Test("empty english returns empty string")
|
||||
func emptyEnglish() {
|
||||
#expect(t("", "ind_presente", 0) == "")
|
||||
#expect(t("to ", "ind_presente", 0) == "")
|
||||
}
|
||||
|
||||
@Test("unknown tense falls back to pronoun + base")
|
||||
func unknownTense() {
|
||||
#expect(t("to speak", "some_future_tense", 0) == "I speak")
|
||||
}
|
||||
|
||||
@Test("3rd person present: study → studies")
|
||||
func thirdPersonYRule() {
|
||||
#expect(t("to study", "ind_presente", 2) == "he/she studies")
|
||||
}
|
||||
|
||||
@Test("3rd person present: play → plays")
|
||||
func thirdPersonVowelY() {
|
||||
#expect(t("to play", "ind_presente", 2) == "he/she plays")
|
||||
}
|
||||
|
||||
@Test("3rd person present: watch → watches")
|
||||
func thirdPersonChRule() {
|
||||
#expect(t("to watch", "ind_presente", 2) == "he/she watches")
|
||||
}
|
||||
|
||||
@Test("past regular: carry → carried")
|
||||
func pastYRule() {
|
||||
#expect(t("to carry", "ind_preterito", 0) == "I carried")
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func t(_ english: String, _ tenseId: String, _ personIndex: Int) -> String {
|
||||
EnglishConjugator.translate(english: english, tenseId: tenseId, personIndex: personIndex)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user