Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: safari/ext/common.js

Issue 6326608939974656: Issue 1502 - Cache translation catalogs on Safari (Closed)
Patch Set: Created Oct. 28, 2014, 6:50 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 70
71 this._messageDispatcher.dispatchMessage("request", request); 71 this._messageDispatcher.dispatchMessage("request", request);
72 } 72 }
73 }; 73 };
74 74
75 ext.onMessage = new ext._EventTarget(); 75 ext.onMessage = new ext._EventTarget();
76 76
77 77
78 /* I18n */ 78 /* I18n */
79 79
80 var localeCandidates = null;
81 var uiLocale;
82
83 var getLocaleCandidates = function() 80 var getLocaleCandidates = function()
84 { 81 {
85 var candidates = []; 82 var candidates = [];
86 var defaultLocale = "en_US"; 83 var defaultLocale = "en_US";
87 84
88 // e.g. "ja-jp-mac" -> "ja", "jp", note that the part after the second 85 // e.g. "ja-jp-mac" -> "ja", "jp", note that the part after the second
89 // dash is dropped, since we only support language and region 86 // dash is dropped, since we only support language and region
90 var [language, region] = navigator.language.split("-"); 87 var [language, region] = navigator.language.split("-");
91 88
92 if (region) 89 if (region)
93 candidates.push(language + "_" + region.toUpperCase()); 90 candidates.push(language + "_" + region.toUpperCase());
94 91
95 candidates.push(language); 92 candidates.push(language);
96 93
97 if (candidates.indexOf(defaultLocale) == -1) 94 if (candidates.indexOf(defaultLocale) == -1)
98 candidates.push(defaultLocale); 95 candidates.push(defaultLocale);
99 96
100 return candidates; 97 return candidates;
101 }; 98 };
102 99
103 var getCatalog = function(locale) 100 var locales = getLocaleCandidates();
101 var catalog = {__proto__: null, "@@ui_locale": [locales[0], []]};
102
103 var replacePlaceholder = function(text, placeholder, content)
104 {
105 return text.split("$" + placeholder + "$").join(content || "");
106 };
107
108 var parseMessage = function(source)
109 {
110 var text = source.message;
111 var placeholders = [];
112
113 for (var placeholder in source.placeholders)
114 {
115 var content = source.placeholders[placeholder].content;
116
117 if (/^\$\d+$/.test(content))
118 placeholders[parseInt(content.substr(1)) - 1] = placeholder;
119 else
120 text = replacePlaceholder(text, placeholder, content);
121 }
122
123 return [text, placeholders];
124 };
125
126 var readCatalog = function(locale)
104 { 127 {
105 var xhr = new XMLHttpRequest(); 128 var xhr = new XMLHttpRequest();
106 129
107 xhr.open("GET", safari.extension.baseURI + "_locales/" + locale + "/messages .json", false); 130 xhr.open("GET", safari.extension.baseURI + "_locales/" + locale + "/messages .json", false);
108 131
109 try { 132 try
133 {
110 xhr.send(); 134 xhr.send();
111 } 135 }
112 catch (e) 136 catch (e)
113 { 137 {
114 return null; 138 return;
115 } 139 }
116 140
117 if (xhr.status != 200 && xhr.status != 0) 141 if (xhr.status != 200 && xhr.status != 0)
118 return null; 142 return;
119 143
120 return JSON.parse(xhr.responseText); 144 var source = JSON.parse(xhr.responseText);
kzar 2014/10/28 19:12:16 I found it confusing that this variable is called
Sebastian Noack 2014/10/28 19:35:53 I could argue that this is a different context and
kzar 2014/10/28 22:05:29 Perhaps the source variable here could be renamed
Sebastian Noack 2014/10/29 08:08:54 Not really consistent. Since the variable storing
kzar 2014/10/30 12:40:15 Cool that makes more sense to me now.
145 for (var msgId in source)
146 {
147 if (!(msgId in catalog))
148 catalog[msgId] = parseMessage(source[msgId]);
149 }
121 }; 150 };
122 151
123 ext.i18n = { 152 ext.i18n = {
124 getMessage: function(msgId, substitutions) 153 getMessage: function(msgId, substitutions)
125 { 154 {
126 if (!localeCandidates) 155 while (true)
127 { 156 {
128 localeCandidates = getLocaleCandidates(); 157 var message = catalog[msgId];
129 uiLocale = localeCandidates[0]; 158 if (message)
130 } 159 {
160 var [text, placeholders] = message;
kzar 2014/10/28 19:12:16 I've never seen this syntax in JS before, sure it'
Sebastian Noack 2014/10/28 19:35:53 It's called destructuring assignment, and is a new
kzar 2014/10/28 22:05:29 I guessed you were somehow right :p (Understand ab
131 161
132 if (msgId == "@@ui_locale") 162 if (!(substitutions instanceof Array))
133 return uiLocale; 163 substitutions = [substitutions];
134 164
135 for (var i = 0; i < localeCandidates.length; i++) 165 for (var i = 0; i < placeholders.length; i++)
136 { 166 text = replacePlaceholder(text, placeholders[i], substitutions[i]);
137 var catalog = getCatalog(localeCandidates[i]); 167
138 if (!catalog) 168 return text;
139 {
140 // if there is no catalog for this locale
141 // candidate, don't try to load it again
142 localeCandidates.splice(i--, 1);
143 continue;
144 } 169 }
145 170
146 var msg = catalog[msgId]; 171 if (locales.length == 0)
147 if (!msg) 172 return "";
148 continue;
149 173
150 var msgstr = msg.message; 174 readCatalog(locales.shift());
151 if (!msgstr)
152 continue;
153
154 for (var placeholder in msg.placeholders)
155 {
156 var placeholderDetails = msg.placeholders[placeholder];
157 if (!placeholderDetails || !placeholderDetails.content)
158 continue;
159 if (placeholderDetails.content.indexOf("$") != 0)
160 continue;
161
162 var placeholderIdx = parseInt(placeholderDetails.content.substr(1));
163 if (isNaN(placeholderIdx) || placeholderIdx < 1)
164 continue;
165
166 var placeholderValue;
167 if (typeof substitutions != "string")
168 placeholderValue = substitutions[placeholderIdx - 1];
169 else if (placeholderIdx == 1)
170 placeholderValue = substitutions;
171
172 msgstr = msgstr.replace("$" + placeholder + "$", placeholderValue || " ");
173 }
174
175 return msgstr;
176 } 175 }
177
178 return "";
179 } 176 }
180 }; 177 };
181 178
182 179
183 /* Utils */ 180 /* Utils */
184 181
185 ext.getURL = function(path) 182 ext.getURL = function(path)
186 { 183 {
187 return safari.extension.baseURI + path; 184 return safari.extension.baseURI + path;
188 }; 185 };
189 })(); 186 })();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld