Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Polyfill Intl Grapheme Laravel Package

symfony/polyfill-intl-grapheme

Native PHP polyfill for Intl Grapheme functions when ext-intl isn’t available. Works with UTF-8 strings and provides grapheme-aware length, substring, splitting, extraction, and case-sensitive/insensitive position and search functions.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/polyfill-intl-grapheme
    

    Add to composer.json under require-dev if only needed for testing.

  2. First Use Case: Reverse RTL text (e.g., Arabic) correctly:

    use Symfony\Component\Polyfill\Intl\Grapheme\GraphemeStr;
    
    $rtlText = "مدم"; // Arabic palindrome
    $reversed = GraphemeStr::reverse($rtlText); // Returns "مدم" (correct)
    
  3. Where to Look First:


Implementation Patterns

Usage Patterns

  1. Laravel Str Helper Extension: Extend Laravel’s Str helper for consistency:

    // app/Providers/AppServiceProvider.php
    use Illuminate\Support\Str;
    use Symfony\Component\Polyfill\Intl\Grapheme\GraphemeStr;
    
    public function boot()
    {
        Str::macro('graphemeReverse', function ($string) {
            return GraphemeStr::reverse($string);
        });
    }
    

    Usage:

    $reversed = Str::graphemeReverse("👨‍👩‍👧‍👦"); // Handles emoji clusters
    
  2. Form Validation: Validate RTL palindromes (e.g., usernames):

    use Illuminate\Validation\Rule;
    
    $rules = [
        'username' => [
            'required',
            Rule::palindrome()->ignoreCase(),
            function ($attribute, $value, $fail) {
                if (!GraphemeStr::reverse($value) === $value) {
                    $fail('The '.$attribute.' must be a grapheme palindrome.');
                }
            },
        ],
    ];
    
  3. Search/Autocomplete: Reverse queries for RTL languages in Elasticsearch:

    $query = GraphemeStr::reverse(request('q'));
    $results = Search::query($query)->get();
    
  4. Blade Directives: Create a custom Blade directive for RTL text:

    // app/Providers/BladeServiceProvider.php
    Blade::directive('reverseGraphemes', function ($expression) {
        return "<?php echo GraphemeStr::reverse({$expression}); ?>";
    });
    

    Usage:

    @reverseGraphemes($rtlText)
    
  5. Text Processing Workflows:

    • Tokenization: Split RTL text into graphemes:
      $tokens = GraphemeStr::split("مدم");
      
    • Substring Extraction: Extract grapheme clusters:
      $substr = GraphemeStr::substr("مدم", 0, 2); // "م"
      

Integration Tips

  • Combine with intl Extension: If available, prefer native IntlGraphemeClusterIterator for full Unicode support:

    if (extension_loaded('intl')) {
        $iterator = new IntlGraphemeClusterIterator($string);
    } else {
        // Fallback to polyfill
    }
    
  • Performance Optimization: Cache reversed strings for static content (e.g., RTL menus):

    $cacheKey = 'rtl_menu_reversed';
    $reversed = Cache::remember($cacheKey, now()->addHours(1), function () {
        return GraphemeStr::reverse($rtlMenuText);
    });
    
  • Testing: Use GraphemeStr in PHPUnit tests for RTL edge cases:

    $this->assertEquals("مدم", GraphemeStr::reverse("مدم"));
    $this->assertEquals("👨‍👩‍👧‍👦", GraphemeStr::reverse("👨‍👩‍👧‍👦"));
    

Gotchas and Tips

Pitfalls

  1. UTF-8 Validation: The polyfill requires UTF-8 encoded strings. Invalid UTF-8 will throw exceptions:

    try {
        GraphemeStr::reverse("\xFF"); // Invalid UTF-8
    } catch (\InvalidArgumentException $e) {
        // Handle error
    }
    

    Fix: Validate input with mb_check_encoding() or iconv.

  2. PHP 8.6+ Requirement: The grapheme_strrev() function (added in v1.37.0) only works on PHP 8.6+. For older versions:

    • Use grapheme_str_split() + array_reverse() + implode() as a fallback.
    • Or rely on the intl extension if available.
  3. PCRE Version Issues: Older PCRE versions (<10.44) may cause incorrect splitting in grapheme_str_split(). Upgrade PCRE or use a fallback:

    if (version_compare(PCRE_VERSION, '10.44') < 0) {
        // Custom splitting logic
    }
    
  4. Emoji Cluster Handling: Some emoji sequences (e.g., "👨‍👩‍👧‍👦") may not reverse as expected if the underlying PCRE library has bugs. Test thoroughly with emoji combinations.

  5. Case-Insensitive Search: grapheme_stripos()/grapheme_strripos() do not support RTL case folding. For RTL languages, use IntlChar::foldCase() if the intl extension is available.

Debugging Tips

  1. Enable Error Reporting: Ensure E_ALL is enabled to catch UTF-8 or PCRE-related errors.

  2. Log Grapheme Clusters: Debug splitting issues by logging grapheme clusters:

    $clusters = GraphemeStr::split($string);
    \Log::debug('Grapheme clusters:', $clusters);
    
  3. Compare with Native intl: If available, compare results with the intl extension:

    $nativeResult = IntlGraphemeClusterIterator::reverse($string);
    $polyfillResult = GraphemeStr::reverse($string);
    $this->assertEquals($nativeResult, $polyfillResult);
    
  4. Check for False Positives: grapheme_strpos() may return false for invalid positions. Always validate:

    $pos = GraphemeStr::position($haystack, $needle);
    if ($pos === false) {
        // Handle not found
    }
    

Extension Points

  1. Custom Grapheme Functions: Extend the polyfill by creating wrapper classes:

    class RTLStringHelper {
        public static function reverseWithFallback($string) {
            try {
                return GraphemeStr::reverse($string);
            } catch (\Exception $e) {
                return strrev($string); // Fallback
            }
        }
    }
    
  2. Laravel Service Provider: Register the polyfill globally in AppServiceProvider:

    public function register()
    {
        $this->app->singleton('grapheme', function () {
            return new GraphemeStr();
        });
    }
    
  3. Event Listeners: Use the polyfill in event listeners for RTL text processing:

    public function handle(TranslatedEvent $event)
    {
        if (Str::contains($event->text, ['م', 'ש', 'س'])) {
            $event->text = GraphemeStr::reverse($event->text);
        }
    }
    
  4. Middleware: Process RTL requests in middleware:

    public function handle($request, Closure $next)
    {
        if ($request->isRtl()) {
            $request->merge(['reversed_query' => GraphemeStr::reverse($request->query('q'))]);
        }
        return $next($request);
    }
    

Config Quirks

  1. Autoloading: Ensure the polyfill is autoloaded in composer.json:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Symfony\\Component\\Polyfill\\Intl\\Grapheme\\": "vendor/symfony/polyfill-intl-grapheme/src/"
        }
    }
    
  2. Environment-Specific Loading: Load the polyfill only in RTL-enabled environments:

    if (config('app
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony