This repository has been archived by the owner on Jul 9, 2018. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WordPress i18n package: Initial commit
- Loading branch information
1 parent
138c958
commit ec9d4b4
Showing
8 changed files
with
912 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package-lock=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
i18n | ||
====== | ||
|
||
Internationalization utilities for client-side localization. | ||
|
||
https://codex.wordpress.org/I18n_for_WordPress_Developers | ||
|
||
|
||
## Installation | ||
|
||
Install the module: | ||
|
||
```bash | ||
npm install @wordpress/i18n --save-dev | ||
``` | ||
|
||
```js | ||
import { sprintf, _n } from '@wordpress/i18n'; | ||
|
||
sprintf( _n( '%d hat', '%d hats', 4, 'text-domain' ), 4 ); | ||
// 4 hats | ||
``` | ||
|
||
Note that you will not need to specify [domain](https://codex.wordpress.org/I18n_for_WordPress_Developers#Text_Domains) for the strings. | ||
|
||
## Build | ||
|
||
Included is a [custom Babel plugin](./tools/babel-plugin.js) which, when integrated into a Babel configuration, will scan all processed JavaScript files for use of localization functions. It then compiles these into a [gettext POT formatted](https://en.wikipedia.org/wiki/Gettext) file as a template for translation. By default the output file will be written to `gettext.pot` of the root project directory. This can be overridden using the `"output"` option of the plugin: | ||
|
||
```json | ||
[ "babel-plugin-wp-i18n", { | ||
"output": "languages/myplugin.pot" | ||
} ] | ||
``` | ||
|
||
The package also includes a `pot-to-php` script used to generate a php files containing the messages listed in a `.pot` file. This is usefull to trick WordPress.org translation strings discovery since at the moment, WordPress.org is not capable of parsing strings directly from JavaScript files. | ||
|
||
```sh | ||
node tools/pot-to-php languages/myplugin.pot languages/myplugin-translations.php text-domain | ||
``` | ||
|
||
## API | ||
|
||
`__( text: string, domain: string ): string` | ||
|
||
Retrieve the translation of text. | ||
|
||
See: https://developer.wordpress.org/reference/functions/__/ | ||
|
||
`_x( text: string, context: string, domain: string ): string` | ||
|
||
Retrieve translated string with gettext context. | ||
|
||
See: https://developer.wordpress.org/reference/functions/_x/ | ||
|
||
`_n( single: string, plural: string, number: Number, domain: string ): string` | ||
|
||
Translates and retrieves the singular or plural form based on the supplied number. | ||
|
||
See: https://developer.wordpress.org/reference/functions/_n/ | ||
|
||
`_nx( single: string, plural: string, number: Number, context: string, domain: string ): string` | ||
|
||
Translates and retrieves the singular or plural form based on the supplied number, with gettext context. | ||
|
||
See: https://developer.wordpress.org/reference/functions/_nx/ | ||
|
||
`sprintf( format: string, ...args: mixed[] ): string` | ||
|
||
Returns a formatted string. | ||
|
||
See: http://www.diveintojavascript.com/projects/javascript-sprintf | ||
|
||
`setLocaleData( data: Object, domain: string )` | ||
|
||
Creates a new Jed instance with specified locale data configuration. | ||
|
||
`getI18n(): Jed` | ||
|
||
Returns the current Jed instance, initializing with a default configuration if not already assigned. | ||
|
||
See: http://messageformat.github.io/Jed/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "@wordpress/i18n", | ||
"version": "1.0.0-beta.0", | ||
"description": "WordPress i18n library", | ||
"author": "WordPress", | ||
"license": "GPL-2.0-or-later", | ||
"keywords": [ | ||
"i18n" | ||
], | ||
"homepage": "https://github.com/WordPress/packages/tree/master/packages/i18n/README.md", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/WordPress/packages.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/WordPress/packages/issues" | ||
}, | ||
"main": "build/index.js", | ||
"module": "build-module/index.js", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"gettext-parser": "^1.3.1", | ||
"jed": "^1.1.1", | ||
"lodash": "^4.17.5", | ||
"memize": "^1.0.5" | ||
}, | ||
"devDependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-traverse": "^6.26.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import Jed from 'jed'; | ||
import memoize from 'memize'; | ||
|
||
let i18n; | ||
|
||
/** | ||
* Log to console, once per message; or more precisely, per referentially equal | ||
* argument set. Because Jed throws errors, we log these to the console instead | ||
* to avoid crashing the application. | ||
* | ||
* @param {...*} args Arguments to pass to `console.error` | ||
*/ | ||
const logErrorOnce = memoize( console.error ); // eslint-disable-line no-console | ||
|
||
/** | ||
* Merges locale data into the Jed instance by domain. Creates a new Jed | ||
* instance if one has not yet been assigned. | ||
* | ||
* @see http://messageformat.github.io/Jed/ | ||
* | ||
* @param {?Object} localeData Locale data configuration. | ||
* @param {?string} domain Domain for which configuration applies. | ||
*/ | ||
export function setLocaleData( localeData = { '': {} }, domain = 'default' ) { | ||
if ( ! i18n ) { | ||
i18n = new Jed( { | ||
domain: 'default', | ||
locale_data: { | ||
default: {}, | ||
}, | ||
} ); | ||
} | ||
|
||
i18n.options.locale_data[ domain ] = localeData; | ||
} | ||
|
||
/** | ||
* Returns the current Jed instance, initializing with a default configuration | ||
* if not already assigned. | ||
* | ||
* @return {Jed} Jed instance. | ||
*/ | ||
export function getI18n() { | ||
if ( ! i18n ) { | ||
setLocaleData(); | ||
} | ||
|
||
return i18n; | ||
} | ||
|
||
/** | ||
* Wrapper for Jed's `dcnpgettext`, its most qualified function. Absorbs errors | ||
* which are thrown as the result of invalid translation. | ||
* | ||
* @param {?string} domain Domain to retrieve the translated text. | ||
* @param {?string} context Context information for the translators. | ||
* @param {string} single Text to translate if non-plural. Used as fallback | ||
* return value on a caught error. | ||
* @param {?string} plural The text to be used if the number is plural. | ||
* @param {?number} number The number to compare against to use either the | ||
* singular or plural form. | ||
* | ||
* @return {string} The translated string. | ||
*/ | ||
export function dcnpgettext( domain = 'default', context, single, plural, number ) { | ||
try { | ||
return getI18n().dcnpgettext( domain, context, single, plural, number ); | ||
} catch ( error ) { | ||
logErrorOnce( 'Jed localization error: \n\n' + error.toString() ); | ||
|
||
return single; | ||
} | ||
} | ||
|
||
/** | ||
* Retrieve the translation of text. | ||
* | ||
* @see https://developer.wordpress.org/reference/functions/__/ | ||
* | ||
* @param {string} text Text to translate. | ||
* @param {?string} domain Domain to retrieve the translated text. | ||
* | ||
* @return {string} Translated text. | ||
*/ | ||
export function __( text, domain ) { | ||
return dcnpgettext( domain, undefined, text ); | ||
} | ||
|
||
/** | ||
* Retrieve translated string with gettext context. | ||
* | ||
* @see https://developer.wordpress.org/reference/functions/_x/ | ||
* | ||
* @param {string} text Text to translate. | ||
* @param {string} context Context information for the translators. | ||
* @param {?string} domain Domain to retrieve the translated text. | ||
* | ||
* @return {string} Translated context string without pipe. | ||
*/ | ||
export function _x( text, context, domain ) { | ||
return dcnpgettext( domain, context, text ); | ||
} | ||
|
||
/** | ||
* Translates and retrieves the singular or plural form based on the supplied | ||
* number. | ||
* | ||
* @see https://developer.wordpress.org/reference/functions/_n/ | ||
* | ||
* @param {string} single The text to be used if the number is singular. | ||
* @param {string} plural The text to be used if the number is plural. | ||
* @param {number} number The number to compare against to use either the | ||
* singular or plural form. | ||
* @param {?string} domain Domain to retrieve the translated text. | ||
* | ||
* @return {string} The translated singular or plural form. | ||
*/ | ||
export function _n( single, plural, number, domain ) { | ||
return dcnpgettext( domain, undefined, single, plural, number ); | ||
} | ||
|
||
/** | ||
* Translates and retrieves the singular or plural form based on the supplied | ||
* number, with gettext context. | ||
* | ||
* @see https://developer.wordpress.org/reference/functions/_nx/ | ||
* | ||
* @param {string} single The text to be used if the number is singular. | ||
* @param {string} plural The text to be used if the number is plural. | ||
* @param {number} number The number to compare against to use either the | ||
* singular or plural form. | ||
* @param {string} context Context information for the translators. | ||
* @param {?string} domain Domain to retrieve the translated text. | ||
* | ||
* @return {string} The translated singular or plural form. | ||
*/ | ||
export function _nx( single, plural, number, context, domain ) { | ||
return dcnpgettext( domain, context, single, plural, number ); | ||
} | ||
|
||
/** | ||
* Returns a formatted string. If an error occurs in applying the format, the | ||
* original format string is returned. | ||
* | ||
* @param {string} format The format of the string to generate. | ||
* @param {string[]} ...args Arguments to apply to the format. | ||
* | ||
* @see http://www.diveintojavascript.com/projects/javascript-sprintf | ||
* | ||
* @return {string} The formatted string. | ||
*/ | ||
export function sprintf( format, ...args ) { | ||
try { | ||
return Jed.sprintf( format, ...args ); | ||
} catch ( error ) { | ||
logErrorOnce( 'Jed sprintf error: \n\n' + error.toString() ); | ||
|
||
return format; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { dcnpgettext, sprintf } from '../'; | ||
|
||
// Mock memoization as identity function. Inline since Jest errors on out-of- | ||
// scope references in a mock callback. | ||
jest.mock( 'memize', () => ( fn ) => fn ); | ||
|
||
describe( 'i18n', () => { | ||
describe( 'dcnpgettext()', () => { | ||
it( 'absorbs errors', () => { | ||
const result = dcnpgettext( 'domain-without-data', undefined, 'Hello' ); | ||
|
||
expect( console ).toHaveErrored(); | ||
expect( result ).toBe( 'Hello' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'sprintf()', () => { | ||
it( 'absorbs errors', () => { | ||
const result = sprintf( 'Hello %(placeholder-not-provided)s' ); | ||
|
||
expect( console ).toHaveErrored(); | ||
expect( result ).toBe( 'Hello %(placeholder-not-provided)s' ); | ||
} ); | ||
} ); | ||
} ); |
Oops, something went wrong.