PageRenderTime 26ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/qooxdoo-2.1.1-sdk/framework/source/class/qx/locale/Manager.js

https://bitbucket.org/vegansk/test_qooxdoo
JavaScript | 463 lines | 200 code | 72 blank | 191 comment | 42 complexity | 5cc44ad0e145651dd4212e164a6f68e7 MD5 | raw file
  1. /* ************************************************************************
  2. qooxdoo - the new era of web development
  3. http://qooxdoo.org
  4. Copyright:
  5. 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
  6. License:
  7. LGPL: http://www.gnu.org/licenses/lgpl.html
  8. EPL: http://www.eclipse.org/org/documents/epl-v10.php
  9. See the LICENSE file in the project's top-level directory for details.
  10. Authors:
  11. * Sebastian Werner (wpbasti)
  12. * Andreas Ecker (ecker)
  13. * Fabian Jakobs (fjakobs)
  14. ************************************************************************ */
  15. /*
  16. #require(qx.event.dispatch.Direct)
  17. #require(qx.locale.LocalizedString)
  18. #cldr
  19. */
  20. /**
  21. * The qx.locale.Manager provides static translation methods (like tr()) and
  22. * general locale information.
  23. */
  24. qx.Class.define("qx.locale.Manager",
  25. {
  26. type : "singleton",
  27. extend : qx.core.Object,
  28. /*
  29. *****************************************************************************
  30. CONSTRUCTOR
  31. *****************************************************************************
  32. */
  33. construct : function()
  34. {
  35. this.base(arguments);
  36. this.__translations = qx.$$translations || {};
  37. this.__locales = qx.$$locales || {};
  38. var locale = qx.core.Environment.get("locale");
  39. var variant = qx.core.Environment.get("locale.variant");
  40. if (variant !== "") {
  41. locale += "_" + variant;
  42. }
  43. this.__clientLocale = locale;
  44. this.setLocale(locale || this.__defaultLocale);
  45. },
  46. /*
  47. *****************************************************************************
  48. STATICS
  49. *****************************************************************************
  50. */
  51. statics :
  52. {
  53. /**
  54. * Translate a message
  55. *
  56. * @param messageId {String} message id (may contain format strings)
  57. * @param varargs {Object} variable number of arguments applied to the format string
  58. * @return {String | LocalizedString} The translated message or localized string
  59. * @see qx.lang.String.format
  60. */
  61. tr : function(messageId, varargs)
  62. {
  63. var args = qx.lang.Array.fromArguments(arguments);
  64. args.splice(0, 1);
  65. return qx.locale.Manager.getInstance().translate(messageId, args);
  66. },
  67. /**
  68. * Translate a plural message
  69. *
  70. * Depending on the third argument the plural or the singular form is chosen.
  71. *
  72. * @param singularMessageId {String} message id of the singular form (may contain format strings)
  73. * @param pluralMessageId {String} message id of the plural form (may contain format strings)
  74. * @param count {Integer} singular form if equals 1, otherwise plural
  75. * @param varargs {Object} variable number of arguments applied to the format string
  76. * @return {String | LocalizedString} The translated message or localized string
  77. * @see qx.lang.String.format
  78. */
  79. trn : function(singularMessageId, pluralMessageId, count, varargs)
  80. {
  81. var args = qx.lang.Array.fromArguments(arguments);
  82. args.splice(0, 3);
  83. // assumes "Two forms, singular used for one only" (seems to be the most common form)
  84. // (http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html#Plural-forms)
  85. // closely related with bug #745
  86. if (count != 1) {
  87. return qx.locale.Manager.getInstance().translate(pluralMessageId, args);
  88. } else {
  89. return qx.locale.Manager.getInstance().translate(singularMessageId, args);
  90. }
  91. },
  92. /**
  93. * Translate a message with translation hint
  94. *
  95. * @param hint {String} hint for the translator of the message. Will be included in the .po file.
  96. * @param messageId {String} message id (may contain format strings)
  97. * @param varargs {Object} variable number of arguments applied to the format string
  98. * @return {String | LocalizedString} The translated message or localized string
  99. * @see qx.lang.String.format
  100. */
  101. trc : function(hint, messageId, varargs)
  102. {
  103. var args = qx.lang.Array.fromArguments(arguments);
  104. args.splice(0, 2);
  105. return qx.locale.Manager.getInstance().translate(messageId, args);
  106. },
  107. /**
  108. * Mark the message for translation but return the original message.
  109. *
  110. * @param messageId {String} the message ID
  111. * @return {String} messageId
  112. */
  113. marktr : function(messageId) {
  114. return messageId;
  115. }
  116. },
  117. /*
  118. *****************************************************************************
  119. PROPERTIES
  120. *****************************************************************************
  121. */
  122. properties :
  123. {
  124. /** current locale. locale is an language code like de, de_AT, en, en_GB, fr, ... */
  125. locale :
  126. {
  127. check : "String",
  128. nullable : true,
  129. apply : "_applyLocale",
  130. event : "changeLocale"
  131. }
  132. },
  133. /*
  134. *****************************************************************************
  135. MEMBERS
  136. *****************************************************************************
  137. */
  138. members :
  139. {
  140. __defaultLocale : "C",
  141. __locale : null,
  142. __language : null,
  143. __translations : null,
  144. __locales : null,
  145. __clientLocale : null,
  146. /**
  147. * Get the language code of the current locale
  148. *
  149. * This is the first part of a locale definition. The language for "de_DE" would be "de"
  150. *
  151. * @return {String} language code
  152. */
  153. getLanguage : function() {
  154. return this.__language;
  155. },
  156. /**
  157. * Get the territory code of the current locale
  158. *
  159. * This is the second part of a locale definition. The territory for "de_DE" would be "DE"
  160. *
  161. * @return {String} territory code
  162. */
  163. getTerritory : function() {
  164. return this.getLocale().split("_")[1] || "";
  165. },
  166. /**
  167. * Return the available application locales
  168. *
  169. * This corresponds to the LOCALES setting in config.json. Without argument,
  170. * it only returns the currently loaded locales, with an argument of true
  171. * all locales that went into the build. This is particularly interesting if
  172. * locales were generated as dedicated I18N parts, and have to be loaded
  173. * explicitly before being available.
  174. *
  175. * @param includeNonloaded {Boolean?null} include locales not yet loaded
  176. * @return {String[]} array of available locales
  177. */
  178. getAvailableLocales : function(includeNonloaded)
  179. {
  180. var locales = [];
  181. for (var locale in this.__locales)
  182. {
  183. if (locale != this.__defaultLocale) {
  184. if (this.__locales[locale] === null && !includeNonloaded) {
  185. continue; // skip not yet loaded locales
  186. }
  187. locales.push(locale);
  188. }
  189. }
  190. return locales;
  191. },
  192. /**
  193. * Extract the language part from a locale.
  194. *
  195. * @param locale {String} locale to be used
  196. * @return {String} language
  197. */
  198. __extractLanguage : function(locale)
  199. {
  200. var language;
  201. if (locale == null) {
  202. return null;
  203. }
  204. var pos = locale.indexOf("_");
  205. if (pos == -1) {
  206. language = locale;
  207. } else {
  208. language = locale.substring(0, pos);
  209. }
  210. return language;
  211. },
  212. // property apply
  213. _applyLocale : function(value, old)
  214. {
  215. if (qx.core.Environment.get("qx.debug")) {
  216. if (!(value in this.__locales || value == this.__clientLocale)) {
  217. qx.log.Logger.warn("Locale: " + value+" not available.");
  218. }
  219. }
  220. this.__locale = value;
  221. this.__language = this.__extractLanguage(value);
  222. },
  223. /**
  224. * Add a translation to the translation manager.
  225. *
  226. * If <code>languageCode</code> already exists, its map will be updated with
  227. * <code>translationMap</code> (new keys will be added, existing keys will be
  228. * overwritten).
  229. *
  230. * @param languageCode {String} language code of the translation like <i>de, de_AT, en, en_GB, fr, ...</i>
  231. * @param translationMap {Map} mapping of message identifiers to message strings in the target
  232. * language, e.g. <i>{"greeting_short" : "Hello"}</i>. Plural forms
  233. * are separate keys.
  234. */
  235. addTranslation : function(languageCode, translationMap)
  236. {
  237. var catalog = this.__translations;
  238. if (catalog[languageCode])
  239. {
  240. for (var key in translationMap) {
  241. catalog[languageCode][key] = translationMap[key];
  242. }
  243. }
  244. else
  245. {
  246. catalog[languageCode] = translationMap;
  247. }
  248. },
  249. /**
  250. * Add a localization to the localization manager.
  251. *
  252. * If <code>localeCode</code> already exists, its map will be updated with
  253. * <code>localeMap</code> (new keys will be added, existing keys will be overwritten).
  254. *
  255. * @param localeCode {String} locale code of the translation like <i>de, de_AT, en, en_GB, fr, ...</i>
  256. * @param localeMap {Map} mapping of locale keys to the target locale values, e.g.
  257. * <i>{"cldr_date_format_short" : "M/d/yy"}</i>.
  258. */
  259. addLocale : function(localeCode, localeMap)
  260. {
  261. var catalog = this.__locales;
  262. if (catalog[localeCode])
  263. {
  264. for (var key in localeMap) {
  265. catalog[localeCode][key] = localeMap[key];
  266. }
  267. }
  268. else
  269. {
  270. catalog[localeCode] = localeMap;
  271. }
  272. },
  273. /**
  274. * Translate a message using the current locale and apply format string to the arguments.
  275. *
  276. * Implements the lookup chain locale (e.g. en_US) -> language (e.g. en) ->
  277. * default locale (e.g. C). Localizes the arguments if possible and splices
  278. * them into the message. If qx.dynlocale is on, returns a {@link
  279. * LocalizedString}.
  280. *
  281. * @param messageId {String} message id (may contain format strings)
  282. * @param args {Object[]} array of objects, which are inserted into the format string
  283. * @param locale {String ? #locale} locale to be used; if not given, defaults to the value of {@link #locale}
  284. * @return {String | LocalizedString} translated message or localized string
  285. */
  286. translate : function(messageId, args, locale)
  287. {
  288. var catalog = this.__translations;
  289. return this.__lookupAndExpand(catalog, messageId, args, locale);
  290. },
  291. /**
  292. * Provide localisation (CLDR) data.
  293. *
  294. * Implements the lookup chain locale (e.g. en_US) -> language (e.g. en) ->
  295. * default locale (e.g. C). Localizes the arguments if possible and splices
  296. * them into the message. If qx.dynlocale is on, returns a {@link
  297. * LocalizedString}.
  298. *
  299. * @param messageId {String} message id (may contain format strings)
  300. * @param args {Object[]} array of objects, which are inserted into the format string
  301. * @param locale {String ? #locale} locale to be used; if not given, defaults to the value of {@link #locale}
  302. * @return {String | LocalizedString} translated message or localized string
  303. */
  304. localize : function(messageId, args, locale)
  305. {
  306. var catalog = this.__locales;
  307. return this.__lookupAndExpand(catalog, messageId, args, locale);
  308. },
  309. /**
  310. * Look up an I18N key in a catalog and expand format strings.
  311. *
  312. * Implements the lookup chain locale (e.g. en_US) -> language (e.g. en) ->
  313. * default locale (e.g. C). Localizes the arguments if possible and splices
  314. * them into the message. If qx.dynlocale is on, returns a {@link
  315. * LocalizedString}.
  316. *
  317. * @param catalog {Map} map of I18N keys and their values
  318. * @param messageId {String} message id (may contain format strings)
  319. * @param args {Object[]} array of objects, which are inserted into the format string
  320. * @param locale {String ? #locale} locale to be used; if not given, defaults to the value of {@link #locale}
  321. * @return {String | LocalizedString} translated message or localized string
  322. */
  323. __lookupAndExpand : function(catalog, messageId, args, locale)
  324. {
  325. if (qx.core.Environment.get("qx.debug")) {
  326. this.assertObject(catalog);
  327. this.assertString(messageId);
  328. this.assertArray(args);
  329. }
  330. var txt;
  331. if (!catalog) {
  332. return messageId;
  333. }
  334. if (locale) {
  335. var language = this.__extractLanguage(locale);
  336. }
  337. else
  338. {
  339. locale = this.__locale;
  340. language = this.__language;
  341. }
  342. // e.g. DE_at
  343. if (!txt && catalog[locale]) {
  344. txt = catalog[locale][messageId];
  345. }
  346. // e.g. DE
  347. if (!txt && catalog[language]) {
  348. txt = catalog[language][messageId];
  349. }
  350. // C
  351. if (!txt && catalog[this.__defaultLocale]) {
  352. txt = catalog[this.__defaultLocale][messageId];
  353. }
  354. if (!txt) {
  355. txt = messageId;
  356. }
  357. if (args.length > 0)
  358. {
  359. var translatedArgs = [];
  360. for ( var i = 0; i < args.length; i++)
  361. {
  362. var arg = args[i];
  363. if (arg && arg.translate) {
  364. translatedArgs[i] = arg.translate();
  365. } else {
  366. translatedArgs[i] = arg;
  367. }
  368. }
  369. txt = qx.lang.String.format(txt, translatedArgs);
  370. }
  371. if (qx.core.Environment.get("qx.dynlocale")) {
  372. txt = new qx.locale.LocalizedString(txt, messageId, args);
  373. }
  374. return txt;
  375. }
  376. },
  377. /*
  378. *****************************************************************************
  379. DESTRUCTOR
  380. *****************************************************************************
  381. */
  382. destruct : function() {
  383. this.__translations = this.__locales = null;
  384. }
  385. });