You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
7.0KB

  1. var SC = SC || {},
  2. CoreDocs = CoreDocs || {},
  3. NO = false,
  4. YES = true;
  5. // ==========================================================================
  6. // This is copied from CoreDocs to facilitate automatically generating Strings.js files.
  7. // ==========================================================================
  8. CoreDocs.loc = function(input, comment) {
  9. if (comment === undefined)
  10. {
  11. CoreDocs.error("\"" + input + "\" needs a comment to be picked up for loc.");
  12. }
  13. // When we call SproutCore's loc(), it will replace all %@ parameters, and there is no way to escape them.
  14. // In the future, we should get an escaping method into SC, and/or take advantage of their loc's string replacement.
  15. // For now, we use @@ instead of %@ as a preliminary parameter marker.
  16. input = input.loc();
  17. input = input.replace(/@@/g, "%@");
  18. return input;
  19. }
  20. // ==========================================================================
  21. // This is the necessary subset of sproutcore strings for use in localization.
  22. // ==========================================================================
  23. // ==========================================================================
  24. // SproutCore -- JavaScript Application Framework
  25. // copyright 2006-2008, Sprout Systems, Inc. and contributors.
  26. // ==========================================================================
  27. // These are basic enhancements to the string class used throughout
  28. // SproutCore.
  29. /**
  30. @namespace
  31. SproutCore implements a variety of enhancements to the built-in String
  32. object that make it easy to perform common substitutions and conversions.
  33. Most of the utility methods defined here mirror those found in Prototype
  34. 1.6.
  35. @since SproutCore 1.0
  36. */
  37. SC.String = {
  38. // Interpolate string. looks for %@ or %@1; to control the order of params.
  39. /**
  40. Apply formatting options to the string. This will look for occurrences
  41. of %@ in your string and substitute them with the arguments you pass into
  42. this method. If you want to control the specific order of replacement,
  43. you can add a number after the key as well to indicate which argument
  44. you want to insert.
  45. Ordered insertions are most useful when building loc strings where values
  46. you need to insert may appear in different orders.
  47. h3. Examples
  48. {{{
  49. "Hello %@ %@".fmt('John', 'Doe') => "Hello John Doe"
  50. "Hello %@2, %@1".fmt('John', 'Doe') => "Hello Doe, John"
  51. }}}
  52. @param args {Object...} optional arguments
  53. @returns {String} formatted string
  54. */
  55. fmt: function() {
  56. // first, replace any ORDERED replacements.
  57. var str = this.gsub(/%@([0-9]+)/, function(m) {
  58. return (arguments[parseInt(m[1],0)-1] || '').toString();
  59. }) ;
  60. // now, replace any remaining %@ items. Use this indexOf() method b/c
  61. // it is faster than split().
  62. var ret = [] ;
  63. var idx = -1 ;
  64. var loc = 0 ;
  65. var argIdx = 0;
  66. while((idx = str.indexOf("%@",loc)) >= 0) {
  67. // slice off initial part of string and push into ret. update loc.
  68. ret.push(str.slice(loc,idx)) ;
  69. loc = idx + 2 ; // 2 to skip '%@'.
  70. // add in replacement.
  71. var value = arguments[argIdx++] ;
  72. if (value && value.toString) value = value.toString() ;
  73. ret.push(value) ;
  74. }
  75. // include any remaining bits of the string.
  76. if (loc < str.length) {
  77. ret.push(str.slice(loc,str.length)) ;
  78. }
  79. // join return value.
  80. return (ret.length > 1) ? ret.join('') : ret[0] ;
  81. },
  82. /**
  83. Localizes the string. This will look up the reciever string as a key
  84. in the current Strings hash. If the key matches, the loc'd value will be
  85. used. The resulting string will also be passed through fmt() to insert
  86. any variables.
  87. @param args {Object...} optional arguments to interpolate also
  88. @returns {String} the localized and formatted string.
  89. */
  90. loc: function() {
  91. // NB: This could be implemented as a wrapper to locWithDefault() but
  92. // it would add some overhead to deal with the arguments and adds stack
  93. // frames, so we are keeping the implementation separate.
  94. var kit = String[String.currentLanguage()];
  95. var str = kit[this] ;
  96. if (!str) str = String.English[this] || this ;
  97. return str.fmt.apply(str,arguments) ;
  98. }
  99. } ;
  100. // Apply SC.String mixin to built-in String object
  101. for (var key in SC.String) {
  102. String.prototype[key] = SC.String[key];
  103. }
  104. // Add strings for various languages to this collection. String.loc()
  105. // method will try to localize the string passed using the current language.
  106. // if the language is not available, it will use English.
  107. Object.extend(String,
  108. /** @scope String @static */ {
  109. /**
  110. The current browser language as a two letter code.
  111. */
  112. browserLanguage: ((navigator.language || navigator.browserLanguage).split('-', 1)[0]),
  113. /**
  114. If YES, localization will favor the detected language instead of the
  115. preferred one.
  116. */
  117. useAutodetectedLanguage: NO,
  118. /**
  119. This property is set by the build tools to the current build language.
  120. */
  121. preferredLanguage: null,
  122. /**
  123. Returns the hash key to use for loc strings. The default implementation
  124. will autodetect the browser language and look for a loc string to
  125. match. If it can't find one then it will introspect to find loc strings
  126. that are defined and use those instead.
  127. */
  128. currentLanguage: function () {
  129. var ret = (this.useAutodetectedLanguage) ? (this.browserLanguage || this.preferredLanguage || 'en') : (this.preferredLanguage || this.browserLanguage || 'en') ;
  130. // then try a couple of normalized forms...
  131. if (!this[ret]) ret = this.normalizedLanguage(ret);
  132. return ret ;
  133. },
  134. /**
  135. Returns a normalized language string for the two letter country code.
  136. */
  137. normalizedLanguage: function(ret) {
  138. switch(ret) {
  139. case 'fr':
  140. ret = 'French';
  141. break ;
  142. case 'de':
  143. ret = 'German';
  144. break ;
  145. case 'ja':
  146. case 'jp':
  147. ret = 'Japanese';
  148. break ;
  149. case 'en':
  150. ret = 'English' ;
  151. break ;
  152. case 'es':
  153. ret = 'Spanish' ;
  154. break;
  155. default:
  156. ret = "English";
  157. break ;
  158. }
  159. return ret;
  160. },
  161. /**
  162. Adds loc strings for the named language. This method takes care of
  163. creating the localized string hash if it does not already exist.
  164. The language can be one of the following or any two-letter country code.
  165. English, French, German, Japanese, Spanish
  166. @param language {String} the language code
  167. @param strings {Hash} hash of loc strings.
  168. @returns {this}
  169. */
  170. addStringsFor: function(language, strings) {
  171. // convert language to a normalized name...
  172. language = String.normalizedLanguage(language) ;
  173. if (!String[language]) String[language] = {} ;
  174. Object.extend(String[language], strings || {});
  175. return this;
  176. }
  177. });
  178. String.English = String.English || {};
  179. String.French = String.French || {};
  180. String.German = String.German || {};
  181. String.Japanese = String.Japanese || {};
  182. String.Spanish = String.Spanish || {};