Skip to content

Commit

Permalink
Remove MessageContext.formatToParts
Browse files Browse the repository at this point in the history
  • Loading branch information
stasm committed Dec 12, 2017
1 parent 087978b commit 8c419b1
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 298 deletions.
5 changes: 4 additions & 1 deletion fluent/CHANGELOG.md
Expand Up @@ -2,7 +2,10 @@

## Unreleased

-
- Remove MessageContext.formatToParts.

It's only use-case was passing React elements as arguments to
translations which is now possible thanks to DOM overlays (#101).


## fluent 0.4.2 (November 27, 2017)
Expand Down
66 changes: 2 additions & 64 deletions fluent/src/context.js
@@ -1,6 +1,5 @@
import resolve from './resolver';
import parse from './parser';
import { FluentNone } from './types';

/**
* Message contexts are single-language stores of translations. They are
Expand Down Expand Up @@ -80,7 +79,7 @@ export class MessageContext {
* Return the internal representation of a message.
*
* The internal representation should only be used as an argument to
* `MessageContext.format` and `MessageContext.formatToParts`.
* `MessageContext.format`.
*
* @param {string} id - The identifier of the message to check.
* @returns {Any}
Expand Down Expand Up @@ -116,61 +115,6 @@ export class MessageContext {
return errors;
}

/**
* Format a message to an array of `FluentTypes` or null.
*
* Format a raw `message` from the context into an array of `FluentType`
* instances which may be used to build the final result. It may also return
* `null` if it has a null value. `args` will be used to resolve references
* to external arguments inside of the translation.
*
* See the documentation of {@link MessageContext#format} for more
* information about error handling.
*
* In case of errors `format` will try to salvage as much of the translation
* as possible and will still return a string. For performance reasons, the
* encountered errors are not returned but instead are appended to the
* `errors` array passed as the third argument.
*
* ctx.addMessages('hello = Hello, { $name }!');
* const hello = ctx.getMessage('hello');
* ctx.formatToParts(hello, { name: 'Jane' }, []);
* // → ['Hello, ', '\u2068', 'Jane', '\u2069']
*
* The returned parts need to be formatted via `valueOf` before they can be
* used further. This will ensure all values are correctly formatted
* according to the `MessageContext`'s locale.
*
* const parts = ctx.formatToParts(hello, { name: 'Jane' }, []);
* const str = parts.map(part => part.valueOf(ctx)).join('');
*
* @see MessageContext#format
* @param {Object | string} message
* @param {Object | undefined} args
* @param {Array} errors
* @returns {?Array<FluentType>}
*/
formatToParts(message, args, errors) {
// optimize entities which are simple strings with no attributes
if (typeof message === 'string') {
return [message];
}

// optimize simple-string entities with attributes
if (typeof message.val === 'string') {
return [message.val];
}

// optimize entities with null values
if (message.val === undefined) {
return null;
}

const result = resolve(this, args, message, errors);

return result instanceof FluentNone ? null : result;
}

/**
* Format a message to a string or null.
*
Expand Down Expand Up @@ -217,13 +161,7 @@ export class MessageContext {
return null;
}

const result = resolve(this, args, message, errors);

if (result instanceof FluentNone) {
return null;
}

return result.map(part => part.valueOf(this)).join('');
return resolve(this, args, message, errors);
}

_memoizeIntlObject(ctor, opts) {
Expand Down
53 changes: 12 additions & 41 deletions fluent/src/resolver.js
Expand Up @@ -59,27 +59,6 @@ const FSI = '\u2068';
const PDI = '\u2069';


/**
* Helper for computing the total character length of a placeable.
*
* Used in Pattern.
*
* @param {Object} env
* Resolver environment object.
* @param {Array} parts
* List of parts of a placeable.
* @returns {Number}
* @private
*/
function PlaceableLength(env, parts) {
const { ctx } = env;
return parts.reduce(
(sum, part) => sum + part.valueOf(ctx).length,
0
);
}


/**
* Helper for choosing the default value from a set of members.
*
Expand Down Expand Up @@ -504,26 +483,20 @@ function Pattern(env, ptn) {
continue;
}

const part = Type(env, elem);
const part = Type(env, elem).valueOf(ctx);

if (ctx._useIsolating) {
result.push(FSI);
}

if (Array.isArray(part)) {
const len = PlaceableLength(env, part);

if (len > MAX_PLACEABLE_LENGTH) {
errors.push(
new RangeError(
'Too many characters in placeable ' +
`(${len}, max allowed is ${MAX_PLACEABLE_LENGTH})`
)
);
result.push(new FluentNone());
} else {
result.push(...part);
}
if (part.length > MAX_PLACEABLE_LENGTH) {
errors.push(
new RangeError(
'Too many characters in placeable ' +
`(${part.length}, max allowed is ${MAX_PLACEABLE_LENGTH})`
)
);
result.push(part.slice(MAX_PLACEABLE_LENGTH));
} else {
result.push(part);
}
Expand All @@ -534,13 +507,11 @@ function Pattern(env, ptn) {
}

dirty.delete(ptn);
return result;
return result.join('');
}

/**
* Format a translation into an `FluentType`.
*
* The return value must be unwrapped via `valueOf` by the caller.
* Format a translation into a string.
*
* @param {MessageContext} ctx
* A MessageContext instance which will be used to resolve the
Expand All @@ -558,5 +529,5 @@ export default function resolve(ctx, args, message, errors = []) {
const env = {
ctx, args, errors, dirty: new WeakSet()
};
return Type(env, message);
return Type(env, message).valueOf(ctx);
}
48 changes: 14 additions & 34 deletions fluent/test/arguments_test.js
Expand Up @@ -217,9 +217,8 @@ suite('External arguments', function() {
let argval, args;

class CustomType extends FluentType {
// This Type doesn't valueOf to a string.
valueOf() {
return this.value;
return 'CUSTOM';
}
}

Expand All @@ -229,44 +228,25 @@ suite('External arguments', function() {
foo = { $arg }
bar = { foo }
`);
// The argument value is an arbitrary object.
argval = new Object();

args = {
// CustomType is a wrapper around the value
arg: new CustomType(argval)
arg: new CustomType()
};
});

test('interpolation', function(){
const msg = ctx.getMessage('foo');

const parts = ctx.formatToParts(msg, args, errs);
assert.equal(errs.length, 0);
test('interpolation', function () {
const msg = ctx.getMessage('foo');
const value = ctx.format(msg, args, errs);
assert.equal(value, 'CUSTOM');
assert.equal(errs.length, 0);
});

const [part] = parts;
assert.equal(part, args.arg);
assert.equal(part.$$typeof, Symbol.for('FluentType'));
assert.equal(FluentType.isTypeOf(part), true);

const vals = parts.map(part => part.valueOf(ctx));
assert.deepEqual(vals, [argval]);
});

test('nested interpolation', function(){
const msg = ctx.getMessage('bar');

const parts = ctx.formatToParts(msg, args, errs);
assert.equal(errs.length, 0);

const [part] = parts;
assert.equal(part, args.arg);
assert.equal(part.$$typeof, Symbol.for('FluentType'));
assert.equal(FluentType.isTypeOf(part), true);

const vals = parts.map(part => part.valueOf(ctx));
assert.deepEqual(vals, [argval]);
test('nested interpolation', function () {
const msg = ctx.getMessage('bar');
const value = ctx.format(msg, args, errs);
assert.equal(value, 'CUSTOM');
assert.equal(errs.length, 0);
});
});
});

});

0 comments on commit 8c419b1

Please sign in to comment.