mxResources.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /**
  2. * Copyright (c) 2006-2016, JGraph Ltd
  3. * Copyright (c) 2006-2016, Gaudenz Alder
  4. */
  5. var mxResources =
  6. {
  7. /**
  8. * Class: mxResources
  9. *
  10. * Implements internationalization. You can provide any number of
  11. * resource files on the server using the following format for the
  12. * filename: name[-en].properties. The en stands for any lowercase
  13. * 2-character language shortcut (eg. de for german, fr for french).
  14. *
  15. * If the optional language extension is omitted, then the file is used as a
  16. * default resource which is loaded in all cases. If a properties file for a
  17. * specific language exists, then it is used to override the settings in the
  18. * default resource. All entries in the file are of the form key=value. The
  19. * values may then be accessed in code via <get>. Lines without
  20. * equal signs in the properties files are ignored.
  21. *
  22. * Resource files may either be added programmatically using
  23. * <add> or via a resource tag in the UI section of the
  24. * editor configuration file, eg:
  25. *
  26. * (code)
  27. * <mxEditor>
  28. * <ui>
  29. * <resource basename="examples/resources/mxWorkflow"/>
  30. * (end)
  31. *
  32. * The above element will load examples/resources/mxWorkflow.properties as well
  33. * as the language specific file for the current language, if it exists.
  34. *
  35. * Values may contain placeholders of the form {1}...{n} where each placeholder
  36. * is replaced with the value of the corresponding array element in the params
  37. * argument passed to <mxResources.get>. The placeholder {1} maps to the first
  38. * element in the array (at index 0).
  39. *
  40. * See <mxClient.language> for more information on specifying the default
  41. * language or disabling all loading of resources.
  42. *
  43. * Lines that start with a # sign will be ignored.
  44. *
  45. * Special characters
  46. *
  47. * To use unicode characters, use the standard notation (eg. \u8fd1) or %u as a
  48. * prefix (eg. %u20AC will display a Euro sign). For normal hex encoded strings,
  49. * use % as a prefix, eg. %F6 will display a "o umlaut" (&ouml;).
  50. *
  51. * See <resourcesEncoded> to disable this. If you disable this, make sure that
  52. * your files are UTF-8 encoded.
  53. *
  54. * Asynchronous loading
  55. *
  56. * By default, the core adds two resource files synchronously at load time.
  57. * To load these files asynchronously, set <mxLoadResources> to false
  58. * before loading mxClient.js and use <mxResources.loadResources> instead.
  59. *
  60. * Variable: resources
  61. *
  62. * Object that maps from keys to values.
  63. */
  64. resources: {},
  65. /**
  66. * Variable: extension
  67. *
  68. * Specifies the extension used for language files. Default is <mxResourceExtension>.
  69. */
  70. extension: mxResourceExtension,
  71. /**
  72. * Variable: resourcesEncoded
  73. *
  74. * Specifies whether or not values in resource files are encoded with \u or
  75. * percentage. Default is false.
  76. */
  77. resourcesEncoded: false,
  78. /**
  79. * Variable: loadDefaultBundle
  80. *
  81. * Specifies if the default file for a given basename should be loaded.
  82. * Default is true.
  83. */
  84. loadDefaultBundle: true,
  85. /**
  86. * Variable: loadDefaultBundle
  87. *
  88. * Specifies if the specific language file file for a given basename should
  89. * be loaded. Default is true.
  90. */
  91. loadSpecialBundle: true,
  92. /**
  93. * Function: isLanguageSupported
  94. *
  95. * Hook for subclassers to disable support for a given language. This
  96. * implementation returns true if lan is in <mxClient.languages>.
  97. *
  98. * Parameters:
  99. *
  100. * lan - The current language.
  101. */
  102. isLanguageSupported: function(lan)
  103. {
  104. if (mxClient.languages != null)
  105. {
  106. return mxUtils.indexOf(mxClient.languages, lan) >= 0;
  107. }
  108. return true;
  109. },
  110. /**
  111. * Function: getDefaultBundle
  112. *
  113. * Hook for subclassers to return the URL for the special bundle. This
  114. * implementation returns basename + <extension> or null if
  115. * <loadDefaultBundle> is false.
  116. *
  117. * Parameters:
  118. *
  119. * basename - The basename for which the file should be loaded.
  120. * lan - The current language.
  121. */
  122. getDefaultBundle: function(basename, lan)
  123. {
  124. if (mxResources.loadDefaultBundle || !mxResources.isLanguageSupported(lan))
  125. {
  126. return basename + mxResources.extension;
  127. }
  128. else
  129. {
  130. return null;
  131. }
  132. },
  133. /**
  134. * Function: getSpecialBundle
  135. *
  136. * Hook for subclassers to return the URL for the special bundle. This
  137. * implementation returns basename + '_' + lan + <extension> or null if
  138. * <loadSpecialBundle> is false or lan equals <mxClient.defaultLanguage>.
  139. *
  140. * If <mxResources.languages> is not null and <mxClient.language> contains
  141. * a dash, then this method checks if <isLanguageSupported> returns true
  142. * for the full language (including the dash). If that returns false the
  143. * first part of the language (up to the dash) will be tried as an extension.
  144. *
  145. * If <mxResources.language> is null then the first part of the language is
  146. * used to maintain backwards compatibility.
  147. *
  148. * Parameters:
  149. *
  150. * basename - The basename for which the file should be loaded.
  151. * lan - The language for which the file should be loaded.
  152. */
  153. getSpecialBundle: function(basename, lan)
  154. {
  155. if (mxClient.languages == null || !this.isLanguageSupported(lan))
  156. {
  157. var dash = lan.indexOf('-');
  158. if (dash > 0)
  159. {
  160. lan = lan.substring(0, dash);
  161. }
  162. }
  163. if (mxResources.loadSpecialBundle && mxResources.isLanguageSupported(lan) && lan != mxClient.defaultLanguage)
  164. {
  165. return basename + '_' + lan + mxResources.extension;
  166. }
  167. else
  168. {
  169. return null;
  170. }
  171. },
  172. /**
  173. * Function: add
  174. *
  175. * Adds the default and current language properties file for the specified
  176. * basename. Existing keys are overridden as new files are added. If no
  177. * callback is used then the request is synchronous.
  178. *
  179. * Example:
  180. *
  181. * At application startup, additional resources may be
  182. * added using the following code:
  183. *
  184. * (code)
  185. * mxResources.add('resources/editor');
  186. * (end)
  187. *
  188. * Parameters:
  189. *
  190. * basename - The basename for which the file should be loaded.
  191. * lan - The language for which the file should be loaded.
  192. * callback - Optional callback for asynchronous loading.
  193. */
  194. add: function(basename, lan, callback)
  195. {
  196. lan = (lan != null) ? lan : ((mxClient.language != null) ?
  197. mxClient.language.toLowerCase() : mxConstants.NONE);
  198. if (lan != mxConstants.NONE)
  199. {
  200. var defaultBundle = mxResources.getDefaultBundle(basename, lan);
  201. var specialBundle = mxResources.getSpecialBundle(basename, lan);
  202. var loadSpecialBundle = function()
  203. {
  204. if (specialBundle != null)
  205. {
  206. if (callback)
  207. {
  208. mxUtils.get(specialBundle, function(req)
  209. {
  210. mxResources.parse(req.getText());
  211. callback();
  212. }, function()
  213. {
  214. callback();
  215. });
  216. }
  217. else
  218. {
  219. try
  220. {
  221. var req = mxUtils.load(specialBundle);
  222. if (req.isReady())
  223. {
  224. mxResources.parse(req.getText());
  225. }
  226. }
  227. catch (e)
  228. {
  229. // ignore
  230. }
  231. }
  232. }
  233. else if (callback != null)
  234. {
  235. callback();
  236. }
  237. }
  238. if (defaultBundle != null)
  239. {
  240. if (callback)
  241. {
  242. mxUtils.get(defaultBundle, function(req)
  243. {
  244. mxResources.parse(req.getText());
  245. loadSpecialBundle();
  246. }, function()
  247. {
  248. loadSpecialBundle();
  249. });
  250. }
  251. else
  252. {
  253. try
  254. {
  255. var req = mxUtils.load(defaultBundle);
  256. if (req.isReady())
  257. {
  258. mxResources.parse(req.getText());
  259. }
  260. loadSpecialBundle();
  261. }
  262. catch (e)
  263. {
  264. // ignore
  265. }
  266. }
  267. }
  268. else
  269. {
  270. // Overlays the language specific file (_lan-extension)
  271. loadSpecialBundle();
  272. }
  273. }
  274. },
  275. /**
  276. * Function: parse
  277. *
  278. * Parses the key, value pairs in the specified
  279. * text and stores them as local resources.
  280. */
  281. parse: function(text)
  282. {
  283. if (text != null)
  284. {
  285. var lines = text.split('\n');
  286. for (var i = 0; i < lines.length; i++)
  287. {
  288. if (lines[i].charAt(0) != '#')
  289. {
  290. var index = lines[i].indexOf('=');
  291. if (index > 0)
  292. {
  293. var key = lines[i].substring(0, index);
  294. var idx = lines[i].length;
  295. if (lines[i].charCodeAt(idx - 1) == 13)
  296. {
  297. idx--;
  298. }
  299. var value = lines[i].substring(index + 1, idx);
  300. if (this.resourcesEncoded)
  301. {
  302. value = value.replace(/\\(?=u[a-fA-F\d]{4})/g,"%");
  303. mxResources.resources[key] = unescape(value);
  304. }
  305. else
  306. {
  307. mxResources.resources[key] = value;
  308. }
  309. }
  310. }
  311. }
  312. }
  313. },
  314. /**
  315. * Function: get
  316. *
  317. * Returns the value for the specified resource key.
  318. *
  319. * Example:
  320. * To read the value for 'welomeMessage', use the following:
  321. * (code)
  322. * var result = mxResources.get('welcomeMessage') || '';
  323. * (end)
  324. *
  325. * This would require an entry of the following form in
  326. * one of the English language resource files:
  327. * (code)
  328. * welcomeMessage=Welcome to mxGraph!
  329. * (end)
  330. *
  331. * The part behind the || is the string value to be used if the given
  332. * resource is not available.
  333. *
  334. * Parameters:
  335. *
  336. * key - String that represents the key of the resource to be returned.
  337. * params - Array of the values for the placeholders of the form {1}...{n}
  338. * to be replaced with in the resulting string.
  339. * defaultValue - Optional string that specifies the default return value.
  340. */
  341. get: function(key, params, defaultValue)
  342. {
  343. var value = mxResources.resources[key];
  344. // Applies the default value if no resource was found
  345. if (value == null)
  346. {
  347. value = defaultValue;
  348. }
  349. // Replaces the placeholders with the values in the array
  350. if (value != null && params != null)
  351. {
  352. value = mxResources.replacePlaceholders(value, params);
  353. }
  354. return value;
  355. },
  356. /**
  357. * Function: replacePlaceholders
  358. *
  359. * Replaces the given placeholders with the given parameters.
  360. *
  361. * Parameters:
  362. *
  363. * value - String that contains the placeholders.
  364. * params - Array of the values for the placeholders of the form {1}...{n}
  365. * to be replaced with in the resulting string.
  366. */
  367. replacePlaceholders: function(value, params)
  368. {
  369. var result = [];
  370. var index = null;
  371. for (var i = 0; i < value.length; i++)
  372. {
  373. var c = value.charAt(i);
  374. if (c == '{')
  375. {
  376. index = '';
  377. }
  378. else if (index != null && c == '}')
  379. {
  380. index = parseInt(index)-1;
  381. if (index >= 0 && index < params.length)
  382. {
  383. result.push(params[index]);
  384. }
  385. index = null;
  386. }
  387. else if (index != null)
  388. {
  389. index += c;
  390. }
  391. else
  392. {
  393. result.push(c);
  394. }
  395. }
  396. return result.join('');
  397. },
  398. /**
  399. * Function: loadResources
  400. *
  401. * Loads all required resources asynchronously. Use this to load the graph and
  402. * editor resources if <mxLoadResources> is false.
  403. *
  404. * Parameters:
  405. *
  406. * callback - Callback function for asynchronous loading.
  407. */
  408. loadResources: function(callback)
  409. {
  410. mxResources.add(mxClient.basePath+'/resources/editor', null, function()
  411. {
  412. mxResources.add(mxClient.basePath+'/resources/graph', null, callback);
  413. });
  414. }
  415. };
  416. __mxOutput.mxResources = typeof mxResources !== 'undefined' ? mxResources : undefined;