forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
19.5 KiB
1//! Strings for the releases and CI pages. One variant per phrase, an exhaustive `t` match, and
2//! `fmt`-style helpers for sentences that carry numbers or names.
3
4use std::fmt::Display;
5
6use super::Lang;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum K {
10 // Repo home page: the latest release card.
11 LatestReleaseHeading,
12
13 // CI notices, shown after a run action.
14 CiNoticeStarted,
15 CiNoticeCancelled,
16 CiNoticeApproved,
17 CiNoticeRerun,
18 CiNoticeFinished,
19 CiNoticeNotWaiting,
20 CiNoticeNoBranch,
21 CiNoticeNoManual,
22
23 // CI run list and run page.
24 RunWorkflow,
25 RunWorkflowHelp,
26 Branch,
27 ApproveAndRun,
28 Cancel,
29 Rerun,
30 Runs,
31 NoRunsYet,
32 Jobs,
33 NoJobs,
34 ColRun,
35 ColState,
36 ColTrigger,
37 ColRef,
38 ColCommit,
39 ColActor,
40 ColAge,
41 ColJob,
42 ColDuration,
43 ColRunner,
44 ColMessage,
45 Newer,
46 Older,
47 DeletedUser,
48 RunNumber,
49 Started,
50 Finished,
51 Runner,
52 Exit,
53 Log,
54 FullLog,
55 LogTruncated,
56 Artifacts,
57
58 // CI status badge, on the run list.
59 BadgeHeading,
60 BadgeHelp,
61 BadgeSnippet,
62
63 // CI state words.
64 StateWaitingApproval,
65 StateQueued,
66 StateRunning,
67 StateSuccess,
68 StateFailure,
69 StateCancelled,
70 StateError,
71 StateBlocked,
72 StateSkipped,
73
74 // Release notices, shown after a release action.
75 RelSaved,
76 RelDeleted,
77 RelAssetUploaded,
78 RelAssetDeleted,
79 RelAssetTooLarge,
80 RelAssetExists,
81 RelAssetName,
82 RelAssetInvalid,
83 RelConfirm,
84 RelInvalid,
85 RelAssetEmpty,
86
87 // Release form errors.
88 RelErrTagName,
89 RelErrReleaseExists,
90 RelErrChooseBranch,
91
92 // Release pages.
93 Releases,
94 NewRelease,
95 EditRelease,
96 SaveRelease,
97 TagHint,
98 Tag,
99 TargetBranch,
100 Title,
101 ReleaseNotes,
102 PrereleaseHelp,
103 DraftHelp,
104 PreRelease,
105 Draft,
106 Latest,
107 NoReleasesYet,
108 NoAssetsYet,
109 NoAssets,
110 File,
111 Size,
112 Downloads,
113 Edit,
114 Assets,
115 AllReleases,
116 SourceCode,
117 Confirm,
118 DeleteRelease,
119 BackToRelease,
120 UploadAsset,
121 DeleteReleaseHelp,
122 YesDeleteRelease,
123}
124
125pub fn t(lang: Lang, key: K) -> &'static str {
126 use K::*;
127 use Lang::*;
128 match (key, lang) {
129 (LatestReleaseHeading, En) => "Latest release",
130 (LatestReleaseHeading, Tr) => "Son sürüm",
131 (CiNoticeStarted, En) => "Workflow run queued.",
132 (CiNoticeStarted, Tr) => "İş akışı çalıştırması sıraya alındı.",
133 (CiNoticeCancelled, En) => {
134 "Cancellation requested. Queued jobs were cancelled; running jobs stop at their next heartbeat."
135 }
136 (CiNoticeCancelled, Tr) => {
137 "İptal istendi. Sıradaki işler iptal edildi; çalışan işler bir sonraki kalp atışında duracak."
138 }
139 (CiNoticeApproved, En) => "Run approved. Its jobs are queued.",
140 (CiNoticeApproved, Tr) => "Çalıştırma onaylandı. İşler sıraya alındı.",
141 (CiNoticeRerun, En) => "A new run was created from the same commit.",
142 (CiNoticeRerun, Tr) => "Aynı commit'ten yeni bir çalıştırma oluşturuldu.",
143 (CiNoticeFinished, En) => "This run has already finished. Nothing was changed.",
144 (CiNoticeFinished, Tr) => "Bu çalıştırma zaten tamamlanmış. Hiçbir şey değiştirilmedi.",
145 (CiNoticeNotWaiting, En) => "This run is not waiting for approval. Nothing was changed.",
146 (CiNoticeNotWaiting, Tr) => "Bu çalıştırma onay beklemiyor. Hiçbir şey değiştirilmedi.",
147 (CiNoticeNoBranch, En) => "Choose a branch of this repository.",
148 (CiNoticeNoBranch, Tr) => "Bu depodaki bir dal seçin.",
149 (CiNoticeNoManual, En) => {
150 "Nothing was started: the branch has no usable workflow file, or the workflow does not allow manual runs."
151 }
152 (CiNoticeNoManual, Tr) => {
153 "Hiçbir şey başlatılmadı: dalda kullanılabilir bir iş akışı dosyası yok ya da iş akışı elle çalıştırmaya izin vermiyor."
154 }
155
156 (RunWorkflow, En) => "Run workflow",
157 (RunWorkflow, Tr) => "İş akışını çalıştır",
158 (RunWorkflowHelp, En) => {
159 "Starts the workflow on a branch's head, if its .forge/ci.toml allows manual runs."
160 }
161 (RunWorkflowHelp, Tr) => {
162 "Bir dalın ucundaki iş akışını başlatır; .forge/ci.toml dosyası elle çalıştırmaya izin veriyorsa."
163 }
164 (Branch, En) => "Branch",
165 (Branch, Tr) => "Dal",
166 (ApproveAndRun, En) => "Approve and run",
167 (ApproveAndRun, Tr) => "Onayla ve çalıştır",
168 (Cancel, En) => "Cancel",
169 (Cancel, Tr) => "İptal et",
170 (Rerun, En) => "Re-run",
171 (Rerun, Tr) => "Yeniden çalıştır",
172 (Runs, En) => "Runs",
173 (Runs, Tr) => "Çalıştırmalar",
174 (NoRunsYet, En) => "No runs yet.",
175 (NoRunsYet, Tr) => "Henüz çalıştırma yok.",
176 (Jobs, En) => "Jobs",
177 (Jobs, Tr) => "İşler",
178 (NoJobs, En) => "No jobs.",
179 (NoJobs, Tr) => "İş yok.",
180 (ColRun, En) => "Run",
181 (ColRun, Tr) => "Çalıştırma",
182 (ColState, En) => "State",
183 (ColState, Tr) => "Durum",
184 (ColTrigger, En) => "Trigger",
185 (ColTrigger, Tr) => "Tetikleyici",
186 (ColRef, En) => "Ref",
187 (ColRef, Tr) => "Referans",
188 (ColCommit, En) => "Commit",
189 (ColCommit, Tr) => "Commit",
190 (ColActor, En) => "Actor",
191 (ColActor, Tr) => "Kullanıcı",
192 (ColAge, En) => "Age",
193 (ColAge, Tr) => "Zaman",
194 (ColJob, En) => "Job",
195 (ColJob, Tr) => "İş",
196 (ColDuration, En) => "Duration",
197 (ColDuration, Tr) => "Süre",
198 (ColRunner, En) => "Runner",
199 (ColRunner, Tr) => "Çalıştırıcı",
200 (ColMessage, En) => "Message",
201 (ColMessage, Tr) => "Mesaj",
202 (Newer, En) => "Newer",
203 (Newer, Tr) => "Daha yeni",
204 (Older, En) => "Older",
205 (Older, Tr) => "Daha eski",
206 (DeletedUser, En) => "deleted user",
207 (DeletedUser, Tr) => "silinmiş kullanıcı",
208 (RunNumber, En) => "Run #",
209 (RunNumber, Tr) => "Çalıştırma #",
210 (Started, En) => "Started",
211 (Started, Tr) => "Başlangıç",
212 (Finished, En) => "Finished",
213 (Finished, Tr) => "Bitiş",
214 (Runner, En) => "runner",
215 (Runner, Tr) => "çalıştırıcı",
216 (Exit, En) => "exit",
217 (Exit, Tr) => "çıkış",
218 (Log, En) => "Log",
219 (Log, Tr) => "Günlük",
220 (FullLog, En) => "Full log (log.txt)",
221 (FullLog, Tr) => "Tam günlük (log.txt)",
222 (LogTruncated, En) => "Showing the last 512 KiB of the log. The full log is linked above.",
223 (LogTruncated, Tr) => {
224 "Günlüğün son 512 KiB'ı gösteriliyor. Tam günlük yukarıda bağlantılı."
225 }
226 (Artifacts, En) => "Artifacts",
227 (Artifacts, Tr) => "Yapıtlar",
228 (BadgeHeading, En) => "Status badge",
229 (BadgeHeading, Tr) => "Durum rozeti",
230 (BadgeHelp, En) => {
231 "Embed this image in a README to show the newest run on the branch. It refreshes on every load."
232 }
233 (BadgeHelp, Tr) => {
234 "Bu resmi bir README'ye ekleyin; dalın en son çalıştırmasını gösterir. Her yüklemede yenilenir."
235 }
236 (BadgeSnippet, En) => "Markdown",
237 (BadgeSnippet, Tr) => "Markdown",
238
239 (StateWaitingApproval, En) => "waiting approval",
240 (StateWaitingApproval, Tr) => "onay bekliyor",
241 (StateQueued, En) => "queued",
242 (StateQueued, Tr) => "sırada",
243 (StateRunning, En) => "running",
244 (StateRunning, Tr) => "çalışıyor",
245 (StateSuccess, En) => "success",
246 (StateSuccess, Tr) => "başarılı",
247 (StateFailure, En) => "failure",
248 (StateFailure, Tr) => "başarısız",
249 (StateCancelled, En) => "cancelled",
250 (StateCancelled, Tr) => "iptal edildi",
251 (StateError, En) => "error",
252 (StateError, Tr) => "hata",
253 (StateBlocked, En) => "blocked",
254 (StateBlocked, Tr) => "engellendi",
255 (StateSkipped, En) => "skipped",
256 (StateSkipped, Tr) => "atlandı",
257
258 (RelSaved, En) => "Release saved.",
259 (RelSaved, Tr) => "Sürüm kaydedildi.",
260 (RelDeleted, En) => "Release deleted. The tag was kept.",
261 (RelDeleted, Tr) => "Sürüm silindi. Etiket korundu.",
262 (RelAssetUploaded, En) => "Asset uploaded.",
263 (RelAssetUploaded, Tr) => "Dosya yüklendi.",
264 (RelAssetDeleted, En) => "Asset deleted.",
265 (RelAssetDeleted, Tr) => "Dosya silindi.",
266 (RelAssetTooLarge, En) => {
267 "The file is larger than this instance allows for a release asset."
268 }
269 (RelAssetTooLarge, Tr) => {
270 "Dosya, bu sunucunun sürüm dosyaları için izin verdiğinden büyük."
271 }
272 (RelAssetExists, En) => {
273 "An asset with this file name already exists on the release. Nothing was changed."
274 }
275 (RelAssetExists, Tr) => {
276 "Bu sürümde bu adı taşıyan bir dosya zaten var. Hiçbir şey değiştirilmedi."
277 }
278 (RelAssetName, En) => {
279 "The file name may only contain letters, digits, and . _ - +, and cannot start with a dot."
280 }
281 (RelAssetName, Tr) => {
282 "Dosya adı yalnızca harf, rakam ve . _ - + karakterlerini içerebilir ve nokta ile başlayamaz."
283 }
284 (RelAssetInvalid, En) => "The upload could not be read. Nothing was changed; try again.",
285 (RelAssetInvalid, Tr) => {
286 "Yüklenen dosya okunamadı. Hiçbir şey değiştirilmedi; yeniden deneyin."
287 }
288 (RelConfirm, En) => "Tick the confirmation box to delete the release. Nothing was deleted.",
289 (RelConfirm, Tr) => "Sürümü silmek için onay kutusunu işaretleyin. Hiçbir şey silinmedi.",
290 (RelInvalid, En) => {
291 "Enter a title of up to 200 characters and release notes of up to 65536 characters. Nothing was changed."
292 }
293 (RelInvalid, Tr) => {
294 "En fazla 200 karakterlik bir başlık ve en fazla 65536 karakterlik sürüm notları girin. Hiçbir şey değiştirilmedi."
295 }
296 (RelAssetEmpty, En) => "Choose a file to upload. Nothing was changed.",
297 (RelAssetEmpty, Tr) => "Yüklemek için bir dosya seçin. Hiçbir şey değiştirilmedi.",
298
299 (RelErrTagName, En) => {
300 "Enter a tag name using letters, digits, and . _ - + (no slashes), up to 100 characters."
301 }
302 (RelErrTagName, Tr) => {
303 "En fazla 100 karakterlik bir etiket adı girin; yalnızca harf, rakam ve . _ - + kullanın, eğik çizgi kullanmayın."
304 }
305 (RelErrReleaseExists, En) => {
306 "A release already exists for this tag. Edit that release instead."
307 }
308 (RelErrReleaseExists, Tr) => {
309 "Bu etiket için zaten bir sürüm var. Bunun yerine o sürümü düzenleyin."
310 }
311 (RelErrChooseBranch, En) => "Choose a branch to create the tag on.",
312 (RelErrChooseBranch, Tr) => "Etiketin oluşturulacağı bir dal seçin.",
313
314 (Releases, En) => "Releases",
315 (Releases, Tr) => "Sürümler",
316 (NewRelease, En) => "New release",
317 (NewRelease, Tr) => "Yeni sürüm",
318 (EditRelease, En) => "Edit release",
319 (EditRelease, Tr) => "Sürümü düzenle",
320 (SaveRelease, En) => "Save release",
321 (SaveRelease, Tr) => "Sürümü kaydet",
322 (TagHint, En) => {
323 "Use letters, digits, and . _ - +. Slashes are not allowed. If the tag does not exist yet, it is created at the head of the branch you choose."
324 }
325 (TagHint, Tr) => {
326 "Harf, rakam ve . _ - + kullanın; eğik çizgi kullanılamaz. Etiket yoksa, seçtiğiniz dalın ucunda oluşturulur."
327 }
328 (Tag, En) => "Tag",
329 (Tag, Tr) => "Etiket",
330 (TargetBranch, En) => "Target branch (used only when the tag is created)",
331 (TargetBranch, Tr) => "Hedef dal (yalnızca etiket oluşturulurken kullanılır)",
332 (Title, En) => "Title",
333 (Title, Tr) => "Başlık",
334 (ReleaseNotes, En) => "Release notes (Markdown)",
335 (ReleaseNotes, Tr) => "Sürüm notları (Markdown)",
336 (PrereleaseHelp, En) => "Pre-release: never shown as the latest release",
337 (PrereleaseHelp, Tr) => "Ön sürüm: asla en son sürüm olarak gösterilmez",
338 (DraftHelp, En) => "Draft: visible only to people who can write to the repository",
339 (DraftHelp, Tr) => "Taslak: yalnızca depoya yazabilen kişiler görebilir",
340 (PreRelease, En) => "Pre-release",
341 (PreRelease, Tr) => "Ön sürüm",
342 (Draft, En) => "Draft",
343 (Draft, Tr) => "Taslak",
344 (Latest, En) => "Latest",
345 (Latest, Tr) => "En son",
346 (NoReleasesYet, En) => "No releases yet.",
347 (NoReleasesYet, Tr) => "Henüz sürüm yok.",
348 (NoAssetsYet, En) => "No assets yet.",
349 (NoAssetsYet, Tr) => "Henüz dosya yok.",
350 (NoAssets, En) => "No assets.",
351 (NoAssets, Tr) => "Dosya yok.",
352 (File, En) => "File",
353 (File, Tr) => "Dosya",
354 (Size, En) => "Size",
355 (Size, Tr) => "Boyut",
356 (Downloads, En) => "Downloads",
357 (Downloads, Tr) => "İndirmeler",
358 (Edit, En) => "Edit",
359 (Edit, Tr) => "Düzenle",
360 (Assets, En) => "Assets",
361 (Assets, Tr) => "Dosyalar",
362 (AllReleases, En) => "All releases",
363 (AllReleases, Tr) => "Tüm sürümler",
364 (SourceCode, En) => "Source code",
365 (SourceCode, Tr) => "Kaynak kodu",
366 (Confirm, En) => "Confirm",
367 (Confirm, Tr) => "Onayla",
368 (DeleteRelease, En) => "Delete release",
369 (DeleteRelease, Tr) => "Sürümü sil",
370 (BackToRelease, En) => "Back to the release",
371 (BackToRelease, Tr) => "Sürüme dön",
372 (UploadAsset, En) => "Upload asset",
373 (UploadAsset, Tr) => "Dosya yükle",
374 (DeleteReleaseHelp, En) => {
375 "Deleting removes the release and its assets. The git tag is kept."
376 }
377 (DeleteReleaseHelp, Tr) => "Sürümü ve dosyalarını siler. Git etiketi korunur.",
378 (YesDeleteRelease, En) => "Yes, delete this release",
379 (YesDeleteRelease, Tr) => "Evet, bu sürümü sil",
380 }
381}
382
383/// "Page 2".
384pub fn page_label(lang: Lang, page: u32) -> String {
385 match lang {
386 Lang::En => format!("Page {page}"),
387 Lang::Tr => format!("Sayfa {page}"),
388 }
389}
390
391/// "1m 5s".
392pub fn duration_minutes(lang: Lang, minutes: i64, secs: i64) -> String {
393 match lang {
394 Lang::En => format!("{minutes}m {secs}s"),
395 Lang::Tr => format!("{minutes} dk {secs} sn"),
396 }
397}
398
399/// "9s".
400pub fn duration_seconds(lang: Lang, secs: i64) -> String {
401 match lang {
402 Lang::En => format!("{secs}s"),
403 Lang::Tr => format!("{secs} sn"),
404 }
405}
406
407/// "3 downloads".
408pub fn download_count(lang: Lang, count: u64) -> String {
409 match lang {
410 Lang::En => format!("{count} downloads"),
411 Lang::Tr => format!("{count} indirme"),
412 }
413}
414
415/// The title length refusal, with the limit.
416pub fn title_too_long(lang: Lang, max: usize) -> String {
417 match lang {
418 Lang::En => format!("Enter a title of up to {max} characters."),
419 Lang::Tr => format!("En fazla {max} karakterlik bir başlık girin."),
420 }
421}
422
423/// The release notes length refusal, with the limit.
424pub fn body_too_long(lang: Lang, max: usize) -> String {
425 match lang {
426 Lang::En => format!("The release notes can be at most {max} characters."),
427 Lang::Tr => format!("Sürüm notları en fazla {max} karakter olabilir."),
428 }
429}
430
431/// "Edit v1.0", the edit page's title part.
432pub fn edit_title(lang: Lang, tag: &str) -> String {
433 match lang {
434 Lang::En => format!("Edit {tag}"),
435 Lang::Tr => format!("{tag} sürümünü düzenle"),
436 }
437}
438
439/// The upload limit hint under the assets heading.
440pub fn upload_hint(lang: Lang, max_mb: impl Display) -> String {
441 match lang {
442 Lang::En => format!(
443 "Up to {max_mb} MiB per file. Names may contain letters, digits, and . _ - +. Files are served as downloads."
444 ),
445 Lang::Tr => format!(
446 "Dosya başına en fazla {max_mb} MiB. Adlar harf, rakam ve . _ - + içerebilir. Dosyalar indirme olarak sunulur."
447 ),
448 }
449}
450
451#[cfg(test)]
452mod tests {
453 use super::*;
454
455 const ALL: &[K] = &[
456 K::LatestReleaseHeading,
457 K::CiNoticeStarted,
458 K::CiNoticeCancelled,
459 K::CiNoticeApproved,
460 K::CiNoticeRerun,
461 K::CiNoticeFinished,
462 K::CiNoticeNotWaiting,
463 K::CiNoticeNoBranch,
464 K::CiNoticeNoManual,
465 K::RunWorkflow,
466 K::RunWorkflowHelp,
467 K::Branch,
468 K::ApproveAndRun,
469 K::Cancel,
470 K::Rerun,
471 K::Runs,
472 K::NoRunsYet,
473 K::Jobs,
474 K::NoJobs,
475 K::ColRun,
476 K::ColState,
477 K::ColTrigger,
478 K::ColRef,
479 K::ColCommit,
480 K::ColActor,
481 K::ColAge,
482 K::ColJob,
483 K::ColDuration,
484 K::ColRunner,
485 K::ColMessage,
486 K::Newer,
487 K::Older,
488 K::DeletedUser,
489 K::RunNumber,
490 K::Started,
491 K::Finished,
492 K::Runner,
493 K::Exit,
494 K::Log,
495 K::FullLog,
496 K::LogTruncated,
497 K::Artifacts,
498 K::BadgeHeading,
499 K::BadgeHelp,
500 K::BadgeSnippet,
501 K::StateWaitingApproval,
502 K::StateQueued,
503 K::StateRunning,
504 K::StateSuccess,
505 K::StateFailure,
506 K::StateCancelled,
507 K::StateError,
508 K::StateBlocked,
509 K::StateSkipped,
510 K::RelSaved,
511 K::RelDeleted,
512 K::RelAssetUploaded,
513 K::RelAssetDeleted,
514 K::RelAssetTooLarge,
515 K::RelAssetExists,
516 K::RelAssetName,
517 K::RelAssetInvalid,
518 K::RelConfirm,
519 K::RelInvalid,
520 K::RelAssetEmpty,
521 K::RelErrTagName,
522 K::RelErrReleaseExists,
523 K::RelErrChooseBranch,
524 K::Releases,
525 K::NewRelease,
526 K::EditRelease,
527 K::SaveRelease,
528 K::TagHint,
529 K::Tag,
530 K::TargetBranch,
531 K::Title,
532 K::ReleaseNotes,
533 K::PrereleaseHelp,
534 K::DraftHelp,
535 K::PreRelease,
536 K::Draft,
537 K::Latest,
538 K::NoReleasesYet,
539 K::NoAssetsYet,
540 K::NoAssets,
541 K::File,
542 K::Size,
543 K::Downloads,
544 K::Edit,
545 K::Assets,
546 K::AllReleases,
547 K::SourceCode,
548 K::Confirm,
549 K::DeleteRelease,
550 K::BackToRelease,
551 K::UploadAsset,
552 K::DeleteReleaseHelp,
553 K::YesDeleteRelease,
554 ];
555
556 #[test]
557 fn every_key_has_text_in_both_languages() {
558 for key in ALL {
559 assert!(!t(Lang::En, *key).is_empty(), "{key:?} has no English");
560 assert!(!t(Lang::Tr, *key).is_empty(), "{key:?} has no Turkish");
561 }
562 }
563
564 #[test]
565 fn turkish_differs_from_english_for_translated_keys() {
566 let differing = ALL
567 .iter()
568 .filter(|key| t(Lang::En, **key) != t(Lang::Tr, **key))
569 .count();
570 assert!(differing >= 3);
571 assert_eq!(t(Lang::Tr, K::Releases), "Sürümler");
572 assert_eq!(t(Lang::En, K::Releases), "Releases");
573 }
574
575 #[test]
576 fn counted_sentences_read_in_both_languages() {
577 assert_eq!(download_count(Lang::En, 3), "3 downloads");
578 assert_eq!(download_count(Lang::Tr, 3), "3 indirme");
579 assert_eq!(duration_minutes(Lang::En, 1, 5), "1m 5s");
580 assert_eq!(duration_minutes(Lang::Tr, 1, 5), "1 dk 5 sn");
581 assert_eq!(page_label(Lang::Tr, 2), "Sayfa 2");
582 }
583}