Localization in a custom Laravel Package - php

My service provider of my custom package has the following lines in the boot() method:
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'name');
$this->publishes([
__DIR__.'/../resources/lang' => resource_path('lang/vendor/name'),
], 'lang');
I ran the php artisan vendor:publish command and the packages/vendorname/packagename/resources/lang/de.json file was successfully copied to the project.
The translation is not working. I tried copying to the /lang/vendor/name/ folder as well.
When I move my de.json file manually to /lang then the translation is working. To there is no issue with the file itself.
I tried to clear all caches already.

I am not sure why, But, it seems that Laravel just loads only the JSON translation files of the main project and the first package in the Vendor folder.
My solution is:
for loading the JSON translation files from your package, you have to
use loadJsonTranslationsFrom in your package's service provider:
class CustomeServiceProvider extends ServiceProvider
{
/**
* Bootstrap the package services.
*
* #return void
*/
public function boot()
{
$this->loadJsonTranslationsFrom(__DIR__.'/../resources/lang');
}
}
In your JSON file you can use your package name as a prefix for every key. for example, if your package name is MyPackage, your en.json file
looks like:
{
"MyPackage::email": "Email",
"MyPackage::username": "Username",
...
}
You can use some helper functions of Laravel to load your translation keys:
trans('MyPackage::email'); // returns "Email"
OR
__('MyPackage::username'); // returns "Username"
You can follow the links below for more information:
https://laracasts.com/discuss/channels/laravel/loadjsontranslationsfrom-does-not-load-all-json-translation-files
https://github.com/laravel/framework/issues/17923
Laravel 5 loadJsonTranslationsFrom method does not load all JSON translation files from packages
https://github.com/nWidart/laravel-modules/pull/412
https://github.com/laravel/framework/pull/20599

Related

Error: "Your Application class does not have a bootstrap() method. Please add one."

I recently started building an application, locally, using CakePHP 4.X. I installed Composer and successfully installed the CakePHP Authentication and Authorization plugins using it. Now, I'm trying to move on to some community-developed plugins such as
https://github.com/FriendsOfCake/bootstrap-ui
https://github.com/gutocf/page-title
https://github.com/dereuromark/cakephp-feedback
I'm able to install all of the plugins okay but the issue arises when I try to load the plugins. Per the instructions on each of the plugin Git pages, I try to load the plugin from my CLI using the line
bin\cake plugin load BootstrapUI
(I'm on Windows hence the backslash)
I am returned the following message in all cases:
Your Application class does not have a bootstrap() method. Please add one.
My src/Application.php file looks like this
class Application extends BaseApplication
public function bootstrap() : void
{
// Call the parent to `require_once` config/bootstrap.php
parent::bootstrap();
if (PHP_SAPI === 'cli') {
$this->bootstrapCli();
} else {
FactoryLocator::add(
'Table',
(new TableLocator())->allowFallbackClass(false)
);
}
/*
* Only try to load DebugKit in development mode
* Debug Kit should not be installed on a production system
*/
if (Configure::read('debug')) {
$this->addPlugin('DebugKit');
}
// Load more plugins here
$this->addPlugin('Authorization');
$this->addPlugin('Authentication');
$this->addPlugin('BootstrapUI');
}
Your Application class is missing an { after class Application extends BaseApplication but I guess it was pasted/edited incorrectly here.
Your command seems to work because I see the plugin $this->addPlugin('BootstrapUI') already added in the file.
Make sure to be on the correct path (in the root of your app) when you execute the CLI command:
bin\cake plugin load BootstrapUI
You can manually add the plugins in the bootstrap() method without CLI.

Class 'Vendor\PackageName\ClassName' not found for newly created Laravel package

I've a problem running my newly created Laravel package which please check out https://github.com/Younesi/laravel-aparat
I can download it via Composer with no problem and it's auto-discovered via Laravel but when I try to use it, It gives me the following error of not finding class.
Class 'Younesi\LaravelAparat\Aparat' not found
My service Provider code is like:
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->bind('aparat', function ($app) {
return new Aparat;
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return array('aparat');
}
Any help would be appreciated.
Looking at the package it's working fine, in composer.json of that package there is:
"autoload": {
"psr-4": {
"Younesi\\laravelAparat\\": "src"
}
},
Notice that laravel is not with capital letter here, so in your code you should import rather this way:
use Younesi\laravelAparat\Aparat;
instead of:
use Younesi\LaravelAparat\Aparat;
I also see that you are author of this package, so I would recommend using standard conversion (namespace starting with capital letter) instead of current namespace.
Looking further at package code, I also see that in service provider there is:
namespace Younesi\LaravelAparat;
namespace so it's nothing weird it won't work if you autoload it with lower-case letter and have namespace with upper-case letter
There were some cases with registration problem, cache issues, etc. Try one of these solutions:
register your provider (in main composer.json, then in config/app.php [provider & alias] ), then run composer dump-autoload
make sure you have initiated your package : go to the folder, then composer init
try php artisan config:cache or delete everything in bootstrap/cache/

How to bootstrap laravel 5 service providers from the vendor package itself?

I am working on a Laravel 5 application and now the code of the application is supposed to be re-used in multiple laravel 5 applications which is why I am creating a composer package and then I would like to install this package in any number of laravel 5 applications to have the same functionality and build over it too.
I am new to composer package development and especially hooking packages into Laravel 5 using Service Providers. So far I have learnt that if I use a service provider as the one below, I will be able to use the routes in the laravel 5 application:
<?php
namespace Uppdragshuset\AO\Tenant;
use Illuminate\Support\ServiceProvider;
class TenantServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
include __DIR__.'/routes.php';
}
}
Now to make this work, I just require the package via composer into any brand new Laravel 5 installation and then I just need to updated the provider's array in app.php with this:
Uppdragshuset\AO\Tenant\TenantServiceProvider::class
This makes sense to me and works too. But now the package that I am developing also has dependencies of its own and many of the those dependency packages also have laravel 5 service providers included so I have to manually include all of them in the laravel5 installations to make them work.
But I am guessing there must be a way to register these dependent service providers in the package that I am creating itself somehow so that I just need to register the one provider I mentioned above. The problem is I don't know how to do this and cannot find a similar reference anywhere. How to register multiple service providers from the composer package itself?
So I finally figured out how to register dependant service providers from the composer package itself.
I have the main TenantServiceProvider in my package which is supposed to hook in routes into the main application and is also responsible for publishing migrations, configs and so on.
Turns out I can register any dependant service providers via the same provider using the register() method on the App facade and calling it in the register method of my main TenantServiceProvider like so:
public function register()
{
include __DIR__.'/routes.php';
App::register(RepositoryServiceProvider::class);
App::register(\Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class);
}
In this way I only have to register the TenantServiceProvider in the provider's array in the app.php config file of the laravel application. When it is called and the register method on it is called, all the other providers will be registered via the App::register() calls. Hope this helps someone.
you can create a package composer.json file and add the dependencies in there for the package itself so when you do composer require author/package it will look at the dependencies of that package and require them automatically below is an example of a composer.json requirement for a package I often pull
"require": {
"php": ">=5.5.0",
"illuminate/console": "~5.0",
"illuminate/support": "~5.0",
"illuminate/cache": "~5.0"
you can add the following Boot Method to Publish your service provider
public function boot()
{
$this->publishes([
__DIR__ . '/config/configifyouhaveone.php' => config_path('pathtotheconfig.php')
]);
AliasLoader::getInstance()->alias(
'serviceprovidername',
'Namespace\Subfolder\PackageName\PackageFacade'
);
}
after that you will need to do php artisan vendor:publish so do not forget that
Update
Since Laravel 5.5 you can now register your package's service provider with the application which depends on it, by adding the following block to your package's composer.json:
...
"extra": {
"laravel": {
"providers": [
"Acme\\Package\\ServiceProvider"
]
}
},
...
See the documentation: https://laravel.com/docs/5.5/packages#package-discovery

laravel 5.1 access package config values

I'm starting a package on laravel 5.1. Up till now using laravel 4.2
I've been able to publish the package config file using the following in the boot method of the service provider for my package as described in the documents:
public function boot()
{
$this->publishes([
__DIR__ . '/config/config.php' => config_path('/packages/longestdrive/googlecal/googlecal.php'),
]);
Now I'm trying to access the items in this config using:
config('googlecal.client_id');
This however returns null
If I simply do: config() I get a full array of the config arrays and can see my package config file there.
If I then do: config('longestdrive.googlecal.googlecal.client_id') I can access the variable.
In L4.2 I did not need to add effectively the full path to the variable.
Have I missed something to enable me to simply do: config('googlecal.client_id')
Thanks
You have to merge your config file in ServiceProvider
/**
* Register the service provider.
*/
public function register()
{
$this->app->bind('laravel-db-localization', function ($app) {
return new LaravelDbLocalization();
});
// Load the config file
$this->mergeConfigFrom(__DIR__.'/config/laravel-db-localization.php', 'laravel-db-localization');
}
May be you should run "php artisan config:cache", it works for me:)

Adding a custom Artisan command with Behat

I've registered a custom Artisan command:
Artisan::add(new MigrateAll);
The class resides in app/commands (default location)
However when I run Behat I get the error:
Class 'MigrateAll' not found
Artisan is called in Behat for setting up the DB:
/**
* #static
* #beforeSuite
*/
public static function setUpDb()
{
Artisan::call('migrate:install');
//...
}
Do I need to give it a namespace? (I could not find the correct way to call the Artisan::add command with a namespaced class)
This is somewhat related to your earlier question. Your Behat test suite runs in a separate process independently of your app and knows nothing about the configuration. This also applies to the autoloading in your bootstrap and the autoloading would be the most likely reason why classes don't get found. This should be easily fixed by using Composer to autoload your own sources and vendor packages (both in your app and in your test suite).
# composer.json
{
"require": {
"…": "…"
},
"autoload": {
"psr-0": {
"": "../src"
}
}
}
// Include composer's autoloader in your `setUp()` / bootstrap / index.php.
include __DIR__ . '../vendor/autoload.php';
Take that process separation as a rule and keep in mind that Laravel like any other framework requires a whole bunch of other configuration. Since you are trying to use the database component, your next issue will be with that, because it won't be configured in your test suite.
The best approach is to create separate bootstrap file for Behat, which would inherit most lines from your normal bootstrap, where you need to pass the necessary configuration and do this:
/**
* #static
* #beforeSuite
*/
public static function setUp()
{
include_once('bootstrap.php');
}
If you configured your behat environment with this tut (Laravel, BDD And You: Let’s Get Started), after you added a new command, you need to $ composer dump-autoload to make behat to know the command.

Categories