kriss-gettext_i18n 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/CHANGELOG.rdoc +8 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +78 -0
  4. data/VERSION.yml +4 -0
  5. data/gettext_i18n.gemspec +86 -0
  6. data/init.rb +1 -0
  7. data/lib/gettext_i18n.rb +25 -0
  8. data/lib/globalize/backend/gettext.rb +26 -0
  9. data/lib/globalize/i18n.rb +46 -0
  10. data/lib/rails/extend.rb +7 -0
  11. data/lib/ruby/string.rb +15 -0
  12. data/lib/ruby/symbol.rb +15 -0
  13. data/test/gettext_i18n_test.rb +114 -0
  14. data/test/locales/en.yml +2 -0
  15. data/test/locales/pl.yml +6 -0
  16. data/test/locales/root.yml +2 -0
  17. data/test/test_helper.rb +13 -0
  18. data/vendor/globalize2/LICENSE +21 -0
  19. data/vendor/globalize2/README.textile +202 -0
  20. data/vendor/globalize2/Rakefile +22 -0
  21. data/vendor/globalize2/generators/db_backend.rb +0 -0
  22. data/vendor/globalize2/generators/templates/db_backend_migration.rb +25 -0
  23. data/vendor/globalize2/init.rb +10 -0
  24. data/vendor/globalize2/lib/globalize/backend/chain.rb +102 -0
  25. data/vendor/globalize2/lib/globalize/backend/pluralizing.rb +37 -0
  26. data/vendor/globalize2/lib/globalize/backend/static.rb +59 -0
  27. data/vendor/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb +41 -0
  28. data/vendor/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb +27 -0
  29. data/vendor/globalize2/lib/globalize/load_path.rb +63 -0
  30. data/vendor/globalize2/lib/globalize/locale/fallbacks.rb +63 -0
  31. data/vendor/globalize2/lib/globalize/locale/language_tag.rb +81 -0
  32. data/vendor/globalize2/lib/globalize/model/active_record/adapter.rb +96 -0
  33. data/vendor/globalize2/lib/globalize/model/active_record/translated.rb +161 -0
  34. data/vendor/globalize2/lib/globalize/model/active_record.rb +38 -0
  35. data/vendor/globalize2/lib/globalize/translation.rb +32 -0
  36. data/vendor/globalize2/lib/locale/root.yml +3 -0
  37. data/vendor/globalize2/lib/rails_edge_load_path_patch.rb +40 -0
  38. data/vendor/globalize2/notes.textile +51 -0
  39. data/vendor/globalize2/test/backends/chained_test.rb +175 -0
  40. data/vendor/globalize2/test/backends/pluralizing_test.rb +63 -0
  41. data/vendor/globalize2/test/backends/static_test.rb +143 -0
  42. data/vendor/globalize2/test/data/locale/all.yml +2 -0
  43. data/vendor/globalize2/test/data/locale/de-DE.yml +2 -0
  44. data/vendor/globalize2/test/data/locale/en-US/module.yml +2 -0
  45. data/vendor/globalize2/test/data/locale/en-US.yml +2 -0
  46. data/vendor/globalize2/test/data/locale/fi-FI/module.yml +2 -0
  47. data/vendor/globalize2/test/data/locale/root.yml +0 -0
  48. data/vendor/globalize2/test/data/no_globalize_schema.rb +11 -0
  49. data/vendor/globalize2/test/data/post.rb +24 -0
  50. data/vendor/globalize2/test/data/schema.rb +39 -0
  51. data/vendor/globalize2/test/i18n/missing_translations_test.rb +36 -0
  52. data/vendor/globalize2/test/load_path_test.rb +49 -0
  53. data/vendor/globalize2/test/locale/fallbacks_test.rb +154 -0
  54. data/vendor/globalize2/test/locale/language_tag_test.rb +130 -0
  55. data/vendor/globalize2/test/model/active_record/migration_test.rb +78 -0
  56. data/vendor/globalize2/test/model/active_record/sti_translated_test.rb +75 -0
  57. data/vendor/globalize2/test/model/active_record/translated_test.rb +458 -0
  58. data/vendor/globalize2/test/test_helper.rb +36 -0
  59. data/vendor/globalize2/test/translation_test.rb +54 -0
  60. metadata +121 -0
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,8 @@
1
+ == 0.2.0
2
+ * Integrated with globalize2
3
+ * Simple backend extension moved to Gettext backend
4
+ * Add I18n::Globalize and I18n::Globalize::Singleton
5
+ * Add ruby Symbol extension
6
+ * ActiveRecord::Base extended with I18n::Gettext
7
+ * Add almost all tests (only tests for controllers and views are missing)
8
+ * Add full documentation and examples
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kriss Kowalik
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ Extended Globalize2 which is acting like gettext translations.
2
+
3
+ == Installation
4
+
5
+ sudo gem install kriss-gettext_like_i18n --source=http://gems.github.com/
6
+
7
+ == Usage
8
+
9
+ in controllers...
10
+
11
+ class FooController < ApplicationController
12
+ def bar
13
+ render :text => _('Wonderfull i18n notice!')
14
+ end
15
+ end
16
+
17
+ in models...
18
+
19
+ class Bar < ActiveRecord::Base
20
+ def foo(condition)
21
+ if condition
22
+ return "Some translated string".t
23
+ else
24
+ return :"some.key.for.translation".t
25
+ end
26
+ end
27
+ end
28
+
29
+ in views...
30
+
31
+ <div id="foo">
32
+ <%=_ 'Translated message' %> or <%= 'Other translated message'.t %><br />
33
+ <%=_ 'Great translated string with {{parameter}}, :parameter => 'gettext like i18n' %><br />
34
+ <%= link_to _('Get it now!'), 'http://github.com/kriss/gettext_like_i18n/' %>
35
+ </div>
36
+
37
+ == Translations
38
+
39
+ Each string will be displayed as default if is not translated in locale files.
40
+ Eg. locale file locales/pl.yml can look like this:
41
+
42
+ pl:
43
+ "Translated message": "Tlumaczona wiadomosc"
44
+ "Some translated string": "Jakis tlumaczony tekst"
45
+ key_to_translate: "Translated!"
46
+ nested:
47
+ key: "Hello!"
48
+
49
+ == Rails i18n & Globalize2 compatibility
50
+
51
+ gettext_like_i18n is full compatible with Ruby on Rails i18n and Globalize2 plugin.
52
+ Only you should remember that to load translation by key using gettext method you
53
+ have to specify key as symbol, eg:
54
+
55
+ <%=_ "nested.key" %>
56
+
57
+ is not the same as:
58
+
59
+ <%=_ :"nested.key" %>
60
+
61
+ First will produce "nested key" string, and second translation for specified key.
62
+ For key based translation it's better to use #t or #translate method.
63
+
64
+ == Extending your classes and modules
65
+
66
+ You can also extend your own classes and modules in easy way. Only thing you
67
+ have to do is include I18n::Gettext or I18n::Gettext::Singleton with your library, eg.
68
+
69
+ class Foo
70
+ include I18n::Gettext
71
+ include I18n::Gettext::Singleton
72
+ end
73
+
74
+ module Foo
75
+ extend I18n::Gettext
76
+ end
77
+
78
+ Enjoy!
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,86 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'gettext_i18n'
3
+ s.version = '0.2.0'
4
+ s.date = '2009-09-25'
5
+
6
+ s.summary = "Extended Globalize2 which is acting like gettext translations"
7
+ s.description = "Extended Globalize2 which is acting like gettext translations"
8
+
9
+ s.authors = ['Kriss Kowalik']
10
+ s.email = 'kriss.kowalik@gmail.pl'
11
+ s.homepage = 'http://krisskowalik.pl'
12
+
13
+ s.has_rdoc = false
14
+ s.rdoc_options = ['--main', 'README.rdoc']
15
+ s.rdoc_options << '--inline-source' << '--charset=UTF-8'
16
+ s.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE', 'CHANGELOG.rdoc']
17
+
18
+ s.files = [
19
+ 'MIT-LICENSE',
20
+ 'README.rdoc',
21
+ 'CHANGELOG.rdoc',
22
+ 'VERSION.yml',
23
+ 'gettext_i18n.gemspec',
24
+ 'init.rb',
25
+ 'lib/gettext_i18n.rb',
26
+ 'lib/globalize/backend/gettext.rb',
27
+ 'lib/globalize/i18n.rb',
28
+ 'lib/rails/extend.rb',
29
+ 'lib/ruby/string.rb',
30
+ 'lib/ruby/symbol.rb',
31
+ 'test/gettext_i18n_test.rb',
32
+ 'test/locales/en.yml',
33
+ 'test/locales/pl.yml',
34
+ 'test/locales/root.yml',
35
+ 'test/test_helper.rb',
36
+ 'vendor/globalize2/LICENSE',
37
+ 'vendor/globalize2/README.textile',
38
+ 'vendor/globalize2/Rakefile',
39
+ 'vendor/globalize2/generators/db_backend.rb',
40
+ 'vendor/globalize2/generators/templates/db_backend_migration.rb',
41
+ 'vendor/globalize2/init.rb',
42
+ 'vendor/globalize2/lib/globalize/backend/chain.rb',
43
+ 'vendor/globalize2/lib/globalize/backend/pluralizing.rb',
44
+ 'vendor/globalize2/lib/globalize/backend/static.rb',
45
+ 'vendor/globalize2/lib/globalize/i18n/missing_translations_log_handler.rb',
46
+ 'vendor/globalize2/lib/globalize/i18n/missing_translations_raise_handler.rb',
47
+ 'vendor/globalize2/lib/globalize/load_path.rb',
48
+ 'vendor/globalize2/lib/globalize/locale/fallbacks.rb',
49
+ 'vendor/globalize2/lib/globalize/locale/language_tag.rb',
50
+ 'vendor/globalize2/lib/globalize/model/active_record.rb',
51
+ 'vendor/globalize2/lib/globalize/model/active_record/adapter.rb',
52
+ 'vendor/globalize2/lib/globalize/model/active_record/translated.rb',
53
+ 'vendor/globalize2/lib/globalize/translation.rb',
54
+ 'vendor/globalize2/lib/locale/root.yml',
55
+ 'vendor/globalize2/lib/rails_edge_load_path_patch.rb',
56
+ 'vendor/globalize2/notes.textile',
57
+ 'vendor/globalize2/test/backends/chained_test.rb',
58
+ 'vendor/globalize2/test/backends/pluralizing_test.rb',
59
+ 'vendor/globalize2/test/backends/static_test.rb',
60
+ 'vendor/globalize2/test/data/locale/all.yml',
61
+ 'vendor/globalize2/test/data/locale/de-DE.yml',
62
+ 'vendor/globalize2/test/data/locale/en-US.yml',
63
+ 'vendor/globalize2/test/data/locale/en-US/module.yml',
64
+ 'vendor/globalize2/test/data/locale/fi-FI/module.yml',
65
+ 'vendor/globalize2/test/data/locale/root.yml',
66
+ 'vendor/globalize2/test/data/no_globalize_schema.rb',
67
+ 'vendor/globalize2/test/data/post.rb',
68
+ 'vendor/globalize2/test/data/schema.rb',
69
+ 'vendor/globalize2/test/i18n/missing_translations_test.rb',
70
+ 'vendor/globalize2/test/load_path_test.rb',
71
+ 'vendor/globalize2/test/locale/fallbacks_test.rb',
72
+ 'vendor/globalize2/test/locale/language_tag_test.rb',
73
+ 'vendor/globalize2/test/model/active_record/migration_test.rb',
74
+ 'vendor/globalize2/test/model/active_record/sti_translated_test.rb',
75
+ 'vendor/globalize2/test/model/active_record/translated_test.rb',
76
+ 'vendor/globalize2/test/test_helper.rb',
77
+ 'vendor/globalize2/test/translation_test.rb'
78
+ ]
79
+ s.test_files = [
80
+ 'test/gettext_i18n_test.rb',
81
+ 'test/locales/en.yml',
82
+ 'test/locales/pl.yml',
83
+ 'test/locales/root.yml',
84
+ 'test/test_helper.rb',
85
+ ]
86
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "gettext_i18n"
@@ -0,0 +1,25 @@
1
+ # Path to Globalize2 plugin
2
+ GLOBALIZE_ROOT = File.join(File.dirname(__FILE__), '../vendor/globalize2')
3
+ $:.unshift(File.join(GLOBALIZE_ROOT, 'lib'))
4
+
5
+ # Globalize2 plugin is required so we have to load it...
6
+ require "globalize/load_path"
7
+ require "globalize/backend/static"
8
+ require "globalize/model/active_record"
9
+ require 'globalize/i18n/missing_translations_raise_handler'
10
+ require File.join(GLOBALIZE_ROOT, 'init')
11
+
12
+ # Internationalization extensions
13
+ require "globalize/backend/gettext"
14
+ require "globalize/i18n"
15
+
16
+ # Ruby core extensions
17
+ require "ruby/string"
18
+ require "ruby/symbol"
19
+
20
+ # Extend Rails with I18n::Gettext
21
+ require "rails/extend"
22
+
23
+ # Set gettex backend in I18n
24
+ I18n.backend = Globalize::Backend::Gettext.new
25
+ I18n.exception_handler = :missing_translations_raise_handler
@@ -0,0 +1,26 @@
1
+ module Globalize
2
+ module Backend
3
+ class Gettext < Static
4
+ # Gettext like translations
5
+ #
6
+ # == Examples
7
+ #
8
+ # I18n.backend.gettext(:en, :"key.of.translation") # => Some value of specified key
9
+ # I18n.backend.gettext(:pl, "Some string to translate") # => Jakis tekst do przetlumaczenia
10
+ # I18n.backend.gettext(:pl, "Hello {{msg}}!", :msg => 'world') # => Hello world!
11
+ def gettext(locale, key, options={})
12
+ # TODO: hmm, should i check all ancestors?
13
+ if key.is_a? String
14
+ return if key.blank?
15
+ begin
16
+ translate locale, key.to_sym, options
17
+ rescue I18n::MissingTranslationData
18
+ return key
19
+ end
20
+ else
21
+ translate locale, key, options
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,46 @@
1
+ module I18n
2
+ class << self
3
+ # Returns translation for current string
4
+ def gettext(key, options={})
5
+ I18n.backend.gettext(locale, key, options)
6
+ end
7
+
8
+ # Shortcut for gettext method
9
+ alias :_ :gettext
10
+ end
11
+
12
+ # Extension for other modules and classess, especially for Ruby on Rails
13
+ # ActionController and ActionView helpers
14
+ #
15
+ # == Usage
16
+ #
17
+ # class Foo < Bar
18
+ # include I18n::Gettext
19
+ #
20
+ # def bar
21
+ # return _("Translate!")
22
+ # end
23
+ # end
24
+ #
25
+ # module Hello
26
+ # extend I18n::Gettext
27
+ # end
28
+ module Gettext
29
+ # Gettext translation method
30
+ def gettext(key, options={})
31
+ I18n.gettext(key, options)
32
+ end
33
+
34
+ # Shortcut for #translate method
35
+ alias :_ :gettext
36
+
37
+ # Extend singleton with Gettext methods
38
+ module Singleton
39
+ def self.included(base)
40
+ base.class_eval do
41
+ extend I18n::Gettext
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ class ActiveRecord::Base
2
+ include I18n::Gettext
3
+ include I18n::Gettext::Singleton
4
+ end
5
+
6
+ ActionController::Translation.send(:extend, I18n::Gettext)
7
+ ActionView::Helpers::TranslationHelper.send(:extend, I18n::Gettext)
@@ -0,0 +1,15 @@
1
+ class String
2
+ # Special string translations
3
+ #
4
+ # == Usage
5
+ #
6
+ # I18n.locale = :pl
7
+ # "Some string to translate".translate # => Jakis tekst do przetlumaczenia
8
+ def translate(options={})
9
+ I18n.gettext(self, options)
10
+ end
11
+
12
+ # Shortcuts for #translate
13
+ alias_method :gettext, :translate
14
+ alias_method :t, :translate
15
+ end
@@ -0,0 +1,15 @@
1
+ class Symbol
2
+ # Show translation for key
3
+ #
4
+ # == Usage
5
+ #
6
+ # I18n.locale = :pl
7
+ # :key_for_translation.translate # => Jakis tlumaczony tekst
8
+ def translate(options={})
9
+ I18n.gettext(self, options)
10
+ end
11
+
12
+ # Shortcuts for #translate
13
+ alias_method :gettext, :translate
14
+ alias_method :t, :translate
15
+ end
@@ -0,0 +1,114 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class GettextI18nTest < Test::Unit::TestCase
4
+ context "Simple translate" do
5
+ should "return itself if are not translated" do
6
+ I18n.locale = :en
7
+ assert_equal "Some not translated text", I18n.gettext("Some not translated text")
8
+ end
9
+
10
+ should "return translated string if are translated" do
11
+ I18n.locale = :pl
12
+ assert_equal "Testowa translacja", I18n.gettext("Test translation")
13
+ end
14
+
15
+ should "return translated string in the same language if such is defined" do
16
+ I18n.locale = :en
17
+ assert_equal "Correct translation", I18n.gettext("Translation with mistake")
18
+ end
19
+
20
+ should "return translation for specified key" do
21
+ I18n.locale = :pl
22
+ assert_equal "Sukces!", I18n._(:key_to_translate)
23
+ assert_equal "Sukces!", I18n._(:"nested.translation")
24
+ end
25
+
26
+ should "translate string and symbol using built in helpers" do
27
+ I18n.locale = :pl
28
+ assert_equal "Testowa translacja", "Test translation".t
29
+ assert_equal "Sukces!", :"nested.translation".t
30
+ end
31
+
32
+ should "fallback translation to :root language" do
33
+ I18n.locale = :en
34
+ #assert_equal "It's work!", I18n.gettext("Translation fallback")
35
+ end
36
+ end
37
+
38
+ context "Translate inside modules and classes" do
39
+ should "allow to use gettext methods in extended module" do
40
+ module SampleFoo
41
+ extend I18n::Gettext
42
+
43
+ def self.test
44
+ gettext('Test translation')
45
+ end
46
+ end
47
+
48
+ result = nil
49
+ I18n.locale = :pl
50
+
51
+ assert begin
52
+ result = SampleFoo.test
53
+ true
54
+ rescue
55
+ false
56
+ end
57
+
58
+ assert_equal "Testowa translacja", result
59
+ end
60
+
61
+ should "allow to use gettext methods in extended class and it singleton" do
62
+ class SampleBar
63
+ include I18n::Gettext
64
+ include I18n::Gettext::Singleton
65
+
66
+ def self.test
67
+ gettext('Test translation')
68
+ end
69
+ def test
70
+ gettext('Test translation')
71
+ end
72
+ end
73
+
74
+ results = []
75
+ I18n.locale = :pl
76
+
77
+ assert begin
78
+ results << SampleBar.test
79
+ results << SampleBar.new.test
80
+ true
81
+ rescue
82
+ false
83
+ end
84
+
85
+ assert_equal "Testowa translacja", results.first
86
+ assert_equal "Testowa translacja", results.last
87
+ end
88
+ end
89
+
90
+ context "Translation in Rails" do
91
+ should "allow to use gettext methods in models" do
92
+ class SampleModel < ActiveRecord::Base
93
+ def self.columns; []; end
94
+ def self.foo
95
+ gettext('Test translation')
96
+ end
97
+ end
98
+
99
+ result = nil
100
+ I18n.locale = :pl
101
+
102
+ assert begin
103
+ result = SampleModel.foo
104
+ true
105
+ rescue
106
+ false
107
+ end
108
+
109
+ assert_equal "Testowa translacja", result
110
+ end
111
+
112
+ # TODO: tests for controllers and views
113
+ end
114
+ end
@@ -0,0 +1,2 @@
1
+ en:
2
+ "Translation with mistake": "Correct translation"
@@ -0,0 +1,6 @@
1
+ pl:
2
+ "Translation with mistake": "Poprawne tlumaczenie"
3
+ "Test translation": "Testowa translacja"
4
+ key_to_translate: "Sukces!"
5
+ nested:
6
+ translation: "Sukces!"
@@ -0,0 +1,2 @@
1
+ root:
2
+ "Translation fallback": "It's work!"
@@ -0,0 +1,13 @@
1
+ ENV['RAILS_ENV'] = 'test'
2
+ ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
3
+
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ gem 'rspec-rails'
7
+ gem 'thoughtbot-shoulda'
8
+ require 'shoulda'
9
+ require 'test/unit'
10
+ require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
11
+
12
+ I18n.load_path << Dir[File.join(File.dirname(__FILE__), 'locales', '*.{rb,yml}')]
13
+ I18n.backend.send(:init_translations)
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2008, 2009 Joshua Harvey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.