@azure-id/orc 1.2.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,22 @@
1
- {
2
- "nav.overview": "Overview",
3
- "nav.settings": "Settings",
4
- "nav.lanes": "Lanes",
5
- "nav.runs": "Runs",
6
- "nav.knowledge": "Knowledge",
7
- "nav.stats": "Stats",
8
- "nav.flow": "Flow",
9
- "nav.crosslink": "Crosslink",
10
- "nav.learn": "Learn",
11
- "nav.mockrun": "Mocked Skill Use",
12
- "nav.experiment": "Experiment",
13
- "nav.maintenance": "Maintenance",
14
- "nav.pact": "Promises",
15
- "nav.boundary": "Boundary",
16
- "nav.handoff": "Self-serve",
17
- "nav.challenge": "Challenge",
18
- "nav.extra": "Extra",
19
- "nav.wait": "Wait",
20
- "nav.docs": "Docs"
21
- }
1
+ {
2
+ "nav.overview": "Overview",
3
+ "nav.settings": "Settings",
4
+ "nav.lanes": "Lanes",
5
+ "nav.runs": "Runs",
6
+ "nav.knowledge": "Knowledge",
7
+ "nav.stats": "Stats",
8
+ "nav.flow": "Flow",
9
+ "nav.crosslink": "Crosslink",
10
+ "nav.learn": "Learn",
11
+ "nav.mockrun": "Mocked Skill Use",
12
+ "nav.experiment": "Experiment",
13
+ "nav.maintenance": "Maintenance",
14
+ "nav.pact": "Promises",
15
+ "nav.boundary": "Boundary",
16
+ "nav.handoff": "Self-serve",
17
+ "nav.challenge": "Challenge",
18
+ "nav.extra": "Extra",
19
+ "nav.wait": "Wait",
20
+ "nav.docs": "Docs",
21
+ "nav.hookui": "CLI Hook Interface"
22
+ }
@@ -88,5 +88,8 @@
88
88
  "overview.extraOrphan.chip": "{n} dispatch",
89
89
  "overview.extraOrphan.chipPlural": "{n} dispatches",
90
90
  "overview.extraOrphan.slug": "never reported back",
91
- "overview.extraOrphan.where": "Extra · Recovery"
91
+ "overview.extraOrphan.where": "Extra · Recovery",
92
+ "overview.item.statuslineOrphaned.cta": "Open the CLI Hook Interface",
93
+ "overview.item.statuslineInvalid.cta": "Open the CLI Hook Interface",
94
+ "overview.item.statuslineUnreadable.cta": "Open the CLI Hook Interface"
92
95
  }
@@ -29,5 +29,7 @@
29
29
  "tour.13.title": "A long document, in one picture",
30
30
  "tour.13.text": "Each block is a section, sized by how long it is and coloured by its state. Nothing here loads the document itself - ORC works from this map instead, which is why a long document does not end the session.",
31
31
  "tour.14.title": "Work that runs somewhere else",
32
- "tour.14.text": "One line from nothing to a hundred: how hard a task scored. Every part of it shows where that work actually runs — Claude in blue, a provider you connected in green. A range you have not connected keeps its slot, so \"I left the hard work on Claude on purpose\" never looks like \"there is no hard work\". Nothing leaves this machine until you connect something, test it, and press Apply."
32
+ "tour.14.text": "One line from nothing to a hundred: how hard a task scored. Every part of it shows where that work actually runs — Claude in blue, a provider you connected in green. A range you have not connected keeps its slot, so \"I left the hard work on Claude on purpose\" never looks like \"there is no hard work\". Nothing leaves this machine until you connect something, test it, and press Apply.",
33
+ "tour.15.title": "Build your own status line",
34
+ "tour.15.text": "Three lines, each holding up to five parts. Line 1 must have something before line 2 can. The preview at the top is exactly what your terminal will show — it is drawn by the same code the bar runs."
33
35
  }
