copy_tuner_client 1.5.0 → 2.1.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -2
  3. data/.github/workflows/rspec.yml +1 -1
  4. data/CHANGELOG.md +27 -0
  5. data/CLAUDE.md +6 -4
  6. data/README.md +6 -27
  7. data/UPGRADING.md +201 -0
  8. data/app/assets/javascripts/copytuner.js +162 -250
  9. data/biome.json +39 -0
  10. data/index.html +9 -11
  11. data/lib/copy_tuner_client/cache.rb +0 -2
  12. data/lib/copy_tuner_client/configuration.rb +23 -37
  13. data/lib/copy_tuner_client/copyray/marker.rb +24 -0
  14. data/lib/copy_tuner_client/copyray/rewriter.rb +113 -0
  15. data/lib/copy_tuner_client/copyray.rb +11 -4
  16. data/lib/copy_tuner_client/copyray_middleware.rb +10 -8
  17. data/lib/copy_tuner_client/engine.rb +1 -1
  18. data/lib/copy_tuner_client/helper_extension.rb +0 -3
  19. data/lib/copy_tuner_client/i18n_backend.rb +5 -12
  20. data/lib/copy_tuner_client/version.rb +1 -1
  21. data/mise.toml +3 -0
  22. data/package.json +9 -13
  23. data/pnpm-lock.yaml +600 -0
  24. data/skills/copy-tuner/SKILL.md +37 -6
  25. data/skills/copy-tuner-to-locales-cleanup/SKILL.md +4 -4
  26. data/skills/copy-tuner-to-locales-migrate-prefix/references/local-first-regexp.md +4 -9
  27. data/skills/copy-tuner-to-t-migrate/SKILL.md +131 -0
  28. data/skills/copy-tuner-to-t-migrate/scripts/migrate_tt.rb +189 -0
  29. data/spec/copy_tuner_client/cache_spec.rb +2 -10
  30. data/spec/copy_tuner_client/client_spec.rb +1 -0
  31. data/spec/copy_tuner_client/configuration_spec.rb +16 -16
  32. data/spec/copy_tuner_client/copyray/marker_spec.rb +41 -0
  33. data/spec/copy_tuner_client/copyray/rewriter_spec.rb +216 -0
  34. data/spec/copy_tuner_client/copyray_middleware_spec.rb +88 -0
  35. data/spec/copy_tuner_client/copyray_spec.rb +22 -39
  36. data/spec/copy_tuner_client/helper_extension_spec.rb +18 -5
  37. data/spec/copy_tuner_client/i18n_backend_spec.rb +8 -15
  38. data/spec/support/client_spec_helpers.rb +0 -1
  39. data/src/copyray-overlay.ts +125 -0
  40. data/src/copytuner-bar.ts +153 -0
  41. data/src/main.ts +33 -26
  42. data/src/{copyray.css → styles.ts} +112 -136
  43. data/src/util.ts +9 -1
  44. data/tsconfig.json +5 -10
  45. data/vite.config.ts +0 -1
  46. metadata +15 -8
  47. data/.eslintrc.js +0 -12
  48. data/app/assets/stylesheets/copytuner.css +0 -1
  49. data/src/copyray.ts +0 -130
  50. data/src/copytuner_bar.ts +0 -115
  51. data/src/specimen.ts +0 -84
  52. data/yarn.lock +0 -2540
