From 18e85e6383a3612f8f3eb8a96eb25d4496a007c3 Mon Sep 17 00:00:00 2001 From: Domizio Demichelis Date: Mon, 3 Feb 2025 16:07:16 +0700 Subject: [PATCH] WIP: Refactor i18n --- .rubocop.yml | 1 + CHANGELOG-10.md | 51 +++--- README.md | 2 +- gem/config/pagy.rb | 45 +---- gem/lib/pagy.rb | 1 + gem/lib/pagy/backend/loader.rb | 24 +-- .../{pagynators => paginators}/arel.rb | 0 .../{pagynators => paginators}/array.rb | 0 .../{pagynators => paginators}/calendar.rb | 0 .../{pagynators => paginators}/countless.rb | 0 .../{pagynators => paginators}/keynav.rb | 0 .../{pagynators => paginators}/keyset.rb | 0 .../{pagynators => paginators}/offset.rb | 0 .../searches/elasticsearch_rails.rb | 0 .../searches/meilisearch.rb | 0 .../searches/searchkick.rb | 0 .../searches/wrapper.rb | 0 gem/lib/pagy/frontend.rb | 2 +- gem/lib/pagy/i18n.rb | 166 +++--------------- gem/lib/pagy/i18n/p11n.rb | 15 ++ gem/lib/pagy/i18n/p11n/arabic.rb | 23 +++ gem/lib/pagy/i18n/p11n/east_slavic.rb | 22 +++ gem/lib/pagy/i18n/p11n/one_other.rb | 15 ++ gem/lib/pagy/i18n/p11n/one_upto_two_other.rb | 15 ++ gem/lib/pagy/i18n/p11n/other.rb | 13 ++ gem/lib/pagy/i18n/p11n/polish.rb | 22 +++ gem/lib/pagy/i18n/p11n/west_slavic.rb | 19 ++ gem/locales/README.md | 25 ++- gem/locales/ar.yml | 3 +- gem/locales/be.yml | 3 +- gem/locales/bg.yml | 3 +- gem/locales/bs.yml | 3 +- gem/locales/ca.yml | 3 +- gem/locales/ckb.yml | 3 +- gem/locales/cs.yml | 3 +- gem/locales/da.yml | 3 +- gem/locales/de.yml | 3 +- gem/locales/dz.yml | 3 +- gem/locales/en.yml | 3 +- gem/locales/es.yml | 3 +- gem/locales/fr.yml | 3 +- gem/locales/hr.yml | 3 +- gem/locales/id.yml | 3 +- gem/locales/it.yml | 3 +- gem/locales/ja.yml | 3 +- gem/locales/km.yml | 3 +- gem/locales/ko.yml | 3 +- gem/locales/nb.yml | 3 +- gem/locales/nl.yml | 3 +- gem/locales/nn.yml | 3 +- gem/locales/pl.yml | 3 +- gem/locales/pt-BR.yml | 5 +- gem/locales/pt.yml | 5 +- gem/locales/ru.yml | 3 +- gem/locales/sr.yml | 3 +- gem/locales/sv-SE.yml | 3 +- gem/locales/sv.yml | 3 +- gem/locales/sw.yml | 9 +- gem/locales/ta.yml | 9 +- gem/locales/tr.yml | 3 +- gem/locales/uk.yml | 3 +- gem/locales/vi.yml | 3 +- gem/locales/zh-CN.yml | 3 +- gem/locales/zh-HK.yml | 3 +- gem/locales/zh-TW.yml | 3 +- test/helpers/nav_tests.rb | 2 +- test/pagy/backend/calendar_test.rb | 2 +- test/pagy/frontend/pagy_test.rb | 2 +- test/pagy/frontend_test.rb | 28 +-- test/pagy/helpers/i18n/load_test.rb | 14 -- test/pagy/helpers/i18n/locales_test.rb | 64 ------- test/pagy/helpers/i18n/p11n_test.rb | 143 --------------- test/pagy/i18n/locales_test.rb | 56 ++++++ test/pagy/i18n/p11n_test.rb | 129 ++++++++++++++ 74 files changed, 499 insertions(+), 529 deletions(-) rename gem/lib/pagy/backend/{pagynators => paginators}/arel.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/array.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/calendar.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/countless.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/keynav.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/keyset.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/offset.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/searches/elasticsearch_rails.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/searches/meilisearch.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/searches/searchkick.rb (100%) rename gem/lib/pagy/backend/{pagynators => paginators}/searches/wrapper.rb (100%) create mode 100644 gem/lib/pagy/i18n/p11n.rb create mode 100644 gem/lib/pagy/i18n/p11n/arabic.rb create mode 100644 gem/lib/pagy/i18n/p11n/east_slavic.rb create mode 100644 gem/lib/pagy/i18n/p11n/one_other.rb create mode 100644 gem/lib/pagy/i18n/p11n/one_upto_two_other.rb create mode 100644 gem/lib/pagy/i18n/p11n/other.rb create mode 100644 gem/lib/pagy/i18n/p11n/polish.rb create mode 100644 gem/lib/pagy/i18n/p11n/west_slavic.rb delete mode 100644 test/pagy/helpers/i18n/load_test.rb delete mode 100644 test/pagy/helpers/i18n/locales_test.rb delete mode 100644 test/pagy/helpers/i18n/p11n_test.rb create mode 100644 test/pagy/i18n/locales_test.rb create mode 100644 test/pagy/i18n/p11n_test.rb diff --git a/.rubocop.yml b/.rubocop.yml index 311a15c27..e4b6ac4a9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,6 +6,7 @@ require: # trying to be good O:) AllCops: + SuggestExtensions: false TargetRubyVersion: 3.2 NewCops: enable Exclude: diff --git a/CHANGELOG-10.md b/CHANGELOG-10.md index e7ce3d094..76d0f4306 100644 --- a/CHANGELOG-10.md +++ b/CHANGELOG-10.md @@ -64,8 +64,8 @@ The best technique for performance AND functionality! Check it out. #### Automatic loading of just the code that you actually use -Every class, module and helper is automatically loaded only if you actually use it, without the need of any explicit `require`. _( -the legacy version was requiring more code)_ +Every class, module and helper is automatically loaded only if you actually use it, without the need of any explicit `require`. +The legacy version was requiring more code by default; this one is autoloading only the specific methods. #### The extras are all gone @@ -75,14 +75,14 @@ You can now use the methods that you need, and they will just work without the n ### The configuration is minimal and non-technical -Take a look at the configuration file: all the extra `requires` and the `Pagy::DEFAULT` configurations are gone. The only four -optional configuration left, are simple Pagy function calls. +Take a look at the configuration file: all the extra `requires` and the `Pagy::DEFAULT` configurations are gone. The only 3 +optional configuration left, are simple one-liner Pagy function calls. #### Better file and namespace system organization and coding style The class hierarchy, the mixin files, and the test file structure have been deeply reorganized. The code is cleaner, more concise -and more readable, adding fewer modules to the `ancestors` array of your app. -Abbreviated naming is gone consistently everywhere. +and more readable, adding fewer modules to the `ancestors` array of your app. Also, abbreviated naming is gone consistently +everywhere. #### The Pagy::Countless remembers the last page @@ -99,11 +99,17 @@ Updated the support for all the pagy helpers and `keynav` pagination. Added the Added `Pagy::Javascript.install` function to avoid messing up with complicated javascript cofigurations. +#### I18n refactoring + +No setup required. The locales and their pluralization are autoloaded when you app use them. + +The code is simpler and lighter, you can also override the lookup of dictionary files with `Pagy::I18n::PATHNAMES.unshift(Pathname.new('my/customized/dictionaries'))`. + ### Breaking Changes #### Simple search and replace renaming (without logic changes) -Many of the changes in the following list are seldom used by the app code, we wrote them all for completeness: +Your app may use just a little fraction of the renamed things in the list below, but we wrote them all for completeness: | Type | Search | Replace | Notes | |-------------|------------------|--------------------|-----------------------------------------------------------------------| @@ -121,17 +127,17 @@ Many of the changes in the following list are seldom used by the app code, we wr | Method/args | `label(page` | `label(page: page` | Same name: `page` is now a keywork argument | | Naming | `*prev*` | `*previous*` | Unabbreviated word everywhere (option, accessor, methods, CSS class) | -#### The `Pagy::DEFAULT` is now frozen +#### Replace your `pagy.rb` config file -- Remove all the `Pagy::DEFAULT` statements and pass their variables to the paginator constructors that you use. -- As an alternative to avoid repetitions, define your own default hash and pass it to the different paginator methods. -- See the new initializer for details. +With no more `Pagy::DEFAULT` and no more extras to `require`, all the statements in your old version are obsolete, so it's better +to start with the new version of the file. -#### Replace your `pagy.rb` config file +#### The `Pagy::DEFAULT` is now frozen -With no more `Pagy::DEFAULT` and no more extras to `require`, the statements in your old version are all obsolete but any existing -`Pagy::I18n` configuration, so it's better to start with the new version of the file, and copy over only the `Pagy::I18n.load` -(if you used it). +- The `Pagy::DEFAULT` is now an internal hash and it's frozen. If you had any default set there, you should pass the options to + the paginator constructors. +- As an alternative to avoid repetitions, define your own default hash and pass it to the different paginator methods/helpers. +- See the new initializer for details. #### Core changes @@ -140,7 +146,7 @@ With no more `Pagy::DEFAULT` and no more extras to `require`, the statements in - The `:outset` and `:cycle` variables have been removed. They were seldom used, mostly useless, and implementing them in your code is trivial. - You can pass the `:length` and `countless` options (legacy `:size` and `ends`), preferably to the `*_nav`, `_nav_js` helpers, - but it's also possible to pass them to the pagynator. + but it's also possible to pass them to the paginator. #### Extras Changes @@ -152,15 +158,15 @@ All the extras are gone. Here is what to do in order to accomodate the changes: ##### `calendar` -- Discard your old localization config, and uncomment/add this line to your initializer: +- Discard your old localization config (if any), and uncomment this line in the `pagy.rb` initializer: `Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales)`. - - In non-rails apps, calendar localization requires to add `rails-i18n` to your gemfile. + - In non-rails apps, calendar localization requires to add `rails-i18n` to your Gemfile. - Replace the existing `Pagy::Calendar::OutOfRangeError` with `Pagy::RangeError` ##### `elasticsearch_rails`, `meilisearch`, `searchkick` - Replace any existing `Pagy.new_from_` with `pagy_`. _(Active and passive modes are now handled by the - same pagynator.)_ + same paginator.)_ - Remove any existing `:_pagy_search` variable from your code, and use the standard `pagy_search` method instead. _( the `pagy_search` name customization has been discontinued.)_ - Rename any existing `:_search` variable as `:search_method` and pass it to the paginator method. @@ -179,8 +185,9 @@ All the extras are gone. Here is what to do in order to accomodate the changes: ##### `keyset` - Replace any existing `:jsonify_keyset_attributes` with `stringify_keyset_values`. The lambda receives the same - `keyset_attributes` but it must return the array of attribute values `->(keyset_attributes) { ...; keyset_attributes.values }`. -- Remove any existing`:filter_newest`. Override the `after_cutoff_sql` method instead. + `keyset_attributes` argument, but it must return the array of attribute values + `->(keyset_attributes) { ...; keyset_attributes.values }`. +- Remove any existing`:filter_newest`. Override the `compose_predicate` method instead. ##### `limit` @@ -236,7 +243,7 @@ All the extras are gone. Here is what to do in order to accomodate the changes: #### Direct instantiation of the pagy classes is not recommended -- Use the provided `pagynators` for easier usage, maintenance and forward compatibility. +- Use the provided `paginators` for easier usage, maintenance and forward compatibility. - Use the implementing classes only if the documentation explicitly suggests you to do so, or if you know what you are doing. #### Possibly Breaking Overridings diff --git a/README.md b/README.md index c9e0a34ae..84fc0d35f 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ include Pagy::Backend # Include it in the helpers (e.g. application_helper.rb) include Pagy::Frontend -# Wrap your collections with one of many pagynators in your actions. For example: +# Wrap your collections with one of many paginators in your actions. For example: @pagy, @records = pagy_offset(Product.all) @pagy, @records = pagy_keyset(Product.order(my_order).all) @pagy, @records = pagy_keynav(Product.order(my_order).all) diff --git a/gem/config/pagy.rb b/gem/config/pagy.rb index 75294ef4e..e0fff0e89 100644 --- a/gem/config/pagy.rb +++ b/gem/config/pagy.rb @@ -14,9 +14,6 @@ # pagy_offset(collection, **PAGY_DEFAULT, **other_vars) # pagy_keyset(set, **PAGY_DEFAULT, **other_vars) -# Notice that it's just a hash that you can name and define how and where you prefer: -# just remember to pass it to the paginator when you need it. - ############ Install Pagy Javascript ##################################################### # If you use any pagy method ending with '*_js', @@ -34,49 +31,19 @@ # Pagy::Javascript.install('pagy.mjs', javascript_path) if Rails.env.development? - -#################################### IMPORTANT ####################################### -# Do not configure anything below this line if you use only the :en locale +############# Overriding Pagy::I18n dictionary lookup ###################################### +# Override the dictionary lookup for customization. Just drop your customized +# dictionary/dictionaries in a dir and add its pathname to the lookup: +# Pagy::I18n::PATHNAMES.unshift(Pathname.new('my/customized/dictionaries')) -############# Pagy Translation Besides :en ########################################### -# Use the Pagy::I18n: ~18x faster using ~10x less memory than the i18n gem -# If you want to use the slower I18n gem, skip this and look at the end of this file. -# -# Examples (use only one statement): -# -# Load the "de" built-in locale: -# Pagy::I18n.load(locale: 'de') -# -# Load the "de" locale defined in the custom file at :filepath: -# Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml') -# -# Load the "de", "en" and "es" built-in locales: -# (the first passed :locale will be used also as the default_locale) -# Pagy::I18n.load({ locale: 'de' }, -# { locale: 'en' }, -# { locale: 'es' }) -# -# ADVANCED USAGE: -# Load the "en" built-in locale, a custom "es" locale, -# and a totally custom locale complete with a custom :pluralize proc: -# (the first passed :locale will be used also as the default_locale) -# Pagy::I18n.load({ locale: 'en' }, -# { locale: 'es', filepath: 'path/to/pagy-es.yml' }, -# { locale: 'xyz', # not built-in -# filepath: 'path/to/pagy-xyz.yml', -# pluralize: lambda{ |count| ... } ) - - -############# I18n gem Translation Besides :en ###################################### -# Uncomment the following line if you REALLY want to switch +############# I18n gem translation ###################################### +# Uncomment the following line if you really have to switch # to the standard I18n gem translation: -# # Pagy::Frontend.translate_with_the_slower_i18n_gem! ############# Calendar Localization Besides :en ###################################### # Add the list of your locales and uncomment the following line to enable it, # regardless if you use the I18n gem for translations or not, Rails or not. -# # Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales) diff --git a/gem/lib/pagy.rb b/gem/lib/pagy.rb index d5990f1d7..6955cd61d 100644 --- a/gem/lib/pagy.rb +++ b/gem/lib/pagy.rb @@ -12,6 +12,7 @@ class Pagy autoload :Backend, PAGY_PATH.join('backend') autoload :Frontend, PAGY_PATH.join('frontend') autoload :I18n, PAGY_PATH.join('i18n') + autoload :P11n, PAGY_PATH.join('i18n') autoload :Offset, PAGY_PATH.join('offset') autoload :Calendar, PAGY_PATH.join('calendar') autoload :Search, PAGY_PATH.join('search') diff --git a/gem/lib/pagy/backend/loader.rb b/gem/lib/pagy/backend/loader.rb index 015776dc5..46b37ce2d 100644 --- a/gem/lib/pagy/backend/loader.rb +++ b/gem/lib/pagy/backend/loader.rb @@ -15,18 +15,18 @@ def pagy_load_backend(...) pagy_headers_merge: 'helpers/headers', pagy_data: 'helpers/data', pagy_links: 'helpers/links', - pagy_arel: 'pagynators/arel', - pagy_array: 'pagynators/array', - pagy_calendar: 'pagynators/calendar', - pagy_countless: 'pagynators/countless', - pagy_keynav_js: 'pagynators/keynav', - pagy_keyset: 'pagynators/keyset', - pagy_keyset_first_url: 'pagynators/keyset', - pagy_keyset_next_url: 'pagynators/keyset', - pagy_offset: 'pagynators/offset', - pagy_elasticsearch_rails: 'pagynators/searches/elasticsearch_rails', - pagy_meilisearch: 'pagynators/searches/meilisearch', - pagy_searchkick: 'pagynators/searches/searchkick' }.freeze + pagy_arel: 'paginators/arel', + pagy_array: 'paginators/array', + pagy_calendar: 'paginators/calendar', + pagy_countless: 'paginators/countless', + pagy_keynav_js: 'paginators/keynav', + pagy_keyset: 'paginators/keyset', + pagy_keyset_first_url: 'paginators/keyset', + pagy_keyset_next_url: 'paginators/keyset', + pagy_offset: 'paginators/offset', + pagy_elasticsearch_rails: 'paginators/searches/elasticsearch_rails', + pagy_meilisearch: 'paginators/searches/meilisearch', + pagy_searchkick: 'paginators/searches/searchkick' }.freeze BACKEND_METHODS.each_key do |method| class_eval "alias #{method} pagy_load_backend", __FILE__, __LINE__ # alias pagy_* pagy_load_backend diff --git a/gem/lib/pagy/backend/pagynators/arel.rb b/gem/lib/pagy/backend/paginators/arel.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/arel.rb rename to gem/lib/pagy/backend/paginators/arel.rb diff --git a/gem/lib/pagy/backend/pagynators/array.rb b/gem/lib/pagy/backend/paginators/array.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/array.rb rename to gem/lib/pagy/backend/paginators/array.rb diff --git a/gem/lib/pagy/backend/pagynators/calendar.rb b/gem/lib/pagy/backend/paginators/calendar.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/calendar.rb rename to gem/lib/pagy/backend/paginators/calendar.rb diff --git a/gem/lib/pagy/backend/pagynators/countless.rb b/gem/lib/pagy/backend/paginators/countless.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/countless.rb rename to gem/lib/pagy/backend/paginators/countless.rb diff --git a/gem/lib/pagy/backend/pagynators/keynav.rb b/gem/lib/pagy/backend/paginators/keynav.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/keynav.rb rename to gem/lib/pagy/backend/paginators/keynav.rb diff --git a/gem/lib/pagy/backend/pagynators/keyset.rb b/gem/lib/pagy/backend/paginators/keyset.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/keyset.rb rename to gem/lib/pagy/backend/paginators/keyset.rb diff --git a/gem/lib/pagy/backend/pagynators/offset.rb b/gem/lib/pagy/backend/paginators/offset.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/offset.rb rename to gem/lib/pagy/backend/paginators/offset.rb diff --git a/gem/lib/pagy/backend/pagynators/searches/elasticsearch_rails.rb b/gem/lib/pagy/backend/paginators/searches/elasticsearch_rails.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/searches/elasticsearch_rails.rb rename to gem/lib/pagy/backend/paginators/searches/elasticsearch_rails.rb diff --git a/gem/lib/pagy/backend/pagynators/searches/meilisearch.rb b/gem/lib/pagy/backend/paginators/searches/meilisearch.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/searches/meilisearch.rb rename to gem/lib/pagy/backend/paginators/searches/meilisearch.rb diff --git a/gem/lib/pagy/backend/pagynators/searches/searchkick.rb b/gem/lib/pagy/backend/paginators/searches/searchkick.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/searches/searchkick.rb rename to gem/lib/pagy/backend/paginators/searches/searchkick.rb diff --git a/gem/lib/pagy/backend/pagynators/searches/wrapper.rb b/gem/lib/pagy/backend/paginators/searches/wrapper.rb similarity index 100% rename from gem/lib/pagy/backend/pagynators/searches/wrapper.rb rename to gem/lib/pagy/backend/paginators/searches/wrapper.rb diff --git a/gem/lib/pagy/frontend.rb b/gem/lib/pagy/frontend.rb index 7edec997a..d5cb0872b 100644 --- a/gem/lib/pagy/frontend.rb +++ b/gem/lib/pagy/frontend.rb @@ -33,7 +33,7 @@ def pagy_anchor(pagy, anchor_string: nil, **) # Similar to I18n.translate: just ~18x faster using ~10x less memory # (@pagy_locale explicitly initialized in order to avoid warning) def pagy_translate(key, **) - Pagy::I18n.translate(key, locale: (@pagy_locale ||= nil), **) + Pagy::I18n.translate(key, locale: (@pagy_locale ||= 'en'), **) end alias pagy_t pagy_translate end diff --git a/gem/lib/pagy/i18n.rb b/gem/lib/pagy/i18n.rb index 79bf6998a..e5b6e5a3e 100644 --- a/gem/lib/pagy/i18n.rb +++ b/gem/lib/pagy/i18n.rb @@ -1,165 +1,43 @@ # frozen_string_literal: true require 'yaml' +require_relative 'i18n/p11n' class Pagy # Pagy i18n implementation, compatible with the I18n gem, just a lot faster and lighter module I18n extend self - # Pluralization rules - module P11n - # Pluralization variables - from0to1 = (0..1).to_a.freeze - from2to4 = (2..4).to_a.freeze - from3to10 = (3..10).to_a.freeze - from5to9 = (5..9).to_a.freeze - from11to14 = (11..14).to_a.freeze - from11to99 = (11..99).to_a.freeze - from12to14 = (12..14).to_a.freeze - - from0to1_from5to9 = from0to1 + from5to9 - - # Store the proc defining each pluralization RULE - # Logic adapted from https://github.com/svenfuchs/rails-i18n - RULE = { - arabic: - lambda do |n = 0| - mod100 = n % 100 - case - when n == 0 then 'zero' # rubocop:disable Style/NumericPredicate - when n == 1 then 'one' - when n == 2 then 'two' - when from3to10.include?(mod100) then 'few' - when from11to99.include?(mod100) then 'many' - else 'other' - end - end, - - east_slavic: - lambda do |n = 0| - mod10 = n % 10 - mod100 = n % 100 - case - when mod10 == 1 && mod100 != 11 then 'one' - when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few' - when mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) then 'many' # rubocop:disable Style/NumericPredicate - else 'other' - end - end, - - one_other: - ->(n) { n == 1 ? 'one' : 'other' }, # default RULE - - one_two_other: - lambda do |n| - case n - when 1 then 'one' - when 2 then 'two' - else 'other' - end - end, - - one_upto_two_other: - ->(n) { n && n >= 0 && n < 2 ? 'one' : 'other' }, - - other: - ->(*) { 'other' }, + # rubocop:disable Style/MutableConstant + PATHNAMES = [ROOT.join('locales')] + # Stores the i18n DATA structure for each loaded locale + DATA = {} + # rubocop:enable Style/MutableConstant - polish: - lambda do |n = 0| - mod10 = n % 10 - mod100 = n % 100 - case - when n == 1 then 'one' - when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few' - when from0to1_from5to9.include?(mod10) || from12to14.include?(mod100) then 'many' - else 'other' - end - end, + # Translate and pluralize the key with the locale DATA + def translate(key, locale:, **options) + data, p11n = DATA[locale] || self.load(locale) + translation = data[key] || (options[:count] && data[key += ".#{p11n.plural_for(options[:count])}"]) \ + or return %([translation missing: "#{key}"]) + translation.gsub(/%{[^}]+?}/) { |match| options[:"#{match[2..-2]}"] || match } + end - west_slavic: - lambda do |n| - case n - when 1 then 'one' - when *from2to4 then 'few' - else 'other' - end - end + private - }.freeze + def load(locale) + path = PATHNAMES.map { |p| p.join("#{locale}.yml") }.find(&:exist?) + raise Errno::ENOENT, "missing dictionary file for #{locale.inspect} locale" unless path - # Store the RULE to apply to each LOCALE - # the :one_other RULE is the default for locales missing from this list - LOCALE = Hash.new(RULE[:one_other]).tap do |hash| - hash['ar'] = RULE[:arabic] - hash['be'] = RULE[:east_slavic] - hash['bs'] = RULE[:east_slavic] - hash['ckb'] = RULE[:other] - hash['cs'] = RULE[:west_slavic] - hash['id'] = RULE[:other] - hash['fr'] = RULE[:one_upto_two_other] - hash['hr'] = RULE[:east_slavic] - hash['ja'] = RULE[:other] - hash['km'] = RULE[:other] - hash['ko'] = RULE[:other] - hash['pl'] = RULE[:polish] - hash['ru'] = RULE[:east_slavic] - hash['sr'] = RULE[:east_slavic] - hash['tr'] = RULE[:other] - hash['uk'] = RULE[:east_slavic] - hash['vi'] = RULE[:other] - hash['zh-CN'] = RULE[:other] - hash['zh-HK'] = RULE[:other] - hash['zh-TW'] = RULE[:other] - hash['dz'] = RULE[:other] - end.freeze + dictionary = YAML.load_file(path)[locale] + p11n = dictionary['pagy'].delete('p11n') + DATA[locale] = [flatten_to_dot_keys(dictionary), Object.const_get("Pagy::I18n::P11n::#{p11n}")] end - # Stores the i18n DATA structure for each loaded locale - # default on the first locale DATA - DATA = Hash.new { |hash,| hash.first[1] } - - private - # Create a flat hash with dotted notation keys - def flatten(initial, prefix = '') + def flatten_to_dot_keys(initial, prefix = '') initial.each.reduce({}) do |hash, (key, value)| - hash.merge!(value.is_a?(Hash) ? flatten(value, "#{prefix}#{key}.") : { "#{prefix}#{key}" => value }) - end - end - - # Build the DATA hash out of the passed locales - def build(*locales) - locales.each do |locale| - locale[:filepath] ||= Pagy::ROOT.join('locales', "#{locale[:locale]}.yml") - locale[:pluralize] ||= P11n::LOCALE[locale[:locale]] - dictionary = YAML.safe_load(File.read(locale[:filepath], encoding: 'UTF-8')) - raise I18nError, %(expected :locale "#{locale[:locale]}" not found in :filepath "#{locale[:filepath].inspect}") \ - unless dictionary.key?(locale[:locale]) - - DATA[locale[:locale]] = [flatten(dictionary[locale[:locale]]), locale[:pluralize]] + hash.merge!(value.is_a?(Hash) ? flatten_to_dot_keys(value, "#{prefix}#{key}.") : { "#{prefix}#{key}" => value }) end end - # Build the default at require time - build(locale: 'en') - - public - - # Public method to configure the locales: overrides the default, build the DATA and freezes it - def load(*locales) - DATA.clear - build(*locales) - DATA.freeze - end - - # Translate and pluralize the key with the locale DATA - def translate(key, locale:, **options) - data, pluralize = DATA[locale] - translation = data[key] || (options[:count] && data[key += ".#{pluralize.call(options[:count])}"]) \ - or return %([translation missing: "#{key}"]) - translation.gsub(/%{[^}]+?}/) { |match| options[:"#{match[2..-2]}"] || match } - end - alias t translate end end diff --git a/gem/lib/pagy/i18n/p11n.rb b/gem/lib/pagy/i18n/p11n.rb new file mode 100644 index 000000000..6d987b053 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + autoload :Arabic, PAGY_PATH.join('i18n/p11n/arabic') + autoload :EastSlavic, PAGY_PATH.join('i18n/p11n/east_slavic') + autoload :OneOther, PAGY_PATH.join('i18n/p11n/one_other') + autoload :OneUptoTwoOther, PAGY_PATH.join('i18n/p11n/one_upto_two_other') + autoload :Other, PAGY_PATH.join('i18n/p11n/other') + autoload :Polish, PAGY_PATH.join('i18n/p11n/polish') + autoload :WestSlavic, PAGY_PATH.join('i18n/p11n/west_slavic') + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/arabic.rb b/gem/lib/pagy/i18n/p11n/arabic.rb new file mode 100644 index 000000000..b16b37e31 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/arabic.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module Arabic + module_function + + def plural_for(n = 0) + mod100 = n % 100 + case + when n == 0 then :zero # rubocop:disable Style/NumericPredicate + when n == 1 then :one + when n == 2 then :two + when (3..10).to_a.include?(mod100) then :few + when (11..99).to_a.include?(mod100) then :many + else :other + end + end + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/east_slavic.rb b/gem/lib/pagy/i18n/p11n/east_slavic.rb new file mode 100644 index 000000000..cd5bd4d34 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/east_slavic.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module EastSlavic + module_function + + def plural_for(n = 0) + mod10 = n % 10 + mod100 = n % 100 + case + when mod10 == 1 && mod100 != 11 then :one + when (2..4).to_a.include?(mod10) && !(12..14).to_a.include?(mod100) then :few + when mod10 == 0 || (5..9).to_a.include?(mod10) || (11..14).to_a.include?(mod100) then :many # rubocop:disable Style/NumericPredicate + else :other + end + end + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/one_other.rb b/gem/lib/pagy/i18n/p11n/one_other.rb new file mode 100644 index 000000000..3dae59ae2 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/one_other.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module OneOther + module_function + + def plural_for(n = 0) + n == 1 ? :one : :other + end + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/one_upto_two_other.rb b/gem/lib/pagy/i18n/p11n/one_upto_two_other.rb new file mode 100644 index 000000000..bb6d3d2b2 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/one_upto_two_other.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module OneUptoTwoOther + module_function + + def plural_for(n = 0) + n >= 0 && n < 2 ? :one : :other + end + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/other.rb b/gem/lib/pagy/i18n/p11n/other.rb new file mode 100644 index 000000000..54c7ed2c8 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/other.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module Other + module_function + + def plural_for(*) = :other + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/polish.rb b/gem/lib/pagy/i18n/p11n/polish.rb new file mode 100644 index 000000000..92df36654 --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/polish.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module Polish + module_function + + def plural_for(n = 0) + mod10 = n % 10 + mod100 = n % 100 + case + when n == 1 then :one + when [2, 3, 4].include?(mod10) && ![12, 13, 14].include?(mod100) then :few + when [0, 1, 5, 6, 7, 8, 9].include?(mod10) || [12, 13, 14].include?(mod100) then :many + else :other + end + end + end + end + end +end diff --git a/gem/lib/pagy/i18n/p11n/west_slavic.rb b/gem/lib/pagy/i18n/p11n/west_slavic.rb new file mode 100644 index 000000000..d846189fd --- /dev/null +++ b/gem/lib/pagy/i18n/p11n/west_slavic.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class Pagy + module I18n + module P11n + module WestSlavic + module_function + + def plural_for(n = 0) + case n + when 1 then :one + when 2, 3, 4 then :few + else :other + end + end + end + end + end +end diff --git a/gem/locales/README.md b/gem/locales/README.md index 6b4190cee..d75e5d2fb 100644 --- a/gem/locales/README.md +++ b/gem/locales/README.md @@ -6,34 +6,29 @@ If you find that some translation could be improved, please, create an issue. If you are using pagy with some language missing from the dictionary files, please, submit your translation! -You can create a Pull Request for your language, and get all the help you need to correctly complete it. Here is a check list. +You can create a Pull Request for your language, and get all the help you need to correctly complete it. Here is a checklist. -### Check list for a new dictionary file: +### Checklist for a new dictionary file: - [ ] Find the pluralization rule for your language (see below for details on how to do this). - [ ] Find the locale file you need in the [list of pluralization](https://github.com/svenfuchs/rails-i18n/tree/master/rails/pluralization) and check the pluralization rule required in it. For example the name of the file required is `one_other` - for [`en.rb`](https://github.com/svenfuchs/rails-i18n/blob/master/rails/pluralization/en.rb). In pagy that translates to the symbol `:one_other`. If you cannot find the pluralization in the aforementioned link, see if you can find it [in the unicode pluralization rules](https://www.unicode.org/cldr/charts/45/supplemental/language_plural_rules.html). + for [`en.rb`](https://github.com/svenfuchs/rails-i18n/blob/master/rails/pluralization/en.rb). In pagy that translates to `'OneOther'`. If you cannot find the pluralization in the aforementioned link, see if you can find it [in the unicode pluralization rules](https://www.unicode.org/cldr/charts/45/supplemental/language_plural_rules.html). - - [ ] If the pluralization rule of your language is not the `:one_other` (default), confirm that pagy already defines the - pluralization rule of your dictionary file in the IRB console, with `require 'pagy'; p Pagy::I18n::P11n::RULE.keys` or check - for it directly in the [i18n.rb file](https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb#L26-L91). + - [ ] Confirm that pagy already defines the + pluralization rule of your dictionary file by checking the file in the [P18n dir](https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n/p18n). - - [ ] If the rule is not defined, you can either: a) Add the rule as a new rule/lambda entry in the `Pagy::I18n::P11n::RULE` - constant hash and relative tests or b) Just create an issue requesting the addition to the rule/lambda entry and tests. + - [ ] If the rule is not defined, you can either: a) Add a new module for the pluralization (practically adapting the same pluralization from the corresponding rails-i18n file) and add some tests for it; or b) Just create an issue requesting the addition to the pluralization entry and tests. - - [ ] Add an entry for your locale to - the [`Pagy::I18n::P11n::LOCALE` hash](https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb#L95C1-L115). +- [ ] Duplicate another pagy locale dictionary file and translate it to your language. -- [ ] add/edit the first line comment in the language rule in your dictionary file (e.g. `# :one_other pluralization ...`. For - example, the [Japanese locale file](https://github.com/ddnexus/pagy/blob/master/gem/lib/locales/ja.yml#L1) uses - the: `# :other pluralization ...` + - [ ] Check that the `p11n` entry point to a module in the P18n dir - [ ] The mandatory pluralized entry in the dictionary file are the `aria_label.nav` and the `item_name`. Please, provide all the - plurals needed by your language. E.g. if your language uses the `:east_slavic` you should provide the plurals - for `one`, `few`, `many` and `other`, if it uses `:one_other`, you should provide `one` and `other` plurals. If it uses `:other` + plurals needed by your language. E.g. if your language uses the `EastSlavic` you should provide the plurals + for `one`, `few`, `many` and `other`, if it uses `OneOther`, you should provide `one` and `other` plurals. If it uses `Other` you should only provide a single value. Look into other dictionary files to get some example. Ask if in doubt. Feel free to ask for help in your Pull Request. diff --git a/gem/locales/ar.yml b/gem/locales/ar.yml index 7c50e80c4..d8f870809 100644 --- a/gem/locales/ar.yml +++ b/gem/locales/ar.yml @@ -1,6 +1,7 @@ -# :arabic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Arabic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ar: pagy: + p11n: 'Arabic' aria_label: nav: zero: "لا يوجد صفحات" diff --git a/gem/locales/be.yml b/gem/locales/be.yml index f518bf8f3..b2d7dce36 100644 --- a/gem/locales/be.yml +++ b/gem/locales/be.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) be: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Старонка" diff --git a/gem/locales/bg.yml b/gem/locales/bg.yml index 215c2aa35..1caa01f67 100644 --- a/gem/locales/bg.yml +++ b/gem/locales/bg.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) bg: pagy: + p11n: 'OneOther' aria_label: nav: one: "Страница" diff --git a/gem/locales/bs.yml b/gem/locales/bs.yml index 7acad5480..c7058820c 100644 --- a/gem/locales/bs.yml +++ b/gem/locales/bs.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) bs: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Stranica" diff --git a/gem/locales/ca.yml b/gem/locales/ca.yml index bafb642f0..35ce81e61 100644 --- a/gem/locales/ca.yml +++ b/gem/locales/ca.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ca: pagy: + p11n: 'OneOther' aria_label: nav: one: "Pàgina" diff --git a/gem/locales/ckb.yml b/gem/locales/ckb.yml index 7333960da..ba424a89b 100644 --- a/gem/locales/ckb.yml +++ b/gem/locales/ckb.yml @@ -1,7 +1,8 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ckb: pagy: + p11n: 'Other' item_name: "بابەت" aria_label: nav: "پەڕەکان" diff --git a/gem/locales/cs.yml b/gem/locales/cs.yml index f947a77c3..54451ae65 100644 --- a/gem/locales/cs.yml +++ b/gem/locales/cs.yml @@ -1,6 +1,7 @@ -# :west_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# WestSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) cs: pagy: + p11n: 'WestSlavic' aria_label: nav: one: "Stránka" diff --git a/gem/locales/da.yml b/gem/locales/da.yml index aaf230c6f..d838fda87 100644 --- a/gem/locales/da.yml +++ b/gem/locales/da.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) da: pagy: + p11n: 'OneOther' aria_label: nav: one: "Side" diff --git a/gem/locales/de.yml b/gem/locales/de.yml index 2145b6b37..cff2ad0c0 100644 --- a/gem/locales/de.yml +++ b/gem/locales/de.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) de: pagy: + p11n: 'OneOther' aria_label: nav: one: "Seite" diff --git a/gem/locales/dz.yml b/gem/locales/dz.yml index 8fcb9b9ee..8dbdef9c9 100644 --- a/gem/locales/dz.yml +++ b/gem/locales/dz.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) dz: pagy: + p11n: 'Other' aria_label: nav: "ཤོག་ལེབ་" previous: "སྔོན་མ་" diff --git a/gem/locales/en.yml b/gem/locales/en.yml index 5e088997c..539ff81fe 100644 --- a/gem/locales/en.yml +++ b/gem/locales/en.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) en: pagy: + p11n: 'OneOther' aria_label: nav: one: "Page" diff --git a/gem/locales/es.yml b/gem/locales/es.yml index 5030cd273..e42281fda 100644 --- a/gem/locales/es.yml +++ b/gem/locales/es.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) es: pagy: + p11n: 'OneOther' aria_label: nav: one: "Página" diff --git a/gem/locales/fr.yml b/gem/locales/fr.yml index 1b242543f..d564fa07e 100644 --- a/gem/locales/fr.yml +++ b/gem/locales/fr.yml @@ -1,6 +1,7 @@ -# :one_upto_two_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneUptoTwoOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) fr: pagy: + p11n: 'OneUptoTwoOther' aria_label: nav: one: "Page" diff --git a/gem/locales/hr.yml b/gem/locales/hr.yml index 3ac7ccaad..4e5f9cac3 100644 --- a/gem/locales/hr.yml +++ b/gem/locales/hr.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) hr: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Stranica" diff --git a/gem/locales/id.yml b/gem/locales/id.yml index d20d0dee3..3ea9372b3 100644 --- a/gem/locales/id.yml +++ b/gem/locales/id.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) id: pagy: + p11n: 'Other' aria_label: # please add a comment in the https://github.com/ddnexus/pagy/issues/588 # posting the translation of the following "Page"/"Pages" with the plurals for this locale diff --git a/gem/locales/it.yml b/gem/locales/it.yml index 40aa5fc7e..4e75137d4 100644 --- a/gem/locales/it.yml +++ b/gem/locales/it.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) it: pagy: + p11n: 'OneOther' aria_label: nav: one: "Pagina" diff --git a/gem/locales/ja.yml b/gem/locales/ja.yml index b4caff180..fec5fcb46 100644 --- a/gem/locales/ja.yml +++ b/gem/locales/ja.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ja: pagy: + p11n: 'Other' aria_label: # please add a comment in the https://github.com/ddnexus/pagy/issues/590 # posting the translation of the following "Page"/"Pages" with the plurals for this locale diff --git a/gem/locales/km.yml b/gem/locales/km.yml index c8071737d..fafae465d 100644 --- a/gem/locales/km.yml +++ b/gem/locales/km.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) km: pagy: + p11n: 'Other' aria_label: # please add a comment in the https://github.com/ddnexus/pagy/issues/591 # posting the translation of the following "Page"/"Pages" with the plurals for this locale diff --git a/gem/locales/ko.yml b/gem/locales/ko.yml index 937402a64..b990f4fbb 100644 --- a/gem/locales/ko.yml +++ b/gem/locales/ko.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ko: pagy: + p11n: 'Other' aria_label: nav: "페이지" previous: "이전" diff --git a/gem/locales/nb.yml b/gem/locales/nb.yml index 3fc30c147..ba718c518 100644 --- a/gem/locales/nb.yml +++ b/gem/locales/nb.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) nb: pagy: + p11n: 'OneOther' aria_label: nav: one: "Side" diff --git a/gem/locales/nl.yml b/gem/locales/nl.yml index c64b0f6d6..904339119 100644 --- a/gem/locales/nl.yml +++ b/gem/locales/nl.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) nl: pagy: + p11n: 'OneOther' aria_label: nav: one: "Pagina" diff --git a/gem/locales/nn.yml b/gem/locales/nn.yml index 9215ac137..0e1980ba2 100644 --- a/gem/locales/nn.yml +++ b/gem/locales/nn.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) nn: pagy: + p11n: 'OneOther' aria_label: nav: one: "Side" diff --git a/gem/locales/pl.yml b/gem/locales/pl.yml index 5c03eb825..84c80decc 100644 --- a/gem/locales/pl.yml +++ b/gem/locales/pl.yml @@ -1,6 +1,7 @@ -# :polish pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Polish pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) pl: pagy: + p11n: 'Polish' aria_label: nav: one: "Strona" diff --git a/gem/locales/pt-BR.yml b/gem/locales/pt-BR.yml index e85f7b7bf..37b0f6343 100644 --- a/gem/locales/pt-BR.yml +++ b/gem/locales/pt-BR.yml @@ -1,8 +1,9 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) pt-BR: pagy: + p11n: 'OneOther' aria_label: - nav: + nav: one: "Página" other: "Páginas" previous: "Anterior" diff --git a/gem/locales/pt.yml b/gem/locales/pt.yml index 67a7a2e51..d4ae15900 100644 --- a/gem/locales/pt.yml +++ b/gem/locales/pt.yml @@ -1,8 +1,9 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) pt: pagy: + p11n: 'OneOther' aria_label: - nav: + nav: one: "Página" other: "Páginas" previous: "Anterior" diff --git a/gem/locales/ru.yml b/gem/locales/ru.yml index 348f08e4a..7d8a663f0 100644 --- a/gem/locales/ru.yml +++ b/gem/locales/ru.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ru: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Страница" diff --git a/gem/locales/sr.yml b/gem/locales/sr.yml index 719de5ef5..4fa448964 100644 --- a/gem/locales/sr.yml +++ b/gem/locales/sr.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) sr: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Страница" diff --git a/gem/locales/sv-SE.yml b/gem/locales/sv-SE.yml index e1d81bbf9..8a257035c 100644 --- a/gem/locales/sv-SE.yml +++ b/gem/locales/sv-SE.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) sv-SE: pagy: + p11n: 'OneOther' aria_label: nav: one: "Sida" diff --git a/gem/locales/sv.yml b/gem/locales/sv.yml index b064cf19d..6e641f1fd 100644 --- a/gem/locales/sv.yml +++ b/gem/locales/sv.yml @@ -1,6 +1,7 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) sv: pagy: + p11n: 'OneOther' aria_label: nav: one: "Sida" diff --git a/gem/locales/sw.yml b/gem/locales/sw.yml index eec1cb98b..4fe5aba89 100644 --- a/gem/locales/sw.yml +++ b/gem/locales/sw.yml @@ -1,14 +1,15 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) sw: pagy: + p11n: 'OneOther' # please add a comment in the https://github.com/ddnexus/pagy/issues/603 # posting the translation of the following "Page"/"Pages" with the plurals for this locale # Please change the final test in 18n_loacles_test.rb to remove the sw.yml exclusion # after you make these changes. aria_label: - nav: "Pages" -# one: "" -# other: "" + nav: + one: "Page" + other: "Pages" previous: "Awali" next: "Ifuatayo" previous: "<" diff --git a/gem/locales/ta.yml b/gem/locales/ta.yml index 3601eb1d6..59f633a51 100644 --- a/gem/locales/ta.yml +++ b/gem/locales/ta.yml @@ -1,14 +1,15 @@ -# :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# OneOther pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) ta: pagy: + p11n: 'OneOther' aria_label: # please add a comment in the https://github.com/ddnexus/pagy/issues/604 # posting the translation of the following "Page"/"Pages" with the plurals for this locale # Please change the final test in 18n_loacles_test.rb to remove the ta.yml exclusion # after you make these changes. - nav: "Pages" -# one: "" -# other: "" + nav: + one: "Page" + other: "Pages" previous: "முந்தையது" next: "அடுத்தது" previous: "<" diff --git a/gem/locales/tr.yml b/gem/locales/tr.yml index eefc36c4a..74d42f0ee 100644 --- a/gem/locales/tr.yml +++ b/gem/locales/tr.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) tr: pagy: + p11n: 'Other' aria_label: # please add a comment in the https://github.com/ddnexus/pagy/issues/605 # posting the translation of the following "Page"/"Pages" with the plurals for this locale diff --git a/gem/locales/uk.yml b/gem/locales/uk.yml index e952405e6..58d7f2a4a 100644 --- a/gem/locales/uk.yml +++ b/gem/locales/uk.yml @@ -1,6 +1,7 @@ -# :east_slavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# EastSlavic pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) uk: pagy: + p11n: 'EastSlavic' aria_label: nav: one: "Сторінка" diff --git a/gem/locales/vi.yml b/gem/locales/vi.yml index d511e9f62..4ba89dc68 100644 --- a/gem/locales/vi.yml +++ b/gem/locales/vi.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) vi: pagy: + p11n: 'Other' aria_label: nav: "Trang" previous: "Trang trước" diff --git a/gem/locales/zh-CN.yml b/gem/locales/zh-CN.yml index 07fc81d22..7dcc20dd2 100644 --- a/gem/locales/zh-CN.yml +++ b/gem/locales/zh-CN.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) zh-CN: pagy: + p11n: 'Other' aria_label: nav: "页" previous: "上一页" diff --git a/gem/locales/zh-HK.yml b/gem/locales/zh-HK.yml index 78bb5b124..ef0349b94 100644 --- a/gem/locales/zh-HK.yml +++ b/gem/locales/zh-HK.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) zh-HK: pagy: + p11n: 'Other' aria_label: nav: "頁" previous: "上一頁" diff --git a/gem/locales/zh-TW.yml b/gem/locales/zh-TW.yml index f72c20446..2784634c9 100644 --- a/gem/locales/zh-TW.yml +++ b/gem/locales/zh-TW.yml @@ -1,6 +1,7 @@ -# :other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) +# Other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) zh-TW: pagy: + p11n: 'Other' aria_label: nav: "頁" previous: "上一頁" diff --git a/test/helpers/nav_tests.rb b/test/helpers/nav_tests.rb index 8d93ec7fd..fe7af0139 100644 --- a/test/helpers/nav_tests.rb +++ b/test/helpers/nav_tests.rb @@ -5,7 +5,7 @@ require_relative '../files/models' # required because we use the class directly, which does not load the mixin, so we miss the extra data_pagy -require_relative '../../gem/lib/pagy/backend/pagynators/keynav' +require_relative '../../gem/lib/pagy/backend/paginators/keynav' module NavTests def app diff --git a/test/pagy/backend/calendar_test.rb b/test/pagy/backend/calendar_test.rb index fc63e4518..f5ad27ad1 100644 --- a/test/pagy/backend/calendar_test.rb +++ b/test/pagy/backend/calendar_test.rb @@ -271,7 +271,7 @@ def app(**) it 'includes title and class in page url' do # We need this require because we use a feature of pagy_calendar that would load with pagy_calendar, # but we don't call it because Pagy::Offset.new is easier to run, still testing the feature... - require_relative '../../../gem/lib/pagy/backend/pagynators/calendar' + require_relative '../../../gem/lib/pagy/backend/paginators/calendar' app = MockApp::CalendarCounts.new pagy = Pagy::Offset.new(count: 103, page: 1, counts: {2 => 0}) _(app.pagy_anchor(pagy, anchor_string: 'X').call(3, classes: 'a b c')).must_equal \ diff --git a/test/pagy/frontend/pagy_test.rb b/test/pagy/frontend/pagy_test.rb index 2f2ef3903..cd5b8547f 100644 --- a/test/pagy/frontend/pagy_test.rb +++ b/test/pagy/frontend/pagy_test.rb @@ -3,7 +3,7 @@ require_relative '../../test_helper' require_relative '../../helpers/nav_tests' require_relative '../../mock_helpers/app' -require_relative '../../../gem/lib/pagy/backend/pagynators/keynav' +require_relative '../../../gem/lib/pagy/backend/paginators/keynav' MIXIN = 'pagy' PREFIX = '' diff --git a/test/pagy/frontend_test.rb b/test/pagy/frontend_test.rb index d86ff29ad..6db6c53ed 100644 --- a/test/pagy/frontend_test.rb +++ b/test/pagy/frontend_test.rb @@ -5,14 +5,6 @@ require_relative '../mock_helpers/app' require_relative '../../gem/lib/pagy/frontend/utils/data_pagy' -# in test we cannot use the Pagy::I18n.load method because -# it would freeze the Pagy::I18n::DATA hash so i18n_load -# do the same as Pagy::I18n.load, just omitting the freeze -def i18n_load(*locales) - Pagy::I18n::DATA.clear - Pagy::I18n.send(:build, *locales) -end - describe 'pagy/frontend' do let(:app) { MockApp.new } @@ -46,31 +38,15 @@ def i18n_load(*locales) end describe "Pagy::I18n" do - it 'loads custom :locale, :filepath and :pluralize' do - _(proc { i18n_load(locale: 'xx') }).must_raise Errno::ENOENT - _(proc { i18n_load(locale: 'xx', filepath: Pagy::ROOT.join('locales/en.yml')) }).must_raise Pagy::I18nError - _(proc { i18n_load(locale: 'en', filepath: Pagy::ROOT.join('locales/xx.yml')) }).must_raise Errno::ENOENT - custom_dictionary = Pagy::ROOT.parent.join('test/files/locales/custom.yml') - i18n_load(locale: 'custom', filepath: custom_dictionary) - _(Pagy::I18n.t('pagy.aria_label.previous', locale: 'custom')).must_equal "Custom Previous" - i18n_load(locale: 'en', pluralize: ->(_) { 'one' }) # returns always 'one' regardless the count - _(Pagy::I18n.t('pagy.item_name', locale: nil, count: 0)).must_equal "item" - _(Pagy::I18n.t('pagy.item_name', locale: 'en', count: 0)).must_equal "item" - _(Pagy::I18n.t('pagy.item_name', locale: 'en', count: 1)).must_equal "item" - _(Pagy::I18n.t('pagy.item_name', locale: 'en', count: 10)).must_equal "item" - i18n_load(locale: 'en') # reset for other tests - end it 'switches :locale according to @pagy_locale' do - i18n_load({ locale: 'de' }, { locale: 'en' }, { locale: 'nl' }) app.set_pagy_locale('nl') _(app.pagy_t('pagy.item_name', count: 1)).must_equal "stuk" app.set_pagy_locale('en') _(app.pagy_t('pagy.item_name', count: 1)).must_equal "item" - app.set_pagy_locale(nil) + app.set_pagy_locale('de') _(app.pagy_t('pagy.item_name', count: 1)).must_equal "Eintrag" app.set_pagy_locale('unknown') - _(app.pagy_t('pagy.item_name', count: 1)).must_equal "Eintrag" # silently serves the first loaded locale - i18n_load(locale: 'en') # reset for other tests + _ { app.pagy_t('pagy.item_name', count: 1) }.must_raise Errno::ENOENT app.instance_variable_set(:@pagy_locale, nil) # reset for other tests end end diff --git a/test/pagy/helpers/i18n/load_test.rb b/test/pagy/helpers/i18n/load_test.rb deleted file mode 100644 index 619335511..000000000 --- a/test/pagy/helpers/i18n/load_test.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -require_relative '../../../test_helper' - -# isolated in this file because uses the frozen public API -describe 'pagy/i18n-load' do - it 'loads with public API' do - Pagy::I18n.load({ locale: 'de' }, { locale: 'en' }) - _(Pagy::I18n::DATA.size).must_equal 2 - _(Pagy::I18n::DATA.keys).must_include 'de' - _(Pagy::I18n::DATA.keys).must_include 'en' - _(proc { Pagy::I18n.load({ locale: 'de' }, { locale: 'en' }) }).must_raise FrozenError - end -end diff --git a/test/pagy/helpers/i18n/locales_test.rb b/test/pagy/helpers/i18n/locales_test.rb deleted file mode 100644 index a47e04b87..000000000 --- a/test/pagy/helpers/i18n/locales_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -require_relative '../../../test_helper' -require 'yaml' - -describe 'pagy/locales' do - let(:rules) { Pagy::I18n::P11n::RULE.keys } - let(:counts) do - { arabic: %w[zero one two few many other], - east_slavic: %w[one few many other], - one_other: %w[one other], - one_two_other: %w[one two other], - one_upto_two_other: %w[one other], - other: %w[other], - polish: %w[one few many other], - west_slavic: %w[one few other] } - end - - # locale files loop - Pagy::ROOT.join('locales').each_child do |f| - next unless f.extname == '.yml' - - message = "locale file #{f}" - locale = f.basename.to_s[0..-5] # e.g. de - comment = f.readlines.first.to_s.strip # e.g. :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) - rule = comment.to_s.split[1][1..].to_s.to_sym # e.g. one_other - pagy = YAML.safe_load(f.read)[locale]['pagy'] - - it "includes a comment with the #{rule} pluralization rule and the i18n.rb reference" do - _(rules).must_include rule, message - _(comment).must_match 'https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb', message - end - it "defines and matches the #{rule} pluralization rule for the #{locale} locale" do - _(Pagy::I18n::P11n::LOCALE[locale]).must_equal Pagy::I18n::P11n::RULE[rule], message - end - it "pluralizes the 'item_name' according to the #{rule} rule" do - item_name = pagy['item_name'] - case item_name - when String - _(rule).must_equal :other - when Hash - _(item_name.keys - counts[rule]).must_be_empty - else - raise StandardError, "the item_name must be a Hash or String" - end - end - it "ensures #{locale}.yml implements the #{rule} pluralization rule" do - # ta.yml and sw.yml do not have the requisite keys yet - skip(message) if %w[ta sw].include?(locale) - - count_keys = counts[rule] - if rule == :other - # With the :other rules, pagy.item_name and pagy.aria_label.nav entries must be strings. - _(pagy['item_name']).must_be_instance_of(String) - _(pagy['aria_label']['nav']).must_be_instance_of(String) - else - _(pagy['item_name'].keys.sort).must_equal count_keys.sort, - "In #{message} - pagy.item_name should be consistent with #{rule}" # rubocop:disable Layout/ArgumentAlignment - _(pagy['aria_label']['nav'].keys.sort).must_equal count_keys.sort, - "In #{message} - pagy.aria_label.nav should be consistent with #{rule}" # rubocop:disable Layout/ArgumentAlignment - end - end - end -end diff --git a/test/pagy/helpers/i18n/p11n_test.rb b/test/pagy/helpers/i18n/p11n_test.rb deleted file mode 100644 index 4c8029fc6..000000000 --- a/test/pagy/helpers/i18n/p11n_test.rb +++ /dev/null @@ -1,143 +0,0 @@ -# frozen_string_literal: true - -# Tests adapted from https://github.com/svenfuchs/rails-i18n - -require_relative '../../../test_helper' - -describe 'p11n' do - let(:p11n) { Pagy::I18n::P11n::RULE } - - describe :arabic do - it "detects that 0 belongs to 'zero'" do - _(p11n[:arabic].call(0)).must_equal 'zero' - end - it "detects that 1 belongs to 'one'" do - _(p11n[:arabic].call(1)).must_equal 'one' - end - it "detects that 2 belongs to 'two'" do - _(p11n[:arabic].call(2)).must_equal 'two' - end - [3, 4, 103, 208, 210, 807].each do |count| - it "detects that #{count} belongs to 'few'" do - _(p11n[:arabic].call(count)).must_equal 'few' - end - end - [11, 112, 280, 344, 523, 699, 820, 25, 27, 936].each do |count| - it "detects that #{count} belongs to 'many'" do - _(p11n[:arabic].call(count)).must_equal 'many' - end - end - [101, 102, 801, 1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:arabic].call(count)).must_equal 'other' - end - end - end - - describe :east_slavic do - [1, 21, 51, 71, 101, 1031].each do |count| - it "detects that #{count} belongs to 'one'" do - _(p11n[:east_slavic].call(count)).must_equal 'one' - end - end - [2, 3, 4, 22, 23, 24, 92, 93, 94].each do |count| - it "detects that #{count} belongs to 'few'" do - _(p11n[:east_slavic].call(count)).must_equal 'few' - end - end - [0, 5, 8, 10, 11, 18, 20, 25, 27, 30, 35, 38, 40].each do |count| - it "detects that #{count} belongs to 'many'" do - _(p11n[:east_slavic].call(count)).must_equal 'many' - end - end - [1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:east_slavic].call(count)).must_equal 'other' - end - end - end - - # default - describe :one_other do - it "detects that 1 belongs to 'one'" do - _(p11n[:one_other].call(1)).must_equal 'one' - end - [0, 0.3, 1.2, 2, 3, 5, 10, 11, 21, 23, 31, 50, 81, 99, 100].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:one_other].call(count)).must_equal 'other' - end - end - end - - describe :one_two_other do - it "detects that 1 belongs to 'one'" do - _(p11n[:one_two_other].call(1)).must_equal 'one' - end - it "detects that 2 belongs to 'two'" do - _(p11n[:one_two_other].call(2)).must_equal 'two' - end - [0, 0.3, 1.2, 3, 5, 10, 11, 21, 23, 31, 50, 81, 99, 100].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:one_two_other].call(count)).must_equal 'other' - end - end - end - - describe :one_upto_two_other do - [0, 0.5, 1, 1.2, 1.8].each do |count| - it "detects that #{count} belongs to 'one'" do - _(p11n[:one_upto_two_other].call(count)).must_equal 'one' - end - end - [2, 2.1, 5, 11, 21, 22, 37, 40, 900.5].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:one_upto_two_other].call(count)).must_equal 'other' - end - end - end - - describe :other do - [0, 1, 1.2, 2, 5, 11, 21, 22, 27, 99, 1000].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:other].call(count)).must_equal 'other' - end - end - end - - describe :polish do - it "detects that 1 belongs to 'one'" do - _(p11n[:polish].call(1)).must_equal 'one' - end - [2, 3, 4, 22, 23, 24, 92, 93, 94].each do |count| - it "detects that #{count} belongs to 'few'" do - _(p11n[:polish].call(count)).must_equal 'few' - end - end - [0, 5, 8, 10, 11, 18, 20, 21, 25, 27, 30, 31, 35, 38, 40, 41, 114].each do |count| - it "detects that #{count} belongs to 'many'" do - _(p11n[:polish].call(count)).must_equal 'many' - end - end - [1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:polish].call(count)).must_equal 'other' - end - end - end - - describe :west_slavic do - it "detects that 1 belongs to 'one'" do - _(p11n[:west_slavic].call(1)).must_equal 'one' - end - [2, 3, 4].each do |count| - it "detects that #{count} belongs to 'few'" do - _(p11n[:west_slavic].call(count)).must_equal 'few' - end - end - [0, 5, 8, 10, 1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| - it "detects that #{count} belongs to 'other'" do - _(p11n[:west_slavic].call(count)).must_equal 'other' - end - end - end -end diff --git a/test/pagy/i18n/locales_test.rb b/test/pagy/i18n/locales_test.rb new file mode 100644 index 000000000..3f2478ff6 --- /dev/null +++ b/test/pagy/i18n/locales_test.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'yaml' + +describe 'pagy/locales' do + let(:counts) do + { 'Arabic' => %w[zero one two few many other], + 'EastSlavic' => %w[one few many other], + 'OneOther' => %w[one other], + 'OneUptoTwoOther' => %w[one other], + 'Other' => %w[other], + 'Polish' => %w[one few many other], + 'WestSlavic' => %w[one few other] } + end + + # locale files loop + Pagy::ROOT.join('locales').each_child do |f| + next unless f.extname == '.yml' + + message = "locale file #{f}" + locale = f.basename.to_s[0..-5] # e.g. de + comment = f.readlines.first.to_s.strip # e.g. :one_other pluralization (see https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb) + pagy = YAML.safe_load(f.read)[locale]['pagy'] + p11n = pagy.delete('p11n') + + it "includes a comment with the #{p11n} pluralization and the i18n.rb reference" do + _(comment).must_match 'https://github.com/ddnexus/pagy/blob/master/gem/lib/pagy/i18n.rb', message + end + it "pluralizes the 'item_name' according to the #{p11n} rules" do + item_name = pagy['item_name'] + case item_name + when String + _(p11n).must_equal 'Other' + when Hash + _(item_name.keys - counts[p11n]).must_be_empty + else + raise StandardError, "the item_name must be a Hash or String" + end + end + it "ensures #{locale}.yml implements the #{p11n} pluralization" do + count_keys = counts[p11n] + if p11n == 'Other' + # With the :other plurals, pagy.item_name and pagy.aria_label.nav entries must be strings. + _(pagy['item_name']).must_be_instance_of(String) + _(pagy['aria_label']['nav']).must_be_instance_of(String) + else + _(pagy['item_name'].keys.sort).must_equal count_keys.sort, + "In #{message} - pagy.item_name should be consistent with #{p11n}" # rubocop:disable Layout/ArgumentAlignment + _(pagy['aria_label']['nav'].keys.sort).must_equal count_keys.sort, + "In #{message} - pagy.aria_label.nav should be consistent with #{p11n}" # rubocop:disable Layout/ArgumentAlignment + end + end + end +end diff --git a/test/pagy/i18n/p11n_test.rb b/test/pagy/i18n/p11n_test.rb new file mode 100644 index 000000000..bd6c793b3 --- /dev/null +++ b/test/pagy/i18n/p11n_test.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +# Tests adapted from https://github.com/svenfuchs/rails-i18n + +require_relative '../../test_helper' + +describe 'p11n' do + let(:p11n) { Pagy::I18n::P11n } + + describe :arabic do + it "detects that 0 belongs to 'zero'" do + _(p11n::Arabic.plural_for(0)).must_equal :zero + end + it "detects that 1 belongs to :one" do + _(p11n::Arabic.plural_for(1)).must_equal :one + end + it "detects that 2 belongs to :two" do + _(p11n::Arabic.plural_for(2)).must_equal :two + end + [3, 4, 103, 208, 210, 807].each do |count| + it "detects that #{count} belongs to :few" do + _(p11n::Arabic.plural_for(count)).must_equal :few + end + end + [11, 112, 280, 344, 523, 699, 820, 25, 27, 936].each do |count| + it "detects that #{count} belongs to :many" do + _(p11n::Arabic.plural_for(count)).must_equal :many + end + end + [101, 102, 801, 1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::Arabic.plural_for(count)).must_equal :other + end + end + end + + describe :east_slavic do + [1, 21, 51, 71, 101, 1031].each do |count| + it "detects that #{count} belongs to :one" do + _(p11n::EastSlavic.plural_for(count)).must_equal :one + end + end + [2, 3, 4, 22, 23, 24, 92, 93, 94].each do |count| + it "detects that #{count} belongs to :few" do + _(p11n::EastSlavic.plural_for(count)).must_equal :few + end + end + [0, 5, 8, 10, 11, 18, 20, 25, 27, 30, 35, 38, 40].each do |count| + it "detects that #{count} belongs to :many" do + _(p11n::EastSlavic.plural_for(count)).must_equal :many + end + end + [1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::EastSlavic.plural_for(count)).must_equal :other + end + end + end + + # default + describe :one_other do + it "detects that 1 belongs to :one" do + _(p11n::OneOther.plural_for(1)).must_equal :one + end + [0, 0.3, 1.2, 2, 3, 5, 10, 11, 21, 23, 31, 50, 81, 99, 100].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::OneOther.plural_for(count)).must_equal :other + end + end + end + + describe :one_upto_two_other do + [0, 0.5, 1, 1.2, 1.8].each do |count| + it "detects that #{count} belongs to :one" do + _(p11n::OneUptoTwoOther.plural_for(count)).must_equal :one + end + end + [2, 2.1, 5, 11, 21, 22, 37, 40, 900.5].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::OneUptoTwoOther.plural_for(count)).must_equal :other + end + end + end + + describe :other do + [0, 1, 1.2, 2, 5, 11, 21, 22, 27, 99, 1000].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::Other.plural_for(count)).must_equal :other + end + end + end + + describe :polish do + it "detects that 1 belongs to :one" do + _(p11n::Polish.plural_for(1)).must_equal :one + end + [2, 3, 4, 22, 23, 24, 92, 93, 94].each do |count| + it "detects that #{count} belongs to :few" do + _(p11n::Polish.plural_for(count)).must_equal :few + end + end + [0, 5, 8, 10, 11, 18, 20, 21, 25, 27, 30, 31, 35, 38, 40, 41, 114].each do |count| + it "detects that #{count} belongs to :many" do + _(p11n::Polish.plural_for(count)).must_equal :many + end + end + [1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::Polish.plural_for(count)).must_equal :other + end + end + end + + describe :west_slavic do + it "detects that 1 belongs to :one" do + _(p11n::WestSlavic.plural_for(1)).must_equal :one + end + [2, 3, 4].each do |count| + it "detects that #{count} belongs to :few" do + _(p11n::WestSlavic.plural_for(count)).must_equal :few + end + end + [0, 5, 8, 10, 1.2, 3.7, 11.5, 20.8, 1004.3].each do |count| + it "detects that #{count} belongs to :other" do + _(p11n::WestSlavic.plural_for(count)).must_equal :other + end + end + end +end