@@ -0,0 +1,180 @@
1
+ {
2
+ "hookui.title": "Antarmuka CLI Hook",
3
+ "hookui.sub": "Bangun baris status ORC. Tiga baris. Tiap baris memuat sampai lima bagian.",
4
+ "hookui.noData": "Baris status tidak dapat dibaca.",
5
+ "hookui.gate": "Status",
6
+ "hookui.on": "hidup",
7
+ "hookui.off": "mati",
8
+ "hookui.saved": "tata letak tersimpan",
9
+ "hookui.gateOnNote": "Baris Anda yang tampil. Dua baris bawaan ORC dimatikan.",
10
+ "hookui.gateOffNote": "ORC menampilkan dua baris bawaannya. Bangun tata letak di bawah, lalu aktifkan ini. Tidak ada yang berubah sampai Anda melakukannya.",
11
+ "hookui.turnOn": "Aktifkan",
12
+ "hookui.turnOff": "Nonaktifkan",
13
+ "hookui.switchFailed": "Saklar tidak dapat diubah.",
14
+ "hookui.cautions": "Peringatan",
15
+
16
+ "hookui.preview": "Pratinjau",
17
+ "hookui.previewAbout": "Inilah barisnya, digambar persis seperti yang akan digambar terminal Anda. Tombol di kanan mengatur lebar terminal, dalam sel karakter: 80 jendela sempit, 120 jendela biasa, 160 jendela lebar. Bagian yang Anda sembunyikan pada terminal sempit akan hilang di 80.",
18
+ "hookui.previewStale": "Ada perubahan yang belum disimpan. Gambar ini menampilkan tata letak yang tersimpan. Tekan Terapkan di bagian bawah halaman agar perubahan Anda masuk ke dalamnya.",
19
+ "hookui.previewUnavailable": "Pratinjau tidak dapat digambar sampai tata letak sah.",
20
+ "hookui.fixturesAbout": "Pilih saat yang digambar. Baris terlihat berbeda ketika ada proses berjalan, ketika kuota hampir habis, dan ketika tidak ada apa-apa — jadi Anda bisa memeriksa semuanya di sini.",
21
+ "hookui.cols": "lebar {n} sel",
22
+ "hookui.colsPlural": "lebar {n} sel",
23
+ "hookui.degrades": "Tata letak yang sama, dalam tiga bentuk yang dapat dipaksakan terminal.",
24
+ "hookui.degNoColor": "tanpa warna",
25
+ "hookui.degAscii": "teks polos",
26
+ "hookui.degNoMotion": "tanpa gerak",
27
+ "hookui.cells": "lebar {n} sel",
28
+ "hookui.cellsPlural": "lebar {n} sel",
29
+
30
+ "hookui.board": "Papan",
31
+ "hookui.boardAbout": "Inilah baris Anda. Seret sebuah bagian untuk memindahkannya, atau pakai tombol di atasnya. Menambah, mengubah, memindahkan dan menghapus semuanya terjadi di sini — daftar di bawah hanya memberi tahu apa isi tiap bagian.",
32
+ "hookui.dragHint": "Seret sebuah bagian dari pegangannya untuk memindahkannya di dalam satu baris atau ke baris lain. Atau tekan Tab untuk mencapai sebuah bagian lalu pakai tombol panah.",
33
+ "hookui.lineN": "Baris {n}",
34
+ "hookui.lineNPlural": "Baris {n}",
35
+ "hookui.slotsUsed": "{n} dari {max} slot terpakai",
36
+ "hookui.slotsUsedPlural": "{n} dari {max} slot terpakai",
37
+ "hookui.add": "+ tambah bagian",
38
+ "hookui.fillFirst": "Isi baris {n} lebih dulu.",
39
+ "hookui.lineFull": "Baris {n} penuh. Sudah memuat {max} bagian. Lepas satu dulu.",
40
+ "hookui.noSuchLine": "Tidak ada baris seperti itu di papan ini.",
41
+ "hookui.applyFirst": "Terapkan atau buang perubahan Anda lebih dulu.",
42
+
43
+ "hookui.separator": "Antara bagian",
44
+ "hookui.sepCustom": "milik Anda: {s}",
45
+ "hookui.opSep": "baris {n}: bagian dipisah dengan {s}",
46
+
47
+ "hookui.edit": "Ubah",
48
+ "hookui.move": "Pindah",
49
+ "hookui.remove": "Hapus",
50
+ "hookui.swap": "Pakai bagian lain di slot ini",
51
+
52
+ "hookui.opAdd": "tambah {id} ke baris {n}",
53
+ "hookui.opRemove": "hapus {id}",
54
+ "hookui.opMove": "pindah {id} ke baris {n}",
55
+ "hookui.opClone": "salin {id}",
56
+ "hookui.opSwap": "pakai {id} di slot ini",
57
+
58
+ "hookui.pickerTitle": "Tambah bagian ke baris {n}",
59
+ "hookui.pickerTitlePlural": "Tambah bagian ke baris {n}",
60
+ "hookui.pickerAbout": "Pilih satu. Bagian itu masuk ke ujung baris {n}. Tidak ada yang tersimpan sampai Anda menekan Terapkan.",
61
+ "hookui.pickerAboutPlural": "Pilih satu. Bagian itu masuk ke ujung baris {n}. Tidak ada yang tersimpan sampai Anda menekan Terapkan.",
62
+ "hookui.pickerReplaceTitle": "Pakai bagian lain",
63
+ "hookui.pickerReplaceAbout": "Pilih bagian yang seharusnya menempati slot ini. Slot tetap di tempatnya pada baris.",
64
+ "hookui.searchPlaceholder": "cari",
65
+ "hookui.matches": "{n} cocok",
66
+ "hookui.matchesPlural": "{n} cocok",
67
+ "hookui.noMatch": "Tidak ada yang cocok.",
68
+
69
+ "hookui.moveTitle": "Pindahkan bagian ini",
70
+ "hookui.moveAbout": "Pilih ke mana {id} harus pergi. Slot 1 adalah ujung kiri sebuah baris.",
71
+ "hookui.slotN": "slot {n}",
72
+ "hookui.slotNPlural": "slot {n}",
73
+ "hookui.alreadyHere": "Sudah ada di sini.",
74
+
75
+ "hookui.removeTitle": "Hapus bagian ini?",
76
+ "hookui.removeAbout": "{id} dilepas dari baris. Tidak ada yang tersimpan sampai Anda menekan Terapkan, jadi Anda masih bisa membatalkannya.",
77
+
78
+ "hookui.unknownComponent": "Versi ORC ini tidak memiliki bagian tersebut.",
79
+ "hookui.shape": "Bentuk",
80
+ "hookui.shapeAbout": "Bagaimana bagian ini digambar. Setiap pilihan di bawah digambar dengan nilai asli bagian ini, jadi Anda bisa melihatnya sebelum memilih. Memilih satu akan menutup jendela ini.",
81
+ "hookui.shapeChange": "bentuk {id} = {r}",
82
+ "hookui.glyphs": "Simbol",
83
+ "hookui.glyphsAbout": "Dari kumpulan simbol mana batang dan tanda digambar. Sebagian terminal dan huruf tidak dapat menggambar semuanya.",
84
+ "hookui.glyphChange": "simbol {id} = {v}",
85
+ "hookui.words": "Kata",
86
+ "hookui.wordsAbout": "Teks di sekitar nilai.",
87
+ "hookui.label": "Nama",
88
+ "hookui.labelAbout": "Kata pendek yang dicetak di depan nilai. Kosongkan agar tidak ada nama sama sekali.",
89
+ "hookui.labelPlaceholder": "ketik nama apa pun",
90
+ "hookui.labelChange": "nama {id} = \"{v}\"",
91
+ "hookui.case": "Huruf",
92
+ "hookui.caseAbout": "Apakah nama dicetak dengan huruf besar, huruf kecil, atau persis seperti yang Anda ketik.",
93
+ "hookui.caseChange": "huruf {id} = {v}",
94
+ "hookui.before": "Sebelum",
95
+ "hookui.beforeAbout": "Teks yang dicetak tepat sebelum bagian ini. Pakai untuk kurung atau spasi.",
96
+ "hookui.beforeChange": "sebelum {id} = \"{v}\"",
97
+ "hookui.after": "Sesudah",
98
+ "hookui.afterAbout": "Teks yang dicetak tepat sesudah bagian ini.",
99
+ "hookui.afterChange": "sesudah {id} = \"{v}\"",
100
+
101
+ "hookui.colour": "Warna",
102
+ "hookui.colourAbout": "Slot warna mana yang harus dipakai terminal Anda untuk bagian ini. ORC tidak pernah mengirim warna tetap, jadi baris selalu mengikuti warna terminal Anda sendiri.",
103
+ "hookui.labelColour": "Warna nama",
104
+ "hookui.labelColourAbout": "Warna kata pendek di depan nilai.",
105
+ "hookui.valueColour": "Warna nilai",
106
+ "hookui.valueColourAbout": "Warna nilainya sendiri.",
107
+ "hookui.colourChange": "warna {id} = {v}",
108
+ "hookui.ramp": "Warna mengikuti nilai",
109
+ "hookui.rampAbout": "Biarkan warna berubah mengikuti angka, sehingga sebuah batang berubah saat terisi. Tiap pilihan menyebut arah mana yang buruk.",
110
+ "hookui.rampChange": "warna mengikuti nilai {id} = {v}",
111
+ "hookui.stateColourWarn": "Bagian ini menyampaikan sesuatu lewat warnanya ({s}). Warna tetap menyembunyikannya.",
112
+ "hookui.emphasis": "Ketebalan",
113
+ "hookui.emphasisAbout": "Tebal, samar, atau salah satu hal lain yang bisa dilakukan terminal pada teks.",
114
+ "hookui.emphasisChange": "ketebalan {id} = {v}",
115
+ "hookui.fontWhy": "Terminal Anda yang menentukan ukuran huruf. ORC tidak dapat mengubahnya. Tebal terlihat lebih besar dan samar terlihat lebih kecil. Untuk membuat sebuah bagian memakan ruang lebih banyak, beri ia lebih banyak sel.",
116
+
117
+ "hookui.numbers": "Angka",
118
+ "hookui.numbersAbout": "Bagaimana angka itu sendiri dicetak.",
119
+ "hookui.format": "Bentuk",
120
+ "hookui.formatAbout": "Cetak angka sebagai bagian dari keseluruhan, sebagai satu angka dari angka lain, atau berdiri sendiri.",
121
+ "hookui.formatChange": "bentuk {id} = {v}",
122
+ "hookui.compact": "Bentuk pendek",
123
+ "hookui.compactAbout": "Perpendek angka besar, sehingga 412000 dicetak dalam tiga karakter, bukan enam.",
124
+ "hookui.compactChange": "bentuk pendek {id} = {v}",
125
+ "hookui.minWidth": "Lebar terkecil",
126
+ "hookui.minWidthWarn": "Angka yang berubah lebar mendorong semua yang ada di kanannya. Tetapkan lebar terkecil — dalam sel — dan angka akan diberi jarak sehingga tidak ada yang bergeser.",
127
+ "hookui.minWidthChange": "lebar terkecil {id} = {v}",
128
+ "hookui.precision": "Angka desimal",
129
+ "hookui.precisionAbout": "Berapa digit setelah titik. 0 mencetak bilangan bulat.",
130
+ "hookui.precisionChange": "desimal {id} = {v}",
131
+ "hookui.width": "Sel",
132
+ "hookui.widthWhy": "Berapa sel karakter yang dipakai untuk menggambar batang. Lebih banyak sel adalah satu-satunya bentuk 'lebih besar' yang dimiliki terminal.",
133
+ "hookui.widthChange": "sel {id} = {v}",
134
+
135
+ "hookui.whenToShow": "Kapan disembunyikan",
136
+ "hookui.whenToShowAbout": "Centang setiap keadaan saat bagian ini harus hilang. Jangan centang apa pun dan ia selalu digambar, bahkan ketika tidak ada yang bisa disampaikan.",
137
+ "hookui.hideChange": "{id} sembunyi saat = {v}",
138
+
139
+ "hookui.narrow": "Pada terminal sempit",
140
+ "hookui.narrowAbout": "Apa yang terjadi pada bagian ini ketika jendela terlalu kecil untuk seluruh baris.",
141
+ "hookui.minCols": "Tampil di atas",
142
+ "hookui.minColsAbout": "Sembunyikan bagian ini ketika terminal lebih sempit dari sekian sel. 0 berarti jangan pernah disembunyikan.",
143
+ "hookui.minColsChange": "{id} tampil di atas {v} kolom",
144
+ "hookui.priority": "Urutan dilepas",
145
+ "hookui.priorityWhy": "Ketika baris tidak muat, 1 pergi lebih dulu dan 5 paling akhir. Anda yang memilih apa yang bertahan, bukan tepi kanan.",
146
+ "hookui.priorityChange": "urutan dilepas {id} = {v}",
147
+ "hookui.explain": "Dari mana nilai ini datang",
148
+ "hookui.explainFailed": "Itu tidak dapat dibaca sekarang.",
149
+
150
+ "hookui.reference": "Isi tiap bagian",
151
+ "hookui.referenceAbout": "Daftar setiap bagian yang dapat digambar ORC, dan artinya. Daftar ini tidak menambahkan apa pun — untuk menaruh sebuah bagian pada baris, pakai \"+ tambah bagian\" di papan di atas.",
152
+
153
+ "hookui.presets": "Tata letak siap pakai",
154
+ "hookui.presetsAbout": "Satu baris utuh yang sudah dirancang orang lain. Memakainya mengganti semua yang Anda punya.",
155
+ "hookui.active": "sedang dipakai",
156
+ "hookui.apply": "Pakai ini",
157
+ "hookui.applyTitle": "Pakai \"{name}\"?",
158
+ "hookui.applyWarn": "Ini MENGGANTI seluruh tata letak Anda. Setiap bagian yang Anda taruh dihapus dan yang siap pakai menggantikannya. Ini tidak dapat dibatalkan.",
159
+ "hookui.applyFailed": "Tata letak itu tidak dapat dipakai.",
160
+ "hookui.resetLayout": "Mulai lagi",
161
+ "hookui.resetTitle": "Mulai lagi?",
162
+ "hookui.resetWarn": "Ini MENGGANTI tata letak Anda dengan bawaan ORC. Setiap bagian yang Anda taruh dihapus. Ini tidak dapat dibatalkan.",
163
+
164
+ "hookui.advanced": "Lainnya",
165
+ "hookui.theme": "Kumpulan warna",
166
+ "hookui.themeAbout": "Satu pilihan yang mewarnai seluruh baris sekaligus. Ia memilih slot warna, bukan warna tetap, jadi baris tetap mengikuti terminal Anda.",
167
+ "hookui.themeOverride": "Bagian yang punya warna sendiri tetap memakainya. Buka bagian itu dan kembalikan warnanya ke warna bersama jika Anda ingin kumpulan ini menjangkaunya.",
168
+ "hookui.themeChange": "kumpulan warna = {v}",
169
+ "hookui.glyphsDocAbout": "Kumpulan simbol yang dipakai setiap bagian sebagai awal. Sebuah bagian tetap dapat diberi kumpulan sendiri.",
170
+ "hookui.glyphsDocChange": "simbol = {v}",
171
+ "hookui.recompile": "Bangun ulang",
172
+ "hookui.recompiled": "Sudah dibangun ulang.",
173
+ "hookui.recompileFailed": "Pembangunan ulang gagal.",
174
+ "hookui.compileNote": "ORC membangun ulang tata letak setelah setiap perubahan, jadi Anda tidak perlu melakukannya. Tombol ini untuk sesudah Anda memperbarui ORC.",
175
+
176
+ "hookui.boardStatus": "Baris status",
177
+ "hookui.boardSubagent": "Satu baris per agen",
178
+ "hookui.boardStatusSub": "Dua baris di bagian bawah terminal Anda.",
179
+ "hookui.boardSubagentSub": "Baris yang digambar Claude Code untuk setiap subagen di panel agen. Satu baris, dan ia menunjukkan agen itu berjalan pada apa dan sudah menghabiskan berapa."
180
+ }
@@ -1,21 +1,22 @@
1
- {
2
- "nav.overview": "Ringkasan",
3
- "nav.settings": "Pengaturan",
4
- "nav.lanes": "Lane",
5
- "nav.runs": "Run",
6
- "nav.knowledge": "Pengetahuan",
7
- "nav.stats": "Statistik",
8
- "nav.flow": "Flow",
9
- "nav.crosslink": "Crosslink",
10
- "nav.learn": "Belajar",
11
- "nav.mockrun": "Contoh Penggunaan Skill",
12
- "nav.experiment": "Eksperimen",
13
- "nav.maintenance": "Pemeliharaan",
14
- "nav.pact": "Janji",
15
- "nav.boundary": "Batas",
16
- "nav.handoff": "Ubah Sendiri",
17
- "nav.challenge": "Challenge",
18
- "nav.extra": "Extra",
19
- "nav.wait": "Tunggu",
20
- "nav.docs": "Dokumen"
21
- }
1
+ {
2
+ "nav.overview": "Ringkasan",
3
+ "nav.settings": "Pengaturan",
4
+ "nav.lanes": "Lane",
5
+ "nav.runs": "Run",
6
+ "nav.knowledge": "Pengetahuan",
7
+ "nav.stats": "Statistik",
8
+ "nav.flow": "Flow",
9
+ "nav.crosslink": "Crosslink",
10
+ "nav.learn": "Belajar",
11
+ "nav.mockrun": "Contoh Penggunaan Skill",
12
+ "nav.experiment": "Eksperimen",
13
+ "nav.maintenance": "Pemeliharaan",
14
+ "nav.pact": "Janji",
15
+ "nav.boundary": "Batas",
16
+ "nav.handoff": "Ubah Sendiri",
17
+ "nav.challenge": "Challenge",
18
+ "nav.extra": "Extra",
19
+ "nav.wait": "Tunggu",
20
+ "nav.docs": "Dokumen",
21
+ "nav.hookui": "Antarmuka CLI Hook"
22
+ }
@@ -88,5 +88,8 @@
88
88
  "overview.extraOrphan.chip": "{n} pengiriman",
