Laravel Get the translations of the application from a package - laravel

I am trying to develop a small package in Laravel, but I have the following problem. From my package I need to get the translations that are present in the languages directory:
Example:
myapp/resources/lang
When I make a call as follows to get the translations of a file:
private function getTranslationsFromFile()
{
return Lang::get('auth');
}
It does not return the translations in that file. It only returns auth. In the Laravel languages directory there is that file, but inside the directory en.
So I have defined before getting the translations the default 'locale' so that I can load them from there in this way:
private function getTranslationsFromFile()
{
app()->setLocale('en');
return Lang::get('auth');
}
this way it works fine, but my question is the following, is there no way to load the translations regardless of whether or not the 'locale' is set? I mean, is it not possible to get the translations just by giving it a file path?
Example:
private function getTranslationsFromFile()
{
return Lang::get('en/auth');
}
Thank you very much in advance.

You can certainly do that by leveraging the third and fourth parameter of Lang::get():
This is the method's signature:
get(string $key, array $replace = [], string|null $locale = null, bool $fallback = true)
The third parameter specifies the locale you'd wish to get the translation string for:
Lang::get('auth.failed', [], 'en')
To set a fallback language in case that the translation is not available in the chosen locale, use the fourth parameter:
Lang::get('auth.failed', [], 'en', 'es')

Related

How can i get value from config file and set in $attribute variable in laravel model file?

I want to assign a default value in Laravel model but the value should come from the config file.
I am writing below code but its giving me error
protected $attributes = [
'is_generation' => true,
'price' => config('test.MY_PRICE'),
];
it's showing me an error like Constant expression contains invalid operations
How can I get value from config file and set in $attribute variable in Laravel model file?
You can use the saving model event by adding this code to your Eloquent Model:
protected static function boot()
{
// sets default values on saving
static::saving(function ($model) {
$model->price = $model->price ?? config('test.MY_PRICE');
});
parent::boot();
}
With this code in place, if the field price is null, it will have assigned a value from the config key just a moment before saving the Model in the database.
BTW you can change the check like if it's an empty string or less then a number and so on, this is only an example.
Class member variables are called "properties". You may also see them
referred to using other terms such as "attributes" or "fields", but
for the purposes of this reference we will use "properties". They are
defined by using one of the keywords public, protected, or private,
followed by a normal variable declaration. This declaration may
include an initialization, but this initialization must be a constant
value--that is, it must be able to be evaluated at compile time and
must not depend on run-time information in order to be evaluated.
The only way you can make this work is :-
<?php
namespace App;
class Amazon
{
protected $serviceURL;
public function __construct()
{
$this->serviceURL = config('api.amazon.service_url');
}
}
You can use attribute mutator as explained here: https://laravel.com/docs/5.8/eloquent-mutators#defining-a-mutator
Class Example{
public function setPriceAttribute(){
return $this->attributes['price'] = config('test.MY_PRICE');
}
}

How to stop slug generation in OctoberCMS

When I write non-unicode letters in OctoberCMS Rainlab blog title, it's converted to English letters such as this:
موضوع جديد
is converted to: modoaa-gdyd
I don't want this, I want only to replace spaces with hyphen to be for example:
موضوع-جديد
How can I do that?
Hmm for now it seems we are not able to extend js plugin for give purpose
but we can extend plugin to not use slug type
you can add this code to any of your plugin's boot method
boot method is imp
<?php namespace HardikSatasiya\DemoTest;
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public function registerComponents()
{
}
public function registerSettings()
{
}
public function boot() {
\Event::listen('backend.form.extendFieldsBefore', function($widget) {
// You should always check to see if you're extending correct model
if(!$widget->model instanceof \RainLab\Blog\Models\Post) {
return;
}
// now we remove type = slug , and use exact
// as type = slug will convert chars ARABIC_MAP to english so
$widget->fields['slug']['preset']['type'] = 'exact';
});
}
}
It will not solve your complete problem but it can simply copy your blog-title exactly in to slug, in slug text-box then you need to add / at the beginning and then you also need to place ' ' => '-' (dash at spaces) manually.
sorry this will not solve your whole issue, but just saves you from copying title to slug again and again.
Add this function as a helper in your app and reuse it
public static function generateSlug($title)
{
$title = strtolower($title);
$title = preg_replace("/[\s-]+/", ' ', $title);
$title = preg_replace("/[\s_]/", '-', $title);
return $title;
}
$slug = Helpers::generateSlug('موضوع جدید', '-');
//will produce "موضوع-جدید"
Or use this package
Sluggable Persian
I solved this problem by editing the following file:
modules\system\assets\ui\storm-min.js
I emptied the following variables:
ARABIC_MAP={},PERSIAN_MAP={}
and edited the slugify function by replacing this line:
slug=slug.replace(/[^-\w\s]/g,'')
with this:
slug=slug.replace(/[^-\w\sء-ي]/g,'')
so, now the slug accepts Arabic characters normally

