@vocab/cli 0.0.16 → 1.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.
- package/CHANGELOG.md +39 -0
- package/README.md +184 -21
- package/package.json +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @vocab/cli
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`87333d7`](https://github.com/seek-oss/vocab/commit/87333d79c4a883b07d7d8f2c272b16e2243c49bd) [#80](https://github.com/seek-oss/vocab/pull/80) Thanks [@askoufis](https://github.com/askoufis)! - Enable the creation of generated languages via the `generatedLanguages` config.
|
|
8
|
+
See [the docs] for more information and examples.
|
|
9
|
+
|
|
10
|
+
[the docs]: https://github.com/seek-oss/vocab#generated-languages
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`87333d7`](https://github.com/seek-oss/vocab/commit/87333d79c4a883b07d7d8f2c272b16e2243c49bd)]:
|
|
15
|
+
- @vocab/core@1.1.0
|
|
16
|
+
|
|
17
|
+
## 1.0.1
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [`3ec6dba`](https://github.com/seek-oss/vocab/commit/3ec6dbaad590299cc33e2d9d4a877576eb05853a) [#63](https://github.com/seek-oss/vocab/pull/63) Thanks [@jahredhope](https://github.com/jahredhope)! - Migrate to new @formatjs/icu-messageformat-parser as intl-messageformat-parser has been deprecated
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [[`3ec6dba`](https://github.com/seek-oss/vocab/commit/3ec6dbaad590299cc33e2d9d4a877576eb05853a)]:
|
|
24
|
+
- @vocab/core@1.0.2
|
|
25
|
+
|
|
26
|
+
## 1.0.0
|
|
27
|
+
|
|
28
|
+
### Major Changes
|
|
29
|
+
|
|
30
|
+
- [`3031054`](https://github.com/seek-oss/vocab/commit/303105440851db6126f0606e1607745b27dd981c) [#51](https://github.com/seek-oss/vocab/pull/51) Thanks [@jahredhope](https://github.com/jahredhope)! - Release v1.0.0
|
|
31
|
+
|
|
32
|
+
Release Vocab as v1.0.0 to signify a stable API and support future [semver versioning](https://semver.org/) releases.
|
|
33
|
+
|
|
34
|
+
Vocab has seen a lot of iteration and changes since it was first published on 20 November 2020. We are now confident with the API and believe Vocab is ready for common use.
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- Updated dependencies [[`0074382`](https://github.com/seek-oss/vocab/commit/007438273ef70f5d5ded45777933651ad8df36f6), [`3031054`](https://github.com/seek-oss/vocab/commit/303105440851db6126f0606e1607745b27dd981c)]:
|
|
39
|
+
- @vocab/core@1.0.0
|
|
40
|
+
- @vocab/phrase@1.0.0
|
|
41
|
+
|
|
3
42
|
## 0.0.16
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -2,34 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Vocab is a strongly typed internationalization framework for React.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Vocab helps you ship multiple languages without compromising the reliability of your site or slowing down delivery.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Shareable translations
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Translations are co-located with the components that use them. Vocab uses the module graph allowing shared components to be installed with package managers like npm, just like any other module.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
$ npm i --save @vocab/cli @vocab/react @vocab/webpack
|
|
13
|
-
```
|
|
11
|
+
- Loading translations dynamically
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
Vocab only loads the current user's language. If the language changes Vocab can load the new language behind the scenes without reloading the page.
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
- Strongly typed with TypeScript
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
When using translations TypeScript will ensure code only accesses valid translations and translations are passed all required dynamic values.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
## Getting started
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
const VocabWebpackPlugin = require('@vocab/webpack').default;
|
|
21
|
+
### Step 1: Install Dependencies
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
Vocab is a monorepo with different packages you can install depending on your usage, the below list will get you started using the cli, React and webpack integrations.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
$ npm i --save @vocab/cli @vocab/react @vocab/webpack
|
|
30
27
|
```
|
|
31
28
|
|
|
32
|
-
### Step
|
|
29
|
+
### Step 2: Configure Vocab
|
|
33
30
|
|
|
34
31
|
You can configure Vocab directly when calling the API or via a `vocab.config.js` file.
|
|
35
32
|
|
|
@@ -113,7 +110,24 @@ So far, your app will run, but you're missing any translations other than the in
|
|
|
113
110
|
}
|
|
114
111
|
```
|
|
115
112
|
|
|
116
|
-
### Step 6:
|
|
113
|
+
### Step 6: [Optional] Set up Webpack plugin
|
|
114
|
+
|
|
115
|
+
Right now every language is loaded into your web application all the time, which could lead to a large bundle size. Ideally you will want to switch out the Node/default runtime for web runtime that will load only the active language.
|
|
116
|
+
|
|
117
|
+
This is done using the **VocabWebpackPlugin**. Applying this plugin to your client webpack configuration will replace all vocab files with a dynamic asynchronous chunks designed for the web.
|
|
118
|
+
|
|
119
|
+
**webpack.config.js**
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
const { VocabWebpackPlugin } = require('@vocab/webpack');
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
...,
|
|
126
|
+
plugins: [new VocabWebpackPlugin()]
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Step 7: [Optional] Optimize for fast page loading
|
|
117
131
|
|
|
118
132
|
Using the above method without optimizing what chunks webpack uses you may find the page needing to do an extra round trip to load languages on a page.
|
|
119
133
|
|
|
@@ -157,8 +171,10 @@ In the below example we use two messages, one that passes in a single parameter
|
|
|
157
171
|
Vocab will automatically parse these strings as ICU messages, identify the required parameters and ensure TypeScript knows the values must be passed in.
|
|
158
172
|
|
|
159
173
|
```tsx
|
|
160
|
-
t('my key with param', {name: 'Vocab'});
|
|
161
|
-
t('my key with component', {
|
|
174
|
+
t('my key with param', { name: 'Vocab' });
|
|
175
|
+
t('my key with component', {
|
|
176
|
+
Link: (children) => <a href="/foo">{children}</a>
|
|
177
|
+
});
|
|
162
178
|
```
|
|
163
179
|
|
|
164
180
|
## Configuration
|
|
@@ -168,6 +184,14 @@ Configuration can either be passed into the Node API directly or be gathered fro
|
|
|
168
184
|
**vocab.config.js**
|
|
169
185
|
|
|
170
186
|
```js
|
|
187
|
+
function capitalize(element) {
|
|
188
|
+
return element.toUpperCase();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function pad(message) {
|
|
192
|
+
return '[' + message + ']';
|
|
193
|
+
}
|
|
194
|
+
|
|
171
195
|
module.exports = {
|
|
172
196
|
devLanguage: 'en',
|
|
173
197
|
languages: [
|
|
@@ -176,11 +200,25 @@ module.exports = {
|
|
|
176
200
|
{ name: 'en-US', extends: 'en' },
|
|
177
201
|
{ name: 'fr-FR' }
|
|
178
202
|
],
|
|
203
|
+
/**
|
|
204
|
+
* An array of languages to generate based off translations for existing languages
|
|
205
|
+
* Default: []
|
|
206
|
+
*/
|
|
207
|
+
generatedLanguages: [
|
|
208
|
+
{
|
|
209
|
+
name: 'generatedLangauge',
|
|
210
|
+
extends: 'en',
|
|
211
|
+
generator: {
|
|
212
|
+
transformElement: capitalize,
|
|
213
|
+
transformMessage: pad
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
],
|
|
179
217
|
/**
|
|
180
218
|
* The root directory to compile and validate translations
|
|
181
219
|
* Default: Current working directory
|
|
182
220
|
*/
|
|
183
|
-
projectRoot:
|
|
221
|
+
projectRoot: './example/',
|
|
184
222
|
/**
|
|
185
223
|
* A custom suffix to name vocab translation directories
|
|
186
224
|
* Default: '.vocab'
|
|
@@ -193,6 +231,131 @@ module.exports = {
|
|
|
193
231
|
};
|
|
194
232
|
```
|
|
195
233
|
|
|
234
|
+
## Generated languages
|
|
235
|
+
|
|
236
|
+
Vocab supports the creation of generated languages via the `generatedLanguages` config.
|
|
237
|
+
|
|
238
|
+
Generated languages are created by running a message `generator` over every translation message in an existing translation.
|
|
239
|
+
A `generator` may contain a `transformElement` function, a `transformMessage` function, or both.
|
|
240
|
+
Both of these functions accept a single string parameter and return a string.
|
|
241
|
+
|
|
242
|
+
`transformElement` is applied to string literal values contained within `MessageFormatElement`s.
|
|
243
|
+
A `MessageFormatElement` is an object representing a node in the AST of a compiled translation message.
|
|
244
|
+
Simply put, any text that would end up being translated by a translator, i.e. anything that is not part of the [ICU Message syntax], will be passed to `transformElement`.
|
|
245
|
+
An example of a use case for this function would be adding [diacritics] to every letter in order to stress your UI from a vertical line-height perspective.
|
|
246
|
+
|
|
247
|
+
`transformMessage` receives the entire translation message _after_ `transformElement` has been applied to its individual elements.
|
|
248
|
+
An example of a use case for this function would be adding padding text to the start/end of your messages in order to easily identify which text in your app has not been extracted into a `translations.json` file.
|
|
249
|
+
|
|
250
|
+
By default, a generated language's messages will be based off the `devLanguage`'s messages, but this can be overridden by providing an `extends` value that references another language.
|
|
251
|
+
|
|
252
|
+
**vocab.config.js**
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
function capitalize(message) {
|
|
256
|
+
return message.toUpperCase();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function pad(message) {
|
|
260
|
+
return '[' + message + ']';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
module.exports = {
|
|
264
|
+
devLanguage: 'en',
|
|
265
|
+
languages: [{ name: 'en' }, { name: 'fr' }],
|
|
266
|
+
generatedLanguages: [
|
|
267
|
+
{
|
|
268
|
+
name: 'generatedLanguage',
|
|
269
|
+
extends: 'en',
|
|
270
|
+
generator: {
|
|
271
|
+
transformElement: capitalize,
|
|
272
|
+
transformMessage: pad
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
};
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Generated languages are consumed the same way as regular languages.
|
|
280
|
+
Any Vocab API that accepts a `language` parameter will work with a generated language as well as a regular language.
|
|
281
|
+
|
|
282
|
+
**App.tsx**
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
const App = () => (
|
|
286
|
+
<VocabProvider language="generatedLanguage">
|
|
287
|
+
...
|
|
288
|
+
</VocabProvider>
|
|
289
|
+
);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
[icu message syntax]: https://formatjs.io/docs/intl-messageformat/#message-syntax
|
|
293
|
+
[diacritics]: https://en.wikipedia.org/wiki/Diacritic
|
|
294
|
+
|
|
295
|
+
## Pseudo-localization
|
|
296
|
+
|
|
297
|
+
The `@vocab/pseudo-localize` package exports low-level functions that can be used for pseudo-localization of translation messages.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import {
|
|
301
|
+
extendVowels,
|
|
302
|
+
padString,
|
|
303
|
+
pseudoLocalize,
|
|
304
|
+
substituteCharacters
|
|
305
|
+
} from '@vocab/pseudo-localize';
|
|
306
|
+
|
|
307
|
+
const message = 'Hello';
|
|
308
|
+
|
|
309
|
+
// [Hello]
|
|
310
|
+
const paddedMessage = padString(message);
|
|
311
|
+
|
|
312
|
+
// Ḩẽƚƚö
|
|
313
|
+
const substitutedMessage = substituteCharacters(message);
|
|
314
|
+
|
|
315
|
+
// Heelloo
|
|
316
|
+
const extendedMessage = extendVowels(message);
|
|
317
|
+
|
|
318
|
+
// Extend the message and then substitute characters
|
|
319
|
+
// Ḩẽẽƚƚöö
|
|
320
|
+
const pseudoLocalizedMessage = pseudoLocalize(message);
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Pseudo-localization is a transformation that can be applied to a translation message.
|
|
324
|
+
Vocab's implementation of this transformation contains the following elements:
|
|
325
|
+
|
|
326
|
+
- _Start and end markers (`padString`):_ All strings are encapsulated in `[` and `]`. If a developer doesn’t see these characters they know the string has been clipped by an inflexible UI element.
|
|
327
|
+
- _Transformation of ASCII characters to extended character equivalents (`substituteCharacters`):_ Stresses the UI from a vertical line-height perspective, tests font and encoding support, and weeds out strings that haven’t been externalized correctly (they will not have the pseudo-localization applied to them).
|
|
328
|
+
- _Padding text (`extendVowels`):_ Simulates translation-induced expansion. Vocab's implementation of this involves repeating vowels (and `y`) to simulate a 40% expansion in the message's length.
|
|
329
|
+
|
|
330
|
+
This Netflix technology [blog post][blog post] inspired Vocab's implementation of this
|
|
331
|
+
functionality.
|
|
332
|
+
|
|
333
|
+
### Generating a pseudo-localized language using Vocab
|
|
334
|
+
|
|
335
|
+
Vocab can generate a pseudo-localized language via the [`generatedLanguages` config][generated languages config], either via the webpack plugin or your `vocab.config.js` file.
|
|
336
|
+
`@vocab/pseudo-localize` exports a `generator` that can be used directly in your config.
|
|
337
|
+
|
|
338
|
+
**vocab.config.js**
|
|
339
|
+
|
|
340
|
+
```js
|
|
341
|
+
const { generator } = require('@vocab/pseudo-localize');
|
|
342
|
+
|
|
343
|
+
module.exports = {
|
|
344
|
+
devLanguage: 'en',
|
|
345
|
+
languages: [{ name: 'en' }, { name: 'fr' }],
|
|
346
|
+
generatedLanguages: [
|
|
347
|
+
{
|
|
348
|
+
name: 'pseudo',
|
|
349
|
+
extends: 'en',
|
|
350
|
+
generator
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
};
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
[blog post]: https://netflixtechblog.com/pseudo-localization-netflix-12fff76fbcbe
|
|
357
|
+
[generated languages config]: #generated-languages
|
|
358
|
+
|
|
196
359
|
## Use without React
|
|
197
360
|
|
|
198
361
|
If you need to use Vocab outside of React, you can access the returned Vocab file directly. You'll then be responsible for when to load translations and how to update on translation load.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vocab/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "dist/vocab-cli.cjs.js",
|
|
5
5
|
"module": "dist/vocab-cli.esm.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/env-ci": "^3.1.0",
|
|
13
|
-
"@vocab/core": "^
|
|
14
|
-
"@vocab/phrase": "^0.0
|
|
13
|
+
"@vocab/core": "^1.1.0",
|
|
14
|
+
"@vocab/phrase": "^1.0.0",
|
|
15
15
|
"env-ci": "^5.0.2",
|
|
16
16
|
"fast-glob": "^3.2.4",
|
|
17
17
|
"form-data": "^3.0.0",
|
|
18
|
-
"intl-messageformat-parser": "^6.0.16",
|
|
19
18
|
"node-fetch": "^2.6.1",
|
|
20
19
|
"prettier": "^2.1.2",
|
|
21
20
|
"yargs": "^16.1.0"
|