data/pnpm-lock.yaml ADDED
@@ -0,0 +1,600 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ devDependencies:
11
+ '@biomejs/biome':
12
+ specifier: 2.5.0
13
+ version: 2.5.0
14
+ typescript:
15
+ specifier: ^6.0.0
16
+ version: 6.0.3
17
+ vite:
18
+ specifier: ^8.0.0
19
+ version: 8.1.0
20
+
21
+ packages:
22
+
23
+ '@biomejs/biome@2.5.0':
24
+ resolution: {integrity: sha512-4kURkd9hAPrdDM3C9n82ycYgx8hvQcW6MjKTEejruj8rK0N8P3OPpdy8BvI8kt3KWY4ycF5XtDOrktetEfhfuw==}
25
+ engines: {node: '>=14.21.3'}
26
+ hasBin: true
27
+
28
+ '@biomejs/cli-darwin-arm64@2.5.0':
29
+ resolution: {integrity: sha512-Mn3Fwi3SA5fgmfCPqmzpWF2DLZnms3BVAhM088nTnGrTZmHS3wwIjcoZPqpXeNgd3DrrLH6xp8vTLIBuJoZiXw==}
30
+ engines: {node: '>=14.21.3'}
31
+ cpu: [arm64]
32
+ os: [darwin]
33
+
34
+ '@biomejs/cli-darwin-x64@2.5.0':
35
+ resolution: {integrity: sha512-rg3VPL5P8mYro6pqlXYXuJWph21slVp3SZtAqWSrkZs40d2gTzYmHF8E/X1iTID25btmNKltNDJ926sqVBp7DQ==}
36
+ engines: {node: '>=14.21.3'}
37
+ cpu: [x64]
38
+ os: [darwin]
39
+
40
+ '@biomejs/cli-linux-arm64-musl@2.5.0':
41
+ resolution: {integrity: sha512-vQdM4oSGaf7ZNeGO9w5+Y8SBtyser9M6znxYbm7Ec8wInxJu1WiKxFYZW5Auj2d80bcVvefuGGRxoFOE0eee8g==}
42
+ engines: {node: '>=14.21.3'}
43
+ cpu: [arm64]
44
+ os: [linux]
45
+ libc: [musl]
46
+
47
+ '@biomejs/cli-linux-arm64@2.5.0':
48
+ resolution: {integrity: sha512-tl+LW8fdD96/xdeWtWwc82LIOc5CoY7N2AsogLTp5R4ECErYt+8Jl/N68ezN9vzSiqPTxw6vjcihoLPYKZHrlw==}
49
+ engines: {node: '>=14.21.3'}
50
+ cpu: [arm64]
51
+ os: [linux]
52
+ libc: [glibc]
53
+
54
+ '@biomejs/cli-linux-x64-musl@2.5.0':
55
+ resolution: {integrity: sha512-+9hIcMngJ+yGUahXqZuZ8CoWKJE9SAZsFsM3QDvXpNsLbXZ9lqVzgBhOk/jTSYkOA0GLP9eu3teukqpLUojHMg==}
56
+ engines: {node: '>=14.21.3'}
57
+ cpu: [x64]
58
+ os: [linux]
59
+ libc: [musl]
60
+
61
+ '@biomejs/cli-linux-x64@2.5.0':
62
+ resolution: {integrity: sha512-zpEGf4RQbFEh8Vt7OmavLyyOzRbtcE9osCqrS1kfvt8jDvxwhKXLSf7n0ebr/ov0RJ9ssP+lhs6C8a9WwFvrQA==}
63
+ engines: {node: '>=14.21.3'}
64
+ cpu: [x64]
65
+ os: [linux]
66
+ libc: [glibc]
67
+
68
+ '@biomejs/cli-win32-arm64@2.5.0':
69
+ resolution: {integrity: sha512-jB0wAvTLI4itx5VidqVUejPQFhRUxiZ9l9FvZ26D5fl6t3qme+ZB4PD3bTSeL1vZ8NI2Rx/zj6H9zcESuGHKGw==}
70
+ engines: {node: '>=14.21.3'}
71
+ cpu: [arm64]
72
+ os: [win32]
73
+
74
+ '@biomejs/cli-win32-x64@2.5.0':
75
+ resolution: {integrity: sha512-VT/lF+GId+67j8aDfLkxdxNoVApsPSTbyAtB3jJq0IWTrY77WXfbPfpngxq0bA6JCEv/7k8C9qWjDRKRznDlyw==}
76
+ engines: {node: '>=14.21.3'}
77
+ cpu: [x64]
78
+ os: [win32]
79
+
80
+ '@emnapi/core@1.11.1':
81
+ resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
82
+
83
+ '@emnapi/runtime@1.11.1':
84
+ resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}
85
+
86
+ '@emnapi/wasi-threads@1.2.2':
87
+ resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
88
+
89
+ '@napi-rs/wasm-runtime@1.1.6':
90
+ resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==}
91
+ peerDependencies:
92
+ '@emnapi/core': ^1.7.1
93
+ '@emnapi/runtime': ^1.7.1
94
+
95
+ '@oxc-project/types@0.137.0':
96
+ resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==}
97
+
98
+ '@rolldown/binding-android-arm64@1.1.3':
99
+ resolution: {integrity: sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==}
100
+ engines: {node: ^20.19.0 || >=22.12.0}
101
+ cpu: [arm64]
102
+ os: [android]
103
+
104
+ '@rolldown/binding-darwin-arm64@1.1.3':
105
+ resolution: {integrity: sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==}
106
+ engines: {node: ^20.19.0 || >=22.12.0}
107
+ cpu: [arm64]
108
+ os: [darwin]
109
+
110
+ '@rolldown/binding-darwin-x64@1.1.3':
111
+ resolution: {integrity: sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==}
112
+ engines: {node: ^20.19.0 || >=22.12.0}
113
+ cpu: [x64]
114
+ os: [darwin]
115
+
116
+ '@rolldown/binding-freebsd-x64@1.1.3':
117
+ resolution: {integrity: sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==}
118
+ engines: {node: ^20.19.0 || >=22.12.0}
119
+ cpu: [x64]
120
+ os: [freebsd]
121
+
122
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.3':
123
+ resolution: {integrity: sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==}
124
+ engines: {node: ^20.19.0 || >=22.12.0}
125
+ cpu: [arm]
126
+ os: [linux]
127
+
128
+ '@rolldown/binding-linux-arm64-gnu@1.1.3':
129
+ resolution: {integrity: sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==}
130
+ engines: {node: ^20.19.0 || >=22.12.0}
131
+ cpu: [arm64]
132
+ os: [linux]
133
+ libc: [glibc]
134
+
135
+ '@rolldown/binding-linux-arm64-musl@1.1.3':
136
+ resolution: {integrity: sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==}
137
+ engines: {node: ^20.19.0 || >=22.12.0}
138
+ cpu: [arm64]
139
+ os: [linux]
140
+ libc: [musl]
141
+
142
+ '@rolldown/binding-linux-ppc64-gnu@1.1.3':
143
+ resolution: {integrity: sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==}
144
+ engines: {node: ^20.19.0 || >=22.12.0}
145
+ cpu: [ppc64]
146
+ os: [linux]
147
+ libc: [glibc]
148
+
149
+ '@rolldown/binding-linux-s390x-gnu@1.1.3':
150
+ resolution: {integrity: sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==}
151
+ engines: {node: ^20.19.0 || >=22.12.0}
152
+ cpu: [s390x]
153
+ os: [linux]
154
+ libc: [glibc]
155
+
156
+ '@rolldown/binding-linux-x64-gnu@1.1.3':
157
+ resolution: {integrity: sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==}
158
+ engines: {node: ^20.19.0 || >=22.12.0}
159
+ cpu: [x64]
160
+ os: [linux]
161
+ libc: [glibc]
162
+
163
+ '@rolldown/binding-linux-x64-musl@1.1.3':
164
+ resolution: {integrity: sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==}
165
+ engines: {node: ^20.19.0 || >=22.12.0}
166
+ cpu: [x64]
167
+ os: [linux]
168
+ libc: [musl]
169
+
170
+ '@rolldown/binding-openharmony-arm64@1.1.3':
171
+ resolution: {integrity: sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==}
172
+ engines: {node: ^20.19.0 || >=22.12.0}
173
+ cpu: [arm64]
174
+ os: [openharmony]
175
+
176
+ '@rolldown/binding-wasm32-wasi@1.1.3':
177
+ resolution: {integrity: sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==}
178
+ engines: {node: ^20.19.0 || >=22.12.0}
179
+ cpu: [wasm32]
180
+
181
+ '@rolldown/binding-win32-arm64-msvc@1.1.3':
182
+ resolution: {integrity: sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==}
183
+ engines: {node: ^20.19.0 || >=22.12.0}
184
+ cpu: [arm64]
185
+ os: [win32]
186
+
187
+ '@rolldown/binding-win32-x64-msvc@1.1.3':
188
+ resolution: {integrity: sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==}
189
+ engines: {node: ^20.19.0 || >=22.12.0}
190
+ cpu: [x64]
191
+ os: [win32]
192
+
193
+ '@rolldown/pluginutils@1.0.1':
194
+ resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
195
+
196
+ '@tybys/wasm-util@0.10.3':
197
+ resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
198
+
199
+ detect-libc@2.1.2:
200
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
201
+ engines: {node: '>=8'}
202
+
203
+ fdir@6.5.0:
204
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
205
+ engines: {node: '>=12.0.0'}
206
+ peerDependencies:
207
+ picomatch: ^3 || ^4
208
+ peerDependenciesMeta:
209
+ picomatch:
210
+ optional: true
211
+
212
+ fsevents@2.3.3:
213
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
214
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
215
+ os: [darwin]
216
+
217
+ lightningcss-android-arm64@1.32.0:
218
+ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
219
+ engines: {node: '>= 12.0.0'}
220
+ cpu: [arm64]
221
+ os: [android]
222
+
223
+ lightningcss-darwin-arm64@1.32.0:
224
+ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
225
+ engines: {node: '>= 12.0.0'}
226
+ cpu: [arm64]
227
+ os: [darwin]
228
+
229
+ lightningcss-darwin-x64@1.32.0:
230
+ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
231
+ engines: {node: '>= 12.0.0'}
232
+ cpu: [x64]
233
+ os: [darwin]
234
+
235
+ lightningcss-freebsd-x64@1.32.0:
236
+ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
237
+ engines: {node: '>= 12.0.0'}
238
+ cpu: [x64]
239
+ os: [freebsd]
240
+
241
+ lightningcss-linux-arm-gnueabihf@1.32.0:
242
+ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
243
+ engines: {node: '>= 12.0.0'}
244
+ cpu: [arm]
245
+ os: [linux]
246
+
247
+ lightningcss-linux-arm64-gnu@1.32.0:
248
+ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
249
+ engines: {node: '>= 12.0.0'}
250
+ cpu: [arm64]
251
+ os: [linux]
252
+ libc: [glibc]
253
+
254
+ lightningcss-linux-arm64-musl@1.32.0:
255
+ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
256
+ engines: {node: '>= 12.0.0'}
257
+ cpu: [arm64]
258
+ os: [linux]
259
+ libc: [musl]
260
+
261
+ lightningcss-linux-x64-gnu@1.32.0:
262
+ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
263
+ engines: {node: '>= 12.0.0'}
264
+ cpu: [x64]
265
+ os: [linux]
266
+ libc: [glibc]
267
+
268
+ lightningcss-linux-x64-musl@1.32.0:
269
+ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
270
+ engines: {node: '>= 12.0.0'}
271
+ cpu: [x64]
272
+ os: [linux]
273
+ libc: [musl]
274
+
275
+ lightningcss-win32-arm64-msvc@1.32.0:
276
+ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
277
+ engines: {node: '>= 12.0.0'}
278
+ cpu: [arm64]
279
+ os: [win32]
280
+
281
+ lightningcss-win32-x64-msvc@1.32.0:
282
+ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
283
+ engines: {node: '>= 12.0.0'}
284
+ cpu: [x64]
285
+ os: [win32]
286
+
287
+ lightningcss@1.32.0:
288
+ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
289
+ engines: {node: '>= 12.0.0'}
290
+
291
+ nanoid@3.3.15:
292
+ resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==}
293
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
294
+ hasBin: true
295
+
296
+ picocolors@1.1.1:
297
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
298
+
299
+ picomatch@4.0.4:
300
+ resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
301
+ engines: {node: '>=12'}
302
+
303
+ postcss@8.5.15:
304
+ resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
305
+ engines: {node: ^10 || ^12 || >=14}
306
+
307
+ rolldown@1.1.3:
308
+ resolution: {integrity: sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==}
309
+ engines: {node: ^20.19.0 || >=22.12.0}
310
+ hasBin: true
311
+
312
+ source-map-js@1.2.1:
313
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
314
+ engines: {node: '>=0.10.0'}
315
+
316
+ tinyglobby@0.2.17:
317
+ resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
318
+ engines: {node: '>=12.0.0'}
319
+
320
+ tslib@2.8.1:
321
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
322
+
323
+ typescript@6.0.3:
324
+ resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
325
+ engines: {node: '>=14.17'}
326
+ hasBin: true
327
+
328
+ vite@8.1.0:
329
+ resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==}
330
+ engines: {node: ^20.19.0 || >=22.12.0}
331
+ hasBin: true
332
+ peerDependencies:
333
+ '@types/node': ^20.19.0 || >=22.12.0
334
+ '@vitejs/devtools': ^0.3.0
335
+ esbuild: ^0.27.0 || ^0.28.0
336
+ jiti: '>=1.21.0'
337
+ less: ^4.0.0
338
+ sass: ^1.70.0
339
+ sass-embedded: ^1.70.0
340
+ stylus: '>=0.54.8'
341
+ sugarss: ^5.0.0
342
+ terser: ^5.16.0
343
+ tsx: ^4.8.1
344
+ yaml: ^2.4.2
345
+ peerDependenciesMeta:
346
+ '@types/node':
347
+ optional: true
348
+ '@vitejs/devtools':
349
+ optional: true
350
+ esbuild:
351
+ optional: true
352
+ jiti:
353
+ optional: true
354
+ less:
355
+ optional: true
356
+ sass:
357
+ optional: true
358
+ sass-embedded:
359
+ optional: true
360
+ stylus:
361
+ optional: true
362
+ sugarss:
363
+ optional: true
364
+ terser:
365
+ optional: true
366
+ tsx:
367
+ optional: true
368
+ yaml:
369
+ optional: true
370
+
371
+ snapshots:
372
+
373
+ '@biomejs/biome@2.5.0':
374
+ optionalDependencies:
375
+ '@biomejs/cli-darwin-arm64': 2.5.0
376
+ '@biomejs/cli-darwin-x64': 2.5.0
377
+ '@biomejs/cli-linux-arm64': 2.5.0
378
+ '@biomejs/cli-linux-arm64-musl': 2.5.0
379
+ '@biomejs/cli-linux-x64': 2.5.0
380
+ '@biomejs/cli-linux-x64-musl': 2.5.0
381
+ '@biomejs/cli-win32-arm64': 2.5.0
382
+ '@biomejs/cli-win32-x64': 2.5.0
383
+
384
+ '@biomejs/cli-darwin-arm64@2.5.0':
385
+ optional: true
386
+
387
+ '@biomejs/cli-darwin-x64@2.5.0':
388
+ optional: true
389
+
390
+ '@biomejs/cli-linux-arm64-musl@2.5.0':
391
+ optional: true
392
+
393
+ '@biomejs/cli-linux-arm64@2.5.0':
394
+ optional: true
395
+
396
+ '@biomejs/cli-linux-x64-musl@2.5.0':
397
+ optional: true
398
+
399
+ '@biomejs/cli-linux-x64@2.5.0':
400
+ optional: true
401
+
402
+ '@biomejs/cli-win32-arm64@2.5.0':
403
+ optional: true
404
+
405
+ '@biomejs/cli-win32-x64@2.5.0':
406
+ optional: true
407
+
408
+ '@emnapi/core@1.11.1':
409
+ dependencies:
410
+ '@emnapi/wasi-threads': 1.2.2
411
+ tslib: 2.8.1
412
+ optional: true
413
+
414
+ '@emnapi/runtime@1.11.1':
415
+ dependencies:
416
+ tslib: 2.8.1
417
+ optional: true
418
+
419
+ '@emnapi/wasi-threads@1.2.2':
420
+ dependencies:
421
+ tslib: 2.8.1
422
+ optional: true
423
+
424
+ '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
425
+ dependencies:
426
+ '@emnapi/core': 1.11.1
427
+ '@emnapi/runtime': 1.11.1
428
+ '@tybys/wasm-util': 0.10.3
429
+ optional: true
430
+
431
+ '@oxc-project/types@0.137.0': {}
432
+
433
+ '@rolldown/binding-android-arm64@1.1.3':
434
+ optional: true
435
+
436
+ '@rolldown/binding-darwin-arm64@1.1.3':
437
+ optional: true
438
+
439
+ '@rolldown/binding-darwin-x64@1.1.3':
440
+ optional: true
441
+
442
+ '@rolldown/binding-freebsd-x64@1.1.3':
443
+ optional: true
444
+
445
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.3':
446
+ optional: true
447
+
448
+ '@rolldown/binding-linux-arm64-gnu@1.1.3':
449
+ optional: true
450
+
451
+ '@rolldown/binding-linux-arm64-musl@1.1.3':
452
+ optional: true
453
+
454
+ '@rolldown/binding-linux-ppc64-gnu@1.1.3':
455
+ optional: true
456
+
457
+ '@rolldown/binding-linux-s390x-gnu@1.1.3':
458
+ optional: true
459
+
460
+ '@rolldown/binding-linux-x64-gnu@1.1.3':
461
+ optional: true
462
+
463
+ '@rolldown/binding-linux-x64-musl@1.1.3':
464
+ optional: true
465
+
466
+ '@rolldown/binding-openharmony-arm64@1.1.3':
467
+ optional: true
468
+
469
+ '@rolldown/binding-wasm32-wasi@1.1.3':
470
+ dependencies:
471
+ '@emnapi/core': 1.11.1
472
+ '@emnapi/runtime': 1.11.1
473
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
474
+ optional: true
475
+
476
+ '@rolldown/binding-win32-arm64-msvc@1.1.3':
477
+ optional: true
478
+
479
+ '@rolldown/binding-win32-x64-msvc@1.1.3':
480
+ optional: true
481
+
482
+ '@rolldown/pluginutils@1.0.1': {}
483
+
484
+ '@tybys/wasm-util@0.10.3':
485
+ dependencies:
486
+ tslib: 2.8.1
487
+ optional: true
488
+
489
+ detect-libc@2.1.2: {}
490
+
491
+ fdir@6.5.0(picomatch@4.0.4):
492
+ optionalDependencies:
493
+ picomatch: 4.0.4
494
+
495
+ fsevents@2.3.3:
496
+ optional: true
497
+
498
+ lightningcss-android-arm64@1.32.0:
499
+ optional: true
500
+
501
+ lightningcss-darwin-arm64@1.32.0:
502
+ optional: true
503
+
504
+ lightningcss-darwin-x64@1.32.0:
505
+ optional: true
506
+
507
+ lightningcss-freebsd-x64@1.32.0:
508
+ optional: true
509
+
510
+ lightningcss-linux-arm-gnueabihf@1.32.0:
511
+ optional: true
512
+
513
+ lightningcss-linux-arm64-gnu@1.32.0:
514
+ optional: true
515
+
516
+ lightningcss-linux-arm64-musl@1.32.0:
517
+ optional: true
518
+
519
+ lightningcss-linux-x64-gnu@1.32.0:
520
+ optional: true
521
+
522
+ lightningcss-linux-x64-musl@1.32.0:
523
+ optional: true
524
+
525
+ lightningcss-win32-arm64-msvc@1.32.0:
526
+ optional: true
527
+
528
+ lightningcss-win32-x64-msvc@1.32.0:
529
+ optional: true
530
+
531
+ lightningcss@1.32.0:
532
+ dependencies:
533
+ detect-libc: 2.1.2
534
+ optionalDependencies:
535
+ lightningcss-android-arm64: 1.32.0
536
+ lightningcss-darwin-arm64: 1.32.0
537
+ lightningcss-darwin-x64: 1.32.0
538
+ lightningcss-freebsd-x64: 1.32.0
539
+ lightningcss-linux-arm-gnueabihf: 1.32.0
540
+ lightningcss-linux-arm64-gnu: 1.32.0
541
+ lightningcss-linux-arm64-musl: 1.32.0
542
+ lightningcss-linux-x64-gnu: 1.32.0
543
+ lightningcss-linux-x64-musl: 1.32.0
544
+ lightningcss-win32-arm64-msvc: 1.32.0
545
+ lightningcss-win32-x64-msvc: 1.32.0
546
+
547
+ nanoid@3.3.15: {}
548
+
549
+ picocolors@1.1.1: {}
550
+
551
+ picomatch@4.0.4: {}
552
+
553
+ postcss@8.5.15:
554
+ dependencies:
555
+ nanoid: 3.3.15
556
+ picocolors: 1.1.1
557
+ source-map-js: 1.2.1
558
+
559
+ rolldown@1.1.3:
560
+ dependencies:
561
+ '@oxc-project/types': 0.137.0
562
+ '@rolldown/pluginutils': 1.0.1
563
+ optionalDependencies:
564
+ '@rolldown/binding-android-arm64': 1.1.3
565
+ '@rolldown/binding-darwin-arm64': 1.1.3
566
+ '@rolldown/binding-darwin-x64': 1.1.3
567
+ '@rolldown/binding-freebsd-x64': 1.1.3
568
+ '@rolldown/binding-linux-arm-gnueabihf': 1.1.3
569
+ '@rolldown/binding-linux-arm64-gnu': 1.1.3
570
+ '@rolldown/binding-linux-arm64-musl': 1.1.3
571
+ '@rolldown/binding-linux-ppc64-gnu': 1.1.3
572
+ '@rolldown/binding-linux-s390x-gnu': 1.1.3
573
+ '@rolldown/binding-linux-x64-gnu': 1.1.3
574
+ '@rolldown/binding-linux-x64-musl': 1.1.3
575
+ '@rolldown/binding-openharmony-arm64': 1.1.3
576
+ '@rolldown/binding-wasm32-wasi': 1.1.3
577
+ '@rolldown/binding-win32-arm64-msvc': 1.1.3
578
+ '@rolldown/binding-win32-x64-msvc': 1.1.3
579
+
580
+ source-map-js@1.2.1: {}
581
+
582
+ tinyglobby@0.2.17:
583
+ dependencies:
584
+ fdir: 6.5.0(picomatch@4.0.4)
585
+ picomatch: 4.0.4
586
+
587
+ tslib@2.8.1:
588
+ optional: true
589
+
590
+ typescript@6.0.3: {}
591
+
592
+ vite@8.1.0:
593
+ dependencies:
594
+ lightningcss: 1.32.0
595
+ picomatch: 4.0.4
596
+ postcss: 8.5.15
597
+ rolldown: 1.1.3
598
+ tinyglobby: 0.2.17
599
+ optionalDependencies:
600
+ fsevents: 2.3.3
@@ -71,13 +71,44 @@ license: MIT
71
71
  削除せず `config/initializers/copy_tuner.rb` の `ignored_keys` に追加する。