Configure langs in Laravel Translatable BootForms

I'm new to Laravel Translatable BootForms, and I was wondering something.
When I use this code :
{!!
TranslatableBootForm::text('Nom', 'name')
->required()
!!}
The render is as follows :
I don't know where this language list comes from.
I only want to list some languages specified in my database, as I do with this workaround :
#foreach($availableLangs as $availableLang)
{!!
TranslatableBootForm::text('Nom', 'name')
->renderLocale($availableLang['locale'])
!!}
#endforeach
Which gives me this :
My two questions are :
Where does this language list come from ?
How can I replace it by my own language list ?
Answering the first question may lead to an automatic answer for the second, though)
In Laravel, you should always try to read the Service Providers, they provide important clues about the project structures. Let's try to follow the trail of the function calls:
TranslatableBootForm is a facade and it resolves to and instance of translatable-bootform from the Service Container according to this line:
protected static function getFacadeAccessor() { return 'translatable-bootform'; }
Now, in the file TranslatableBootFormsServiceProvider.php we can see that translatable-bootform is an instance of TranslatableBootForm. So when you call TranslatableBootForm::text, you will be using the Facade which resolves to an instance of TranslatableBootForm
Opening the TranslatableBootForm class, we cannot find the text method, so there should be a __call method. The __call method always returns whatever is returned from the method render. So that's where the action is happening.
Reading the code there, you will find that it gets the locales from a method called locales and it will intersect it with the func_get_args() function to get whatever languages you pass to it. So renderLocale or simply render will do the same thing.
The method locales just returns an array which is by default empty in the class. If we return back to the TranslatableBootFormsServiceProvider we will see that there's an important line:
$formBuilder->setLocales($this->getLocales());
Which gets the locales from Translatable\TranslatableWrapper which is just a wrapper around this file in another package: https://github.com/dimsav/laravel-translatable/blob/master/src/Translatable/Translatable.php
Looking at the configuration file in the laravel-translatable package, we can see the languages:
https://github.com/dimsav/laravel-translatable/blob/master/src/config/translatable.php
Solutions
Now, you can simply copy the file translatable.php in your config folder and set your locales.
Or, you create a new service provider MyTranslatableBootFormsServiceProvider
class MyTranslatableBootFormsServiceProvider extends TranslatableBootFormsServiceProvider
{
/**
* Get Translatable's locales.
*
* #return array
*/
protected function getLocales()
{
// You can return a config key
// return config('yourconfig.locales');
// Or directly the array containing the languages
return ['en', 'fr', 'nl'];
}
}
Then, you will use this provider in your config/app.php instead of the original TranslatableBootFormsServiceProvider
Disclaimer:
I didn't try the code, you might have a bug, but you get the idea now how to find your way around Laravel packages.

Check line existence in laravel's trans()

