i18n-js 3.0.0.rc8 → 3.0.0.rc9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5f7d877f8e94243760d5e3c4c3bbe232badc99d
4
- data.tar.gz: 0d2cf27dc10c17acc846c457ec48573ae9832413
3
+ metadata.gz: 6e722b7f34475d50126d5ba7556c9a517f65266f
4
+ data.tar.gz: 668e6660683a5eb93b2812f656af2439237299e7
5
5
  SHA512:
6
- metadata.gz: 6ebf38bdbc12665767e0c7c3806fd02221204b26e8b1f82dda78c3f07534ec5cedd18b4b6bc133c2820effc6ddb0f3c6902318a76b78563ceb232e99272213b8
7
- data.tar.gz: c505d9671c59b80c51c28a033b03c8cac3bdc4174621789f7f9e48e5257324c37803f4e1f084cc337c3512894c193bbbf8a820e78c6495f570872dee4ff50f28
6
+ metadata.gz: c0cdc594d00611b72e9ca9327389d9f90b5b4d2990b8ecc3f144b44dfaf03aa793b01acc6a28aa57e46c492fe923eefa5b879696e654a7c689486d46258a4a84
7
+ data.tar.gz: 9ae2cea1e167dc49edf962a1ccb0d0ceb153a7d53e5207bd8c830deed4b1a58a9d19b41b9cdae209fefb385c68798412925fb85874ea02e8670b7081ae609095
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0
5
4
  - 2.1
6
5
  - 2.2
@@ -12,8 +11,8 @@ before_install: # Need to install npm to test js
12
11
  - npm install jasmine-node@1.14.2
13
12
  gemfile:
14
13
  - gemfiles/i18n_0_6.gemfile
14
+ - gemfiles/i18n_0_7.gemfile
15
15
  matrix:
16
16
  fast_finish: true
17
17
  allow_failures:
18
- - rvm: 2.2
19
18
  - rvm: ruby-head
data/Appraisals CHANGED
@@ -1,4 +1,8 @@
1
1
 
2
- appraise "i18n-0-6" do
2
+ appraise "i18n_0_6" do
3
3
  gem 'i18n', '0.6.11'
4
4
  end
5
+
6
+ appraise "i18n_0_7" do
7
+ gem 'i18n', '0.7.0'
8
+ end
@@ -3,8 +3,21 @@
3
3
 
4
4
  ### enhancements
5
5
 
6
+ - [JS] Force currency number sign to be at first place using `sign_first` option, default to `true`
7
+ - [Ruby] Add option `namespace` & `pretty_print` ([#300](https://github.com/fnando/i18n-js/pull/300))
8
+ - [Ruby] Add option `export_i18n_js` ([#301](https://github.com/fnando/i18n-js/pull/301))
9
+ - [Ruby] Now the gem also detects pre-release versions of `rails`
10
+ - [Ruby] Add `:except` option to exclude certain phrases or groups of phrases from the
11
+ outputted translations ([#312](https://github.com/fnando/i18n-js/pull/312))
12
+ - [JS] You can now set `I18n.missingBehavior='guess'` to have the scope string output as text instead of of the
13
+ "[missing `scope`]" message when no translation is available.
14
+ - [JS] Combined that with `I18n.missingTranslationPrefix='SOMETHING'` and you can
15
+ still identify those missing strings.
16
+
6
17
  ### bug fixes
7
18
 
19
+ - [JS] Fix missing translation message when scope is passed in options
20
+
8
21
 
9
22
  ## 3.0.0.rc8
10
23
 
data/README.md CHANGED
@@ -23,8 +23,10 @@ Features:
23
23
  Add the gem to your Gemfile.
24
24
 
25
25
  source "https://rubygems.org"
26
- gem "rails", "3.2.3"
27
- gem "i18n-js"
26
+ gem "rails", "your_rails_version"
27
+ # You only need this RC version constraint during the development of `3.0.0`, once stable version is released you can remove `rc8` suffix
28
+ # `3.0.0.rc8` is the latest version of released RC version when this entry is changed, you might want to change it later
29
+ gem "i18n-js", ">= 3.0.0.rc8"
28
30
 
29
31
  #### Rails app with [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
30
32
 
@@ -107,21 +109,45 @@ translations:
107
109
  <% end %>
108
110
  ```
109
111
 
112
+ You are able to exclude certain phrases or whole groups of phrases by
113
+ specifying the YAML key(s) in the `except` configuration option. The outputted
114
+ JS translations file (exported or generated by the middleware) will omit any
115
+ keys listed in `except` configuration param:
116
+
117
+ ```yaml
118
+ translations:
119
+ - except: ['active_admin', 'ransack']
120
+ ```
121
+
122
+
110
123
  #### Export Configuration (For other things)
111
- - `I18n::JS.config_file_path`
124
+
125
+ - `I18n::JS.config_file_path`
112
126
  Expected Type: `String`
113
127
  Default: `config/i18n-js.yml`
114
128
  Behaviour: Try to read the config file from that location
115
- - `I18n::JS.export_i18n_js_dir_path`
129
+
130
+ - `I18n::JS.export_i18n_js_dir_path`
116
131
  Expected Type: `String`
117
132
  Default: `public/javascripts`
118
133
  Behaviour:
119
134
  - Any `String`: considered as a relative path for a folder to `Rails.root` and export `i18n.js` to that folder for `rake i18n:js:export`
120
- - `nil`: Disable `i18n.js` exporting
135
+ - Any non-`String` (`nil`, `false`, `:none`, etc): Disable `i18n.js` exporting
136
+
137
+ - You may also set `export_i18n_js` in your config file, e.g.:
138
+
139
+ ```yaml
140
+ export_i18n_js_: false
141
+ # OR
142
+ export_i18n_js: "my/path"
143
+
144
+ translations:
145
+ - ...
146
+ ``
121
147
 
122
148
  To find more examples on how to use the configuration file please refer to the tests.
123
149
 
124
- ##### Fallbacks
150
+ #### Fallbacks
125
151
 
126
152
  If you specify the `fallbacks` option, you will be able to fill missing translations with those inside fallback locale(s).
127
153
  Default value is `true`.
@@ -180,11 +206,54 @@ You must disable this feature by setting the option to `false`.
180
206
  To find more examples on how to use the configuration file please refer to the tests.
181
207
 
182
208
 
209
+ #### Namespace
210
+
211
+ Setting the `namespace` option will change the namespace of the output Javascript file to something other than `I18n`.
212
+ This can be useful in no-conflict scenarios. Example:
213
+
214
+ ```yaml
215
+ translations:
216
+ - file: "public/javascripts/i18n/translations.js"
217
+ namespace: "MyNamespace"
218
+ ```
219
+
220
+ will create:
221
+
222
+ ```
223
+ MyNamespace.translations || (MyNamespace.translations = {});
224
+ MyNamespace.translations["en"] = { ... }
225
+ ```
226
+
227
+
228
+ #### Pretty Print
229
+
230
+ Set the `pretty_print` option if you would like whitespace and indentation in your output file (default: false)
231
+
232
+ ```yaml
233
+ translations:
234
+ - file: "public/javascripts/i18n/translations.js"
235
+ pretty_print: true
236
+ ```
237
+
238
+
183
239
  #### Vanilla JavaScript
184
240
 
185
241
  Just add the `i18n.js` file to your page. You'll have to build the translations object
186
242
  by hand or using your favorite programming language. More info below.
187
243
 
244
+
245
+ #### Via NPM with webpack and CommonJS
246
+
247
+ Add the following line to your package.json dependencies (where version is the version you want - n.b. npm install requires it to be the gzipped tarball, see [npm install](https://www.npmjs.org/doc/cli/npm-install.html))
248
+ ```javascript
249
+ "i18n-js": "http://github.com/fnando/i18n-js/archive/v3.0.0.rc8.tar.gz"
250
+ ```
251
+ Run npm install then use via
252
+ ```javascript
253
+ var i18n = require("i18n-js");
254
+ ```
255
+
256
+
188
257
  ### Setting up
189
258
 
190
259
  You **don't** need to set up a thing. The default settings will work just okay. But if you want to split translations into several files or specify specific contexts, you can follow the rest of this setting up section.
@@ -240,7 +309,7 @@ You can also provide a list of default fallbacks for missing scopes:
240
309
  I18n.t("some.missing.scope", {defaults: [{scope: "some.existing.scope"}]});
241
310
 
242
311
  // As a simple translation
243
- I18n.t("some.missing.scope", {defaults: [{message: "some.existing.scope"}]});
312
+ I18n.t("some.missing.scope", {defaults: [{message: "Some message"}]});
244
313
 
245
314
  Default values must be provided as an array of hashs where the key is the
246
315
  type of translation desired, a `scope` or a `message`. The translation returned
@@ -271,6 +340,33 @@ are three different ways of doing it so:
271
340
  I18n.locales.no = "nb";
272
341
  I18n.locales.no = function(locale){ return ["nb"]; };
273
342
 
343
+ By default a missing translation will be displayed as
344
+
345
+ [missing "name of scope" translation]
346
+
347
+ While you are developing or if you do not want to provide a translation
348
+ in the default language you can set
349
+
350
+ I18n.missingBehaviour='guess';
351
+
352
+ this will take the last section of your scope and guess the intended value.
353
+ Camel case becomes lower cased text and underscores are replaced with space
354
+
355
+ questionnaire.whatIsYourFavorite_ChristmasPresent
356
+
357
+ becomes "what is your favorite Christmas present"
358
+
359
+ In order to still detect untranslated strings, you can
360
+ i18n.missingTranslationPrefix to something like:
361
+
362
+ I18n.missingTranslationPrefix = 'EE: '
363
+
364
+ And result will be:
365
+
366
+ "EE: what is your favorite Christmas present"
367
+
368
+ This will help you doing automated tests against your localisation assets.
369
+
274
370
  Pluralization is possible as well and by default provides English rules:
275
371
 
276
372
  I18n.t("inbox.counting", {count: 10}); // You have 10 messages
@@ -350,6 +446,7 @@ The `toCurrency` function accepts the following options:
350
446
  - `format`: sets the format of the output string
351
447
  - `unit`: sets the denomination of the currency
352
448
  - `strip_insignificant_zeros`: defaults to `false`
449
+ - `sign_first`: defaults to `true`
353
450
 
354
451
  You can provide only the options you want to override:
355
452
 
@@ -16,11 +16,9 @@
16
16
  if (typeof module !== 'undefined' && module.exports) {
17
17
  // Node/CommonJS
18
18
  module.exports = factory(this);
19
-
20
19
  } else if (typeof define === 'function' && define.amd) {
21
20
  // AMD
22
- define((function(global){ return function(){ factory(global); }})(this));
23
-
21
+ define('i18n', (function(global){ return function(){ return factory(global); }})(this));
24
22
  } else {
25
23
  // Browser globals
26
24
  this.I18n = factory(this);
@@ -61,13 +59,16 @@
61
59
  unit: "$"
62
60
  , precision: 2
63
61
  , format: "%u%n"
62
+ , sign_first: true
64
63
  , delimiter: ","
65
64
  , separator: "."
66
65
  };
67
66
 
68
67
  // Set default percentage format.
69
68
  var PERCENTAGE_FORMAT = {
70
- precision: 3
69
+ unit: "%"
70
+ , precision: 3
71
+ , format: "%n%u"
71
72
  , separator: "."
72
73
  , delimiter: ""
73
74
  };
@@ -77,12 +78,27 @@
77
78
 
78
79
  // Other default options
79
80
  var DEFAULT_OPTIONS = {
80
- defaultLocale: "en",
81
- locale: "en",
82
- defaultSeparator: ".",
83
- placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm,
84
- fallbacks: false,
85
- translations: {}
81
+ // Set default locale. This locale will be used when fallback is enabled and
82
+ // the translation doesn't exist in a particular locale.
83
+ defaultLocale: "en"
84
+ // Set the current locale to `en`.
85
+ , locale: "en"
86
+ // Set the translation key separator.
87
+ , defaultSeparator: "."
88
+ // Set the placeholder format. Accepts `{placeholder}}` and `%{placeholder}`.}
89
+ , placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm
90
+ // Set if engine should fallback to the default locale when a translation
91
+ // is missing.
92
+ , fallbacks: false
93
+ // Set the default translation object.
94
+ , translations: {}
95
+ // Set missing translation behavior. 'message' will display a message
96
+ // that the translation is missing, 'guess' will try to guess the string
97
+ , missingBehaviour: 'message'
98
+ // if you use missingBehaviour with 'message', but want to know that the
99
+ // string is actually missing for testing purposes, you can prefix the
100
+ // guessed string by setting the value here. By default, no prefix!
101
+ , missingTranslationPrefix: ''
86
102
  };
87
103
 
88
104
  I18n.reset = function() {
@@ -105,6 +121,13 @@
105
121
 
106
122
  // Set the default translation object.
107
123
  this.translations = DEFAULT_OPTIONS.translations;
124
+
125
+ // Set the default missing behaviour
126
+ this.missingBehaviour = DEFAULT_OPTIONS.missingBehaviour;
127
+
128
+ // Set the default missing string prefix for guess behaviour
129
+ this.missingTranslationPrefix = DEFAULT_OPTIONS.missingTranslationPrefix;
130
+
108
131
  };
109
132
 
110
133
  // Much like `reset`, but only assign options if not already assigned
@@ -252,18 +275,7 @@
252
275
  , translations
253
276
  ;
254
277
 
255
- // Deal with the scope as an array.
256
- if (scope.constructor === Array) {
257
- scope = scope.join(this.defaultSeparator);
258
- }
259
-
260
- // Deal with the scope option provided through the second argument.
261
- //
262
- // I18n.t('hello', {scope: 'greetings'});
263
- //
264
- if (options.scope) {
265
- scope = [options.scope, scope].join(this.defaultSeparator);
266
- }
278
+ scope = this.getFullScope(scope, options);
267
279
 
268
280
  while (locales.length) {
269
281
  locale = locales.shift();
@@ -390,7 +402,7 @@
390
402
  }, this);
391
403
 
392
404
  if (!translationFound) {
393
- return this.missingTranslation(scope);
405
+ return this.missingTranslation(scope, options);
394
406
  }
395
407
 
396
408
  if (typeof(translation) === "string") {
@@ -451,7 +463,7 @@
451
463
  }
452
464
 
453
465
  if (!translations) {
454
- return this.missingTranslation(scope);
466
+ return this.missingTranslation(scope, options);
455
467
  }
456
468
 
457
469
  pluralizer = this.pluralization.get(options.locale);
@@ -471,14 +483,21 @@
471
483
  };
472
484
 
473
485
  // Return a missing translation message for the given parameters.
474
- I18n.missingTranslation = function(scope) {
475
- var message = '[missing "';
486
+ I18n.missingTranslation = function(scope, options) {
487
+ //guess intended string
488
+ if(this.missingBehaviour == 'guess'){
489
+ //get only the last portion of the scope
490
+ var s = scope.split('.').slice(-1)[0];
491
+ //replace underscore with space && camelcase with space and lowercase letter
492
+ return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +
493
+ s.replace('_',' ').replace(/([a-z])([A-Z])/g,
494
+ function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );
495
+ }
476
496
 
477
- message += this.currentLocale() + ".";
478
- message += slice.call(arguments).join(".");
479
- message += '" translation]';
497
+ var fullScope = this.getFullScope(scope, options);
498
+ var fullScopeWithLocale = [this.currentLocale(), fullScope].join(this.defaultSeparator);
480
499
 
481
- return message;
500
+ return '[missing "' + fullScopeWithLocale + '" translation]';
482
501
  };
483
502
 
484
503
  // Return a missing placeholder message for given parameters
@@ -514,6 +533,8 @@
514
533
  , precision
515
534
  , buffer = []
516
535
  , formattedNumber
536
+ , format = options.format || "%n"
537
+ , sign = negative ? "-" : ""
517
538
  ;
518
539
 
519
540
  number = parts[0];
@@ -534,9 +555,18 @@
534
555
  formattedNumber += options.separator + precision;
535
556
  }
536
557
 
537
- if (negative) {
538
- formattedNumber = "-" + formattedNumber;
558
+ if (options.sign_first) {
559
+ format = "%s" + format;
539
560
  }
561
+ else {
562
+ format = format.replace("%n", "%s%n");
563
+ }
564
+
565
+ formattedNumber = format
566
+ .replace("%u", options.unit)
567
+ .replace("%n", formattedNumber)
568
+ .replace("%s", sign)
569
+ ;
540
570
 
541
571
  return formattedNumber;
542
572
  };
@@ -564,13 +594,7 @@
564
594
  , CURRENCY_FORMAT
565
595
  );
566
596
 
567
- number = this.toNumber(number, options);
568
- number = options.format
569
- .replace("%u", options.unit)
570
- .replace("%n", number)
571
- ;
572
-
573
- return number;
597
+ return this.toNumber(number, options);
574
598
  };
575
599
 
576
600
  // Localize several values.
@@ -782,8 +806,7 @@
782
806
  , PERCENTAGE_FORMAT
783
807
  );
784
808
 
785
- number = this.toNumber(number, options);
786
- return number + "%";
809
+ return this.toNumber(number, options);
787
810
  };
788
811
 
789
812
  // Convert a number into a readable size representation.
@@ -810,18 +833,31 @@
810
833
 
811
834
  options = this.prepareOptions(
812
835
  options
813
- , {precision: precision, format: "%n%u", delimiter: ""}
836
+ , {unit: unit, precision: precision, format: "%n%u", delimiter: ""}
814
837
  );
815
838
 
816
- number = this.toNumber(size, options);
817
- number = options.format
818
- .replace("%u", unit)
819
- .replace("%n", number)
820
- ;
821
-
822
- return number;
839
+ return this.toNumber(size, options);
823
840
  };
824
841
 
842
+ I18n.getFullScope = function(scope, options) {
843
+ options = this.prepareOptions(options);
844
+
845
+ // Deal with the scope as an array.
846
+ if (scope.constructor === Array) {
847
+ scope = scope.join(this.defaultSeparator);
848
+ }
849
+
850
+ // Deal with the scope option provided through the second argument.
851
+ //
852
+ // I18n.t('hello', {scope: 'greetings'});
853
+ //
854
+ if (options.scope) {
855
+ scope = [options.scope, scope].join(this.defaultSeparator);
856
+ }
857
+
858
+ return scope;
859
+ }
860
+
825
861
  // Set aliases, so we can save some typing.
826
862
  I18n.t = I18n.translate;
827
863
  I18n.l = I18n.localize;