Skip to content

Commit

Permalink
langs is now anarray of lang objects, with code, src and dir
Browse files Browse the repository at this point in the history
  • Loading branch information
stasm committed May 21, 2015
1 parent c125e29 commit 964dcad
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 46 deletions.
16 changes: 10 additions & 6 deletions src/bindings/html/langs.js
Expand Up @@ -3,6 +3,8 @@
import { prioritizeLocales } from '../../lib/intl';
import { initViews } from './service';

const rtlList = ['ar', 'he', 'fa', 'ps', 'qps-plocm', 'ur'];

export function onlanguagechage(appVersion, defaultLang, availableLangs) {
this.languages = Promise.all([
navigator.mozApps.getAdditionalLanguages(), this.languages]).then(
Expand Down Expand Up @@ -30,26 +32,28 @@ export function changeLanguage(
let newLangs = prioritizeLocales(
defaultLang, allAvailableLangs, requestedLangs);

let langs = {
langs: newLangs,
srcs: newLangs.map(lang => getLangSource(
appVersion, availableLangs, additionalLangs, lang))
};
let langs = newLangs.map(lang => ({
code: lang,
src: getLangSource(appVersion, availableLangs, additionalLangs, lang),
dir: getDirection(lang)
}));

if (!arrEqual(prevLangs, newLangs)) {
initViews.call(this, langs);
}

return langs;
}

function getDirection(lang) {
return (rtlList.indexOf(lang) >= 0) ? 'rtl' : 'ltr';
}

function arrEqual(arr1, arr2) {
return arr1.length === arr2.length &&
arr1.every((elem, i) => elem === arr2[i]);
}


function getMatchingLangpack(appVersion, langpacks) {
for (var i = 0, langpack; (langpack = langpacks[i]); i++) {
if (langpack.target === appVersion) {
Expand Down
10 changes: 1 addition & 9 deletions src/bindings/html/service.js
Expand Up @@ -4,10 +4,6 @@ import {
translateDocument, setL10nAttributes, getL10nAttributes
} from './dom';

var rtlList = ['ar', 'he', 'fa', 'ps', 'qps-plocm', 'ur'];

// Public API

export const L10n = {
env: null,
views: [],
Expand All @@ -20,7 +16,7 @@ export const L10n = {
readyState: 'complete',
language: {
code: 'en-US',
direction: getDirection('en-US')
direction: 'ltr'
},
qps: {},
get: id => id,
Expand All @@ -36,10 +32,6 @@ export const L10n = {
}
};

function getDirection(lang) {
return (rtlList.indexOf(lang) >= 0) ? 'rtl' : 'ltr';
}

export function initViews(langs) {
return Promise.all(
this.views.map(view => initView(view, langs))).then(
Expand Down
26 changes: 12 additions & 14 deletions src/lib/context.js
Expand Up @@ -67,46 +67,44 @@ Context.prototype.destroy = function() {
this._env.destroyContext(this);
};

Context.prototype._fetchResources = function({langs, srcs}) {
Context.prototype._fetchResources = function(langs) {
if (langs.length === 0) {
return Promise.reject(
new L10nError('No more supported languages to try'));
}

return Promise.all(
this._resIds.map(
this._env._getResource.bind(this._env, langs[0], srcs[0]))).then(
() => ({langs, srcs}));
this._env._getResource.bind(this._env, langs[0]))).then(
() => langs);
};

Context.prototype._fallback = function(method, id, args, {langs, srcs}) {
Context.prototype._fallback = function(method, id, args, langs) {
let lang = langs[0];
let src = srcs[0];

let entity = this._getEntity({lang, src}, id);
let entity = this._getEntity(lang, id);

if (entity) {
try {
return method.call(this, args, entity);
} catch (e) {
console.error(id, ' in ', lang, ' is broken: ', e);
console.error(id, ' in ', lang.code, ' is broken: ', e);
}
} else {
console.error(id, ' missing from ', lang);
console.error(id, ' missing from ', lang.code);
}

let tail = {langs: langs.slice(1), srcs: srcs.slice(1)};
return this._fetchResources(tail).then(
return this._fetchResources(langs.slice(1)).then(
this._fallback.bind(this, method, id, args),
err => { console.error(err); return id; });
};

Context.prototype._getEntity = function({lang, src}, id) {
Context.prototype._getEntity = function(lang, id) {
var cache = this._env._resCache;

// Look for `id` in every resource in order.
for (var i = 0, resId; resId = this._resIds[i]; i++) {
var resource = cache[resId][lang][src];
var resource = cache[resId][lang.code][lang.src];
if (resource instanceof L10nError) {
continue;
}
Expand All @@ -119,10 +117,10 @@ Context.prototype._getEntity = function({lang, src}, id) {

// XXX in the future macros will be stored in localization resources together
// with regular entities and this method will not be needed anymore
Context.prototype._getMacro = function({lang, src}, id) {
Context.prototype._getMacro = function(lang, id) {
switch(id) {
case 'plural':
return getPluralRule(lang);
return getPluralRule(lang.code);
default:
return undefined;
}
Expand Down
25 changes: 13 additions & 12 deletions src/lib/env.js
Expand Up @@ -38,27 +38,28 @@ Env.prototype.destroyContext = function(ctx) {
});
};

Env.prototype._getResource = function(lang, src, res) {
var cache = this._resCache;
Env.prototype._getResource = function(lang, res) {
let { code, src } = lang;
let cache = this._resCache;

if (!cache[res]) {
cache[res] = Object.create(null);
cache[res][lang] = Object.create(null);
} else if (!cache[res][lang]) {
cache[res][lang] = Object.create(null);
} else if (cache[res][lang][src]) {
return cache[res][lang][src];
cache[res][code] = Object.create(null);
} else if (!cache[res][code]) {
cache[res][code] = Object.create(null);
} else if (cache[res][code][src]) {
return cache[res][code][src];
}

return cache[res][lang][src] = this.fetch(src, res, lang).then(
ast => cache[res][lang][src] = createEntries(lang, src, ast),
err => cache[res][lang][src] = err);
return cache[res][code][src] = this.fetch(src, res, code).then(
ast => cache[res][code][src] = createEntries(lang, ast),
err => cache[res][code][src] = err);
};

function createEntries(lang, src, ast) {
function createEntries(lang, ast) {
var entries = Object.create(null);
for (var i = 0, node; node = ast[i]; i++) {
entries[node.$i] = Resolver.createEntry(node, lang, src);
entries[node.$i] = Resolver.createEntry(node, lang);
}
return entries;
}
10 changes: 5 additions & 5 deletions src/lib/resolver.js
Expand Up @@ -6,7 +6,7 @@ var KNOWN_MACROS = ['plural'];
var MAX_PLACEABLE_LENGTH = 2500;
var rePlaceables = /\{\{\s*(.+?)\s*\}\}/g;

function createEntry(node, lang, src) {
function createEntry(node, lang) {
var keys = Object.keys(node);

// the most common scenario: a simple string with no arguments
Expand All @@ -25,21 +25,21 @@ function createEntry(node, lang, src) {
if (!attrs) {
attrs = Object.create(null);
}
attrs[key] = createAttribute(node[key], lang, src, node.$i + '.' + key);
attrs[key] = createAttribute(node[key], lang, node.$i + '.' + key);
}

return {
id: node.$i,
value: node.$v !== undefined ? node.$v : null,
index: node.$x || null,
attrs: attrs || null,
lang: {lang, src},
lang: lang,
// the dirty guard prevents cyclic or recursive references
dirty: false
};
}

function createAttribute(node, lang, src, id) {
function createAttribute(node, lang, id) {
if (typeof node === 'string') {
return node;
}
Expand All @@ -48,7 +48,7 @@ function createAttribute(node, lang, src, id) {
id: id,
value: node.$v || (node !== undefined ? node : null),
index: node.$x || null,
lang: {lang, src},
lang: lang,
dirty: false
};
}
Expand Down

0 comments on commit 964dcad

Please sign in to comment.