Created
September 29, 2016 17:58
-
-
Save segdeha/670ad8345ccb2773fad16bf5e6a43b96 to your computer and use it in GitHub Desktop.
Method for creating abstracted string generators
This file contains hidden or 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
/** | |
* Returns a function that composes strings from ES6 template literals. | |
* Based on http://stackoverflow.com/a/22619256/11577 | |
* | |
* @usage formatter`${0}, ${1}!`.format('Hello', 'world') // -> 'Hello, world!' | |
* | |
* @param array<string> literals Array of string literals | |
* @param array<mixed> substitutions Rest parameter of substitution values | |
* | |
* @return function | |
*/ | |
exports.formatter = function formatter(literals, ...substitutions) { | |
return { | |
format: function format() { | |
return literals.reduce((accumulator, part, i) => { | |
let sub = arguments[substitutions[i - 1]] | |
sub = Array.isArray(sub) ? combineMultiple(sub) : sub | |
return accumulator + sub + part | |
}) | |
} | |
} | |
} | |
/** | |
* Combine multiple values in an array in a standard way | |
* | |
* @usage combineMultiple(['Me']) // -> 'Me' | |
* @usage combineMultiple(['Me', 'You']) // -> 'Me & You' | |
* @usage combineMultiple(['Me', 'You', 'Us']) // -> 'Me, You & Us' | |
* | |
* @param array<mixed> Array of values | |
* | |
* @return string | |
*/ | |
function combineMultiple(arr) { | |
switch (arr.length) { | |
case 0: | |
return '' | |
case 1: | |
return `${arr[0]}` // always return a string | |
case 2: | |
return `${arr[0]} & ${arr[1]}` | |
default: | |
let lastVal = arr.pop() | |
return `${arr.join(', ')} & ${lastVal}` | |
} | |
} | |
// The idea is to create helpers (similar to `itemsAdded()` below) for creating | |
// the various formats of strings that will be needed in the activities | |
// interface. I haven’t worked out yet how this will mesh with the translation | |
// library. | |
/* | |
function itemsAdded() { | |
return formatter`${0} added ${1} ${2} to ${3}`.format.call(null, ...arguments) | |
} | |
itemsAdded(['James Chou'], 42, 'photos', 'Pretty Sunsets') | |
// => "James Chou added 42 photos to Pretty Sunsets" | |
itemsAdded(['James Chou', 'Terry Liu'], 42, 'photos', 'Pretty Sunsets') | |
// => "James Chou & Terry Liu added 42 photos to Pretty Sunsets" | |
itemsAdded(['James Chou', 'Terry Liu', 'Fan Zhang'], 42, 'photos', 'Pretty Sunsets') | |
// => "James Chou, Terry Liu & Fan Zhang added 42 photos to Pretty Sunsets" | |
*/ | |
// One way to use this for localiztion would be to create helpers based on | |
// locale. We could end up with a lot of functions, but it would give us exact | |
// control over the sentence structure for each language. But even my simple | |
// example below illustrates the complexity of localization. The word ‘photos’ | |
// would need to be translated before it hits the helper the way I have the | |
// functions written. | |
/* | |
let helpers = { | |
de: { | |
itemsAdded: () => formatter`${0} hinzugefügt ${1} ${2} zu ${3}`.format.call(null, ...arguments) | |
} | |
en: { | |
itemsAdded: () => formatter`${0} added ${1} ${2} to ${3}`.format.call(null, ...arguments) | |
}, | |
es: { | |
itemsAdded: () => formatter`${0} añadido ${1} ${2} a ${3}`.format.call(null, ...arguments) | |
}, | |
fr: { | |
itemsAdded: () => formatter`${0} a ajouté ${1} ${2} à ${3}`.format.call(null, ...arguments) | |
} | |
} | |
const locale = store.getIn(['ui', 'locale']) | |
const action = 'itemsAdded' | |
const output = helpers[locale][action](['James Chou'], 42, 'photos', 'Pretty Sunsets') | |
// 'de' => James Chou hinzugefügt 42 Fotos zu Pretty Sunsets | |
// 'en' => James Chou added 42 photos to Pretty Sunsets | |
// 'es' => James Chou añadido 42 fotos a Pretty Sunsets | |
// 'fr' => James Chou a ajouté 42 photos à Pretty Sunsets | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment