[DRE-commits] [ruby-stringex] 03/05: Imported Upstream version 2.2.0

Youhei SASAKI uwabami-guest at moszumanska.debian.org
Mon Feb 10 16:21:52 UTC 2014


This is an automated email from the git hooks/post-receive script.

uwabami-guest pushed a commit to branch master
in repository ruby-stringex.

commit 3857e16daf147941d264593ae3f3449efd0a143a
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date:   Tue Feb 11 01:10:05 2014 +0900

    Imported Upstream version 2.2.0
---
 Gemfile                                            |  10 +-
 Gemfile.lock                                       |  74 ------------
 README.rdoc                                        |  25 ++--
 Rakefile                                           |  10 +-
 VERSION                                            |   2 +-
 checksums.yaml.gz                                  | Bin 427 -> 419 bytes
 lib/stringex/acts_as_url/adapter/active_record.rb  |   2 +-
 lib/stringex/configuration/acts_as_url.rb          |   3 +-
 lib/stringex/configuration/string_extensions.rb    |   3 +-
 lib/stringex/configuration_lite.rb                 |   3 +
 lib/stringex/localization.rb                       |  22 +++-
 lib/stringex/localization/backend/base.rb          |  13 +++
 lib/stringex/localization/backend/i18n.rb          |  40 +++++--
 lib/stringex/localization/backend/internal.rb      |   6 +-
 .../localization/conversion_expressions.rb         |   7 +-
 lib/stringex/localization/converter.rb             |   6 +-
 lib/stringex/localization/default_conversions.rb   |   1 +
 lib/stringex/string_extensions.rb                  |  38 +++++-
 lib/stringex/unidecoder_data/x00.yml               |   2 +-
 lib/stringex_lite.rb                               |  15 +++
 locales/da.yml                                     |   3 +-
 locales/de.yml                                     |  77 ++++++++++++
 locales/en.yml                                     |   1 +
 locales/nl.yml                                     |  69 +++++++++++
 locales/pt-BR.yml                                  |   1 +
 locales/ru.yml                                     |  69 +++++++++++
 metadata.yml                                       |  71 ++++++-----
 stringex.gemspec                                   |  59 ++++++----
 test/performance/localization_performance_test.rb  |  24 ++++
 test/redcloth_to_html_test.rb                      |  37 ------
 .../acts_as_url/adapter/active_record.rb           |   0
 test/{ => unit}/acts_as_url/adapter/data_mapper.rb |   0
 test/{ => unit}/acts_as_url/adapter/mongoid.rb     |   0
 test/{ => unit}/acts_as_url_configuration_test.rb  |   0
 test/{ => unit}/acts_as_url_integration_test.rb    |  18 +++
 test/{ => unit}/localization/da_test.rb            |   5 +-
 test/unit/localization/de_test.rb                  | 118 +++++++++++++++++++
 test/{ => unit}/localization/default_test.rb       |   2 +
 test/{ => unit}/localization/en_test.rb            |   1 +
 test/unit/localization/nl_test.rb                  | 118 +++++++++++++++++++
 test/unit/localization/pt_br_test.rb               | 118 +++++++++++++++++++
 test/unit/localization/ru_test.rb                  | 130 +++++++++++++++++++++
 test/unit/localization_18n_failure_test.rb         |  40 +++++++
 test/{ => unit}/localization_test.rb               |  19 +++
 test/unit/string_extensions_configuration_test.rb  |  17 +++
 test/{ => unit}/string_extensions_test.rb          |  94 ++++++++++++++-
 .../unicode_point_suite/basic_greek_test.rb        |   0
 .../unicode_point_suite/basic_latin_test.rb        |   0
 .../unicode_point_suite/codepoint_test_helper.rb   |   0
 test/{ => unit}/unidecoder/bad_localization.yml    |   0
 test/{ => unit}/unidecoder/localization.yml        |   0
 test/{ => unit}/unidecoder_test.rb                 |   0
 test/{ => unit}/version_test.rb                    |   2 +-
 53 files changed, 1161 insertions(+), 214 deletions(-)

diff --git a/Gemfile b/Gemfile
index fdbed14..18c6638 100644
--- a/Gemfile
+++ b/Gemfile
@@ -14,7 +14,13 @@ group :development do
     puts "Mongoid requires Ruby higher than 1.8.x"
   end
   gem "RedCloth", "4.2.9" # Can I state that I really dislike camelcased gem names?
-  gem "sqlite3", "1.3.7"
   gem "travis-lint", "1.7.0"
   gem "i18n", "0.6.1"
-end
\ No newline at end of file
+  # For non-Jruby...
+  gem "sqlite3", "1.3.7", :platform => [:ruby, :mswin, :mingw]
+  # And for Jruby...
+  platform :jruby do
+    # gem "jdbc-sqlite3"
+    # gem "activerecord-jdbcsqlite3-adapter"
+  end
+end
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index 1946f01..0000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,74 +0,0 @@
-GEM
-  remote: https://rubygems.org/
-  specs:
-    RedCloth (4.2.9)
-    activemodel (3.2.13)
-      activesupport (= 3.2.13)
-      builder (~> 3.0.0)
-    activerecord (3.2.13)
-      activemodel (= 3.2.13)
-      activesupport (= 3.2.13)
-      arel (~> 3.0.2)
-      tzinfo (~> 0.3.29)
-    activesupport (3.2.13)
-      i18n (= 0.6.1)
-      multi_json (~> 1.0)
-    addressable (2.2.8)
-    arel (3.0.2)
-    builder (3.0.4)
-    data_objects (0.10.13)
-      addressable (~> 2.1)
-    dm-core (1.2.0)
-      addressable (~> 2.2.6)
-    dm-do-adapter (1.2.0)
-      data_objects (~> 0.10.6)
-      dm-core (~> 1.2.0)
-    dm-migrations (1.2.0)
-      dm-core (~> 1.2.0)
-    dm-sqlite-adapter (1.2.0)
-      dm-do-adapter (~> 1.2.0)
-      do_sqlite3 (~> 0.10.6)
-    dm-validations (1.2.0)
-      dm-core (~> 1.2.0)
-    do_sqlite3 (0.10.13)
-      data_objects (= 0.10.13)
-    git (1.2.5)
-    hashr (0.0.22)
-    i18n (0.6.1)
-    jeweler (1.8.4)
-      bundler (~> 1.0)
-      git (>= 1.2.5)
-      rake
-      rdoc
-    json (1.8.0)
-    mongoid (3.1.4)
-      activemodel (~> 3.2)
-      moped (~> 1.4)
-      origin (~> 1.0)
-      tzinfo (~> 0.3.22)
-    moped (1.5.0)
-    multi_json (1.7.5)
-    origin (1.1.0)
-    rake (10.0.4)
-    rdoc (4.0.1)
-      json (~> 1.4)
-    sqlite3 (1.3.7)
-    travis-lint (1.7.0)
-      hashr (~> 0.0.22)
-    tzinfo (0.3.37)
-
-PLATFORMS
-  ruby
-
-DEPENDENCIES
-  RedCloth (= 4.2.9)
-  activerecord (= 3.2.13)
-  dm-core (= 1.2.0)
-  dm-migrations (= 1.2.0)
-  dm-sqlite-adapter (= 1.2.0)
-  dm-validations (= 1.2.0)
-  i18n (= 0.6.1)
-  jeweler (= 1.8.4)
-  mongoid (= 3.1.4)
-  sqlite3 (= 1.3.7)
-  travis-lint (= 1.7.0)
diff --git a/README.rdoc b/README.rdoc
index b3e5c79..d2abd11 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -6,6 +6,8 @@ Some [hopefully] useful extensions to Ruby's String class. It is made up of thre
 
 == ActsAsUrl
 
+<em>NOTE: You can now require 'stringex_lite' instead of 'stringex' and skip loading ActsAsUrl functionality if you don't need it.</em>
+
 This library is designed to create URI-friendly representations of an attribute, for use in generating urls from your attributes. Basic usage is just calling the method:
 
   # Inside your model
@@ -26,6 +28,8 @@ which will populate the <tt>url</tt> attribute on the object with the converted
                              if you are routing solely on the generated slug as you will no longer
                              be guaranteed to lookup the expected record based on a duplicate slug.</em>
 <tt>:limit</tt>:: If set, will limit length of url generated. Default is nil.
+<tt>:truncate_words</tt>:: Used with :limit. If set to false, the url will be truncated to the last
+                           whole word before the limit was reached. Default is true.
 
 In order to use the generated url attribute, you will probably want to override <tt>to_param</tt> like so, in your Model:
 
