wuchale 0.1.0 → 0.1.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.
- package/README.md +116 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,10 @@ minimal and constant-time.
|
|
|
35
35
|
### 🧩 Full Nesting Support
|
|
36
36
|
|
|
37
37
|
Handles deeply nested markup and interpolations — mixed conditionals, loops,
|
|
38
|
-
and awaits — by compiling them into nested Svelte snippets.
|
|
38
|
+
and awaits — by compiling them into nested Svelte snippets. That means you can
|
|
39
|
+
go as crazy as
|
|
40
|
+
[this test](https://github.com/K1DV5/wuchale/blob/main/tests/complicated/app.svelte)
|
|
41
|
+
and it will still extract the correct texts.
|
|
39
42
|
|
|
40
43
|
### 📦 No String Parsing at Runtime
|
|
41
44
|
|
|
@@ -56,8 +59,9 @@ optional integration with external tools.
|
|
|
56
59
|
|
|
57
60
|
### 🚀 Tiny Footprint
|
|
58
61
|
|
|
59
|
-
Adds just 2 packages (
|
|
60
|
-
|
|
62
|
+
Adds just 2 packages (itself and `pofile`) to `node_modules`, as the other
|
|
63
|
+
dependency is Svelte itself. No 200 packages and 90MB dependency trees like
|
|
64
|
+
some existing solutions.
|
|
61
65
|
|
|
62
66
|
### ✨ Ready for Svelte 5
|
|
63
67
|
|
|
@@ -79,11 +83,39 @@ Add to your Vite config:
|
|
|
79
83
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
80
84
|
import { wuchale } from 'wuchale'
|
|
81
85
|
|
|
82
|
-
export default {
|
|
86
|
+
export default {
|
|
87
|
+
plugins: [
|
|
88
|
+
wuchale(),
|
|
89
|
+
svelte(),
|
|
90
|
+
]
|
|
91
|
+
// ...your other config
|
|
92
|
+
}
|
|
83
93
|
|
|
84
94
|
```
|
|
85
95
|
|
|
86
|
-
|
|
96
|
+
Create `/locales/` if it doesn't exist, and then set it up in your main
|
|
97
|
+
component. Assuming `/src/App.svelte`:
|
|
98
|
+
|
|
99
|
+
```svelte
|
|
100
|
+
<script>
|
|
101
|
+
import {setTranslations} from 'wuchale/runtime.svelte'
|
|
102
|
+
|
|
103
|
+
let locale = $state('en')
|
|
104
|
+
|
|
105
|
+
$effect.pre(() => {
|
|
106
|
+
import(`../locales/${locale}.json`).then(mod => {
|
|
107
|
+
setTranslations(mod.default)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
</script>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Note that you manage the state of which locale is active and how to download
|
|
114
|
+
the compiled `.json`. This is to allow maximum flexibility, meaning you can use
|
|
115
|
+
lazy loading (like this example) or you can import it directly and it will be
|
|
116
|
+
bundled by Vite. After that, you notify `wuchale` to set it as the current one.
|
|
117
|
+
|
|
118
|
+
Then finally you write your Svelte files naturally:
|
|
87
119
|
|
|
88
120
|
```svelte
|
|
89
121
|
|
|
@@ -98,6 +130,8 @@ import WuchaleTrans, { wuchaleTrans } from 'wuchale/runtime.svelte'
|
|
|
98
130
|
<h1>{wuchaleTrans(0)}</h1> <!-- Extracted "Hello" as index 0 -->
|
|
99
131
|
```
|
|
100
132
|
|
|
133
|
+
Full example below.
|
|
134
|
+
|
|
101
135
|
## 📦 How It Works
|
|
102
136
|
|
|
103
137
|
### Process
|
|
@@ -135,6 +169,8 @@ Input:
|
|
|
135
169
|
|
|
136
170
|
```svelte
|
|
137
171
|
|
|
172
|
+
<p>Hi there!</p>
|
|
173
|
+
|
|
138
174
|
<p>Hello <b>{userName}</b></p>
|
|
139
175
|
|
|
140
176
|
```
|
|
@@ -142,19 +178,62 @@ Input:
|
|
|
142
178
|
Output:
|
|
143
179
|
|
|
144
180
|
```svelte
|
|
181
|
+
<script>
|
|
182
|
+
import WuchaleTrans, { wuchaleTrans } from 'wuchale/runtime.svelte'
|
|
183
|
+
</script>
|
|
145
184
|
|
|
146
|
-
<p>{wuchaleTrans(0
|
|
185
|
+
<p>{wuchaleTrans(0)}</p>
|
|
186
|
+
|
|
187
|
+
<p>
|
|
188
|
+
{#snippet wuchaleSnippet0(ctx)}
|
|
189
|
+
<b>{ctx[1]}</b>
|
|
190
|
+
{/snippet}
|
|
191
|
+
<WuchaleTrans tags={[wuchaleSnippet0]} id={1} args={[userName]} />
|
|
192
|
+
</p>
|
|
147
193
|
|
|
148
194
|
```
|
|
149
195
|
|
|
150
|
-
|
|
196
|
+
Extracted catalog (PO) for `en`:
|
|
151
197
|
|
|
152
198
|
```nginx
|
|
153
199
|
|
|
154
|
-
msgid "
|
|
200
|
+
msgid "Hi there!"
|
|
201
|
+
msgstr "Hi there!"
|
|
202
|
+
|
|
203
|
+
msgid "Hello {0}"
|
|
204
|
+
msgstr "Hello {0}"
|
|
155
205
|
|
|
156
206
|
```
|
|
157
207
|
|
|
208
|
+
Extracted catalog (PO) for `es`, initially empty `msgstr`, but after a translator or Gemini translates it:
|
|
209
|
+
|
|
210
|
+
```nginx
|
|
211
|
+
|
|
212
|
+
msgid "Hi there!"
|
|
213
|
+
msgstr "¡Hola!"
|
|
214
|
+
|
|
215
|
+
msgid "Hello {0}"
|
|
216
|
+
msgstr "Hola {0}"
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Which is then automatically compiled to:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
[
|
|
224
|
+
"¡Hola!",
|
|
225
|
+
[
|
|
226
|
+
"Hola ",
|
|
227
|
+
[
|
|
228
|
+
0,
|
|
229
|
+
0
|
|
230
|
+
]
|
|
231
|
+
]
|
|
232
|
+
]
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
This is what you import when you set it up above in `App.svelte`.
|
|
236
|
+
|
|
158
237
|
## Supported syntax
|
|
159
238
|
|
|
160
239
|
Text can be in three places: markup, script and attributes. Script means not
|
|
@@ -196,6 +275,35 @@ necessary to have a separate plurals support because you can do something like:
|
|
|
196
275
|
And they will be extracted separately. You can also make a reusable function
|
|
197
276
|
yourself.
|
|
198
277
|
|
|
278
|
+
## Configuration
|
|
279
|
+
|
|
280
|
+
To configure `wuchale`, you pass an object that looks like the following (the
|
|
281
|
+
default) to `wuchale()` in your `vite.config.js` `vite.config.ts`:
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
export const defaultOptions = {
|
|
285
|
+
sourceLocale: 'en',
|
|
286
|
+
otherLocales: ['am'],
|
|
287
|
+
localesDir: './locales',
|
|
288
|
+
importFrom: 'wuchale/runtime.svelte',
|
|
289
|
+
heuristic: defaultHeuristic,
|
|
290
|
+
geminiAPIKey: 'env',
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
While the others are self explanatory, the `heuristic` is a function that
|
|
295
|
+
decides what text to extract and what not to. The `defaultHeuristic` is the
|
|
296
|
+
implementation of the above rules, but you can roll your own and provide it
|
|
297
|
+
here. The function should receive the following arguments:
|
|
298
|
+
|
|
299
|
+
- `text`: The candidate text
|
|
300
|
+
- `scope`: Where the text is located, i.e. it can be one of `markup`, `script`, and `attribute`
|
|
301
|
+
|
|
302
|
+
And it should return an object with two properties:
|
|
303
|
+
|
|
304
|
+
- `extract` (boolean): Whether to extract it or not
|
|
305
|
+
- `replace` (`string`): The string to replace it with. This is how you specify how to remove parts such as the prefixes above (`+` and `-`).
|
|
306
|
+
|
|
199
307
|
## 🧹 Cleaning
|
|
200
308
|
|
|
201
309
|
Unused keys are marked as obsolete during a production build. Obsoletes are
|