89
89
  "overview.extraOrphan.chipPlural": "{n} pengiriman",
90
90
  "overview.extraOrphan.slug": "tidak pernah melapor kembali",
91
- "overview.extraOrphan.where": "Extra · Pemulihan"
91
+ "overview.extraOrphan.where": "Extra · Pemulihan",
92
+ "overview.item.statuslineOrphaned.cta": "Buka Antarmuka CLI Hook",
93
+ "overview.item.statuslineInvalid.cta": "Buka Antarmuka CLI Hook",
94
+ "overview.item.statuslineUnreadable.cta": "Buka Antarmuka CLI Hook"
92
95
  }
@@ -29,5 +29,7 @@
29
29
  "tour.13.title": "Dokumen panjang, dalam satu gambar",
30
30
  "tour.13.text": "Setiap blok adalah satu bagian, seukuran panjangnya dan diberi warna sesuai keadaannya. Tidak ada yang memuat dokumen itu sendiri di sini - ORC bekerja dari peta ini, dan itulah sebabnya dokumen panjang tidak menghabiskan sesi.",
31
31
  "tour.14.title": "Pekerjaan yang berjalan di tempat lain",
32
- "tour.14.text": "Satu garis dari nol sampai seratus: seberapa berat skor sebuah tugas. Setiap bagiannya menunjukkan di mana pekerjaan itu benar-benar berjalan — Claude berwarna biru, penyedia yang Anda hubungkan berwarna hijau. Rentang yang belum Anda hubungkan tetap punya tempatnya, jadi \"saya sengaja meninggalkan pekerjaan berat di Claude\" tidak pernah terlihat seperti \"tidak ada pekerjaan berat\". Tidak ada yang keluar dari mesin ini sampai Anda menghubungkan sesuatu, mengujinya, dan menekan Apply."
32
+ "tour.14.text": "Satu garis dari nol sampai seratus: seberapa berat skor sebuah tugas. Setiap bagiannya menunjukkan di mana pekerjaan itu benar-benar berjalan — Claude berwarna biru, penyedia yang Anda hubungkan berwarna hijau. Rentang yang belum Anda hubungkan tetap punya tempatnya, jadi \"saya sengaja meninggalkan pekerjaan berat di Claude\" tidak pernah terlihat seperti \"tidak ada pekerjaan berat\". Tidak ada yang keluar dari mesin ini sampai Anda menghubungkan sesuatu, mengujinya, dan menekan Apply.",
33
+ "tour.15.title": "Bangun baris status Anda sendiri",
34
+ "tour.15.text": "Tiga baris, tiap baris memuat sampai lima bagian. Baris 1 harus terisi sebelum baris 2 bisa. Pratinjau di atas persis seperti yang akan tampil di terminal Anda - digambar oleh kode yang sama dengan yang dijalankan bilah itu."
33
35
  }