@@ -95,14 +99,19 @@ A small collection of extensions on Ruby's String class. Please see the document
 
 With Stringex version 2.0 and higher, you can localize the different conversions in Stringex. Read more here[https://github.com/rsl/stringex/wiki/Localization-of-Stringex-conversions]. If you add a new language, please submit a pull request so we can make it available to other users also.
 
-== Using with Rails
-
-When using Stringex with Ruby on Rails, you automatically get built-in translations for miscellaneous characters, HTML entities, and vulgar fractions.
+== Ruby on Rails Usage
 
-You can see Stringex's standard translations here[https://github.com/rsl/stringex/tree/master/locales].
+When using Stringex with Ruby on Rails, you automatically get built-in translations for miscellaneous characters, HTML entities, and vulgar fractions. You can see Stringex's standard translations here[https://github.com/rsl/stringex/tree/master/locales].
 
 Currently, built-in translations are available for the following languages:
-English (en), Danish (da)
+
+  * English (en)
+  * Danish (da)
+  * Dutch (nl)
+  * German (de)
+  * Portuguese Brazilian (pt-BR)
+  * Russian (ru)
+
 
 You can easily add your own or customize the built-in translations - read here[https://github.com/rsl/stringex/wiki/Localization-of-Stringex-conversions]. If you add a new language, please submit a pull request so we can make it available to other users also.
 
@@ -110,7 +119,7 @@ If you don't want to use the Stringex built-in translations, you can force Strin
 
   Stringex::Localization.locale = :en
 
-== Note to users of CanCan
+== CanCan Usage Note
 
 You'll need to add a <tt>:find_by => :url</tt> to your <tt>load_and_authorize_resource</tt>.  Here's an example:
 
@@ -120,4 +129,6 @@ You'll need to add a <tt>:find_by => :url</tt> to your <tt>load_and_authorize_re
 
 If it's not obvious, some of the code for ActsAsUrl is based on Rick Olsen's permalink_fu[http://svn.techno-weenie.net/projects/plugins/permalink_fu/] plugin. Unidecoder is a Ruby port of Sean Burke's Text::Unidecode[http://interglacial.com/~sburke/tpj/as_html/tpj22.html] module for Perl. And, finally, the bulk of strip_html_tags[link:classes/Stringex/StringExtensions.html#M000005] in StringExtensions was stolen from Tobias Lütke's Regex in Typo[http://typosphere.org/].
 
-copyright (c) 2008-2012 Lucky Sneaks, released under the MIT license
+GIANT thanks to the many contributors who have helped make Stringex better and better: http://github.com/rsl/stringex/contributors
+
+copyright (c) 2008-2013 Lucky Sneaks, released under the MIT license
diff --git a/Rakefile b/Rakefile
index 5fa3f11..d21d86e 100644
--- a/Rakefile
+++ b/Rakefile
@@ -29,10 +29,18 @@ end
 
 Rake::TestTask.new do |t|
   t.libs << 'lib' << 'test'
-  t.pattern   = 'test/**/*_test.rb'
+  t.pattern   = 'test/unit/**/*_test.rb'
   t.verbose   = true
 end
 
+namespace :test do
+  Rake::TestTask.new(:performance) do |t|
+    t.libs << 'lib' << 'test'
+    t.pattern   = 'test/performance/**/*_test.rb'
+    t.verbose   = true
+  end
+end
+
 desc 'Default: Run Stringex test suite using ActiveRecord as the ORM'
 task :default => [:setup_active_record_suite, :test]
 
diff --git a/VERSION b/VERSION
index 6acdb44..e3a4f19 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.3
\ No newline at end of file
+2.2.0
\ No newline at end of file
diff --git a/checksums.yaml.gz b/checksums.yaml.gz
index 754a980..295b2fd 100644
Binary files a/checksums.yaml.gz and b/checksums.yaml.gz differ
diff --git a/lib/stringex/acts_as_url/adapter/active_record.rb b/lib/stringex/acts_as_url/adapter/active_record.rb
index 1d34d37..5242b47 100644
--- a/lib/stringex/acts_as_url/adapter/active_record.rb
+++ b/lib/stringex/acts_as_url/adapter/active_record.rb
@@ -11,7 +11,7 @@ module Stringex
       private
 
         def klass_previous_instances(&block)
-          klass.find_each(:conditions => {settings.url_attribute => [nil, '']}, &block)
+          klass.where(settings.url_attribute => [nil, '']).find_each(&block)
         end
 
         def self.orm_class
diff --git a/lib/stringex/configuration/acts_as_url.rb b/lib/stringex/configuration/acts_as_url.rb
index 226d72c..7046f80 100644
--- a/lib/stringex/configuration/acts_as_url.rb
+++ b/lib/stringex/configuration/acts_as_url.rb
@@ -14,7 +14,8 @@ module Stringex
           :exclude,
           :force_downcase,
           :limit,
-          :replace_whitespace_with
+          :replace_whitespace_with,
+          :truncate_words,
         ].inject(Hash.new){|m, x| m[x] = settings.send(x); m}
       end
 
diff --git a/lib/stringex/configuration/string_extensions.rb b/lib/stringex/configuration/string_extensions.rb
index cefff1d..6b50b24 100644
--- a/lib/stringex/configuration/string_extensions.rb
+++ b/lib/stringex/configuration/string_extensions.rb
@@ -11,7 +11,8 @@ module Stringex
           :exclude => [],
           :force_downcase => true,
           :limit => nil,
-          :replace_whitespace_with => "-"
+          :replace_whitespace_with => "-",
+          :truncate_words => true
         }
       end
     end
diff --git a/lib/stringex/configuration_lite.rb b/lib/stringex/configuration_lite.rb
new file mode 100644
index 0000000..22f5ae1
--- /dev/null
+++ b/lib/stringex/configuration_lite.rb
@@ -0,0 +1,3 @@
+require 'stringex/configuration/base'
+require 'stringex/configuration/configurator'
+require 'stringex/configuration/string_extensions'
diff --git a/lib/stringex/localization.rb b/lib/stringex/localization.rb
index 5ce35c8..1629d2e 100644
--- a/lib/stringex/localization.rb
+++ b/lib/stringex/localization.rb
@@ -2,6 +2,7 @@
 
 require 'stringex/localization/converter'
 require 'stringex/localization/default_conversions'
+require 'stringex/localization/backend/base'
 require 'stringex/localization/backend/internal'
 require 'stringex/localization/backend/i18n'
 
@@ -11,15 +12,19 @@ module Stringex
 
     class << self
       def backend
-        @backend ||= defined?(I18n) ? Backend::I18n : Backend::Internal
+        @backend ||= i18n_present? ? Backend::I18n : Backend::Internal
       end
 
       def backend=(sym_or_class)
         if sym_or_class.is_a?(Symbol)
           @backend = case sym_or_class
-            when :internal then Backend::Internal
-            when :i18n then Backend::I18n
-            else raise "Invalid backend :#{sym_or_class}"
+          when :internal
+            Backend::Internal
+          when :i18n
+            ensure_i18n!
+            Backend::I18n
+          else
+            raise "Invalid backend :#{sym_or_class}"
           end
         else
           @backend = sym_or_class
@@ -93,6 +98,15 @@ module Stringex
         return unless DefaultConversions.respond_to?(scope)
         DefaultConversions.send(scope)[key]
       end
+
+      def i18n_present?
+        defined?(I18n) && I18n.respond_to?(:translate)
+      end
+
+      def ensure_i18n!
+        raise Backend::I18nNotDefined unless defined?(I18n)
+        raise Backend::I18nMissingTranslate unless I18n.respond_to?(:translate)
+      end
     end
   end
 end
diff --git a/lib/stringex/localization/backend/base.rb b/lib/stringex/localization/backend/base.rb
new file mode 100644
index 0000000..de14025
--- /dev/null
+++ b/lib/stringex/localization/backend/base.rb
@@ -0,0 +1,13 @@
+module Stringex
+  module Localization
+    module Backend
+      class Base
+        class << self
+          def reset!
+            instance_variables.each { |var| remove_instance_variable var }
+          end
+        end
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/stringex/localization/backend/i18n.rb b/lib/stringex/localization/backend/i18n.rb
index fbb1456..b290921 100644
--- a/lib/stringex/localization/backend/i18n.rb
+++ b/lib/stringex/localization/backend/i18n.rb
@@ -1,16 +1,16 @@
 module Stringex
   module Localization
     module Backend
-      module I18n
+      class I18n < Base
         LOAD_PATH_BASE = File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', '..', 'locales')
 
         class << self
           def locale
-            ::I18n.locale
+            @locale || ::I18n.locale
           end
 
           def locale=(new_locale)
-            ::I18n.locale = new_locale
+            @locale = new_locale
           end
 
           def default_locale
@@ -27,25 +27,45 @@ module Stringex
 
           def store_translations(locale, scope, data)
             ::I18n.backend.store_translations(locale, { :stringex => { scope => data } })
+            reset_translations_cache
+          end
+
+          def translations
+            # Set up hash like translations[:en][:transliterations]["é"]
+            @translations ||= Hash.new { |hsh, locale| hsh[locale] = Hash.new({}).merge(i18n_translations_for(locale)) }
           end
 
           def initial_translation(scope, key, locale)
-            # I18n can't return a nil as default as this gets interpreted as if no default
-            # is specified, so we use a string instead.
-            translated = ::I18n.translate(key, :scope => [:stringex, scope], :locale => locale, :default => "__default__")
-            translated == "__default__" ? nil : translated
+            translations[locale][scope][key.to_sym]
           end
 
           def load_translations(locale = nil)
-            locale ||= ::I18n.locale
+            locale ||= self.locale
             path = Dir[File.join(LOAD_PATH_BASE, "#{locale}.yml")]
             ::I18n.load_path |= Dir[File.join(LOAD_PATH_BASE, "#{locale}.yml")]
             ::I18n.backend.load_translations
+            reset_translations_cache
           end
 
-          def reset!
-            # Can't reset I18n. Needed?
+          def i18n_translations_for(locale)
+            ::I18n.translate("stringex", :locale => locale, :default => {})
           end
+
+          def reset_translations_cache
+            @translations = nil
+          end
+        end
+      end
+
+      class I18nNotDefined < RuntimeError
+        def initialize
+          super 'Stringex cannot use I18n backend: I18n is not defined'
+        end
+      end
+
+      class I18nMissingTranslate < RuntimeError
+        def initialize
+          super 'Stringex cannot use I18n backend: I18n is defined but missing a translate method'
         end
       end
     end
diff --git a/lib/stringex/localization/backend/internal.rb b/lib/stringex/localization/backend/internal.rb
index 11e12d7..c899ff8 100644
--- a/lib/stringex/localization/backend/internal.rb
+++ b/lib/stringex/localization/backend/internal.rb
@@ -1,7 +1,7 @@
 module Stringex
   module Localization
     module Backend
-      module Internal
+      class Internal < Base
         DEFAULT_LOCALE = :en
 
         class << self
@@ -40,10 +40,6 @@ module Stringex
           def initial_translation(scope, key, locale)
             translations[locale][scope][key.to_sym]
           end
-
-          def reset!
-            @translations = @locale = @default_locale = nil
-          end
         end
       end
     end
diff --git a/lib/stringex/localization/conversion_expressions.rb b/lib/stringex/localization/conversion_expressions.rb
index 2342d7c..0e24dbe 100644
--- a/lib/stringex/localization/conversion_expressions.rb
+++ b/lib/stringex/localization/conversion_expressions.rb
@@ -3,7 +3,7 @@
 module Stringex
   module Localization
     module ConversionExpressions
-      ABBREVIATION = /(\s|^)([[:alpha:]](\.[[:alpha:]])+(\.?)[[:alpha:]]*(\s|$))/
+      ABBREVIATION = /(\s|\(|^)([[:alpha:]](\.[[:alpha:]])+(\.?)[[:alpha:]]*(\s|\)|$))/
 
       ACCENTED_HTML_ENTITY = /&([A-Za-z])(grave|acute|circ|tilde|uml|ring|cedil|slash);/
 
@@ -25,15 +25,16 @@ module Stringex
       }
 
       # Things that just get converted to spaces
