diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 8eb9757eb2088..700b3b520eefb 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New Feature + +- Add `isRTL` function (#20298) + ## 3.1.0 (2018-11-15) ### Enhancements diff --git a/packages/i18n/README.md b/packages/i18n/README.md index 50376d53c3647..21847b5f3f017 100644 --- a/packages/i18n/README.md +++ b/packages/i18n/README.md @@ -27,6 +27,19 @@ For a complete example, see the [Internationalization section of the Block Edito +# **isRTL** + +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`). + +_Returns_ + +- `boolean`: Whether locale is RTL. + # **setLocaleData** Merges locale data into the Tannin instance by domain. Accepts data in a diff --git a/packages/i18n/src/index.js b/packages/i18n/src/index.js index c696cb9f76400..2b4286819c9ca 100644 --- a/packages/i18n/src/index.js +++ b/packages/i18n/src/index.js @@ -150,6 +150,20 @@ export function _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. + */ +export function isRTL() { + return 'rtl' === _x( 'ltr', 'text direction' ); +} + /** * Returns a formatted string. If an error occurs in applying the format, the * original format string is returned. diff --git a/packages/i18n/src/test/index.js b/packages/i18n/src/test/index.js index b5e68537754df..5246bc8f3659b 100644 --- a/packages/i18n/src/test/index.js +++ b/packages/i18n/src/test/index.js @@ -1,8 +1,3 @@ -/** - * Internal dependencies - */ -import { sprintf, __, _x, _n, _nx, setLocaleData } from '../'; - // Mock memoization as identity function. Inline since Jest errors on out-of- // scope references in a mock callback. jest.mock( 'memize', () => ( fn ) => fn ); @@ -31,22 +26,34 @@ const additionalLocaleData = { '%d cat': [ '%d chat', '%d chats' ], }; -setLocaleData( localeData, 'test_domain' ); +// Get clean locale data +let sprintf, __, _x, _n, _nx, isRTL, setLocaleData; +beforeEach( () => { + const module = require.resolve( '..' ); + delete require.cache[ module ]; + ( { sprintf, __, _x, _n, _nx, isRTL, setLocaleData } = require( '..' ) ); +} ); describe( 'i18n', () => { describe( '__', () => { + beforeEach( setDefaultLocalData ); + it( 'use the translation', () => { expect( __( 'hello', 'test_domain' ) ).toBe( 'bonjour' ); } ); } ); describe( '_x', () => { + beforeEach( setDefaultLocalData ); + it( 'use the translation with context', () => { expect( _x( 'feed', 'verb', 'test_domain' ) ).toBe( 'nourrir' ); } ); } ); describe( '_n', () => { + beforeEach( setDefaultLocalData ); + it( 'use the plural form', () => { expect( _n( '%d banana', '%d bananas', 3, 'test_domain' ) ).toBe( '%d bananes' @@ -61,6 +68,8 @@ describe( 'i18n', () => { } ); describe( '_nx', () => { + beforeEach( setDefaultLocalData ); + it( 'use the plural form', () => { expect( _nx( '%d apple', '%d apples', 3, 'fruit', 'test_domain' ) @@ -74,7 +83,31 @@ describe( 'i18n', () => { } ); } ); - describe( 'sprintf()', () => { + describe( 'isRTL', () => { + const ARLocaleData = { + '': { + plural_forms: + 'nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;', + language: 'ar', + localeSlug: 'ar', + }, + 'text direction\u0004ltr': [ 'rtl' ], + Back: [ 'رجوع' ], + }; + + it( 'is false for non-rtl', () => { + expect( isRTL() ).toBe( false ); + } ); + + it( 'is true for rtl', () => { + setLocaleData( ARLocaleData ); + expect( isRTL() ).toBe( true ); + } ); + } ); + + describe( 'sprintf', () => { + beforeEach( setDefaultLocalData ); + it( 'absorbs errors', () => { // Disable reason: Failing case is the purpose of the test. // eslint-disable-next-line @wordpress/valid-sprintf @@ -93,6 +126,7 @@ describe( 'i18n', () => { describe( 'setLocaleData', () => { beforeAll( () => { + setDefaultLocalData(); setLocaleData( additionalLocaleData, 'test_domain' ); } ); @@ -147,3 +181,7 @@ describe( 'i18n', () => { } ); } ); } ); + +function setDefaultLocalData() { + setLocaleData( localeData, 'test_domain' ); +}