custom_i18n.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //TAKEN FROM:
  2. //https://adblockforchrome.googlecode.com/svn/trunk/port.js
  3. // Chrome to Safari port
  4. // Author: Michael Gundlach (gundlach@gmail.com)
  5. // License: GPLv3 as part of adblockforchrome.googlecode.com
  6. // or MIT if GPLv3 conflicts with your code's license.
  7. chrome.i18n = chrome.i18n || {};
  8. chrome.i18n = (function() {
  9. //Supported locales as in:
  10. //https://developers.google.com/chrome/web-store/docs/i18n?hl=it#localeTable
  11. var supportedLocales =
  12. [{"code":"ar", "name":"Arabic"},
  13. {"code":"bg", "name":"Bulgarian"},
  14. {"code":"ca", "name":"Catalan"},
  15. {"code":"zh_CN", "name":"Chinese (China)"},
  16. {"code":"zh_TW", "name":"Chinese (Taiwan)"},
  17. {"code":"hr", "name":"Croatian"},
  18. {"code":"cs", "name":"Czech"},
  19. {"code":"da", "name":"Danish"},
  20. {"code":"nl", "name":"Dutch"},
  21. {"code":"en", "name":"English"},
  22. {"code":"en_GB", "name":"English (Great Britain)"},
  23. {"code":"en_US", "name":"English (USA)"},
  24. {"code":"et", "name":"Estonian"},
  25. {"code":"fil", "name":"Filipino"},
  26. {"code":"fi", "name":"Finnish"},
  27. {"code":"fr", "name":"French"},
  28. {"code":"de", "name":"German"},
  29. {"code":"el", "name":"Greek"},
  30. {"code":"he", "name":"Hebrew"},
  31. {"code":"hi", "name":"Hindi"},
  32. {"code":"hu", "name":"Hungarian"},
  33. {"code":"id", "name":"Indonesian"},
  34. {"code":"it", "name":"Italian"},
  35. {"code":"ja", "name":"Japanese"},
  36. {"code":"ko", "name":"Korean"},
  37. {"code":"lv", "name":"Latvian"},
  38. {"code":"lt", "name":"Lithuanian"},
  39. {"code":"no", "name":"Norwegian"},
  40. {"code":"pl", "name":"Polish"},
  41. {"code":"pt_BR", "name":"Portuguese (Brazil)"},
  42. {"code":"pt_PT", "name":"Portuguese (Portugal)"},
  43. {"code":"ro", "name":"Romanian"},
  44. {"code":"ru", "name":"Russian"},
  45. {"code":"sr", "name":"Serbian"},
  46. {"code":"sk", "name":"Slovak"},
  47. {"code":"sl", "name":"Slovenian"},
  48. {"code":"es", "name":"Spanish"},
  49. {"code":"es_419", "name":"Spanish (Latin America and Caribbean)"},
  50. {"code":"sv", "name":"Swedish"},
  51. {"code":"th", "name":"Thai"},
  52. {"code":"tr", "name":"Turkish"},
  53. {"code":"uk", "name":"Ukrainian"},
  54. {"code":"vi", "name":"Vietnamese"}];
  55. function syncFetch(file, fn) {
  56. var xhr = new XMLHttpRequest();
  57. xhr.open("GET", chrome.extension.getURL(file), false);
  58. xhr.onreadystatechange = function() {
  59. if(this.readyState == 4 && this.responseText != "") {
  60. fn(this.responseText);
  61. }
  62. };
  63. try {
  64. xhr.send();
  65. }
  66. catch (e) {
  67. // File not found, perhaps
  68. }
  69. }
  70. // Insert substitution args into a localized string.
  71. function parseString(msgData, args) {
  72. // If no substitution, just turn $$ into $ and short-circuit.
  73. if (msgData.placeholders == undefined && args == undefined)
  74. return msgData.message.replace(/\$\$/g, '$');
  75. // Substitute a regex while understanding that $$ should be untouched
  76. function safesub(txt, re, replacement) {
  77. var dollaRegex = /\$\$/g, dollaSub = "~~~I18N~~:";
  78. txt = txt.replace(dollaRegex, dollaSub);
  79. txt = txt.replace(re, replacement);
  80. // Put back in "$$" ("$$$$" somehow escapes down to "$$")
  81. var undollaRegex = /~~~I18N~~:/g, undollaSub = "$$$$";
  82. txt = txt.replace(undollaRegex, undollaSub);
  83. return txt;
  84. }
  85. var $n_re = /\$([1-9])/g;
  86. var $n_subber = function(_, num) { return args[num - 1]; };
  87. var placeholders = {};
  88. // Fill in $N in placeholders
  89. for (var name in msgData.placeholders) {
  90. var content = msgData.placeholders[name].content;
  91. placeholders[name.toLowerCase()] = safesub(content, $n_re, $n_subber);
  92. }
  93. // Fill in $N in message
  94. var message = safesub(msgData.message, $n_re, $n_subber);
  95. // Fill in $Place_Holder1$ in message
  96. message = safesub(message, /\$(\w+?)\$/g, function(full, name) {
  97. var lowered = name.toLowerCase();
  98. if (lowered in placeholders)
  99. return placeholders[lowered];
  100. return full; // e.g. '$FoO$' instead of 'foo'
  101. });
  102. // Replace $$ with $
  103. message = message.replace(/\$\$/g, '$');
  104. return message;
  105. }
  106. var l10nData = undefined;
  107. var theI18nObject = {
  108. // chrome.i18n.getMessage() may be used in any extension resource page
  109. // without any preparation. But if you want to use it from a content
  110. // script in Safari, the content script must first run code like this:
  111. //
  112. // get_localization_data_from_global_page_async(function(data) {
  113. // chrome.i18n._setL10nData(data);
  114. // // now I can call chrome.i18n.getMessage()
  115. // });
  116. // // I cannot call getMessage() here because the above call
  117. // // is asynchronous.
  118. //
  119. // The global page will need to receive your request message, call
  120. // chrome.i18n._getL10nData(), and return its result.
  121. //
  122. // We can't avoid this, because the content script can't load
  123. // l10n data for itself, because it's not allowed to make the xhr
  124. // call to load the message files from disk. Sorry :(
  125. _getL10nData: function() {
  126. var result = { locales: [] };
  127. // == Find all locales we might need to pull messages from, in order
  128. // 0: The user's chosen locale, if present
  129. if(preferences.useCustomLocale && preferences.customLocale != null)
  130. result.locales.push(preferences.customLocale);
  131. // 1: The user's current locale, converted to match the format of
  132. // the _locales directories (e.g. "en-US" becomes "en_US"
  133. result.locales.push(navigator.language.replace('-', '_'));
  134. // 2: Perhaps a region-agnostic version of the current locale
  135. if (navigator.language.length > 2)
  136. result.locales.push(navigator.language.substring(0, 2));
  137. // 3: Set English 'en' as default locale
  138. if (result.locales.indexOf("en") == -1)
  139. result.locales.push("en");
  140. // Load all locale files that exist in that list
  141. result.messages = {};
  142. for (var i = 0; i < result.locales.length; i++) {
  143. var locale = result.locales[i];
  144. var file = "_locales/" + locale + "/messages.json";
  145. // Doesn't call the callback if file doesn't exist
  146. syncFetch(file, function(text) {
  147. result.messages[locale] = JSON.parse(text);
  148. });
  149. }
  150. return result;
  151. },
  152. // Manually set the localization data. You only need to call this
  153. // if using chrome.i18n.getMessage() from a content script, before
  154. // the first call. You must pass the value of _getL10nData(),
  155. // which can only be called by the global page.
  156. _setL10nData: function(data) {
  157. l10nData = data;
  158. },
  159. getMessage: function(messageID, args) {
  160. if (l10nData == undefined) {
  161. // Assume that we're not in a content script, because content
  162. // scripts are supposed to have set l10nData already
  163. chrome.i18n._setL10nData(chrome.i18n._getL10nData());
  164. }
  165. if (typeof args == "string")
  166. args = [args];
  167. for (var i = 0; i < l10nData.locales.length; i++) {
  168. var map = l10nData.messages[l10nData.locales[i]];
  169. // We must have the locale, and the locale must have the message
  170. if (map && messageID in map)
  171. return parseString(map[messageID], args);
  172. }
  173. return "";
  174. },
  175. //Returns the list of locales that are actually present in the locale directory
  176. getExistingLocales: function (){
  177. var existingLocales = [];
  178. for (var i = 0; i < supportedLocales.length; i++) {
  179. var locale = supportedLocales[i].code;
  180. var file = "_locales/" + locale + "/messages.json";
  181. var xhr = new XMLHttpRequest();
  182. xhr.open("GET", chrome.extension.getURL(file), false);
  183. xhr.onreadystatechange = function() {
  184. };
  185. try {
  186. xhr.send();
  187. existingLocales.push(supportedLocales[i]);
  188. }
  189. catch (e) {
  190. }
  191. }
  192. return existingLocales;
  193. }
  194. };
  195. return theI18nObject;
  196. })();