pax_global_header00006660000000000000000000000064120427077560014524gustar00rootroot0000000000000052 comment=3d4cbb531125f67873197f4cfbf5917638783247 ruby-i18n-inflector-2.6.6/000077500000000000000000000000001204270775600152605ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/.gemtest000066400000000000000000000000001204270775600167170ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/.yardopts000066400000000000000000000002701204270775600171250ustar00rootroot00000000000000--title 'Simple Inflector for I18n' --protected --readme README.rdoc --no-private --hide-void-return - docs/USAGE docs/EXAMPLES docs/HISTORY ChangeLog docs/COPYING docs/LGPL docs/TODO ruby-i18n-inflector-2.6.6/ChangeLog000066400000000000000000001371701204270775600170430ustar00rootroot00000000000000commit c0bcc1dd60256076d9ac79d6f57d11d6a578f3ee Author: Paweł Wilk Date: Wed Mar 14 02:10:49 2012 +0100 Release 2.6.6 commit 3d2292b4dec50c628fc2feaeba2639e21c44c5c7 Author: Paweł Wilk Date: Wed Mar 14 02:06:50 2012 +0100 Added LazyEnumerator#empty? commit f912309d9f9d0d2e41c901778f885259f907e8ef Author: Paweł Wilk Date: Wed Mar 14 02:06:29 2012 +0100 Documentation and examples updated commit 7d5f57ec1ff967051e693b332c0e72f9bbbbea2a Author: Paweł Wilk Date: Wed Mar 14 02:06:04 2012 +0100 Added support for integers as token names commit d08273f935a3fecc51e4ce27a3ebe01342a338f3 Author: Paweł Wilk Date: Sat Mar 10 21:03:04 2012 +0100 ChangeLog updated commit 2cef335b627a8df8cf595aa8b3507faebc5476a5 Author: Paweł Wilk Date: Sat Mar 10 20:59:17 2012 +0100 Release 2.6.5 commit c59600298fa3f2b5ae860cce89c214da992bb067 Author: Paweł Wilk Date: Sat Mar 10 20:58:55 2012 +0100 Switched YAML parser back to Psych in gem generation commit 295a1c59d0d763e758cab6fe2ea05e477125e39a Author: Paweł Wilk Date: Sat Mar 10 20:24:43 2012 +0100 Release 2.6.4 commit eae90eb5992e189ffc8678c4f810befd8a541cf2 Author: Paweł Wilk Date: Sat Mar 10 20:19:12 2012 +0100 README updated, I18n Inflector tested against Ruby 1.9.3-p0. commit cf59982df41b4a541345e5846d909df727f2ea0b Author: Paweł Wilk Date: Sat Mar 10 20:17:53 2012 +0100 Copyright notices updated. commit 901c65c683fdf0d7a814756aa071a6ff25119263 Author: Paweł Wilk Date: Sat Mar 10 20:16:47 2012 +0100 Dependencies updated. commit dd71d4a5d82417a09393d6aa936f5e59e4c495e5 Author: Paweł Wilk Date: Tue Aug 9 17:13:15 2011 +0200 Release 2.6.3 commit f328167d491eb77b346e0d62d56e52397981c729 Author: Paweł Wilk Date: Tue Aug 9 17:12:41 2011 +0200 Release 2.6.3 commit 93cc55bdae5c466b22999e11c0cc020e8bc04a23 Author: Paweł Wilk Date: Mon Aug 8 00:13:10 2011 +0200 Release 2.6.2 commit fd7508c5bd759e071feae8180b98ed9bf6c2931f Author: Paweł Wilk Date: Sun Jul 10 03:16:21 2011 +0200 Release 2.6.1 commit 613cf034568c536b2dc0edc2d0cf0e80f95afe6a Author: Paweł Wilk Date: Sat Jul 9 18:58:06 2011 +0200 Added @inflected_locales_cache that speeds up reporting of locales that support inflection commit 950e6b8589f2d8893d30e1b892c8ed0fa1e26a78 Author: Paweł Wilk Date: Sat Jul 9 02:42:14 2011 +0200 Gem dependencies updated. commit cd549b15580aff33d212e92870b16942b6cf8f55 Author: Paweł Wilk Date: Fri Jul 8 16:30:01 2011 +0200 Handling methods and Proc objects to obtain inflection options seriously improved - added cache for inflection options that keeps them between calls to interpolate_core. commit 5858b52225759e9760ec2301671cf78e64d02f33 Author: Paweł Wilk Date: Sat Apr 30 18:47:04 2011 +0200 Lazy operations optimized a bit commit ee37910a2419afb9710ff0f1472634b29be7f0d8 Author: Paweł Wilk Date: Sat Apr 30 18:46:23 2011 +0200 Fixed documentation links commit e6b753ac280b14a7c32de2bab3dd9540d72cde72 Author: Paweł Wilk Date: Mon Mar 7 00:45:23 2011 +0100 Release 2.6.0 commit a949e5aad5a2bed695fc3e00f129dd56dda73daa Author: Paweł Wilk Date: Sun Mar 6 23:41:32 2011 +0100 Engine initialization improved commit af4ea17f1961dd54bd600d789c33187af9cc9d69 Author: Paweł Wilk Date: Sun Mar 6 23:36:15 2011 +0100 Added union operators to some arrays commit e21b810282bd98e3e49030267382d2a4358ab285 Author: Paweł Wilk Date: Sun Mar 6 23:35:14 2011 +0100 Added lazy iteration interfaces to API and core classes commit 8f480682b1f5c418c31cbbdfb3b5f1b3d3549713 Author: Paweł Wilk Date: Sat Mar 5 14:32:52 2011 +0100 Added a note about YAML parsing issues. commit 9fb6687d1e7ae003fb653d2af426e522f6d9f399 Author: Paweł Wilk Date: Sat Mar 5 14:32:25 2011 +0100 Fixed static gemspec commit 6ccbc782f089c603afeff48a7b7492011b486dfe Author: Paweł Wilk Date: Sat Mar 5 14:31:42 2011 +0100 Optimized contatenations if Strings commit b62605859be67525a5c2f902a387fa92f0adebb8 Author: Paweł Wilk Date: Fri Feb 25 19:33:24 2011 +0100 Release 2.5.1 commit faba82529657e42fb8b034766a450fc91ebe28bc Author: Paweł Wilk Date: Fri Feb 25 19:32:36 2011 +0100 Inflector is able to parse symbols as descriptions (and aliases) commit 2fddd234ffe5847ad21d46c36495c02431684ad4 Author: Paweł Wilk Date: Wed Feb 23 23:12:04 2011 +0100 Release 2.5.0 commit 0b49cd677a695db4b8f50151529555155fadce59 Author: Paweł Wilk Date: Wed Feb 23 23:08:06 2011 +0100 Added tests covering fixed bug that caused Arrays to be interpolated in a wrong way commit 80fa0b092de9bc08ee16e64ae6d93b799e6ee521 Author: Paweł Wilk Date: Wed Feb 23 23:07:34 2011 +0100 Interpolation wrapper refactored; it now operates on Arrays, Hashes, Symbols and other objects commit ab5f5bc04814c1181bd9919ce159292362abc3bb Author: Paweł Wilk Date: Wed Feb 23 23:06:18 2011 +0100 Added string version of regexps to constants for debugging purposes commit 8a27302b1535c68496cc60b55bcdfc958f837300 Author: Paweł Wilk Date: Wed Feb 23 23:05:34 2011 +0100 Dependencies updated commit 6d343ad3137735492e130b7abdd8f86bf23a4a06 Author: Paweł Wilk Date: Wed Feb 23 02:20:18 2011 +0100 Release 2.4.0 commit d8a8354dfa428d649c89157bbcf4f2a4aa2fa74f Author: Paweł Wilk Date: Wed Feb 23 02:19:29 2011 +0100 Added collections support commit ed4cea2f3b809028b02fa19c089fecc7cf56713b Author: Paweł Wilk Date: Tue Feb 15 02:39:26 2011 +0100 Release 2.3.1 commit c274ae5e650ffc0abe8095c70104ae74e88c58ff Author: Paweł Wilk Date: Tue Feb 15 02:36:58 2011 +0100 Fixed documentation links commit 40e61b0adb92c7e401316f097c2774e48f2629cf Author: Paweł Wilk Date: Tue Feb 15 01:53:37 2011 +0100 README updated for Github's rdoc parser commit 76c7a61ca6b96e94a4362f31a36d6c79e476be97 Author: Paweł Wilk Date: Tue Feb 15 01:20:52 2011 +0100 Release 2.3.0 commit fe4469dc11a908dc6e0174955a8e37db092da674 Author: Paweł Wilk Date: Tue Feb 15 01:18:29 2011 +0100 Added missing token name validation checks to the interpolate method commit 41a008ed23a89de0cefcd6cb920d3c496eb57ccb Author: Paweł Wilk Date: Mon Feb 14 23:01:56 2011 +0100 Changed arguments passing when Proc objects are passed as inflection options commit d6da97e49497b8c9d8349d0bafa2d0e801382d56 Author: Paweł Wilk Date: Mon Feb 14 23:01:04 2011 +0100 Documentation updated commit b025fdbf5f210828b0ddec75f75d694442bda640 Author: Paweł Wilk Date: Mon Feb 14 17:48:42 2011 +0100 Changed wildcard token interpolation according to the principle of least surprise commit ef7c7c6c786f2deb72e8d449cd0a3d36ccc6b7ce Author: Paweł Wilk Date: Mon Feb 14 17:47:17 2011 +0100 Arguments to external inflection Methods and Procs are now passed through blocks commit 2cfcc43a7fd7f343aeb563354bbe46e9db919279 Author: Paweł Wilk Date: Mon Feb 14 17:44:26 2011 +0100 Documentation updated commit d3b667d9691fc86f4fe02c0e8b19281e22197709 Author: Paweł Wilk Date: Sun Feb 13 22:22:19 2011 +0100 Proc and Method object support improved commit e437ef670a286169f2ebbba31d1ea988c721aabc Author: Paweł Wilk Date: Sun Feb 13 22:21:40 2011 +0100 Added wildcard token examples to EXAMPLES commit 13d8e02ab2369e6b345d28158f5209165c722179 Author: Paweł Wilk Date: Sun Feb 13 22:21:17 2011 +0100 TODO updated commit b755aca6146c010df71e9b79c7faaf3156df559f Author: Paweł Wilk Date: Sun Feb 13 22:20:57 2011 +0100 Wildcard token support enabled commit b52b16e4a61ce20b3e2d4599fee5a4b082a3bf24 Author: Paweł Wilk Date: Sun Feb 13 22:20:35 2011 +0100 Removed usage documentation from long_comments.rb commit 2f222adb9c4368199bb4849190e17afbae1fb482 Author: Paweł Wilk Date: Sun Feb 13 22:19:43 2011 +0100 Added wildcard token support commit a54bae6164a98d0bee29632c678b17b76720c272 Author: Paweł Wilk Date: Sun Feb 13 22:16:55 2011 +0100 Documentation: link to USAGE fixed commit e681df415d2d864678b22107236d430ebf6de27d Author: Paweł Wilk Date: Sun Feb 13 22:16:08 2011 +0100 Documentation updated commit e459b7471892d1f8dc410a5f89cf706a9b3a3b5e Author: Paweł Wilk Date: Sun Feb 13 22:15:31 2011 +0100 docs/RELATIONS removed from static gemspec commit d8c69ce2e097f1364d22a167dfd6849186738e5b Author: Paweł Wilk Date: Sun Feb 13 22:15:04 2011 +0100 Gemfile updated commit e679fbdf6c901d335fd27cbd664fa8b9b19b251e Author: Paweł Wilk Date: Sun Feb 13 22:00:17 2011 +0100 Documentation about object relations moved to USAGE commit dd4c51acb617595d8d3a7ff2cfa4b631e73f87df Author: Paweł Wilk Date: Sun Feb 13 21:55:23 2011 +0100 Manifest.txt regenerated commit 2edaf6479b48ab628c9a52cfc9b443949844e119 Author: Paweł Wilk Date: Sun Feb 13 21:55:00 2011 +0100 Inflector usage documentation moved to USAGE commit 0e7ef2933baf1abbef13d9516c5f39f8f749bc1e Author: Paweł Wilk Date: Fri Feb 11 13:41:11 2011 +0100 Exceptions of Methods and Procs are now ignored unless :inflector_raises is set commit 5556f3ecdc4685f06599ec9b401704194988a3c5 Author: Paweł Wilk Date: Fri Feb 11 12:19:48 2011 +0100 Variable number of arguments supported in passed method calls commit 9ffde532e9a1f2a0bc7ccb04dfbe884031725469 Author: Paweł Wilk Date: Fri Feb 11 04:13:42 2011 +0100 HISTORY & TODO updated commit ff4f62bb19962559f08c76bdc1a6a3a1135dc1b4 Author: Paweł Wilk Date: Fri Feb 11 04:13:03 2011 +0100 Added the ability to pass Proc and Method objects as inflection options, fixed excluded_defaults commit 9f65a7f971c8942ba99795426039b5ec3f0917e8 Author: Paweł Wilk Date: Fri Feb 11 04:11:32 2011 +0100 Added I18n::Inflector::Config::Markers::STRICT_KIND commit 79809f3644791dc105f2a94c1cb3464f33fa6d53 Author: Paweł Wilk Date: Wed Feb 9 21:16:08 2011 +0100 Typo fixed in README commit a60370126b5981255aff1b6de47c98ea3e740c04 Author: Paweł Wilk Date: Wed Feb 9 18:49:52 2011 +0100 Release 2.2.0 commit 38416442533f9c4b44f51ee13f676460ad23fbbc Author: Paweł Wilk Date: Wed Feb 9 18:47:22 2011 +0100 Tested with Ruby 1.8, Ruby 1.9, i18n-inflector-rails, full-stacked Rails app, I18n v0.4.1 & v0.5.0 commit 732260142ca0ce727b9690c0374c7e5043e95130 Author: Paweł Wilk Date: Wed Feb 9 18:17:32 2011 +0100 README updated commit ffe39ffe0a4cc26b76c720507c5a46eb7d10b57e Author: Paweł Wilk Date: Wed Feb 9 18:17:10 2011 +0100 Documentation updated commit c81ed66f010b350f6db6d21d6194ceb0ba0d8167 Author: Paweł Wilk Date: Wed Feb 9 18:16:22 2011 +0100 EXAMPLES updated commit 4c09e2c3c5f549eca7a2024cea0e2bb5f3bc5078 Author: Paweł Wilk Date: Wed Feb 9 03:45:10 2011 +0100 Documentation fixes, error messages fixes commit 3917807f00ff9ec0d641557c29eee15878914b67 Author: Paweł Wilk Date: Wed Feb 9 01:21:15 2011 +0100 Documentation updated commit 924f84f57d19ff8d1f8a9c18764f40a2f9ccea49 Author: Paweł Wilk Date: Tue Feb 8 23:57:57 2011 +0100 README updated commit cec22a1422f6b8e4213d8ce435ed0c3fa5390cad Author: Paweł Wilk Date: Tue Feb 8 23:57:36 2011 +0100 Fixed pattern escaping when locale is not inflected commit 9649c6b292c169a8d4f7aaa9daa929c61388b9d5 Author: Paweł Wilk Date: Tue Feb 8 18:00:58 2011 +0100 Removed magic symbols from code and fixed regular expression generators to be Ruby 1.8 compliant commit a41dd59db76910c5a1eb0baa2bc8c818224187bc Author: Paweł Wilk Date: Tue Feb 8 17:59:45 2011 +0100 Added key-based inflection and multiple patterns support and some tests commit 3c7f5ae5acf8f0061944fab46dc020b46fa7dd32 Author: Paweł Wilk Date: Mon Feb 7 17:16:22 2011 +0100 Documentation updated commit aa278841eb957a6ccc858ec6cb86832f59677587 Author: Paweł Wilk Date: Mon Feb 7 00:46:41 2011 +0100 Documentation fix. commit 90b55fd784818b0456aec01416195b5267fba3ff Author: Paweł Wilk Date: Mon Feb 7 00:46:20 2011 +0100 Added some old constants in case someone uses them. commit b083527e545701a1c5fbe39d010618e148db6904 Author: Paweł Wilk Date: Mon Feb 7 00:24:11 2011 +0100 Added config.rb to Manifest.txt commit 2f917d62b456abe8b54f2e82a2441b35d6b25821 Author: Paweł Wilk Date: Mon Feb 7 00:22:41 2011 +0100 Updated TODO and HISTORY commit 10e98a1c7fc7d426f437ed0b25ff0c969ff1b2f9 Author: Paweł Wilk Date: Mon Feb 7 00:22:06 2011 +0100 Tests fixed according to strict specification keeping while paring inflection options commit be4f1f6cb53949166894529ec2a8433098909f43 Author: Paweł Wilk Date: Mon Feb 7 00:21:00 2011 +0100 Documentation updated to reflect the changes commit 1ea80871cbb114939d8e645b33a91272e72fab78 Author: Paweł Wilk Date: Mon Feb 7 00:20:24 2011 +0100 Interpolation method refactored; cleaned options parsing code commit 7e4bf4e2bbb21958971c354615c2077e44e66dd9 Author: Paweł Wilk Date: Mon Feb 7 00:17:46 2011 +0100 Removed 'sudo' from installation instruction commit 47e3b4ee161985f0457b19e9d475f17aa87c8c1e Author: Paweł Wilk Date: Sat Feb 5 17:46:56 2011 +0100 Tests updated commit f32e334d04c66a9e7e24e5d9bce3c637ab312c62 Author: Paweł Wilk Date: Sat Feb 5 17:46:39 2011 +0100 Added validations to interpolation and tokens loading routines commit 83020be4362c615b8191632fc8c7a4f9d03690f5 Author: Paweł Wilk Date: Sat Feb 5 17:44:29 2011 +0100 Known options generation and keeping moved to attr_accessor and class-level instance variable commit bb09d160ec99b41d26bb6ddcd97f667fc28c21f2 Author: Paweł Wilk Date: Sat Feb 5 17:43:03 2011 +0100 Added new error classes: I18n::InvalidInflectionOption and I18n::InvalidInflectionKind commit dd702ebff0a0204affd5623bce3df86a1a0f171b Author: Paweł Wilk Date: Sat Feb 5 17:41:58 2011 +0100 I18n::Inflector::Config updated commit 7855e234e01be5a4e44a539a01c5730919b5f87d Author: Paweł Wilk Date: Sat Feb 5 17:40:48 2011 +0100 Added config proxy to API commit e4500dbfa83371052f4f1fdeaebbb7574bb343b9 Author: Paweł Wilk Date: Sat Feb 5 17:40:10 2011 +0100 Backend module loading moved after config module loading commit c63d0b50f5492387eafdf6b83fb169f9c9c9feea Author: Paweł Wilk Date: Thu Feb 3 19:56:55 2011 +0100 I18n::Inflector::Config optimized commit 39826057121142674a8e366d487f4f1509f03cfb Author: Paweł Wilk Date: Thu Feb 3 19:56:25 2011 +0100 Documentation updated commit c2954fb3480b43953ba044ff3826b0ca909ba187 Author: Paweł Wilk Date: Thu Feb 3 03:06:30 2011 +0100 Refactored configuration constants handling and started working on validation routines commit aefb526f9251c48e0270615d8ae8e8eb31a7b946 Author: Paweł Wilk Date: Wed Feb 2 03:48:50 2011 +0100 Kind validation and I18n::BadInflectionKind implemented in Backend#prepare_inflection_tokens commit 72699c8d3b075515c7bb005ae284798044880a21 Author: Paweł Wilk Date: Wed Feb 2 03:47:39 2011 +0100 Interpolation routine for complex kinds simplified commit dbaf3062790c3290fbd738ba2c2176decf7f4c4f Author: Paweł Wilk Date: Wed Feb 2 03:47:15 2011 +0100 I18n::BadInflectionKind documented commit 5d287872bea57aaf8ef42f82b3a00bebefebab42 Author: Paweł Wilk Date: Wed Feb 2 03:46:53 2011 +0100 Added I18n::BadInflectionKind exception class commit 5e887376c1de71b5100d12bac9aac3d3f56836ae Author: Paweł Wilk Date: Wed Feb 2 00:52:19 2011 +0100 Added some tests for complex patterns commit d7b371087665ba02b248aa259169877aea33b9df Author: Paweł Wilk Date: Wed Feb 2 00:52:00 2011 +0100 Documentation updated commit 584986b39d77fa212cafcce6c7473205f4ede6c1 Author: Paweł Wilk Date: Wed Feb 2 00:51:39 2011 +0100 Complex pattern interpolation simplified a lot. commit bdbeea5e539f6e690d03f4de253fbaa72f23fa32 Author: Paweł Wilk Date: Mon Jan 31 04:55:31 2011 +0100 Workarounds in complex pattern processing method for Ruby 1.8 (symbols, erronous enumerators) commit ff0379e4eea9cafe1d4da9cb8b5df1284b710bf0 Author: Paweł Wilk Date: Mon Jan 31 02:21:43 2011 +0100 Interpolation method fixed and improved (now it sends all subpatterns at once) commit fc4ece4637a00003156e1cdf3742c6b9649bc211 Author: Paweł Wilk Date: Mon Jan 31 02:20:21 2011 +0100 Key reporting in error reporting methods fixed and improved commit 74194159094b59e87899d3b6f231181912a2f6b0 Author: Paweł Wilk Date: Mon Jan 31 02:19:36 2011 +0100 Reserved keys updated commit aa374a3e84a45ac69e7c79e8d12596932a44604e Author: Paweł Wilk Date: Mon Jan 31 02:19:05 2011 +0100 Documentation updated, removed debugging switch from backend method commit c133c73b5260d44bcbc2a765c5b46a82a14151e9 Author: Paweł Wilk Date: Mon Jan 31 02:18:27 2011 +0100 Documentation fixed commit 3eca748793ac7e1ac4adb5501ffad69d96485e2c Author: Paweł Wilk Date: Sun Jan 30 23:49:06 2011 +0100 Added :inflector_cache_aware switch that causes inflector to pass all options to translate call commit 0a9efaedff51caecd1741dfe39152c9a0dbc387f Author: Paweł Wilk Date: Sun Jan 30 22:58:11 2011 +0100 Reading of known kinds improved a bit; one intermediate array on each call commit 09d5358f6f829cea2eb42543270c2a0097fe9472 Author: Paweł Wilk Date: Sun Jan 30 20:38:08 2011 +0100 Updated HISTORY and TODO commit ac2331d4f72b7cbe9a0c2b1c1860a374210800f6 Author: Paweł Wilk Date: Sun Jan 30 20:37:42 2011 +0100 Removed cache-related stuff. A cache should be other backend for I18n, not a class for Inflector commit a8c48bf13f8856d48195ca40b4e4110339de2d82 Author: Paweł Wilk Date: Sun Jan 30 20:36:18 2011 +0100 Options preparing methods moved to I18n::Inflector::InflectionOptions, @known is now a lazy hash commit 9cce55b6dfedf0a1720dd8fd7dbe821f7a666d32 Author: Paweł Wilk Date: Sun Jan 30 20:32:52 2011 +0100 All inflection related exceptions are now aware of translation key commit abee72cce5f552aa0a217a2ef4ed977d7f251cd5 Author: Paweł Wilk Date: Sun Jan 30 17:43:53 2011 +0100 Added some test for complex patterns mixed with aliased patterns and loud tokens commit d38d9fdb5e4cea7cd2add52d94a1262d3d54cd9a Author: Paweł Wilk Date: Sun Jan 30 17:40:55 2011 +0100 Documentation updated commit 67edeef3557064af60de255f2a0778aa9df5d3e6 Author: Paweł Wilk Date: Sun Jan 30 17:40:44 2011 +0100 Typo removed commit 0fbcc31ab7ada438dc209d49569daf5d44267b02 Author: Paweł Wilk Date: Sun Jan 30 17:40:34 2011 +0100 Complex patterns now support loud tokens commit d2cd5d76a457f4865c330b7d22d32e27ae903fc7 Author: Paweł Wilk Date: Sun Jan 30 06:09:19 2011 +0100 Updated TODO, ChangeLog and HISTORY commit 0c77a0c49f32b3a20d1ad6fd6c16ff441e12d8d3 Author: Paweł Wilk Date: Sun Jan 30 05:56:50 2011 +0100 Added complex patterns support commit 67c0fc2acfe950d96752094fb42d87e9154d562c Author: Paweł Wilk Date: Sun Jan 30 05:55:24 2011 +0100 Added lazy enumerators for arrays commit 6e1db292b9f49570780558b1b1d5a3e9aa833e3f Author: Paweł Wilk Date: Sun Jan 30 04:14:52 2011 +0100 Options reading refactored: more efficient way of gathering global & local options in API methods commit b99e4a5b02a685ec0f3c210e00428a337c99082a Author: Paweł Wilk Date: Sun Jan 30 04:09:42 2011 +0100 Error messages handling refactored: exceptions are more hierarchical and more DRY commit b9c35db66702d137f21a3ef8cc64caba59b20202 Author: Paweł Wilk Date: Sat Jan 29 23:38:01 2011 +0100 Added some constants for future features commit d29026e54e5f0fea1f43fd5eb89b37808ed12e09 Author: Paweł Wilk Date: Sat Jan 29 23:37:26 2011 +0100 Added abstract error reporting classes: - I18n::InflectionException, - I18n::InflectionPatternException, - I18n::InclectionConfigurationException. commit e88c43fccf877dd69ae25c2793f0da4e3103b31c Author: Paweł Wilk Date: Fri Jan 28 03:50:17 2011 +0100 Bugfix: filtering reserved option names enabled :> commit 67f6a0c12cbbe4a7e6980b0b3d2f68e39b665dbf Author: Paweł Wilk Date: Fri Jan 28 01:50:24 2011 +0100 Manifest.txt updated commit e624ff5e8102ad5bdd0279a428debaded911df8f Author: Paweł Wilk Date: Fri Jan 28 01:49:37 2011 +0100 Interpolation method moved to I18n::Inflector::Interpolate, loud tokens documented, escaping fixed commit 25d9c41cf12c4cbfec237abe9dec7b1991df004a Author: Paweł Wilk Date: Thu Jan 27 18:01:20 2011 +0100 Lists of escape strings are now kind of HSet commit 290ee7fb55aaca4dfe788f34fffb914660829cae Author: Paweł Wilk Date: Thu Jan 27 17:33:01 2011 +0100 Added support for loud tokens commit 7da2fcd563bdc6c9b8bc0475c4163e16860c27e4 Author: Paweł Wilk Date: Thu Jan 27 02:46:44 2011 +0100 Documentation fixes commit ceb547f1cc32690ff9ee1e6d5225dfe18119164f Author: Paweł Wilk Date: Thu Jan 27 02:46:30 2011 +0100 Intermediate array removed when dumping hash from LazyHashEnumerator commit 50eff6c3ce7def1dddd2f840590f17c8a38c5b61 Author: Paweł Wilk Date: Thu Jan 27 02:26:30 2011 +0100 Fixed typo in README commit abe5a4570b80924c323dde65e30ba30be50446ce Author: Paweł Wilk Date: Thu Jan 27 01:30:54 2011 +0100 Release 2.1.0 commit 72a808453e71b18c696943b37d8bd07c3f5c6c93 Author: Paweł Wilk Date: Thu Jan 27 01:29:55 2011 +0100 Tested with Ruby 1.8 and 1.9, with Rails app, with i18n-inflector-rails, with I18n v4.1 and v5.0 commit f8c13ef824d68bed04a96d52a8be8399d21617f1 Author: Paweł Wilk Date: Thu Jan 27 01:27:11 2011 +0100 Added some tests for multiple patterns in one translation data commit becf2f23bd41e7902d2510531e9383abb310a861 Author: Paweł Wilk Date: Thu Jan 27 01:26:47 2011 +0100 Ideas reorganized in TODO commit 44fce7b2959040657d5d52f21a1c1a3c63a80921 Author: Paweł Wilk Date: Thu Jan 27 01:26:17 2011 +0100 Added EXAMPLES commit b43472f4d4433b1d1cc7001b8bec9844f9a6b6f4 Author: Paweł Wilk Date: Wed Jan 26 22:29:20 2011 +0100 Ideas updated commit bcc5c7994867e784bcb6950db18021a82a1a9daf Author: Paweł Wilk Date: Wed Jan 26 22:26:54 2011 +0100 Added a test that verifies whether original translate eats options and impacts interpolation commit 7c274ca8a6192495c4b3bfa2edc99339d01a4308 Author: Paweł Wilk Date: Wed Jan 26 20:45:25 2011 +0100 Options for translate are now duplicated before calling the original version commit 138273a0780289ec7b330c8f54090bb72b0e9d82 Author: Paweł Wilk Date: Wed Jan 26 20:19:08 2011 +0100 Manifest.txt regenerated commit 5c47868b4a51012e8a722a66a383b014eb9e959e Author: Paweł Wilk Date: Wed Jan 26 19:36:33 2011 +0100 Added LazyHashEnumerator#keys for dumping keys of a resulting hash commit 831eff126f9d233c75e3793798f20ae23d7de6db Author: Paweł Wilk Date: Wed Jan 26 19:33:16 2011 +0100 File RELATIONS updated commit c3c3cdf4abd57631b52bb3b960bd08289bf6edc9 Author: Paweł Wilk Date: Wed Jan 26 17:37:40 2011 +0100 Added some extra tests for InflectionData#add_token and InflectionData_Strict#add_token commit df4675d463fc9b405077282bd474671b80b65656 Author: Paweł Wilk Date: Wed Jan 26 17:37:04 2011 +0100 Documentation for InflectionDataStrict updated commit b764b00b1c5de5d377a064404c3a3dc45864e1a9 Author: Paweł Wilk Date: Wed Jan 26 17:15:32 2011 +0100 Documentation updates commit ff581f4dd2e0ea9ee2f19474f84b10fc79b8b0c2 Author: Paweł Wilk Date: Wed Jan 26 16:45:45 2011 +0100 Method API_Strict#inflected_locales fixed; verifies results with InflectionData_Strict#empty? commit 1f270ea082729c30c9851fa519e0f1c07ca39528 Author: Paweł Wilk Date: Wed Jan 26 16:42:03 2011 +0100 Added some tests for getting inflections commit 26cea141be36b443f866d04a04bd57941bc02bb0 Author: Paweł Wilk Date: Wed Jan 26 16:41:36 2011 +0100 Documentation updates commit e9646adb37bde86f9131f3be8e5e1faef292fb84 Author: Paweł Wilk Date: Wed Jan 26 03:30:33 2011 +0100 Documentation updated for the class InflectionData commit 739c724cbfc452925c0ad74dd1ede66f5e495804 Author: Paweł Wilk Date: Wed Jan 26 03:29:51 2011 +0100 Added EXAMPLES file to documentation commit d27b9d5457872dbdd66d14611b1016e2fb5e2ecf Author: Paweł Wilk Date: Wed Jan 26 02:55:23 2011 +0100 TODO updated commit 4a052f86d488c37f1c4c70a716bc4d5fc3a507fc Author: Paweł Wilk Date: Wed Jan 26 02:54:53 2011 +0100 Documentation for class API_Strict updated commit d9c380cb22848e001de5eb98f9103950dd470d61 Author: Paweł Wilk Date: Wed Jan 26 01:55:54 2011 +0100 Class LazyEnumerator cleaned and renamed to LazyHashEnumerator commit 5dff82b62eefa0ecefbb2109870f5d27ad4b867b Author: Paweł Wilk Date: Wed Jan 26 01:08:58 2011 +0100 Strict kinds described commit 14d91e3eb09eccfddbc9e73f97c8d715f158c4eb Author: Paweł Wilk Date: Wed Jan 26 01:08:33 2011 +0100 Added RELATIONS documentation to compat gemspec commit 70d0f47ead977140ec0e87aa1e28f06f2b652040 Author: Paweł Wilk Date: Wed Jan 26 01:08:03 2011 +0100 Improvements of interpolation routine, error reporting and arguments validation commit ce54b7309fef659b8a06e6f011d30a4dc15587e5 Author: Paweł Wilk Date: Wed Jan 26 01:04:59 2011 +0100 Added tests for named patterns, some tests fixed commit 5d81d7514ad94a12b72e7ffcb2f2168511a52f2f Author: Paweł Wilk Date: Wed Jan 26 01:04:27 2011 +0100 Added new error classes InflectionOptionNotFound and InflectionOptionIncorrect commit 2d0d2f041798681ce598f95bfa2847e7c86e8fef Author: Paweł Wilk Date: Tue Jan 25 04:10:18 2011 +0100 Added note about named patterns to README commit 663aedad35b98c6aac08073ef13f6145041eb431 Author: Paweł Wilk Date: Tue Jan 25 04:00:47 2011 +0100 Documentation updated commit 0658fe79eaa385ca058ed29e4cc8a18007875a11 Author: Paweł Wilk Date: Tue Jan 25 03:36:24 2011 +0100 Added tests for easy API calls with @kind in arguments commit aa9dd4a1133eeb50dfe5237f142350fb6e0609d9 Author: Paweł Wilk Date: Tue Jan 25 03:35:04 2011 +0100 Documentation fixes commit 3b241abe7ae39219a0e847bddc65e76f89590055 Author: Paweł Wilk Date: Tue Jan 25 03:34:29 2011 +0100 Fixed bug in typing that caused some API calls to has_kind? and default_token to be erroneus commit 71600f1056aa3e89fe2f5c21982bca5f5379ec50 Author: Paweł Wilk Date: Tue Jan 25 03:32:43 2011 +0100 Documentation for API updated and corrected commit e007ce75e59bbb42f2d6474d8fbfd0888937bd1b Author: Paweł Wilk Date: Tue Jan 25 03:32:05 2011 +0100 Fixed bug that caused some aliases for strict kinds to not be loaded because of missing @ commit 25303663e091123e1820b33f2c3e670c054fc25f Author: Paweł Wilk Date: Mon Jan 24 18:31:09 2011 +0100 Documentation updated, tests fixed commit 370ad6e4e5f1ab6dcbe7b9a7edd703064ee708a9 Author: Paweł Wilk Date: Mon Jan 24 18:29:53 2011 +0100 API_Named calls changed to API_Strict, documentation updated commit d95b43f359b438e4a1fef4907545dae4ec7abe9d Author: Paweł Wilk Date: Mon Jan 24 18:29:01 2011 +0100 API_Named renamed to API_Strict commit a5c1467e931279022173e86e5e05992a30768334 Author: Paweł Wilk Date: Mon Jan 24 14:38:59 2011 +0100 Fixes: slow blocks removed, magic @kind interpreting finished, Ruby's version test improved commit fbdd10ae7ff73ceb5b5697f138f2e02deee8bb5e Author: Paweł Wilk Date: Mon Jan 24 13:02:52 2011 +0100 Removed backport.rb, added some backporting code directly to LazyEnumerator class commit 570709c07a293b4a1cd4e1b864744ac38f12f2ee Author: Paweł Wilk Date: Mon Jan 24 11:32:01 2011 +0100 Manifest.txt and ChangeLog regenerated commit 691d74f506c78566f2d5d04d55f0381a0a2209a6 Author: Paweł Wilk Date: Mon Jan 24 11:31:31 2011 +0100 Added backport methods for lazy enumerators to work with Ruby 1.8 and some tests commit 65c6c73e263f6e8e655921fcea78e6237d3a438f Author: Paweł Wilk Date: Mon Jan 24 03:07:26 2011 +0100 Documentation updated commit cc3d99c2b869cd8ee467ffd97d286850f0763125 Author: Paweł Wilk Date: Mon Jan 24 02:58:39 2011 +0100 Tokens querying methods of InflectionData and InflectionData_Strict are based on lazy enumerators commit 90bcb046711fcce1d0302bc4de3cb5caf728518c Author: Paweł Wilk Date: Sun Jan 23 21:04:07 2011 +0100 Added lazy enumerators class commit 869810b79278843efe712580589e69676a230cf4 Author: Paweł Wilk Date: Sun Jan 23 21:03:41 2011 +0100 Important fix to @kind-style tokens parsing commit a17a2a86839e6ef969ca0672648423c65ee5f28d Author: Paweł Wilk Date: Sun Jan 23 21:02:53 2011 +0100 Documentation fixes commit 354ae5dd247a5d0b9c3a15ae226757c215c8335a Author: Paweł Wilk Date: Sun Jan 23 21:01:15 2011 +0100 Added lazy enumeration while loading tokens commit 2a853fad411a2fb1cabb18eaf0b594486cbbfa71 Author: Paweł Wilk Date: Sun Jan 23 04:41:07 2011 +0100 Added magic to API; kinds with names containing @ marker are now parsed by methods from @named commit 5a0894ee65bb08732186e1cae0e0e32311144621 Author: Paweł Wilk Date: Sun Jan 23 04:17:16 2011 +0100 Loading inflection tokens cleaned up, documentation updated commit 377d8e6077bba885885ae3fda441935b88137365 Author: Paweł Wilk Date: Sat Jan 22 23:07:29 2011 +0100 Fixed databases loading, API unified, InflectionData and InflectionData_Strict databases split commit 7a6401eefa879905b40181f44a95fcfcb916c3c0 Author: Paweł Wilk Date: Sat Jan 22 18:57:12 2011 +0100 Documentation updated commit 4d076ecf54f195755c560ecac0370eddc4624111 Author: Paweł Wilk Date: Sat Jan 22 18:16:25 2011 +0100 Reader for @locale moved to base class (InflectionData_Strict) from InflectionData commit 8b2c38a5151ae4fc66dfbf98533be816fa7400f6 Author: Paweł Wilk Date: Sat Jan 22 18:12:14 2011 +0100 Removed InflectionStore class, moved logic to InflectionData and InflectionData_Strict commit afd1dee0fc460d433fb7235148ef53d780952481 Author: Paweł Wilk Date: Sat Jan 22 17:25:30 2011 +0100 I18n::Inflector::API is now major class for using inflections commit 593ae7ff42fcdac1fa5951f0324990d3caa2d31f Author: Paweł Wilk Date: Sat Jan 22 14:39:17 2011 +0100 Class API removed and methods joined to Core class. Class API::Named moved to NamedAPI commit 8eef8a5bc39ce202332a53f659ff6593f0d29ace Author: Paweł Wilk Date: Sat Jan 22 02:00:46 2011 +0100 Documentation updates commit c77c841aed0dbc19ef26ce1c44fe38b74fe46e2f Author: Paweł Wilk Date: Thu Jan 20 23:21:44 2011 +0100 Added tests to cover public API, database management methods moved to InflectionStore commit 61b0e11d895de3284eab73805c471505b1fdc0a9 Author: Paweł Wilk Date: Thu Jan 20 18:13:12 2011 +0100 Dummy whitespaces removed commit d7fcb11585469b40c2a03e03d70d3382d30efa50 Author: Paweł Wilk Date: Thu Jan 20 16:52:41 2011 +0100 Added named patterns support, I18n::Inflector::Core refactored commit a358abde6191cb48d80a087a3b4da58f8cb4166e Author: Paweł Wilk Date: Thu Jan 20 05:37:24 2011 +0100 Internal classes seriously refactored New class I18n::Inflector::InflectionStore that is a child class of I18n::Inflector::InflectionData New class I18n::Inflector::InflectionData::Strict which instance is in InflectionStore Reader strict for InflectionStore to access inflection data for named patterns (strict kinds) commit 599aed89b85f72274d6e4f9e9efd4c11ba863026 Author: Paweł Wilk Date: Wed Jan 19 15:50:07 2011 +0100 Added support for loading named patterns and partial support for interpolating strict kinds commit 7818644eee848f3c2d744b41240f00486822a319 Author: Paweł Wilk Date: Wed Jan 19 15:46:13 2011 +0100 Error messages corrected commit be0c88a74f18575932663c4822c3d45e46442eab Author: Paweł Wilk Date: Tue Jan 18 12:24:04 2011 +0100 Default rake task now runs tests for inflector with both: i18n and i18n version 4 commit c5ce5658d45b867ed3f0157c1f45a2b60d4f50b6 Author: Paweł Wilk Date: Mon Jan 17 23:08:03 2011 +0100 Manifest.txt updated, ChangeLog updated commit 481ffa6a961bc4713c75fefd7e2dd48b3fa8668b Author: Paweł Wilk Date: Mon Jan 17 23:06:09 2011 +0100 Added rake test for i18n in version 4 commit 498b2b78908a2b1173360034bafa265cac67002f Author: Paweł Wilk Date: Mon Jan 17 15:25:52 2011 +0100 RESERVED_KEYS fetching improved commit 4dbdc4b1fb569f7239157aa19b8db8a0ec964d64 Author: Paweł Wilk Date: Mon Jan 17 15:03:19 2011 +0100 Documentation updated commit bb0670ef630cab63736145b3554739be6630f307 Author: Paweł Wilk Date: Mon Jan 17 15:02:50 2011 +0100 Fixes in README commit e8ada4542f3ec98a669a39443c7e556a61894e44 Author: Paweł Wilk Date: Sat Jan 15 14:46:09 2011 +0100 README examples fixed commit dc6ff4d63c7df14681c42ee9799c495aed8140de Author: Paweł Wilk Date: Sat Jan 15 14:35:00 2011 +0100 Doco fixes commit 6afd66c2780f792c13e9e61491cbcc55d684b882 Author: Paweł Wilk Date: Sat Jan 15 01:20:17 2011 +0100 Fix for duplicated dependency in Rakefile, typos fixed in README commit e7a6eb41eab2f76881169eeabb03e9540adeeb0e Author: Paweł Wilk Date: Fri Jan 14 17:33:44 2011 +0100 Version 2.0.0 ready to be released commit 9d87da0b8781be172ed7216aafc57e3bde096504 Author: Paweł Wilk Date: Fri Jan 14 17:29:19 2011 +0100 Added more tests and cleaned up conditional expressions in InflectionData commit 295f2e3c98a23b1109e8e8355c008e9d59ecd010 Author: Paweł Wilk Date: Fri Jan 14 16:26:20 2011 +0100 Version 2.0.0 tested in Rails 3 environment commit 62785a25f593460d91294cd87fdde254acb5f2e3 Author: Paweł Wilk Date: Fri Jan 14 15:06:14 2011 +0100 Speed improvements. commit 1b3ac06a779288f8f9584dd0fc4f50e9f1728a34 Author: Paweł Wilk Date: Fri Jan 14 12:54:40 2011 +0100 Updated version information in README commit d76bd2a91323c8f612a7328191b69014353a3802 Author: Paweł Wilk Date: Fri Jan 14 12:52:13 2011 +0100 Version 2.0.0 commit 33c2e77ecef865c7f1813c1a7db899e66be98c13 Author: Paweł Wilk Date: Fri Jan 14 12:36:36 2011 +0100 Version 1.2.0 commit c86af221fe2a3d7f0bcba863a2ef9e2a91d4825a Author: Paweł Wilk Date: Fri Jan 14 12:31:47 2011 +0100 Documentation updates, code cleanups commit 2fb80a5725325071b9dbad85c8662e263edcfbcc Author: Paweł Wilk Date: Fri Jan 14 02:55:12 2011 +0100 README.rdoc fixed commit f39db3b5a29ee34706326d337cc766983a1bfb9b Author: Paweł Wilk Date: Fri Jan 14 02:51:52 2011 +0100 Added RELATIONS to documentation commit bf8a9799aa0600eddecbf95a981947cf2ef805ef Author: Paweł Wilk Date: Fri Jan 14 02:51:06 2011 +0100 Documentation updated commit 4bf626399b4556ee2a4aaa76a9a7559bd20464a3 Author: Paweł Wilk Date: Thu Jan 13 18:47:08 2011 +0100 Serious refactoring - Interpolating method moved to I18n::Inflector - Loading inflections now creates InflactionData object that feeds I18n::Inflector::Core - Locale management created in I18n::Inflector::Core (pluggable databases) - Added safe_data() and data() methods to Core in order to simplify inflection database calls - Removed send() calls, removed bridge; not needed anymore - InflectionData initializer can now be feeded with locale (it's also stored there) - Removed unneeded I18n::Inflector::Util incusion in I18n::Inflector::Backend commit 0fc113797bdd9ff7bd3d1e953385c6670064b936 Author: Paweł Wilk Date: Thu Jan 13 06:36:19 2011 +0100 I18n::Inflector is a regular module and inflector is sticked to the backend again New class I18n::Inflector::Core is API to deal with inflection data. Inflector is now @inflector in altered I18n::Backend::Simple and I18n.inflector is a proxy method commit cf547a804c4c90418e8cfb69de405660a959eba9 Author: Paweł Wilk Date: Thu Jan 13 05:25:21 2011 +0100 Options are now kind of InflectionOptions and are controlled by I18n::Inflector class methods commit a7cbc568ca90d67a4c7ef2b9c9c08f1c5dbc94f0 Author: Paweł Wilk Date: Thu Jan 13 01:56:15 2011 +0100 Errors moved out if I18n::Inflector::InflectionData, documentation updated a bit commit 324a647292c9e9d5121b0b2bd18fb83151458afb Author: Paweł Wilk Date: Wed Jan 12 22:13:52 2011 +0100 Code refactored. Added class InflectionData and keeping all data in its instance Aliases are now keeped along with tokens in one hash, there are also some new API methods commit faa4ca16bbafb572e7d209e139b8664406040a43 Author: Paweł Wilk Date: Wed Jan 12 01:36:26 2011 +0100 Serious refactoring and namespace changes - Most of inflector-specific API methods are now in I18n::Inflector - Core logic (loading and translations) in I18n::Backend::Inflector - Useful methods used in both modules listed above in I18n::Inflector::Util - Added new method for checking if token exists - Added bridge between I18n::Inflector and I18n::Backend::Inflector (init_frontend) - Started working on feature for is_* methods (additional argument narrows tests to some kind) - Changed method names to more intuitive commit edc402233f62b6a135882a28fc1c284d5a5fee99 Author: Paweł Wilk Date: Tue Jan 11 21:50:28 2011 +0100 Added support for negative matches in patterns commit 6cf50a1b31c61a0f0ddb102d8b5f1a68bf769247 Author: Paweł Wilk Date: Tue Jan 11 16:04:16 2011 +0100 Added support for token groups seaprated by commas commit e399d04ba157e16fe45c55b41ff5cb313ce6da3e Author: Paweł Wilk Date: Tue Jan 11 08:21:32 2011 +0100 Inflected locale testing is not raising errors when entered locale is invalid commit a336e2376c3e0e2e50f1404529dd5e726732583b Author: Paweł Wilk Date: Mon Jan 10 05:38:14 2011 +0100 Fix for apps initializing translations via YAML files commit dc81afa48b36336b9efde0ce9019637edc0474f8 Author: Paweł Wilk Date: Mon Jan 10 04:23:49 2011 +0100 Release 1.0.10 commit 2a3e10b2b9310c37a66a88f0511e24336671ee80 Author: Paweł Wilk Date: Mon Jan 10 04:19:21 2011 +0100 Serious bugfixes and enhancements; removed cause of the infinite loop while loading translations commit 34321a02570226c07948f306bf3a68dff9d8ecb1 Author: Paweł Wilk Date: Mon Jan 10 01:38:22 2011 +0100 Added TODO commit 5e3f970ffd3bd9d56bad8fe910439d2689e83da1 Author: Paweł Wilk Date: Sun Jan 9 07:06:39 2011 +0100 ChangeLog updated commit fb02e573ec85a29efac5e7cd3f2f5f01c7ff3859 Author: Paweł Wilk Date: Sun Jan 9 07:06:11 2011 +0100 Version information moved out of main include file and Backend namespace, dependencies fixed commit dff3f3214f4601d1ac5351b1f7444b200abc7101 Author: Paweł Wilk Date: Sun Jan 9 07:03:15 2011 +0100 Year change to 2011 in doco commit f100799dff8d5b289db6fa7e7348e17439847037 Author: Paweł Wilk Date: Sat Jan 8 16:47:16 2011 +0100 Fixed typo in doc commit 5b6fbbf2bffdcf5cd082532068ad7900454db163 Author: Paweł Wilk Date: Sat Jan 8 16:30:23 2011 +0100 Release 1.0.8 commit a58d0636a559419e6c3f715562d2240ee9f6e1ff Author: Paweł Wilk Date: Sat Jan 8 16:29:40 2011 +0100 Enabled escaping of patterns and added some documentation about it and tests commit 3e0a295246dd90a18cc164d71f064fb11d8d2364 Author: Paweł Wilk Date: Fri Jan 7 00:08:18 2011 +0100 Using default GPG key for signing tags that's referenced in the global configuration of the git tool commit 591de41dd9e6418457ee6273121ac25ee7e0d4b8 Author: Paweł Wilk Date: Thu Jan 6 23:54:41 2011 +0100 Release 1.0.7 commit 7bb3d12c15221b3d2bb9cb74ff9cda86378ce5c7 Author: Paweł Wilk Date: Thu Jan 6 23:53:52 2011 +0100 Fixed bug that caused translation data containing anything but a pattern to not be interpolated commit 70fceb583e8201ac5ae5d8a6210e160024fd3c83 Author: Paweł Wilk Date: Thu Jan 6 23:52:26 2011 +0100 Typo in documentation fixed commit 948438fdcbb940b5f02186b7fe337348c7e86930 Author: Paweł Wilk Date: Thu Dec 30 18:00:22 2010 +0100 Release 1.0.6 commit cf0e6b5a0c01de939c0bdeea82b9cd615966b3a8 Author: Paweł Wilk Date: Thu Dec 30 17:43:49 2010 +0100 Added two API methods to test tokens: inflection_true_token() and inflecion_kind() commit a1b2aa5314e7724c145902fec445dd2ef63356c3 Author: Paweł Wilk Date: Thu Dec 30 02:37:41 2010 +0100 Added API method inflected_locale? to check if a locale supports inflection commit 322d88353b88966a2c1f2daa281b2e825156201b Author: Paweł Wilk Date: Thu Dec 30 02:35:14 2010 +0100 Added YARD's @api public metatag to public methods commit d20c178f9ca63735e5cad860b09a0935c3601365 Author: Paweł Wilk Date: Thu Dec 30 02:31:44 2010 +0100 Moved RESERVED_KEYS reading to module scope from instance method commit 44b365005abe11ac310ceb3ca55dd598f73ae6b6 Author: Paweł Wilk Date: Wed Dec 29 16:18:59 2010 +0100 Release 1.0.5 commit c101947a64bb40050ff7a7df48c7207297140b5b Author: Paweł Wilk Date: Wed Dec 29 16:18:22 2010 +0100 Compatible with i18n >= 0.4.1 commit d2916cbe2fb605c95c875cef0c16f9f6bacaf001 Author: Paweł Wilk Date: Mon Dec 27 16:02:59 2010 +0100 Release 1.0.4 commit 2c87d11e253ed34d427e6c74c052c7a890f75a80 Author: Paweł Wilk Date: Mon Dec 27 15:45:53 2010 +0100 Added @return metatags to shortcuts documentation commit b269c64ae9be6054d61cac5ac17611c37efccc3f Author: Paweł Wilk Date: Sun Dec 26 00:59:05 2010 +0100 Typo fixed commit 822737f020057b84179b323e3e156f8521fb7507 Author: Paweł Wilk Date: Sun Dec 26 00:16:42 2010 +0100 Added entry to HISTORY file and fixed the description string commit e3fde026a01ec3103650f5beac96f831da422c99 Author: Paweł Wilk Date: Sat Dec 25 21:48:57 2010 +0100 Release 1.0.3 commit 1425a4ec1101de2b4d15182af012714a842308ed Author: Paweł Wilk Date: Sat Dec 25 21:47:40 2010 +0100 Serious changes in documentation, accessors refactored - YARD options moved to .yardopts - Added YARD metatags to inline documentation - Exception classes moved to in errors.rb - Method inflection_raw_tokens renamed to inflection_tokens_raw with alias added - Method inflection_true_tokens renamed to inflection_tokens_true with alias added - Shortcut names from I18n::Inflector are now module methods defined within class< Date: Wed Dec 22 20:37:49 2010 +0100 Cosmetics in README.rdoc commit 79e3a3adf00b6fbd4709ab1d60631ae4c8a676f5 Author: Paweł Wilk Date: Wed Dec 22 20:13:20 2010 +0100 Moving to README.rdoc as an index file for documentation commit b299fef82a0358fecdeb0ff9b634a34b3f30f707 Author: Paweł Wilk Date: Wed Dec 22 20:04:26 2010 +0100 Removed redundant dependencies and moved YARD options out of Rakefile commit 0c12a10a5a0b0a6a886cea5bbafd6f77a15ae8a9 Author: Paweł Wilk Date: Wed Dec 22 15:59:50 2010 +0100 Release 1.0.2 commit bc666bd326a2bd3724239923f8204d5576d3a855 Author: Paweł Wilk Date: Wed Dec 22 15:58:42 2010 +0100 Prepared for release 1.0.2 commit 6bbda195d3f4fe0999a1a88b42a8489b0ebbd210 Author: Paweł Wilk Date: Wed Dec 22 15:55:06 2010 +0100 Release 1.0.1 fixed commit fb6ecc91e8c8a7d06e8fce986209a0443aa05cc6 Author: Paweł Wilk Date: Wed Dec 22 15:52:27 2010 +0100 Module linked in README. commit 678e90c7b04499a71f1c6f907a898a2b5722a853 Author: Paweł Wilk Date: Wed Dec 22 15:42:37 2010 +0100 Release 1.0.1 commit 778841d1dab12aafc478e74df61f192a744607f1 Author: Paweł Wilk Date: Wed Dec 22 15:40:56 2010 +0100 Switched fully to YARD commit 053d21b50b5441a973a870d415e72fb88497d0f2 Author: Paweł Wilk Date: Wed Dec 22 14:15:01 2010 +0100 Tests simplified, Rakefile cleaned, dependencies cleaned, documentation fixed. commit 3ed077e240660ff09e4ff3df5e698f198b8eafbf Author: Paweł Wilk Date: Wed Dec 22 04:01:25 2010 +0100 Prepared for v1.0.0 commit 3cf24746a9a4e3b41ef9b4ee11334df76607d6b6 Author: Paweł Wilk Date: Wed Dec 22 04:00:13 2010 +0100 Documentation fixes commit 3ceb7f1aeaa1d682ac3d1ee0d091e5be4caad3b6 Author: Paweł Wilk Date: Wed Dec 22 03:48:07 2010 +0100 Fixes in documentation, dependencies and examples commit 8f88cedae5b9f15a0e468f568103125933af3f27 Author: Paweł Wilk Date: Wed Dec 22 02:26:03 2010 +0100 Initial commit ruby-i18n-inflector-2.6.6/Gemfile000066400000000000000000000010721204270775600165530ustar00rootroot00000000000000# -*- ruby -*- # DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake bundler:gemfile`. source :gemcutter gem "i18n", ">=0.4.1" gem "hoe-yard", ">=0.1.2", :group => [:development, :test] gem "test_declarative", ">=0.0.5", :group => [:development, :test] gem "yard", ">=0.7.2", :group => [:development, :test] gem "rdoc", ">=3.8.0", :group => [:development, :test] gem "bundler", ">=1.0.15", :group => [:development, :test] gem "hoe-bundler", ">=1.1.0", :group => [:development, :test] gem "hoe", "~>2.16", :group => [:development, :test] # vim: syntax=ruby ruby-i18n-inflector-2.6.6/Gemfile.lock000066400000000000000000000007731204270775600175110ustar00rootroot00000000000000GEM remote: http://rubygems.org/ specs: hoe (2.16.0) rake (~> 0.8) hoe-bundler (1.1.0) hoe (>= 2.2.0) hoe-yard (0.1.2) yard (>= 0.2.3.1) i18n (0.6.0) json (1.6.5) rake (0.9.2.2) rdoc (3.12) json (~> 1.4) test_declarative (0.0.5) yard (0.7.5) PLATFORMS ruby DEPENDENCIES bundler (>= 1.0.15) hoe (~> 2.16) hoe-bundler (>= 1.1.0) hoe-yard (>= 0.1.2) i18n (>= 0.4.1) rdoc (>= 3.8.0) test_declarative (>= 0.0.5) yard (>= 0.7.2) ruby-i18n-inflector-2.6.6/LGPL-LICENSE000066400000000000000000000172061204270775600170270ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ruby-i18n-inflector-2.6.6/Manifest.txt000066400000000000000000000013771204270775600175770ustar00rootroot00000000000000.yardopts ChangeLog Gemfile Gemfile.lock LGPL-LICENSE Manifest.txt README.rdoc Rakefile ci/i18n-inflector.gemspec ci/i18nv4-Gemfile ci/i18nv4-Gemfile.lock docs/COPYING docs/EXAMPLES docs/HISTORY docs/LEGAL docs/LGPL docs/TODO docs/USAGE docs/rdoc.css lib/i18n-inflector.rb lib/i18n-inflector/api.rb lib/i18n-inflector/api_strict.rb lib/i18n-inflector/backend.rb lib/i18n-inflector/config.rb lib/i18n-inflector/errors.rb lib/i18n-inflector/hset.rb lib/i18n-inflector/inflection_data.rb lib/i18n-inflector/inflection_data_strict.rb lib/i18n-inflector/inflector.rb lib/i18n-inflector/interpolate.rb lib/i18n-inflector/lazy_enum.rb lib/i18n-inflector/long_comments.rb lib/i18n-inflector/options.rb lib/i18n-inflector/version.rb test/inflector_test.rb test/test_helper.rb ruby-i18n-inflector-2.6.6/README.rdoc000066400000000000000000000171611204270775600170740ustar00rootroot00000000000000= I18n Inflector i18n-inflector version 2.6.6 (Little Kózka) * https://rubygems.org/gems/i18n-inflector * https://github.com/siefca/i18n-inflector/tree * mailto:pw@gnu.org == Summary This library contains a backend module for I18n that adds some extra functionality to standard backend. It overwrites the translate method in a way that it will interpolate additional inflection tokens present in translations. == Synopsis require 'i18n-inflector' I18n.translate( 'to_be', :number => :singular, :tense => :past, :person => 2 ) #=> You were here I18n.translate('welcome', :gender => :female) #=> Dear Lady == Why? You can use I18n Inflector to (relatively easy) create translations for highly inflected languages (like those belonging to Slavic language family). You can also use it in translation services that may operate on sentences instead of exact words. == When? It is intended to be used in a web projects or other projects where translations are performed by many people, yet there is a need to inflect sentences with some external variables. To achieve similar functionality lambdas can be used but including many Proc objects might be considered unsafe or memory consuming. See i18n-inflector-rails[https://rubygems.org/gems/i18n-inflector-rails] if you need Rails integration. == How? I18n Inflector lets you build you own inflection patterns contained in translation entries. The patterns may contain simple conditions and tokens, which combined with parameters passed to +I18n.translate+ method can produce inflected strings. * See {USAGE}[http://rubydoc.info/gems/i18n-inflector/file/docs/USAGE] for detailed information about the usage. * See {EXAMPLES}[http://rubydoc.info/gems/i18n-inflector/file/docs/EXAMPLES] for examples. * See {whole documentation}[http://rubydoc.info/gems/i18n-inflector/] to browse all documents. == Features * Inline inflection using patterns in translation data. * Key-based inflection using individual inflection keys. * Definable inflection kinds and tokens. * Easy to use public API for inflection data. * Configurable using special scope of translation data. * Lazily evaluated Proc and Method objects as inflection options. * Complex patterns support; inflection by more than one kind at a time. * Negative matching, aliases, default tokens, token groups and more… == Description The I18n Inflector extends the translate method from I18n in a way that it will interpolate additional inflection tokens present in translations. These tokens may appear in *patterns* which are contained within @{ and } symbols. Configuration is stored also in translation data, in a scope .i18n.inflections, where locale is a locale subtree. You can create your own inflection kinds (gender, title, person, time, author, etc.) of tokens to group them in a meaningful, semantical sets. That means you can apply Inflector to do simple inflection by a gender or a person, when some language requires it. It adds the +inflector+ object to the default backend so you can use many methods for accessing loaded inflection data at runtime, or to set up global switches that are controlling the engine. == Short example Example configuration which uses translation data: en: i18n: inflections: gender: f: "female" m: "male" n: "neuter" female: @f male: @m default: n Example translation data: en: welcome: "Dear @{f:Lady|m:Sir|n:You|All}!" @same_but_as_key: f: "Lady" m: "Sir" n: "You" @prefix: "Dear " @suffix: "!" @free: "All" === Note about YAML parsing The example above is not compatible with Psych parser, which is used by Rails 3. There are two ways to solve that problem. First is to change a YAML file and replace any value that has special meaning with a symbol: en: i18n: inflections: gender: f: "female" m: "male" n: "neuter" female: :@f male: :@m default: :n Second way is to use other parser by adding to +config/boot.rb+: require 'yaml' YAML::ENGINE.yamler = 'syck' == New features From version 2.1.0 the Inflector supports so called named patterns, which can be used if there is a need to be strict and/or to use the same token names but assigned to different kinds. Example: welcome: "Dear @gender{f:Lady|m:Sir|n:You|All}" From version 2.2.0 the Inflector supports complex patterns, which can be used to inflect some sentence or a word by more than a one kind. That might be very helpful for highly inflected languages. An example pattern: welcome: "Dear @gender+number{f+s:Lady|f+p:Ladies|m+s:Sir|m+p:Gentlemen|All}" == Requirements * i18n[https://rubygems.org/gems/i18n] * rake[https://rubygems.org/gems/rake] * rubygems[http://docs.rubygems.org/] * bundler[http://gembundler.com/] == Download ==== Source code * https://github.com/siefca/i18n-inflector/tree * git clone git://github.com/siefca/i18n-inflector.git ==== Gem * https://rubygems.org/gems/i18n-inflector == Installation * gem install i18n-inflector == Detailed example YAML: en: i18n: inflections: gender: f: "female" m: "male" n: "neuter" o: "other" default: n welcome: "Dear @{f:Lady|m:Sir|n:You|All}" Code: I18n.t('welcome') # => "Dear You" I18n.t('welcome', :gender => :m) # => "Dear Sir" I18n.t('welcome', :gender => :unknown) # => "Dear You" I18n.inflector.options.unknown_defaults = false I18n.t('welcome', :gender => :unknown) # => "Dear All" I18n.t('welcome', :gender => :o) # => "Dear All" I18n.inflector.options.excluded_defaults = true I18n.t('welcome', :gender => :o) # => "Dear You" == More information * See {I18n::Inflector::API} class documentation for detailed information about the API. * See {I18n::Backend::Inflector} module documentation for detailed information about the internals. == Tests You can run tests both with * bundle exec rake test or just bundle exec rake * run bundle exec rake testv4 to test with version 4 of I18n * run a test file directly, e.g. ruby -Ilib -Itest test/inflector_test.rb == Common rake tasks * bundle exec rake bundler:gemfile – regenerate the +Gemfile+ * bundle exec rake docs – render the documentation (output in the subdirectory directory +doc+) * bundle exec rake gem – builds package (output in the subdirectory +pkg+) * bundle exec rake test, bundle exec rake testv4 – performs tests * bundle exec rake Manifest.txt – regenerates the +Manifest.txt+ file * bundle exec rake ChangeLog – regenerates the +ChangeLog+ file == Credits {Heise Media Polska}[http://www.heise-online.pl/] supports Free Software and has contributed to this library by paying for me to eat when I've been coding. == License Copyright (c) 2011,2012 by Paweł Wilk. i18n-inflector is copyrighted software owned by Paweł Wilk (pw@gnu.org). You may redistribute and/or modify this software as long as you comply with either the terms of the LGPL (see {file:docs/LGPL}), or Ruby's license (see {file:docs/COPYING}). THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ruby-i18n-inflector-2.6.6/Rakefile000066400000000000000000000054731204270775600167360ustar00rootroot00000000000000# encoding: utf-8 # -*- ruby -*- $:.unshift File.join(File.dirname(__FILE__), "lib") require 'rubygems' require 'bundler/setup' require "rake" require "rake/clean" require "fileutils" require 'i18n-inflector/version' require 'hoe' task :default do Rake::Task[:test].invoke Rake::Task[:test].reenable Rake::Task[:testv4].invoke end # Update Gemfile for I18n in version 4 task :gemfilev4 do gemprev = ENV['BUNDLE_GEMFILE'] ENV['BUNDLE_GEMFILE'] = 'ci/i18nv4-Gemfile' `rake bundler:gemfile` ENV['BUNDLE_GEMFILE'] = gemprev end # Tests for I18n in version 4 task :testv4 do gemprev = ENV['BUNDLE_GEMFILE'] ENV['BUNDLE_GEMFILE'] = 'ci/i18nv4-Gemfile' `bundle install` Rake::Task[:test].invoke ENV['BUNDLE_GEMFILE'] = gemprev end desc "install by setup.rb" task :install do sh "sudo ruby setup.rb install" end ### Gem # Issue has been fixed in Psych, see: # https://github.com/tenderlove/psych/commit/fe65329ce9ece399d61dadf1610e342ff456654e # #if !defined?(YAML::ENGINE).nil? && YAML::ENGINE.respond_to?(:yamler) # YAML::ENGINE.yamler = 'syck' #end Hoe.plugin :bundler Hoe.plugin :yard Hoe.spec 'i18n-inflector' do developer I18n::Inflector::DEVELOPER, I18n::Inflector::EMAIL self.version = I18n::Inflector::VERSION self.rubyforge_name = I18n::Inflector::NAME self.summary = I18n::Inflector::SUMMARY self.description = I18n::Inflector::DESCRIPTION self.url = I18n::Inflector::URL self.test_globs = %w(test/**/*_test.rb) self.remote_rdoc_dir = '' self.rsync_args << '--chmod=a+rX' self.readme_file = 'README.rdoc' self.history_file = 'docs/HISTORY' extra_deps << ['i18n', '>= 0.4.1'] extra_dev_deps << ['test_declarative', '>= 0.0.5'] << ['yard', '>= 0.7.2'] << ['rdoc', '>= 3.8.0'] << ['bundler', '>= 1.0.15'] << ['hoe-bundler', '>= 1.1.0'] unless extra_dev_deps.flatten.include?('hoe-yard') extra_dev_deps << ['hoe-yard', '>= 0.1.2'] end end task 'Manifest.txt' do puts 'generating Manifest.txt from git' sh %{git ls-files | grep -v gitignore > Manifest.txt} sh %{git add Manifest.txt} end task 'ChangeLog' do sh %{git log > ChangeLog} end desc "Fix documentation's file permissions" task :docperm do sh %{chmod -R a+rX doc} end ### Sign & Publish desc "Create signed tag in Git" task :tag do sh %{git tag -s v#{I18n::Inflector::VERSION} -m 'version #{I18n::Inflector::VERSION}'} end desc "Create external GnuPG signature for Gem" task :gemsign do sh %{gpg -u #{I18n::Inflector::EMAIL} -ab pkg/#{I18n::Inflector::NAME}-#{I18n::Inflector::VERSION}.gem \ -o pkg/#{I18n::Inflector::NAME}-#{I18n::Inflector::VERSION}.gem.sig} end ruby-i18n-inflector-2.6.6/ci/000077500000000000000000000000001204270775600156535ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/ci/i18n-inflector.gemspec000066400000000000000000000030001204270775600217530ustar00rootroot00000000000000# encoding: utf-8 lib = File.expand_path('../../lib/', __FILE__) $:.unshift lib unless $:.include?(lib) require 'i18n-inflector/version' if !defined?(YAML::ENGINE).nil? && YAML::ENGINE.respond_to?(:yamler) YAML::ENGINE.yamler = 'syck' end Gem::Specification.new do |s| s.name = I18n::Inflector::NAME s.version = I18n::Inflector::VERSION s.authors = [I18n::Inflector::DEVELOPER] s.email = I18n::Inflector::EMAIL s.homepage = I18n::Inflector::URL s.summary = I18n::Inflector::SUMMARY s.description = I18n::Inflector::DESCRIPTION s.files = Dir.glob("{ci,lib,spec,docs}/**/**") + %w(Gemfile .yardopts README.rdoc LGPL-LICENSE ChangeLog Manifest.txt) s.extra_rdoc_files = ["README.rdoc", "docs/USAGE", "docs/EXAMPLES", "docs/TODO", "docs/HISTORY", "docs/LEGAL", "docs/LGPL", "docs/COPYING"] s.rdoc_options = [ "--charset=UTF-8", "--main", "README.rdoc"] s.platform = Gem::Platform::RUBY s.require_path = 'lib' s.rubyforge_project = '[none]' s.required_rubygems_version = '>= 1.4.0' s.specification_version = 3 s.add_dependency 'i18n', '>= 0.4.1' s.add_development_dependency 'test_declarative', '>= 0.0.5' s.add_development_dependency 'rspec', '>= 2.3.0' s.add_development_dependency 'yard', '>= 0.7.2' s.add_development_dependency 'bundler', '>= 1.0.15' s.add_development_dependency 'hoe-yard', '>= 0.1.2' s.add_development_dependency 'hoe-bundler', '>= 1.1.0' end ruby-i18n-inflector-2.6.6/ci/i18nv4-Gemfile000066400000000000000000000007671204270775600202070ustar00rootroot00000000000000# -*- ruby -*- source :gemcutter gem "i18n", ">=0.4.1", "<0.5.0" gem "hoe-yard", ">=0.1.2", :group => [:development, :test] gem "test_declarative", ">=0.0.4", :group => [:development, :test] gem "yard", ">=0.6.4", :group => [:development, :test] gem "bundler", ">=1.0.7", :group => [:development, :test] gem "hoe-bundler", ">=1.0.0", :group => [:development, :test] gem "hoe-yard", ">=0.1.2", :group => [:development, :test] gem "hoe", ">=2.10.0", :group => [:development, :test] # vim: syntax=ruby ruby-i18n-inflector-2.6.6/ci/i18nv4-Gemfile.lock000066400000000000000000000006761204270775600211350ustar00rootroot00000000000000GEM remote: http://rubygems.org/ specs: hoe (2.16.0) rake (~> 0.8) hoe-bundler (1.1.0) hoe (>= 2.2.0) hoe-yard (0.1.2) yard (>= 0.2.3.1) i18n (0.4.2) rake (0.9.2.2) test_declarative (0.0.5) yard (0.7.5) PLATFORMS ruby DEPENDENCIES bundler (>= 1.0.7) hoe (>= 2.10.0) hoe-bundler (>= 1.0.0) hoe-yard (>= 0.1.2) i18n (>= 0.4.1, < 0.5.0) test_declarative (>= 0.0.4) yard (>= 0.6.4) ruby-i18n-inflector-2.6.6/data.tar.gz.sig000066400000000000000000000004001204270775600200730ustar00rootroot00000000000000M3tF9 ɔeVۉqvJJ:C8yo֕:GÜl 縁tlTɼ=rŸ|\X0<|X:/me*dL6?JnS23'9lJ%w:{;/>#śVL6n?]OY N~ { :inflections => { :gender => { :m => 'male', :f => 'female', :n => 'neuter', :default => :n }, :@person => { :i => 'i', :u => 'you', :he => 'he', :she => 'she', :it => 'it', :you => :@u } }}) I18n.backend.store_translations(:en, 'welcome' => 'Dear @{f:Lady|m:Sir|n:You|All}!') I18n.backend.store_translations(:en, 'sayit' => '@person{i:I|u:You|he:He|she:She|it:It}{ }{i:am|u:are|he,she,it:is}') I18n.backend.store_translations(:en, 'tobe' => '%{person} @person{i:am|u:are|he,she,it:is}') I18n.locale = :en == Simple interpolation When no option, it falls back to default token (n): I18n.translate('welcome') #=> "Dear You!" When :m, it interpolates the m token's value: I18n.translate('welcome', :gender => :m) #=> "Dear Sir!" When unknown, it falls back to default token (n): I18n.translate('welcome', :gender => :unknown) #=> "Dear You!" When +nil+, it falls back to default token (n): I18n.translate('welcome', :gender => nil) #=> "Dear You!" === inflector_unknown_defaults When :inflector_unknown_defaults is false, it falls back to free text: I18n.translate('welcome', :gender => :unknown, :inflector_unknown_defaults => false) #=> "Dear All!" It also falls back when an inflection option is nil or empty: I18n.translate('welcome', :gender => nil, :inflector_unknown_defaults => false) #=> "Dear All!" == Named pattern Regular inflection option will be used if there is no strict inflection option: I18n.translate('sayit', :person => :i) #=> "I am" Strict inflection option has precedence: I18n.translate('sayit', :person => :i, :@person => :u) #=> "You are" Strict inflection option has precedence even if the option's value is messy: I18n.translate('sayit', :person => :i, :@person => :unknown) #=> " " === Using with interpolation argument First part is interpolated using standard interpolation variable while second part of the sentence comes from interpolation of inflection pattern. The same option is feeding both engines. I18n.translate('tobe', :person => :i) #=> "i am" Note funny thing. The interpolation variable +test+ takes value (+i+) from +:person+ while option +:@person+ takes precedence when it comes to inflections. Keep that in mind when combining regular interpolation variables with named patterns while using the same variable for controlling both. Choose non-strict notation for an option then. I18n.translate('tobe', :person => :i, :@person => :u) #=> "i are" No free text in 'tobe' so the empty string is interpolated when strict kind is unknown: I18n.translate('tobe', :person => :i, :@person => :unknown) #=> "i " == API === Getting kinds Getting all known regular kinds: I18n.inflector.kinds #=> [:gender] Getting all known strict kinds: I18n.inflector.strict.kinds #=> [:person] Getting all known kinds for language 'pl': I18n.inflector.kinds(:pl) #=> [] === Listing all known options I18n.inflector.options.known #=> [:inflector_cache_aware, :inflector_raises, :inflector_aliased_patterns, # :inflector_unknown_defaults, :inflector_excluded_defaults] == Real-life example for Polish language Polish is highly inflected language. Additionally, position of a word in a sentence is mutually coupled with meaning. That makes it extreemly hard to create finite-state machine that would handle Polish grammar. However, flection means that the same cores are combined with suffixes and prefixes depending on many different kinds: gender, tense, form, animation, declination and more. That makes Polish (and other Slavic languages) alphabetically redundant. By interpolating common cores, prefixes and suffixes of words we're able make our patterns compact. === YAML pl: are_you_sure: "@{m,f:Jesteś pew}{m:ien|f:na}{n:Na pewno}?" i18n: inflections: gender: f: "rodzaj żeński" m: "rodzaj męski" n: "forma bezosobowa" masculine: @m facet: @m chłopak: @m feminine: @f pani: @f kobieta: @f k: @f dziewczyna: @f impersonal: @n default: n === Code # Using shorter form than listed as YAML I18n.backend.store_translations(:pl, :i18n => { :inflections => { :gender => { :f => 'f', :m=>'m', :n=>'n', :kobieta=>:@f, :facet => :@m, :default=>:n }}}) # Making use of commas makes it easy to implement DRY # and re-use some parts of the words that are the same in two or more phrases I18n.backend.store_translations(:pl, :are_you_sure => "@{m,f:Jesteś pew}@{m:ien|f:na}@{n:Na pewno}?") I18n.locale = :pl I18n.translate('are_you_sure', :gender => :kobieta) #=> "Jesteś pewna?" I18n.translate('are_you_sure', :gender => :facet) #=> "Jesteś pewien?" I18n.translate('are_you_sure') #=> "Na pewno?" # It would look like that without commas: I18n.backend.store_translations(:pl, :are_you_sure => "@{m:Jesteś pewien|f:Jesteś pewna|n:Na pewno}?") # That would also work but it's less readable. # PS: Have you ever configured Sendmail? ;-) I18n.backend.store_translations(:pl, :are_you_sure => "@{n:Na|m,f:Jesteś}{ pew}{m:ie}{n}{f:a|n:o}?") === Complex pattern usage # Store needed translations I18n.backend.store_translations(:pl, :i18n => { :inflections => { :@gender => { :f => 'f', :m => 'm', :n => 'n', :kobieta => :@f, :facet => :@m, :default => :n }, :@tense => { :t => 'teraz', :w => 'przeszły', :j => 'przyszły', :teraz => :@t, :wczoraj => :@w, :jutro => :@j, :default => :t } }}) I18n.backend.store_translations(:pl, :msg_receive => "@gender+tense{n+w:Otrzymano|Dosta}{*+t:jesz|*+j:niesz|f+w:łaś|m+w:łeś} wiadomość") I18n.locale = :pl p I18n.translate('msg_receive', :gender => :kobieta) #=> "Dostajesz wiadomość" p I18n.translate('msg_receive', :gender => :facet) #=> "Dostajesz wiadomość" p I18n.translate('msg_receive') #=> "Dostajesz wiadomość" p I18n.translate('msg_receive', :gender => :kobieta, :tense => :wczoraj) #=> "Dostałaś wiadomość" p I18n.translate('msg_receive', :gender => :facet, :tense => :wczoraj) #=> "Dostałeś wiadomość" p I18n.translate('msg_receive', :tense => :jutro) #=> "Dostaniesz wiadomość" p I18n.translate('msg_receive', :tense => :wczoraj) #=> "Otrzymano wiadomość" ==== YAML for the example above The example above may use this YAML content instead of +store_translations+: pl: msg_receive: "@gender+tense{n+w:Otrzymano|Dosta}{*+t:jesz|*+j:niesz|f+w:łaś|m+w:łeś} wiadomość" i18n: inflections: @gender: m: 'male' f: 'female' n: 'neuter' kobieta: @f facet: @m default: n @tense: t: 'teraźniejszy' w: 'przeszły' j: 'przyszły' teraz: @t wczoraj: @w jutro: @j default: @t ===== Alternative for +msg_receive+ key The +msg_receive+ might also be expressed using two infleciton keys: pl: @msg_receive_1: @kind: gender+tense @free: 'Dosta' n+w: 'Otrzymano' @msg_receive_2: @kind: gender+tense @suffix: " wiadomość" m,f,n+t: "jesz" m,f,n+j: "niesz" f+w: "łaś" m+w: "łeś" But then you have to change the translation call too, e.g.: p I18n.translate(['@msg_receive_1','@msg_receive_2'], :gender => :kobieta).join #=> "Dostajesz wiadomość" The split is necessary because we have two patterns here and no way to express them as one inflection key. == To be or not to be Here is the example pattern that inflects English to be by tense, person and grammatical number: en: i18n: inflections: @person: 1: first 2: second 3: third i: :@1 you: :@2 He: :@3 She: :@3 it: :@3 @tense: past: past present: present now: @present default: present @num: s: singular p: plural default: s to_be: > @num+person{s+1:I|*+2:You|s+3:%{person}|p+3:They|p+1:We} @num+person+tense{s+1+present:am|s+2+present:are|s+3+present:is| p+*+present:are|s+1,3+past:was|p+*+past:were|s+2+past:were} And the code that prints all possible combinations: [:i, :you, :He, :She, :It].each do |person| puts I18n.translate(:to_be, :num => :s, :person => person, :tense => :now) + "\t| " + I18n.translate(:to_be, :num => :s, :person => person, :tense => :past) end puts (1..3).each do |person| puts I18n.translate(:to_be, :num => :p, :person => person, :tense => :now) + " | " + I18n.translate(:to_be, :num => :p, :person => person, :tense => :past) end to be continued… ruby-i18n-inflector-2.6.6/docs/HISTORY000066400000000000000000000151711204270775600173010ustar00rootroot00000000000000=== 2.6.6 / 2012-03-14 * major enhancements * Added support for integers as token names * Added nice example of "to be" inflection in English * minor enhancements * Documentation updated * Added instance method empty? to LazyEnumerator === 2.6.5 / 2012-03-10 * minor enhancements * Back to Psych YAML parser while creating gem === 2.6.4 / 2012-03-10 * minor enhancements * Changed documentation examples for calling rake * Tested against Ruby 1.9.3-p0 * Updated dependencies * Updated copyright notices * Started codenaming each version (including minor version numbers) === 2.6.2 / 2011-08-07 * minor bugfixes * Applied a workaround against a buggy parser in Rubygems === 2.6.1 / 2011-07-10 * major enhancements * Handling of methods and Proc objects used to obtain inflection options improved by caching * Added caching for methods reporting locales that support inflection * Lazy operations optimized * minor enhancements * Fixed documentation links * Dependencies updated === 2.6.0 / 2011-03-08 * minor enhancements * Strings concatenation optimized * API methods simplified * Added lazy iteration methods to I18n::Inflector::InflectionData and I18n::Inflector::InflectionData_Strict * Added lazy iteration methods to I18n::Inflector::API and I18n::Inflector::API_Strict === 2.5.1 / 2011-02-25 * minor enhancements * Added the ability to use symbols as descriptions (values) in a configuration === 2.5.0 / 2011-02-24 * major enhancements * Interpolation wrapper refactored; works with many types of results * Added :inflector_interpolate_symbols switch * minor enhancements * Added TOKENS_RESTR, MULTI_RESTR and PATTERN_RESTR configuration constants * Dependencies updated * major bugfixes * Fixed interpolation of Arrays * minor bugfixes * Fixed pattern filtering when locale is invalid or not inflected === 2.4.0 / 2011-02-23 * major enhancements * Added nested translations (collections) support * Added :inflector_traverses switch === 2.3.1 / 2011-02-14 * major enhancements * Added wildcard tokens support * Proc and Method kind of objects might be passed as inflection options * minor enhancements * Added I18n::Inflector::Config::Markers::STRICT_KIND (character used when passing strict kinds) * Important documentation moved to the USAGE file * minor bugfixes * Fixed parsing of named patterns when :inflector_excluded_defaults is used * Fixed links in documentation === 2.2.0 / 2011-02-09 * major enhancements * Added loud tokens support * Added complex patterns support * Added key-based inflection support * Added :cache_aware switch * Improved validation of token and kind identifiers * minor enhancements * Refactored error reporting code * Refactored options gathering code * Removed magic symbols and strings * Removed intermediate array from LazyHashEnumerator#to_h * Added multiple patterns support (syntactic sugar) * Added I18n::Inflector::Config module * Added I18n::Inflector::LazyArrayEnumerator class * Added I18n::Inflector::HSet class for keeping collections of data * Added error classes: I18n::InvalidInflectionOption and I18n::InvalidInflectionKind * Interpolation method moved to I18n::Inflector::Interpolate module * All inflection related exceptions now have the attribute "key" containing key name * major bugfixes * Fixed handling of missing inflection option when :inflector_raises is set * minor bugfixes * Fixed interpolation when :excluded_defaults is on and a kind is strict * Fixed interpolation when pattern is escaped and locale is not inflected * Enabled filtering of reserved names in options * Enabled filtering of inflection options for options that go to original translate method * Updated documentation in a section describing options * Fixed some examples === 2.1.0 / 2011-01-27 * major enhancements * Added named patterns support (strict kinds) * API improved: major class is I18n::Inflector::API * Added class I18n::Inflector::API_Strict for accessing strict inflections * Added lazy enumerators for internal hashes, which saves some memory * Added strict kinds detection (@-style kind names) to most of the methods from main API class * Added new error classes: InflectionOptionNotFound and InflectionOptionIncorrect * Added class for handling inflection data for strict kinds: I18n::Inflector::InflectionData_Strict * Inflections for regular and strict kinds are handled by separate data structures and objects * Documentation updated * minor bugfixes * Error reporting fixed in some places * Strict kinds interpolation improved * Removed some slow blocks * Loading inflection tokens cleaned up === 2.0.1 / 2011-01-15 * minor enhancements * Documentation updated * minor bugfixes * Fixed duplicated dependency generation in Hoe === 2.0.0 / 2011-01-14 * major enhancements * API changed * Added a class for keeping internal inflection data: I18n::Inflector::InflectionData * Added a class for keeping options: I18n::Inflector::InflectionOptions * Added a class for controlling the inflection: I18n::Inflector::Core * Added a module for utilities: I18n::Inflector::Util * Added token groups support * Added inversed matching of tokens in inflection patterns * Added support for aliases in inflection patterns * Most of the methods from I18n::Backend::Inflector moved to Core submodule * Most methods rewritten === 1.0.10 / 2011-01-10 * major bugfixes * Removed cause of infinite loops while initializing translations * Disabled lookup from being used before translations are initialized * Fixed initialization routine (dangerous typo when setting booleans) * minor enhancements * Switched to lazy loading of inflection data for certain locales === 1.0.8 / 2011-01-08 * major enhancements * Enabled escaping of patterns using @@{pattern} or \@{pattern} === 1.0.7 / 2011-01-07 * major bugfixes * Fixed interpolation when a translated string begins with a pattern === 1.0.6 / 2010-12-30 * minor enhancements * Added API method inflection_kind(token) * Added API method inflection_true_token(token) * Added API method inflected_locale(locale) === 1.0.5 / 2010-12-29 * major enhancements * Compatible with i18n >= 0.4.1 === 1.0.4 / 2010-12-27 * minor enhancements * Documentation updated === 1.0.3 / 2010-12-25 * major enhancements * YARD documentation updated with metatags * minor enhancements * Some changes in accessors for interpolation switches === 1.0.2 / 2010-12-22 * minor enhancements * Switched to YARD documentation * Tests simplified * Depandencies simplified === 1.0.0 / 2010-12-22 * 1 major enhancement * Birthday! ruby-i18n-inflector-2.6.6/docs/LEGAL000066400000000000000000000005701204270775600167610ustar00rootroot00000000000000LEGAL NOTICE INFORMATION ------------------------ i18n-inflector is Copyright (C) 2011,2012 by Paweł Wilk. i18n-inflector is copyrighted software owned by Paweł Wilk (pw@gnu.org). You may redistribute and/or modify this software as long as you comply with either the terms of the LGPL (see the file {file:docs/LGPL}), or Ruby's license (see the file {file:docs/COPYING}). ruby-i18n-inflector-2.6.6/docs/LGPL000066400000000000000000000163351204270775600167010ustar00rootroot00000000000000 = GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. < http://fsf.org/ > Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. === 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. === 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. === 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. === 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. === 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) === 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. === 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ruby-i18n-inflector-2.6.6/docs/TODO000066400000000000000000000003451204270775600167020ustar00rootroot00000000000000== Near future == Distant future * split interpolate_core and make it more reusable by raw data (e.g. pattern content) * allow different descriptions for aliases pointing to the same token, e.g.: now: @present ="description" ruby-i18n-inflector-2.6.6/docs/USAGE000066400000000000000000001045111204270775600170010ustar00rootroot00000000000000= Usage of the I18n Inflector The {I18n::Inflector I18n Inflector} contains inflection classes and modules for enabling the inflection support in I18n translations. It is also used by the module called {I18n::Backend::Inflector} that overwrites the translate method from the Simple backend so it will interpolate additional inflection data present in translations. That data may appear in *patterns* enclosed within @{ and } symbols. Each pattern consist of *tokens* and respective *values*. One of the value will be used depending on additional data passed to the translate method. That additional data is called inflection options. == Usage require 'i18-inflector' i18n.translate('welcome', :gender => :f) # => Dear Madam i18n.inflector.kinds # => [:gender] i18n.inflector.true_tokens.keys # => [:f, :m, :n] See the {file:docs/EXAMPLES} for more information about real-life usage of Inflector. == Inflection pattern An example inflection pattern stored under a translation key looks like: welcome: "Dear @{f:Madam|m:Sir|n:You|All}" The +f+, +m+ and +n+ are inflection *tokens* and +Madam+, +Sir+, +You+ and +All+ are *values*. Only one value is going to replace the whole pattern. To select which one an additional option is used. That option must be passed to the translate method. There are also so called named patterns that will be explained later. == Configuration To recognize tokens present in patterns keys grouped in the scope called +inflections+ for the given locale are used. For instance (YAML format): en: i18n: inflections: gender: f: "female" m: "male" n: "neuter" man: @m woman: @f default: n Elements in the example above are: * +en+: language * +i18n+: configuration scope * +inflections+: inflections configuration scope * +gender+: kind scope * +f+, +m+, +n+: inflection tokens * "male", "female", "neuter": tokens' descriptions * +woman+, +man+: inflection aliases * @f, @m: pointers to real tokens * +default+: default token for a kind +gender+ === Note about YAML parsing The example above is not compatible with Psych parser, which is used by Rails 3. There are two ways to solve that problem. First is to make a change in a YAML file and replace any value that has special meaning with a symbol: en: i18n: inflections: gender: f: "female" m: "male" n: "neuter" female: :@f male: :@m default: :n Second way is to use other parser by adding to +config/boot.rb+: require 'yaml' YAML::ENGINE.yamler = 'syck' Note that all the examples in this documentation use the less strict format. If you will encounter any parsing problems in your application then change all problematic inflection values in YAML files into symbols. === Kind Note the fourth scope selector in the example above (+gender+). It's called the *kind* and contains *tokens*. We have the kind +gender+ to which the inflection tokens +f+, +m+ and +n+ are assigned. You cannot assign the same token to more than one kind. Trying to do that will raise {I18n::DuplicatedInflectionToken} exception. This is required in order to keep patterns simple and tokens interpolation fast. Kind is also used to instruct {I18n::Backend::Inflector#translate} method which token it should pick. This is done through options and will be explained later. There is also a class of kind called strict kind used by named patterns; that will be explained later. === Tokens The token is an element of a pattern. Any pattern may have many tokens of the same kind separated by vertical bars. Optionally tokens might be groupped using commas (these are token groups; that will be explained later). Each token name (or a group of tokens) used in a pattern should end with colon sign. After this colon a value should appear (or an empty string). Tokens also appear in a configuration data. They are assigned to kinds. Token names must be unique across all kinds, since it would be impossible for interpolation routine to guess a kind of a token present in a pattern. There is however a class of kinds called strict kinds, for which tokens must be unique only within a kind. The named patterns that are using strict kinds will be explained later. === Aliases Aliases are special tokens that point to other tokens. By default they cannot appear in inflection patterns but they are fully recognized in options that are be passed to the translation method. Aliases might be helpful in multilingual applications that are using a fixed set of values passed through options to describe some properties of messages, e.g. +masculine+ and +feminine+ for a grammatical gender. Translators will then use their own tokens (like +f+ and +m+ for English) to produce pretty and intuitive patterns. For example: if some application uses database with gender assigned to a user which may be +male+, +female+ or +none+, then a translator may find it useful to map impersonal token (none) to the +neuter+ token, since in translations for his language the neuter gender is in use. Here is the example of such situation: en: i18n: inflections: gender: male: "male" female: "female" none: "impersonal form" default: none pl: i18n: inflections: gender: k: "female" m: "male" n: "neuter" male: @k female: @m none: @n default: none In the case above Polish translator decided to use neuter instead of impersonal form when +none+ token will be passed through the option +:gender+ to the translate method. He also decided that he will use +k+, +m+ or +n+ in patterns, because the names are short and correspond to gender names in Polish language: +k+ for 'kobieta' (woman), +m+ for 'mężczyzna' (man), +n+ for 'nijaki' (neuter). Aliases may point to other aliases. While loading inflections they will be internally shortened and they will always point to real tokens, not other aliases. === Default token There is a special token called the +default+, which points to a token that should be used if the interpolation routine cannot deduce which one it should use because a proper option was not given. Default tokens may point to aliases and may use aliases' syntax, e.g.: default: @man === Descriptions The values of keys in the example (+female+, +male+ and +neuter+) are *descriptions* which usually are not used by the interpolation routine but might be helpful (e.g. in UI). For obvious reasons you cannot describe aliases. == Interpolation The value of each token present in a pattern is to be picked by the interpolation routine and will replace the whole pattern, when a token name from that pattern matches the given value of an option passed to the {I18n.translate} method. === Inflection option The mentioned option is called the inflection option. Its name should be the same as a *kind* of tokens used within a pattern. The first token in a pattern determines the kind of all tokens used in that pattern. You can pass many inflection options, each one designated for transporting a token of a different kind. ==== Examples *YAML:* Let's assume that the translation data in YAML format listed below is used in any later example, unless other inflections are given. en: i18n: inflections: gender: m: "male" f: "female" n: "neuter" default: n welcome: "Dear @{f:Madam|m:Sir|n:You|All}" *Code:* I18n.translate('welcome', :gender => :m) # => "Dear Sir" I18n.translate('welcome', :gender => :unknown) # => "Dear All" I18n.translate('welcome') # => "Dear You" In the second example the fallback value +All+ was interpolated because the routine had been unable to find the token called +:unknown+. That differs from the latest example, in which there was no option given, so the default token for a kind had been applied (in this case +n+). ==== Inflection options as Methods or Procs The inflection option may contain an object that is a kind of Method or a Proc. The token will be obtained by calling the given method or a block when interpolation routine will need it. The passed method or a block should return an object that is a kind of Symbol. It will be used as an inflection token. Optionally the inflection method may make use of a block that is passed to it. Currently two parameters can be obtained using the keyword +yield+. Fist is the currenty parsed kind (including +@+ character in case of a strict kind) and second is the locale; both are the kind of Symbol. Example: def get_gender kind, locale = yield # optional :n # return token n end translate('welcome', :gender => method(:get_gender)) In case of Proc, the arguments are passed in a more comprehensive way, as parameters passed to a block. Such a block must handle exactly two arguments: p = lambda{ |kind, locale| :m } translate('welcome', :gender => p) Note that if there will be any error that causes exception to be raised by such a method or a block then it will be raised regardless of +:inflector_raises+ option. === Local fallbacks (free text) The fallback value will be used when none of the tokens contained within a pattern can be interpolated. Be aware that enabling extended error reporting makes it unable to use fallback values in most cases. Local fallbacks will then be applied only when the given option contains a proper value for some kind but it's just not present in a pattern, for example: *YAML:* en: i18n: inflections: gender: n: 'neuter' o: 'other' welcome: "Dear @{n:You|All}" *Code:* I18n.translate('welcome', :gender => :o, :inflector_raises => true) # => "Dear All" # since the token :o was configured but not used in the pattern === Bad and empty tokens in options If an option containing token is not present at all then the interpolation routine will try the default token for a processed kind, if the default token is present in a pattern. The same thing will happend if the option is present but its value is malformed, unknown, empty or +nil+. If the default token is not present in a pattern or is not defined in a configuration data then the processing of a pattern will result in an empty string or in a local fallback value if there is a free text placed in a pattern. You can change this default behavior and force inflector not to use a default token when a value of an option for a kind is malformed, unknown, empty or +nil+ but only when it's not present. To do that you should set option +:inflector_unknown_defaults+ to +false+ and pass it to the translate method. Other way is to set this switch globally using the {I18n::Inflector::InflectionOptions#unknown_defaults}. === Unmatched tokens in options It might happend that there will be a default token present in a pattern but the given inflection option will cause some other token to be picked up, which however won't be present in this pattern (although it will be correct and assigned to the currently processed kind). In such case the given free text or an empty string will be generated. You may change that behavior by passing +:inflector_excluded_defaults+ option set to +true+ or by setting the global option called {I18n::Inflector::InflectionOptions#excluded_defaults}. If this option is set then any unmatched (excluded but correct) token given in an inflection option will cause the default token's value to be picked up (of course if a default token will be present in a pattern). === Mixing inflection and standard interpolation patterns The Inflector allows you to include standard %{} patterns inside of inflection patterns. The value of a standard interpolation variable will be evaluated and interpolated *before* processing an inflection pattern. For example: *YAML:* Note: Uses inflection configuration given in the first example. en: hi: "Dear @{f:Lady|m:%{test}}!" *Code:* I18n.t('hi', :gender => :m, :locale => :xx, :test => "Dude") # => Dear Dude! === Token groups It is possible to assign some value to more than one token in a patterns. You can create group of tokens by separating them using commas. The comma has the meaning of logical OR. *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "Hello @{m,f:Ladies and Gentlemen|n:You}!" *Code:* I18n.t('welcome', :gender => :f) # => Hello Ladies and Gentlemen! === Inversed matching of tokens You can place exclamation mark before a token that should be matched negatively. Its value will be used for a pattern if the given inflection option contains other token. You can use inversed matching of tokens in token groups but note that putting more than one inversed token to a group will cause the expression to mach every time. *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "Hello @{!m:Ladies|n:You}!" *Code:* I18n.t('welcome', :gender => :n) # => Hello Ladies! I18n.t('welcome', :gender => :f) # => Hello Ladies! I18n.t('welcome', :gender => :m) # => Hello ! === Wildcard tokens You may use the wildcard character, a star (+*+), in place of token group to create a virtual token that matches any token of a parsed kind. For example: *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "Hello @{n:you|*:ladies and gentlemen}!" *Code:* I18n.t('welcome', :gender => :n) # => Hello you! I18n.t('welcome', :gender => :f) # => Hello ladies and gentlemen! Note that for simple patterns you can use free text instead, which works almost the same way with one significant difference: free text will be evaluated as the last expression, regardless of its placement. On the contrary a wildcard token will be evaluated as any other token group and may not be used if any previously tested token will match (like +n+ in the example above). While a wildcard token is processed then the interpolation routine will validate if the required inflection option exists and if it contains a proper token. Using wildcard token is like using a token group for any other token group containing all possible true tokens in it. In case of regular patterns containing just a wildcard token alone there is no way to easily decide which kind the expression refers to. To deduce it the first valid inflection option will be used. In order to work it must contain some valid token identifier. If the token identifier is invalid and there are more inflection options then they are tried. Wildcard tokens are useful in so called complex patterns which will be explained later. === Loud tokens Sometimes there might be a need to use descriptions of matching tokens instead of some given values. Use loud tokens to achieve that. Any matching token in a pattern that has tilde symbol (+~+) set as its value will be replaced by its description. In case of undescribed aliases, the description from a target token will be used. *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "Hello @{m:~|n:~}!" *Code:* I18n.t('welcome', :gender => :n) # => Hello neuter! I18n.t('welcome', :gender => :f) # => Hello female! To use tilde symbol as the only value of a token you may esape it by putting a backslash in front of the symbol. Using loud token with wildcard token will result in a description of first matching token. === Aliases in a pattern Normally it is possible to use in patterns only true tokens, not aliases. However, if you feel lucky and you're not affraid of messy patterns you can use the switch {I18n::Inflector::InflectionOptions#aliased_patterns} or pass corresponding +:inflector_aliased_patterns+ option to the translate method. === Escaping a pattern If there is a need to translate something that accidentally matches an inflection pattern then the escape symbols can be used to disable the interpolation. These symbols are \\ and +@+ and they should be placed just before a pattern that should be left untouched. For instance: *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "This is the @@{pattern}!" *Code:* I18n.t('welcome', :gender => :m, :locale => :xx) # => This is the @{pattern}! === More about applying aliases It may seem very easy and attractive to use aliases in environments where inflection option's value comes from a user. In such cases aliases may be used as database that translates common words to inflection tokens that have meanings. For example a user may enter a gender in some text field and it will be used as value of inflection option. To map different names (e.g. male, boy, sir, female, girl, lady) to exact inflection tokens the aliases would be used. Note hovewer, that you can make use of I18n.inflector.true_token method (see {I18n::Inflector::API#true_token}) that will resolve any alias, and then use that data to feed an inflection option (e.g. +:gender+). In such scenario you don't have to rely on resolving aliases any time translation is performed and you will gain some speed. == Named patterns A named pattern is a pattern that contains name of a kind that tokens from a pattern are assigned to. It looks like: welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}" === Configuring named patterns To recognize tokens present in named patterns, inflector uses keys grouped in the scope called +inflections+ for the given locale. For instance (YAML format): en: i18n: inflections: @gender: f: "female" woman: @f default: f Elements in the example above are: * +en+: language * +i18n+: configuration scope * +inflections+: inflections configuration scope * +gender+: strict kind scope * +f+: inflection token * "female": token's description * +woman+: inflection alias * @f: pointer to real token * +default+: default token for a strict kind +gender+ === Strict kinds In order to handle named patterns properly a new data structure is used. It is called the strict kind. Strict kinds are defined in a configuration in a similar way the regular kinds are but tokens assigned to them may have the same names across a whole configuration. (Note that tokens of the same strict kind should still be unique.) That implies a requirement of passing the identifier of a kind in patterns when referring to such tokens. Here is the example configuration using strict kinds: en: i18n: inflections: @gender: f: "female" m: "male" n: "neuter" man: @m woman: @f default: n @title: s: "sir" l: "lady" u: "you" m: @s f: @l default: u The only thing that syntactically distinguishes strict kinds from regular kinds is a presence of the +@+ symbol. You can mix regular and strict kinds having the same names in one translation entry, but not in one inflection pattern. The proper class of kind will be picked up by interpolation method easily, since the first mentioned class uses patterns that are not named, and the second uses named patterns. ==== Strict kinds in inflection options The interpolation routine recognizes strict kinds passed as names of inflection options in almost the same way that it does for regular kinds. The only difference is that you can override usage of a regular kind inflection option (if there is any) by putting a strict kind option with the same name but prefixed by +@+ symbol. The inflection options starting with this symbol have precedence over inflection options without it; that is of course only true for strict kinds and has any effect only when both options describing kinds of the same name are present. In other words: interpolation routine is looking for strict kinds in inflection options using their names with +@+ in front. When that fails it falls back to an option named like the strict kind but without the +@+ symbol. Examples: I18n.translate(welcome, :gender => :m, :@gender => :f) # the :f will be picked for the strict kind gender I18n.translate(welcome, :@gender => :f) # the :f will be picked for the strict kind gender I18n.translate(welcome, :gender => :f) # the :f will be picked for the strict kind gender In the example above we assume that +welcome+ is defined like that: welcome: "Dear @gender{f:Madam|m:Sir|n:You|All}" Note that for regular kinds the option named +:@gender+ will have no meaning. ==== Note for developers Strict kinds that are used to handle named patterns are internally stored in a different database and handled by similar but different API methods than regular kinds. However most of the {I18n::Inflector::API} methods are also aware of strict kinds and will call proper methods oprating on strict inflections data when the +@+ symbol is detected at the beginning of the identifier of a kind passed as an argument. For example: I18n.inflector.has_token?(:m, :@gender) will effectively call: I18n.inflector.strict.has_token?(:m, :gender) As you can see above, to access {API_Strict} methods for strict kinds (and strict kinds data) only, associated with default I18n backend, use: I18n.inflector.strict == Multiple patterns You can make use of some syntactic sugar when having more than one pattern (regular or named) in your string. To not repeat a kind identifier(s) you may join pattern contents as in the following example: welcome: "You are @gender{f:pretty|m,n:handsome}{ }{f:lady|m:sir|n:human}" As you can see there should be no spaces or any other characters between successive patterns. That's why in this example an empty pattern content is used. This is in fact a pattern containing no tokens but just a free text consisting of single space character. == Complex patterns A complex pattern is a named pattern that uses more than one inflection kind and sets of a respective tokens. The given identifiers of kinds should be separated by the plus sign and instead of single tokens there should be token sets (a tokens separated by the plus sign too). Example: welcome: "Dear @gender+number{f+s:Lady|f+p:Ladies|m+s:Sir|m+p:Gentlemen|All}" In the example above the complex pattern uses +gender+ and +number+ inflection kinds and a token set (e.g. f+s) matches when both tokens match interpolation options (e.g. :gender => :f, :number => :s). The order of tokens in sets has meaning and should reflect the order of declared kinds. Note, that the count of tokens in each set should reflect the count of kinds that are used. Otherwise the interpolation routine will interpolate a free text (if given) or an empty string. If the switch {InflectionOptions#raises} is on then the {I18n::ComplexPatternMalformed} exception will be raised. The inflection tokens used in sets may make use of any features mentioned before (defaults, excluded defaults, negative matching, token groups, aliases, aliased patterns, loud tokens, wildcards). === Loud tokens in complex patterns In case of loud tokens (having values taken from their descriptions), the complex pattern will be replaced by the descriptions of matching tokens joined with a single space character. So, for instance, when the translation data looks like: i18n: inflections: @person: i: 'I' u: 'You' @tense: now: 'am' past: 'were' welcome: "@person+tense{i+now:~|u+past:~}" the translate method will give the following results: I18n.translate('welcome', :person => :i, :tense => :now) # => "I am" I18n.translate('welcome', :person => :you, :tense => :past) # => "You were" This example is abstract, since the combination of +:i+ and +:past+ will result in i were string, which is probably something unexpected. To achieve that kind of logic simply use combined patterns with the given values instead of loud tokens. === Wildcard tokens in complex patterns The wildcard tokens might be extremely helpful in complex patterns since there is one shared free text for a whole pattern yet there might be a need to match any token for some subkind. For example: welcome: @person+tense{i+present:am|u+present:are|*+present:is} Note that in the example above +*+ matches 'i', 'you', 'he', 'she' and 'it' but 'i' and 'u' are effectively matched before. The equivalent pattern without a wildcard token would look like: welcome: @person+tense{i+present:am|u+present:are|i,u,he,she,it+present:is} == Inflection keys There is a way of storing inflected strings in keys instead of patterns. To use it you should simply assign subkeys to some translation key instead of string containing a pattern. The key-based inflection group is contained within a key which name begins with the +@+ symbol. The translation key containing a pattern: welcome: "Dear @{f:Lady|m:Sir|n:You|All}!" Can be easily written as: @welcome: f: "Lady" m: "Sir" n: "You" @free: "All" @prefix: "Dear " @suffix: "!" You can also use strict kind or even the inflection sets, token groups, etc.: welcome: "@gender+tense{f+past:She was|m+present:He is|n+future:You will be}" Can be written as: @welcome: f+past: "She was" m+present: "He is" n+future: "You will be" @kind: "gender+tense" There are special, optional subkeys that may give you more control over inflection process. These are: * +@kind+: a kind or kinds in case of strict kinds * +@prefix+: a prefix to be put before the interpolated data * +@suffix+: a suffix to be put after the interpolated data * +@free+: a free text that is to be used when no token will match === Limitations Inflection keys look compact and clean but obviously you cannot use the key-based inflection to simply replace a string containing more than one inflection pattern. Also, you have to be very careful when using this method with Ruby 1.8 because the order of processed token sets may change. That may break the logic in case of inflection sets where order has meaning (e.g. tokens with inverted matching). == Errors By default the module will silently ignore non-critical interpolation errors. You can turn off this default behavior by passing +:inflector_raises+ option set to +true+. Note that most errors is reported because of wrong data in patterns or in configuration. In case of inflection options only malformed, empty or +nil+ values are reported when the mentioned switch is turned on. For inflection options containing unknown tokens no errors are generated. === Usage of +:inflector_raises+ option *YAML:* Note: Uses inflection configuration given in the first example. en: welcome: "Dear @{m:Sir|f:Madam|Fallback}" *Code:* I18n.t('welcome', :inflector_raises => true) # => I18n::InflectionOptionNotFound: en.welcome: # @{m:Sir|f:Madam|Fallback}" - required option :gender was not found === Exception meanings Here are the exceptions that may be raised when the option +:inflector_raises+ is set to +true+: * {I18n::InvalidInflectionToken I18n::InvalidInflectionToken} * {I18n::InvalidInflectionKind I18n::InvalidInflectionKind} * {I18n::InvalidInflectionOption I18n::InvalidInflectionOption} * {I18n::MisplacedInflectionToken I18n::MisplacedInflectionToken} * {I18n::InflectionOptionNotFound I18n::InflectionOptionNotFound} * {I18n::InflectionOptionIncorrect I18n::InflectionOptionIncorrect} * {I18n::ComplexPatternMalformed I18n::ComplexPatternMalformed} There are also exceptions that are raised regardless of :+inflector_raises+ presence or value. These are usually caused by critical errors encountered during processing inflection data or exceptions raised by I18n. Note that the pure I18n's exceptions are not described here. * {I18n::ArgumentError I18n::ArgumentError} * {I18n::InvalidLocale I18n::InvalidLocale} * {I18n::DuplicatedInflectionToken I18n::DuplicatedInflectionToken} * {I18n::BadInflectionKind I18n::BadInflectionKind} * {I18n::BadInflectionToken I18n::BadInflectionToken} * {I18n::BadInflectionAlias I18n::BadInflectionAlias} === Exception hierarchy I18n::ArgumentError | `-- I18n::InvalidLocale | `-- I18n::InflectionException | `-- I18n::InflectionPatternException | | | |-- I18n::InvalidInflectionToken | |-- I18n::InvalidInflectionKind | |-- I18n::MisplacedInflectionToken | |-- I18n::ComplexPatternMalformed | `-- I18n::InvalidOptionForKind | |-- I18n::InflectionOptionNotFound | `-- I18n::InflectionOptionIncorrect | `-- I18n::InflectionConfigurationException | |-- I18n::DuplicatedInflectionToken |-- I18n::BadInflectionAlias |-- I18n::BadInflectionToken `-- I18n::BadInflectionKind == Reserved names and characters Some strings cannot be used as names and/or identifiers of kinds and tokens. There are also some reserved characters that cannot be used within them. === Reserved keys Reserved keys, that cannot be used as names of inflection options and as names of kinds in the configuration are available after issuing: I18n::Inflector::Config::Reserved::KEYS.to_a Here is the current list: :scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :raise, :rescue_format, :inflector_cache_aware, :inflector_raises, :inflector_aliased_patterns, :inflector_unknown_defaults, :inflector_excluded_defaults. Additionally all Symbols or Strings beginning with +inflector_+ are prohibited, since they are reserved as controlling options. === Reserved characters All characters that have special meaning (operators and markers) are not allowed in patterns, in configuration and in options. ==== Reserved characters in kinds ===== Passed as inflection options * *Constant:* {I18n::Inflector::Config::Reserved::Kinds::OPTION} * *List:* + | : ! { } and , (comma). ===== Given in a configuration * *Constant:* {I18n::Inflector::Config::Reserved::Kinds::DB} * *List:* + | : ! { } and , (comma). ===== Placed in patterns * *Constant:* {I18n::Inflector::Config::Reserved::Kinds::PATTERN} * *List:* + | : , ! @ { } and , (comma). ==== Reserved characters in tokens ===== Passed as values of inflection options * *Constant:* {I18n::Inflector::Config::Reserved::Tokens::OPTION} * *List:* * + | : ! @ { } and , (comma). ===== Given in a configuration * *Constant:* {I18n::Inflector::Config::Reserved::Tokens::DB} * *List:* * + | : ! @ { } and , (comma). ===== Placed in patterns * *Constant:* {I18n::Inflector::Config::Reserved::Tokens::PATTERN} * *List:* + | : ! @ { } and , (comma). == Operators and markers Here is more formal definition of operators and markers used in patterns. === Pattern @[kind][+kind ...]{token_set[|token_set ...][|free_text]} * +@+ is the pattern marker * +{+ and +}+ are pattern delimiters * +free_text+ is an optional free text value * +kind+ is a kind identifier * + is the +AND+ operator that joins kinds (produces complex kinds) ==== +token_set+ *|token_group[+token_group ...]:value * +:+ is the +ASSIGNMENT+ operator * +value+ is a value to be picked up then a token set matches; value may also be the loud marker (+~+) * + is the +AND+ operator that joins many token groups into a set * +*+ is the +WILDCARD+ operator ===== +token_group+ [!]token[,[!]token ...] * +token+ is a token identifier * +!+ is the +NOT+ operator * +,+ is the +OR+ operator === Operator precedence * Single token level * +NOT+ operators for inversed matching of tokens (!) * +OR+ operators for joining tokens into token groups (,) * Token group level * +WILDCARD+ operators for matching any token (*) * +AND+ operators for joining token groups into sets (+) * Token set level * +ASSIGNMENT+ operators for assigning values to token sets (:) * +OR+ operators for separating token sets and/or free texts (|) * Pattern name level * +AND+ operators for kind identifiers (+) * Pattern level * Pattern marker and pattern delimiters == Classes and relations === Library contents * Module {I18n::Inflector} containing everything * Class {I18n::Inflector::API} used to create inflector object attached to I18n backend (handles regular and strict kinds) * Class {I18n::Inflector::API_Strict} which instance is attached to {I18n::Inflector::API} and handles strict kinds * Class {I18n::Inflector::InflectionData} used to store inflection data for regular kinds and tokens * Class {I18n::Inflector::InflectionData_Strict} used to store inflection data for strict kinds and tokens * Class {I18n::Inflector::InflectionOptions} used for keeping switches and options * Class {I18n::Inflector::LazyHashEnumerator} used to manage lazy evaluation of internal data * Module {I18n::Backend::Inflector} used to alter methods of {I18n::Backend::Simple} * Several classes for error reporting === Relations * {I18n.backend} is the currently used backend and the instance of {I18n::Backend::Simple} * {I18n.backend.inflector} is the instance of {I18n::Inflector::API} attached to backend * {I18n.inflector} is the proxy module method that calls inflector for currently used backend {I18n.backend.inflector} * {I18n.backend.inflector.options} is the instance of {I18n::Inflector::InflectionOptions} and mainly it controls a behavior of interpolation method * {I18n.backend.inflector.strict} is the instance of {I18n::Inflector::API_Strict} and handles strict kinds * {I18n.backend.inflector} uses {I18n.backend.inflector.strict} to access strict kinds when it's needed * {I18n::Inflector::API} has an instance variable @idb that contains database of inflections indexed by locale * {I18n::Inflector::API_Strict} has an instance variable @idb that contains database of inflections indexed by locale * Translation databases are kind of {I18n::Inflector::InflectionData} and {I18n::Inflector::InflectionData_Strict} * When initializing translations a method from {I18n::Backend::Simple} (altered by {I18n::Backend::Inflector}) takes the loaded data, processes their i18n.inflections scope for each locale and creates database objects which are kind of {I18n::Inflector::InflectionData} and {I18n::Inflector::InflectionData_Strict}. That objects are then attached to instances of {I18n::Inflector::API} and {I18n::Inflector::API_Strict}. ruby-i18n-inflector-2.6.6/docs/rdoc.css000066400000000000000000000006141204270775600176520ustar00rootroot00000000000000@import "rdoc_base.css"; #documentation > ul:first-of-type { padding-bottom: 2em; padding-top: 1.5em; background-position: 20em 0%; background-repeat: no-repeat; } #documentation .method-description > p:first-of-type + p { margin-top: 0.5em; } #documentation .method-description > ul { margin-left: 1.2em; } #documentation .method-description > p + ul { margin-left: 1.8em; } ruby-i18n-inflector-2.6.6/lib/000077500000000000000000000000001204270775600160265ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/lib/i18n-inflector.rb000077500000000000000000000010511204270775600211150ustar00rootroot00000000000000# encoding: utf-8 require 'i18n' require 'i18n-inflector/version' require 'i18n-inflector/hset' require 'i18n-inflector/lazy_enum' require 'i18n-inflector/inflection_data_strict' require 'i18n-inflector/inflection_data' require 'i18n-inflector/options' require 'i18n-inflector/inflector' require 'i18n-inflector/config' require 'i18n-inflector/backend' require 'i18n-inflector/errors' require 'i18n-inflector/interpolate' require 'i18n-inflector/api_strict' require 'i18n-inflector/api' I18n::Backend::Simple.send(:include, I18n::Backend::Inflector) ruby-i18n-inflector-2.6.6/lib/i18n-inflector/000077500000000000000000000000001204270775600205705ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/lib/i18n-inflector/api.rb000066400000000000000000001144711204270775600216760ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains {I18n::Inflector::API} class, # which is public API for I18n Inflector. module I18n module Inflector # Instance of this class, the inflector, is attached # to I18n backend. This class contains common operations # that can be performed on inflections. It can operate # on both unnamed an named patterns (regular and strict kinds). # This class is used by backend methods to interpolate # strings and load inflections. # # It uses the databases containing instances of # {I18n::Inflector::InflectionData} and {I18n::Inflector::InflectionData_Strict} # that are stored in the Hashes and indexed by locale names. # # Note that strict kinds used to handle named patterns # internally are stored in a different database than # regular kinds. Most of the methods of this class are also # aware of strict kinds and will call proper methods handling # strict inflection data when the +@+ symbol is detected # at the beginning of the given identifier of a kind. # # ==== Usage # You can access the instance of this class attached to # default I18n backend by calling: # I18n.backend.inflector # or in a short form: # I18n.inflector # In case of named patterns (strict kinds): # I18n.inflector.strict # # @see I18n::Inflector::API_Strict The API_Strict class # for accessing inflection data for named # patterns (strict kinds). # @see file:docs/EXAMPLES The examples of real-life usage. # @api public class API < API_Strict include I18n::Inflector::Interpolate # Options controlling the engine. # # @api public # @return [I18n::Inflector::InflectionOptions] the set of options # controlling inflection engine # @see I18n::Inflector::InflectionOptions#raises # @see I18n::Inflector::InflectionOptions#unknown_defaults # @see I18n::Inflector::InflectionOptions#excluded_defaults # @see I18n::Inflector::InflectionOptions#aliased_patterns # @example Usage of +options+: # # globally set raises flag # I18n.inflector.options.raises = true # # # globally set raises flag (the same meaning as the example above) # I18n.backend.inflector.options.raises = true # # # set raises flag just for this translation # I18n.translate('welcome', :inflector_raises => true) attr_reader :options # @private def config I18n::Inflector::Config end # @private def strict @strict ||= I18n::Inflector::API_Strict.new(@idb_strict, @options) end # Initilizes the inflector by creating internal databases # used for storing inflection data and options. # # @api public def initialize super(nil, nil) @idb_strict = {} end # Creates a database for the specified locale. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @param [Symbol] locale the locale for which the inflections database is to be created # @return [I18n::Inflector::InflectionData] the new object for keeping inflection data def new_database(locale) locale = prep_locale(locale) @idb[locale] = I18n::Inflector::InflectionData.new(locale) end # Creates internal databases (regular and strict) for the specified locale. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @param [Symbol] locale the locale for which the inflections databases are to be created # @return [Array] the # array of objects for keeping inflection data def new_databases(locale) normal = new_databases(locale) strict = strict.new_database(locale) [normal, strict] end # Attaches instance of {I18n::Inflector::InflectionData} and # optionally {I18n::Inflector::InflectionData_Strict} # to the inflector. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @note It doesn't create a copy of inflection data, but registers the given object(s). # @return [I18n::Inflector::InflectionData,Array,nil] # @overload add_database(db) # @param [I18n::Inflector::InflectionData] db inflection data to add # @return [I18n::Inflector::InflectionData,nil] the given object or +nil+ # if something went wrong (e.g. +nil+ was given as an argument) # @overload add_database(db, db_strict) # @note An array is returned and databases are # used only if both databases are successfully attached. References to # both databases will be unset if there would be a problem with attaching # any of them. # @param [I18n::Inflector::InflectionData] db inflection data to add # @param [I18n::Inflector::InflectionData_Strict] db_strict strict inflection data to add # @return [Array,nil] the # array of the given objects or +nil+ if something went wrong (e.g. +nil+ was # given as the first argument) def add_database(db, db_strict=nil) r = super(db) return r if (r.nil? || db_strict.nil?) r_strict = strict.add_database(db_strict) if r_strict.nil? delete_database(db.locale) return nil end [r, r_strict] end alias_method :add_databases, :add_database # Deletes the internal databases for the specified locale. # # @api public # @note It detaches the databases from {I18n::Inflector::API} instance. # Other objects referring to them may still use it. # @raise [I18n::InvalidLocale] if there is no proper locale name # @param [Symbol] locale the locale for which the inflections database is to be deleted. # @return [void] def delete_databases(locale) delete_database(locale) strict.delete_database(locale) end # Checks if the given locale was configured to support inflection. # # @api public # @note That method uses information from regular and strict kinds. # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Boolean] +true+ if a locale supports inflection # @overload inflected_locale?(locale) # Checks if the given locale was configured to support inflection. # @param [Symbol] locale the locale to test # @return [Boolean] +true+ if the given locale supports inflection # @overload inflected_locale? # Checks if the current locale was configured to support inflection. # @return [Boolean] +true+ if the current locale supports inflection def inflected_locale?(locale=nil) super || strict.inflected_locale?(locale) end alias_method :locale?, :inflected_locale? alias_method :locale_supported?, :inflected_locale? # Gets locales which have configured inflection support. # # @api public # @note This method uses information from both regular and strict kinds. # @return [Array] the array containing locales that support inflection # # @overload inflected_locales # Gets locales which have configured inflection support. # @return [Array] the array containing locales that support inflection # @overload inflected_locales(kind) # Gets locales which have configured inflection support for the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [Array] the array containing locales that support inflection # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#inflected_locales}) def inflected_locales(kind=nil) if kind.to_s[0..0] == Markers::STRICT_KIND strict.inflected_locales(kind.to_s[1..-1]) else kind = kind.to_s.empty? ? nil : kind.to_sym r = ( @inflected_locales_cache[kind] ||= super(kind).uniq ) r.nil? ? r : r.dup end end # Iterates through locales which have configured inflection support. # # @api public # @note This method uses information from both regular and strict kinds. # The locale identifiers may be duplicated! # @return [LazyArrayEnumerator] the lazy enumerator # @yield [locale] optional block in which each kind will be yielded # @yieldparam [Symbol] locale the inflected locale identifier # @yieldreturn [LazyArrayEnumerator] the lazy enumerator # @overload each_inflected_locale # Iterates through locales which have configured inflection support. # @return [LazyArrayEnumerator] the lazy enumerator # @overload each_inflected_locale(kind) # Iterates through locales which have configured inflection support for the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [LazyArrayEnumerator] the lazy enumerator def each_inflected_locale(kind=nil, &block) super + strict.inflected_locales(kind) end alias_method :each_locale, :each_inflected_locale alias_method :each_supported_locale, :each_inflected_locale # Tests if a kind exists. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#has_kind?}) # @overload has_kind?(kind) # Tests if a regular kind exists for the current locale. # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +kind+ exists for the current # locale, +false+ otherwise # @overload has_kind?(kind, locale) # Tests if a regular kind exists for the given +locale+. # @param [Symbol,String] kind the identifier of a kind # @param [Symbol] locale the locale identifier # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise def has_kind?(kind, locale=nil) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.has_kind?(kind.to_s[1..-1], locale) end super end # Reads default token for the given +kind+. # # @api public # @return [Symbol,nil] the default token or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#default_token}) # @overload default_token(kind) # This method reads default token for the given +kind+ and the current locale. # @param [Symbol,String] kind the kind of tokens # @return [Symbol,nil] the default token or +nil+ if # there is no default token # @overload default_token(kind, locale) # This method reads default token for the given +kind+ and the given +locale+. # @param [Symbol,String] kind the kind of tokens # @param [Symbol] locale the locale to use # @return [Symbol,nil] the default token or +nil+ if # there is no default token def default_token(kind, locale=nil) return nil if (kind.nil? || kind.to_s.empty?) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.default_token(kind.to_s[1..-1], locale) end super end # Checks if the given +token+ is an alias. # # @api public # @note By default it uses regular kinds database, not strict kinds. # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_alias?(token) # Uses current locale to check if the given +token+ is an alias. # @param [Symbol,String] token name of the checked token # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @overload has_alias?(token, locale) # Uses the given +locale+ to check if the given +token+ is an alias. # @param [Symbol,String] token name of the checked token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @overload has_alias?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ is an alias. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#has_alias?}) # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind used to narrow the check # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @overload has_alias?(token, strict_kind) # Uses the current locale and the given +strict_kind+ (which name must begin with # the +@+ symbol) to check if the given +token+ is an alias. # @note It calls {I18n::Inflector::API_Strict#has_alias?} on strict kinds data. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] strict_kind the kind of the given alias # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise def has_alias?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s reutrn false if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.has_alias?(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).has_alias?(token.to_sym, kind) end alias_method :token_has_alias?, :has_alias? # Checks if the given +token+ is a true token (not alias). # # @api public # @note By default it uses regular kinds database, not strict kinds. # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_true_token?(token) # Uses current locale to check if the given +token+ is a true token. # @param [Symbol,String] token name of the checked token # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @overload has_true_token?(token, locale) # Uses the given +locale+ to check if the given +token+ is a true token. # @param [Symbol,String] token name of the checked token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @overload has_true_token?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ is a true token. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#has_true_token?}) # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind used to narrow the check # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @overload has_true_token?(token, strict_kind) # Uses the current locale and the given +strict_kind+ (which name must begin with # the +@+ symbol) to check if the given +token+ is a true token. # @note It calls {I18n::Inflector::API_Strict#has_true_token?} on strict kinds data. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] strict_kind the kind of the given token # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise def has_true_token?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s return false if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.has_true_token?(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).has_true_token?(token.to_sym, kind) end alias_method :token_has_true?, :has_true_token? # Checks if the given +token+ exists. It may be an alias or a true token. # # @api public # @note By default it uses regular kinds database, not strict kinds. # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_token?(token) # Uses current locale to check if the given +token+ is a token. # @param [Symbol,String] token name of the checked token # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @overload has_token?(token, locale) # Uses the given +locale+ to check if the given +token+ exists. # @param [Symbol,String] token name of the checked token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @overload has_token?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ exists. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#has_token?}) # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind used to narrow the check # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @overload has_token?(token, strict_kind) # Uses the current locale and the given +strict_kind+ (which name must begin with # the +@+ symbol) to check if the given +token+ exists. # @note It calls {I18n::Inflector::API_Strict#has_token?} on strict kinds data. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] strict_kind the kind of the given token # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise def has_token?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s return false if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.has_token?(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).has_token?(token.to_sym, kind) end alias_method :token_exists?, :has_token? # Gets true token for the given +token+. If the token # is an alias it will be resolved # and a true token (target) will be returned. # @note By default it uses regular kinds database, not strict kinds. # @api public # @return [Symbol,nil] the true token or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload true_token(token) # Uses current locale to get a real token for the given +token+. # @param [Symbol,String] token name of the checked token # @return [Symbol,nil] the true token or +nil+ # @overload true_token(token, locale) # Uses the given +locale+ to get a real token for the given +token+. # If the token is an alias it will be resolved # and a true token (target) will be returned. # @param [Symbol,String] token name of the checked token # @param [Symbol] locale the locale to use # @return [Symbol,nil] the true token or +nil+ # @overload true_token(token, kind, locale) # Uses the given +locale+ and +kind+ to get a real token for the given +token+. # If the token is an alias it will be resolved # and a true token (target) will be returned. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#true_token}) # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @param [Symbol] locale the locale to use # @return [Symbol,nil] the true token or +nil+ # @overload true_token(token, strict_kind) # Uses the current locale and the given +strict_kind+ (which name must begin with # the +@+ symbol) to get a real token for the given +token+. # @note It calls {I18n::Inflector::API_Strict#true_token} on strict kinds data. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] strict_kind the kind of the given token # @return [Symbol,nil] the true token def true_token(*args) token, kind, locale = tkl_args(args) return nil if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s return nil if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.true_token(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).get_true_token(token.to_sym, kind) end alias_method :resolve_alias, :true_token # Gets a kind for the given +token+ (which may be an alias). # # @api public # @note By default it uses regular kinds database, not strict kinds. # @return [Symbol,nil] the kind of the given +token+ or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload kind(token) # Uses the current locale to get a kind of the given +token+ (which may be an alias). # @param [Symbol,String] token name of the token or alias # @return [Symbol,nil] the kind of the given +token+ # @overload kind(token, locale) # Uses the given +locale+ to get a kind of the given +token+ (which may be an alias). # @param [Symbol,String] token name of the token or alias # @param [Symbol] locale the locale to use # @return [Symbol,nil] the kind of the given +token+ # @overload kind(token, kind, locale) # Uses the given +locale+ to get a kind of the given +token+ (which may be an alias). # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#kind}) # @param [Symbol,String] token name of the token or alias # @param [Symbol,String] kind the kind name to narrow the search # @param [Symbol] locale the locale to use # @return [Symbol,nil] the kind of the given +token+ # @overload kind(token, strict_kind) # Uses the current locale and the given +strict_kind+ (which name must begin with # the +@+ symbol) to get a kind of the given +token+ (which may be an alias). # @note It calls {I18n::Inflector::API_Strict#kind} on strict kinds data. # @param [Symbol,String] token name of the token or alias # @param [Symbol,String] kind the kind of the given token # @return [Symbol,nil] the kind of the given +token+ def kind(*args) token, kind, locale = tkl_args(args) return nil if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s return nil if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.kind(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).get_kind(token.to_sym, kind) end # Iterates through available inflection tokens and their descriptions. # # @api public # @note By default it uses regular kinds database, not strict kinds. # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @note You cannot deduce where aliases are pointing to, since the information # about a target is replaced by the description. To get targets use the # {#raw_tokens} method. To simply list aliases and their targets use # the {#aliases} method. # @overload each_token # Iterates through available inflection tokens and their descriptions. # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token(kind) # Iterates through available inflection tokens and their descriptions for some +kind+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token(kind, locale) # Iterates through available inflection tokens and their descriptions for some +kind+ and +locale+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_token(kind=nil, locale=nil) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.each_token(kind.to_s[1..-1], locale) end super end # Iterates through available inflection tokens and their values. # # @api public # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @yield [token, value] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [Symbol, String] value a description string for a token or a target (if alias) # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @raise [I18n::InvalidLocale] if there is no proper locale name # @note You may deduce whether the returned values are aliases or true tokens # by testing if a value is a type of Symbol or String. # @overload each_token_raw # Iterates through available inflection tokens and their values for regular kinds. # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @overload each_token_raw(kind) # Iterates through available inflection tokens and their values for the given +kind+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token_raw}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @overload each_token_raw(kind, locale) # Iterates through available inflection tokens and their values for the given +kind+ and +locale+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token_raw}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) def each_token_raw(kind=nil, locale=nil) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.each_token_raw(kind.to_s[1..-1], locale) end super end alias_method :each_raw_token, :each_token_raw # Iterates through true inflection tokens and their values. # # @api public # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @raise [I18n::InvalidLocale] if there is no proper locale name # @note It returns only true tokens, not aliases. # @overload each_token_true # Iterates through true inflection tokens and their values for regular kinds. # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token_true(kind) # Iterates through true inflection tokens and their values for the given +kind+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token_true}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token_true(kind, locale) # Iterates through true inflection tokens and their values for the given +kind+ and +value+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_token_true}) # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_token_true(kind=nil, locale=nil, &block) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.each_token_true(kind.to_s[1..-1], locale, &block) end super end alias_method :each_true_token, :each_token_true # Iterates through inflection aliases and their pointers. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [LazyHashEnumerator] the lazy enumerator (token => target) # @yield [alias, target] optional block in which each alias will be yielded # @yieldparam [Symbol] alias an alias # @yieldparam [Symbol] target a name of the target token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_alias(kind) # Iterates through inflection aliases (and their pointers) of the given +kind+ and the current locale. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_alias}) # @param [Symbol,String] kind the kind of aliases to get # @return [LazyHashEnumerator] the lazy enumerator (token => target) # @overload each_alias(kind, locale) # Iterates through inflection aliases (and their pointers) of the given +kind+ and +locale+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#each_alias}) # @param [Symbol,String] kind the kind of aliases to get # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => target) def each_alias(kind=nil, locale=nil, &block) if kind.to_s[0..0] == Markers::STRICT_KIND return strict.each_alias(kind.to_s[1..-1], locale, &block) end super end # Gets the description of the given inflection token. # # @api public # @note If the given +token+ is really an alias it # returns the description of the true token that # it points to. By default it uses regular kinds database, # not strict kinds. # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [String,nil] the descriptive string or +nil+ # @overload token_description(token) # Uses current locale to get description of the given inflection +token+. # @param [Symbol] token the identifier of a token # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found) # @overload token_description(token, locale) # Uses the given +locale+ to get description of the given inflection +token+. # @param [Symbol,String] token the identifier of a token # @param [Symbol] locale the locale to use # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found) # @overload token_description(token, kind, locale) # Uses the given +locale+ and +kind+ to get description of the given inflection +token+. # @note If +kind+ begins with the +@+ symbol then the variant of this method # operating on strict kinds will be called ({I18n::Inflector::API_Strict#token_description}) # @param [Symbol,String] token the identifier of a token # @param [Symbol,String] kind the kind to narrow the results # @param [Symbol] locale the locale to use # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found or +kind+ mismatched) # @overload token_description(token, strict_kind) # Uses the default locale and the given +kind+ (which name must begin with # the +@+ symbol) to get description of the given inflection +token+. # @note It calls {I18n::Inflector::API_Strict#token_description} on strict kinds data. # @param [Symbol,String] token the identifier of a token # @param [Symbol,String] strict_kind the kind of a token # @param [Symbol] locale the locale to use # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found or +kind+ mismatched) def token_description(*args) token, kind, locale = tkl_args(args) return nil if (token.nil? || token.to_s.empty?) unless kind.nil? kind = kind.to_s return nil if kind.empty? if kind[0..0] == Markers::STRICT_KIND return strict.token_description(token, kind[1..-1], locale) end kind = kind.to_sym end data_safe(locale).get_description(token.to_sym, kind) end protected # @private def data(locale=nil) @idb[prep_locale(locale)] end # @private def data_safe(locale=nil) @idb[prep_locale(locale)] || I18n::Inflector::InflectionData.new(locale) end # This method is the internal helper that prepares arguments # containing +token+, +kind+ and +locale+. # # @note This method leaves +kind+ as is when it's +nil+ or empty. It sets # +token+ to +nil+ when it's empty. # @raise [I18n::InvalidLocale] if there is no proper locale name # @raise [ArgumentError] if the count of arguments is invalid # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token, kind, locale) # Prepares arguments containing +token+, +kind+ and +locale+. # @param [String,Hash] token the token # @param [String,Hash] kind the inflection kind # @param [String,Hash] locale the locale identifier # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token, locale) # Prepares arguments containing +token+ and +locale+. # @param [String,Hash] token the token # @param [String,Hash] locale the locale identifier # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token) # Prepares arguments containing +token+. # @param [String,Hash] token the token # @return [Array] the array containing # cleaned and validated +token+ and the current locale # @overload tkl_args(token, strict_kind) # Prepares arguments containing +token+ and +strict_kind+. # @param [String,Hash] token the token # @param [String,Hash] strict_kind the strict kind identifier beginning with +@+ symbol # @return [Array] the array containing # cleaned and validated +token+, +strict_kind+ and the current locale def tkl_args(args) token, kind, locale = case args.count when 1 then [args[0], nil, nil] when 2 then args[1].to_s[0..0] == Markers::STRICT_KIND ? [args[0], args[1], nil] : [args[0], nil, args[1]] when 3 then args else raise I18n::ArgumentError.new("wrong number of arguments: #{args.count} for (1..3)") end [token,kind,locale] end end # class API # @abstract This is for backward compatibility with the old naming scheme. class Core < API end end # module Inflector end # module I18n ruby-i18n-inflector-2.6.6/lib/i18n-inflector/api_strict.rb000066400000000000000000001016421204270775600232620ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains I18n::Inflector::API_Strict class, # which handles public API for managing inflection data # for named patterns (strict kinds). module I18n module Inflector # This class contains common operations # that can be performed on inflection data describing # strict kinds and tokens assigned to them (used in named # patterns). It is used by the regular {I18n::Inflector::API API} # and present there as {I18n::Inflector::API#strict strict} # instance attribute. # # It operates on the database containing instances # of {I18n::Inflector::InflectionData_Strict} indexed by locale # names and has methods to access the inflection data in an easy way. # It can operate on a database and options passed to initializer; # if they aren't passet it will create them. # # ==== Usage # You can access the instance of this class attached to # default I18n backend by calling: # I18n.backend.inflector.strict # or in a short form: # I18n.inflector.strict # # In most cases using the regular {I18n::Inflector::API} instance # may be sufficient to operate on inflection data, # because the regular API (instantiated as I18n.inflector) # is aware of strict kinds and can pass calls from +API_Strict+ # object if the +kind+ argument given in a method call # contains the +@+ symbol. # # For an instance connected to default I18n backend # the object containing inflection options is shared # with the regular API. # # @api public class API_Strict # Initilizes inflector by connecting to internal databases # used for storing inflection data and options. # # @api public # @note If any given option is +nil+ then a proper object will be created. # If it's given, then it will be referenced, not copied. # @param [Hash,nil] idb the strict inflections databases indexed by locale # @param [I18n::Inflector::InflectionOptions,nil] options the inflection options def initialize(idb=nil, options=nil) @idb = idb.nil? ? {} : idb @options = options.nil? ? I18n::Inflector::InflectionOptions.new : options @lazy_locales = LazyHashEnumerator.new(@idb) @inflected_locales_cache = Hash.new end # Creates an empty strict inflections database for the specified locale. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @param [Symbol] locale the locale for which the inflections database # should be created # @return [I18n::Inflector::InflectionData_Strict] the new object for keeping # inflection data def new_database(locale) locale = prep_locale(locale) @inflected_locales_cache.clear @idb[locale] = I18n::Inflector::InflectionData_Strict.new(locale) end # Attaches {I18n::Inflector::InflectionData_Strict} instance to the # current object. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @note It doesn't create copy of inflection database, it registers the given object. # @param [I18n::Inflector::InflectionData_Strict] idb inflection data to add # @return [I18n::Inflector::InflectionData_Strict] the given +idb+ or +nil+ if something # went wrong (e.g. +nil+ was given as an argument) def add_database(db) return nil if db.nil? locale = prep_locale(db.locale) delete_database(locale) @inflected_locales_cache.clear @idb[locale] = db end # Deletes a strict inflections database for the specified locale. # # @api public # @note It detaches the database from {I18n::Inflector::API_Strict} instance. # Other objects referring to it directly may still use it. # @raise [I18n::InvalidLocale] if there is no proper locale name # @param [Symbol] locale the locale for which the inflections database is to be deleted. # @return [void] def delete_database(locale) locale = prep_locale(locale) return nil if @idb[locale].nil? @inflected_locales_cache.clear @idb[locale] = nil end # Checks if the given locale was configured to support strict inflection. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Boolean] +true+ if a locale supports inflection # @overload inflected_locale? # Checks if the current locale was configured to support inflection. # @return [Boolean] +true+ if the current locale supports inflection # @overload inflected_locale?(locale) # Checks if the given locale was configured to support inflection. # @param [Symbol] locale the locale to test # @return [Boolean] +true+ if the given locale supports inflection def inflected_locale?(locale=nil) not @idb[prep_locale(locale)].nil? rescue false end alias_method :locale?, :inflected_locale? alias_method :locale_supported?, :inflected_locale? # Iterates through locales which have configured strict inflection support. # # @api public # @return [LazyArrayEnumerator] the lazy enumerator # @yield [locale] optional block in which each kind will be yielded # @yieldparam [Symbol] locale the inflected locale identifier # @yieldreturn [LazyArrayEnumerator] the lazy enumerator # @overload each_inflected_locale # Iterates through locales which have configured inflection support. # @return [LazyArrayEnumerator] the lazy enumerator # @overload each_inflected_locale(kind) # Iterates through locales which have configured inflection support for the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [LazyArrayEnumerator] the lazy enumerator def each_inflected_locale(kind=nil, &block) kind = kind.to_s.empty? ? nil : kind.to_sym i = @lazy_locales.reject { |lang,data| data.empty? } i = i.select { |lang,data| data.has_kind?(kind) } unless kind.nil? i.each_key(&block) end alias_method :each_locale, :each_inflected_locale alias_method :each_supported_locale, :each_inflected_locale # Gets locales which have configured strict inflection support. # # @api public # @return [Array] the array containing locales that support inflection # @overload inflected_locales # Gets locales which have configured inflection support. # @return [Array] the array containing locales that support inflection # @overload inflected_locales(kind) # Gets locales which have configured inflection support for the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [Array] the array containing locales that support inflection def inflected_locales(kind=nil) kind = kind.to_s.empty? ? nil : kind.to_sym r = ( @inflected_locales_cache[kind] ||= each_inflected_locale(kind).to_a ) r.nil? ? r : r.dup end alias_method :locales, :inflected_locales alias_method :supported_locales, :inflected_locales # Iterates through known strict inflection kinds. # # @api public # @return [LazyArrayEnumerator] the lazy enumerator # @yield [kind] optional block in which each kind will be yielded # @yieldparam [Symbol] kind the inflection kind # @yieldreturn [LazyArrayEnumerator] the lazy enumerator # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload kinds # Iterates through known inflection kinds for the current locale. # @return [LazyArrayEnumerator] the lazy enumerator # @overload kinds(locale) # Iterates through known inflection kinds for the given +locale+. # @param [Symbol] locale the locale for which kinds should be listed # @return [LazyArrayEnumerator] the lazy enumerator def each_kind(locale=nil, &block) data_safe(locale).each_kind(&block) end alias_method :each_inflection_kind, :each_kind # Gets known strict inflection kinds. # # @api public # @return [Array] the array containing known inflection kinds # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload kinds # Gets known inflection kinds for the current locale. # @return [Array] the array containing known inflection kinds # @overload kinds(locale) # Gets known inflection kinds for the given +locale+. # @param [Symbol] locale the locale for which kinds should be listed # @return [Array] the array containing known inflection kinds def kinds(locale=nil) each_kind(locale).to_a end alias_method :inflection_kinds, :kinds # Tests if a strict kind exists. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise # @overload has_kind?(kind) # Tests if a strict kind exists for the current locale. # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise # @overload has_kind?(kind, locale) # Tests if a strict kind exists for the given +locale+. # @param [Symbol,String] kind the identifier of a kind # @param [Symbol] locale the locale identifier # @return [Boolean] +true+ if the given +kind+ exists, +false+ otherwise def has_kind?(kind, locale=nil) return false if (kind.nil? || kind.to_s.empty?) data_safe(locale).has_kind?(kind.to_sym) end # Reads default token of the given strict +kind+. # # @api public # @return [Symbol,nil] the default token or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload default_token(kind) # This method reads default token of the given +kind+ and the current locale. # @param [Symbol,String] kind the kind of tokens # @return [Symbol,nil] the default token or +nil+ if # there is no default token # @overload default_token(kind, locale) # This method reads default token of the given +kind+ and the given +locale+. # @param [Symbol,String] kind the kind of tokens # @param [Symbol] locale the locale to use # @return [Symbol,nil] the default token or +nil+ if # there is no default token def default_token(kind, locale=nil) return nil if (kind.nil? || kind.to_s.empty?) data_safe(locale).get_default_token(kind.to_sym) end # Checks if the given +token+ belonging to a strict kind is an alias. # # @api public # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_alias?(token, kind) # Uses the current locale and the given +kind+ to check if the given +token+ is an alias. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise # @overload has_alias?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ is an alias. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is an alias, +false+ otherwise def has_alias?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || kind.nil?) data_safe(locale).has_alias?(token, kind) end alias_method :token_is_alias?, :has_alias? # Checks if the given +token+ belonging to a strict kind is a true token (not alias). # # @api public # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_true_token?(token, kind) # Uses the current locale and the given +kind+ to check if the given +token+ is a true token. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise # @overload has_true_token?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ is a true token. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ is a true token, +false+ otherwise def has_true_token?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || kind.nil?) data_safe(locale).has_true_token?(token, kind) end alias_method :token_is_true?, :has_true_token? # Checks if the given +token+ belonging to a strict kind exists. It may be an alias or a true token. # # @api public # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [ArgumentError] if the count of arguments is invalid # @overload has_token?(token, kind) # Uses the current locale and the given kind +kind+ to check if the given +token+ exists. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise # @overload has_token?(token, kind, locale) # Uses the given +locale+ and +kind+ to check if the given +token+ exists. # @param [Symbol,String] token name of the checked token # @param [Symbol,String] kind the kind of the given token # @param [Symbol] locale the locale to use # @return [Boolean] +true+ if the given +token+ exists, +false+ otherwise def has_token?(*args) token, kind, locale = tkl_args(args) return false if (token.nil? || kind.nil?) data_safe(locale).has_token?(token, kind) end alias_method :token_exists?, :has_token? # Gets true token for the given +token+ belonging to # a strict kind. If the token is an alias it will be resolved # and a true token (target) will be returned. # # @api public # @return [Symbol,nil] the true token or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload true_token(token, kind) # Uses the current +locale+ and the given +kind+ to get a real token # for the given +token+. If the token is an alias it will be resolved # and a true token (target) will be returned. # @param [Symbol,String] token the identifier of the checked token # @param [Symbol,String] kind the identifier of a kind # @return [Symbol,nil] the true token or +nil+ # @overload true_token(token, kind, locale) # Uses the given +locale+ and +kind+ to get a real token # for the given +token+. If the token is an alias it will be resolved # and a true token (target) will be returned. # @param [Symbol,String] token the identifier of the checked token # @param [Symbol,String] kind the identifier of a kind # @param [Symbol] locale the locale to use # @return [Symbol,nil] the true token or +nil+ def true_token(*args) token, kind, locale = tkl_args(args) return nil if (token.nil? || kind.nil?) data_safe(locale).get_true_token(token, kind) end alias_method :resolve_alias, :true_token # Gets a kind of the given +token+ (which may be an alias) belonging to a strict kind. # # @api public # @return [Symbol,nil] the kind of the given +token+ or +nil+ # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload kind(token, kind) # Uses current locale and the given +kind+ to get a kind of # the given +token+ (which may be an alias). # @param [Symbol,String] token name of the token or alias # @param [Symbol,String] kind the identifier of a kind (expectations filter) # @return [Symbol,nil] the kind of the given +token+ or +nil+ # @overload kind(token, kind, locale) # Uses the given +locale+ to get a kind of the given +token+ (which may be an alias). # @param [Symbol,String] token name of the token or alias # @param [Symbol,String] kind the identifier of a kind (expectations filter) # @param [Symbol] locale the locale to use # @return [Symbol,nil] the kind of the given +token+ or +nil+ def kind(token, kind=nil, locale=nil) return nil if (token.nil? || kind.nil? || token.to_s.empty? || kind.to_s.empty?) data_safe(locale).get_kind(token.to_sym, kind.to_sym) end # Iterates through available inflection tokens belonging to a strict kind and their descriptions. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @note You cannot deduce where aliases are pointing to, since the information # about a target is replaced by the description. To get targets use the # {#raw_tokens} method. To simply list aliases and their targets use # the {#aliases} method. # @overload each_token(kind) # Iterates through available inflection tokens and their descriptions for some +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token(kind, locale) # Iterates through available inflection tokens and their descriptions of the given # +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_token(kind=nil, locale=nil, &block) kind = kind.to_s.empty? ? nil : kind.to_sym data_safe(locale).each_token(kind, &block) end # Gets available inflection tokens belonging to a strict kind and their descriptions. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Hash] the hash containing available inflection tokens and descriptions # @note You cannot deduce where aliases are pointing to, since the information # about a target is replaced by the description. To get targets use the # {#raw_tokens} method. To simply list aliases and their targets use # the {#aliases} method. # @overload tokens(kind) # Gets available inflection tokens and their descriptions for some +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [Hash] the hash containing available inflection tokens (including # aliases) as keys and their descriptions as values # @overload tokens(kind, locale) # Gets available inflection tokens and their descriptions of the given # +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [Hash] the hash containing available inflection tokens (including # aliases) as keys and their descriptions as values def tokens(kind=nil, locale=nil) each_token(kind, locale).to_h end # Iterates through available inflection tokens belonging to a strict kind and their values. # # @api public # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @yield [token, value] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [Symbol, String] value a description string for a token or a target (if alias) # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @raise [I18n::InvalidLocale] if there is no proper locale name # @note You may deduce whether the returned values are aliases or true tokens # by testing if a value is a kind of Symbol or a String. # @overload each_token_raw(kind) # Iterates through available inflection tokens and their values of the given +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @overload each_token_raw(kind, locale) # Iterates through available inflection tokens (and their values) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) def each_token_raw(kind=nil, locale=nil, &block) kind = kind.to_s.empty? ? nil : kind.to_sym data_safe(locale).each_raw_token(kind, &block) end alias_method :each_raw_token, :each_token_raw # Gets available inflection tokens belonging to a strict kind and their values. # # @api public # @return [Hash] the hash containing available inflection tokens and descriptions (or alias pointers) # @raise [I18n::InvalidLocale] if there is no proper locale name # @note You may deduce whether the returned values are aliases or true tokens # by testing if a value is a kind of Symbol or a String. # @overload tokens_raw(kind) # Gets available inflection tokens and their values of the given +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [Hash] the hash containing available inflection tokens as keys # and their descriptions as values; in case of aliases the returned # values are Symbols # @overload tokens_raw(kind, locale) # Gets available inflection tokens (and their values) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [Hash] the hash containing available inflection tokens as keys # and their descriptions as values. In case of aliases the returned # values are Symbols def tokens_raw(kind=nil, locale=nil) each_token_raw(kind, locale).to_h end alias_method :raw_tokens, :tokens_raw # Iterates through inflection tokens belonging to a strict kind and their values. # # @api public # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @raise [I18n::InvalidLocale] if there is no proper locale name # @note It returns only true tokens, not aliases. # @overload each_token_true(kind) # Iterates through true inflection tokens (and their values) of the given +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token_true(kind, locale) # Iterates through true inflection tokens (and their values) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_token_true(kind=nil, locale=nil, &block) kind = kind.to_s.empty? ? nil : kind.to_sym data_safe(locale).each_true_token(kind, &block) end alias_method :each_true_token, :each_token_true # Gets true inflection tokens belonging to a strict kind and their values. # # @api public # @return [Hash] the hash containing available inflection tokens and descriptions # @raise [I18n::InvalidLocale] if there is no proper locale name # @note It returns only true tokens, not aliases. # @overload tokens_true(kind) # Gets true inflection tokens (and their values) of the given +kind+ and # the current locale. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @return [Hash] the hash containing available inflection tokens as keys # and their descriptions as values # @overload tokens_true(kind, locale) # Gets true inflection tokens (and their values) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of inflection tokens to be returned # @param [Symbol] locale the locale to use # @return [Hash] the hash containing available inflection tokens as keys # and their descriptions as values def tokens_true(kind=nil, locale=nil) each_token_true(kind, locale).to_h end alias_method :true_tokens, :tokens_true # Iterates through inflection aliases belonging to a strict kind and their pointers. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [LazyHashEnumerator] the lazy enumerator (token => target) # @yield [alias, target] optional block in which each alias will be yielded # @yieldparam [Symbol] alias an alias # @yieldparam [Symbol] target a name of the target token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_alias(kind) # Iterates through inflection aliases (and their pointers) of the given +kind+ and the current locale. # @param [Symbol,String] kind the kind of aliases to get # @return [LazyHashEnumerator] the lazy enumerator (token => target) # @overload each_alias(kind, locale) # Iterates through inflection aliases (and their pointers) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of aliases to get # @param [Symbol] locale the locale to use # @return [LazyHashEnumerator] the lazy enumerator (token => target) def each_alias(kind=nil, locale=nil, &block) kind = kind.to_s.empty? ? nil : kind.to_sym data_safe(locale).each_alias(kind, &block) end # Gets inflection aliases belonging to a strict kind and their pointers. # # @api public # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Hash] the Hash containing available inflection aliases (alias => target) # @overload aliases(kind) # Gets inflection aliases (and their pointers) of the given +kind+ and the current locale. # @param [Symbol,String] kind the kind of aliases to get # @return [Hash] the Hash containing available inflection aliases # @overload aliases(kind, locale) # Gets inflection aliases (and their pointers) of the given +kind+ and +locale+. # @param [Symbol,String] kind the kind of aliases to get # @param [Symbol] locale the locale to use # @return [Hash] the Hash containing available inflection aliases def aliases(kind=nil, locale=nil) each_alias(kind, locale).to_h end # Gets the description of the given inflection token belonging to a strict kind. # # @api public # @note If the given +token+ is really an alias it # returns the description of the true token that # it points to. # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [String,nil] the descriptive string or +nil+ # @overload token_description(token, kind) # Uses the current locale and the given +token+ to get a description of that token. # @param [Symbol,String] token the token # @param [Symbol,String] kind the identifier of a kind # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found) # @overload token_description(token, kind, locale) # Uses the given +locale+ and the given +token+ to get a description of that token. # @param [Symbol,String] token the token # @param [Symbol,String] kind the identifier of a kind # @param [Symbol] locale the locale to use # @return [String,nil] the descriptive string or +nil+ if something # went wrong (e.g. token was not found) def token_description(*args) token, kind, locale = tkl_args(args) return nil if (token.nil? || kind.nil?) data_safe(locale).get_description(token, kind) end protected # @private def data(locale=nil) @idb[prep_locale(locale)] end # @private def data_safe(locale=nil) @idb[prep_locale(locale)] || I18n::Inflector::InflectionData_Strict.new(locale) end # This method is the internal helper that prepares arguments # containing +token+, +kind+ and +locale+. # # @raise [I18n::InvalidLocale] if there is no proper locale name # @raise [ArgumentError] if the count of arguments is invalid # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token, kind, locale) # Prepares arguments containing +token+, +kind+ and +locale+. # @param [String,Hash] token the token # @param [String,Hash] kind the inflection kind # @param [String,Hash] locale the locale identifier # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token, kind) # Prepares arguments containing +token+ and +locale+. # @param [String,Hash] token the token # @param [String,Hash] kind the inflection kind # @return [Array] the array containing # cleaned and validated +token+, +kind+ and +locale+ # @overload tkl_args(token) # Prepares arguments containing +token+. # @param [String,Hash] token the token # @return [Array] the array containing # cleaned and validated +token+ and the current locale def tkl_args(args) token, kind, locale = case args.count when 1 then [args[0], nil, nil] when 2 then [args[0], args[1], nil] when 3 then args else raise I18n::ArgumentError.new("wrong number of arguments: #{args.count} for (1..3)") end token = token.nil? || token.to_s.empty? ? nil : token.to_sym kind = kind.nil? || kind.to_s.empty? ? nil : kind.to_sym [token,kind,locale] end # Processes +locale+ identifier and validates # whether it's correct (not empty and not +nil+). # # @note If the +locale+ is not correct, it # tries to use locale from {I18n.locale} and validates it # as well. # @param [Symbol,String] locale the locale identifier # @raise [I18n::InvalidLocale] if there is no proper locale name # @return [Symbol] the given locale or the global locale def prep_locale(locale=nil) locale ||= I18n.locale raise I18n::InvalidLocale.new(locale) if locale.to_s.empty? locale.to_sym end end # class API_Strict end # module Inflector end # module I18n ruby-i18n-inflector-2.6.6/lib/i18n-inflector/backend.rb000066400000000000000000000357541204270775600225220ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains I18n::Backend::Inflector module, # which extends I18n::Backend::Simple by adding the ability # to interpolate patterns containing inflection tokens # defined in translation data. module I18n # @abstract This namespace is shared with I18n subsystem. module Backend # This module contains methods that add # tokenized inflection support to internal I18n classes. # It is intened to be included in the Simple backend # module so that it will patch translate method in order # to interpolate additional inflection tokens present in translations. # Usually you don't have to know what's here to use it. module Inflector # Shortcut to configuration module. InflectorCfg = I18n::Inflector::Config # This accessor allows to reach API methods of the # inflector object associated with this class. def inflector inflector_try_init @inflector end # Cleans up internal hashes containg kinds, inflections and aliases. # # @api public # @note It calls {I18n::Backend::Simple#reload! I18n::Backend::Simple#reload!} # @return [Boolean] the result of calling ancestor's method def reload! @inflector = nil super end # Translates given key taking care of inflections. # # @api public # @see I18n::Inflector::API#interpolate # @see I18n::Inflector::InflectionOptions # @param [Symbol] locale locale # @param [Symbol,String] key translation key # @param [Hash] options a set of options to pass to the translation routines. # @note The given +options+ along with a translated string and the given # +locale+ are passed to # {I18n::Backend::Simple#translate I18n::Backend::Simple#translate} # and then the result is processed by {I18n::Inflector::API#interpolate} # @return [String] the translated string with interpolated patterns def translate(locale, key, options = {}) inflector_try_init # take care about cache-awareness cached = options.has_key?(:inflector_cache_aware) ? options[:inflector_cache_aware] : @inflector.options.cache_aware if cached interpolate_options = options @inflector.options.prepare_options!(options) else interpolate_options = options.dup @inflector.options.clean_for_translate!(options) end # translate string using original translate translated_string = super # generate a pattern from key-based inflection object if (translated_string.is_a?(Hash) && key.to_s[0..0] == InflectorCfg::Markers::STRICT_KIND) translated_string = @inflector.key_to_pattern(translated_string) end # interpolate string begin @inflector.options.prepare_options!(interpolate_options) unless cached @inflector.interpolate(translated_string, locale, interpolate_options) # complete the exception by adding translation key rescue I18n::InflectionException => e e.key = key raise end end # Stores translations in memory. # # @api public # @raise [I18n::InvalidLocale] if the given +locale+ is invalid # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists # @raise [I18n::BadInflectionKind] if a loaded kind identifier is invalid # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration # @note If inflections are changed it will regenerate proper internal # structures. # @return [Hash] the stored translations def store_translations(locale, data, options = {}) r = super inflector_try_init if data.respond_to?(:has_key?) subdata = (data[:i18n] || data['i18n']) unless subdata.nil? subdata = (subdata[:inflections] || subdata['inflections']) unless subdata.nil? db, db_strict = load_inflection_tokens(locale, r[:i18n][:inflections]) @inflector.add_database(db, db_strict) end end end r end protected # Initializes internal hashes used for keeping inflections configuration. # # @return [void] def inflector_try_init unless (defined?(@inflector) && !@inflector.nil?) @inflector = I18n::Inflector::API.new init_translations unless initialized? end end # Takes care of loading inflection tokens # for all languages (locales) that have them # defined. # # @note It calls {I18n::Backend::Simple#init_translations I18n::Backend::Simple#init_translations} # @raise [I18n::BadInflectionToken] if a name of some loaded token is invalid # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists # @raise [I18n::BadInflectionKind] if a loaded kind identifier is invalid # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration # @return [Boolean] +true+ if everything went fine def init_translations unless (defined?(@inflector) && !@inflector.nil?) @inflector = I18n::Inflector::API.new end super end # Gives an access to the internal structure containing configuration data # for the given locale. # # @note Under some very rare conditions this method may be called while # translation data is loading. It must always return when translations # are not initialized. Otherwise it will cause loops and someone in Poland # will eat a kittien! # @param [Symbol] locale the locale to use # @return [Hash,nil] part of the translation data that # reflects inflections for the given locale or +nil+ # if translations are not initialized def inflection_subtree(locale) return nil unless initialized? lookup(locale, :"i18n.inflections", [], :fallback => true, :raise => :false) end # Resolves an alias for a token if the given +token+ is an alias. # # @note It does take care of aliasing loops (max traverses is set to 64). # @raise [I18n::BadInflectionToken] if a name of the token that alias points to is corrupted # @raise [I18n::BadInflectionAlias] if an alias points to token that does not exists # @return [Symbol] the true token that alias points to if the given +token+ # is an alias or the given +token+ if it is a true token # @overload shorten_inflection_alias(token, kind, locale) # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+. # @note This version uses internal subtree and needs the translation data to be initialized. # @param [Symbol] token the token name # @param [Symbol] kind the kind of the given token # @param [Symbol] locale the locale to use # @return [Symbol] the true token that alias points to if the given +token+ # is an alias or the given +token+ if it is a true token # @overload shorten_inflection_alias(token, kind, locale, subtree) # Resolves an alias for a token if the given +token+ is an alias for the given +locale+ and +kind+. # @param [Symbol] token the token name # @param [Symbol] kind the kind of the given token # @param [Symbol] locale the locale to use # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan # @return [Symbol] the true token that alias points to if the given +token+ # is an alias or the given +token+ if it is a true token def shorten_inflection_alias(token, kind, locale, subtree=nil, count=0) count += 1 return nil if count > 64 inflections_tree = subtree || inflection_subtree(locale) return nil if (inflections_tree.nil? || inflections_tree.empty?) kind_subtree = inflections_tree[kind] value = kind_subtree[token].to_s if value[0..0] != InflectorCfg::Markers::ALIAS if kind_subtree.has_key?(token) return token else raise I18n::BadInflectionToken.new(locale, token, kind) end else orig_token = token token = value[1..-1] if InflectorCfg::Reserved::Tokens.invalid?(token, :DB) raise I18n::BadInflectionToken.new(locale, token, kind) end token = token.to_sym if kind_subtree[token].nil? raise BadInflectionAlias.new(locale, orig_token, kind, token) else shorten_inflection_alias(token, kind, locale, inflections_tree, count) end end end # Uses the inflections subtree and creates internal mappings # to resolve kinds assigned to inflection tokens and aliases, including defaults. # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens # or +nil+ if something went wrong # @raise [I18n::BadInflectionToken] if a token identifier is invalid # @raise [I18n::BadInflectionKind] if a kind identifier is invalid # @raise [I18n::BadInflectionAlias] if a loaded alias points to a token that does not exists # @raise [I18n::DuplicatedInflectionToken] if a token has already appeard in loaded configuration # @overload load_inflection_tokens(locale) # @note That version calls the {inflection_subtree} method to obtain internal translations data. # Loads inflection tokens for the given locale using internal hash of stored translations. Requires # translations to be initialized. # @param [Symbol] locale the locale to use and work for # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens # or +nil+ if something went wrong # @overload load_inflection_tokens(locale, subtree) # Loads inflection tokens for the given locale using datthe given in an argument # @param [Symbol] locale the locale to use and work for # @param [Hash] subtree the tree (in a form of nested Hashes) containing inflection tokens to scan # @return [I18n::Inflector::InflectionData,nil] the database containing inflections tokens # or +nil+ if something went wrong def load_inflection_tokens(locale, subtree=nil) inflections_tree = subtree || inflection_subtree(locale) return nil if (inflections_tree.nil? || inflections_tree.empty?) inflections_tree = deep_symbolize(inflections_tree) idb = I18n::Inflector::InflectionData.new(locale) idb_strict = I18n::Inflector::InflectionData_Strict.new(locale) return nil if (idb.nil? || idb_strict.nil?) inflections = prepare_inflections(locale, inflections_tree, idb, idb_strict) # add inflection tokens and kinds to internal database inflections.each do |orig_kind, kind, strict_kind, subdb, tokens| # validate token's kind if (kind.to_s.empty? || InflectorCfg::Reserved::Kinds.invalid?(orig_kind, :DB)) raise I18n::BadInflectionKind.new(locale, orig_kind) end tokens.each_pair do |token, description| # test for duplicate if subdb.has_token?(token, strict_kind) raise I18n::DuplicatedInflectionToken.new(locale, token, orig_kind, subdb.get_kind(token, strict_kind)) end # validate token's name if InflectorCfg::Reserved::Tokens.invalid?(token, :DB) raise I18n::BadInflectionToken.new(locale, token, orig_kind) end # validate token's description if description.nil? raise I18n::BadInflectionToken.new(locale, token, orig_kind, description) elsif description.to_s[0..0] == InflectorCfg::Markers::ALIAS next end # skip default token for later processing next if token == :default subdb.add_token(token, kind, description) end end # handle aliases inflections.each do |orig_kind, kind, strict_kind, subdb, tokens| tokens.each_pair do |token, description| next if token == :default next if description.to_s[0..0] != InflectorCfg::Markers::ALIAS real_token = shorten_inflection_alias(token, orig_kind, locale, inflections_tree) subdb.add_alias(token, real_token, kind) unless real_token.nil? end end # handle default tokens inflections.each do |orig_kind, kind, strict_kind, subdb, tokens| next unless tokens.has_key?(:default) if subdb.has_default_token?(kind) raise I18n::DuplicatedInflectionToken.new(locale, :default, kind, orig_kind) end orig_target = tokens[:default] target = orig_target.to_s target = target[1..-1] if target[0..0] == InflectorCfg::Markers::ALIAS if target.empty? raise I18n::BadInflectionToken.new(locale, token, orig_kind, orig_target) end target = subdb.get_true_token(target.to_sym, kind) if target.nil? raise I18n::BadInflectionAlias.new(locale, :default, orig_kind, orig_target) end subdb.set_default_token(kind, target) end [idb, idb_strict] end # @private def prepare_inflections(locale, inflections, idb, idb_strict) unless inflections.respond_to?(:has_key?) raise I18n::BadInflectionKind.new(locale, :INFLECTIONS_ROOT) end I18n::Inflector::LazyHashEnumerator.new(inflections).ary_map do |kind, tokens| next if (tokens.nil? || tokens.empty?) unless tokens.respond_to?(:has_key?) raise I18n::BadInflectionKind.new(locale, kind) end subdb = idb strict_kind = nil orig_kind = kind if kind.to_s[0..0] == InflectorCfg::Markers::STRICT_KIND kind = kind.to_s[1..-1] next if kind.empty? kind = kind.to_sym subdb = idb_strict strict_kind = kind end [orig_kind, kind, strict_kind, subdb, tokens] end end # @private def deep_symbolize(obj) obj.inject({}) do |result, (key, value)| value = deep_symbolize(value) if value.is_a?(Hash) result[(key.to_s.to_sym rescue key) || key] = value result end end end # module Inflector end # module Backend end # module I18n ruby-i18n-inflector-2.6.6/lib/i18n-inflector/config.rb000066400000000000000000000250451204270775600223700ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains configuration of I18n::Inflector module. module I18n module Inflector # This module contains submodules and module # methods for handling global configuration # of the engine. module Config # @private def get_i18n_reserved_keys return I18n::RESERVED_KEYS if defined?(I18n::RESERVED_KEYS) return I18n::Backend::Base::RESERVED_KEYS if defined?(I18n::Backend::Base::RESERVED_KEYS) return I18n::Backend::Simple::RESERVED_KEYS if defined?(I18n::Backend::Simple::RESERVED_KEYS) return RESERVED_KEYS if defined?(RESERVED_KEYS) [] end module_function :get_i18n_reserved_keys # @private def all_consts(obj, f=String) obj.constants.map do |c| v = obj.const_get(c) (v.is_a?(f) && c != 'ALL') ? v : nil end.compact.uniq end module_function :all_consts # @private def gen_regexp(ary) ::Regexp.new '[' << ary.join << ']' end module_function :gen_regexp # Prefix that makes option a controlling option. OPTION_PREFIX = InflectionOptions::OPTION_PREFIX # Regexp matching a prefix that makes option # a controlling option. OPTION_PREFIX_REGEXP = Regexp.new('^' << OPTION_PREFIX) # This module contains keys that have special # meaning. module Keys # A Symbol that is used to mark default token # in configuration and in options. DEFAULT_TOKEN = :default # All keys ALL = HSet.new Config.all_consts(self, Symbol) end # module Keys # This module contains characters that are markers # giving the shape for a pattern and its elements. module Markers # A character that is used to mark pattern. PATTERN = '@' # A character that is used to mark a strict kind. STRICT_KIND = '@' # A character that is used to open a pattern. PATTERN_BEGIN = '{' # A character that ends a pattern. PATTERN_END = '}' # A character that indicates an alias. ALIAS = '@' # A character used to mark token value as loud. LOUD_VALUE = '~' # All markers. ALL = Config.all_consts(self) end # module Markers module Escapes # A general esape symbol. ESCAPE = '\\' # A regular expression that catches escape symbols. ESCAPE_R = /\\([^\\])/ # A list of escape symbols that cause a pattern to be escaped. PATTERN = HSet[Markers::PATTERN, Escapes::ESCAPE] end # module Escapes # This module contains constants that define # operators in patterns. module Operators # This module contains constants that define # operators in patterns that handle token # groups or tokens. module Tokens # A character used to mark patterns as complex # and to separate token groups assigned to different # strict kinds. AND = '+' # A character that is used to separate tokens # or token groups within a pattern. OR = '|' # A character used to assign value to a token # or a group of tokens. ASSIGN = ':' # A character used to create a virtual token # that always matches. WILDCARD = '*' # All token groups operators. ALL = Config.all_consts(self) end # module Tokens # This module contains constants that are operators # in patterns that handle token groups or tokens. module Token # A character used to separate multiple tokens. OR = ',' # A character used to mark tokens as negative. NOT = '!' # All token operators. ALL = Config.all_consts(self) end # module Token # All operators. ALL = Tokens::ALL | Token::ALL end # module Operators # This module contains constants defining # reserved characters in tokens and kinds. module Reserved # Reserved keys. KEYS = HSet.new Config.get_i18n_reserved_keys + Config::Keys::ALL.to_a + InflectionOptions.known.values # This module contains constants defining # reserved characters in token identifiers. module Tokens # Reserved characters in token identifiers placed in configuration. DB = (Operators::ALL | Markers::ALL) - [Markers::LOUD_VALUE] # Reserved characters in token identifiers passed as options. OPTION = DB # Reserved characters in token identifiers placed in patterns. PATTERN = OPTION - [Operators::Tokens::WILDCARD] # This module contains constants defining # regular expressions for reserved characters # in token identifiers. module Regexp # Reserved characters in token identifiers placed in configuration. DB = Config.gen_regexp Tokens::DB # Reserved characters in token identifiers passed as options. OPTION = Config.gen_regexp Tokens::OPTION # Reserved characters in token identifiers placed in patterns. PATTERN = Config.gen_regexp Tokens::PATTERN end # module Regexp # This method checks if the given +token+ is invalid, # that means it's either +nil+ or empty or it matches # the refular expression given as +root+. # # @api public # @param [Symbol,String] token the identifier of a token # @param [Regexp] root the regular expression used to test # @return [Boolean] +true+ if the given +token+ is # invalid, +false+ otherwise def invalid?(token, root) token = token.to_s token.empty? || (root == Regexp::PATTERN && Keys::ALL[token.to_sym]) || Regexp.const_get(root) =~ token end module_function :invalid? end # module Tokens # This module contains constants defining # reserved characters in kind identifiers. module Kinds # Reserved characters in kind identifiers placed in configuration. DB = (Operators::ALL | Markers::ALL) - [Markers::ALIAS, Markers::LOUD_VALUE] # Reserved characters in kind identifiers passed as option values. OPTION = DB # Reserved characters in kind identifiers placed in patterns. PATTERN = (Operators::ALL | Markers::ALL) - [Markers::LOUD_VALUE] # This module contains constants defining # regular expressions for reserved characters # in kind identifiers. module Regexp # Reserved characters in kind identifiers placed in configuration. DB = Config.gen_regexp Kinds::DB # Reserved characters in kind identifiers passed as option values. OPTION = Config.gen_regexp Kinds::OPTION # Reserved characters in kind identifiers placed in patterns. PATTERN = Config.gen_regexp Kinds::PATTERN end # module Regexp # This method checks if the given +kind+ is invalid, # that means it's either +nil+ or empty or it matches # the refular expression given as +root+. # # @api public # @param [Symbol,String] kind the identifier of a kind # @param [Regexp] root the regular expression used to test # @return [Boolean] +true+ if the given +kind+ is # invalid, +false+ otherwise def invalid?(kind, root) kind = kind.to_s kind.empty? || (root != Regexp::OPTION && (KEYS[kind.to_sym] || OPTION_PREFIX_REGEXP =~ kind)) || Regexp.const_get(root) =~ kind end module_function :invalid? end # module Kinds end # module Reserved # A string for regular expression that catches patterns. PATTERN_RESTR = '(.?)' << Markers::PATTERN << '([^\\' << Markers::PATTERN_BEGIN << ']*)\\' << Markers::PATTERN_BEGIN << '([^\\' << Markers::PATTERN_END << ']+)\\' << Markers::PATTERN_END << '((?:\\'<< Markers::PATTERN_BEGIN << '([^\\' << Markers::PATTERN_BEGIN << ']+)\\' << Markers::PATTERN_END << ')*)' # A string for regular expression that extracts additional patterns attached. MULTI_RESTR = '\\' << Markers::PATTERN_BEGIN << '([^\\' << Markers::PATTERN_END + ']+)\\' << Markers::PATTERN_END # A regular expression that catches token groups or single tokens. TOKENS_RESTR = '(?:' << '([^' << Operators::Tokens::ASSIGN << '\\' << Operators::Tokens::OR << ']+)' << Operators::Tokens::ASSIGN << '+' << '([^\\' << Operators::Tokens::OR << ']+)\1?)' << '|([^' << Operators::Tokens::ASSIGN << '\\' << Operators::Tokens::OR << ']+)' # A regular expression that catches patterns. PATTERN_REGEXP = Regexp.new PATTERN_RESTR # A regular expression that extracts additional patterns attached. MULTI_REGEXP = Regexp.new MULTI_RESTR # A regular expression that catches token groups or single tokens. TOKENS_REGEXP = Regexp.new TOKENS_RESTR end # module Config # @private PATTERN_MARKER = Config::Markers::PATTERN # @private NAMED_MARKER = Config::Markers::STRICT_KIND # @private ALIAS_MARKER = Config::Markers::ALIAS # @private ESCAPE = Config::Escapes::ESCAPE # @private ESCAPE_R = Config::Escapes::ESCAPE_R # @private ESCAPES = Config::Escapes::PATTERN # @private PATTERN = Config::PATTERN_REGEXP # @private TOKENS = Config::TOKENS_REGEXP # @private INFLECTOR_RESERVED_KEYS = Config::Reserved::KEYS end # module Inflector end # module I18n ruby-i18n-inflector-2.6.6/lib/i18n-inflector/errors.rb000066400000000000000000000161221204270775600224330ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains error reporting classes for I18n::Backend::Inflector module. module I18n # @abstract It is a parent class for all exceptions # related to inflections. class InflectionException < I18n::ArgumentError attr_accessor :token attr_accessor :kind attr_accessor :key def initialize(locale, token, kind) @locale, @token, @kind = locale, token, kind @key = nil super() end end # @abstract It is a parent class for all exceptions # related to inflection patterns that are processed. class InflectionPatternException < InflectionException attr_accessor :pattern def initialize(locale, pattern, token, kind) super(locale, token, kind) @pattern = pattern end def message mkey = @key.nil? ? "" : ".#{@key}" @pattern.nil? ? "" : "#{@locale}#{mkey}: #{@pattern} - " end end # @abstract It is a parent class for all exceptions # related to configuration data of inflections that is processed. class InflectionConfigurationException < InflectionException attr_accessor :locale def message mkey = @key.nil? ? ".i18n.inflections.#{@kind}" : ".#{@key}" "#{@locale}#{mkey}: " end end # @abstract It is a parent class for exceptions raised when # inflection option is bad or missing. class InvalidOptionForKind < InflectionPatternException attr_accessor :option def initialize(locale, pattern, token, kind, option) super(locale, pattern, token, kind) @option = option end end # This is raised when there is no kind given in options. The kind # is determined by looking at token placed in a pattern. class InflectionOptionNotFound < InvalidOptionForKind def message kind = @kind.to_s unless kind.empty? if kind[0..0] == I18n::Inflector::Config::Markers::STRICT_KIND kindmsg = ":#{kind} (or :#{kind[1..-1]})" else kindmsg = kind.to_sym.inspect end end "" << super << "required option #{kindmsg} was not found" end end # This exception will be raised when a required option, describing token selected # for a kind contains a token that is not of the given kind. class InflectionOptionIncorrect < InvalidOptionForKind def message "" << super << "required value #{@option.inspect} of option #{@kind.inspect} " \ "does not match any token" end end # This is raised when a token given in a pattern is invalid (empty or has no # kind assigned). class InvalidInflectionToken < InflectionPatternException def initialize(locale, pattern, token, kind=nil) super(locale, pattern, token, kind) end def message badkind = "" if (!@token.to_s.empty? && !kind.nil?) kind = @kind.to_s.empty? ? "" : @kind.to_sym badkind = " (processed kind: #{kind.inspect})" end "" << super << "token #{@token.to_s.inspect} is invalid" + badkind end end # This is raised when an inflection option name is invalid (contains # reserved symbols). class InvalidInflectionOption < InflectionPatternException def initialize(locale, pattern, option) super(locale, pattern, nil, option) end def message "" << super << "inflection option #{@kind.inspect} is invalid" end end # This is raised when a kind given in a pattern is invalid (empty, reserved # or containing a reserved character). class InvalidInflectionKind < InflectionPatternException def initialize(locale, pattern, kind) super(locale, pattern, nil, kind) end def message "" << super << "kind #{@kind.to_s.inspect} is invalid" end end # This is raised when an inflection token used in a pattern does not match # an assumed kind determined by reading previous tokens from that pattern # or by the given strict kind of a named pattern. class MisplacedInflectionToken < InflectionPatternException def initialize(locale, pattern, token, kind) super(locale, pattern, token, kind) end def message "" << super << "token #{@token.to_s.inspect} " \ "is not of the expected kind #{@kind.inspect}" end end # This is raised when a complex inflection pattern is malformed # and cannot be reduced to set of regular patterns. class ComplexPatternMalformed < InflectionPatternException def initialize(locale, pattern, token, complex_kind) unless pattern.include?(I18n::Inflector::Config::Markers::PATTERN) pattern = I18n::Inflector::Config::Markers::PATTERN + "#{complex_kind}{#{pattern}}" end super(locale, pattern, token, complex_kind) end def message "" << super << "pattern is malformed; token count differs from kind count" end end # This is raised when an inflection token of the same name is already defined in # inflections tree of translation data. class DuplicatedInflectionToken < InflectionConfigurationException attr_accessor :original_kind def initialize(locale, token, kind, original_kind) super(locale, token, kind) @original_kind = original_kind end def message "" << super << "token #{@token.inspect} " \ "was already assigned to the kind #{@original_kind.inspect}" end end # This is raised when an alias for an inflection token points to a token that # doesn't exists. It is also raised when default token of some kind points # to a non-existent token. class BadInflectionAlias < InflectionConfigurationException attr_accessor :pointer def initialize(locale, token, kind, pointer) super(locale, token, kind) @pointer = pointer end def message what = token == :default ? "default token" : "alias #{@token.inspect}" "" << super << "the #{what} " \ "points to an unknown token #{@pointer.inspect}" end end # This is raised when an inflection token or its description has a bad name. This # includes an empty name or a name containing prohibited characters. class BadInflectionToken < InflectionConfigurationException attr_accessor :description def initialize(locale, token, kind=nil, description=nil) super(locale, token, kind) @description = description end def message if @description.nil? "" << super << "inflection token #{@token.inspect} " \ "has a bad name" else "" << super << "inflection token #{@token.inspect} " \ "has a bad description #{@description.inspect}" end end end # This is raised when an inflection kind has a bad name # or is not a root for a tree of tokens. class BadInflectionKind < InflectionConfigurationException def initialize(locale, kind) super(locale, nil, kind) end def message "" << super << "inflection kind #{@kind.inspect} has bad name or type" end end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/hset.rb000066400000000000000000000011331204270775600220560ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains more intuitive version of Set. require 'set' module I18n module Inflector # This class keeps sets of data class HSet < Set # This method performs a fast check # if an element exists in a set. # # @return [Boolean] def [](k) @hash[k] == true end end end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/inflection_data.rb000066400000000000000000000371661204270775600242550ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains class that is used to keep # inflection data. # @abstract This namespace is shared with I18n subsystem. module I18n module Inflector # This class contains structures for keeping parsed translation data # and basic operations for performing on them. class InflectionData < InflectionData_Strict # Initializes internal structures. # # @param [Symbol,nil] locale the locale identifier for the object to be labeled with def initialize(locale=nil) @kinds = Hash.new(false) @tokens = Hash.new(DUMMY_TOKEN) @lazy_tokens = LazyHashEnumerator.new(@tokens) @lazy_kinds = LazyArrayEnumerator.new(@kinds) @defaults = Hash.new @locale = locale end # Adds an alias (overwriting an existing alias). # # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad or +nil+ names or non-existent targets) # @overload add_alias(name, target) # Adds an alias (overwriting an existing alias). # @param [Symbol] name the name of an alias # @param [Symbol] target the target token for the given +alias+ # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad or +nil+ names or non-existent targets) # @overload add_alias(name, target, kind) # Adds an alias (overwriting an existing alias) if the given # +kind+ matches the kind of the given target. # @param [Symbol] name the name of an alias # @param [Symbol] target the target token for the given +alias+ # @param [Symbol] kind the optional kind of a taget # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad or +nil+ names or non-existent targets) def add_alias(name, target, kind=nil) target = target.to_s name = name.to_s return false if (name.empty? || target.empty?) kind = nil if kind.to_s.empty? unless kind.nil? name = name.to_sym target = target.to_sym t_kind = get_kind(target) return false if (t_kind.nil? || (!kind.nil? && t_kind != kind)) @tokens[name] = {} @tokens[name][:kind] = kind @tokens[name][:target] = target @tokens[name][:description] = @tokens[target][:description] true end # Adds a token (overwriting existing token). # # @param [Symbol] token the name of a token to add # @param [Symbol] kind the kind of a token # @param [String] description the description of a token # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad names or non-existent targets) def add_token(token, kind, description) return false if (token.to_s.empty? || kind.to_s.empty? || description.nil?) token = token.to_sym @tokens[token] = {} @tokens[token][:kind] = kind.to_sym @tokens[token][:description] = description.to_s @kinds[kind] = true end # Tests if the token is a true token. # # @overload has_true_token?(token) # Tests if the token is a true token. # @param [Symbol] token the identifier of a token # @return [Boolean] +true+ if the given +token+ is # a token and not an alias, +false+ otherwise # @overload has_true_token?(token, kind) # Tests if the token is a true token. # The kind will work as the expectation filter. # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +token+ is # a token and not an alias, and is a kind of # the given kind, +false+ otherwise def has_true_token?(token, kind=nil) o = @tokens[token] k = o[:kind] return false if (k.nil? || !o[:target].nil?) kind.nil? ? true : k == kind end # Tests if a token (or alias) is present. # # @overload has_token(token) # Tests if a token (or alias) is present. # @param [Symbol] token the identifier of a token # @return [Boolean] +true+ if the given +token+ # (which may be an alias) exists # @overload has_token(token, kind) # Tests if a token (or alias) is present. # The kind will work as the expectation filter. # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +token+ # (which may be an alias) exists and if kind of # the given kind def has_token?(token, kind=nil) k = @tokens[token][:kind] kind.nil? ? !k.nil? : k == kind end # Tests if a kind exists. # # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +kind+ exists def has_kind?(kind) @kinds.has_key?(kind) end # Tests if a kind has a default token assigned. # # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if there is a default # token of the given kind def has_default_token?(kind) @defaults.has_key?(kind) end # Tests if the given alias is really an alias. # # @overload has_alias?(alias_name) # Tests if the given alias is really an alias. # @param [Symbol] alias_name the identifier of an alias # @return [Boolean] +true+ if the given alias is really an alias, # +false+ otherwise # @overload has_alias?(alias_name, kind) # Tests if the given alias is really an alias. # The kind will work as the expectation filter. # @param [Symbol] alias_name the identifier of an alias # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given alias is really an alias # being a kind of the given kind, +false+ otherwise def has_alias?(alias_name, kind=nil) o = @tokens[alias_name] return false if o[:target].nil? kind.nil? ? true : o[:kind] == kind end # Iterates through all the true tokens (not aliases). # # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_true_token # Reads all the true tokens (not aliases). # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_true_token(kind) # Reads all the true tokens (not aliases) of the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_true_token(kind=nil, &block) t = @lazy_tokens t = t.select { |token,data| data[:kind] == kind } unless kind.nil? t.select { |token,data| data[:target].nil? }. map { |token,data| data[:description] }.each(&block) end # Iterates through all the aliases. # # @return [LazyHashEnumerator] the lazy enumerator (alias => target) # @yield [alias, target] optional block in which each alias will be yielded # @yieldparam [Symbol] alias an alias # @yieldparam [Symbol] target a name of the target token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_alias # Reads all the aliases. # @return [LazyHashEnumerator] the lazy enumerator (alias => target) # @overload each_alias(kind) # Reads all the aliases of the given +kind+. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (alias => target) def each_alias(kind=nil, &block) t = @lazy_tokens t = t.select { |token,data| data[:kind] == kind } unless kind.nil? t.reject { |token,data| data[:target].nil? }. map { |token,data| data[:target] }.each(&block) end # Iterates through all the tokens in a way that it is possible to # distinguish true tokens from aliases. # # @note True tokens have descriptions (String) and aliases # have targets (Symbol) assigned. # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @yield [token, value] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [Symbol, String] value a description string for a token or a target (if alias) # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_raw_token # Reads all the tokens in a way that it is possible to # distinguish true tokens from aliases. # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @overload each_raw_token(kind) # Reads all the tokens of the given +kind+ in a way # that it is possible to distinguish true tokens from aliases. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) def each_raw_token(kind=nil, &block) t = @lazy_tokens t = t.select { |token,data| data[:kind] == kind } unless kind.nil? t.map { |token,data| data[:target] || data[:description] }. each(&block) end # Iterates through all the tokens (including aliases). # # @note Use {#each_raw_token} if you want to distinguish # true tokens from aliases. # @return return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator # @overload each_token # Reads all the tokens (including aliases). # @return return [LazyHashEnumerator] the lazy enumerator (token => description) # @overload each_token(kind) # Reads all the tokens (including aliases) of the # given +kind+. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description) def each_token(kind=nil, &block) t = @lazy_tokens t = t.select { |token,data| data[:kind] == kind } unless kind.nil? t.map { |token,data| data[:description] }.each(&block) end # Gets a target token for the alias. # # @return [Symbol,nil] the token that the given alias points to # or +nil+ if it isn't really an alias # @overload get_target_for_alias(alias_name) # Gets a target token for the alias. # @param [Symbol] alias_name the identifier of an alias # @return [Symbol,nil] the token that the given alias points to # or +nil+ if it isn't really an alias # @overload get_target_for_alias(alias_name, kind) # Gets a target token for the alias that's +kind+ is given. # @param [Symbol] alias_name the identifier of an alias # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the token that the given alias points to # or +nil+ if it isn't really an alias def get_target_for_alias(alias_name, kind=nil) @tokens[alias_name][:target] end # Gets a kind of the given token or alias. # # @return [Symbol,nil] the kind of the given +token+ # or +nil+ if the token is unknown # @overload get_kind(token) # Gets a kind of the given token or alias. # @param [Symbol] token identifier of a token # @return [Symbol,nil] the kind of the given +token+ # or +nil+ if the token is unknown # @overload get_kind(token, kind) # Gets a kind of the given token or alias. # The kind will work as the expectation filter. # @param [Symbol] token identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the kind of the given +token+ # or +nil+ if the token is unknown def get_kind(token, kind=nil) k = @tokens[token][:kind] return k if (kind.nil? || kind == k) nil end # Gets a true token for the given identifier. # # @note If the given +token+ is really an alias it will # be resolved and the real token pointed by that alias # will be returned. # @return [Symbol,nil] the true token for the given +token+ # or +nil+ # @overload get_true_token(token) # Gets a true token for the given +token+ identifier. # @param [Symbol] token the identifier of a token # @return [Symbol,nil] the true token for the given +token+ # or +nil+ if the token is unknown # @overload get_true_token(token, kind) # Gets a true token for the given +token+ identifier and the # given +kind+. The kind will work as the expectation filter. # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the true token for the given +token+ # or +nil+ if the token is unknown or is not a kind of the # given +kind+ def get_true_token(token, kind=nil) o = @tokens[token] k = o[:kind] return nil if k.nil? r = (o[:target] || token) return r if kind.nil? k == kind ? r : nil end # Reads the default token of a kind. # # @note It will always return true token (not an alias). # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the default token of the given +kind+ # or +nil+ if there is no default token set def get_default_token(kind) @defaults[kind] end # Gets a description of a token or an alias. # @note If the token is really an alias it will resolve the alias first. # @return [String,nil] the string containing description of the given # token (which may be an alias) or +nil+ if the token is unknown # @overload get_description(token) # Gets a description of a token or an alias. # @param [Symbol] token the identifier of a token # @return [String,nil] the string containing description of the given # token (which may be an alias) or +nil+ if the token is unknown # @overload get_description(token, kind) # Gets a description of a token or an alias of the given +kind+ # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [String,nil] the string containing description of the given # token (which may be an alias) or +nil+ if the token is unknown def get_description(token, kind=nil) @tokens[token][:description] if (kind.nil? || @tokens[token][:kind] == kind) end end # InflectionData end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/inflection_data_strict.rb000066400000000000000000000274701204270775600256420ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains class that is used to keep # inflection data for strict kinds. # @abstract This namespace is shared with I18n subsystem. module I18n module Inflector # This class contains structures for keeping parsed translation data # and basic operations for strict kinds and tokens assigned to them. # Methods in this class vary from methods from {I18n::Inflector::InflectionData} # in a way that +kind+ argument is usually required, not optional, since # managing the strict kinds requires a kind of any token to be always known. class InflectionData_Strict # This constant contains a dummy hash for an empty token. It makes # chaining calls to internal data easier. DUMMY_TOKEN = {:kind=>nil, :target=>nil, :description=>nil}.freeze # This constant contains a dummy hash of hashes for tokens collection. # It makes chaining calls to internal data easier. DUMMY_TOKENS = Hash.new(DUMMY_TOKEN).freeze # This constant contains a dummy hash. It makes # chaining calls to internal data easier. DUMMY_HASH = Hash.new.freeze # Locale this database works for. attr_reader :locale # Initializes internal structures. # # @param [Symbol,nil] locale the locale identifier for # the object to be labeled with def initialize(locale=nil) @tokens = Hash.new(DUMMY_TOKENS) @lazy_kinds = LazyArrayEnumerator.new(@tokens) @defaults = Hash.new @locale = locale end # Adds an alias (overwriting existing alias). # # @param [Symbol] name the name of an alias # @param [Symbol] target the target token for the created alias # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad names or non-existent targets) def add_alias(name, target, kind) return false if (name.nil? || target.nil? || kind.nil?) return false if (name.to_s.empty? || target.to_s.empty? || kind.to_s.empty?) name = name.to_sym target = target.to_sym kind = kind.to_sym k = @tokens[kind] return false unless k.has_key?(target) token = k[name] = {} token[:description] = k[target][:description] token[:target] = target true end # Adds a token (overwriting existing token). # # @param [Symbol] token the name of a token to add # @param [Symbol] kind the identifier of a kind # @param [String] description the description of a token # @return [Boolean] +true+ if everything went ok, +false+ otherwise # (in case of bad names) def add_token(token, kind, description) return false if (token.to_s.empty? || kind.to_s.empty? || description.nil?) token = token.to_sym kind = kind.to_sym kind_tree = @tokens[kind] if kind_tree.equal?(DUMMY_TOKENS) kind_tree = @tokens[kind] = Hash.new(DUMMY_TOKEN) end token = kind_tree[token] = {} token[:description] = description.to_s true end # Sets the default token for the given strict kind. # # @param [Symbol] kind the kind to which the default # token should be assigned # @param [Symbol] target the token to set # @return [void] def set_default_token(kind, target) @defaults[kind.to_sym] = target.to_sym end # Tests if the given token of the given # strict kind is a true token. # # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +token+ is # a token and not an alias, and is a kind of # the given kind, +false+ otherwise def has_true_token?(token, kind) @tokens[kind].has_key?(token) && @tokens[kind][token][:target].nil? end # Tests if the given token (or alias) of the # given strict kind is present. # # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +token+ # (which may be an alias) exists and if kind of # the given kind def has_token?(token, kind) @tokens[kind].has_key?(token) end # Tests if a strict kind exists. # # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given +kind+ exists def has_kind?(kind) @tokens.has_key?(kind) end # Tests if the given strict kind has a default # token assigned. # # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if there is a default # token of the given kind def has_default_token?(kind) @defaults.has_key?(kind) end # Tests if the given alias of the given strict # kind is really an alias. # # @param [Symbol] alias_name the identifier of an alias # @param [Symbol] kind the identifier of a kind # @return [Boolean] +true+ if the given alias is really an alias # being a kind of the given kind, +false+ otherwise def has_alias?(alias_name, kind) not @tokens[kind][alias_name][:target].nil? end # Iterates through all the true tokens (not aliases) of the # given strict kind. # # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator def each_true_token(kind, &block) LazyHashEnumerator.new(@tokens[kind]). select { |token,data| data[:target].nil? }. map { |token,data| data[:description] }. each(&block) end # Iterates through all the aliases of the given strict kind. # # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => target) # @yield [alias, target] optional block in which each alias will be yielded # @yieldparam [Symbol] alias an alias # @yieldparam [Symbol] target a name of the target token # @yieldreturn [LazyHashEnumerator] the lazy enumerator def each_alias(kind, &block) LazyHashEnumerator.new(@tokens[kind]). reject { |token,data| data[:target].nil? }. map { |token,data| data[:target] }. each(&block) end # Iterates through all the tokens of the given strict kind # in a way that it is possible to # distinguish true tokens from aliases. # # @note True tokens have descriptions (String) and aliases # have targets (Symbol) assigned. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description|target) # @yield [token, value] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [Symbol, String] value a description string for a token or a target (if alias) # @yieldreturn [LazyHashEnumerator] the lazy enumerator def each_raw_token(kind, &block) LazyHashEnumerator.new(@tokens[kind]). map { |token,data| data[:target] || data[:description] }. each(&block) end # Iterates through all the tokens (including aliases) of the given # strict kind. # # @note Use {#each_raw_token} if you want to distinguish # true tokens from aliases. # @param [Symbol] kind the identifier of a kind # @return [LazyHashEnumerator] the lazy enumerator (token => description) # @yield [token, description] optional block in which each token will be yielded # @yieldparam [Symbol] token a token # @yieldparam [String] description a description string for a token # @yieldreturn [LazyHashEnumerator] the lazy enumerator def each_token(kind, &block) LazyHashEnumerator.new(@tokens[kind]). map{ |token,data| data[:description] }. each(&block) end # Gets a target token for the given alias of a strict kind. # # @param [Symbol] alias_name the identifier of an alias # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the token that the given alias points to # or +nil+ if it isn't really an alias def get_target_for_alias(alias_name, kind) @tokens[kind][alias_name][:target] end # Gets a strict kind of the given token or alias. # # @note This method may be concidered dummy since there is a # need to give the inflection kind, but it's here in order # to preserve compatibility with the same method from # {I18n::Inflector::InflectionData} which guesses the kind. # @param [Symbol] token identifier of a token # @param [Symbol] kind the identifier of a kind (expectations filter) # @return [Symbol,nil] the kind of the given +token+ # or +nil+ if the token is unknown or is not of the given kind def get_kind(token, kind) @tokens[kind].has_key?(token) ? kind : nil end # Gets a true token (of the given strict kind) for the given # identifier. # # @note If the given +token+ is really an alias it will # be resolved and the real token pointed by that alias # will be returned. # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the true token for the given +token+ # or +nil+ if the token is unknown or is not a kind of the # given +kind+ def get_true_token(token, kind) o = @tokens[kind] return nil unless o.has_key?(token) o = o[token] o[:target].nil? ? token : o[:target] end # Iterates through all known strict kinds. # # @return [LazyArrayEnumerator] the lazy enumerator # @yield [kind] optional block in which each kind will be yielded # @yieldparam [Symbol] kind the inflection kind # @yieldreturn [LazyArrayEnumerator] the lazy enumerator def each_kind(&block) @lazy_kinds.map{|k,v| k}.each(&block) end # Reads the default token of a strict kind. # # @note It will always return true token (not an alias). # @param [Symbol] kind the identifier of a kind # @return [Symbol,nil] the default token of the given +kind+ # or +nil+ if there is no default token set def get_default_token(kind) @defaults[kind] end # Gets a description of a token or alias belonging to a strict kind. # # @note If the token is really an alias it will resolve the alias first. # @param [Symbol] token the identifier of a token # @param [Symbol] kind the identifier of a kind # @return [String,nil] the string containing description of the given # token (which may be an alias) or +nil+ if the token is unknown def get_description(token, kind) @tokens[kind][token][:description] end # Test if the inflection data have no elements. # # @return [Boolean] +true+ if the inflection data # have no elements def empty? @tokens.empty? end end # InflectionData_Strict end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/inflector.rb000066400000000000000000000023121204270775600231000ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains a stub of I18n::Inflector module, # which extends I18n by adding the ability # to interpolate patterns containing inflection tokens # defined in translation data and manipulate on that data. module I18n class < e e.pattern = ext_pattern raise end found = pattern_content = "" # disable further processing else # Strict kinds preparing subdb = idb_strict # validate strict kind and set needed variables if (Reserved::Kinds.invalid?(strict_kind, :PATTERN) || !idb_strict.has_kind?(strict_kind.to_sym)) raise I18n::InvalidInflectionKind.new(locale, ext_pattern, sym_parsed_kind) if raises # Take a free text for invalid kind and return it next "" << pattern_fix << pattern_content.scan(TOKENS_REGEXP).reverse. select { |t,v,f| t.nil? && !f.nil? }. map { |t,v,f| f.to_s }. first.to_s else strict_kind = strict_kind.to_sym parsed_kind = strict_kind # inject default token default_token = subdb.get_default_token(parsed_kind) end end end # process pattern content's pattern_content.scan(TOKENS_REGEXP) do ext_token = $1.to_s # token(s) ext_value = $2.to_s # value of token(s) ext_freetext = $3.to_s # freetext if any ext_tokens = nil tokens = Hash.new(false) negatives = Hash.new(false) kind = nil passed_token = nil result = nil # TOKEN GROUP PROCESSING # token not found? if ext_token.empty? # free text not found too? that should never happend. if ext_freetext.empty? raise I18n::InvalidInflectionToken.new(locale, ext_pattern, ext_token) if raises end next end # unroll wildcard token if ext_token == Operators::Tokens::WILDCARD if parsed_kind.nil? # wildcard for a regular kind that we do not know yet wildcard_value = ext_value else # wildcard for a known strict or regular kind ext_tokens = subdb.each_true_token(parsed_kind).each_key.map{|k|k.to_s} end end # split groupped tokens if comma is present and put into fast list ext_tokens = ext_token.split(Operators::Token::OR) if ext_tokens.nil? # for each token from group ext_tokens.each do |t| # token name corrupted if t.to_s.empty? raise I18n::InvalidInflectionToken.new(locale, ext_pattern, t) if raises next end # mark negative-matching token and put it on the negatives fast list if t[0..0] == Operators::Token::NOT t = t[1..-1] negative = true else negative = false end # is token name corrupted? if Reserved::Tokens.invalid?(t, :PATTERN) raise I18n::InvalidInflectionToken.new(locale, ext_pattern, t) if raises next end t = t.to_sym t = subdb.get_true_token(t, strict_kind) if aliased_patterns negatives[t] = true if negative # get a kind for that token kind = subdb.get_kind(t, strict_kind) if kind.nil? if raises # regular pattern and token that has a bad kind if strict_kind.nil? raise I18n::InvalidInflectionToken.new(locale, ext_pattern, t, sym_parsed_kind) else # named pattern (kind validated before, so the only error is misplaced token) raise I18n::MisplacedInflectionToken.new(locale, ext_pattern, t, sym_parsed_kind) end end next end # set processed kind after matching first token in a pattern if parsed_kind.nil? parsed_kind = kind sym_parsed_kind = kind.to_sym default_token = subdb.get_default_token(parsed_kind) elsif parsed_kind != kind # tokens of different kinds in one regular (not named) pattern are prohibited raise I18n::MisplacedInflectionToken.new(locale, ext_pattern, t, sym_parsed_kind) if raises next end # use that token unless negatives[t] tokens[t] = true default_value = ext_value if t == default_token end end # token group processing # self-explanatory if (tokens.empty? && negatives.empty?) raise I18n::InvalidInflectionToken.new(locale, ext_pattern, ext_token) if raises end # INFLECTION OPTION PROCESSING # set up expected_kind depending on type of a kind if strict_kind.nil? expected_kind = parsed_kind else expected_kind = sym_parsed_kind expected_kind = parsed_kind unless passed_kinds.has_key?(expected_kind) end # get passed token from options or from a default token if passed_kinds.has_key?(expected_kind) passed_token = passed_kinds[expected_kind] if passed_token.is_a?(Method) passed_token = passed_token.call { next expected_kind, locale } passed_kinds[expected_kind] = passed_token # cache the result elsif passed_token.is_a?(Proc) passed_token = passed_token.call(expected_kind, locale) passed_kinds[expected_kind] = passed_token # cache the result end orig_passed_token = passed_token # validate passed token's name if Reserved::Tokens.invalid?(passed_token, :OPTION) raise I18n::InvalidInflectionOption.new(locale, ext_pattern, orig_passed_token) if raises passed_token = default_token if unknown_defaults end else # current inflection option wasn't found # but delay this exception because we might use # the default token if found somewhere in a pattern tb_raised = InflectionOptionNotFound.new(locale, ext_pattern, ext_token, expected_kind, orig_passed_token) if raises passed_token = default_token orig_passed_token = nil end # explicit default passed_token = default_token if passed_token == Keys::DEFAULT_TOKEN # resolve token from options and check if it's known unless passed_token.nil? passed_token = subdb.get_true_token(passed_token.to_s.to_sym, parsed_kind) passed_token = default_token if passed_token.nil? && unknown_defaults end # handle memorized wildcard waiting for a kind if !wildcard_value.nil? && !parsed_kind.nil? found = passed_token result = wildcard_value wildcard_value = nil break end # throw the value if the given option matches one of the tokens from group # or negatively matches one of the negated tokens case negatives.count when 0 then next unless tokens[passed_token] when 1 then next if negatives[passed_token] end # skip further evaluation of the pattern # since the right token has been found found = passed_token result = ext_value break end # single token (or a group) processing # RESULTS PROCESSING # handle memorized wildcard token # when there was no way to deduce a token or a kind # it's just for regular kinds unless (wildcard_value.nil? || passed_kinds.nil?) parsed_kind = nil found = nil passed_kinds.each do |k, ot| t = subdb.get_true_token(ot, k) if Reserved::Tokens.invalid?(t, :OPTION) raise I18n::InvalidInflectionOption.new(locale, ext_pattern, ot) if raises next end unless t.nil? found = t parsed_kind = k break end end unless (parsed_kind.nil? || found.nil?) result = wildcard_value wildcard_value = nil else found = nil parsed_kind = nil end end # if there was no hit for that option if result.nil? raise tb_raised unless tb_raised.nil? # try to extract default token's value # if there is excluded_defaults switch turned on # and a correct token was found in an inflection option but # has not been found in a pattern then interpolate # the pattern with a value picked for the default # token for that kind if a default token was present # in a pattern if (excluded_defaults && !parsed_kind.nil?) expected_kind = sym_parsed_kind expected_kind = parsed_kind unless passed_kinds.has_key?(expected_kind) t = passed_kinds[expected_kind] if t.is_a?(Method) t = t.call { next expected_kind, locale } passed_kinds[expected_kind] = t # cache the result elsif t.is_a?(Proc) t = t.call(expected_kind, locale) passed_kinds[expected_kind] = t # cache the result end if Reserved::Tokens.invalid?(t, :OPTION) raise I18n::InvalidInflectionOption.new(locale, ext_pattern, t) if raises end result = subdb.has_token?(t, parsed_kind) ? default_value : nil end # interpolate loud tokens elsif result == Markers::LOUD_VALUE result = subdb.get_description(found, parsed_kind) # interpolate escaped loud tokens or other escaped strings elsif result[0..0] == Escapes::ESCAPE result.sub!(Escapes::ESCAPE_R, '\1') end "" << pattern_fix << (result || ext_freetext) end # single pattern processing end # def interpolate # This is a helper that reduces a complex inflection pattern # by producing equivalent of regular patterns of it and # by interpolating them using {#interpolate} method. # # @param [String] complex_kind the complex kind (many kinds separated # by the {Operators::Tokens::AND}) # @param [String] content the content of the processed pattern # @param [Symbol] locale the locale to use # @param [Hash] options the options # @return [String] the interpolated pattern def interpolate_complex(complex_kind, content, locale, options) result = nil free_text = "" kinds = complex_kind.split(Operators::Tokens::AND). reject{ |k| k.nil? || k.empty? }.each begin content.scan(TOKENS_REGEXP) do |tokens, value, free| if tokens.nil? raise IndexError.new if free.empty? free_text = free next end kinds.rewind # process each token from set results = tokens.split(Operators::Tokens::AND).map do |token| raise IndexError.new if token.empty? if value == Markers::LOUD_VALUE r = interpolate_core("" << Markers::PATTERN << kinds.next.to_s << Markers::PATTERN_BEGIN << token.to_s << Operators::Tokens::ASSIGN << value.to_s << Operators::Tokens::OR << Markers::PATTERN << Markers::PATTERN_END, locale, options) break if r == Markers::PATTERN # using this marker only as a helper to indicate empty result! else r = interpolate_core("" << Markers::PATTERN << kinds.next.to_s << Markers::PATTERN_BEGIN << token.to_s << Operators::Tokens::ASSIGN << value.to_s << Markers::PATTERN_END, locale, options) break if r != value # stop with this set, because something is not matching end r end # some token didn't matched, try another set next if results.nil? # generate result for set or raise error if results.size == kinds.count result = value == Markers::LOUD_VALUE ? results.join(' ') : value break else raise IndexError.new end end # scan tokens rescue IndexError, StopIteration if options[:inflector_raises] raise I18n::ComplexPatternMalformed.new(locale, content, nil, complex_kind) end result = nil end result || free_text end # def interpolate_complex end # module Interpolate end # module Inflector end # module I18n ruby-i18n-inflector-2.6.6/lib/i18n-inflector/lazy_enum.rb000066400000000000000000000151551204270775600231270ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains lazy enumerators. module I18n module Inflector if RUBY_VERSION.gsub(/\D/,'')[0..1].to_i < 19 require 'enumerator' rescue nil class LazyEnumerator < Object.const_defined?(:Enumerator) ? Enumerator : Enumerable::Enumerator # This class allows to initialize the Enumerator with a block class Yielder def initialize(&block) @main_block = block end def each(&block) @final_block = block @main_block.call(self) end if Proc.method_defined?(:yield) def yield(*arg) @final_block.yield(*arg) end else def yield(*arg) @final_block.call(*arg) end end if method_defined?(:yield) and not method_defined?(:"<<") alias_method :"<<", :yield end end unless (self.new{} rescue false) def initialize(*args, &block) args.empty? ? super(Yielder.new(&block)) : super(*args, &nil) end end if method_defined?(:with_object) and not method_defined?(:each_with_object) alias_method :each_with_object, :with_object end end # class LazyEnumerator for ruby18 else # if RUBY_VERSION >= 1.9.0 class LazyEnumerator < Enumerator end end # This class adds some lazy operations for collections class LazyEnumerator # Addition operator for collections # @return [I18n::Inflector::LazyEnumerator] the enumerator def +(other) self.class.new do |yielder| each do |v| yielder << v end other.each do |v| yielder << v end end end # Insertion operator for collections # @return [I18n::Inflector::LazyEnumerator] the enumerator def insert(value) self.class.new do |yielder| yielder << value each do |v| yielder << v end end end # Appending operator for collections # @return [I18n::Inflector::LazyEnumerator] the enumerator def append(value) self.class.new do |yielder| each do |v| yielder << v end yielder << value end end # Mapping enumerator # @return [I18n::Inflector::LazyEnumerator] the enumerator def map(&block) self.class.new do |yielder| each do |v| yielder << block[v] end end end # Selecting enumerator # @return [I18n::Inflector::LazyEnumerator] the enumerator def select(&block) self.class.new do |yielder| each do |v| yielder << v if block[v] end end end # Rejecting enumerator # @return [I18n::Inflector::LazyEnumerator] the enumerator def reject(&block) self.class.new do |yielder| each do |v| yielder << v unless block[v] end end end # Checks if a collection is empty # @return [Boolean] +true+ if collection is empty, +false+ otherwise def empty? self.class.new do |yielder| each do |k,v| return false end end true end end # This class implements simple enumerators for arrays # that allow to do lazy operations on them. class LazyArrayEnumerator < LazyEnumerator end # This class implements simple enumerators for hashes # that allow to do lazy operations on them. class LazyHashEnumerator < LazyEnumerator # Creates a Hash kind of object by collecting all # data from enumerated collection. # @return [Hash] the resulting hash def to_h h = Hash.new each{|k,v| h[k]=v } h end # Insertion operator for Hash enumerators # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def insert(key, value) self.class.new do |yielder| yielder.yield(key, value) each do |k,v| yielder.yield(k,v) end end end # Appending operator for Hash enumerators # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def append(key, value) self.class.new do |yielder| each do |k,v| yielder.yield(k,v) end yielder.yield(key, value) end end # Hash mapping enumerator # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def map(&block) LazyHashEnumerator.new do |yielder| each do |k,v| yielder.yield(k,block[k,v]) end end end # Hash to Array mapping enumerator # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def ary_map(&block) LazyHashEnumerator.new do |yielder| each do |value| yielder << block[value] end end end # This method converts resulting keys # to an array. def keys ary = [] each{ |k,v| ary << k } return ary end # This method converts resulting values # to an array. def values ary = [] each{ |k,v| ary << v } return ary end # Keys enumerator # @return [I18n::Inflector::LazyArrayEnumerator.new] the enumerator def each_key(&block) LazyArrayEnumerator.new do |yielder| each do |k,v| yielder << k end end end # Values enumerator # @return [I18n::Inflector::LazyArrayEnumerator.new] the enumerator def each_value(&block) LazyArrayEnumerator.new do |yielder| each do |k,v| yielder << v end end end # Hash selecting enumerator # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def select(&block) self.class.new do |yielder| each do |k,v| yielder.yield(k,v) if block[k,v] end end end # Hash rejecting enumerator # @return [I18n::Inflector::LazyHashEnumerator] the enumerator def reject(&block) self.class.new do |yielder| each do |k,v| yielder.yield(k,v) unless block[k,v] end end end end # class LazyHashEnumerator end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/long_comments.rb000066400000000000000000000045201204270775600237620ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains inline documentation data # that would make the file with code less readable # if placed there. Code from this file is not used # by the library, it's just for documentation. module I18n module Inflector class API # This reader allows to reach a reference of the # object that is a kind of {I18n::Inflector::API_Strict} # and handles inflections for named patterns (strict kinds). # # @api public # @return [I18n::Inflector::API_Strict] the object containing # database and operations for named patterns (strict kinds) attr_reader :strict # This reader allows to reach internal configuration # of the engine. It is shared among all instances of # the Inflector and also available as # {I18n::Inflector::Config I18n::Inflector::Config}. attr_reader :config # Gets known regular inflection kinds. # # @api public # @note To get all inflection kinds (regular and strict) for default inflector # use: I18n.inflector.kinds + I18n.inflector.strict.kinds # @return [Array] the array containing known inflection kinds # @raise [I18n::InvalidLocale] if there is no proper locale name # @overload kinds # Gets known inflection kinds for the current locale. # @return [Array] the array containing known inflection kinds # @overload kinds(locale) # Gets known inflection kinds for the given +locale+. # @param [Symbol] locale the locale for which operation has to be done # @return [Array] the array containing known inflection kinds def kinds(locale=nil); super end alias_method :inflection_kinds, :kinds end end # @abstract This exception class is defined in package I18n. It is raised when # the given and/or processed locale parameter is invalid. class InvalidLocale; end # @abstract This exception class is defined in package I18n. It is raised when # the given and/or processed translation data or parameter are invalid. class ArgumentError; end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/options.rb000066400000000000000000000314651204270775600226210ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains a class used to set up some options, # for engine. module I18n module Inflector # This class contains structures for keeping parsed translation data # and basic operations. # # All global options are available for current backend's inflector by # calling: # I18n.backend.inflector.options. # or just: # I18n.inflector.options. # A global option may be overriden by passing a proper option to # the translation method. Such option should have the name of a # global option but prefixed with +inflector_+: # translate('welcome', :inflector_ => value) # @note This class uses modified version of +attr_accessor+ that # memorizes any added method name as an option name. These options # (with +inflector_+ prefix added) are accessible through # {#known} method. The last method is used by options preparing # routine when the interpolation is performed. class InflectionOptions # Prefix used to mark option as a controlling option. OPTION_PREFIX = 'inflector_' class <options.options.prepare_options!(options) on the used backend, # for example: # I18n.backend.inflector.options.prepare(options) # That will alter the +options+ data so they will contain all switches # and values. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch attr_accessor :cache_aware # This is a switch that enables extended error reporting. When it's enabled then # errors are raised in case of unknown or empty tokens present in a pattern # or in options. This switch is by default set to +false+. # # @note Local option +:inflector_raises+ passed # to the {I18n::Backend::Inflector#translate} overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch attr_accessor :raises # This is a switch that enables you to use aliases in patterns. When it's enabled then # aliases may be used in inflection patterns, not only true tokens. This operation # may make your translation data a bit messy if you're not alert. # That's why this switch is by default set to +false+. # # @note Local option +:inflector_aliased_patterns+ passed to the # {I18n::Backend::Inflector#translate} overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch attr_accessor :aliased_patterns # This is a switch that enables you to interpolate patterns contained # in resulting nested Hashes. It is used when the original translation # method returns a subtree of translation data because the given key # is not pointing to a leaf of the data but to some collection. # # This switch is by default set to +true+. When you turn it off then # the Inflector won't touch nested results and will return them as they are. # # @note Local option +:inflector_traverses+ passed to the # {I18n::Backend::Inflector#translate} overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch attr_accessor :traverses # This is a switch that enables interpolation of symbols. Whenever # interpolation method will receive a collection of symbols as a result # of calling underlying translation method # it won't process them, returning as they are, unless # this switch is enabled. # # Note that using symbols as values in translation data creates # I18n aliases. This option is intended to work with arrays of # symbols or hashes with symbols as values, if the original translation # method returns such structures. # # This switch is by default set to +false+. # # @note Local option +:inflector_interpolate_symbols+ passed to the # {I18n::Backend::Inflector#translate} overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch attr_accessor :interpolate_symbols # When this switch is set to +true+ then inflector falls back to the default # token for a kind if an inflection option passed to the # {I18n::Backend::Inflector#translate} is unknown or +nil+. # Note that the value of the default token will be # interpolated only when this token is present in a pattern. This switch # is by default set to +true+. # # @note Local option +:inflector_unknown_defaults+ passed # to the {I18n::Backend::Inflector#translate} overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch # # @example YAML: # en: # i18n: # inflections: # gender: # n: 'neuter' # o: 'other' # default: n # # welcome: "Dear @{n:You|o:Other}" # welcome_free: "Dear @{n:You|o:Other|Free}" # # @example Example 1 # # # :gender option is not present, # # unknown tokens in options are falling back to default # # I18n.t('welcome') # # => "Dear You" # # # :gender option is not present, # # unknown tokens from options are not falling back to default # # I18n.t('welcome', :inflector_unknown_defaults => false) # # => "Dear You" # # # other way of setting an option – globally # # I18n.inflector.options.unknown_defaults = false # I18n.t('welcome') # # => "Dear You" # # # :gender option is not present, free text is present, # # unknown tokens from options are not falling back to default # # I18n.t('welcome_free', :inflector_unknown_defaults => false) # # => "Dear You" # # @example Example 2 # # # :gender option is nil, # # unknown tokens from options are falling back to default token for a kind # # I18n.t('welcome', :gender => nil) # # => "Dear You" # # # :gender option is nil # # unknown tokens from options are not falling back to default token for a kind # # I18n.t('welcome', :gender => nil, :inflector_unknown_defaults => false) # # => "Dear " # # # :gender option is nil, free text is present # # unknown tokens from options are not falling back to default token for a kind # # I18n.t('welcome_free', :gender => nil, :inflector_unknown_defaults => false) # # => "Dear Free" # # @example Example 3 # # # :gender option is unknown, # # unknown tokens from options are falling back to default token for a kind # # I18n.t('welcome', :gender => :unknown_blabla) # # => "Dear You" # # # :gender option is unknown, # # unknown tokens from options are not falling back to default token for a kind # # I18n.t('welcome', :gender => :unknown_blabla, :inflector_unknown_defaults => false) # # => "Dear " # # # :gender option is unknown, free text is present # # unknown tokens from options are not falling back to default token for a kind # # I18n.t('welcome_free', :gender => :unknown_blabla, :inflector_unknown_defaults => false) # # => "Dear Free" attr_accessor :unknown_defaults # When this switch is set to +true+ then inflector falls back to the default # token for a kind if the given inflection option is correct but doesn't exist # in a pattern. # # There might happen that the inflection option # given to {#translate} method will contain some proper token, but that token # will not be present in a processed pattern. Normally an empty string will # be generated from such a pattern or a free text (if a local fallback is present # in a pattern). You can change that behavior and tell interpolating routine to # use the default token for a processed kind in such cases. # # This switch is by default set to +false+. # # @note Local option +:inflector_excluded_defaults+ passed to the {I18n::Backend::Inflector#translate} # overrides this setting. # # @api public # @return [Boolean] state of the switch # @param [Boolean] state +true+ enables, +false+ disables this switch # # @example YAML: # en: # i18n: # inflections: # gender: # o: "other" # m: "male" # n: "neuter" # default: n # # welcome: 'Dear @{n:You|m:Sir}' # @example Usage of +:inflector_excluded_defaults+ option # I18n.t('welcome', :gender => :o) # # => "Dear " # # I18n.t('welcome', :gender => :o, :inflector_excluded_defaults => true) # # => "Dear You" attr_accessor :excluded_defaults # This method initializes all internal structures. def initialize reset end # This method resets all options to their default values. # # @return [void] def reset @unknown_defaults = true @traverses = true @interpolate_symbols= false @excluded_defaults = false @aliased_patterns = false @cache_aware = false @raises = false nil end # This method processes the given argument # in a way that it will use default values # for options that are missing. # # @api public # @note It modifies the given object. # @param [Hash] options the options # @return [Hash] the given options def prepare_options!(options) self.class.known. reject { |name,long| options.has_key?(long) }. each { |name,long| options[long] = instance_variable_get(name) } options end # This method prepares options for translate method. # That means removal of all kind-related options # and all options that are flags. # # @api public # @note It modifies the given object. # @param [Hash] options the given options # @return [Hash] the given options def clean_for_translate!(options) self.class.known.each { |name,long| options.delete long } options end # Lists all known options in a long format # (each name preceeded by inflector_). # # @api public # @return [Array] the known options def known self.class.known.values end end end end ruby-i18n-inflector-2.6.6/lib/i18n-inflector/version.rb000066400000000000000000000014431204270775600226040ustar00rootroot00000000000000# encoding: utf-8 # # Author:: Paweł Wilk (mailto:pw@gnu.org) # Copyright:: (c) 2011,2012 by Paweł Wilk # License:: This program is licensed under the terms of {file:docs/LGPL GNU Lesser General Public License} or {file:docs/COPYING Ruby License}. # # This file contains version information. module I18n module Inflector # @private DEVELOPER = 'Paweł Wilk' # @private EMAIL = 'pw@gnu.org' # @private VERSION = '2.6.6' # @private NAME = 'i18n-inflector' # @private SUMMARY = 'Inflection module for I18n' # @private URL = 'https://rubygems.org/gems/i18n-inflector/' # @private DESCRIPTION = 'Enhances simple I18n backend in a way that it inflects translation data using pattern interpolation.' end end ruby-i18n-inflector-2.6.6/metadata.gz.sig000066400000000000000000000004001204270775600201550ustar00rootroot00000000000000[?Nс0Mc0Ds+jk͒$tnU?5{r0 a06žZ}K#}c?"EYƄ'RZDrĨØDiu55r}RVORy-J=PguQ.LWJ4=' - !ruby/object:Gem::Version version: 0.4.1 type: :runtime prerelease: false version_requirements: *2161408440 - !ruby/object:Gem::Dependency name: hoe-yard requirement: &2161407820 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 0.1.2 type: :development prerelease: false version_requirements: *2161407820 - !ruby/object:Gem::Dependency name: test_declarative requirement: &2161407160 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 0.0.5 type: :development prerelease: false version_requirements: *2161407160 - !ruby/object:Gem::Dependency name: yard requirement: &2161406440 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 0.7.2 type: :development prerelease: false version_requirements: *2161406440 - !ruby/object:Gem::Dependency name: rdoc requirement: &2161405660 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 3.8.0 type: :development prerelease: false version_requirements: *2161405660 - !ruby/object:Gem::Dependency name: bundler requirement: &2161405020 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 1.0.15 type: :development prerelease: false version_requirements: *2161405020 - !ruby/object:Gem::Dependency name: hoe-bundler requirement: &2161404300 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 1.1.0 type: :development prerelease: false version_requirements: *2161404300 - !ruby/object:Gem::Dependency name: hoe requirement: &2161403320 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '2.16' type: :development prerelease: false version_requirements: *2161403320 description: Enhances simple I18n backend in a way that it inflects translation data using pattern interpolation. email: - pw@gnu.org executables: [] extensions: [] extra_rdoc_files: - Manifest.txt - README.rdoc files: - .yardopts - ChangeLog - Gemfile - Gemfile.lock - LGPL-LICENSE - Manifest.txt - README.rdoc - Rakefile - ci/i18n-inflector.gemspec - ci/i18nv4-Gemfile - ci/i18nv4-Gemfile.lock - docs/COPYING - docs/EXAMPLES - docs/HISTORY - docs/LEGAL - docs/LGPL - docs/TODO - docs/USAGE - docs/rdoc.css - lib/i18n-inflector.rb - lib/i18n-inflector/api.rb - lib/i18n-inflector/api_strict.rb - lib/i18n-inflector/backend.rb - lib/i18n-inflector/config.rb - lib/i18n-inflector/errors.rb - lib/i18n-inflector/hset.rb - lib/i18n-inflector/inflection_data.rb - lib/i18n-inflector/inflection_data_strict.rb - lib/i18n-inflector/inflector.rb - lib/i18n-inflector/interpolate.rb - lib/i18n-inflector/lazy_enum.rb - lib/i18n-inflector/long_comments.rb - lib/i18n-inflector/options.rb - lib/i18n-inflector/version.rb - test/inflector_test.rb - test/test_helper.rb - .gemtest homepage: https://rubygems.org/gems/i18n-inflector/ licenses: [] post_install_message: rdoc_options: - --title - I18n::Inflector Documentation - --quiet require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' segments: - 0 hash: -404233212743185379 required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: i18n-inflector rubygems_version: 1.8.15 signing_key: specification_version: 3 summary: Inflection module for I18n test_files: - test/inflector_test.rb ruby-i18n-inflector-2.6.6/test/000077500000000000000000000000001204270775600162375ustar00rootroot00000000000000ruby-i18n-inflector-2.6.6/test/inflector_test.rb000066400000000000000000001477521204270775600216300ustar00rootroot00000000000000require 'test_helper' class I18nInflectorTest < Test::Unit::TestCase class Backend < I18n::Backend::Simple include I18n::Backend::Inflector include I18n::Backend::Fallbacks end def setup I18n.backend = Backend.new store_translations(:xx, :i18n => { :inflections => { :gender => { :m => 'male', :f => 'female', :n => 'neuter', :s => 'strange', :masculine => '@m', :feminine => '@f', :neuter => '@n', :neutral => '@neuter', :default => 'neutral' }, :person => { :i => 'I', :you => 'You'}, :@gender => { :m => 'male', :f => 'female', :n => 'neuter', :s => 'strange', :masculine => '@m', :feminine => '@f', :neuter => '@n', :neutral => '@neuter', :default => 'neutral' } } }) store_translations(:xx, 'welcome' => 'Dear @{f:Lady|m:Sir|n:You|All}!') store_translations(:xx, 'named_welcome' => 'Dear @gender{f:Lady|m:Sir|n:You|All}!') I18n.locale = :en end test "backend inflector has methods to test its switches" do assert_equal true, I18n.inflector.options.unknown_defaults = true assert_equal false, I18n.inflector.options.excluded_defaults = false assert_equal false, I18n.inflector.options.aliased_patterns = false assert_equal false, I18n.inflector.options.raises = false assert_equal false, I18n.backend.inflector.options.raises assert_equal true, I18n.backend.inflector.options.unknown_defaults assert_equal false, I18n.backend.inflector.options.excluded_defaults assert_equal false, I18n.backend.inflector.options.aliased_patterns end test "backend inflector store_translations: regenerates inflection structures when translations are loaded" do store_translations(:xx, :i18n => { :inflections => { :gender => { :o => 'other' }}}) store_translations(:xx, 'hi' => 'Dear @{f:Lady|o:Others|n:You|All}!') assert_equal 'Dear Others!', I18n.t('hi', :gender => :o, :locale => :xx) assert_equal 'Dear Lady!', I18n.t('hi', :gender => :f, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => :unknown, :locale => :xx) assert_equal 'Dear All!', I18n.t('hi', :gender => :m, :locale => :xx) end test "backend inflector store_translations: raises I18n::DuplicatedInflectionToken when duplicated token is given" do assert_raise I18n::DuplicatedInflectionToken do store_translations(:xx, :i18n => { :inflections => { :gender => { :o => 'other' }, :person => { :o => 'o' }}}) end end test "backend inflector strict store_translations: allows duplicated tokens across differend kinds" do assert_nothing_raised I18n::DuplicatedInflectionToken do store_translations(:xx, :i18n => { :inflections => { :@gender => { :o => 'other' }, :@person => { :o => 'o' }}}) store_translations(:xx, :i18n => { :inflections => { :gender => { :o => 'other' }, :@gender => { :o => 'o' }}}) end end test "backend inflector store_translations: raises I18n::BadInflectionAlias when bad alias is given" do assert_raise I18n::BadInflectionAlias do store_translations(:xx, :i18n => { :inflections => { :gender => { :o => '@xnonexistant' }}}) end end test "backend inflector store_translations: raises I18n::BadInflectionAlias when bad default is given" do assert_raise I18n::BadInflectionAlias do store_translations(:xx, :i18n => { :inflections => { :gender => { :default => '@ynonexistant' }}}) end end test "backend inflector strict store_translations: raises I18n::BadInflectionAlias when bad alias is given" do assert_raise I18n::BadInflectionAlias do store_translations(:xx, :i18n => { :inflections => { :@gender => { :oh => '@znonex' }}}) end end test "backend inflector strict store_translations: raises I18n::BadInflectionAlias when bad default is given" do assert_raise I18n::BadInflectionAlias do store_translations(:xx, :i18n => { :inflections => { :@gender => { :default => '@cnonex' }}}) end end test "backend inflector store_translations: raises I18n::BadInflectionToken when bad token is given" do assert_raise I18n::BadInflectionToken do store_translations(:xx, :i18n => { :inflections => { :gender => { :o => '@' }}}) store_translations(:xx, :i18n => { :inflections => { :gender => { :tok => nil }}}) store_translations(:xx, :i18n => { :inflections => { :@gender => { :o => '@' }}}) store_translations(:xx, :i18n => { :inflections => { :@gender => { :tok => nil }}}) end end test "backend inflector translate: allows pattern-only translation data" do store_translations(:xx, 'clear_welcome' => '@{f:Lady|m:Sir|n:You|All}') assert_equal 'Lady', I18n.t('clear_welcome', :gender => 'f', :locale => :xx) store_translations(:xx, 'clear_welcome' => '@gender{f:Lady|m:Sir|n:You|All}') assert_equal 'Lady', I18n.t('clear_welcome', :gender => 'f', :locale => :xx) end test "backend inflector translate: allows patterns to be escaped using @@ or \\@" do store_translations(:xx, 'escaped_welcome' => '@@{f:AAAAA|m:BBBBB}') assert_equal '@{f:AAAAA|m:BBBBB}', I18n.t('escaped_welcome', :gender => 'f', :locale => :xx) store_translations(:xx, 'escaped_welcome' => '\@{f:AAAAA|m:BBBBB}') assert_equal '@{f:AAAAA|m:BBBBB}', I18n.t('escaped_welcome', :gender => 'f', :locale => :xx) assert_equal 'Dear All!', I18n.t('welcome', :gender => nil, :locale => :xx, :inflector_unknown_defaults => false) store_translations(:xx, 'escaped_welcome' => 'Dear \@{f:Lady|m:Sir|n:You|All}!'); assert_equal 'Dear @{f:Lady|m:Sir|n:You|All}!', I18n.t('escaped_welcome', :locale => :xx, :inflector_unknown_defaults => false) end test "backend inflector translate: picks Lady for :f gender option" do assert_equal 'Dear Lady!', I18n.t('welcome', :gender => :f, :locale => :xx) end test "backend inflector translate: picks Lady for f gender option" do assert_equal 'Dear Lady!', I18n.t('welcome', :gender => 'f', :locale => :xx) end test "backend inflector translate: picks Sir for :m gender option" do assert_equal 'Dear Sir!', I18n.t('welcome', :gender => :m, :locale => :xx) end test "backend inflector translate: picks Sir for :masculine gender option" do assert_equal 'Dear Sir!', I18n.t('welcome', :gender => :masculine, :locale => :xx) end test "backend inflector translate: picks Sir for masculine gender option" do assert_equal 'Dear Sir!', I18n.t('welcome', :gender => 'masculine', :locale => :xx) end test "backend inflector translate: picks an empty string when no default token is present and no free text is there" do store_translations(:xx, 'none_welcome' => '@{n:You|f:Lady}') assert_equal '', I18n.t('none_welcome', :gender => 'masculine', :locale => :xx) end test "backend inflector translate: allows multiple patterns in the same data" do store_translations(:xx, 'multiple_welcome' => '@@{f:AAAAA|m:BBBBB} @{f:Lady|m:Sir|n:You|All} @{f:Lady|All}@{m:Sir|All}@{n:You|All}') assert_equal '@{f:AAAAA|m:BBBBB} Sir AllSirAll', I18n.t('multiple_welcome', :gender => 'masculine', :locale => :xx) end test "backend inflector translate: falls back to default for the unknown gender option" do assert_equal 'Dear You!', I18n.t('welcome', :gender => :unknown, :locale => :xx) end test "backend inflector translate: falls back to default for a gender option set to nil" do assert_equal 'Dear You!', I18n.t('welcome', :gender => nil, :locale => :xx) end test "backend inflector translate: falls back to default for no gender option" do assert_equal 'Dear You!', I18n.t('welcome', :locale => :xx) end test "backend inflector translate: falls back to free text for the proper gender option but not present in pattern" do assert_equal 'Dear All!', I18n.t('welcome', :gender => :s, :locale => :xx) end test "backend inflector translate: falls back to free text when :inflector_unknown_defaults is false" do assert_equal 'Dear All!', I18n.t('welcome', :gender => :unknown, :locale => :xx, :inflector_unknown_defaults => false) assert_equal 'Dear All!', I18n.t('welcome', :gender => :s, :locale => :xx, :inflector_unknown_defaults => false) assert_equal 'Dear All!', I18n.t('welcome', :gender => nil, :locale => :xx, :inflector_unknown_defaults => false) end test "backend inflector translate: uses default token when inflection option is set to :default" do assert_equal 'Dear You!', I18n.t('welcome', :gender => :default, :locale => :xx, :inflector_unknown_defaults => true) assert_equal 'Dear You!', I18n.t('welcome', :gender => :default, :locale => :xx, :inflector_unknown_defaults => false) end test "backend inflector translate: falls back to default for no inflection option when :inflector_unknown_defaults is false" do assert_equal 'Dear You!', I18n.t('welcome', :locale => :xx, :inflector_unknown_defaults => false) end test "backend inflector translate: falls back to free text for the unknown gender option when global inflector_unknown_defaults is false" do I18n.inflector.options.unknown_defaults = false assert_equal 'Dear All!', I18n.t('welcome', :gender => :unknown, :locale => :xx) end test "backend inflector translate: falls back to default for the unknown gender option when global inflector_unknown_defaults is overriden" do I18n.inflector.options.unknown_defaults = false assert_equal 'Dear You!', I18n.t('welcome', :gender => :unknown, :locale => :xx, :inflector_unknown_defaults => true) end test "backend inflector translate: falls back to default token for ommited gender option when :inflector_excluded_defaults is true" do assert_equal 'Dear You!', I18n.t('welcome', :gender => :s, :locale => :xx, :inflector_excluded_defaults => true) assert_equal 'Dear You!', I18n.t('named_welcome', :@gender => :s, :locale => :xx, :inflector_excluded_defaults => true) I18n.inflector.options.excluded_defaults = true assert_equal 'Dear You!', I18n.t('welcome', :gender => :s, :locale => :xx) assert_equal 'Dear You!', I18n.t('named_welcome', :gender => :s, :locale => :xx) end test "backend inflector translate: falls back to free text for ommited gender option when :inflector_excluded_defaults is false" do assert_equal 'Dear All!', I18n.t('welcome', :gender => :s, :locale => :xx, :inflector_excluded_defaults => false) I18n.inflector.options.excluded_defaults = false assert_equal 'Dear All!', I18n.t('welcome', :gender => :s, :locale => :xx) end test "backend inflector translate: raises I18n::InvalidOptionForKind when bad kind is given and inflector_raises is true" do assert_nothing_raised I18n::InvalidOptionForKind do I18n.t('welcome', :locale => :xx, :inflector_raises => true) end tr = I18n.backend.send(:translations) tr[:xx][:i18n][:inflections][:gender].delete(:default) store_translations(:xx, :i18n => { :inflections => { :gender => { :o => 'other' }}}) assert_raise(I18n::InflectionOptionNotFound) { I18n.t('welcome', :locale => :xx, :inflector_raises => true) } assert_raise(I18n::InvalidInflectionOption) { I18n.t('welcome', :locale => :xx, :gender => "", :inflector_raises => true) } assert_raise(I18n::InvalidInflectionOption) { I18n.t('welcome', :locale => :xx, :gender => nil, :inflector_raises => true) } assert_raise I18n::InflectionOptionNotFound do I18n.inflector.options.raises = true I18n.t('welcome', :locale => :xx) end end test "backend inflector translate: raises I18n::MisplacedInflectionToken when misplaced token is given and inflector_raises is true" do store_translations(:xx, 'hi' => 'Dear @{f:Lady|i:BAD_TOKEN|n:You|First}!') assert_raise(I18n::MisplacedInflectionToken) { I18n.t('hi', :locale => :xx, :inflector_raises => true) } assert_raise I18n::MisplacedInflectionToken do I18n.inflector.options.raises = true I18n.t('hi', :locale => :xx) end end test "backend inflector translate: raises I18n::MisplacedInflectionToken when bad token is given and inflector_raises is true" do store_translations(:xx, 'hi' => 'Dear @{f:Lady|i:Me|n:You|First}!') assert_raise(I18n::MisplacedInflectionToken) { I18n.t('hi', :locale => :xx, :inflector_raises => true) } assert_raise I18n::MisplacedInflectionToken do I18n.inflector.options.raises = true I18n.t('hi', :locale => :xx) end end test "backend inflector translate: works with %{} patterns" do store_translations(:xx, 'hi' => 'Dear @{f:Lady|m:%{test}}!') assert_equal 'Dear Dude!', I18n.t('hi', :gender => :m, :locale => :xx, :test => "Dude") store_translations(:xx, 'to be' => '%{person} @{i:am|you:are}') assert_equal 'you are', I18n.t('to be', :person => :you, :locale => :xx) end test "backend inflector translate: works with doubled patterns" do store_translations(:xx, 'dd' => 'Dear @{f:Lady|m:Sir|All}! Dear @{f:Lady|m:Sir|All}!') assert_equal 'Dear Lady! Dear Lady!', I18n.t('dd', :gender => :f, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{f:Lady|m:%{test}}! Dear @{f:Lady|m:%{test}}!') assert_equal 'Dear Dude! Dear Dude!', I18n.t('hi', :gender => :m, :locale => :xx, :test => "Dude") end test "backend inflector translate: works with complex patterns" do store_translations(:xx, :i18n => { :inflections => { :@tense => { :s => 's', :now => 'now', :past => 'later', :default => 'now' }}}) store_translations(:xx, 'hi' => '@gender+tense{m+now:he is|f+past:she was} here!') assert_equal 'he is here!', I18n.t('hi', :gender => :m, :locale => :xx, :inflector_raises => true) assert_equal 'he is here!', I18n.t('hi', :gender => :m, :locale => :xx, :inflector_raises => true) assert_equal 'he is here!', I18n.t('hi', :gender => :m, :tense => :s, :locale => :xx, :inflector_excluded_defaults => true) assert_equal 'she was here!', I18n.t('hi', :gender => :f, :tense => :past, :locale => :xx, :inflector_raises => true) assert_equal 'she was here!', I18n.t('hi', :gender => :feminine, :tense => :past, :locale => :xx, :inflector_raises => true) store_translations(:xx, 'hi' => '@gender+tense{masculine+now:he is|feminine+past:she was}') assert_equal 'he is', I18n.t('hi', :gender => :m, :tense => :now, :inflector_aliased_patterns => true, :locale => :xx) assert_equal 'she was', I18n.t('hi', :gender => :f, :tense => :past, :inflector_aliased_patterns => true, :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{masculine+now:he is|feminine+past:she was}') assert_equal 'she was', I18n.t('hi', :gender => :f, :tense => :past, :inflector_aliased_patterns => true, :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{masculine+now:he is|feminine+past:she was}') assert_equal 'she was', I18n.t('hi', :gender => :feminine, :tense => :past, :inflector_aliased_patterns => true, :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{masculine+now:he is|m+past:he was}') assert_equal 'he was', I18n.t('hi', :gender => :m, :tense => :past, :inflector_aliased_patterns => true, :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{m+now:he is|masculine+past:he was}') assert_equal 'he was', I18n.t('hi', :gender => :m, :tense => :past, :inflector_aliased_patterns => true, :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{m+now:~|f+past:she was}') assert_equal 'male now', I18n.t('hi', :gender => :m, :tense => :now, :locale => :xx) end test "backend inflector translate: works with multiple patterns" do store_translations(:xx, 'hi' => '@gender{m:Sir|f:Lady}{m: Lancelot|f: Morgana}') assert_equal 'Sir Lancelot', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Lady Morgana', I18n.t('hi', :gender => :f, :locale => :xx) store_translations(:xx, 'hi' => '@{m:Sir|f:Lady}{m: Lancelot|f: Morgana}') assert_equal 'Sir Lancelot', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Lady Morgana', I18n.t('hi', :gender => :f, :locale => :xx) store_translations(:xx, 'hi' => 'Hi @{m:Sir|f:Lady}{m: Lancelot|f: Morgana}!') assert_equal 'Hi Sir Lancelot!', I18n.t('hi', :gender => :m, :locale => :xx) end test "backend inflector translate: works with key-based inflections" do I18n.backend.store_translations(:xx, '@hi' => { :m => 'Sir', :f => 'Lady', :n => 'You', :@free => 'TEST', :@prefix => 'Dear ', :@suffix => '!' }) assert_equal 'Dear Sir!', I18n.t('@hi', :gender => :m, :locale => :xx, :inflector_raises=>true) assert_equal 'Dear Lady!', I18n.t('@hi', :gender => :f, :locale => :xx, :inflector_raises=>true) assert_equal 'Dear TEST!', I18n.t('@hi', :gender => :x, :locale => :xx, :inflector_unknown_defaults => false) assert_equal 'Dear TEST!', I18n.t('@hi', :gender => :x, :locale => :xx, :inflector_unknown_defaults => false) end test "backend inflector translate: raises I18n::ComplexPatternMalformed for malformed complex patterns" do store_translations(:xx, :i18n => { :inflections => { :@tense => { :now => 'now', :past => 'later', :default => 'now' }}}) store_translations(:xx, 'hi' => '@gender+tense{m+now+cos:he is|f+past:she was} here!') assert_raise I18n::ComplexPatternMalformed do I18n.t('hi', :gender => :m, :person => :you, :locale => :xx, :inflector_raises => true) end store_translations(:xx, 'hi' => '@gender+tense{m+:he is|f+past:she was} here!') assert_raise I18n::ComplexPatternMalformed do I18n.t('hi', :gender => :m, :person => :you, :locale => :xx, :inflector_raises => true) end store_translations(:xx, 'hi' => '@gender+tense{+:he is|f+past:she was} here!') assert_raise I18n::ComplexPatternMalformed do I18n.t('hi', :gender => :m, :person => :you, :locale => :xx, :inflector_raises => true) end store_translations(:xx, 'hi' => '@gender+tense{m:he is|f+past:she was} here!') assert_raise I18n::ComplexPatternMalformed do I18n.t('hi', :gender => :m, :person => :you, :locale => :xx, :inflector_raises => true) end end test "backend inflector translate: works with wildcard tokens" do store_translations(:xx, 'hi' => 'Dear @{n:You|*:Any|All}!') assert_equal 'Dear You!', I18n.t('hi', :gender => :n, :locale => :xx) assert_equal 'Dear Any!', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Dear Any!', I18n.t('hi', :gender => :f, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => :xxxxxx, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :locale => :xx) end test "backend inflector translate: works with loud tokens" do store_translations(:xx, 'hi' => 'Dear @{m:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @gender{m:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{masculine:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx, :inflector_aliased_patterns => true) store_translations(:xx, 'hi' => 'Dear @{f,m:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{!n:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{!n:\~|n:You|All}!') assert_equal 'Dear ~!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{!n:\\\\~|n:You|All}!') assert_equal 'Dear \\~!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{*:~|n:You|All}!') assert_equal 'Dear male!', I18n.t('hi', :gender => :m, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{*:~|n:You|All}!') assert_equal 'Dear neuter!', I18n.t('hi', :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{m:abc|*:~|n:You|All}!') assert_equal 'Dear neuter!', I18n.t('hi', :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{*:~|All}!') assert_equal 'Dear All!', I18n.t('hi', :gender => :unasdasd, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{*:~|All}!') assert_equal 'Dear All!', I18n.t('hi', :gender => nil, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{*:~|All}!') assert_equal 'Dear neuter!', I18n.t('hi', :gender => :n, :locale => :xx) store_translations(:xx, :i18n => { :inflections => { :@tense => { :s => 's', :now => 'now', :past => 'later', :default => 'now' }}}) store_translations(:xx, 'hi' => 'Dear @gender+tense{*+*:~|All}!') assert_equal 'Dear male now!', I18n.t('hi', :gender => :m, :person => :i, :locale => :xx) assert_equal 'Dear neuter now!', I18n.t('hi', :locale => :xx) assert_equal 'Dear neuter later!', I18n.t('hi', :tense => :past, :locale => :xx) end test "backend inflector translate: works with tokens separated by commas" do store_translations(:xx, 'hi' => 'Dear @{f,m:Someone|n:You|All}!') assert_equal 'Dear Someone!', I18n.t('hi', :gender => :m, :locale => :xx) end test "backend inflector translate: works with collections" do h = Hash.new h[:hi2] = h[:hi] = "Dear Someone!" store_translations(:xx, 'welcomes' => {'hi' => 'Dear @{f,m:Someone|n:You|All}!', 'hi2' => 'Dear @{f,m:Someone|n:You|All}!'}) assert_equal h, I18n.t('welcomes', :gender => :m, :foo => 5, :locale => :xx) end test "backend inflector translate: works with arrays as results" do a = [ :one, :two, :three ] store_translations(:xx, 'welcomes' => {'hi' => a}) store_translations(:uu, 'welcomes' => {'hi' => a}) assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :xx) assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :uu) a = [ :one, :two, :"x@{m:man|woman}d" ] store_translations(:xx, 'welcomes' => {'hi' => a}) store_translations(:uu, 'welcomes' => {'hi' => a}) assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :xx) assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :uu) a = [ :one, :two, :xmand ] assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :xx, :inflector_interpolate_symbols => true) a = [ :one, :two, :xd ] assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :uu, :inflector_interpolate_symbols => true) a = [ :one, :two, :"x@{m:man|woman}d" ] assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :xx, :inflector_traverses => false, :inflector_interpolate_symbols => true) a = [ :one, :two, :"x@{m:man|woman}d" ] assert_equal a, I18n.t('welcomes.hi', :gender => :m, :locale => :uu, :inflector_traverses => false, :inflector_interpolate_symbols => true) end test "backend inflector translate: works with other types as results" do store_translations(:xx, 'welcomes' => {'hi' => 31337}) assert_equal 31337, I18n.t('welcomes.hi', :gender => :m, :locale => :xx) end test "backend inflector translate: works with negative tokens" do store_translations(:xx, 'hi' => 'Dear @{!m:Lady|m:Sir|n:You|All}!') assert_equal 'Dear Lady!', I18n.t('hi', :gender => :n, :locale => :xx) assert_equal 'Dear Sir!', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Dear Lady!', I18n.t('hi', :locale => :xx) assert_equal 'Dear Lady!', I18n.t('hi', :gender => :unknown, :locale => :xx) store_translations(:xx, 'hi' => 'Hello @{!m:Ladies|n:You}') assert_equal 'Hello Ladies', I18n.t('hi', :gender => :n, :locale => :xx) assert_equal 'Hello Ladies', I18n.t('hi', :gender => :f, :locale => :xx) assert_equal 'Hello ', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Hello Ladies', I18n.t('hi', :locale => :xx) store_translations(:xx, 'hi' => 'Hello @{!n:Ladies|m,f:You}') assert_equal 'Hello ', I18n.t('hi', :locale => :xx, :inflector_raises => false) end test "backend inflector translate: works with tokens separated by commas and negative tokens" do store_translations(:xx, 'hi' => 'Dear @{!f,!m:Someone|m:Sir}!') assert_equal 'Dear Someone!', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Dear Someone!', I18n.t('hi', :gender => :n, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{!f,!m,n:Someone|m:Sir}!') assert_equal 'Dear Someone!', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Dear Someone!', I18n.t('hi', :gender => :n, :locale => :xx) store_translations(:xx, 'hi' => 'Dear @{!f,n:Someone|m:Sir|f:Lady}!') assert_equal 'Dear Someone!', I18n.t('hi', :gender => :m, :locale => :xx) assert_equal 'Dear Lady!', I18n.t('hi', :gender => :f, :locale => :xx) assert_equal 'Dear Someone!', I18n.t('hi', :locale => :xx) end test "backend inflector translate: works with aliased patterns" do store_translations(:xx, 'hi' => 'Dear @{masculine:Sir|feminine:Lady|n:You|All}!') assert_equal 'Dear Sir!', I18n.t('hi', :gender => :m, :locale => :xx, :inflector_aliased_patterns => true) assert_equal 'Dear Sir!', I18n.t('hi', :gender => :masculine, :locale => :xx, :inflector_aliased_patterns => true) assert_equal 'Dear Lady!', I18n.t('hi', :gender => :f, :locale => :xx, :inflector_aliased_patterns => true) assert_equal 'Dear Lady!', I18n.t('hi', :gender => :feminine, :locale => :xx, :inflector_aliased_patterns => true) assert_equal 'Dear All!', I18n.t('hi', :gender => :s, :locale => :xx, :inflector_aliased_patterns => true) assert_equal 'Dear You!', I18n.t('hi', :locale => :xx, :inflector_aliased_patterns => true) I18n.inflector.options.aliased_patterns = true assert_equal 'Dear Sir!', I18n.t('hi', :gender => :masculine, :locale => :xx) end test "backend inflector translate: works with Method and Proc object given as inflection options" do def femme kind, locale = yield (locale == :xx && kind == :gender) ? :f : :m end def excluded :s end def bad_method(a,b,c) :m end procek = method(:femme) procun = method(:excluded) badmet = method(:bad_method) assert_equal 'Dear Lady!', I18n.t('welcome', :gender => procek, :locale => :xx, :inflector_raises => true) assert_equal 'Dear Lady!', I18n.t('named_welcome', :gender => procek, :locale => :xx, :inflector_raises => true) assert_equal 'Dear Sir!', I18n.t('named_welcome', :@gender => procek, :locale => :xx, :inflector_raises => true) assert_equal 'Dear You!', I18n.t('named_welcome', :@gender => procun, :locale => :xx, :inflector_excluded_defaults => true) assert_equal 'Dear All!', I18n.t('named_welcome', :@gender => procun, :locale => :xx, :inflector_excluded_defaults => false) assert_raise(ArgumentError) { I18n.t('named_welcome', :@gender => badmet, :locale => :xx, :inflector_raises => true) } assert_equal 'Dear Sir!', I18n.t('named_welcome', :@gender => lambda{|k,l|:m}, :locale => :xx, :inflector_raises => true) assert_equal 'Dear Lady!', I18n.t('welcome', :gender => lambda{|k,l| k==:gender ? :f : :s}, :locale => :xx, :inflector_raises => true) end test "backend inflector translate: recognizes named patterns and strict kinds" do store_translations(:xx, :i18n => { :inflections => { :@gender => { :s => 'sir', :o => 'other', :s => 'a', :n => 'n', :default => 'n' }}}) store_translations(:xx, 'hi' => 'Dear @gender{s:Sir|o:Other|n:You|All}!') assert_equal 'Dear Sir!', I18n.t('hi', :gender => :s, :locale => :xx) assert_equal 'Dear Other!', I18n.t('hi', :gender => :o, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => "", :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => :unknown, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :@gender => :unknown, :locale => :xx) end test "backend inflector translate: prioritizes @-style kinds in options for named patterns" do store_translations(:xx, :i18n => { :inflections => { :@gender => { :s => 'sir', :o => 'other', :s => 'a', :n => 'n', :default => 'n' }}}) store_translations(:xx, 'hi' => 'Dear @gender{s:Sir|o:Other|n:You|All}!') assert_equal 'Dear Sir!', I18n.t('hi', :gender => :s, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => :s, :@gender => :unknown, :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => :s, :@gender => nil, :locale => :xx) assert_equal 'Dear Sir!', I18n.t('hi', :gender => :s, :@gender => :s, :locale => :xx) end test "backend inflector translate: is immune to reserved or bad content" do store_translations(:xx, :i18n => { :inflections => { :@gender => { :s => 'sir', :o => 'other', :s => 'a', :n => 'n', :default => 'n' }}}) store_translations(:xx, :i18n => { :inflections => { :@tense => { :now => ''}}}) store_translations(:xx, 'hi' => 'Dear @nonexistant{s:Sir|o:Other|n:You|All}!') assert_equal 'Dear All!', I18n.t('hi', :gender => 'm', :locale => :xx) store_translations(:xx, 'hi' => 'Dear @gender{s:Sir|o:Other|n:You|All}!') assert_equal 'Dear You!', I18n.t('hi', :gender => '@', :@gender => '+', :locale => :xx) assert_equal 'Dear You!', I18n.t('hi', :gender => '', :@gender => '', :locale => :xx) store_translations(:xx, 'hi' => '@gender+tense{m+now:~|f+past:she was}') assert_equal 'male ', I18n.t('hi', :gender => :m, :tense => :now, :locale => :xx) assert_raise I18n::ArgumentError do I18n.t('', :gender => :s, :locale => :xx) end assert_raise I18n::InvalidInflectionKind do store_translations(:xx, 'hop' => '@gen,der{m+now:~|f+past:she was}') I18n.t('hop', :gender => :s, :locale => :xx, :inflector_raises => true) end assert_raise I18n::InvalidInflectionToken do I18n.backend.store_translations(:xx, 'hop' => '@{m+now:~|f+past:she was}') I18n.t('hop', :gender => :s, :locale => :xx, :inflector_raises => true) end assert_raise I18n::InvalidInflectionKind do store_translations(:xx, 'hi' => 'Dear @uuuuuuuu{s:Sir|o:Other|n:You|All}!') I18n.t('hi', :gender => 'm', :locale => :xx, :inflector_raises => true) end assert_raise I18n::MisplacedInflectionToken do store_translations(:xx, 'hi' => 'Dear @tense{s:Sir|o:Other|n:You|All}!') I18n.t('hi', :gender => 'm', :locale => :xx, :inflector_raises => true) end I18n.backend = Backend.new assert_raise I18n::BadInflectionKind do store_translations(:xx, :i18n => { :inflections => { :@gender => 'something' }}) end I18n.backend = Backend.new store_translations(:xx, 'hi' => '@gender+tense{m+now:~|f+past:she was}') assert_equal '', I18n.t('hi', :gender => :s, :@gender => :s, :locale => :xx) assert_raise I18n::BadInflectionToken do store_translations(:xx, :i18n => { :inflections => { :@gender => { :sb => '@', :d=>'1'}}}) end I18n.backend = Backend.new assert_raise I18n::BadInflectionToken do store_translations(:xx, :i18n => { :inflections => { :@gender => { :sa => nil, :d=>'1'}}}) end I18n.backend = Backend.new assert_raise I18n::BadInflectionToken do store_translations(:xx, :i18n => { :inflections => { :@gender => { '' => 'a', :d=>'1'}}}) end ['@',',','cos,cos','@cos+cos','+','cos!cos',':','cos:',':cos','cos:cos','!d'].each do |token| I18n.backend = Backend.new assert_raise I18n::BadInflectionToken do store_translations(:xx, :i18n => { :inflections => { :@gender => { token.to_sym => 'a', :d=>'1' }}}) end end ['@',',','inflector_something','default','cos,cos','@cos+cos','+','cos!cos',':','cos:',':cos','cos:cos','!d'].each do |kind| I18n.backend = Backend.new assert_raise I18n::BadInflectionKind do store_translations(:xx, :i18n => { :inflections => { kind.to_sym => { :s => 'a', :d=>'1' }}}) end end end test "inflector inflected_locales: lists languages that support inflection" do assert_equal [:xx], I18n.inflector.inflected_locales assert_equal [:xx], I18n.inflector.inflected_locales(:gender) end test "inflector.strict inflected_locales: lists languages that support inflection" do assert_equal [:xx], I18n.inflector.strict.inflected_locales assert_equal [:xx], I18n.inflector.strict.inflected_locales(:gender) store_translations(:yy, :i18n => { :inflections => { :@person => { :s => 'sir'}}}) assert_equal [:xx], I18n.inflector.strict.inflected_locales(:gender) assert_equal [:yy], I18n.inflector.strict.inflected_locales(:person) assert_equal [:xx], I18n.inflector.inflected_locales(:gender) assert_equal [:yy], I18n.inflector.inflected_locales(:@person) assert_equal [:xx,:yy], I18n.inflector.inflected_locales.sort{|k,v| k.to_s<=>v.to_s} assert_equal [:xx,:yy], I18n.inflector.strict.inflected_locales.sort{|k,v| k.to_s<=>v.to_s} store_translations(:zz, :i18n => { :inflections => { :some => { :s => 'sir'}}}) assert_equal [:xx,:yy,:zz], I18n.inflector.inflected_locales.sort{|k,v| k.to_s<=>v.to_s} assert_equal [:xx,:yy], I18n.inflector.strict.inflected_locales.sort{|k,v| k.to_s<=>v.to_s} assert_equal [], I18n.inflector.inflected_locales(:@some) assert_equal [:zz], I18n.inflector.inflected_locales(:some) end test "inflector inflected_locale?: tests if the given locale supports inflection" do assert_equal true, I18n.inflector.inflected_locale?(:xx) I18n.locale = :xx assert_equal true, I18n.inflector.inflected_locale? end test "inflector.strict inflected_locale?: tests if the given locale supports inflection" do assert_equal true, I18n.inflector.strict.inflected_locale?(:xx) I18n.locale = :xx assert_equal true, I18n.inflector.strict.inflected_locale? end test "inflector new_database creates a database with inflections" do assert_kind_of I18n::Inflector::InflectionData, I18n.inflector.new_database(:yy) assert_equal true, I18n.inflector.inflected_locale?(:yy) assert_equal false, I18n.inflector.inflected_locale?(:yyyyy) end test "inflector add_database adds existing database with inflections" do db = I18n::Inflector::InflectionData.new(:zz) assert_kind_of I18n::Inflector::InflectionData, I18n.inflector.add_database(db) assert_equal true, I18n.inflector.inflected_locale?(:zz) assert_equal false, I18n.inflector.inflected_locale?(:zzzzzz) end test "inflector delete_database deletes existing inflections database" do I18n.inflector.new_database(:vv) assert_equal true, I18n.inflector.inflected_locale?(:vv) assert_kind_of NilClass, I18n.inflector.delete_database(:vv) assert_equal false, I18n.inflector.inflected_locale?(:vv) end test "inflector locale_supported?: checks if a language supports inflection" do assert_equal true, I18n.inflector.locale_supported?(:xx) assert_equal false, I18n.inflector.locale_supported?(:pl) assert_equal false, I18n.inflector.locale_supported?(nil) assert_equal false, I18n.inflector.locale_supported?("") I18n.locale = :xx assert_equal true, I18n.inflector.locale_supported? I18n.locale = :pl assert_equal false, I18n.inflector.locale_supported? I18n.locale = nil assert_equal false, I18n.inflector.locale_supported? I18n.locale = "" assert_equal false, I18n.inflector.locale_supported? end test "inflector.strict locale_supported?: checks if a language supports inflection" do assert_equal true, I18n.inflector.strict.locale_supported?(:xx) assert_equal false, I18n.inflector.strict.locale_supported?(:pl) assert_equal false, I18n.inflector.strict.locale_supported?(nil) assert_equal false, I18n.inflector.strict.locale_supported?("") I18n.locale = :xx assert_equal true, I18n.inflector.strict.locale_supported? I18n.locale = :pl assert_equal false, I18n.inflector.strict.locale_supported? I18n.locale = nil assert_equal false, I18n.inflector.strict.locale_supported? I18n.locale = "" assert_equal false, I18n.inflector.strict.locale_supported? end test "inflector has_token?: checks if a token exists" do assert_equal true, I18n.inflector.has_token?(:neuter, :gender, :xx) assert_equal true, I18n.inflector.has_token?(:neuter, :xx) assert_equal true, I18n.inflector.has_token?(:f, :xx) assert_equal true, I18n.inflector.has_token?(:you, :xx) I18n.locale = :xx assert_equal true, I18n.inflector.has_token?(:f) assert_equal true, I18n.inflector.has_token?(:you) assert_equal false,I18n.inflector.has_token?(:faafaffafafa) end test "inflector.strict has_token?: checks if a token exists" do assert_equal true, I18n.inflector.strict.has_token?(:neuter, :gender, :xx) assert_equal true, I18n.inflector.strict.has_token?(:f, :gender, :xx) assert_equal false, I18n.inflector.strict.has_token?(:you, :gender) I18n.locale = :xx assert_equal true, I18n.inflector.strict.has_token?(:f, :gender) assert_equal false, I18n.inflector.strict.has_token?(:you, :gender) assert_equal false, I18n.inflector.strict.has_token?(:faafaffafafa) end test "inflector has_kind?: checks if an inflection kind exists" do assert_equal true, I18n.inflector.has_kind?(:gender, :xx) assert_equal true, I18n.inflector.has_kind?(:person, :xx) assert_equal false, I18n.inflector.has_kind?(:nonono, :xx) assert_equal false, I18n.inflector.has_kind?(nil, :xx) I18n.locale = :xx assert_equal true, I18n.inflector.has_kind?(:gender) assert_equal true, I18n.inflector.has_kind?(:person) assert_equal false, I18n.inflector.has_kind?(:faafaffafafa) end test "inflector.strict has_kind?: checks if an inflection kind exists" do assert_equal true, I18n.inflector.strict.has_kind?(:gender, :xx) assert_equal false, I18n.inflector.strict.has_kind?(:person, :xx) assert_equal false, I18n.inflector.strict.has_kind?(nil, :xx) I18n.locale = :xx assert_equal true, I18n.inflector.strict.has_kind?(:gender) assert_equal false, I18n.inflector.strict.has_kind?(nil) assert_equal false, I18n.inflector.strict.has_kind?(:faafaffa) end test "inflector kind: checks what is the inflection kind of the given token" do assert_equal :gender, I18n.inflector.kind(:neuter, :xx) assert_equal :gender, I18n.inflector.kind(:f, :xx) assert_equal :person, I18n.inflector.kind(:you, :xx) assert_equal nil, I18n.inflector.kind(nil, :xx) assert_equal nil, I18n.inflector.kind(nil, nil) assert_equal nil, I18n.inflector.kind(:nononono,:xx) I18n.locale = :xx assert_equal :gender, I18n.inflector.kind(:neuter) assert_equal :gender, I18n.inflector.kind(:f) assert_equal :person, I18n.inflector.kind(:you) assert_equal nil, I18n.inflector.kind(nil) assert_equal nil, I18n.inflector.kind(:faafaffa) end test "inflector.strict kind: checks what is the inflection kind of the given token" do assert_equal :gender, I18n.inflector.strict.kind(:neuter, :gender, :xx) assert_equal :gender, I18n.inflector.strict.kind(:f, :gender, :xx) assert_equal nil, I18n.inflector.strict.kind(:f, :nontrue, :xx) assert_equal nil, I18n.inflector.strict.kind(:f, nil, :xx) assert_equal nil, I18n.inflector.strict.kind(nil, :gender, :xx) assert_equal nil, I18n.inflector.strict.kind(nil, nil, :xx) assert_equal nil, I18n.inflector.strict.kind(:faafaffafafa, nil, :xx) assert_equal nil, I18n.inflector.strict.kind(:nil, :faafafa, :xx) I18n.locale = :xx assert_equal :gender, I18n.inflector.strict.kind(:neuter, :gender) assert_equal :gender, I18n.inflector.strict.kind(:f, :gender) assert_equal nil, I18n.inflector.strict.kind(:f, :nontrue) assert_equal nil, I18n.inflector.strict.kind(nil, :gender) assert_equal nil, I18n.inflector.strict.kind(nil, nil) assert_equal nil, I18n.inflector.strict.kind(:faafaffa) end test "inflector true_token: gets true token for the given token name" do assert_equal :n, I18n.inflector.true_token(:neuter, :xx) assert_equal :f, I18n.inflector.true_token(:f, :xx) I18n.locale = :xx assert_equal :n, I18n.inflector.true_token(:neuter) assert_equal :f, I18n.inflector.true_token(:f) assert_equal :f, I18n.inflector.true_token(:f, :xx) assert_equal nil, I18n.inflector.true_token(:f, :person, :xx) assert_equal nil, I18n.inflector.true_token(:f, :nokind, :xx) assert_equal nil, I18n.inflector.true_token(:faafaffa) end test "inflector.strict true_token: gets true token for the given token name" do assert_equal :n, I18n.inflector.strict.true_token(:neuter, :gender, :xx ) assert_equal :f, I18n.inflector.strict.true_token(:f, :gender, :xx ) I18n.locale = :xx assert_equal :n, I18n.inflector.strict.true_token(:neuter, :gender ) assert_equal :f, I18n.inflector.strict.true_token(:f, :gender ) assert_equal :f, I18n.inflector.strict.true_token(:f, :gender, :xx ) assert_equal nil, I18n.inflector.strict.true_token(:f, :person, :xx ) assert_equal nil, I18n.inflector.strict.true_token(:f, nil, :xx ) assert_equal nil, I18n.inflector.strict.true_token(:faafaffa) end test "inflector has_true_token?: tests if true token exists for the given token name" do assert_equal false, I18n.inflector.has_true_token?(:neuter, :xx ) assert_equal true, I18n.inflector.has_true_token?(:f, :xx ) I18n.locale = :xx assert_equal false, I18n.inflector.has_true_token?(:neuter ) assert_equal true, I18n.inflector.has_true_token?(:f ) assert_equal true, I18n.inflector.has_true_token?(:f, :xx ) assert_equal false, I18n.inflector.has_true_token?(:f, :person, :xx) assert_equal false, I18n.inflector.has_true_token?(:f, :nokind, :xx) assert_equal false, I18n.inflector.has_true_token?(:faafaff) end test "inflector strict markers: tests if named markers in kinds are working for API calls" do tt= {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange"} t = tt.merge({:masculine=>"male",:feminine=>"female",:neuter=>"neuter",:neutral=>"neuter"}) al= {:masculine=>:m,:feminine=>:f,:neuter=>:n,:neutral=>:n} tr= tt.merge(al) assert_equal [:xx], I18n.inflector.inflected_locales( :@gender ) assert_equal t, I18n.inflector.tokens( :@gender, :xx ) assert_equal tt, I18n.inflector.true_tokens( :@gender, :xx ) assert_equal tr, I18n.inflector.raw_tokens( :@gender, :xx ) assert_equal :n, I18n.inflector.default_token( :@gender, :xx ) assert_equal al, I18n.inflector.aliases( :@gender, :xx ) assert_equal true, I18n.inflector.has_kind?( :@gender, :xx ) assert_equal true, I18n.inflector.has_alias?( :neuter, :@gender, :xx ) assert_equal true, I18n.inflector.has_token?( :n, :@gender, :xx ) assert_equal false, I18n.inflector.has_true_token?( :neuter, :@gender, :xx ) assert_equal true, I18n.inflector.has_true_token?( :n, :@gender, :xx ) assert_equal :n, I18n.inflector.true_token( :neuter, :@gender, :xx ) assert_equal "neuter",I18n.inflector.token_description( :neuter, :@gender, :xx ) assert_equal "neuter",I18n.inflector.token_description( :n, :@gender, :xx ) I18n.locale = :xx assert_equal t, I18n.inflector.tokens( :@gender ) assert_equal tt, I18n.inflector.true_tokens( :@gender ) assert_equal tr, I18n.inflector.raw_tokens( :@gender ) assert_equal :n, I18n.inflector.default_token( :@gender ) assert_equal al, I18n.inflector.aliases( :@gender ) assert_equal true, I18n.inflector.has_kind?( :@gender ) assert_equal true, I18n.inflector.has_alias?( :neuter, :@gender ) assert_equal true, I18n.inflector.has_token?( :n, :@gender ) assert_equal false, I18n.inflector.has_true_token?( :neuter, :@gender ) assert_equal true, I18n.inflector.has_true_token?( :n, :@gender ) assert_equal :n, I18n.inflector.true_token( :neuter, :@gender ) assert_equal "neuter",I18n.inflector.token_description( :neuter, :@gender ) assert_equal "neuter",I18n.inflector.token_description( :n, :@gender ) end test "inflector.strict has_true_token?: tests if true token exists for the given token name" do assert_equal false, I18n.inflector.strict.has_true_token?(:neuter, :gender, :xx ) assert_equal true, I18n.inflector.strict.has_true_token?(:f, :gender, :xx ) I18n.locale = :xx assert_equal false, I18n.inflector.strict.has_true_token?(:neuter, :gender ) assert_equal true, I18n.inflector.strict.has_true_token?(:f, :gender ) assert_equal true, I18n.inflector.strict.has_true_token?(:f, :gender, :xx ) assert_equal false, I18n.inflector.strict.has_true_token?(:f, :person, :xx ) assert_equal false, I18n.inflector.strict.has_true_token?(:f, nil, :xx ) assert_equal false, I18n.inflector.strict.has_true_token?(:faafaff) end test "inflector kinds: lists inflection kinds" do assert_not_nil I18n.inflector.kinds(:xx) assert_equal [:gender,:person], I18n.inflector.kinds(:xx).sort{|k,v| k.to_s<=>v.to_s} I18n.locale = :xx assert_equal [:gender,:person], I18n.inflector.kinds.sort{|k,v| k.to_s<=>v.to_s} end test "inflector.strict kinds: lists inflection kinds" do assert_not_nil I18n.inflector.strict.kinds(:xx) assert_equal [:gender], I18n.inflector.strict.kinds(:xx) I18n.locale = :xx assert_equal [:gender], I18n.inflector.strict.kinds end test "inflector tokens: lists all inflection tokens including aliases" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange", :masculine=>"male",:feminine=>"female",:neuter=>"neuter", :neutral=>"neuter"} ha = h.merge(:i=>'I', :you=>'You') assert_equal h, I18n.inflector.tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.tokens(:gender) assert_equal ha, I18n.inflector.tokens end test "inflector.strict tokens: lists all inflection tokens including aliases" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange", :masculine=>"male",:feminine=>"female",:neuter=>"neuter", :neutral=>"neuter"} assert_equal h, I18n.inflector.strict.tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.strict.tokens(:gender) assert_equal Hash.new, I18n.inflector.strict.tokens end test "inflector true_tokens: lists true tokens" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange"} ha = h.merge(:i=>"I",:you=>"You") assert_equal h, I18n.inflector.true_tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.true_tokens(:gender) assert_equal ha, I18n.inflector.true_tokens end test "inflector.strict true_tokens: lists true tokens" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange"} assert_equal h, I18n.inflector.strict.true_tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.strict.true_tokens(:gender) assert_equal Hash.new, I18n.inflector.strict.true_tokens end test "inflector raw_tokens: lists tokens in a so called raw format" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange", :masculine=>:m,:feminine=>:f,:neuter=>:n, :neutral=>:n} ha = h.merge(:i=>'I',:you=>"You") assert_equal h, I18n.inflector.raw_tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.raw_tokens(:gender) assert_equal ha, I18n.inflector.raw_tokens end test "inflector.strict raw_tokens: lists tokens in a so called raw format" do h = {:m=>"male",:f=>"female",:n=>"neuter",:s=>"strange", :masculine=>:m,:feminine=>:f,:neuter=>:n, :neutral=>:n} assert_equal h, I18n.inflector.strict.raw_tokens(:gender, :xx) I18n.locale = :xx assert_equal h, I18n.inflector.strict.raw_tokens(:gender) assert_equal Hash.new, I18n.inflector.strict.raw_tokens end test "inflector default_token: returns a default token for a kind" do assert_equal :n, I18n.inflector.default_token(:gender, :xx) I18n.locale = :xx assert_equal :n, I18n.inflector.default_token(:gender) end test "inflector.strict default_token: returns a default token for a kind" do assert_equal :n, I18n.inflector.strict.default_token(:gender, :xx) I18n.locale = :xx assert_equal :n, I18n.inflector.strict.default_token(:gender) end test "inflector aliases: lists aliases" do a = {:masculine=>:m, :feminine=>:f, :neuter=>:n, :neutral=>:n} assert_equal a, I18n.inflector.aliases(:gender, :xx) I18n.locale = :xx assert_equal a, I18n.inflector.aliases(:gender) assert_equal a, I18n.inflector.aliases end test "inflector.strict aliases: lists aliases" do a = {:masculine=>:m, :feminine=>:f, :neuter=>:n, :neutral=>:n} assert_equal a, I18n.inflector.strict.aliases(:gender, :xx) I18n.locale = :xx assert_equal a, I18n.inflector.strict.aliases(:gender) assert_equal Hash.new, I18n.inflector.strict.aliases end test "inflector token_description: returns token's description" do assert_equal "male", I18n.inflector.token_description(:m, :xx) I18n.locale = :xx assert_equal "male", I18n.inflector.token_description(:m) assert_equal nil, I18n.inflector.token_description(:vnonexistent, :xx) assert_equal "neuter", I18n.inflector.token_description(:neutral, :xx) end test "inflector.strict token_description: returns token's description" do assert_equal "male", I18n.inflector.strict.token_description(:m, :gender, :xx) I18n.locale = :xx assert_equal "male", I18n.inflector.strict.token_description(:m, :gender) assert_equal nil, I18n.inflector.strict.token_description(:bnonexistent, :gender, :xx) assert_equal "neuter", I18n.inflector.strict.token_description(:neutral, :gender, :xx) end test "inflector has_alias?: tests whether a token is an alias" do assert_equal true, I18n.inflector.has_alias?(:neutral, :xx) assert_equal false, I18n.inflector.has_alias?(:you, :xx) assert_equal true, I18n.inflector.has_alias?(:neutral, :gender, :xx) assert_equal false, I18n.inflector.has_alias?(:you, :gender, :xx) assert_equal false, I18n.inflector.has_alias?(:neutral, :nokind, :xx) I18n.locale = :xx assert_equal true, I18n.inflector.has_alias?(:neutral) end test "inflector.strict has_alias?: tests whether a token is an alias" do assert_equal true, I18n.inflector.strict.has_alias?(:neutral, :gender, :xx) assert_equal false, I18n.inflector.strict.has_alias?(:you, :person, :xx) assert_equal false, I18n.inflector.strict.has_alias?(:you, :gender, :xx) I18n.locale = :xx assert_equal true, I18n.inflector.strict.has_alias?(:neutral, :gender) end end ruby-i18n-inflector-2.6.6/test/test_helper.rb000066400000000000000000000012371204270775600211050ustar00rootroot00000000000000require 'test/unit' require 'test_declarative' require 'i18n-inflector' class Test::Unit::TestCase def teardown I18n.locale = nil I18n.default_locale = :en I18n.load_path = [] I18n.available_locales = nil I18n.backend = nil end if not method_defined?(:teardown) def translations I18n.backend.instance_variable_get(:@translations) end def store_translations(*args) data = args.pop locale = args.pop || :en I18n.backend.store_translations(locale, data) end end Object.class_eval do def meta_class class << self; self; end end end unless Object.method_defined?(:meta_class)