Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n: Add create-i18n function #21182

Merged
merged 18 commits into from
Mar 27, 2020
2 changes: 1 addition & 1 deletion packages/i18n/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- Add `isRTL` function ([#20298](https://github.com/WordPress/gutenberg/pull/20298))
- Include TypeScript type declarations ([#18942](https://github.com/WordPress/gutenberg/pull/18942))

- Add `createI18n` method to allow creation of multiple i18n instances ([#21182](https://github.com/WordPress/gutenberg/pull/21182))

## 3.1.0 (2018-11-15)

Expand Down
13 changes: 13 additions & 0 deletions packages/i18n/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ For a complete example, see the [Internationalization section of the Block Edito

<!-- START TOKEN(Autogenerated API docs) -->

<a name="createI18n" href="#createI18n">#</a> **createI18n**

Create an i18n instance

_Parameters_

- _initialData_ `[LocaleData]`: Locale data configuration.
- _initialDomain_ `[string]`: Domain for which configuration applies.

_Returns_

- `I18n`: I18n instance

<a name="isRTL" href="#isRTL">#</a> **isRTL**

Check if current locale is RTL.
Expand Down
200 changes: 200 additions & 0 deletions packages/i18n/src/create-i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/**
* External dependencies
*/
import Tannin from 'tannin';

/**
* @typedef {Record<string,any>} LocaleData
*/

/**
* Default locale data to use for Tannin domain when not otherwise provided.
* Assumes an English plural forms expression.
*
* @type {LocaleData}
*/
const DEFAULT_LOCALE_DATA = {
'': {
/** @param {number} n */
plural_forms( n ) {
return n === 1 ? 0 : 1;
},
},
};

/**
* An i18n instance
*
* @typedef {Object} I18n
* @property {Function} setLocaleData Merges locale data into the Tannin instance by domain. Accepts data in a
* Jed-formatted JSON object shape.
* @property {Function} __ Retrieve the translation of text.
* @property {Function} _x Retrieve translated string with gettext context.
* @property {Function} _n Translates and retrieves the singular or plural form based on the supplied
* number.
* @property {Function} _nx Translates and retrieves the singular or plural form based on the supplied
* number, with gettext context.
* @property {Function} isRTL Check if current locale is RTL.
*/

/**
* Create an i18n instance
*
* @param {LocaleData} [initialData] Locale data configuration.
* @param {string} [initialDomain] Domain for which configuration applies.
* @return {I18n} I18n instance
*/
export const createI18n = ( initialData, initialDomain ) => {
/**
* The underlying instance of Tannin to which exported functions interface.
*
* @type {Tannin}
*/
const tannin = new Tannin( {} );

/**
* Merges locale data into the Tannin instance by domain. Accepts data in a
* Jed-formatted JSON object shape.
*
* @see http://messageformat.github.io/Jed/
*
* @param {LocaleData} [data] Locale data configuration.
sirreal marked this conversation as resolved.
Show resolved Hide resolved
sirreal marked this conversation as resolved.
Show resolved Hide resolved
* @param {string} [domain] Domain for which configuration applies.
*/
const setLocaleData = ( data, domain = 'default' ) => {
tannin.data[ domain ] = {
...DEFAULT_LOCALE_DATA,
...tannin.data[ domain ],
...data,
};

// Populate default domain configuration (supported locale date which omits
// a plural forms expression).
tannin.data[ domain ][ '' ] = {
...DEFAULT_LOCALE_DATA[ '' ],
...tannin.data[ domain ][ '' ],
};
};

/**
* Wrapper for Tannin's `dcnpgettext`. Populates default locale data if not
* otherwise previously assigned.
*
* @param {string|undefined} domain Domain to retrieve the translated text.
* @param {string|undefined} 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.
*/
const dcnpgettext = (
domain = 'default',
context,
single,
plural,
number
) => {
if ( ! tannin.data[ domain ] ) {
setLocaleData( undefined, domain );
}

return tannin.dcnpgettext( domain, context, single, plural, number );
};

/**
* 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.
*/
const __ = ( 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.
*/
const _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.
*/
const _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.
*/
const _nx = ( single, plural, number, context, domain ) => {
return dcnpgettext( domain, context, single, plural, number );
};

/**
* Check if current locale is RTL.
*
* **RTL (Right To Left)** is a locale property indicating that text is written from right to left.
* For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common
* language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages,
* including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`).
*
* @return {boolean} Whether locale is RTL.
*/
const isRTL = () => {
return 'rtl' === _x( 'ltr', 'text direction' );
};

if ( initialData ) {
setLocaleData( initialData, initialDomain );
}

return {
setLocaleData,
__,
_x,
_n,
_nx,
isRTL,
};
};
96 changes: 96 additions & 0 deletions packages/i18n/src/default-i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Internal dependencies
*/
import { createI18n } from './create-i18n';

const i18n = createI18n();

/*
* Comments in this file are duplicated from ./i18n due to
* https://github.com/WordPress/gutenberg/pull/20318#issuecomment-590837722
*/

/**
* @typedef {import('./create-i18n').LocaleData} LocaleData
*/

/**
* Merges locale data into the Tannin instance by domain. Accepts data in a
* Jed-formatted JSON object shape.
*
* @see http://messageformat.github.io/Jed/
*
* @param {LocaleData} [data] Locale data configuration.
sirreal marked this conversation as resolved.
Show resolved Hide resolved
* @param {string} [domain] Domain for which configuration applies.
*/
export const setLocaleData = i18n.setLocaleData.bind( i18n );

/**
* 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 const __ = i18n.__.bind( i18n );

/**
* 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 const _x = i18n._x.bind( i18n );

/**
* 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 const _n = i18n._n.bind( i18n );

/**
* 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 const _nx = i18n._nx.bind( i18n );

/**
* Check if current locale is RTL.
*
* **RTL (Right To Left)** is a locale property indicating that text is written from right to left.
* For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common
* language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages,
* including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`).
*
* @return {boolean} Whether locale is RTL.
*/
export const isRTL = i18n.isRTL.bind( i18n );
Loading