forge
ExploreLog in

Tahinli/forge

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