|
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
|
3 /* globals FirefoxCom */ |
|
4 |
|
5 'use strict'; |
|
6 |
|
7 // Small subset of the webL10n API by Fabien Cazenave for pdf.js extension. |
|
8 (function(window) { |
|
9 var gLanguage = ''; |
|
10 |
|
11 // fetch an l10n objects |
|
12 function getL10nData(key) { |
|
13 var response = FirefoxCom.requestSync('getStrings', key); |
|
14 var data = JSON.parse(response); |
|
15 if (!data) { |
|
16 console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']'); |
|
17 } |
|
18 return data; |
|
19 } |
|
20 |
|
21 // replace {{arguments}} with their values |
|
22 function substArguments(text, args) { |
|
23 if (!args) { |
|
24 return text; |
|
25 } |
|
26 return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function(all, name) { |
|
27 return (name in args ? args[name] : '{{' + name + '}}'); |
|
28 }); |
|
29 } |
|
30 |
|
31 // translate a string |
|
32 function translateString(key, args, fallback) { |
|
33 var i = key.lastIndexOf('.'); |
|
34 var name, property; |
|
35 if (i >= 0) { |
|
36 name = key.substring(0, i); |
|
37 property = key.substring(i + 1); |
|
38 } else { |
|
39 name = key; |
|
40 property = 'textContent'; |
|
41 } |
|
42 var data = getL10nData(name); |
|
43 var value = (data && data[property]) || fallback; |
|
44 if (!value) { |
|
45 return '{{' + key + '}}'; |
|
46 } |
|
47 return substArguments(value, args); |
|
48 } |
|
49 |
|
50 // translate an HTML element |
|
51 function translateElement(element) { |
|
52 if (!element || !element.dataset) { |
|
53 return; |
|
54 } |
|
55 |
|
56 // get the related l10n object |
|
57 var key = element.dataset.l10nId; |
|
58 var data = getL10nData(key); |
|
59 if (!data) { |
|
60 return; |
|
61 } |
|
62 |
|
63 // get arguments (if any) |
|
64 // TODO: more flexible parser? |
|
65 var args; |
|
66 if (element.dataset.l10nArgs) { |
|
67 try { |
|
68 args = JSON.parse(element.dataset.l10nArgs); |
|
69 } catch (e) { |
|
70 console.warn('[l10n] could not parse arguments for #' + key + ''); |
|
71 } |
|
72 } |
|
73 |
|
74 // translate element |
|
75 // TODO: security check? |
|
76 for (var k in data) { |
|
77 element[k] = substArguments(data[k], args); |
|
78 } |
|
79 } |
|
80 |
|
81 |
|
82 // translate an HTML subtree |
|
83 function translateFragment(element) { |
|
84 element = element || document.querySelector('html'); |
|
85 |
|
86 // check all translatable children (= w/ a `data-l10n-id' attribute) |
|
87 var children = element.querySelectorAll('*[data-l10n-id]'); |
|
88 var elementCount = children.length; |
|
89 for (var i = 0; i < elementCount; i++) { |
|
90 translateElement(children[i]); |
|
91 } |
|
92 |
|
93 // translate element itself if necessary |
|
94 if (element.dataset.l10nId) { |
|
95 translateElement(element); |
|
96 } |
|
97 } |
|
98 |
|
99 window.addEventListener('DOMContentLoaded', function() { |
|
100 gLanguage = FirefoxCom.requestSync('getLocale', null); |
|
101 |
|
102 translateFragment(); |
|
103 |
|
104 // fire a 'localized' DOM event |
|
105 var evtObject = document.createEvent('Event'); |
|
106 evtObject.initEvent('localized', false, false); |
|
107 evtObject.language = gLanguage; |
|
108 window.dispatchEvent(evtObject); |
|
109 }); |
|
110 |
|
111 // Public API |
|
112 document.mozL10n = { |
|
113 // get a localized string |
|
114 get: translateString, |
|
115 |
|
116 // get the document language |
|
117 getLanguage: function() { |
|
118 return gLanguage; |
|
119 }, |
|
120 |
|
121 // get the direction (ltr|rtl) of the current language |
|
122 getDirection: function() { |
|
123 // http://www.w3.org/International/questions/qa-scripts |
|
124 // Arabic, Hebrew, Farsi, Pashto, Urdu |
|
125 var rtlList = ['ar', 'he', 'fa', 'ps', 'ur']; |
|
126 return (rtlList.indexOf(gLanguage) >= 0 ? 'rtl' : 'ltr'); |
|
127 }, |
|
128 |
|
129 // translate an element or document fragment |
|
130 translate: translateFragment |
|
131 }; |
|
132 })(this); |
|
133 |