-      CLEANUP_CHARACTERS = /[\.,:;(){}\[\]\?!\^'ʼ"_\|]/
+      CLEANUP_CHARACTERS = /[\.,:;(){}\[\]\?!\^'ʼ"_\|<>]/
       CLEANUP_HTML_ENTITIES = /&[^;]+;/
 
       CURRENCIES_SUPPORTED_SIMPLE = {
+        :generic => /¤/,
         :dollars => /\$/,
         :euros   => /€/,
         :pounds  => /£/,
         :yen     => /¥/,
-        :reais   => /R$/
+        :reais   => /R\$/
       }
       CURRENCIES_SUPPORTED_COMPLEX = {
         :dollars => :dollars_cents,
diff --git a/lib/stringex/localization/converter.rb b/lib/stringex/localization/converter.rb
index 5daaa17..8c84f33 100644
--- a/lib/stringex/localization/converter.rb
+++ b/lib/stringex/localization/converter.rb
@@ -36,6 +36,10 @@ module Stringex
         end
       end
 
+      def normalize_currency!
+        string.gsub! /(\d+),(\d+)/, '\1\2'
+      end
+
       def smart_strip!
         string.strip!
         @string = "#{starting_whitespace}#{string}#{ending_whitespace}"
@@ -71,7 +75,7 @@ module Stringex
         expressions.characters.each do |key, expression|
           next if key == :slash && options[:allow_slash]
           replacement = translate(key)
-          replacement = " #{replacement} " unless key == :dot
+          replacement = " #{replacement} " unless replacement == '' || key == :dot
           string.gsub! expression, replacement
         end
       end
diff --git a/lib/stringex/localization/default_conversions.rb b/lib/stringex/localization/default_conversions.rb
index 78bf9ee..a60fb8f 100644
--- a/lib/stringex/localization/default_conversions.rb
+++ b/lib/stringex/localization/default_conversions.rb
@@ -19,6 +19,7 @@ module Stringex
       }
 
       CURRENCIES_SIMPLE = {
+        :generic       => '\1 dollars',
         :dollars       => '\1 dollars',
         :euros         => '\1 euros',
         :pounds        => '\1 pounds',
diff --git a/lib/stringex/string_extensions.rb b/lib/stringex/string_extensions.rb
index 0c12c5b..16d38af 100644
--- a/lib/stringex/string_extensions.rb
+++ b/lib/stringex/string_extensions.rb
@@ -2,6 +2,14 @@
 
 module Stringex
   module StringExtensions
+    def self.configure(&block)
+      Stringex::Configuration::StringExtensions.configure &block
+    end
+
+    def self.unconfigure!
+      Stringex::Configuration::StringExtensions.unconfigure!
+    end
+
     # These methods are all included into the String class.
     module PublicInstanceMethods
       # Removes specified character from the beginning and/or end of the string and then performs
@@ -53,6 +61,7 @@ module Stringex
       # before running this method.
       def convert_miscellaneous_characters(options = {})
         stringex_convert(options) do
+          normalize_currency!
           translate! :ellipses, :currencies, :abbreviations, :characters, :apostrophes
           cleanup_characters!
         end
@@ -85,10 +94,31 @@ module Stringex
       end
 
       # Returns the string limited in size to the value of limit.
-      def limit(limit = nil)
-        limit.nil? ? self : self[0...limit]
+      def limit(limit = nil, truncate_words = true)
+        if limit.nil?
+          self
+        else
+          truncate_words == false ? self.whole_word_limit(limit) : self[0...limit]
+        end
       end
 
+      def whole_word_limit(limit)
+        whole_words = []
+        words = self.split('-')
+
+        words.each do |word|
+          if word.size > limit
+            break
+          else
+            whole_words << word
+            limit -= (word.size + 1)
+          end
+        end
+
+        whole_words.join('-')
+      end
+
+
       # Performs multiple text manipulations. Essentially a shortcut for typing them all. View source
       # below to see which methods are run.
       def remove_formatting(options = {})
@@ -158,7 +188,7 @@ module Stringex
         dummy = remove_formatting(options).
                   replace_whitespace(whitespace_replacement_token).
                   collapse("-").
-                  limit(options[:limit])
+                  limit(options[:limit], options[:truncate_words])
         dummy.downcase! unless options[:force_downcase] == false
         dummy
       end
@@ -170,7 +200,7 @@ module Stringex
       end
 
       def stringex_default_options
-        Stringex::Configuration::StringExtensions.default_settings
+        Stringex::Configuration::StringExtensions.new.settings.marshal_dump
       end
     end
 
diff --git a/lib/stringex/unidecoder_data/x00.yml b/lib/stringex/unidecoder_data/x00.yml
index e757ed2..c921cfc 100644
--- a/lib/stringex/unidecoder_data/x00.yml
+++ b/lib/stringex/unidecoder_data/x00.yml
@@ -163,7 +163,7 @@
 - ''
 - C/
 - PS
-- $?
+- $
 - Y=
 - '|'
 - SS
diff --git a/lib/stringex_lite.rb b/lib/stringex_lite.rb
new file mode 100644
index 0000000..0fb8716
--- /dev/null
+++ b/lib/stringex_lite.rb
@@ -0,0 +1,15 @@
+# encoding: UTF-8
+
+require 'ostruct'
+require 'stringex/configuration'
+require 'stringex/localization'
+require 'stringex/string_extensions'
+require 'stringex/unidecoder'
+require 'stringex/version'
+
+String.send :include, Stringex::StringExtensions::PublicInstanceMethods
+String.send :extend, Stringex::StringExtensions::PublicClassMethods
+
+if defined?(Rails::Railtie)
+  require 'stringex/rails/railtie'
+end
diff --git a/locales/da.yml b/locales/da.yml
index ef99bf4..9c68202 100644
--- a/locales/da.yml
+++ b/locales/da.yml
@@ -19,6 +19,7 @@ da:
       slash: skråstreg
       star: stjerne
     currencies:
+      generic: \1 kroner
       dollars: \1 dollars
       dollars_cents: \1 dollars \2 cents
       pounds: \1 pund
@@ -29,7 +30,7 @@ da:
       reais: \1 reais
       reais_cents: \1 reais \2 cents
     html_entities:
-      amp: and
+      amp: og
       cent: " cents"
       copy: (c)
       deg: " grader "
diff --git a/locales/de.yml b/locales/de.yml
new file mode 100644
index 0000000..a34e891
--- /dev/null
+++ b/locales/de.yml
@@ -0,0 +1,77 @@
+# NOTE: Some translation keys make use of matches from regular expressions
+# to manipulate whitespace and order. Please consult the source code for
+# Stringex::Localization::ConversionExpressions to see what those
+# regular expressions look like if you need to manipulate the order
+# differently than the usage below.
+de:
+  stringex:
+    characters:
+      and: und
+      at: um
+      divide: geteilt durch
+      degrees: Grad
+      dot: \1 Punkt \2
+      ellipsis: Punkt Punkt Punkt
+      equals: gleich
+      number: Nummer
+      percent: Prozent
+      plus: plus
+      slash: Strich
+      star: Stern
+    currencies:
+      generic: \1 Euro
+      dollars: \1 Dollar
+      dollars_cents: \1 Dollar \2 Cent
+      pounds: \1 Pfund
+      pounds_pence: \1 Pfund \2 Pence
+      euros: \1 Euro
+      euros_cents: \1 Euro \2 Cent
+      yen: \1 Yen
+      reais: \1 Reais
+      reais_cents: \1 Reais \2 Cent
+    html_entities:
+      amp: und
+      cent: " Cent"
+      copy: (C)
+      deg: " Grad "
+      divide: " geteilt durch "
+      double_quote: '"'
+      ellipsis: "..."
+      en_dash: "-"
+      em_dash: "--"
+      frac14: ein Viertel
+      frac12: halbe(r)
+      frac34: drei Viertel
+      gt: ">"
+      lt: <
+      nbsp: " "
+      pound: " Pfund "
+      reg: (R)
+      single_quote: "'"
+      times: x
+      trade: (TM)
+      yen: " Yen "
+    vulgar_fractions:
+      half: halbe(r)
+      one_third: ein Drittel
+      two_thirds: zwei Drittel
+      one_fourth: ein Viertel
+      three_fourths: drei Viertel
+      one_fifth: ein Fünftel
+      two_fifths: zwei Fünftel
+      three_fifths: drei Fünftel
+      four_fifths: vier Fünftel
+      one_sixth: ein Sechstel
+      five_sixths: fünf Sechstel
+      one_eighth: ein Achtel
+      three_eighths: drei Achtel
+      five_eighths: fünf Achtel
+      seven_eighths: sieben Achtel
+    transliterations:
+      Ä: AE
+      Ö: OE
+      Ü: UE
+      ß: ss
+      ä: ae
+      ö: oe
+      ü: ue
\ No newline at end of file
diff --git a/locales/en.yml b/locales/en.yml
index e1138cd..921791a 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -19,6 +19,7 @@ en:
       slash: slash
       star: star
     currencies:
+      generic: \1 pounds
       dollars: \1 dollars
       dollars_cents: \1 dollars \2 cents
       pounds: \1 pounds
diff --git a/locales/nl.yml b/locales/nl.yml
new file mode 100644
index 0000000..e1d00e5
--- /dev/null
+++ b/locales/nl.yml
@@ -0,0 +1,69 @@
+# NOTE: Some translation keys make use of matches from regular expressions
+# to manipulate whitespace and order. Please consult the source code for
+# Stringex::Localization::ConversionExpressions to see what those
+# regular expressions look like if you need to manipulate the order
+# differently than the usage below.
+nl:
+  stringex:
+    characters:
+      and: en
+      at: op
+      divide: gedeeld door
+      degrees: graden
+      dot: \1 punt \2
+      ellipsis: punt punt punt
+      equals: is
+      number: nummer
+      percent: procent
+      plus: plus
+      slash: slash
+      star: ster
+    currencies:
+      generic: \1 euro
+      dollars: \1 dollar
+      dollars_cents: \1 dollar \2 cent
+      pounds: \1 pond
+      pounds_pence: \1 pond \2 pence
+      euros: \1 euro
+      euros_cents: \1 euro \2 cent
+      yen: \1 yen
+      reais: \1 reais
+      reais_cents: \1 reais \2 cents
+    html_entities:
+      amp: en
+      cent: " cent"
+      copy: (c)
+      deg: " graden "
+      divide: " gedeeld door "
+      double_quote: '"'
+      ellipsis: "..."
+      en_dash: "-"
+      em_dash: "--"
+      frac14: eenvierde
+      frac12: half
+      frac34: drievierde
+      gt: ">"
+      lt: <
+      nbsp: " "
+      pound: " pond "
+      reg: (r)
+      single_quote: "'"
+      times: x
+      trade: (tm)
+      yen: " yen "
+    vulgar_fractions:
+      half: half
+      one_third: eenderde
+      two_thirds: tweederde
+      one_fourth: eenvierde
+      three_fourths: drievierde
+      one_fifth: eenvijfde
+      two_fifths: tweevijfde
+      three_fifths: drievijfde
+      four_fifths: viervijfde
+      one_sixth: eenzesde
+      five_sixths: vijfzesde
+      one_eighth: eenachtste
+      three_eighths: drieachtste
+      five_eighths: vijfachtste
+      seven_eighths: zevenachtste
diff --git a/locales/pt-BR.yml b/locales/pt-BR.yml
index 4e58717..04e4fef 100644
--- a/locales/pt-BR.yml
+++ b/locales/pt-BR.yml
@@ -19,6 +19,7 @@ pt-BR:
       slash: barra
       star: estrela
     currencies:
+      generic: \1 reais
       dollars: \1 dólares
       dollars_cents: \1 dólares \2 cents
       pounds: \1 libras
diff --git a/locales/ru.yml b/locales/ru.yml
new file mode 100644
index 0000000..4bc420a
--- /dev/null
+++ b/locales/ru.yml
@@ -0,0 +1,69 @@
+# NOTE: Some translation keys make use of matches from regular expressions
+# to manipulate whitespace and order. Please consult the source code for
+# Stringex::Localization::ConversionExpressions to see what those
+# regular expressions look like if you need to manipulate the order
+# differently than the usage below.
+ru:
+  stringex:
+    characters:
+      and: и
+      at: в
+      divide: делить на
+      degrees: градусов
+      dot: \1 точка \2
+      ellipsis: многоточие
+      equals: равно
+      number: номер
+      percent: процентов
+      plus: плюс
+      slash: слеш
+      star: звезда
+    currencies:
+      generic: \1 рубль
+      dollars: \1 долларов
+      dollars_cents: \1 долларов \2 центов
+      pounds: \1 фунтов
+      pounds_pence: \1 фунтов \2 пенсов
+      euros: \1 евро
+      euros_cents: \1 евро \2 центов
+      yen: \1 йен
+      reais: \1 реал
+      reais_cents: \1 реал \2 сентаво
+    html_entities:
+      amp: и
+      cent: " центов"
+      copy: (c)
+      deg: " градусов "
+      divide: " делить на "
+      double_quote: '"'
+      ellipsis: "..."
+      en_dash: "-"
+      em_dash: "--"
+      frac14: одна четверть
+      frac12: половина
+      frac34: три четверти
+      gt: ">"
+      lt: <
+      nbsp: " "
+      pound: " фунтов "
+      reg: (r)
+      single_quote: "'"
+      times: x
+      trade: (tm)
+      yen: " йен "
+    vulgar_fractions:
+      half: половина
+      one_third: одна треть
+      two_thirds: две трети
+      one_fourth: одна четверть
+      three_fourths: три четверти
+      one_fifth: одна пятая
+      two_fifths: две пятых
+      three_fifths: три пятых
+      four_fifths: четыре пятых
+      one_sixth: одна шестая
+      five_sixths: пять шестых
+      one_eighth: одна восьмая
+      three_eighths: три восьмых
+      five_eighths: пять восьмых
+      seven_eighths: семь восьмых
diff --git a/metadata.yml b/metadata.yml
index 7f16300..dbc8195 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: stringex
 version: !ruby/object:Gem::Version
-  version: 2.0.3
+  version: 2.2.0
 platform: ruby
 authors:
 - Russell Norris
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2013-06-17 00:00:00.000000000 Z
+date: 2014-02-03 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: activerecord
@@ -123,47 +123,47 @@ dependencies:
       - !ruby/object:Gem::Version
         version: 4.2.9
 - !ruby/object:Gem::Dependency
-  name: sqlite3
+  name: travis-lint
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 1.3.7
+        version: 1.7.0
   type: :development
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 1.3.7
+        version: 1.7.0
 - !ruby/object:Gem::Dependency
-  name: travis-lint
+  name: i18n
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 1.7.0
+        version: 0.6.1
   type: :development
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 1.7.0
+        version: 0.6.1
 - !ruby/object:Gem::Dependency
-  name: i18n
+  name: sqlite3
   requirement: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 0.6.1
+        version: 1.3.7
   type: :development
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - '='
       - !ruby/object:Gem::Version
-        version: 0.6.1
+        version: 1.3.7
 description: ! 'Some [hopefully] useful extensions to Ruby''s String class. Stringex
   is made up of three libraries: ActsAsUrl [permalink solution with better character
   translation], Unidecoder [Unicode to ASCII transliteration], and StringExtensions
@@ -176,7 +176,6 @@ extra_rdoc_files:
 - README.rdoc
 files:
 - Gemfile
-- Gemfile.lock
 - MIT-LICENSE
 - README.rdoc
 - Rakefile
@@ -194,7 +193,9 @@ files:
 - lib/stringex/configuration/base.rb
 - lib/stringex/configuration/configurator.rb
 - lib/stringex/configuration/string_extensions.rb
+- lib/stringex/configuration_lite.rb
 - lib/stringex/localization.rb
+- lib/stringex/localization/backend/base.rb
 - lib/stringex/localization/backend/i18n.rb
 - lib/stringex/localization/backend/internal.rb
 - lib/stringex/localization/conversion_expressions.rb
@@ -384,29 +385,39 @@ files:
 - lib/stringex/unidecoder_data/xfe.yml
 - lib/stringex/unidecoder_data/xff.yml
 - lib/stringex/version.rb
+- lib/stringex_lite.rb
 - locales/da.yml
+- locales/de.yml
 - locales/en.yml
+- locales/nl.yml
 - locales/pt-BR.yml
+- locales/ru.yml
 - stringex.gemspec
-- test/acts_as_url/adapter/active_record.rb
-- test/acts_as_url/adapter/data_mapper.rb
-- test/acts_as_url/adapter/mongoid.rb
-- test/acts_as_url_configuration_test.rb
-- test/acts_as_url_integration_test.rb
-- test/localization/da_test.rb
-- test/localization/default_test.rb
-- test/localization/en_test.rb
-- test/localization_test.rb
-- test/redcloth_to_html_test.rb
-- test/string_extensions_test.rb
+- test/performance/localization_performance_test.rb
 - test/test_helper.rb
-- test/unicode_point_suite/basic_greek_test.rb
-- test/unicode_point_suite/basic_latin_test.rb
-- test/unicode_point_suite/codepoint_test_helper.rb
-- test/unidecoder/bad_localization.yml
-- test/unidecoder/localization.yml
-- test/unidecoder_test.rb
-- test/version_test.rb
+- test/unit/acts_as_url/adapter/active_record.rb
+- test/unit/acts_as_url/adapter/data_mapper.rb
+- test/unit/acts_as_url/adapter/mongoid.rb
+- test/unit/acts_as_url_configuration_test.rb
+- test/unit/acts_as_url_integration_test.rb
+- test/unit/localization/da_test.rb
+- test/unit/localization/de_test.rb
+- test/unit/localization/default_test.rb
+- test/unit/localization/en_test.rb
+- test/unit/localization/nl_test.rb
+- test/unit/localization/pt_br_test.rb
+- test/unit/localization/ru_test.rb
+- test/unit/localization_18n_failure_test.rb
+- test/unit/localization_test.rb
+- test/unit/string_extensions_configuration_test.rb
+- test/unit/string_extensions_test.rb
+- test/unit/unicode_point_suite/basic_greek_test.rb
+- test/unit/unicode_point_suite/basic_latin_test.rb
+- test/unit/unicode_point_suite/codepoint_test_helper.rb
+- test/unit/unidecoder/bad_localization.yml
+- test/unit/unidecoder/localization.yml
+- test/unit/unidecoder_test.rb
+- test/unit/version_test.rb
 homepage: http://github.com/rsl/stringex
 licenses:
 - MIT
diff --git a/stringex.gemspec b/stringex.gemspec
index e58edf7..b854c71 100644
--- a/stringex.gemspec
+++ b/stringex.gemspec
@@ -5,11 +5,11 @@
 
 Gem::Specification.new do |s|
   s.name = "stringex"
-  s.version = "2.0.3"
+  s.version = "2.2.0"
 
   s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
   s.authors = ["Russell Norris"]
-  s.date = "2013-06-17"
+  s.date = "2014-02-03"
   s.description = "Some [hopefully] useful extensions to Ruby's String class. Stringex is made up of three libraries: ActsAsUrl [permalink solution with better character translation], Unidecoder [Unicode to ASCII transliteration], and StringExtensions [miscellaneous helper methods for the String class]."
   s.email = "rsl at luckysneaks.com"
   s.extra_rdoc_files = [
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
   ]
   s.files = [
     "Gemfile",
-    "Gemfile.lock",
     "MIT-LICENSE",
     "README.rdoc",
     "Rakefile",
@@ -36,7 +35,9 @@ Gem::Specification.new do |s|
     "lib/stringex/configuration/base.rb",
     "lib/stringex/configuration/configurator.rb",
     "lib/stringex/configuration/string_extensions.rb",
+    "lib/stringex/configuration_lite.rb",
     "lib/stringex/localization.rb",
+    "lib/stringex/localization/backend/base.rb",
     "lib/stringex/localization/backend/i18n.rb",
     "lib/stringex/localization/backend/internal.rb",
     "lib/stringex/localization/conversion_expressions.rb",
@@ -226,29 +227,39 @@ Gem::Specification.new do |s|
     "lib/stringex/unidecoder_data/xfe.yml",
     "lib/stringex/unidecoder_data/xff.yml",
     "lib/stringex/version.rb",
+    "lib/stringex_lite.rb",
     "locales/da.yml",
+    "locales/de.yml",
     "locales/en.yml",
+    "locales/nl.yml",
     "locales/pt-BR.yml",
+    "locales/ru.yml",
     "stringex.gemspec",
-    "test/acts_as_url/adapter/active_record.rb",
-    "test/acts_as_url/adapter/data_mapper.rb",
-    "test/acts_as_url/adapter/mongoid.rb",
-    "test/acts_as_url_configuration_test.rb",
-    "test/acts_as_url_integration_test.rb",
-    "test/localization/da_test.rb",
-    "test/localization/default_test.rb",
-    "test/localization/en_test.rb",
-    "test/localization_test.rb",
-    "test/redcloth_to_html_test.rb",
-    "test/string_extensions_test.rb",
+    "test/performance/localization_performance_test.rb",
     "test/test_helper.rb",
-    "test/unicode_point_suite/basic_greek_test.rb",
-    "test/unicode_point_suite/basic_latin_test.rb",
-    "test/unicode_point_suite/codepoint_test_helper.rb",
-    "test/unidecoder/bad_localization.yml",
-    "test/unidecoder/localization.yml",
-    "test/unidecoder_test.rb",
-    "test/version_test.rb"
+    "test/unit/acts_as_url/adapter/active_record.rb",
+    "test/unit/acts_as_url/adapter/data_mapper.rb",
+    "test/unit/acts_as_url/adapter/mongoid.rb",
+    "test/unit/acts_as_url_configuration_test.rb",
+    "test/unit/acts_as_url_integration_test.rb",
+    "test/unit/localization/da_test.rb",
+    "test/unit/localization/de_test.rb",
+    "test/unit/localization/default_test.rb",
+    "test/unit/localization/en_test.rb",
+    "test/unit/localization/nl_test.rb",
+    "test/unit/localization/pt_br_test.rb",
+    "test/unit/localization/ru_test.rb",
+    "test/unit/localization_18n_failure_test.rb",
+    "test/unit/localization_test.rb",
+    "test/unit/string_extensions_configuration_test.rb",
+    "test/unit/string_extensions_test.rb",
+    "test/unit/unicode_point_suite/basic_greek_test.rb",
+    "test/unit/unicode_point_suite/basic_latin_test.rb",
+    "test/unit/unicode_point_suite/codepoint_test_helper.rb",
+    "test/unit/unidecoder/bad_localization.yml",
+    "test/unit/unidecoder/localization.yml",
+    "test/unit/unidecoder_test.rb",
+    "test/unit/version_test.rb"
   ]
   s.homepage = "http://github.com/rsl/stringex"
   s.licenses = ["MIT"]
@@ -269,9 +280,9 @@ Gem::Specification.new do |s|
       s.add_development_dependency(%q<jeweler>, ["= 1.8.4"])
       s.add_development_dependency(%q<mongoid>, ["= 3.1.4"])
       s.add_development_dependency(%q<RedCloth>, ["= 4.2.9"])
-      s.add_development_dependency(%q<sqlite3>, ["= 1.3.7"])
       s.add_development_dependency(%q<travis-lint>, ["= 1.7.0"])
       s.add_development_dependency(%q<i18n>, ["= 0.6.1"])
+      s.add_development_dependency(%q<sqlite3>, ["= 1.3.7"])
     else
       s.add_dependency(%q<activerecord>, ["= 3.2.13"])
       s.add_dependency(%q<dm-core>, ["= 1.2.0"])
@@ -281,9 +292,9 @@ Gem::Specification.new do |s|
       s.add_dependency(%q<jeweler>, ["= 1.8.4"])
       s.add_dependency(%q<mongoid>, ["= 3.1.4"])
       s.add_dependency(%q<RedCloth>, ["= 4.2.9"])
-      s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
       s.add_dependency(%q<travis-lint>, ["= 1.7.0"])
       s.add_dependency(%q<i18n>, ["= 0.6.1"])
+      s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
     end
   else
     s.add_dependency(%q<activerecord>, ["= 3.2.13"])
@@ -294,9 +305,9 @@ Gem::Specification.new do |s|
     s.add_dependency(%q<jeweler>, ["= 1.8.4"])
     s.add_dependency(%q<mongoid>, ["= 3.1.4"])
     s.add_dependency(%q<RedCloth>, ["= 4.2.9"])
-    s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
     s.add_dependency(%q<travis-lint>, ["= 1.7.0"])
     s.add_dependency(%q<i18n>, ["= 0.6.1"])
+    s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
   end
 end
 
diff --git a/test/performance/localization_performance_test.rb b/test/performance/localization_performance_test.rb
new file mode 100644
index 0000000..b2c3461
--- /dev/null
+++ b/test/performance/localization_performance_test.rb
@@ -0,0 +1,24 @@
+require "test_helper"
+require 'stringex'
+require 'i18n'
+require 'benchmark'
+
+class LocalizationPerformanceTest < Test::Unit::TestCase
+  def setup
+    I18n.locale = :en
+    Stringex::Localization.reset!
+  end
+
+  def test_i18n_performance
+    Stringex::Localization.backend = :internal
+    internal_time = Benchmark.realtime { 100.times{ "alskdjfal".to_url } }
+
+    Stringex::Localization.backend = :i18n
+    i18n_time = Benchmark.realtime { 100.times{ "alskdjfal".to_url } }
+
+    percentage_difference = ((i18n_time - internal_time) / internal_time) * 100
+    allowed_difference = 25
+
+    assert percentage_difference <= allowed_difference, "The I18n backend is #{percentage_difference.to_i} percent slower than the internal backend. The allowed difference is #{allowed_difference} percent."
+  end
+end
diff --git a/test/redcloth_to_html_test.rb b/test/redcloth_to_html_test.rb
deleted file mode 100644
index 45c6854..0000000
--- a/test/redcloth_to_html_test.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'test_helper'
-require 'stringex'
-
-begin
-  require 'rubygems'
-  require 'RedCloth'
-rescue LoadError
-  puts
-  puts ">> Could not load RedCloth. String#to_html was not tested."
-  puts ">> Please gem install RedCloth if you'd like to use this functionality."
-  puts
-end
-
-class RedclothToHTMLTest < Test::Unit::TestCase
-  if defined?(RedCloth)
-    def test_to_html
-      {
-        "h1. A Solution" => "<h1>A Solution</h1>",
-        "I hated wrapping textilize around a string.\n\nIt always felt dirty." =>
-          "<p>I hated wrapping textilize around a string.</p>\n<p>It always felt dirty.</p>",
-        "I think _this_ is awesome" => "<p>I think <em>this</em> is awesome</p>",
-        "Um... _*really*_, man" => "<p>Um… <em><strong>really</strong></em>, man</p>"
-      }.each do |plain, html|
-        assert_equal html, plain.to_html
-      end
-    end
-
-    def test_to_html_lite
-      {
-        "I have no pee on me" => "I have no pee on me",
-        "But I _do_ get Textile!" => "But I <em>do</em> get Textile!"
-      }.each do |plain, html|
-        assert_equal html, plain.to_html(:lite)
-      end
-    end
-  end
-end
diff --git a/test/acts_as_url/adapter/active_record.rb b/test/unit/acts_as_url/adapter/active_record.rb
similarity index 100%
rename from test/acts_as_url/adapter/active_record.rb
rename to test/unit/acts_as_url/adapter/active_record.rb
diff --git a/test/acts_as_url/adapter/data_mapper.rb b/test/unit/acts_as_url/adapter/data_mapper.rb
similarity index 100%
rename from test/acts_as_url/adapter/data_mapper.rb
rename to test/unit/acts_as_url/adapter/data_mapper.rb
diff --git a/test/acts_as_url/adapter/mongoid.rb b/test/unit/acts_as_url/adapter/mongoid.rb
similarity index 100%
rename from test/acts_as_url/adapter/mongoid.rb
rename to test/unit/acts_as_url/adapter/mongoid.rb
diff --git a/test/acts_as_url_configuration_test.rb b/test/unit/acts_as_url_configuration_test.rb
similarity index 100%
rename from test/acts_as_url_configuration_test.rb
rename to test/unit/acts_as_url_configuration_test.rb
diff --git a/test/acts_as_url_integration_test.rb b/test/unit/acts_as_url_integration_test.rb
similarity index 95%
rename from test/acts_as_url_integration_test.rb
rename to test/unit/acts_as_url_integration_test.rb
index c06f04b..0780053 100644
--- a/test/acts_as_url_integration_test.rb
+++ b/test/unit/acts_as_url_integration_test.rb
@@ -326,4 +326,22 @@ class ActsAsUrlIntegrationTest < Test::Unit::TestCase
     @doc = Document.create(:title => "a b/c d")
     assert_equal "a-b/c-d", @doc.url
   end
+
+  def test_should_truncate_words_by_default
+    Document.class_eval do
+      acts_as_url :title, :limit => 20
+    end
+
+    @doc = Document.create(:title => "title with many whole words")
+    assert_equal 'title-with-many-whol', @doc.url
+  end
+
+  def test_should_not_truncate_words
+    Document.class_eval do
+      acts_as_url :title, :limit => 20, :truncate_words => false
+    end
+
+    @doc = Document.create(:title => "title with many whole words")
+    assert_equal 'title-with-many', @doc.url
+  end
 end
diff --git a/test/localization/da_test.rb b/test/unit/localization/da_test.rb
similarity index 97%
rename from test/localization/da_test.rb
rename to test/unit/localization/da_test.rb
index 5952d08..f36f866 100644
--- a/test/localization/da_test.rb
+++ b/test/unit/localization/da_test.rb
@@ -24,7 +24,7 @@ class DanishYAMLLocalizationTest < Test::Unit::TestCase
     "100%" => "100 procent",
     "cost+tax" => "cost plus tax",
     "batman/robin fan fiction" => "batman skråstreg robin fan fiction",
-    "dial *69" => "dial stjerne 69",
+    "dial *69" => "dial stjerne 69"
     # " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
   }.each do |original, converted|
     define_method "test_character_conversion: '#{original}'" do
@@ -33,6 +33,7 @@ class DanishYAMLLocalizationTest < Test::Unit::TestCase
   end
 
   {
+    "¤20" => "20 kroner",
     "$100" => "100 dollars",
     "$19.99" => "19 dollars 99 cents",
     "£100" => "100 pund",
@@ -47,7 +48,7 @@ class DanishYAMLLocalizationTest < Test::Unit::TestCase
   end
 
   {
-    "Tea & Sympathy" => "Tea and Sympathy",
+    "Tea & Sympathy" => "Tea og Sympathy",
     "10¢" => "10 cents",
     "©2000" => "(c)2000",
     "98° is fine" => "98 grader is fine",
diff --git a/test/unit/localization/de_test.rb b/test/unit/localization/de_test.rb
new file mode 100644
index 0000000..36bfed6
--- /dev/null
+++ b/test/unit/localization/de_test.rb
@@ -0,0 +1,118 @@
+# encoding: UTF-8
+
+require 'test_helper'
+require 'i18n'
+require 'stringex'
+
+class GermanYAMLLocalizationTest < Test::Unit::TestCase
+  def setup
+    Stringex::Localization.reset!
+    Stringex::Localization.backend = :i18n
+    Stringex::Localization.backend.load_translations :de
+    Stringex::Localization.locale = :de
+  end
+
+  {
+    "foo & bar" => "foo und bar",
+    "AT&T" => "AT und T",
+    "99° sind normal" => "99 Grad sind normal",
+    "4 ÷ 2 ist 2" => "4 geteilt durch 2 ist 2",
+    "webcrawler.com" => "webcrawler Punkt com",
+    "Nun..." => "Nun Punkt Punkt Punkt",
+    "x=1" => "x gleich 1",
+    "Ein #2 Stift" => "Ein Nummer 2 Stift",
+    "100%" => "100 Prozent",
+    "Kosten+Steuern" => "Kosten plus Steuern",
+    "Batman/Robin Fan Fiction" => "Batman Strich Robin Fan Fiction",
+    "Wähle *69" => "Wähle Stern 69",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_character_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "¤20" => "20 Euro",
+    "$100" => "100 Dollar",
+    "$19.99" => "19 Dollar 99 Cent",
+    "£100" => "100 Pfund",
+    "£19.99" => "19 Pfund 99 Pence",
+    "€100" => "100 Euro",
+    "€19.99" => "19 Euro 99 Cent",
+    "¥1000" => "1000 Yen"
+  }.each do |original, converted|
+    define_method "test_currency_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "Hennes & Mauritz" => "Hennes und Mauritz",
+    "10¢" => "10 Cent",
+    "©2000" => "(C)2000",
+    "98° sind ok" => "98 Grad sind ok",
+    "10÷5" => "10 geteilt durch 5",
+    ""zitiert"" => '"zitiert"',
+    "Fortsetzung folgt…" => "Fortsetzung folgt...",
+    "2000–2004" => "2000-2004",
+    "Ich wünschte—oh, ach nichts" => "Ich wünschte--oh, ach nichts",
+    "&frac12; Unze Gold" => "halbe(r) Unze Gold",
+    "1 und &frac14; Unzen Silber" => "1 und ein Viertel Unzen Silber",
+    "9 und &frac34; Unzen Platin" => "9 und drei Viertel Unzen Platin",
+    "3>2" => "3>2",
+    "2<3" => "2<3",
+    "zwei Worte" => "zwei Worte",
+    "100£" => "100 Pfund",
+    "Walmart®" => "Walmart(R)",
+    "'einfach zitiert'" => "'einfach zitiert'",
+    "2×4" => "2x4",
+    "Programming™" => "Programming(TM)",
+    "20000¥" => "20000 Yen",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_html_entity_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_html_entities
+    end
+  end
+
+  {
+    "&frac12;" => "halbe(r)",
+    "½" => "halbe(r)",
+    "½" => "halbe(r)",
+    "⅓" => "ein Drittel",
+    "⅓" => "ein Drittel",
+    "⅔" => "zwei Drittel",
+    "⅔" => "zwei Drittel",
+    "&frac14;" => "ein Viertel",
+    "¼" => "ein Viertel",
+    "¼" => "ein Viertel",
+    "&frac34;" => "drei Viertel",
+    "¾" => "drei Viertel",
+    "¾" => "drei Viertel",
+    "⅕" => "ein Fünftel",
+    "⅕" => "ein Fünftel",
+    "⅖" => "zwei Fünftel",
+    "⅖" => "zwei Fünftel",
+    "⅗" => "drei Fünftel",
+    "⅗" => "drei Fünftel",
+    "⅘" => "vier Fünftel",
+    "⅘" => "vier Fünftel",
+    "⅙" => "ein Sechstel",
+    "⅙" => "ein Sechstel",
+    "⅚" => "fünf Sechstel",
+    "⅚" => "fünf Sechstel",
+    "⅛" => "ein Achtel",
+    "⅛" => "ein Achtel",
+    "⅜" => "drei Achtel",
+    "⅜" => "drei Achtel",
+    "⅝" => "fünf Achtel",
+    "⅝" => "fünf Achtel",
+    "⅞" => "sieben Achtel",
+    "⅞" => "sieben Achtel"
+  }.each do |original, converted|
+    define_method "test_vulgar_fractions_conversion: #{original}" do
+      assert_equal converted, original.convert_vulgar_fractions
+    end
+  end
+end
diff --git a/test/localization/default_test.rb b/test/unit/localization/default_test.rb
similarity index 99%
rename from test/localization/default_test.rb
rename to test/unit/localization/default_test.rb
index 79f713c..b8eec3c 100644
--- a/test/localization/default_test.rb
+++ b/test/unit/localization/default_test.rb
@@ -8,6 +8,7 @@ class DefaultLocalizationTest < Test::Unit::TestCase
     Stringex::Localization.reset!
     Stringex::Localization.backend = :internal
   end
+
   {
     "foo & bar" => "foo and bar",
     "AT&T" => "AT and T",
@@ -29,6 +30,7 @@ class DefaultLocalizationTest < Test::Unit::TestCase
   end
 
   {
+    "¤20" => "20 dollars",
     "$100" => "100 dollars",
     "$19.99" => "19 dollars 99 cents",
     "£100" => "100 pounds",
diff --git a/test/localization/en_test.rb b/test/unit/localization/en_test.rb
similarity index 99%
rename from test/localization/en_test.rb
rename to test/unit/localization/en_test.rb
index 7184b18..3487884 100644
--- a/test/localization/en_test.rb
+++ b/test/unit/localization/en_test.rb
@@ -33,6 +33,7 @@ class EnglishYAMLLocalizationTest < Test::Unit::TestCase
   end
 
   {
+    "¤20" => "20 pounds",
     "$100" => "100 dollars",
     "$19.99" => "19 dollars 99 cents",
     "£100" => "100 pounds",
diff --git a/test/unit/localization/nl_test.rb b/test/unit/localization/nl_test.rb
new file mode 100644
index 0000000..e0ad287
--- /dev/null
+++ b/test/unit/localization/nl_test.rb
@@ -0,0 +1,118 @@
+# encoding: UTF-8
+
+require 'test_helper'
+require 'i18n'
+require 'stringex'
+
+class DutchYAMLLocalizationTest < Test::Unit::TestCase
+  def setup
+    Stringex::Localization.reset!
+    Stringex::Localization.backend = :i18n
+    Stringex::Localization.backend.load_translations :nl
+    Stringex::Localization.locale = :nl
+  end
+
+  {
+    "foo & bar" => "foo en bar",
+    "AT&T" => "AT en T",
+    "99° is normaal" => "99 graden is normaal",
+    "4 ÷ 2 is 2" => "4 gedeeld door 2 is 2",
+    "webcrawler.com" => "webcrawler punt com",
+    "Dus..." => "Dus punt punt punt",
+    "x=1" => "x is 1",
+    "Een potlood #2" => "Een potlood nummer 2",
+    "100%" => "100 procent",
+    "prijs+belasting" => "prijs plus belasting",
+    "Batman/Robin fan fiction" => "Batman slash Robin fan fiction",
+    "bel *69" => "bel ster 69",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_character_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "¤20" => "20 euro",
+    "$100" => "100 dollar",
+    "$19.99" => "19 dollar 99 cent",
+    "£100" => "100 pond",
+    "£19.99" => "19 pond 99 pence",
+    "€100" => "100 euro",
+    "€19.99" => "19 euro 99 cent",
+    "¥1000" => "1000 yen"
+  }.each do |original, converted|
+    define_method "test_currency_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "Appels & peren" => "Appels en peren",
+    "10¢" => "10 cent",
+    "©2000" => "(c)2000",
+    "98° is acceptabel" => "98 graden is acceptabel",
+    "10÷5" => "10 gedeeld door 5",
+    ""tussen aanhalingstekens"" => '"tussen aanhalingstekens"',
+    "wordt vervolgd…" => "wordt vervolgd...",
+    "2000–2004" => "2000-2004",
+    "Ik wil—oh, laat maar" => "Ik wil--oh, laat maar",
+    "&frac12; ons goud" => "half ons goud",
+    "1 en &frac14; ons zilver" => "1 en eenvierde ons zilver",
+    "9 en &frac34; ons platina" => "9 en drievierde ons platina",
+    "3>2" => "3>2",
+    "2<3" => "2<3",
+    "twee woorden" => "twee woorden",
+    "100£" => "100 pond",
+    "Walmart®" => "Walmart(r)",
+    "'enkele aanhalingstekens'" => "'enkele aanhalingstekens'",
+    "2×4" => "2x4",
+    "Programming™" => "Programming(tm)",
+    "20000¥" => "20000 yen",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_html_entity_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_html_entities
+    end
+  end
+
+  {
+    "&frac12;" => "half",
+    "½" => "half",
+    "½" => "half",
+    "⅓" => "eenderde",
+    "⅓" => "eenderde",
+    "⅔" => "tweederde",
+    "⅔" => "tweederde",
+    "&frac14;" => "eenvierde",
+    "¼" => "eenvierde",
+    "¼" => "eenvierde",
+    "&frac34;" => "drievierde",
+    "¾" => "drievierde",
+    "¾" => "drievierde",
+    "⅕" => "eenvijfde",
+    "⅕" => "eenvijfde",
+    "⅖" => "tweevijfde",
+    "⅖" => "tweevijfde",
+    "⅗" => "drievijfde",
+    "⅗" => "drievijfde",
+    "⅘" => "viervijfde",
+    "⅘" => "viervijfde",
+    "⅙" => "eenzesde",
+    "⅙" => "eenzesde",
+    "⅚" => "vijfzesde",
+    "⅚" => "vijfzesde",
+    "⅛" => "eenachtste",
+    "⅛" => "eenachtste",
+    "⅜" => "drieachtste",
+    "⅜" => "drieachtste",
+    "⅝" => "vijfachtste",
+    "⅝" => "vijfachtste",
+    "⅞" => "zevenachtste",
+    "⅞" => "zevenachtste"
+  }.each do |original, converted|
+    define_method "test_vulgar_fractions_conversion: #{original}" do
+      assert_equal converted, original.convert_vulgar_fractions
+    end
+  end
+end
diff --git a/test/unit/localization/pt_br_test.rb b/test/unit/localization/pt_br_test.rb
new file mode 100644
index 0000000..bee51cb
--- /dev/null
+++ b/test/unit/localization/pt_br_test.rb
@@ -0,0 +1,118 @@
+# encoding: UTF-8
+
+require 'test_helper'
+require 'i18n'
+require 'stringex'
+
+class BrazilianYAMLLocalizationTest < Test::Unit::TestCase
+  def setup
+    Stringex::Localization.reset!
+    Stringex::Localization.backend = :i18n
+    Stringex::Localization.backend.load_translations :'pt-BR'
+    Stringex::Localization.locale = :'pt-BR'
+  end
+
+  {
+    "foo & bar" => "foo e bar",
+    "AT&T" => "AT e T",
+    "99° is normal" => "99 graus is normal",
+    "4 ÷ 2 is 2" => "4 dividido por 2 is 2",
+    "webcrawler.com" => "webcrawler ponto com",
+    "Well..." => "Well reticências",
+    "x=1" => "x igual à 1",
+    "a #2 pencil" => "a número 2 pencil",
+    "100%" => "100 porcento",
+    "cost+tax" => "cost mais tax",
+    "batman/robin fan fiction" => "batman barra robin fan fiction",
+    "dial *69" => "dial estrela 69",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_character_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "¤20" => "20 reais",
+    "$100" => "100 dólares",
+    "$19.99" => "19 dólares 99 cents",
+    "£100" => "100 libras",
+    "£19.99" => "19 libras 99 centavos",
+    "€100" => "100 euros",
+    "€19.99" => "19 euros 99 cents",
+    "¥1000" => "1000 yen"
+  }.each do |original, converted|
+    define_method "test_currency_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "Tea & Sympathy" => "Tea e Sympathy",
+    "10¢" => "10 centavos",
+    "©2000" => "(c)2000",
+    "98° is fine" => "98 graus is fine",
+    "10÷5" => "10 dividido por 5",
+    ""quoted"" => '"quoted"',
+    "to be continued…" => "to be continued...",
+    "2000–2004" => "2000-2004",
+    "I wish—oh, never mind" => "I wish--oh, never mind",
+    "&frac12; ounce of gold" => "metade ounce of gold",
+    "1 and &frac14; ounces of silver" => "1 and um quarto ounces of silver",
+    "9 and &frac34; ounces of platinum" => "9 and três quartos ounces of platinum",
+    "3>2" => "3>2",
+    "2<3" => "2<3",
+    "two words" => "two words",
+    "£100" => "libras 100",
+    "Walmart®" => "Walmart(r)",
+    "'single quoted'" => "'single quoted'",
+    "2×4" => "2x4",
+    "Programming™" => "Programming(tm)",
+    "¥20000" => "yen 20000",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_html_entity_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_html_entities
+    end
+  end
+
+  {
+    "&frac12;" => "metade",
+    "½" => "metade",
+    "½" => "metade",
+    "⅓" => "um terço",
+    "⅓" => "um terço",
+    "⅔" => "dois terços",
+    "⅔" => "dois terços",
+    "&frac14;" => "um quarto",
+    "¼" => "um quarto",
+    "¼" => "um quarto",
+    "&frac34;" => "três quartos",
+    "¾" => "três quartos",
+    "¾" => "três quartos",
+    "⅕" => "um quinto",
+    "⅕" => "um quinto",
+    "⅖" => "dois quintos",
+    "⅖" => "dois quintos",
+    "⅗" => "três quintos",
+    "⅗" => "três quintos",
+    "⅘" => "quatro quintos",
+    "⅘" => "quatro quintos",
+    "⅙" => "um sexto",
+    "⅙" => "um sexto",
+    "⅚" => "cinco sextos",
+    "⅚" => "cinco sextos",
+    "⅛" => "um oitavo",
+    "⅛" => "um oitavo",
+    "⅜" => "três oitavos",
+    "⅜" => "três oitavos",
+    "⅝" => "cinco oitavos",
+    "⅝" => "cinco oitavos",
+    "⅞" => "sete oitavos",
+    "⅞" => "sete oitavos"
+  }.each do |original, converted|
+    define_method "test_vulgar_fractions_conversion: #{original}" do
+      assert_equal converted, original.convert_vulgar_fractions
+    end
+  end
+end
diff --git a/test/unit/localization/ru_test.rb b/test/unit/localization/ru_test.rb
new file mode 100644
index 0000000..8e145e5
--- /dev/null
+++ b/test/unit/localization/ru_test.rb
@@ -0,0 +1,130 @@
+# encoding: UTF-8
+
+require 'test_helper'
+require 'i18n'
+require 'stringex'
+
+class RussianYAMLLocalizationTest < Test::Unit::TestCase
+  def setup
+    Stringex::Localization.reset!
+    Stringex::Localization.backend = :i18n
+    Stringex::Localization.backend.load_translations :ru
+    Stringex::Localization.locale = :ru
+  end
+
+  {
+    "foo & bar" => "foo и bar",
+    "AT&T" => "AT и T",
+    "99° is normal" => "99 градусов is normal",
+    "4 ÷ 2 is 2" => "4 делить на 2 is 2",
+    "webcrawler.com" => "webcrawler точка com",
+    "Well..." => "Well многоточие",
+    "x=1" => "x равно 1",
+    "a #2 pencil" => "a номер 2 pencil",
+    "100%" => "100 процентов",
+    "cost+tax" => "cost плюс tax",
+    "batman/robin fan fiction" => "batman слеш robin fan fiction",
+    "dial *69" => "dial звезда 69",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_character_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "¤20" => "20 рубль",
+    "$100" => "100 долларов",
+    "$19.99" => "19 долларов 99 центов",
+    "£100" => "100 фунтов",
+    "£19.99" => "19 фунтов 99 пенсов",
+    "€100" => "100 евро",
+    "€19.99" => "19 евро 99 центов",
+    "¥1000" => "1000 йен"
+  }.each do |original, converted|
+    define_method "test_currency_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_characters
+    end
+  end
+
+  {
+    "Tea & Sympathy" => "Tea и Sympathy",
+    "10¢" => "10 центов",
+    "©2000" => "(c)2000",
+    "98° is fine" => "98 градусов is fine",
+    "10÷5" => "10 делить на 5",
+    ""quoted"" => '"quoted"',
+    "to be continued…" => "to be continued...",
+    "2000–2004" => "2000-2004",
+    "I wish—oh, never mind" => "I wish--oh, never mind",
+    "&frac12; ounce of gold" => "половина ounce of gold",
+    "1 and &frac14; ounces of silver" => "1 and одна четверть ounces of silver",
+    "9 and &frac34; ounces of platinum" => "9 and три четверти ounces of platinum",
+    "3>2" => "3>2",
+    "2<3" => "2<3",
+    "two words" => "two words",
+    "£100" => "фунтов 100",
+    "Walmart®" => "Walmart(r)",
+    "'single quoted'" => "'single quoted'",
+    "2×4" => "2x4",
+    "Programming™" => "Programming(tm)",
+    "¥20000" => "йен 20000",
+    " i leave whitespace on ends unchanged " => " i leave whitespace on ends unchanged "
+  }.each do |original, converted|
+    define_method "test_html_entity_conversion: '#{original}'" do
+      assert_equal converted, original.convert_miscellaneous_html_entities
+    end
+  end
+
+  {
+    "&frac12;" => "половина",
+    "½" => "половина",
+    "½" => "половина",
+    "⅓" => "одна треть",
+    "⅓" => "одна треть",
+    "⅔" => "две трети",
+    "⅔" => "две трети",
+    "&frac14;" => "одна четверть",
+    "¼" => "одна четверть",
+    "¼" => "одна четверть",
+    "&frac34;" => "три четверти",
+    "¾" => "три четверти",
+    "¾" => "три четверти",
+    "⅕" => "одна пятая",
+    "⅕" => "одна пятая",
+    "⅖" => "две пятых",
+    "⅖" => "две пятых",
+    "⅗" => "три пятых",
+    "⅗" => "три пятых",
+    "⅘" => "четыре пятых",
+    "⅘" => "четыре пятых",
+    "⅙" => "одна шестая",
+    "⅙" => "одна шестая",
+    "⅚" => "пять шестых",
+    "⅚" => "пять шестых",
+    "⅛" => "одна восьмая",
+    "⅛" => "одна восьмая",
+    "⅜" => "три восьмых",
+    "⅜" => "три восьмых",
+    "⅝" => "пять восьмых",
+    "⅝" => "пять восьмых",
+    "⅞" => "семь восьмых",
+    "⅞" => "семь восьмых"
+  }.each do |original, converted|
+    define_method "test_vulgar_fractions_conversion: #{original}" do
+      assert_equal converted, original.convert_vulgar_fractions
+    end
+  end
+
+  {
+    "foo & bar" => "foo-i-bar",
+    "AT&T" => "at-i-t",
+    "99° is normal" => "99-ghradusov-is-normal",
+    "4 ÷ 2 is 2" => "4-dielit-na-2-is-2",
+    "webcrawler.com" => "webcrawler-tochka-com",
+  }.each do |original, converted|
+    define_method "test_character_conversion: '#{original}'" do
+      assert_equal converted, original.to_url
+    end
+  end
+end
diff --git a/test/unit/localization_18n_failure_test.rb b/test/unit/localization_18n_failure_test.rb
new file mode 100644
index 0000000..936024e
--- /dev/null
+++ b/test/unit/localization_18n_failure_test.rb
@@ -0,0 +1,40 @@
+require "test_helper"
+require 'stringex'
+
+class LocalizationI18nFailureTest < Test::Unit::TestCase
+  def setup
+    alias_i18n
+    Stringex::Localization.reset!
+  end
+
+  def test_loading_i18n_backend_fails_if_no_i18n_module
+    assert_raise(Stringex::Localization::Backend::I18nNotDefined) do
+      Stringex::Localization.backend = :i18n
+    end
+  ensure
+    unalias_i18n
+  end
+
+  def test_loading_i18n_backend_fails_if_i18n_defined_without_translate
+    Object.send :const_set, :I18n, Module.new
+
+    assert_raise(Stringex::Localization::Backend::I18nMissingTranslate) do
+      Stringex::Localization.backend = :i18n
+    end
+  ensure
+    Object.send :remove_const, :I18n
+    unalias_i18n
+  end
+
+private
+
+  def alias_i18n
+    Object.send :const_set, :I18nBackup, I18n
+    Object.send :remove_const, :I18n
+  end
+
+  def unalias_i18n
+    Object.send :const_set, :I18n, I18nBackup
+    Object.send :remove_const, :I18nBackup
+  end
+end
diff --git a/test/localization_test.rb b/test/unit/localization_test.rb
similarity index 88%
rename from test/localization_test.rb
rename to test/unit/localization_test.rb
index b936f81..92b8a14 100644
--- a/test/localization_test.rb
+++ b/test/unit/localization_test.rb
@@ -4,6 +4,7 @@ require 'i18n'
 
 class LocalizationTest < Test::Unit::TestCase
   def setup
+    I18n.locale = :en
     Stringex::Localization.reset!
   end
 
@@ -120,4 +121,22 @@ class LocalizationTest < Test::Unit::TestCase
       assert_equal "Testblank", "Test blank".convert_miscellaneous_html_entities
     end
   end
+
+  def test_assigns_locale_in_i18n_backend
+    I18n.locale = :en
+    Stringex::Localization.backend = :i18n
+
+    assert_equal :en, Stringex::Localization.locale
+
+    I18n.locale = :jp
+    assert_equal :jp, Stringex::Localization.locale
+
+    Stringex::Localization.locale = :de
+    assert_equal :de, Stringex::Localization.locale
+    assert_equal :jp, I18n.locale
+
+    Stringex::Localization.locale = nil
+    assert_equal :jp, Stringex::Localization.locale
+    assert_equal :jp, I18n.locale
+  end
 end
diff --git a/test/unit/string_extensions_configuration_test.rb b/test/unit/string_extensions_configuration_test.rb
new file mode 100644
index 0000000..563ae29
--- /dev/null
+++ b/test/unit/string_extensions_configuration_test.rb
@@ -0,0 +1,17 @@
+# encoding: UTF-8
+
+require 'test_helper'
+require 'stringex'
+
+class StringExtensionsConfigurationTest < Test::Unit::TestCase
+  def teardown
+    Stringex::StringExtensions.unconfigure!
+  end
+
+  def test_can_set_base_settings
+    Stringex::StringExtensions.configure do |c|
+      c.replace_whitespace_with = "~"
+    end
+    assert_equal "foo~bar", "foo bar".to_url
+  end
+end
diff --git a/test/string_extensions_test.rb b/test/unit/string_extensions_test.rb
similarity index 72%
rename from test/string_extensions_test.rb
rename to test/unit/string_extensions_test.rb
index 32e3729..2a1b7d1 100644
--- a/test/string_extensions_test.rb
+++ b/test/unit/string_extensions_test.rb
@@ -7,6 +7,16 @@ if RUBY_VERSION.to_f < 1.9
   $KCODE = "U"
 end
 
+# Try loading RedCloth but it's okay if it's not there
+begin
+  gem 'RedCloth'
+rescue LoadError
+  puts
+  puts ">> Could not load RedCloth. String#to_html was not tested."
+  puts ">> Please gem install RedCloth if you'd like to use this functionality."
+  puts
+end
+
 class StringExtensionsTest < Test::Unit::TestCase
   def setup
     Stringex::Localization.reset!
@@ -71,12 +81,27 @@ class StringExtensionsTest < Test::Unit::TestCase
       "У лукоморья дуб зеленый" =>
         "u-lukomoria-dub-zielienyi",
       "Here are some {braces}" =>
-        "here-are-some-braces"
+        "here-are-some-braces",
+      "$1,000" =>
+        "1000-dollars",
+      "«zut alors»" =>
+        "zut-alors",
+      "Rabbits aren't real" =>
+        "rabbits-arent-real",
+      "R$ isn't R" =>
+        "reais-isnt-r",
+      "Last Friday Night (T.G.I.F.)" =>
+        "last-friday-night-tgif"
     }.each do |html, plain|
       assert_equal plain, html.to_url
     end
   end
 
+  def test_to_url_with_danish_characters
+    Stringex::Localization.locale = :da
+    assert_equal "roedgroed-med-floede", "Rødgrød med fløde".to_url
+  end
+
   def test_to_url_with_excludes
     assert_equal "So Fucking Special", "So Fucking Special".to_url(:exclude => "So Fucking Special")
   end
@@ -134,11 +159,11 @@ class StringExtensionsTest < Test::Unit::TestCase
 
   def test_localized_vulgar_fractions_conversion
     Stringex::Localization.backend = :internal
-    Stringex::Localization.store_translations :de, :vulgar_fractions, {
+    Stringex::Localization.store_translations :da, :vulgar_fractions, {
       :one_fourth => "en fjerdedel",
       :half => "en halv"
     }
-    Stringex::Localization.locale = :de
+    Stringex::Localization.locale = :da
 
     {
       "&frac14;" => "en fjerdedel",
@@ -214,4 +239,67 @@ class StringExtensionsTest < Test::Unit::TestCase
 
     assert_equal "now-with-hyphens", "----now---------with-hyphens--------".collapse("-")
   end
+
+  def test_empty_translations
+    Stringex::Localization.backend = :internal
+    Stringex::Localization.store_translations :de, :characters, {
+      :star => "",
+      :percent => "prozent"
+    }
+    Stringex::Localization.locale = :de
+
+    assert_equal "foobar ist 100 prozent gut", "foo*bar ist 100% gut".convert_miscellaneous_characters
+  end
+
+  def test_overriding_to_ascii_allows_utf8_urls
+    String.class_eval do
+      alias :old_to_ascii :to_ascii
+
+      def to_ascii
+        self
+      end
+    end
+
+    {
+      "مصدر أمني: مجهولون يطلقون «خرطوش» على متظاهرين بمترو عزبة النخل وإصابة 16" =>
+        "مصدر-أمني-مجهولون-يطلقون-«خرطوش»-على-متظاهرين-بمترو-عزبة-النخل-وإصابة-16",
+      "c'est ça" =>
+        "cest-ça",
+      "la muñeca" =>
+        "la-muñeca"
+    }.each do |original, converted|
+      assert_equal converted, original.to_url
+    end
+  ensure
+    String.class_eval do
+      remove_method :to_ascii
+
+      def to_ascii
+        old_to_ascii
+      end
+    end
+  end
+
+  if defined?(RedCloth)
+    def test_to_html
+      {
+        "h1. A Solution" => "<h1>A Solution</h1>",
+        "I hated wrapping textilize around a string.\n\nIt always felt dirty." =>
+          "<p>I hated wrapping textilize around a string.</p>\n<p>It always felt dirty.</p>",
+        "I think _this_ is awesome" => "<p>I think <em>this</em> is awesome</p>",
+        "Um... _*really*_, man" => "<p>Um… <em><strong>really</strong></em>, man</p>"
+      }.each do |plain, html|
+        assert_equal html, plain.to_html
+      end
+    end
+
+    def test_to_html_lite
+      {
+        "I have no pee on me" => "I have no pee on me",
+        "But I _do_ get Textile!" => "But I <em>do</em> get Textile!"
+      }.each do |plain, html|
+        assert_equal html, plain.to_html(:lite)
+      end
+    end
+  end
 end
diff --git a/test/unicode_point_suite/basic_greek_test.rb b/test/unit/unicode_point_suite/basic_greek_test.rb
similarity index 100%
rename from test/unicode_point_suite/basic_greek_test.rb
rename to test/unit/unicode_point_suite/basic_greek_test.rb
diff --git a/test/unicode_point_suite/basic_latin_test.rb b/test/unit/unicode_point_suite/basic_latin_test.rb
similarity index 100%
rename from test/unicode_point_suite/basic_latin_test.rb
rename to test/unit/unicode_point_suite/basic_latin_test.rb
diff --git a/test/unicode_point_suite/codepoint_test_helper.rb b/test/unit/unicode_point_suite/codepoint_test_helper.rb
similarity index 100%
rename from test/unicode_point_suite/codepoint_test_helper.rb
rename to test/unit/unicode_point_suite/codepoint_test_helper.rb
diff --git a/test/unidecoder/bad_localization.yml b/test/unit/unidecoder/bad_localization.yml
similarity index 100%
rename from test/unidecoder/bad_localization.yml
rename to test/unit/unidecoder/bad_localization.yml
diff --git a/test/unidecoder/localization.yml b/test/unit/unidecoder/localization.yml
similarity index 100%
rename from test/unidecoder/localization.yml
rename to test/unit/unidecoder/localization.yml
diff --git a/test/unidecoder_test.rb b/test/unit/unidecoder_test.rb
similarity index 100%
rename from test/unidecoder_test.rb
rename to test/unit/unidecoder_test.rb
diff --git a/test/version_test.rb b/test/unit/version_test.rb
similarity index 98%
rename from test/version_test.rb
rename to test/unit/version_test.rb
index 1e2a819..d058bbb 100644
--- a/test/version_test.rb
+++ b/test/unit/version_test.rb
@@ -9,4 +9,4 @@ class VersionTest < Test::Unit::TestCase
       Stringex::Version
     end
   end
-end
\ No newline at end of file
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-stringex.git



More information about the Pkg-ruby-extras-commits mailing list