@@ -1,151 +1,152 @@
1
- "use strict";
2
- /* 01-i18n.js — orc ui client
3
- LANGS, loadLang, setLang, t, applyStaticText, cycleLang.
4
-
5
- Keys are written out IN FULL, never assembled from a fragment. The v0.48.1
6
- file split is by key PREFIX only; `docs.ship.confirm` is still spelled
7
- `docs.ship.confirm` at every call site.
8
-
9
- Loaded by app.html in the order its numeric prefix names. Classic
10
- script, no import/export: an ES module import carries no query string,
11
- and every static request here needs the per-launch session token. */
12
-
13
- /* ------------------------------------------------------------------- i18n -- */
14
- /*
15
- THE SCOPE RULE, and it is deliberately narrow: only the panel's OWN prose is
16
- translated. Everything that arrives from `bin/cli.js --json` stays exactly as
17
- the CLI wrote it — config keys and their descriptions, values, agent names,
18
- model ids, file paths, commands, `orc doctor` messages, command output. Those
19
- are identifiers, not sentences: a translated config key is a key that does not
20
- exist, and a translated command is a command you cannot type. So `t()` is
21
- never applied to a value read out of a payload, and neither string table
22
- contains a single ORC key name.
23
-
24
- The tables are plain JSON served as static assets. Adding a language is a
25
- FOLDER in i18n/ plus one row in LANGS — no build step, no library, no
26
- dependency, and no server change (serve.js walks i18n/ at boot).
27
- */
28
- const LANGS = [
29
- { code: "en", label: "English" },
30
- { code: "id", label: "Bahasa Indonesia" },
31
- ];
32
- const LANG_KEY = "orc-ui-lang";
33
-
34
- // v0.48.1 — one file per namespace instead of one 53 KB table, so changing the
35
- // Docs panel's wording means opening i18n/en/docs.json rather than paging
36
- // through every string in the panel.
37
- //
38
- // A plain array, and deliberately NOT an index file to fetch: an index would be
39
- // one more round trip and one more thing to forget to update. A namespace owns
40
- // one or more key PREFIXES (`stats` owns `stats.*` and `cost.*`), which the
41
- // test suite asserts — a key whose prefix belongs to no namespace would load
42
- // nowhere and render as a raw dotted string.
43
- const NAMESPACES = [
44
- "common",
45
- "nav",
46
- "banner",
47
- "overview",
48
- "settings",
49
- "lanes",
50
- "runs",
51
- "knowledge",
52
- "stats",
53
- "flow",
54
- "crosslink",
55
- "learn",
56
- "mockrun",
57
- "maintenance",
58
- "pact",
59
- "boundary",
60
- "wait",
61
- "handoff",
62
- "challenge",
63
- "docs",
64
- "extra",
65
- "experiment",
66
- "tour",
67
- ];
68
-
69
- let lang = "en";
70
- // English is loaded first and kept as the FALLBACK table: a key the other
71
- // language has not translated yet renders in English rather than as a raw
72
- // dotted key. A half-finished translation degrades to mixed prose, never to
73
- // debug output on somebody's screen.
74
- let DICT = {};
75
- let DICT_EN = {};
76
-
77
- // The namespaces are fetched in parallel and merged into ONE flat table, so
78
- // `t()` is unchanged and no call site knows the split happened.
79
- //
80
- // A namespace that fails to load falls back to ENGLISH for its keys rather than
81
- // rejecting the whole language: a network hiccup on one file should cost that
82
- // file's prose, not the entire panel. English itself has no fallback below it,
83
- // so a failure there rejects and boot() lands on raw keys ugly, never blank.
84
- function loadLang(code) {
85
- return Promise.all(
86
- NAMESPACES.map((ns) =>
87
- fetch(`/i18n/${code}/${ns}.json`, { headers: { "x-orc-token": TOKEN }, cache: "no-store" })
88
- .then((r) => {
89
- if (!r.ok) throw new Error(`i18n ${code}/${ns} ${r.status}`);
90
- return r.json();
91
- })
92
- .catch((e) => {
93
- if (code === "en") throw e;
94
- return null;
95
- })
96
- )
97
- ).then((parts) => Object.assign({}, ...parts.filter(Boolean)));
98
- }
99
-
100
- // A missing or broken table must never blank the UI. Every failure path here
101
- // lands on English, so the worst case is untranslated text never empty text.
102
- async function setLang(code, opts) {
103
- const rerender = !opts || opts.rerender !== false;
104
- const want = LANGS.some((l) => l.code === code) ? code : "en";
105
- try {
106
- DICT = want === "en" ? DICT_EN : await loadLang(want);
107
- lang = want;
108
- } catch (_) {
109
- DICT = DICT_EN;
110
- lang = "en";
111
- }
112
- try {
113
- localStorage.setItem(LANG_KEY, lang);
114
- } catch (_) {}
115
- document.documentElement.setAttribute("lang", lang);
116
- applyStaticText();
117
- if (rerender) route();
118
- }
119
-
120
- function t(key, vars) {
121
- let s = DICT[key];
122
- if (s === undefined) s = DICT_EN[key];
123
- if (s === undefined) s = key;
124
- if (vars) for (const k of Object.keys(vars)) s = s.split("{" + k + "}").join(String(vars[k]));
125
- return s;
126
- }
127
-
128
- // English has one plural form and Indonesian has none, so count-aware lookup is
129
- // a second key rather than a plural-rules engine: `n === 1` picks the singular.
130
- const tn = (n, key, vars) => t(n === 1 ? key : key + "Plural", Object.assign({ n }, vars || {}));
131
-
132
- // The parts of the shell that are markup rather than a render function. Called
133
- // on every language change; panels re-render themselves through `route()`.
134
- function applyStaticText() {
135
- for (const node of document.querySelectorAll("[data-i18n]")) node.textContent = t(node.dataset.i18n);
136
- const tt = $("#theme-toggle");
137
- if (tt) tt.textContent = document.documentElement.getAttribute("data-theme") === "light" ? t("rail.dark") : t("rail.light");
138
- const hint = $("#shortcut-hint");
139
- if (hint) hint.title = t("rail.shortcuts");
140
- const label = $("#lang-label");
141
- if (label) label.textContent = (LANGS.find((l) => l.code === lang) || LANGS[0]).label;
142
- const btn = $("#lang-toggle");
143
- if (btn) btn.title = t("lang.title");
144
- }
145
-
146
- // Two languages, so the control is a TOGGLE rather than a menu: one click, no
147
- // dropdown to open. A third language would make this a <select>; two do not.
148
- function cycleLang() {
149
- const i = LANGS.findIndex((l) => l.code === lang);
150
- setLang(LANGS[(i + 1) % LANGS.length].code);
151
- }
1
+ "use strict";
2
+ /* 01-i18n.js — orc ui client
3
+ LANGS, loadLang, setLang, t, applyStaticText, cycleLang.
4
+
5
+ Keys are written out IN FULL, never assembled from a fragment. The v0.48.1
6
+ file split is by key PREFIX only; `docs.ship.confirm` is still spelled
7
+ `docs.ship.confirm` at every call site.
8
+
9
+ Loaded by app.html in the order its numeric prefix names. Classic
10
+ script, no import/export: an ES module import carries no query string,
11
+ and every static request here needs the per-launch session token. */
12
+
13
+ /* ------------------------------------------------------------------- i18n -- */
14
+ /*
15
+ THE SCOPE RULE, and it is deliberately narrow: only the panel's OWN prose is
16
+ translated. Everything that arrives from `bin/cli.js --json` stays exactly as
17
+ the CLI wrote it — config keys and their descriptions, values, agent names,
18
+ model ids, file paths, commands, `orc doctor` messages, command output. Those
19
+ are identifiers, not sentences: a translated config key is a key that does not
20
+ exist, and a translated command is a command you cannot type. So `t()` is
21
+ never applied to a value read out of a payload, and neither string table
22
+ contains a single ORC key name.
23
+
24
+ The tables are plain JSON served as static assets. Adding a language is a
25
+ FOLDER in i18n/ plus one row in LANGS — no build step, no library, no
26
+ dependency, and no server change (serve.js walks i18n/ at boot).
27
+ */
28
+ const LANGS = [
29
+ { code: "en", label: "English" },
30
+ { code: "id", label: "Bahasa Indonesia" },
31
+ ];
32
+ const LANG_KEY = "orc-ui-lang";
33
+
34
+ // v0.48.1 — one file per namespace instead of one 53 KB table, so changing the
35
+ // Docs panel's wording means opening i18n/en/docs.json rather than paging
36
+ // through every string in the panel.
37
+ //
38
+ // A plain array, and deliberately NOT an index file to fetch: an index would be
39
+ // one more round trip and one more thing to forget to update. A namespace owns
40
+ // one or more key PREFIXES (`stats` owns `stats.*` and `cost.*`), which the
41
+ // test suite asserts — a key whose prefix belongs to no namespace would load
42
+ // nowhere and render as a raw dotted string.
43
+ const NAMESPACES = [
44
+ "common",
45
+ "nav",
46
+ "banner",
47
+ "overview",
48
+ "settings",
49
+ "lanes",
50
+ "runs",
51
+ "knowledge",
52
+ "stats",
53
+ "flow",
54
+ "crosslink",
55
+ "learn",
56
+ "mockrun",
57
+ "maintenance",
58
+ "pact",
59
+ "boundary",
60
+ "wait",
61
+ "hookui",
62
+ "handoff",
63
+ "challenge",
64
+ "docs",
65
+ "extra",
66
+ "experiment",
67
+ "tour",
68
+ ];
69
+
70
+ let lang = "en";
71
+ // English is loaded first and kept as the FALLBACK table: a key the other
72
+ // language has not translated yet renders in English rather than as a raw
73
+ // dotted key. A half-finished translation degrades to mixed prose, never to
74
+ // debug output on somebody's screen.
75
+ let DICT = {};
76
+ let DICT_EN = {};
77
+
78
+ // The namespaces are fetched in parallel and merged into ONE flat table, so
79
+ // `t()` is unchanged and no call site knows the split happened.
80
+ //
81
+ // A namespace that fails to load falls back to ENGLISH for its keys rather than
82
+ // rejecting the whole language: a network hiccup on one file should cost that
83
+ // file's prose, not the entire panel. English itself has no fallback below it,
84
+ // so a failure there rejects and boot() lands on raw keys — ugly, never blank.
85
+ function loadLang(code) {
86
+ return Promise.all(
87
+ NAMESPACES.map((ns) =>
88
+ fetch(`/i18n/${code}/${ns}.json`, { headers: { "x-orc-token": TOKEN }, cache: "no-store" })
89
+ .then((r) => {
90
+ if (!r.ok) throw new Error(`i18n ${code}/${ns} ${r.status}`);
91
+ return r.json();
92
+ })
93
+ .catch((e) => {
94
+ if (code === "en") throw e;
95
+ return null;
96
+ })
97
+ )
98
+ ).then((parts) => Object.assign({}, ...parts.filter(Boolean)));
99
+ }
100
+
101
+ // A missing or broken table must never blank the UI. Every failure path here
102
+ // lands on English, so the worst case is untranslated text — never empty text.
103
+ async function setLang(code, opts) {
104
+ const rerender = !opts || opts.rerender !== false;
105
+ const want = LANGS.some((l) => l.code === code) ? code : "en";
106
+ try {
107
+ DICT = want === "en" ? DICT_EN : await loadLang(want);
108
+ lang = want;
109
+ } catch (_) {
110
+ DICT = DICT_EN;
111
+ lang = "en";
112
+ }
113
+ try {
114
+ localStorage.setItem(LANG_KEY, lang);
115
+ } catch (_) {}
116
+ document.documentElement.setAttribute("lang", lang);
117
+ applyStaticText();
118
+ if (rerender) route();
119
+ }
120
+
121
+ function t(key, vars) {
122
+ let s = DICT[key];
123
+ if (s === undefined) s = DICT_EN[key];
124
+ if (s === undefined) s = key;
125
+ if (vars) for (const k of Object.keys(vars)) s = s.split("{" + k + "}").join(String(vars[k]));
126
+ return s;
127
+ }
128
+
129
+ // English has one plural form and Indonesian has none, so count-aware lookup is
130
+ // a second key rather than a plural-rules engine: `n === 1` picks the singular.
131
+ const tn = (n, key, vars) => t(n === 1 ? key : key + "Plural", Object.assign({ n }, vars || {}));
132
+
133
+ // The parts of the shell that are markup rather than a render function. Called
134
+ // on every language change; panels re-render themselves through `route()`.
135
+ function applyStaticText() {
136
+ for (const node of document.querySelectorAll("[data-i18n]")) node.textContent = t(node.dataset.i18n);
137
+ const tt = $("#theme-toggle");
138
+ if (tt) tt.textContent = document.documentElement.getAttribute("data-theme") === "light" ? t("rail.dark") : t("rail.light");
139
+ const hint = $("#shortcut-hint");
140
+ if (hint) hint.title = t("rail.shortcuts");
141
+ const label = $("#lang-label");
142
+ if (label) label.textContent = (LANGS.find((l) => l.code === lang) || LANGS[0]).label;
143
+ const btn = $("#lang-toggle");
144
+ if (btn) btn.title = t("lang.title");
145
+ }
146
+
147
+ // Two languages, so the control is a TOGGLE rather than a menu: one click, no
148
+ // dropdown to open. A third language would make this a <select>; two do not.
149
+ function cycleLang() {
150
+ const i = LANGS.findIndex((l) => l.code === lang);
151
+ setLang(LANGS[(i + 1) % LANGS.length].code);
152
+ }