Skip to content

Commit

Permalink
Message: Provide Bidi structured text support (2/2)
Browse files Browse the repository at this point in the history
  • Loading branch information
rxaviers authored and nkovacs committed May 15, 2017
1 parent dd5770c commit 3ceb8b6
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 61 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ Read more details about locale at [UTS#35 locale][].

[Read more...](doc/api/message/load-messages.md)

- **`.messageFormatter( path ) ➡ function( [variables] )`**
- **`.messageFormatter( path [, options] ) ➡ function( [variables] )`**

Return a function that formats a message (using ICU message format pattern)
given its path and a set of variables into a user-readable string. It supports
Expand All @@ -525,9 +525,9 @@ Read more details about locale at [UTS#35 locale][].

[Read more...](doc/api/message/message-formatter.md)

- **`.formatMessage( path [, variables ] )`**
- **`.formatMessage( path [, variables, options ] )`**

Alias for `.messageFormatter( path )([ variables ])`.
Alias for `.messageFormatter( path [, options] )([ variables ])`.

### Number module

Expand Down
44 changes: 20 additions & 24 deletions doc/api/message/message-formatter.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## .messageFormatter( path, options ) ➡ function([ variables ])
## .messageFormatter( path [, options] ) ➡ function([ variables ])

Return a function that formats a message (using ICU message format pattern)
given its path and a set of variables into a user-readable string. It supports
Expand All @@ -16,22 +16,22 @@ String or Array containing the path of the message content, eg.

**options** (optional)

Options should be an Objects, where each property can be referenced by name.
The possible property having name recognizable by messageFormatter is "setBiDiSupport".
It should have Boolean value indicating whether Bidi structuring is to be imposed on formatted
message (like {"setBiDiSupport": true}).
Special Unicode Bidi marks are inserted depending on locale in order to preserve the text
flow of structured message which corresponds give local (from right-to-left for Bidi scripts
like Arabic, Hebrew or Pharsi and left-to-right otherwise.
For more info on Bidi structured text see:
http://cldr.unicode.org/development/development-process/design-proposals/bidi-handling-of-structured-text
A JSON object including none or any of the following options.

> **setBiDiSupport** Optional
>
> Boolean (default `false`) enable or disable the addition of Unicode BiDi
> control characters to all input to preserve the the integrity of the output
> when mixing LTR and RTL text, e.g., `{ setBiDiSupport: true }`.
>
> For more information on BiDi structured text see:
> http://cldr.unicode.org/development/development-process/design-proposals/bidi-handling-of-structured-text
**variables** (optional)

Variables can be Objects, where each property can be referenced by name inside a
message; or Arrays, where each entry of the Array can be used inside a message,
using numeric indices. When passing one or more arguments of other types,
they're converted to an Array and used as such.
A JSON object or an Array. When it's a JSON object, each key corresponds to a
message variable. When it's an Array, each item corresponds to a message
variable using numeric indices.

### Example

Expand Down Expand Up @@ -84,10 +84,6 @@ formatter = Globalize( "en" ).messageFormatter( "hello" );
formatter([ "Wolfgang", "Amadeus", "Mozart" ]);
// > "Hello, Wolfgang Amadeus Mozart"

// Numbered variables using function arguments.
formatter( "Wolfgang", "Amadeus", "Mozart" );
// > "Hello, Wolfgang Amadeus Mozart"

// Named variables using Object key-value pairs.
formatter = Globalize( "en" ).messageFormatter( "hey" );
formatter({
Expand Down Expand Up @@ -224,16 +220,16 @@ likeFormatter( 2 );
likeFormatter( 3 );
// > "You and 2 others liked this"
```
#### Bidi structured meessage
Globalize.loadMessages({
ar: { breadcrumb: "{0} >> {1} >> {2}" }
});
bidiFormatter = Globalize( "ar" ).messageFormatter( "breadcrumb", {"setBiDiSupport": true} );

#### BiDi structured meessage
Globalize.loadMessages({
ar: { breadcrumb: "{0} >> {1} >> {2}" }
});
bidiFormatter = Globalize( "ar" ).messageFormatter( "breadcrumb", { setBiDiSupport: true } );

bidiFormatter( "First", "Second", "Third" );
// > "Third << Second << First"


Read on [SlexAxton/messageFormatter.js][] for more information on regard of ICU
MessageFormat.

Expand Down
9 changes: 5 additions & 4 deletions src/message-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ Globalize._messageFormat = new messageFormatterRuntime(); // TODO setStrictNumbe
Globalize._validateParameterTypeMessageVariables = validateParameterTypeMessageVariables;

Globalize.messageFormatter =
Globalize.prototype.messageFormatter = function( /* path */ ) {
Globalize.prototype.messageFormatter = function( path, options ) {
options = options || {};
return Globalize[
runtimeKey( "messageFormatter", this._locale, [].slice.call( arguments, 0 ) )
runtimeKey( "messageFormatter", this._locale, [ path, options ] )
];
};

Globalize.formatMessage =
Globalize.prototype.formatMessage = function( path /* , variables */ ) {
return this.messageFormatter( path ).apply( {}, [].slice.call( arguments, 1 ) );
Globalize.prototype.formatMessage = function( path, variables, options ) {
return this.messageFormatter( path, options ).apply( {}, [ variables ] );
};

return Globalize;
Expand Down
20 changes: 10 additions & 10 deletions src/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ define([
messageCompiler, messageFormatterRuntime, messageFormatterFn, messageFormatterRuntimeBind,
alwaysArray ) {

var slice = [].slice;

/**
* .loadMessages( json )
*
Expand Down Expand Up @@ -64,19 +62,21 @@ Globalize.loadMessages = function( json ) {
*/
Globalize.messageFormatter =
Globalize.prototype.messageFormatter = function( path, options ) {
var cldr, formatter, message, pluralGenerator, returnFn,
args = slice.call( arguments, 0 );
var args, cldr, formatter, message, pluralGenerator, returnFn;

validateParameterPresence( path, "path" );
validateParameterType( path, "path", typeof path === "string" || Array.isArray( path ),
"a String nor an Array" );

path = alwaysArray( path );
cldr = this.cldr;
options = options || {};

validateDefaultLocale( cldr );
validateMessageBundle( cldr );

args = [ path, options ];
path = alwaysArray( path );

message = cldr.get( [ "globalize-messages/{bundle}" ].concat( path ) );
validateMessagePresence( path, message );

Expand Down Expand Up @@ -144,19 +144,19 @@ Globalize.prototype.messageFormatter = function( path, options ) {
};

/**
* .formatMessage( path [, variables] )
* .formatMessage( path [, variables, options] )
*
* @path [String or Array]
*
* @variables [Number, String, Array or Object]
*
* @options [object]
*
* Format a message given its path.
*/
Globalize.formatMessage =
Globalize.prototype.formatMessage = function( path /* , variables */ ) {
return ( arguments[ 1 ] && arguments[ 1 ].setBiDiSupport === true ) ?
this.messageFormatter( path, arguments[ 1 ] ).apply( {}, slice.call( arguments, 2 ) ) :
this.messageFormatter( path ).apply( {}, slice.call( arguments, 1 ) );
Globalize.prototype.formatMessage = function( path, variables, options ) {
return this.messageFormatter( path, options ).apply( {}, [ variables ] );
};

return Globalize;
Expand Down
16 changes: 6 additions & 10 deletions test/functional/message/format-message.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
define([
define([
"globalize",
"json!cldr-data/supplemental/likelySubtags.json",
"json!cldr-data/supplemental/plurals.json",
Expand Down Expand Up @@ -52,15 +52,11 @@ QUnit.test( "should format a message", function( assert ) {
}), "Hello, Beethoven" );
});

QUnit.test( "should format a message", function( assert ) {
assert.equal( Globalize( "en" ).formatMessage( "greetings/hello", {
name: "Beethoven"
}), "Hello, Beethoven" );
});

QUnit.test( "should support Bidi structured text", function( assert ) {
assert.equal( Globalize( "he" ).formatMessage( "breadcrumb", {"setBiDiSupport": true},
[ "Mozart", "Bethoven", "Dvorzak" ]
QUnit.test( "should support BiDi structured text", function( assert ) {
assert.equal( Globalize( "he" ).formatMessage(
"breadcrumb",
[ "Mozart", "Bethoven", "Dvorzak" ],
{ setBiDiSupport: true }
), "\u200FMozart\u200F >> \u200FBethoven\u200F >> \u200FDvorzak\u200F" );
});

Expand Down
18 changes: 8 additions & 10 deletions test/functional/message/message-formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,6 @@ QUnit.test( "should support ICU message format", function( assert ) {
assert.messageFormatter( "en", "greetings/helloArray", "Beethoven", "Hello, Beethoven" );
assert.messageFormatter( "en", "greetings/helloArray2", [ "Beethoven", "Mozart" ],
"Hello, Beethoven and Mozart" );
assert.equal(
Globalize( "en" ).messageFormatter( "greetings/helloArray2" )( "Beethoven", "Mozart" ),
"Hello, Beethoven and Mozart"
);
assert.messageFormatter( "en", "greetings/helloName", {
name: "Beethoven"
}, "Hello, Beethoven" );
Expand Down Expand Up @@ -201,9 +197,11 @@ QUnit.test( "should support ICU message format", function( assert ) {
}, "4th category" );
});

QUnit.test( "should support Bidi structured text", function( assert ) {
QUnit.test( "should support BiDi structured text", function( assert ) {
assert.equal(
Globalize( "he" ).messageFormatter( "helloArray", {"setBiDiSupport": true} )( "Beethoven", "Mozart" ),
Globalize( "he" ).messageFormatter( "helloArray", {
setBiDiSupport: true
})( "Beethoven", "Mozart" ),
"Hello, \u200FBeethoven\u200F & \u200FMozart\u200F"
);
});
Expand All @@ -228,8 +226,8 @@ QUnit.test( "should allow for runtime compilation", function( assert ) {
util.assertRuntimeBind(
assert,
Globalize( "en" ).messageFormatter( "amen" ),
"b639686813",
"Globalize(\"en\").messageFormatter(\"amen\")",
"b141291319",
"Globalize(\"en\").messageFormatter(\"amen\",{})",
function( runtimeArgs ) {
assert.equal(
runtimeArgs[ 0 ].toString(),
Expand All @@ -241,8 +239,8 @@ QUnit.test( "should allow for runtime compilation", function( assert ) {
util.assertRuntimeBind(
assert,
Globalize( "en" ).messageFormatter( "like" ),
"b328290139",
"Globalize(\"en\").messageFormatter(\"like\")",
"b452335545",
"Globalize(\"en\").messageFormatter(\"like\",{})",
function( runtimeArgs ) {
assert.equal(
runtimeArgs[ 0 ].toString(),
Expand Down

0 comments on commit 3ceb8b6

Please sign in to comment.