Currently Available: Need a skilled Software Developer for your next project?
Categories
Laravel

How to Localize Laravel Spark in Apps Using Laravel-Localization

If you're using Laravel Spark in an application that implements multilingual support via the popular mcamara/laravel-localization package, you might run into some challenges getting Spark's routes to work with your language prefixes. Here's a quick guide on how to set it up correctly.

The Challenge

By default, Laravel Spark's billing portal is accessible at /billing, while laravel-localization expects routes to be prefixed with the locale (e.g. /de/billing).

The Solution

The solution is surprisingly simple. Instead of letting Spark register its routes independently, we include them in our localization group in routes/web.php. The implementation differs slightly depending on whether you're using Spark Paddle or Spark Stripe:

For Spark Paddle

Route::group([
    'prefix' => LaravelLocalization::setLocale(),
    'middleware' => ['localize']
], function () {
    // Import Spark Paddle routes alongside other routes
    require base_path('vendor/laravel/spark-paddle/routes/web.php');

    // ... your other routes ...
});

For Spark Stripe

Route::group([
    'prefix' => LaravelLocalization::setLocale(),
    'middleware' => ['localize']
], function () {
    // Import Spark Stripe routes alongside other routes
    require base_path('vendor/laravel/spark-stripe/routes/routes.php');

    // ... your other routes ...
});

Translation Files

Don't forget to publish and translate Spark's language files:

  1. Publish the files:

    php artisan vendor:publish --tag=spark-lang
  2. This creates resources/lang/spark/en.json. Copy it for each language you support:

    /lang
    /spark
        en.json
        de.json
        es.json
        # etc...
  3. Translate the strings in each JSON file.

Result

Your Spark billing portal will now be accessible at:

  • /en/billing for English
  • /de/billing for German
  • etc.

And all of Spark's interface text will be properly translated based on the current locale.

Webhook

  • The Paddle webhook endpoint (/spark/webhook) will continue to work as expected

Translating Plan Information

Now we also need to translate plan names, descriptions, and features. Fortunately, Spark makes this quite straightforward once you understand how it works.

Spark automatically attempts to translate any string it displays through Laravel's translation system. This means that if you provide a string in your plan configuration that matches a key in your translation files, Spark will automatically use the translated version.

Step 1: Add Translations

Add all plan-related strings to your Spark language files (lang/spark/{locale}.json). For example:

{
    // English (lang/spark/en.json)
    "Basic": "Basic",
    "Pro": "Pro",
    "Perfect for small teams": "Perfect for small teams",
    "For power teams": "For power teams",
    "1,000 credits per month": "1,000 credits per month",
    "Access to all basic tools": "Access to all basic tools",
    "Email support": "Email support",
    "monthly": "monthly",
    "yearly": "yearly"
}

{
    // German (lang/spark/de.json)
    "Basic": "Basic",
    "Pro": "Pro",
    "Perfect for small teams": "Ideal für kleine Teams",
    "For power teams": "Für Power-Teams",
    "1,000 credits per month": "1.000 Credits pro Monat",
    "Access to all basic tools": "Zugriff auf alle Basic-Tools",
    "Email support": "E-Mail-Support",
    "monthly": "monatlich",
    "yearly": "jährlich"
}

Step 2: Use Translation Keys in Configuration

In your config/spark.php, use the exact same strings that you defined in your translation files:

'plans' => [
    [
        'name' => 'Basic',  // Will display as "Basic" in English and German
        'short_description' => 'Perfect for small teams', // Will display as "Ideal für kleine Teams" in German
        'monthly_id' => env('SPARK_BASIC_MONTHLY_PLAN'),
        'yearly_id' => env('SPARK_BASIC_YEARLY_PLAN'),
        'features' => [
            '1,000 credits per month',    // Will display as "1.000 Credits pro Monat" in German
            'Access to all basic tools',   // Will display as "Zugriff auf alle Basic-Tools" in German
            'Email support',              // Will display as "E-Mail-Support" in German
        ],
        'archived' => false,
    ],
]

Some Notes

  1. Exact Matching: The strings in your Spark configuration must match exactly with the keys in your translation files.

  2. Price Formatting: The "monthly" and "yearly" translations are used for the billing interval display next to prices.

  3. Plan Names: Even if plan names stay the same across languages (like "Basic" or "Pro"), it's good practice to include them in the translation files for future flexibility.

  4. HTML: If you need HTML in your descriptions or features, it will work as expected - just make sure to include the HTML in your translations as well.

With this setup, your entire billing portal, including plan information, will automatically display in the user's selected language. The translations will update dynamically as users switch between different locales using your Laravel Localization implementation.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Subscribe to my newsletter

Get new posts when I publish them.

I respect your privacy. Unsubscribe at any time.

Leave a Reply

Your email address will not be published. Required fields are marked *