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

Internationalisation #8

Open
theninja opened this issue Jul 11, 2017 · 2 comments
Open

Internationalisation #8

theninja opened this issue Jul 11, 2017 · 2 comments

Comments

@theninja
Copy link

Think about how we would format different currencies based on the locale.

We could just replicate a subset of the functionality in ICU; in particular their patterns for formatting numbers would be useful for outputting currencies in different locales.

@theninja
Copy link
Author

theninja commented Jul 11, 2017

This should give you a rough idea of how I envisioned it working (run in your console to see the output).

/**
 * Parse and extract our subset of the ICU DecimalFormat pattern
 * to some kind of sane formatting object.
 *
 * @param      string  pattern  The formatting pattern.
 *
 * @return     object  A "formatting object".
 */
function parsePattern(pattern) {
	let
		format = {
			decimalPlaces: 0,
			leftConcat: '',
			rightConcat: '',
			groupLengths: [],
			zeros: 0
		},
		groupLength = 0;

	pattern = pattern.split(';')[0]

	for(let i = pattern.length - 1; i >= 0; i--) {
		let ch = pattern[i];
		switch(ch) {
			case '#':
				groupLength++;
				break;
			case ',':
				format.groupLengths.push(groupLength);
				groupLength = 0;
				break;
			case '0':
				format.zeros++;
				if(format.decimalPlaces > 0) {
					groupLength++;
				}
				break;
			case '.':
				if(format.groupLengths.length === 0) {
					format.decimalPlaces = format.zeros;
				}
				break;
			default:
				if(format.decimalPlaces > 0) {
					format.leftConcat = ch + format.leftConcat;
				} else {
					format.rightConcat = ch + format.rightConcat;
				}
			break;
		}
	}

	return format;
}

/**
 * Take a number and a "currency object" and format our number accordingly.
 *
 * @param      string  num     The number to format
 * @param      object  curr    The currency object.
 *
 * @return     string  The number formatted based on our currency object.
 */
function format(num, curr) {

	if(isNaN(num)) {
		console.error('"num" is not a number');
	}

	let
		// we wouldn't be doing this at all in our real implementation
		n = parseFloat(num),
		fm = parsePattern(curr.format);

	// remove decimal point, round if necessary and convert to string
	n = Math.round(n * Math.pow(10, fm.decimalPlaces)) + '';

	let
		value = '',
		group = 0,
		count = 0;

	const offset = n.length - fm.decimalPlaces;

	for(let i = n.length - 1; i >= 0; i--) {
		value = n[i] + value;

		if(offset - i === 0) {
			value = curr.decimalSymbol + value;
		}

		if(offset - i > 0) {
			count++;

			if(count % fm.groupLengths[group] === 0 && i !== 0) {
				if(group + 1 < fm.groupLengths.length) {
					group++;
				}

				value = curr.thousandsSeparator + value;
				count = 0;
			}
		}
	}

	return (fm.leftConcat + value + fm.rightConcat).replace(/¤/g, curr.symbol);
}

const currencies = {
	'uk': {
		symbol: '£',
		format: '¤#,##0.00',
		thousandsSeparator: ',',
		decimalSymbol: '.'
	},
	'germany': {
		symbol: '€',
		format: '#,##0.00 ¤',
		thousandsSeparator: '.',
		decimalSymbol: ','
	},
	'poland': {
		symbol: 'zł',
		format: '#,##0.00 ¤',
		thousandsSeparator: ' ',
		decimalSymbol: ','
	},
	'latvia': {
		symbol: '€',
		format: '¤#,##0.00',
		thousandsSeparator: ' ',
		decimalSymbol: ','
	},
	'netherlands': {
		symbol: '€',
		format: '¤ #,##0.00;¤ #,##0.00-',
		thousandsSeparator: '.',
		decimalSymbol: ','
	}
};

for(var country in currencies) {
	console.log(
		format('1000000.896264567890000', currencies[country]),
		country
	);
}

@amirmohsen
Copy link
Owner

I ran it. That's cool. Using a pattern seem like a good way to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants