Locale support: abstract Locale, En, instance API, extension methods (v2.1 — §5 + §5a)#22
Open
Locale support: abstract Locale, En, instance API, extension methods (v2.1 — §5 + §5a)#22
Conversation
…n methods
Roadmap items §5 + §5a (v2.1).
Architecture:
- Inflect\Locale\Locale: abstract class holding rule tables as
protected instance state, with a shared regex-rule inflection engine
(pluralize, singularize) and extension methods (addIrregular,
addUncountable, addPluralRule, addSingularRule). Per-instance
memoization caches that clear on rule mutation.
- Inflect\Locale\En: English locale seeding rule tables from
protected const class constants via the constructor.
- Inflect\Inflect: facade with both static and instance APIs.
Static API (back-compat — zero signature changes):
Inflect::pluralize(), singularize(), pluralizeIf() delegate to a
lazily-initialized shared En instance. Proxy extension methods
(addIrregular, addUncountable, addPluralRule, addSingularRule)
mutate that shared instance.
Instance API (new):
new Inflect('en') or new Inflect(new En()) — per-instance locale,
isolated cache and rules. Methods: plural(), singular(), pluralIf(),
getLocale().
Locale registry:
Inflect::registerLocale('name', Class::class|$instance) — lazy
resolution via class-string. Ships with 'en' pre-registered.
Unknown locale throws InvalidArgumentException.
Tests:
12 new tests covering instance API (plural, singular, pluralIf,
construction from Locale object, instance isolation), extension
methods (addIrregular, addUncountable, addPluralRule,
addSingularRule, cache invalidation), locale registration (register
+ resolve, unknown-locale exception), and the static extension proxy.
129 tests / 141 assertions pass on PHP 8.1 and 8.3.
PHPStan level 8: no errors. PHP-CS-Fixer: clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #22 +/- ##
============================================
- Coverage 98.07% 93.63% -4.45%
- Complexity 27 51 +24
============================================
Files 1 3 +2
Lines 52 110 +58
============================================
+ Hits 51 103 +52
- Misses 1 7 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…erage) - Add tests for static proxy methods: addUncountable, addPluralRule, addSingularRule (lines 54, 59, 64 in Inflect.php were uncovered). - Test the no-rule-match fallback in Locale::pluralize (line 62) using an anonymous empty Locale subclass — En's catch-all '/$/' => 's' makes this path unreachable with real English rules. 133 tests / 145 assertions. 100% line, method, and class coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements ROADMAP items §5 (extensibility) and §5a (locale-based inflections) per the design locked in #20.
New files
Changed files
Static API (back-compat)
```php
Inflect::pluralize('cat'); // 'cats' — unchanged
Inflect::singularize('cats'); // 'cat' — unchanged
Inflect::pluralizeIf(3, 'person'); // '3 people' — unchanged
```
Internally delegates to a lazily-initialized shared `En` instance. New proxy extension methods:
```php
Inflect::addIrregular('dwarf', 'dwarves');
Inflect::addUncountable('moose');
Inflect::addPluralRule('/^(platypus)$/i', '$1es');
Inflect::addSingularRule('/(platypus)es$/i', '$1');
```
Instance API (new)
```php
$en = new Inflect(); // default 'en'
$en = new Inflect('en'); // explicit by name
$en = new Inflect(new En()); // explicit by object
$en->plural('cat'); // 'cats'
$en->singular('cats'); // 'cat'
$en->pluralIf(3, 'person'); // '3 people'
$en->getLocale()->addIrregular('formula', 'formulae');
```
Instances are isolated — extending one instance's rules doesn't affect another.
Locale registry
```php
Inflect::registerLocale('fr', Fr::class); // lazy: class instantiated on first use
$fr = new Inflect('fr');
```
Unknown locale throws `InvalidArgumentException`. Ships with `'en'` pre-registered.
Test plan
Follow-up (not in this PR)
🤖 Generated with Claude Code