diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # ordinal
 
-[![Build Status of the package by Travis](https://travis-ci.com/hapytex/ordinal.svg?branch=master)](https://travis-ci.com/hapytex/ordinal)
+[![Build Status of the package by GitHub actions](https://github.com/hapytex/ordinal/actions/workflows/build-ci.yml/badge.svg)](https://github.com/hapytex/ordinal/actions/workflows/build-ci.yml)
 [![Build Status of the package by Hackage](https://matrix.hackage.haskell.org/api/v2/packages/ordinal/badge)](https://matrix.hackage.haskell.org/#/package/ordinal)
 [![Hackage version badge](https://img.shields.io/hackage/v/ordinal.svg)](https://hackage.haskell.org/package/ordinal)
 
@@ -88,7 +88,9 @@
 include a new language. This includes a list of tasks to do in order to add the
 language. The `test/` directory contains a `test/Text/Numerals/Languages/LanguageSpec.hs.template`
 file to test the new language. In these templates, one needs to fill in the
-`???` parts.
+`???` parts. One can make use of the `new-language.sh` script to automatically
+copy the templates and open the editor to add the language. In that case the name
+of the language is passed as first parameter.
 
 Normally the languages are tested for all numbers in the 0-200 range, and the
 first hundred Fibonacci numbers greater than 200, so:
diff --git a/ordinal.cabal b/ordinal.cabal
--- a/ordinal.cabal
+++ b/ordinal.cabal
@@ -1,5 +1,5 @@
 name:                ordinal
-version:             0.4.0.0
+version:             0.4.0.2
 synopsis:            Convert numbers to words in different languages.
 description:
     A package based on Python's num2words package that converts numbers
@@ -40,6 +40,7 @@
       base >= 4.7 && < 5
     , containers >=0.5
     , data-default >=0.2
+    , QuickCheck >=2.8
     , regex >=1.0
     , text >= 0.1
     , time >=1.0
@@ -61,7 +62,7 @@
       base
     , ordinal
     , hspec ==2.*
-    , QuickCheck >=2.13 && <2.14
+    , QuickCheck >=2.8
     , text >= 0.1
   build-tool-depends: hspec-discover:hspec-discover == 2.*
   default-language:    Haskell2010
diff --git a/src/Text/Numerals/Algorithm.hs b/src/Text/Numerals/Algorithm.hs
--- a/src/Text/Numerals/Algorithm.hs
+++ b/src/Text/Numerals/Algorithm.hs
@@ -34,6 +34,9 @@
 import Data.Vector(Vector, (!), (!?), fromList)
 import qualified Data.Vector as V
 
+import Test.QuickCheck(oneof)
+import Test.QuickCheck.Arbitrary(Arbitrary(arbitrary, shrink))
+
 import Text.Numerals.Class(
     NumToWord(toCardinal, toOrdinal, toShortOrdinal, toTimeText')
   , FreeMergerFunction, FreeNumberToWords, FreeValueSplitter
@@ -43,7 +46,7 @@
   , ClockText
   , toClockSegment, toDaySegment
   )
-import Text.Numerals.Internal(_thousand, _iLogFloor)
+import Text.Numerals.Internal(_genText, _shrinkText, _thousand, _iLogFloor)
 import Text.Numerals.Prefix(latinPrefixes)
 
 -- | A data type for algorithmic number to word conversions. Most western
@@ -86,6 +89,11 @@
   = ShortScale Text
   | LongScale Text Text
   deriving (Eq, Ord, Read, Show)
+
+instance Arbitrary HighNumberAlgorithm where
+  arbitrary = oneof [ShortScale <$> _genText, LongScale <$> _genText <*> _genText]
+  shrink (ShortScale t) = ShortScale <$> _shrinkText t
+  shrink (LongScale ta tb) = ((`LongScale` tb) <$> _shrinkText ta) <> (LongScale ta <$> _shrinkText tb)
 
 instance Default HighNumberAlgorithm where
     def = ShortScale "illion"
diff --git a/src/Text/Numerals/Class.hs b/src/Text/Numerals/Class.hs
--- a/src/Text/Numerals/Class.hs
+++ b/src/Text/Numerals/Class.hs
@@ -39,6 +39,11 @@
 import Data.Time.Clock(getCurrentTime, utctDayTime)
 import Data.Time.LocalTime(TimeOfDay(TimeOfDay), TimeZone, timeToTimeOfDay, utcToLocalTimeOfDay)
 
+import Test.QuickCheck(choose)
+import Test.QuickCheck.Arbitrary(Arbitrary(arbitrary, shrink), Arbitrary1(liftArbitrary), arbitrary1, arbitraryBoundedEnum)
+
+import Text.Numerals.Internal(_genText, _shrinkText)
+
 -- | A type alias for a function that maps a number to a 'Text' object.
 type NumberToWords i = i -> Text
 
@@ -76,6 +81,19 @@
   , segmentRemainder ::  MNumberSegment i  -- ^ The optional remainder part. 'Nothing' if the remainder is equal to zero.
   } deriving (Foldable, Functor, Eq, Ord, Read, Show)
 
+instance Arbitrary1 NumberSegment where
+  liftArbitrary gen = go
+      where go = NumberSegment <$> liftArbitrary go <*> gen <*> _genText <*> liftArbitrary go
+
+instance Arbitrary i => Arbitrary (NumberSegment i) where
+  arbitrary = arbitrary1
+  shrink (NumberSegment dv val txt rm) =
+    ((\x -> NumberSegment x val txt rm) <$> shrink dv) <>
+    ((\x -> NumberSegment dv x txt rm) <$> shrink val) <>
+    ((\x -> NumberSegment dv val x rm) <$> _shrinkText txt) <>
+    (NumberSegment dv val txt <$> shrink rm)
+
+
 -- | A 'Maybe' variant of the 'NumberSegment' data type. This is used since the
 -- division part can be one, or the remainder part can be zero.
 type MNumberSegment i = Maybe (NumberSegment i)
@@ -88,6 +106,9 @@
   | ShortOrdinal -- ^ /Short ordinal/ numbers like 1st, 2nd, 3rd, etc.
   deriving (Bounded, Enum, Eq, Ord, Read, Show)
 
+instance Arbitrary NumberType where
+  arbitrary = arbitraryBoundedEnum
+
 -- | The type of a function that converts time to its description. The first
 -- two parameters are used to make conversion more convenient.
 type ClockText
@@ -109,6 +130,9 @@
   | To Int  -- ^ The parameter is the number of minutes to the next hour, this is between @1@ and @14@.
   deriving (Eq, Ord, Read, Show)
 
+instance Arbitrary ClockSegment where
+  arbitrary = toClockSegment <$> choose (0, 59)
+
 -- | A data type that describes the state of the hours within a day.
 data DayPart
   = Night  -- ^ It is night, this means that it is between @0:00@ and @5:59@.
@@ -117,6 +141,9 @@
   | Evening  -- ^ It is evening, this means it is between @18:00@ and @23:59@.
   deriving (Bounded, Enum, Eq, Ord, Read, Show)
 
+instance Arbitrary DayPart where
+  arbitrary = arbitraryBoundedEnum
+
 -- | A data type that describes the part of the day, and the number of hours on
 -- a 12-hour clock.
 data DaySegment
@@ -126,6 +153,8 @@
       }
   deriving (Eq, Ord, Read, Show)
 
+instance Arbitrary DaySegment where
+  arbitrary = toDaySegment <$> choose (0, 23)
 
 -- | Convert the given number of minutes to the corresponding 'ClockSegment'.
 toClockSegment
@@ -205,14 +234,14 @@
     toWords Cardinal = toCardinal
     toWords Ordinal = toOrdinal
     toWords ShortOrdinal = toShortOrdinal
-    
+
     -- | Convert the given time of the day to text describing that time.
     toTimeText
       :: a  -- ^ The conversion algorithm to transform numbers into words.
       -> TimeOfDay  -- ^ The time of the day to convert to words.
       -> Text  -- ^ The time as /text/.
     toTimeText gen (TimeOfDay h m _) = toTimeText' gen h m
-    
+
     -- | Convert the given hours and minutes to text that describes the time.
     toTimeText'
       :: a  -- ^ The conversion algorithm to transform numbers into words.
diff --git a/src/Text/Numerals/Internal.hs b/src/Text/Numerals/Internal.hs
--- a/src/Text/Numerals/Internal.hs
+++ b/src/Text/Numerals/Internal.hs
@@ -10,12 +10,19 @@
   , _stripLastIf
   , _showIntegral
   , _showPositive
+  , _genText, _shrinkText
   ) where
 
+import Control.Applicative(liftA2)
+
 import Data.Char(intToDigit)
-import Data.Text(Text, cons, dropEnd, isSuffixOf, singleton, pack)
+import Data.Text(Text, cons, dropEnd, inits, isSuffixOf, singleton, tails, pack)
 import qualified Data.Text as T
 
+import Test.QuickCheck(listOf)
+import Test.QuickCheck.Arbitrary(Arbitrary(arbitrary))
+import Test.QuickCheck.Gen(Gen)
+
 _pluralize :: a -> a -> Int -> a
 _pluralize sing plur = go
     where go 1 = sing
@@ -108,3 +115,9 @@
     | otherwise = _showPositive q tl
     where (q, r) = quotRem n 10
           tl = intToDigit (fromIntegral r) : s
+
+_genText :: Gen Text
+_genText = pack <$> listOf arbitrary
+
+_shrinkText :: Text -> [Text]
+_shrinkText = liftA2 (zipWith (<>)) inits (tails . T.drop 1)
