forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
20.6 KiB
1//! Strings for the code group: repo browsing, commits, refs, diffs, archives, code search,
2//! star and fork. One `K` variant per phrase, an exhaustive `t` match, and helpers for
3//! sentences that carry arguments.
4
5use forge_core::store::commit_status::StatusState;
6
7use super::Lang;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum K {
11 SearchWord,
12 SearchFailed,
13 SearchCodePlaceholder,
14 SearchButton,
15 RefField,
16 PathField,
17 MatchCase,
18 RegexOption,
19 SearchFilesAt,
20 NoMatches,
21 ShowingFirst,
22 ShowingFirstEnd,
23 CloneTitle,
24 SshRequiresKey,
25 BranchesTitle,
26 EmptyRepoPush,
27 OverHttps,
28 OverSsh,
29 DownloadNav,
30 DownloadZip,
31 DownloadTarGz,
32 RecentPushes,
33 HadRecentPushes,
34 CompareAndPr,
35 BranchLabel,
36 NameHeader,
37 LastCommitHeader,
38 AgeHeader,
39 KindDir,
40 KindFile,
41 KindExec,
42 KindLink,
43 KindSubmodule,
44 Rendered,
45 SourceToggle,
46 HistoryLink,
47 RawLink,
48 DownloadLink,
49 FileNav,
50 SymlinkPrefix,
51 SubmodulePrefix,
52 SubmoduleSuffix,
53 TruncatedPrefix,
54 ViewFullRaw,
55 StatusAdded,
56 StatusDeleted,
57 StatusModified,
58 StatusRenamed,
59 StatusCopied,
60 StatusTypeChanged,
61 NoFileChanges,
62 BinaryFileChanged,
63 DiffTooLargePrefix,
64 ViewFile,
65 DiffTooLarge,
66 CommentOnLine,
67 AddReviewComment,
68 StartReview,
69 CommentLabel,
70 AddSingleComment,
71 CancelLink,
72 ThisCommit,
73 CommitStatusPrefix,
74 StateSuccess,
75 StateFailure,
76 StateError,
77 StatePending,
78 NoChecksReported,
79 AllChecksPassed,
80 ChecksPending,
81 SomeChecksFailed,
82 ShowChecks,
83 DetailsLink,
84 AuthorLabel,
85 CommitterLabel,
86 RootCommit,
87 ParentLabel,
88 BrowseFiles,
89 SigVerified,
90 SigUnverified,
91 CommitsOn,
92 FilteredTo,
93 ClearFilter,
94 NoCommits,
95 Committed,
96 BrowseFilesShort,
97 NewerLink,
98 OlderLink,
99 NothingHere,
100 DefaultBadge,
101 TagsTitle,
102 TagKindLabel,
103 ForkedFrom,
104 MirrorOf,
105 NotSyncedYet,
106 ForkButton,
107 StarsAria,
108 ArchivedNotice,
109 RepositoryNav,
110 TabIssues,
111 TabPulls,
112 TabCommits,
113 TabReleases,
114 TabCi,
115 TabDiscussions,
116 TabWiki,
117 TabSettings,
118}
119
120pub fn t(lang: Lang, key: K) -> &'static str {
121 use K::*;
122 use Lang::*;
123 match (key, lang) {
124 (SearchWord, En) => "search",
125 (SearchWord, Tr) => "arama",
126 (SearchFailed, En) => {
127 "The search could not run. Check the pattern; regex mode uses extended regular expressions."
128 }
129 (SearchFailed, Tr) => {
130 "Arama çalıştırılamadı. Deseni kontrol edin; regex kipi genişletilmiş düzenli ifadeleri kullanır."
131 }
132 (SearchCodePlaceholder, En) => "Search code",
133 (SearchCodePlaceholder, Tr) => "Kodda ara",
134 (SearchButton, En) => "Search",
135 (SearchButton, Tr) => "Ara",
136 (RefField, En) => "Ref ",
137 (RefField, Tr) => "Referans ",
138 (PathField, En) => "Path ",
139 (PathField, Tr) => "Yol ",
140 (MatchCase, En) => " Match case",
141 (MatchCase, Tr) => " Büyük/küçük harfe duyarlı",
142 (RegexOption, En) => " Regex",
143 (RegexOption, Tr) => " Düzenli ifade",
144 (SearchFilesAt, En) => "Search the files at ",
145 (SearchFilesAt, Tr) => "Dosyaları şurada ara: ",
146 (NoMatches, En) => "No matches.",
147 (NoMatches, Tr) => "Eşleşme yok.",
148 (ShowingFirst, En) => " (showing the first ",
149 (ShowingFirst, Tr) => " (ilk ",
150 (ShowingFirstEnd, En) => ")",
151 (ShowingFirstEnd, Tr) => " gösteriliyor)",
152 (CloneTitle, En) => "Clone",
153 (CloneTitle, Tr) => "Klonla",
154 (SshRequiresKey, En) => "SSH (requires an ed25519 or ECDSA key on your account)",
155 (SshRequiresKey, Tr) => "SSH (hesabınızda bir ed25519 veya ECDSA anahtarı olmalı)",
156 (BranchesTitle, En) => "Branches",
157 (BranchesTitle, Tr) => "Dallar",
158 (EmptyRepoPush, En) => "This repository is empty. Push a branch to get started:",
159 (EmptyRepoPush, Tr) => "Bu depo boş. Başlamak için bir dal gönderin:",
160 (OverHttps, En) => "Over HTTPS",
161 (OverHttps, Tr) => "HTTPS üzerinden",
162 (OverSsh, En) => "Over SSH",
163 (OverSsh, Tr) => "SSH üzerinden",
164 (DownloadNav, En) => "Download",
165 (DownloadNav, Tr) => "İndir",
166 (DownloadZip, En) => "Download ZIP",
167 (DownloadZip, Tr) => "ZIP olarak indir",
168 (DownloadTarGz, En) => "Download tar.gz",
169 (DownloadTarGz, Tr) => "tar.gz olarak indir",
170 (RecentPushes, En) => "Recent pushes",
171 (RecentPushes, Tr) => "Son gönderimler",
172 (HadRecentPushes, En) => " had recent pushes ",
173 (HadRecentPushes, Tr) => " dalına son zamanlarda gönderim yapıldı ",
174 (CompareAndPr, En) => "Compare & pull request",
175 (CompareAndPr, Tr) => "Karşılaştır ve çekme isteği aç",
176 (BranchLabel, En) => "Branch",
177 (BranchLabel, Tr) => "Dal",
178 (NameHeader, En) => "Name",
179 (NameHeader, Tr) => "Ad",
180 (LastCommitHeader, En) => "Last commit",
181 (LastCommitHeader, Tr) => "Son commit",
182 (AgeHeader, En) => "Age",
183 (AgeHeader, Tr) => "Zaman",
184 (KindDir, En) => "dir",
185 (KindDir, Tr) => "dizin",
186 (KindFile, En) => "file",
187 (KindFile, Tr) => "dosya",
188 (KindExec, En) => "exec",
189 (KindExec, Tr) => "çalıştırılabilir",
190 (KindLink, En) => "link",
191 (KindLink, Tr) => "bağlantı",
192 (KindSubmodule, En) => "submodule",
193 (KindSubmodule, Tr) => "alt modül",
194 (Rendered, En) => "Rendered",
195 (Rendered, Tr) => "Önizleme",
196 (SourceToggle, En) => "Source",
197 (SourceToggle, Tr) => "Kaynak",
198 (HistoryLink, En) => "History",
199 (HistoryLink, Tr) => "Geçmiş",
200 (RawLink, En) => "Raw",
201 (RawLink, Tr) => "Ham",
202 (DownloadLink, En) => "Download",
203 (DownloadLink, Tr) => "İndir",
204 (FileNav, En) => "File",
205 (FileNav, Tr) => "Dosya",
206 (SymlinkPrefix, En) => "Symbolic link → ",
207 (SymlinkPrefix, Tr) => "Sembolik bağlantı → ",
208 (SubmodulePrefix, En) => "Submodule at commit ",
209 (SubmodulePrefix, Tr) => "Alt modül, şu commit'te: ",
210 (SubmoduleSuffix, En) => ". Its contents are not in this repository.",
211 (SubmoduleSuffix, Tr) => ". İçeriği bu depoda yok.",
212 (TruncatedPrefix, En) => "Showing the first 1 MiB of this file. ",
213 (TruncatedPrefix, Tr) => "Bu dosyanın ilk 1 MiB'ı gösteriliyor. ",
214 (ViewFullRaw, En) => "View the full file raw",
215 (ViewFullRaw, Tr) => "Dosyanın tamamını ham olarak görüntüle",
216 (StatusAdded, En) => "added",
217 (StatusAdded, Tr) => "eklendi",
218 (StatusDeleted, En) => "deleted",
219 (StatusDeleted, Tr) => "silindi",
220 (StatusModified, En) => "modified",
221 (StatusModified, Tr) => "değiştirildi",
222 (StatusRenamed, En) => "renamed",
223 (StatusRenamed, Tr) => "yeniden adlandırıldı",
224 (StatusCopied, En) => "copied",
225 (StatusCopied, Tr) => "kopyalandı",
226 (StatusTypeChanged, En) => "type changed",
227 (StatusTypeChanged, Tr) => "tür değiştirildi",
228 (NoFileChanges, En) => "No file changes.",
229 (NoFileChanges, Tr) => "Dosya değişikliği yok.",
230 (BinaryFileChanged, En) => "Binary file changed",
231 (BinaryFileChanged, Tr) => "İkili dosya değiştirildi",
232 (DiffTooLargePrefix, En) => "Diff too large; ",
233 (DiffTooLargePrefix, Tr) => "Fark çok büyük; ",
234 (ViewFile, En) => "view file",
235 (ViewFile, Tr) => "dosyayı görüntüle",
236 (DiffTooLarge, En) => "Diff too large.",
237 (DiffTooLarge, Tr) => "Fark çok büyük.",
238 (CommentOnLine, En) => "Comment on this line",
239 (CommentOnLine, Tr) => "Bu satıra yorum yap",
240 (AddReviewComment, En) => "Add review comment",
241 (AddReviewComment, Tr) => "İnceleme yorumu ekle",
242 (StartReview, En) => "Start a review",
243 (StartReview, Tr) => "İnceleme başlat",
244 (CommentLabel, En) => "Comment",
245 (CommentLabel, Tr) => "Yorum",
246 (AddSingleComment, En) => "Add single comment",
247 (AddSingleComment, Tr) => "Tek yorum ekle",
248 (CancelLink, En) => "Cancel",
249 (CancelLink, Tr) => "İptal",
250 (ThisCommit, En) => "this commit",
251 (ThisCommit, Tr) => "bu commit",
252 (CommitStatusPrefix, En) => "Commit status: ",
253 (CommitStatusPrefix, Tr) => "Commit durumu: ",
254 (StateSuccess, En) => "success",
255 (StateSuccess, Tr) => "başarılı",
256 (StateFailure, En) => "failure",
257 (StateFailure, Tr) => "başarısız",
258 (StateError, En) => "error",
259 (StateError, Tr) => "hata",
260 (StatePending, En) => "pending",
261 (StatePending, Tr) => "bekliyor",
262 (NoChecksReported, En) => "No checks reported",
263 (NoChecksReported, Tr) => "Hiç kontrol bildirilmedi",
264 (AllChecksPassed, En) => "All checks have passed",
265 (AllChecksPassed, Tr) => "Tüm kontroller geçti",
266 (ChecksPending, En) => "Checks pending",
267 (ChecksPending, Tr) => "Kontroller bekliyor",
268 (SomeChecksFailed, En) => "Some checks failed",
269 (SomeChecksFailed, Tr) => "Bazı kontroller başarısız oldu",
270 (ShowChecks, En) => "Show checks",
271 (ShowChecks, Tr) => "Kontrolleri göster",
272 (DetailsLink, En) => "Details",
273 (DetailsLink, Tr) => "Ayrıntılar",
274 (AuthorLabel, En) => "Author ",
275 (AuthorLabel, Tr) => "Yazar ",
276 (CommitterLabel, En) => "Committer ",
277 (CommitterLabel, Tr) => "Commit eden ",
278 (RootCommit, En) => "Root commit (no parents)",
279 (RootCommit, Tr) => "Kök commit (üst commit yok)",
280 (ParentLabel, En) => "Parent: ",
281 (ParentLabel, Tr) => "Üst commit: ",
282 (BrowseFiles, En) => "Browse files at this commit",
283 (BrowseFiles, Tr) => "Bu commit'teki dosyalara göz at",
284 (SigVerified, En) => "Verified",
285 (SigVerified, Tr) => "Doğrulandı",
286 (SigUnverified, En) => "Unverified",
287 (SigUnverified, Tr) => "Doğrulanmadı",
288 (CommitsOn, En) => "Commits on ",
289 (CommitsOn, Tr) => "Referanstaki commit'ler: ",
290 (FilteredTo, En) => "Filtered to ",
291 (FilteredTo, Tr) => "Şuna göre filtrelendi: ",
292 (ClearFilter, En) => "Clear filter",
293 (ClearFilter, Tr) => "Filtreyi temizle",
294 (NoCommits, En) => "No commits.",
295 (NoCommits, Tr) => "Commit yok.",
296 (Committed, En) => "committed",
297 (Committed, Tr) => "commit etti",
298 (BrowseFilesShort, En) => "Browse files",
299 (BrowseFilesShort, Tr) => "Dosyalara göz at",
300 (NewerLink, En) => "Newer",
301 (NewerLink, Tr) => "Daha yeni",
302 (OlderLink, En) => "Older",
303 (OlderLink, Tr) => "Daha eski",
304 (NothingHere, En) => "Nothing here yet.",
305 (NothingHere, Tr) => "Henüz burada bir şey yok.",
306 (DefaultBadge, En) => "default",
307 (DefaultBadge, Tr) => "varsayılan",
308 (TagsTitle, En) => "Tags",
309 (TagsTitle, Tr) => "Etiketler",
310 (TagKindLabel, En) => "Tag",
311 (TagKindLabel, Tr) => "Etiket",
312 (ForkedFrom, En) => "forked from ",
313 (ForkedFrom, Tr) => "Şu depodan çatallandı: ",
314 (MirrorOf, En) => "Mirror of ",
315 (MirrorOf, Tr) => "Yansı kaynağı: ",
316 (NotSyncedYet, En) => "not synced yet",
317 (NotSyncedYet, Tr) => "henüz eşitlenmedi",
318 (ForkButton, En) => "Fork",
319 (ForkButton, Tr) => "Çatalla",
320 (StarsAria, En) => "Stars",
321 (StarsAria, Tr) => "Yıldızlar",
322 (ArchivedNotice, En) => "This repository is archived. It is read-only.",
323 (ArchivedNotice, Tr) => "Bu depo arşivlendi. Salt okunurdur.",
324 (RepositoryNav, En) => "Repository",
325 (RepositoryNav, Tr) => "Depo",
326 (TabIssues, En) => "Issues",
327 (TabIssues, Tr) => "Sorunlar",
328 (TabPulls, En) => "Pull requests",
329 (TabPulls, Tr) => "Çekme istekleri",
330 (TabCommits, En) => "Commits",
331 (TabCommits, Tr) => "Commitler",
332 (TabReleases, En) => "Releases",
333 (TabReleases, Tr) => "Sürümler",
334 (TabCi, En) => "CI",
335 (TabCi, Tr) => "CI",
336 (TabDiscussions, En) => "Discussions",
337 (TabDiscussions, Tr) => "Tartışmalar",
338 (TabWiki, En) => "Wiki",
339 (TabWiki, Tr) => "Wiki",
340 (TabSettings, En) => "Settings",
341 (TabSettings, Tr) => "Ayarlar",
342 }
343}
344
345/// `N match(es) in M file(s)` in English, `N eşleşme, M dosyada` in Turkish.
346pub fn match_summary(lang: Lang, matches: usize, files: usize) -> String {
347 match lang {
348 Lang::En => format!(
349 "{matches} match{} in {files} file{}",
350 if matches == 1 { "" } else { "es" },
351 if files == 1 { "" } else { "s" },
352 ),
353 Lang::Tr => format!("{matches} eşleşme, {files} dosyada"),
354 }
355}
356
357/// The notice for a repo with no commits on its default branch.
358pub fn empty_repo_message(lang: Lang, branch: &str) -> String {
359 match lang {
360 Lang::En => format!("This repository has no commits on {branch}. Nothing to search yet."),
361 Lang::Tr => {
362 format!("Bu depoda {branch} dalında commit yok. Henüz aranacak bir şey yok.")
363 }
364 }
365}
366
367/// The label shown for a directory-listing row kind. Kinds without a translation show as they are.
368pub fn kind_label(lang: Lang, kind: &'static str) -> &'static str {
369 let key = match kind {
370 "dir" => K::KindDir,
371 "file" => K::KindFile,
372 "exec" => K::KindExec,
373 "link" => K::KindLink,
374 "submodule" => K::KindSubmodule,
375 _ => return kind,
376 };
377 t(lang, key)
378}
379
380/// The note for a file stored with Git LFS, with its size.
381pub fn lfs_stored(lang: Lang, size: &str) -> String {
382 match lang {
383 Lang::En => format!("Stored with Git LFS ({size})"),
384 Lang::Tr => format!("Git LFS ile saklanıyor ({size})"),
385 }
386}
387
388/// The note for a Git LFS file whose object this forge does not have.
389pub fn lfs_missing(lang: Lang, size: &str) -> String {
390 match lang {
391 Lang::En => {
392 format!("Stored with Git LFS ({size}), but this forge does not have the object")
393 }
394 Lang::Tr => {
395 format!("Git LFS ile saklanıyor ({size}), ancak bu forge sunucusunda bu nesne yok")
396 }
397 }
398}
399
400/// The note for a binary file, with its size in bytes.
401pub fn binary_note(lang: Lang, bytes: impl std::fmt::Display) -> String {
402 match lang {
403 Lang::En => format!("Binary file, {bytes} bytes"),
404 Lang::Tr => format!("İkili dosya, {bytes} bayt"),
405 }
406}
407
408/// `N changed file(s)` in English, `N dosya değişti` in Turkish.
409pub fn changed_files(lang: Lang, count: usize) -> String {
410 match lang {
411 Lang::En => format!("{count} changed file{}", if count == 1 { "" } else { "s" }),
412 Lang::Tr => format!("{count} dosya değişti"),
413 }
414}
415
416/// The note that a diff stops at `max` files. `subject` names what the diff shows.
417pub fn diff_truncated(lang: Lang, max: usize, subject: &str) -> String {
418 match lang {
419 Lang::En => format!("Showing the first {max} files; {subject} changes more."),
420 Lang::Tr => {
421 format!("İlk {max} dosya gösteriliyor; {subject} daha fazla değişiklik içeriyor.")
422 }
423 }
424}
425
426/// The word for a commit status state, as the status title and the checks line use it.
427pub fn state_word(lang: Lang, state: StatusState) -> &'static str {
428 let key = match state {
429 StatusState::Pending => K::StatePending,
430 StatusState::Success => K::StateSuccess,
431 StatusState::Failure => K::StateFailure,
432 StatusState::Error => K::StateError,
433 };
434 t(lang, key)
435}
436
437/// `Signed by <signer> with <key>` in English, the Turkish equivalent otherwise.
438pub fn signed_by(lang: Lang, signer: &str, key: &str) -> String {
439 match lang {
440 Lang::En => format!("Signed by {signer} with {key}"),
441 Lang::Tr => format!("{signer} tarafından {key} ile imzalandı"),
442 }
443}
444
445/// `Page <n>` for the commit list pager.
446pub fn page_label(lang: Lang, page: u32) -> String {
447 match lang {
448 Lang::En => format!("Page {page}"),
449 Lang::Tr => format!("Sayfa {page}"),
450 }
451}
452
453/// The star button label: `Unstar <n>` when starred, `★ Star <n>` otherwise.
454pub fn star_label(lang: Lang, starred: bool, stars: u64) -> String {
455 match (lang, starred) {
456 (Lang::En, true) => format!("Unstar {stars}"),
457 (Lang::En, false) => format!("\u{2605} Star {stars}"),
458 (Lang::Tr, true) => format!("Yıldızı kaldır {stars}"),
459 (Lang::Tr, false) => format!("\u{2605} Yıldızla {stars}"),
460 }
461}
462
463/// `<n> watching` in English, `<n> izleyici` in Turkish.
464pub fn watching_count(lang: Lang, watchers: u64) -> String {
465 match lang {
466 Lang::En => format!("{watchers} watching"),
467 Lang::Tr => format!("{watchers} izleyici"),
468 }
469}
470
471/// The mirror status after a successful sync.
472pub fn mirror_synced(lang: Lang, at: &str) -> String {
473 match lang {
474 Lang::En => format!("last synced {at}"),
475 Lang::Tr => format!("son eşitleme: {at}"),
476 }
477}
478
479/// The mirror status after a failed sync.
480pub fn mirror_sync_failed(lang: Lang, at: &str) -> String {
481 match lang {
482 Lang::En => format!("last sync {at} failed"),
483 Lang::Tr => format!("son eşitleme {at} başarısız oldu"),
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490
491 const ALL: &[K] = &[
492 K::SearchWord,
493 K::SearchFailed,
494 K::SearchCodePlaceholder,
495 K::SearchButton,
496 K::RefField,
497 K::PathField,
498 K::MatchCase,
499 K::RegexOption,
500 K::SearchFilesAt,
501 K::NoMatches,
502 K::ShowingFirst,
503 K::ShowingFirstEnd,
504 K::CloneTitle,
505 K::SshRequiresKey,
506 K::BranchesTitle,
507 K::EmptyRepoPush,
508 K::OverHttps,
509 K::OverSsh,
510 K::DownloadNav,
511 K::DownloadZip,
512 K::DownloadTarGz,
513 K::RecentPushes,
514 K::HadRecentPushes,
515 K::CompareAndPr,
516 K::BranchLabel,
517 K::NameHeader,
518 K::LastCommitHeader,
519 K::AgeHeader,
520 K::KindDir,
521 K::KindFile,
522 K::KindExec,
523 K::KindLink,
524 K::KindSubmodule,
525 K::Rendered,
526 K::SourceToggle,
527 K::HistoryLink,
528 K::RawLink,
529 K::DownloadLink,
530 K::FileNav,
531 K::SymlinkPrefix,
532 K::SubmodulePrefix,
533 K::SubmoduleSuffix,
534 K::TruncatedPrefix,
535 K::ViewFullRaw,
536 K::StatusAdded,
537 K::StatusDeleted,
538 K::StatusModified,
539 K::StatusRenamed,
540 K::StatusCopied,
541 K::StatusTypeChanged,
542 K::NoFileChanges,
543 K::BinaryFileChanged,
544 K::DiffTooLargePrefix,
545 K::ViewFile,
546 K::DiffTooLarge,
547 K::CommentOnLine,
548 K::AddReviewComment,
549 K::StartReview,
550 K::CommentLabel,
551 K::AddSingleComment,
552 K::CancelLink,
553 K::ThisCommit,
554 K::CommitStatusPrefix,
555 K::StateSuccess,
556 K::StateFailure,
557 K::StateError,
558 K::StatePending,
559 K::NoChecksReported,
560 K::AllChecksPassed,
561 K::ChecksPending,
562 K::SomeChecksFailed,
563 K::ShowChecks,
564 K::DetailsLink,
565 K::AuthorLabel,
566 K::CommitterLabel,
567 K::RootCommit,
568 K::ParentLabel,
569 K::BrowseFiles,
570 K::SigVerified,
571 K::SigUnverified,
572 K::CommitsOn,
573 K::FilteredTo,
574 K::ClearFilter,
575 K::NoCommits,
576 K::Committed,
577 K::BrowseFilesShort,
578 K::NewerLink,
579 K::OlderLink,
580 K::NothingHere,
581 K::DefaultBadge,
582 K::TagsTitle,
583 K::TagKindLabel,
584 K::ForkedFrom,
585 K::MirrorOf,
586 K::NotSyncedYet,
587 K::ForkButton,
588 K::StarsAria,
589 K::ArchivedNotice,
590 K::RepositoryNav,
591 K::TabIssues,
592 K::TabPulls,
593 K::TabCommits,
594 K::TabReleases,
595 K::TabCi,
596 K::TabDiscussions,
597 K::TabWiki,
598 K::TabSettings,
599 ];
600
601 #[test]
602 fn every_key_has_text_in_both_languages() {
603 for key in ALL {
604 assert!(!t(Lang::En, *key).is_empty(), "{key:?} has no English text");
605 assert!(!t(Lang::Tr, *key).is_empty(), "{key:?} has no Turkish text");
606 }
607 }
608
609 #[test]
610 fn all_lists_each_key_once() {
611 for (i, key) in ALL.iter().enumerate() {
612 assert!(!ALL[i + 1..].contains(key), "{key:?} is listed twice");
613 }
614 }
615
616 #[test]
617 fn turkish_differs_from_english_for_several_keys() {
618 let differing = ALL
619 .iter()
620 .filter(|key| t(Lang::En, **key) != t(Lang::Tr, **key))
621 .count();
622 assert!(differing >= 3, "only {differing} keys differ");
623 }
624}