php - Laravel Localization Nested JSON Language File

Solution:

Try:

<label for="email">
    {{ __('login')['email'] }}
</label>

Answer

Solution:

You can get this approach by changing the default helper by:

use Illuminate\Support\Arr; 

function ($key = null, $replace = [], $locale = null)
{
    // Default behavior
    if (is_null($key)) return $key;        
    if (trans()->has($key)) return trans($key, $replace, $locale);

    // Search in .json file
    $search = Arr::get(trans()->get('*'), $key);
    if ($search !== null) {-code-8};

    // Return .json fallback
    $fallback = Arr::get(trans()->get('*', [], config('app.fallback_locale')), $key);
    if ($fallback !== null) {-code-10};

    // Return key name if not found
    else return $key;
}

Creating custom bootstrap helpers

if you dont know how to change the default helper, create a file with any name (ex: {-code-3}), then in the file {-code-4} add this line just before 'Register The Auto Loader'

/*
|

Answer

Answer

Answer

Answer

Answer

Answer

Answer

---- | Register Custom Helpers |

Answer

Answer

Answer

Answer

Answer

Answer

Answer

-- */ require __DIR__.'/../bootstrap/helpers.php';

(Optional) Variables feature

if you also want to use the Variables feature, just like __(welcome.user, ['user'=>'david']) you must create a new helper on that file:

{-code-7}

and then replace {-code-8} with {-code-9} and {-code-10} with {-code-11}

(Optional) Countable feature

for Countable feature (ex: {-code-12}), is the same process, just add this helper:

use Illuminate\Support\Facades\App;

function trans_choice($key, $number, array $replace = [], $locale = null)
{        
    // Get message
    $message = __($key, $replace, $locale);

    // If the given "number" is actually an array or countable we will simply count the
    // number of elements in an instance.
    if (is_array($number) || $number instanceof Countable) 
    $number = count($number);

    $replace['count'] = $number;

    return trans_replacements(
        trans()->getSelector()->choose($message, $number, $locale = App::getLocale()), 
        $replace
    );
}

Bootstrap Helpers File

here is the file, just in case: bendeckdavid/laravel_locale_nested_json

Answer

Answer

Answer

Answer

Answer

Answer

Answer

---- | Register Custom Helpers |

Answer

Answer

Answer

Answer

Answer

Answer

Answer

-- */ require __DIR__.'/../bootstrap/helpers.php';|||__(welcome.user, ['user'=>'david'])|||use Illuminate\Support\Str; function trans_replacements($line, array $replace) { if (empty($replace)) return $line; $shouldReplace = []; foreach ($replace as $key => $value) { $shouldReplace[':'.Str::ucfirst($key)] = Str::ucfirst($value); $shouldReplace[':'.Str::upper($key)] = Str::upper($value); $shouldReplace[':'.$key] = $value; } return strtr($line, $shouldReplace); }|||return $search|||trans_replacements($search, $replace)|||return $fallback|||trans_replacements($fallback, $replace)|||'an apple|many apples'|||use Illuminate\Support\Facades\App; function trans_choice($key, $number, array $replace = [], $locale = null) { // Get message $message = __($key, $replace, $locale); // If the given "number" is actually an array or countable we will simply count the // number of elements in an instance. if (is_array($number) || $number instanceof Countable) $number = count($number); $replace['count'] = $number; return trans_replacements( trans()->getSelector()->choose($message, $number, $locale = App::getLocale()), $replace ); }

Answer

Solution:

Laravel not supporting this by default is annoying. However, you can use this function I made:

function ___($path) {
        $properties = explode(".", $path);
        $base = __($properties[0]);
        unset($properties[0]);
        foreach($properties as $property) {
            // Allows specification of indexes
            if(is_numeric($property)) {
                $property = intval($property);
            }
            // If the key has not been found, return the initial parameter like __()
            try {
                $base = $base[$property];
            } catch (\Throwable $th) {
                return $path;
            }
        }
        return $base;
}

Answer

Solution:

If you are someone like me stumbling upon here wanting to use a file structure like below without the need to specify keys for each string when using php language files.

-app
-lang
  --fr
    ---Headers.json

A little modification to David G's answer above,

<?php

use Illuminate\Support\Arr; 

function ___($path = null, $replace = [], $locale = null)
{
    // Default behavior
    if (is_null($path)) return $path;
    if(!strrpos($path, '.')) {
        return  $path;
    }

    $properties = explode(".", $path);
    $currentLocale = app()->getLocale();    

    // If the file/folder doesn't exist 
    // return the last part of the dot notation
    $translated_string = substr($path, strrpos($path, '.') + 1);

    if(is_dir(lang_path($currentLocale))) {
        if (is_file(lang_path($currentLocale.'\\'.$properties[0].'.json'))) {
            $contents = json_decode(file_get_contents(lang_path($currentLocale.'\\'.$properties[0].'.json')), true);
            // If no value exists for the key, the key is itself returned
            $translated_string = Arr::get($contents, $properties[1], $properties[1]);
        }
    }

    return $translated_string;
}

As of now this doesn't work for files under subdirectories under the locale folder. I am sure, the above code can be optimized, but this should give you an idea.

Also, this function uses triple-underscore {{___()}} instead of the regular double-underscore {{__()}} to avoid conflicts.

Works for,

{{___('Messages.Welcome') }} // lang/(locale)/Messages.json
{{___('Welcome')}} // lang/(locale).json

Answer

Solution:

Assuming your json is stored in $json, you want to parse it into array by using json_decode

$data = json_decode($json, TRUE);

You can access it by:

<label for="email">
    {{ $data['login']['emailPlaceholder'] }}
</label>

Source