@vocab/types
Advanced tools
Comparing version 1.0.1 to 1.1.0
# @vocab/types | ||
## 1.1.0 | ||
### Minor Changes | ||
- [`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. | ||
See [the docs] for more information and examples. | ||
[the docs]: https://github.com/seek-oss/vocab#generated-languages | ||
## 1.0.1 | ||
@@ -4,0 +13,0 @@ |
@@ -34,3 +34,3 @@ export { FormatXMLElementFn } from 'intl-messageformat'; | ||
/** | ||
* Retrieve already loaded messages. Will return null if no messages have not been loaded. | ||
* Retrieve already loaded messages. Will return null if no messages have been loaded. | ||
*/ | ||
@@ -47,2 +47,11 @@ getLoadedMessages: (language: Language, locale?: string) => ParsedICUMessages<FormatFnByKey> | null; | ||
} | ||
export interface MessageGenerator { | ||
transformElement?: (element: string) => string; | ||
transformMessage?: (message: string) => string; | ||
} | ||
export interface GeneratedLanguageTarget { | ||
name: LanguageName; | ||
extends?: LanguageName; | ||
generator: MessageGenerator; | ||
} | ||
export interface UserConfig { | ||
@@ -62,2 +71,6 @@ /** | ||
/** | ||
* An array of languages to generate from existing translations | ||
*/ | ||
generatedLanguages?: Array<GeneratedLanguageTarget>; | ||
/** | ||
* A custom suffix to name vocab translation directories | ||
@@ -64,0 +77,0 @@ */ |
{ | ||
"name": "@vocab/types", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"main": "dist/vocab-types.cjs.js", | ||
@@ -5,0 +5,0 @@ "module": "dist/vocab-types.esm.js", |
149
README.md
@@ -187,2 +187,10 @@ # Vocab | ||
```js | ||
function capitalize(element) { | ||
return element.toUpperCase(); | ||
} | ||
function pad(message) { | ||
return '[' + message + ']'; | ||
} | ||
module.exports = { | ||
@@ -197,6 +205,20 @@ devLanguage: 'en', | ||
/** | ||
* An array of languages to generate based off translations for existing languages | ||
* Default: [] | ||
*/ | ||
generatedLanguages: [ | ||
{ | ||
name: 'generatedLangauge', | ||
extends: 'en', | ||
generator: { | ||
transformElement: capitalize, | ||
transformMessage: pad | ||
} | ||
} | ||
], | ||
/** | ||
* The root directory to compile and validate translations | ||
* Default: Current working directory | ||
*/ | ||
projectRoot: './example/'; | ||
projectRoot: './example/', | ||
/** | ||
@@ -214,2 +236,127 @@ * A custom suffix to name vocab translation directories | ||
## Generated languages | ||
Vocab supports the creation of generated languages via the `generatedLanguages` config. | ||
Generated languages are created by running a message `generator` over every translation message in an existing translation. | ||
A `generator` may contain a `transformElement` function, a `transformMessage` function, or both. | ||
Both of these functions accept a single string parameter and return a string. | ||
`transformElement` is applied to string literal values contained within `MessageFormatElement`s. | ||
A `MessageFormatElement` is an object representing a node in the AST of a compiled translation message. | ||
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`. | ||
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. | ||
`transformMessage` receives the entire translation message _after_ `transformElement` has been applied to its individual elements. | ||
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. | ||
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. | ||
**vocab.config.js** | ||
```js | ||
function capitalize(message) { | ||
return message.toUpperCase(); | ||
} | ||
function pad(message) { | ||
return '[' + message + ']'; | ||
} | ||
module.exports = { | ||
devLanguage: 'en', | ||
languages: [{ name: 'en' }, { name: 'fr' }], | ||
generatedLanguages: [ | ||
{ | ||
name: 'generatedLanguage', | ||
extends: 'en', | ||
generator: { | ||
transformElement: capitalize, | ||
transformMessage: pad | ||
} | ||
} | ||
] | ||
}; | ||
``` | ||
Generated languages are consumed the same way as regular languages. | ||
Any Vocab API that accepts a `language` parameter will work with a generated language as well as a regular language. | ||
**App.tsx** | ||
```tsx | ||
const App = () => ( | ||
<VocabProvider language="generatedLanguage"> | ||
... | ||
</VocabProvider> | ||
); | ||
``` | ||
[icu message syntax]: https://formatjs.io/docs/intl-messageformat/#message-syntax | ||
[diacritics]: https://en.wikipedia.org/wiki/Diacritic | ||
## Pseudo-localization | ||
The `@vocab/pseudo-localize` package exports low-level functions that can be used for pseudo-localization of translation messages. | ||
```ts | ||
import { | ||
extendVowels, | ||
padString, | ||
pseudoLocalize, | ||
substituteCharacters | ||
} from '@vocab/pseudo-localize'; | ||
const message = 'Hello'; | ||
// [Hello] | ||
const paddedMessage = padString(message); | ||
// Ḩẽƚƚö | ||
const substitutedMessage = substituteCharacters(message); | ||
// Heelloo | ||
const extendedMessage = extendVowels(message); | ||
// Extend the message and then substitute characters | ||
// Ḩẽẽƚƚöö | ||
const pseudoLocalizedMessage = pseudoLocalize(message); | ||
``` | ||
Pseudo-localization is a transformation that can be applied to a translation message. | ||
Vocab's implementation of this transformation contains the following elements: | ||
- _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. | ||
- _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). | ||
- _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. | ||
This Netflix technology [blog post][blog post] inspired Vocab's implementation of this | ||
functionality. | ||
### Generating a pseudo-localized language using Vocab | ||
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. | ||
`@vocab/pseudo-localize` exports a `generator` that can be used directly in your config. | ||
**vocab.config.js** | ||
```js | ||
const { generator } = require('@vocab/pseudo-localize'); | ||
module.exports = { | ||
devLanguage: 'en', | ||
languages: [{ name: 'en' }, { name: 'fr' }], | ||
generatedLanguages: [ | ||
{ | ||
name: 'pseudo', | ||
extends: 'en', | ||
generator | ||
} | ||
] | ||
}; | ||
``` | ||
[blog post]: https://netflixtechblog.com/pseudo-localization-netflix-12fff76fbcbe | ||
[generated languages config]: #generated-languages | ||
## Use without React | ||
@@ -216,0 +363,0 @@ |
@@ -52,3 +52,3 @@ export { FormatXMLElementFn } from 'intl-messageformat'; | ||
/** | ||
* Retrieve already loaded messages. Will return null if no messages have not been loaded. | ||
* Retrieve already loaded messages. Will return null if no messages have been loaded. | ||
*/ | ||
@@ -72,2 +72,16 @@ getLoadedMessages: ( | ||
export interface MessageGenerator { | ||
transformElement?: (element: string) => string; | ||
transformMessage?: (message: string) => string; | ||
} | ||
export interface GeneratedLanguageTarget { | ||
// The name or tag of a generated language | ||
name: LanguageName; | ||
// Language to generate translations from. Defaults to the dev language. | ||
extends?: LanguageName; | ||
// Function used to generate translations | ||
generator: MessageGenerator; | ||
} | ||
export interface UserConfig { | ||
@@ -87,2 +101,6 @@ /** | ||
/** | ||
* An array of languages to generate from existing translations | ||
*/ | ||
generatedLanguages?: Array<GeneratedLanguageTarget>; | ||
/** | ||
* A custom suffix to name vocab translation directories | ||
@@ -89,0 +107,0 @@ */ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29145
236
448