Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions bin/pseudo-localize
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,13 @@ const convert = function(input) {
const options = { strategy: argv.strategy };

if (typeof input === 'string') {
write(localize(input, options));
write(localize(input, options) +'\n');
return;
}

// Flatten nested translation JSONs
input = flatten(input, {
safe: true,
});

for (let key in input) {
// this will need to be updated if other primitives
// support pseudo-localization
Expand All @@ -97,7 +95,7 @@ const convert = function(input) {
let json = null;

if (argv.i) {
convert(argv.i + '\n');
convert(argv.i);
return;
}

Expand Down
67 changes: 58 additions & 9 deletions src/localize.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,68 @@ const strategies = {
},
};

// Reference for ratios https://www.w3.org/International/articles/article-text-size
const numOfCharactersInEnglishToExpansionRatioMap = {
10: 2.5,
20: 1.9,
30: 1.7,
40: 1.5,
50: 1.5,
60: 1.6,
70: 1.6,
over70: 1.3,
};

const isAlpha = character => {
return /[a-zA-Z]/.test(character);
};

const textExpander = (string, numDuplicateChars = 0, expansionRatio = 1) => {
const repeatTimes = Math.ceil(expansionRatio);
const reverseString = string.split('').reverse();

let expandedText = '';
let count = 0;
let maxIndex = numDuplicateChars + string.length;

for (const c of reverseString) {
if (isAlpha(c) && count < numDuplicateChars) {
expandedText += c.repeat(repeatTimes);
count += repeatTimes - 1;
} else {
expandedText += c;
}
}

return expandedText
.split('')
.reverse()
.join('')
.substring(0, maxIndex);
};

const textExpansionHandler = (string, toBeExpanded) => {
const strLen = string.length;
const ratioKey = Math.ceil(strLen / 10) * 10;
const ratio =
ratioKey > 70
? numOfCharactersInEnglishToExpansionRatioMap.over70
: numOfCharactersInEnglishToExpansionRatioMap[ratioKey];
const numDuplicateChars = Math.ceil(strLen * ratio) - strLen;

if (toBeExpanded) return textExpander(string, numDuplicateChars, ratio);
else return textExpander(string);
};

const pseudoLocalizeString = (string, { strategy = 'accented' } = {}) => {
let opts = strategies[strategy];
let expandedString = textExpansionHandler(string, opts.elongate);

let pseudoLocalizedText = '';
for (let character of string) {

for (let character of expandedString) {
if (opts.map[character]) {
const cl = character.toLowerCase();
// duplicate "a", "e", "o" and "u" to emulate ~30% longer text
if (
opts.elongate &&
(cl === 'a' || cl === 'e' || cl === 'o' || cl === 'u')
) {
pseudoLocalizedText += opts.map[character] + opts.map[character];
} else pseudoLocalizedText += opts.map[character];
pseudoLocalizedText += opts.map[character];
} else pseudoLocalizedText += character;
}

Expand All @@ -149,6 +197,7 @@ const pseudoLocalizeString = (string, { strategy = 'accented' } = {}) => {
) {
return pseudoLocalizedText;
}

return opts.prefix + pseudoLocalizedText + opts.postfix;
};

Expand Down
10 changes: 5 additions & 5 deletions src/localize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import localize from './localize';

describe('localize', () => {
test('accented', () => {
expect(localize('abcd')).toBe('ȧȧƀƈḓ');
expect(localize('abcd')).toBe('ȧƀƀƀƈƈƈḓḓḓ');
// aeou are duplicated
expect(localize('aeou')).toBe('ȧȧḗḗǿǿŭŭ');
expect(localize('foo bar')).toBe('ƒǿǿǿǿ ƀȧȧř');
expect(localize('CAPITAL_LETTERS')).toBe('ƇȦȦƤĪŦȦȦĿ_ĿḖḖŦŦḖḖŘŞ');
expect(localize('aeou')).toBe('ȧḗḗḗǿǿǿŭŭŭ');
expect(localize('foo bar')).toBe('ƒƒƒǿǿǿǿǿǿ ƀƀƀȧȧȧřř');
expect(localize('CAPITAL_LETTERS')).toBe('ƇƇȦȦƤƤĪĪŦŦȦȦĿĿ_ĿĿḖḖŦŦŦŦḖḖŘŘŞŞ');
// Everything except ASCII alphabet is passed through
expect(localize('123,. n -~ðÞ')).toBe('123,. ƞ -~ðÞ');
expect(localize('123,. n -~ðÞ')).toBe('123,. ƞƞ -~ðÞ');
});

test('bidi', () => {
Expand Down