72
72
  一定期間どこからも参照されていないことを確認してから手動削除する。
73
73
 
74
- ## `t` と `tt` の使い分け
74
+ ## 翻訳ヘルパー(`t`)
75
75
 
76
- **HTML 要素の属性値には `tt` を使う**(それ以外の通常出力は `t`)。`tt` は copy_tuner_client gem の
77
- `HelperExtension` が提供するエイリアス。`t` は CopyTuner の都合で HTML コメント (`<!-- ... -->`) を
78
- 埋め込むため、属性値に入ると表示崩れや動作不良の原因になる。
76
+ **通常出力・属性値ともに `t`(`translate`)を使う。** 属性値も含めて区別は不要。
77
+
78
+ **`tt` は削除済み。** PR #122 で存在理由を喪失したため削除した。既存の `tt` 呼び出しは `t` へ置き換える(属性値含め)。
79
+
80
+ ## 落とし穴: 開発環境で訳文にマーカートークンが混入する
81
+
82
+ PR #122 の可視トークン方式では、development(`middleware` 有効時)の `t('key')` の戻り値は
83
+ `⟦CT:key⟧訳文本体`(記号は U+27E6 / U+27E7)のように、訳文先頭に Copyray マーカートークンが付いた
84
+ 文字列になる。トークンは配信直前に `CopyrayMiddleware` → `Rewriter` が `data-copyray-key` 属性へ変換
85
+ して HTML から完全除去するため画面表示は正常だが、**ビューで訳文を文字列として加工するコードは、
86
+ 除去前のトークン込み文字列に作用してしまう。**
87
+
88
+ **本番では再現しない。** 本番では `CopyrayMiddleware` 自体が登録されずマーカー注入もされないため、
89
+ 戻り値は素の訳文。**開発環境だけ挙動が違う**のが見落としやすい点。
90
+
91
+ 危険なコード例:
92
+
93
+ ```erb
94
+ <%= truncate(t('views.foo.body')) %> <%# ⟦CT:...⟧ 込みの長さで切られ、トークン途中で切れる/本文が短く切られる %>
95
+ <%= t('views.foo.title').length %> <%# トークン長が加算され想定外の値になる %>
96
+ ```
97
+
98
+ 一般化すると、`t(...)` の戻り値を `truncate` / `length` / スライス(`[0..n]`)/ 正規表現マッチ /
99
+ 文字数バリデーション等で**文字列処理する全般**が対象。
100
+
101
+ **対処**: 訳文を文字列加工する場合、マーカーを注入しない `I18n.t`(`translate` ヘルパーではなく
102
+ `I18n` モジュールを直接呼ぶ)で訳文を取得してから加工する。`I18n.t` は HelperExtension のラッパーを
103
+ 通らないためトークンが付かない。
79
104
 
80
105
  ```erb
81
- <div title="<%= tt('views.tooltips.help_text') %>">...</div>
82
- <h1><%= t('views.simulation.show.title') %></h1>
106
+ <%= truncate(I18n.t('views.foo.body')) %>
83
107
  ```
108
+
109
+ 注意:
110
+ - `I18n.t` は partial 相対キー(先頭ドットの `t('.body')`)を解決しないので、`I18n.t('views.foo.body')`
111
+ のように**絶対キーで書く**こと。
112
+
113
+ **このスキルでの注意**: キー追加・参照・コード差し替えを行う際、上記のように訳文を文字列加工して
114
+ いるコードを書く/触る場合はこの罠を念頭に置くこと。
@@ -82,10 +82,10 @@ migrate-prefix 側で配置を直してから戻る。
82
82
 
83
83
  ### 3. `tt` ヘルパーをアプリ側へ退避
84
84
 
85
- copy_tuner_client `ActionView` の `translate` をフックする際に **`tt` という独自エイリアス**を生やす
86
- (copyray コメント注入なしの純粋な翻訳。シグネチャは `tt(key, **options)`)。アプリのビューが `tt(...)`
87
- 使っていると、gem 撤去で `tt` が消えて `NoMethodError`(テンプレートで未定義ヘルパー)になる。**gem を抜く前に**
88
- アプリ側へ移しておく。
85
+ copy_tuner_client はかつて `ActionView` の `translate` をフックする際に **`tt` という独自エイリアス**を生やして
86
+ いた(シグネチャは `tt(key, **options)`)。PR #122 で存在理由を喪失したため gem からは削除済みだが、過去の
87
+ copy_tuner_client を使っていたアプリのビューに `tt(...)` 呼び出しが残っていると `NoMethodError`(テンプレートで
88
+ 未定義ヘルパー)になる。**gem を抜く前に**アプリ側へ移しておく(既に gem 側に `tt` が無い場合も手順は同じ)。
89
89
 
90
90
  1. 利用箇所を洗い出す(残っていれば移行対象):
91
91
 
@@ -60,13 +60,8 @@ config.local_first_key_regexp = Regexp.union(
60
60
  (`/\Aviews\./`。`Regexp.union` に文字列を渡す場合は自動エスケープされるが、Regexp リテラルを渡すときは自分で
61
61
  書く)。
62
62
 
63
- ## deprecated exclude_key_regexp との違い
63
+ ## exclude_key_regexp について
64
64
 
65
- | | `local_first_key_regexp` | `exclude_key_regexp`(非推奨) |
66
- |---|---|---|
67
- | 対象キー | locale を**除いた**キー(`views.foo`) | locale を**含む**キー(`ja.views.foo`) |
68
- | 作用タイミング | lookup(読み込み)時 | upload(送信)時 |
69
- | 効果 | ローカル YAML を優先(完全分離) | サーバへのアップロードを抑止するだけ |
70
-
71
- `exclude_key_regexp` は PR #110 で非推奨化された(設定すると `ActiveSupport::Deprecation` 警告が出る)。
72
- 移行では使わない。もし既存設定に `exclude_key_regexp` があれば、cleanup スキルで gem ごと撤去される。
65
+ かつて存在した `exclude_key_regexp` オプションは v2 で削除済み。`local_first_key_regexp` を使うこと
66
+ (対象は locale を**除いた**キー `views.foo`、lookup 時に作用しローカル YAML を優先=完全分離)。
67
+ 既存 initializer `exclude_key_regexp` の設定が残っている場合は削除する。