Lets say in my lang/en/general.php there are multiple translation lines for example:
"token" => "This password reset token is invalid.",
"sent" => "Password reminder sent!",
"reset" => "Password has been reset!",
But in my lang/de/general.php these lines are missing.
So later, when I use the Lang::get('general.token') or simply trans('general.token')
The english version will return
This password reset token is invalid.
And the german (de) version will return
general.token
Is there any way I can handle a 'translation not found' function, like a filter but not creating a special class for it? For example, when a line has no translation, I want to throw an Exception.
Thanks in advance!
In Laravel 4 only, you can use Lang::has() as below, here is the doc
if (\Lang::has('general.token')) {
// line exists.
} else {
// line not exist.
}
In current Laravel versions you can just use trans helper like so:
#if (trans()->has('general.token'))
{{ trans('general.token') }}
#endif
This question is getting a little bit old but as per version 5.8 you can simply check as this :
array_key_exists('your-word-key', trans('your-file'))
or
array_key_exists('your-word-key', trans('your-file.array_key'))
for nested translations
You might want to write a helper similar to the one below to help with fallbacks:
/**
* Makes translation fall back to specified value if definition does not exist
*
* #param string $key
* #param null|string $fallback
* #param null|string $locale
* #param array|null $replace
*
* #return array|\Illuminate\Contracts\Translation\Translator|null|string
*/
function trans_fb(string $key, ?string $fallback = null, ?string $locale = null, ?array $replace = [])
{
if (\Illuminate\Support\Facades\Lang::has($key, $locale)) {
return trans($key, $replace, $locale);
}
return $fallback;
}
Note: The helper only works on PHP 7.1 (which has support nullable types). Adjust it to your PHP version if it's lower than 7.1.
You can create your own TranslationServiceProvider and Translator and override the get() method in translator to throw an exception when the parent::get() returns a translation string that is equal to the translation key that was passed in. Both #lang() and trans() functions call the get() method of the translator.
Seems like a whole lot of trouble only to get another reason for a "Whoops! something went wrong!" on your site. You will only get the exception when the translation is encountered.
Another solution: you can use the barryvdh/laravel-translation-manager package, it has a translation service provider that logs missing translation keys and a web interface for managing translations. It will log missing translation keys per locale and let you edit them through a web interface.
It is simple to setup and easy to modify. So you can replace the logging with throwing an exception.

Translate controller class variables in zend framework 2

Let's say I have a controller and I want to define some const variables that hold some messages (eg error messages etc).
Is there a way to make it so they are translated?
An example class is defined bellow:
<?php
namespace Test\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AccountController extends AbstractActionController
{
protected $testError = 'There was an error while testing some stuff';
public function testAction(){
// I know i can use the following approach but I don't want to
// since I want to use a variable for readability issues.
// $testError = $this->getTranslator()->translate('There was an error..');
return new ViewModel();
}
/**
* Retrieve the translator
*
* #return \Zend\I18n\Translator\Translator
*/
public function getTranslator()
{
if (!$this->translator) {
$this->setTranslator($this->getServiceLocator()->get('translator'));
}
return $this->translator;
}
/**
* Set the translator
*
* #param $translator
*/
public function setTranslator($translator)
{
$this->translator = $translator;
}
}
So I want to have the testError translated. I know I can just use the message and translate it via the zend translator without using a variable, but still I want to store it in a variable for readability issues. Any help or other approaches to this?
Simply create a translations.phtml file in any directory in your project root and fill it something like that:
<?php
// Colors
_('Black');
_('White');
_('Green');
_('Light Green');
_('Blue');
_('Orange');
_('Red');
_('Pink');
In poedit, check Catalog Properties > Source keywords list an be sure _ character is exists. (Alias of the gettext method). In application, use $this->translate($colorName) for example.
When poedit scanning your project directory to find the keywords which needs to be translated, translations.phtml file will be scanned too.
Another handy approach is using _ method (gettext alias) to improve code readability. Example:
$this->errorMsg = _('There was an error..');
But don't forget to set the global Locale object's default locale value too when you initialising your translator instance first time in a TranslatorServiceFactory or onBootstrap method of the module:
...
$translator = \Zend\Mvc\I18n\Translator\Translator::factory($config['translator']);
$locale = 'en_US';
$translator->setLocale($locale);
\Locale::setDefault($translator->getLocale());
return $translator;
...
I don't quite understand what you mean:
$errorMessage = 'FooBarBazBat";
return new ViewModel(array(
'error' => $this->getTranslator()->translate($errorMessage)
));
would be a way to store the message inside a variable. But i really don't understand where your problem is.
Or do you mean having the translator as variable?
$translator = $this->getServiceLocator()->get('viewhelpermanager')->get('translate');
$errorMessage = $translator('FooBarBazBat');

Resources